-
Notifications
You must be signed in to change notification settings - Fork 331
/
Game.State.cs
104 lines (85 loc) · 2.99 KB
/
Game.State.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System.Linq;
using System.Threading.Tasks;
using Impostor.Server.Exceptions;
using Impostor.Server.Net.Messages;
using Impostor.Shared.Innersloth.Data;
namespace Impostor.Server.Net.State
{
internal partial class Game
{
private void PlayerAdd(IClientPlayer player)
{
// Store player.
if (!_players.TryAdd(player.Client.Id, player))
{
throw new AmongUsException("Failed to add player to game.");
}
// Assign hostId if none is set.
if (HostId == -1)
{
HostId = player.Client.Id;
}
}
private async ValueTask<bool> PlayerRemove(int playerId, bool isBan = false)
{
if (!_players.TryRemove(playerId, out var player))
{
return false;
}
Logger.Information("{0} - Player {1} ({2}) has left.", Code, player.Client.Name, playerId);
player.Client.Player = null;
// Game is empty, remove it.
if (_players.IsEmpty)
{
GameState = GameStates.Destroyed;
// Remove instance reference.
await _gameManager.RemoveAsync(Code);
return true;
}
// Host migration.
if (HostId == playerId)
{
await MigrateHost();
}
if (isBan && player.Client.Connection != null)
{
_bannedIps.Add(player.Client.Connection.EndPoint.Address);
}
return true;
}
private async ValueTask MigrateHost()
{
// Pick the first player as new host.
var host = _players
.Select(p => p.Value)
.FirstOrDefault(p => !p.Client.IsBot);
if (host == null)
{
await EndAsync();
return;
}
HostId = host.Client.Id;
Logger.Information("{0} - Assigned {1} ({2}) as new host.", Code, host.Client.Name, host.Client.Id);
// Check our current game state.
if (GameState == GameStates.Ended && host.Limbo == LimboStates.WaitingForHost)
{
GameState = GameStates.NotStarted;
// Spawn the host.
await HandleJoinGameNew(host, false);
// Pull players out of limbo.
await CheckLimboPlayers();
}
}
private async ValueTask CheckLimboPlayers()
{
using var message = CreateMessage(MessageType.Reliable);
foreach (var (_, player) in _players.Where(x => x.Value.Limbo == LimboStates.WaitingForHost))
{
WriteJoinedGameMessage(message, true, player);
WriteAlterGameMessage(message, false, IsPublic);
player.Limbo = LimboStates.NotLimbo;
await message.SendToAsync(player.Client);
}
}
}
}