Civilization VI Turn Notifications
Civilization VI has a multiplayer mode that allows users to play at their own pace. All players share a single Cloud Save
file which is updated as each player completes their turn. To enhance this game mode Civilization VI has a game option for a Play By Cloud Webhook URL
.
A webhook is commonly a URL that performs some task or function based off optional data sent to the URL. You can read more about webhooks here. Civilization VI sends a JSON payload that looks like the example below to the configured webhook URL.
{
"Value1":"Game Name",
"Value2":"Player Name",
"Value3":"Turn Number"
}
Prepare
Before starting, make sure you have a Telegram Bot running.
Create a Telegram Group with all the players of the Play By Cloud game.
You will need the bot’s HTTP API Token, the Telegram chat Id for the group chat, and the Telegram user Ids for the members of the group.
If you don’t already have one, create an Azure account here.
Create an Azure Function App
-
On your Azure Dashboard, create a new resource.
-
Use the search function to find the
Function App
resource -
On the next screen create the function app.
-
The next screen will configure your Function App, the steps below describe the available options
- Subscription
- This should be Azure Free, unless you have an existing subscription that you have permission to use.
- Resource Group
- A way to organize common Azure resources, click
Create new
if you don’t have one already.
- Function App Name
- The name for your function app, something like
civ6turnbot
, this will uniquely identify the function’s URL.
- Publish
- If you want to only publish code, or if you want to publish a whole docker image. This guide will use code. The options below are only available if you select code.
- Runtime Stack
- What language you want to code in,
.NET
will useC#
but JavaScript, Python, and Java are available. PowerShell Core and custom options are also available. - Region
- This is also available for Docker, select one that’s closest to most of the players in the game.
- Operating System
- Code can be ran on either Linux or Windows, since we chose
.Net
we’ll pickWindows
.
- Plan
- The plan defines how your app scales and how you pay for the services.
Consumption
grows the resources allocated to your function as usage requirements increase, and you will be charged based on how much resources you’ve used. More details available here, make sure to review this so you don’t have any surprise charges.
-
On the next screen you can adjust hosting related settings, in this case you can define a storage account or use the default generated one as below.
-
The networking tab doesn’t have anything useful for this function app.
-
The Monitoring tab lets you collect performance and other metrics from the function using Azure Application Insights. Select
yes
and either create anApplication Insights resource
or use the default generated one as below. -
Tags
are a name:value way of categorizing resources. -
Review the Function App’s configuration on the next page, and click the
Create
button. -
It will take a few minutes for the app to fully deploy. You can take a break here, you’ll know the process is completed when the page looks like below
- Click on the
Go to resource
button to see your new Function App.
Create the HTTP Trigger Function
- On the left hand section, find the
Functions
category. - Click on the
Functions
link to go the functions page. - Click on the
+ Create
button to create a new function - Select
Develop in Portal
as the development environment. Since this is a relatively simple app we can do everything within the browser and Azure Portal. - Select
HTTP trigger
as the template, this will let the app get data from Civilization VI using HTTP. - Give the function a name, such as
civ6turnbot
and set the authorization level toFunction
. - On the function page, under the
Developer
category, click on theCode + Test
link to open the code editor. - The default code will respond with a message using the value of the
name
parameter you send it. - You can test this code by using something like Postman. Functions also has a
Test/Run
tool. - The default settings for a test are to use the HTTP POST method, and provide a value of
Azure
to thename
parameter. The body is formatted in JSON.
- Clicking the
Run
button will show the response and content from the function.
Code the function
Copy the code below, replacing all the existing default code from the function.
The code ingests the JSON data from Civilization VI and sends a Telegram BOT API call with a message informing the next player its their turn. A Dictionary called players
stores a list of players with the first parameter as their username in Civilization VI or Steam, and the second parameter as a markdown tag to create a custom @ mention in telegram with the associated player’s Telegram Id. Using the telegram Id allows tagging players who might not have a Telegram username. You can find a user’s Telegram Id using the the instructions here.
#r "Newtonsoft.Json"
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
public static async Task Run(HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
Dictionary players = new Dictionary();
players.Add("Player 1", "[Player 1 Name](tg://user?id=99999999)");
players.Add("Player 2", "[Player 2 Name](tg://user?id=11111111)");
players.Add("Player 3", "[Player 3 Name](tg://user?id=22222222)");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
string name = data.value2;
string message = "Hey " + players[name] + "! Its your turn on `" + data?.value1 +"`";
var results = await SendTelegramMessage(message);
log.LogInformation(String.Format("{0}", results));
string responseMessage = String.Format("{0}", results);
return new OkObjectResult(responseMessage);
}
public static async Task SendTelegramMessage(string text)
{
using (var client = new HttpClient())
{
Dictionary dictionary = new Dictionary();
dictionary.Add("chat_id", "CHAT_ID");
dictionary.Add("text", text);
dictionary.Add("parse_mode", "Markdown");
string json = JsonConvert.SerializeObject(dictionary);
var requestData = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(String.Format("https://api.telegram.org/botID:AUTH/sendMessage"), requestData);
var result = await response.Content.ReadAsStringAsync();
return result;
}
}
Connect the Telegram Bot
- If you completed the perquisites you should have a;
- Telegram Bot API Token
- a Telegram group Id
- a list of Telegram user Ids.
- In the code above, go to
line 40
and replaceCHAT_ID
with the ID of the group or user you want to send messages to. Ideally this will be a group Id that starts with a-
and looks like-210987654
- You can also use a regular
chat ID
, which is a positive integer, therefore doesn’t start with a-
. - Go to
line 47
and changebotID:AUTH
to the bot API Token which starts withbot
and looks like123456789:jbd78sadvbdy63d37gda37bd8
. Within the code it should look likebot123456789:jbd78sadvbdy63d37gda37bd8
- For testing purposes you can leave the
players
Dict with sample data and replace it once you’ve verified the function is working with Telegram.
Test the Function
- Click on
Test/Run
to open the testing panel. - In the Input section, add the JSON below to the Body.
{
"value1": "Azure",
"value2": "Player 2",
"value3": "3"
}
- You should receive a message from your bot in Telegram.
- You can see additional details about your call to the Telegram Bot API in the output tab of the
Test/Run
panel.
Setup the players
- The Dictionary
players
online 17
holds information regarding the players.
Dictionary players = new Dictionary();
players.Add("Player 1", "[Player 1 Name](tg://user?id=99999999)");
players.Add("Player 2", "[Player 2 Name](tg://user?id=11111111)");
players.Add("Player 3", "[Player 3 Name](tg://user?id=22222222)");
-
You need three pieces of information to add a player
- Player 1
- The username sent by the Civilization VI.
- Player 1 Name
- The name you want to appear in telegram, this can be anything you want.
- user?id=99999999
- The Telegram user Id for the player.
-
The Civilization VI username can either be set in the game options, or the store/service username such as a Steam Username.
- You can get the Telegram user Id by following the instructions here.
Get the Webhook URL
- Return to the Function’s Overview page.
- Click the
Get Function Url
button to get the URL for the webhook. - Go to the Civilization VI Game Options screen and paste the URL into the
Play By Cloud Webhook URL
input. - Make sure to set the
Frequency
toEvery Turn
so the webhook is called for everyone’s turn, instead of only you. - Start a new
Play By Cloud
game and watch as you get tagged custom Telegram messages on players’ turns.
Notes
Only one player needs to have the Play By Cloud Webhook URL
setup, and the frequency set to every turn. If all players have the URL setup, you will receive multiple messages per turn in Telegram. Any changes to the game settings requires restarting the Play By Cloud game, so make sure to test everything out before starting a real game.
The code in the Function App can be modified to provide additional functions such as reminders when someone hasn’t played for some set time. Utilizing other Azure resources such as a database creates almost endless possibilities to what can be done.