public override async ValueTask HandleMessageAsync(IMessageReader reader, MessageType messageType) { using var messageCopy = reader.Copy(); // Trigger connect event. if (_isFirst) { _isFirst = false; await _recorder.WriteConnectAsync(this); } // Check if we were in-game before handling the message. var inGame = Player?.Game != null; if (!_recordAfter) { // Trigger message event. await _recorder.WriteMessageAsync(this, messageCopy, messageType); } // Handle the message. await base.HandleMessageAsync(reader, messageType); // Player created a game. if (reader.Tag == MessageFlags.HostGame) { _createdGame = true; } else if (reader.Tag == MessageFlags.JoinGame && _createdGame) { _createdGame = false; // We created a game and are now in-game, store that event. if (!inGame && Player?.Game != null) { await _recorder.WriteGameCreatedAsync(this, Player.Game.Code); } _recordAfter = false; // Trigger message event. await _recorder.WriteMessageAsync(this, messageCopy, messageType); } if (_recordAfter) { // Trigger message event. await _recorder.WriteMessageAsync(this, messageCopy, messageType); } }
public override async ValueTask HandleMessageAsync(IMessageReader reader, MessageType messageType) { var flag = reader.Tag; _logger.LogTrace("[{0}] Server got {1}.", Id, flag); switch (flag) { case MessageFlags.HostGame: { // Read game settings. var gameInfo = Message00HostGameC2S.Deserialize(reader, out _); // Create game. var game = await _gameManager.CreateAsync(this, gameInfo); if (game == null) { await DisconnectAsync(DisconnectReason.GameMissing); return; } // Code in the packet below will be used in JoinGame. using (var writer = MessageWriter.Get(MessageType.Reliable)) { Message00HostGameS2C.Serialize(writer, game.Code); await Connection.SendAsync(writer); } break; } case MessageFlags.JoinGame: { Message01JoinGameC2S.Deserialize(reader, out var gameCode); var game = _gameManager.Find(gameCode); if (game == null) { await DisconnectAsync(DisconnectReason.GameMissing); return; } var result = await game.AddClientAsync(this); switch (result.Error) { case GameJoinError.None: break; case GameJoinError.InvalidClient: await DisconnectAsync(DisconnectReason.Custom, "Client is in an invalid state."); break; case GameJoinError.Banned: await DisconnectAsync(DisconnectReason.Banned); break; case GameJoinError.GameFull: await DisconnectAsync(DisconnectReason.GameFull); break; case GameJoinError.InvalidLimbo: await DisconnectAsync(DisconnectReason.Custom, "Invalid limbo state while joining."); break; case GameJoinError.GameStarted: await DisconnectAsync(DisconnectReason.GameStarted); break; case GameJoinError.GameDestroyed: await DisconnectAsync(DisconnectReason.Custom, DisconnectMessages.Destroyed); break; case GameJoinError.Custom: await DisconnectAsync(DisconnectReason.Custom, result.Message); break; default: await DisconnectAsync(DisconnectReason.Custom, "Unknown error."); break; } break; } case MessageFlags.StartGame: { if (!IsPacketAllowed(reader, true)) { return; } await Player!.Game.HandleStartGame(reader); break; } // No idea how this flag is triggered. case MessageFlags.RemoveGame: break; case MessageFlags.RemovePlayer: { if (!IsPacketAllowed(reader, true)) { return; } Message04RemovePlayerC2S.Deserialize( reader, out var playerId, out var reason); await Player!.Game.HandleRemovePlayer(playerId, (DisconnectReason)reason); break; } case MessageFlags.GameData: case MessageFlags.GameDataTo: { if (!IsPacketAllowed(reader, false)) { return; } var toPlayer = flag == MessageFlags.GameDataTo; // Handle packet. using var readerCopy = reader.Copy(); var verified = await Player!.Game.HandleGameDataAsync(readerCopy, Player, toPlayer); if (verified) { // Broadcast packet to all other players. using (var writer = MessageWriter.Get(messageType)) { if (toPlayer) { var target = reader.ReadPackedInt32(); reader.CopyTo(writer); await Player.Game.SendToAsync(writer, target); } else { reader.CopyTo(writer); await Player.Game.SendToAllExceptAsync(writer, Id); } } } break; } case MessageFlags.EndGame: { if (!IsPacketAllowed(reader, true)) { return; } Message08EndGameC2S.Deserialize( reader, out var gameOverReason); await Player!.Game.HandleEndGame(reader, gameOverReason); break; } case MessageFlags.AlterGame: { if (!IsPacketAllowed(reader, true)) { return; } Message10AlterGameC2S.Deserialize( reader, out var gameTag, out var value); if (gameTag != AlterGameTags.ChangePrivacy) { return; } await Player!.Game.HandleAlterGame(reader, Player, value); break; } case MessageFlags.KickPlayer: { if (!IsPacketAllowed(reader, true)) { return; } Message11KickPlayerC2S.Deserialize( reader, out var playerId, out var isBan); await Player!.Game.HandleKickPlayer(playerId, isBan); break; } case MessageFlags.GetGameListV2: { Message16GetGameListC2S.Deserialize(reader, out var options, out _); await OnRequestGameListAsync(options); break; } default: _logger.LogWarning("Server received unknown flag {0}.", flag); break; } #if DEBUG if (flag != MessageFlags.GameData && flag != MessageFlags.GameDataTo && flag != MessageFlags.EndGame && reader.Position < reader.Length) { _logger.LogWarning( "Server did not consume all bytes from {0} ({1} < {2}).", flag, reader.Position, reader.Length); } #endif }