https://www.assetstore.unity3d.com/en/#!/content/72019
http://neverfall.ru/Telegram/
С помощью TUN можно легко добавить в свою игру внутреигровой чат, как для приватных сообщений, так и для группового общения (например, для каждой игровой локации - своя чат-комната).
Так же, Telegram является отличным решением для идентификации (регистрации и авторизации) пользователей и их социальных взаимодействий (публикация скриншотов на каналы, приглашение друзей,...)
(число активных пользователей Telegram превышает 100 миллионов в месяц)
https://telegram.org/blog/100-million
Медвежонок бегает по комнатам, перемещаясь при этом чат-группам Телеграмма.
Публикация скриншота из игры в публичную группу:
* * *
Кроме этого, протокол MTProto можно использовать и для взаимодействия с собственным авторитарным сервером, если выполнить его в виде телеграм-бота (https://core.telegram.org/bots/api).
Вот пример сервера мультиплеерной игры в Крестики-нолики, который я написал за 10 минут, с использованием одной из общедоступных библиотек Telegram Bot API. Столь же легко, его можно написать на любом другом языке (PHP, Java, Node.js, Python, Ruby, Go, Lua, Haskell, Scala,...): https://core.telegram.org/bots/samples.
Синтаксис:
Используется csharp
using System.Collections.Generic;
using Telegram.Bot.Args;
using Telegram.Bot.Types.Enums;
namespace Telegram.Bot.TicTacToe
{
class Program
{
private static readonly TelegramBotClient Bot = new TelegramBotClient("");
static void Main(string[] args)
{
Bot.OnMessage += BotOnMessageReceived;
Bot.OnReceiveError += BotOnReceiveError;
Bot.StartReceiving();
System.Console.ReadLine();
Bot.StopReceiving();
}
private static void BotOnReceiveError(object sender, ReceiveErrorEventArgs receiveErrorEventArgs)
{
System.Diagnostics.Debugger.Break();
}
private static async void BotOnMessageReceived(object sender, MessageEventArgs messageEventArgs)
{
var message = messageEventArgs.Message;
if (message == null || message.Type != MessageType.TextMessage) return;
switch (message.Text)
{
case "9":
await Bot.SendTextMessageAsync(message.Chat.Id, GetGame(message.Chat.Id).Print());
break;
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
Game game = GetGame(message.Chat.Id);
string error = game.MakeTurn(message.Chat.Id, System.Int32.Parse(message.Text));
if (error != null)
{
await Bot.SendTextMessageAsync(message.Chat.Id, error);
}
else
{
await Bot.SendTextMessageAsync(game.users[0], game.Print());
if (game.users[1] != default(long))
await Bot.SendTextMessageAsync(game.users[1], game.Print());
if (game.IsFull() || game.CheckWin() != 2)
RemoveGame(game);
}
break;
default:
await Bot.SendTextMessageAsync(message.Chat.Id, "bad_request");
break;
}
}
private static List<Game> games = new List<Game>();
private static Game GetGame(long id)
{
foreach (var game in games)
{
if (game.users[0] == id || game.users[1] == id)
return game;
}
foreach (var game in games)
{
if (game.users[1] == default(long))
{
game.users[1] = id;
return game;
}
}
var newgame = new Game(id);
games.Add(newgame);
return newgame;
}
private static void RemoveGame(Game game)
{
games.Remove(game);
}
// 0 1 2
// 3 4 5
// 6 7 8
class Game
{
int turn = 0;
public long[] users = new long[2];
private int[] board = new int[9] { 2, 2, 2, 2, 2, 2, 2, 2, 2 };
public Game(long id)
{
users[0] = id;
}
public bool IsFull()
{
for (int i = 0; i < 9; i++)
{
if (board[i] == 2)
return false;
}
return true;
}
public int CheckWin()
{
if (board[4] != 2 && ((board[0] == board[4] && board[8] == board[4]) || (board[1] == board[4] && board[7] == board[4]) || (board[2] == board[4] && board[6] == board[4]) || (board[5] == board[4] && board[3] == board[4])))
return board[4];
if (board[0] != 2 && ((board[0] == board[1] && board[2] == board[0]) || (board[0] == board[3] && board[6] == board[0])))
return board[0];
if (board[8] != 2 && ((board[8] == board[5] && board[2] == board[0]) || (board[8] == board[7] && board[6] == board[0])))
return board[8];
return 2;
}
public string MakeTurn(long id, int i)
{
if (id != users[turn])
return "bad_user";
if (board[i] != 2)
return "bad_cell";
board[i] = turn;
if (turn == 0)
turn++;
else
turn--;
return null;
}
public string Print()
{
return string.Join("", board);
}
}
}
}
using Telegram.Bot.Args;
using Telegram.Bot.Types.Enums;
namespace Telegram.Bot.TicTacToe
{
class Program
{
private static readonly TelegramBotClient Bot = new TelegramBotClient("");
static void Main(string[] args)
{
Bot.OnMessage += BotOnMessageReceived;
Bot.OnReceiveError += BotOnReceiveError;
Bot.StartReceiving();
System.Console.ReadLine();
Bot.StopReceiving();
}
private static void BotOnReceiveError(object sender, ReceiveErrorEventArgs receiveErrorEventArgs)
{
System.Diagnostics.Debugger.Break();
}
private static async void BotOnMessageReceived(object sender, MessageEventArgs messageEventArgs)
{
var message = messageEventArgs.Message;
if (message == null || message.Type != MessageType.TextMessage) return;
switch (message.Text)
{
case "9":
await Bot.SendTextMessageAsync(message.Chat.Id, GetGame(message.Chat.Id).Print());
break;
case "0":
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
Game game = GetGame(message.Chat.Id);
string error = game.MakeTurn(message.Chat.Id, System.Int32.Parse(message.Text));
if (error != null)
{
await Bot.SendTextMessageAsync(message.Chat.Id, error);
}
else
{
await Bot.SendTextMessageAsync(game.users[0], game.Print());
if (game.users[1] != default(long))
await Bot.SendTextMessageAsync(game.users[1], game.Print());
if (game.IsFull() || game.CheckWin() != 2)
RemoveGame(game);
}
break;
default:
await Bot.SendTextMessageAsync(message.Chat.Id, "bad_request");
break;
}
}
private static List<Game> games = new List<Game>();
private static Game GetGame(long id)
{
foreach (var game in games)
{
if (game.users[0] == id || game.users[1] == id)
return game;
}
foreach (var game in games)
{
if (game.users[1] == default(long))
{
game.users[1] = id;
return game;
}
}
var newgame = new Game(id);
games.Add(newgame);
return newgame;
}
private static void RemoveGame(Game game)
{
games.Remove(game);
}
// 0 1 2
// 3 4 5
// 6 7 8
class Game
{
int turn = 0;
public long[] users = new long[2];
private int[] board = new int[9] { 2, 2, 2, 2, 2, 2, 2, 2, 2 };
public Game(long id)
{
users[0] = id;
}
public bool IsFull()
{
for (int i = 0; i < 9; i++)
{
if (board[i] == 2)
return false;
}
return true;
}
public int CheckWin()
{
if (board[4] != 2 && ((board[0] == board[4] && board[8] == board[4]) || (board[1] == board[4] && board[7] == board[4]) || (board[2] == board[4] && board[6] == board[4]) || (board[5] == board[4] && board[3] == board[4])))
return board[4];
if (board[0] != 2 && ((board[0] == board[1] && board[2] == board[0]) || (board[0] == board[3] && board[6] == board[0])))
return board[0];
if (board[8] != 2 && ((board[8] == board[5] && board[2] == board[0]) || (board[8] == board[7] && board[6] == board[0])))
return board[8];
return 2;
}
public string MakeTurn(long id, int i)
{
if (id != users[turn])
return "bad_user";
if (board[i] != 2)
return "bad_cell";
board[i] = turn;
if (turn == 0)
turn++;
else
turn--;
return null;
}
public string Print()
{
return string.Join("", board);
}
}
}
}
Это код сервера мультиплеерной игры Крестики-нолики. Ничего лишнего, написан за 10 минут, включая время на скачивание библиотеки для работы с API (https://github.com/MrRoundRobin/telegram.bot).
Вам не нужно думать о таких вещах как авторизация пользователей, видимость IP вашего сервера и т.д. Эту всю часть возьмёт на себя Telegram Cloud.