break;
}
- // 101A3BA6
- case RequestFlag.JoinedGame:
- break;
-
case RequestFlag.EndGame:
{
if (!IsPacketAllowed(message, true))
Player.Game.HandleEndGame(message);
break;
}
+
+ case RequestFlag.AlterGame:
+ {
+ if (!IsPacketAllowed(message, true))
+ {
+ return;
+ }
+
+ if (message.ReadByte() != (byte) AlterGameTags.ChangePrivacy)
+ {
+ return;
+ }
+
+ var isPublic = message.ReadByte() == 1;
+
+ Player.Game.HandleAlterGame(message, Player, isPublic);
+ break;
+ }
default:
Logger.Warning("Server received unknown flag {0}.", flag);
if (flag != RequestFlag.GameData &&
flag != RequestFlag.GameDataTo &&
+ flag != RequestFlag.EndGame &&
message.Position < message.Length)
{
Logger.Warning("Server did not consume all bytes from {0} ({1} < {2}).",
private void OnDisconnected(object sender, DisconnectedEventArgs e)
{
+ try
+ {
+ if (Player.Game != null)
+ {
+ Player.Game.HandleRemovePlayer(Id, 0);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Error(ex, "Exception caught in client disconnection.");
+ }
+
_clientManager.Remove(this);
}
}
using System;
using System.Collections.Concurrent;
using System.Linq;
+using AmongUs.Server.Data;
using AmongUs.Server.Exceptions;
using AmongUs.Server.Extensions;
using AmongUs.Server.Net.Response;
{
private static readonly ILogger Logger = Log.ForContext<Game>();
+ private readonly GameManager _gameManager;
private readonly ConcurrentDictionary<int, ClientPlayer> _players;
- public Game(int code, GameOptionsData options)
+ public Game(GameManager gameManager, int code, GameOptionsData options)
{
+ _gameManager = gameManager;
+ _players = new ConcurrentDictionary<int, ClientPlayer>();
+
Code = code;
CodeStr = GameCode.IntToGameName(code);
HostId = -1;
GameState = GameStates.NotStarted;
Options = options;
- _players = new ConcurrentDictionary<int, ClientPlayer>();
}
public int Code { get; }
}
}
- public void HandleJoinGame(ClientPlayer player)
+ public void HandleJoinGame(ClientPlayer sender)
{
switch (GameState)
{
case GameStates.NotStarted:
- HandleJoinGameNew(player);
+ HandleJoinGameNew(sender);
break;
case GameStates.Ended:
- HandleJoinGameNext(player);
+ HandleJoinGameNext(sender);
break;
case GameStates.Started:
+ sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.GameStarted));
+ return;
case GameStates.Destroyed:
- player.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.GameStarted));
+ sender.Client.Connection.Send(new Message1DisconnectReason(DisconnectReason.Custom, DisconnectMessages.Destroyed));
return;
default:
throw new ArgumentOutOfRangeException();
_players.Clear();
}
- public void HandleRemovePlayer(int playerId, byte reason)
+ public void HandleAlterGame(MessageReader message, ClientPlayer sender, bool isPublic)
{
- _players.TryRemove(playerId, out var player);
+ IsPublic = isPublic;
- // TODO: Host migration
+ using (var packet = MessageWriter.Get(SendOption.Reliable))
+ {
+ packet.CopyFrom(message);
+ SendToAllExcept(packet, sender);
+ }
+ }
+
+ public void HandleRemovePlayer(int playerId, byte reason)
+ {
+ if (_players.TryRemove(playerId, out var player))
+ {
+ player.Game = null;
+ }
+
+ // Game is empty, remove it.
+ if (_players.Count == 0)
+ {
+ GameState = GameStates.Destroyed;
+
+ // Remove instance reference.
+ _gameManager.Remove(Code);
+ return;
+ }
+
+ // Host migration.
+ if (HostId == playerId)
+ {
+ HostId = _players.First().Value.Client.Id;
+ }
using (var packet = MessageWriter.Get(SendOption.Reliable))
{
+ packet.StartMessage((byte) RequestFlag.RemovePlayer);
packet.Write(Code);
packet.Write(playerId);
packet.Write(HostId);
packet.Write(reason);
+ packet.EndMessage();
SendToAllExcept(packet, player);
}