public virtual void HandleRpcCall(RpcCalls rpcCall, HazelBinaryReader reader) { if (this is DummyComponent dummy) { Console.WriteLine($"[{GetType().Name}][{dummy.name}]Recived RPC call: {rpcCall}"); } else { Console.WriteLine($"[{GetType().Name}]Recived RPC call: {rpcCall}"); } }
internal IMessageWriter StartRpc(uint targetNetId, RpcCalls callId, int targetClientId = -1, MessageType type = MessageType.Reliable) { var writer = MessageWriter.Get(type); if (targetClientId < 0) { writer.StartMessage(MessageFlags.GameData); writer.Write(Code); } else { writer.StartMessage(MessageFlags.GameDataTo); writer.Write(Code); writer.WritePacked(targetClientId); } writer.StartMessage(GameDataTag.RpcFlag); writer.WritePacked(targetNetId); writer.Write((byte)callId); return(writer); }
public virtual async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { return(await HandleCustomRpcAsync(sender, target, call, reader) ?? await UnregisteredCall(call, sender)); }
public override ValueTask HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (call == RpcCalls.SnapTo) { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SnapTo)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SnapTo)} to a specific player instead of broadcast"); } if (!sender.Character.PlayerInfo.IsImpostor) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SnapTo)} as crewmate"); } SnapTo(ReadVector2(reader), reader.ReadUInt16()); } else { _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerCustomNetworkTransform), call); } return(default);
public override async ValueTask HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { switch (call) { case RpcCalls.Close: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.Close)} but was not a host"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.Close)} to a specific player instead of broadcast"); } break; } case RpcCalls.VotingComplete: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.VotingComplete)} but was not a host"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.VotingComplete)} to a specific player instead of broadcast"); } var states = reader.ReadBytesAndSize(); var playerId = reader.ReadByte(); var tie = reader.ReadBoolean(); if (playerId != byte.MaxValue) { var player = _game.GameNet.GameData.GetPlayerById(playerId); if (player != null) { player.Controller.Die(DeathReason.Exile); await _eventManager.CallAsync(new PlayerExileEvent(_game, sender, player.Controller)); } } await _eventManager.CallAsync(new MeetingEndedEvent(_game, this)); break; } case RpcCalls.CastVote: { var srcPlayerId = reader.ReadByte(); if (srcPlayerId != sender.Character.PlayerId) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CastVote)} to an unowned {nameof(InnerPlayerControl)}"); } // Host broadcasts vote to others. if (sender.IsHost && target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CastVote)} to a specific player instead of broadcast"); } // Player sends vote to host. if (target == null || !target.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CastVote)} to wrong destinition, must be host"); } var targetPlayerId = reader.ReadByte(); break; } default: { _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerMeetingHud), call); break; } } }
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (!await ValidateHost(call, sender)) { return(false); } switch (call) { case RpcCalls.SetTasks: { Rpc29SetTasks.Deserialize(reader, out var playerId, out var taskTypeIds); SetTasks(playerId, taskTypeIds); break; } default: return(await UnregisteredCall(call, sender)); } return(true); }
public override async ValueTask HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { switch (call) { // Play an animation. case RpcCalls.PlayAnimation: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.PlayAnimation)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.PlayAnimation)} to a specific player instead of broadcast"); } var animation = reader.ReadByte(); break; } // Complete a task. case RpcCalls.CompleteTask: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CompleteTask)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CompleteTask)} to a specific player instead of broadcast"); } var taskId = reader.ReadPackedUInt32(); var task = PlayerInfo.Tasks[(int)taskId]; if (task == null) { _logger.LogWarning($"Client sent {nameof(RpcCalls.CompleteTask)} with a taskIndex that is not in their {nameof(InnerPlayerInfo)}"); } else { task.Complete = true; await _eventManager.CallAsync(new PlayerCompletedTaskEvent(_game, sender, this, task)); } break; } // Update GameOptions. case RpcCalls.SyncSettings: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SyncSettings)} but was not a host"); } _game.Options.Deserialize(reader.ReadBytesAndSize()); break; } // Set Impostors. case RpcCalls.SetInfected: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetInfected)} but was not a host"); } var length = reader.ReadPackedInt32(); for (var i = 0; i < length; i++) { var playerId = reader.ReadByte(); var player = _game.GameNet.GameData.GetPlayerById(playerId); if (player != null) { player.IsImpostor = true; } } if (_game.GameState == GameStates.Starting) { await _game.StartedAsync(); } break; } // Player was voted out. case RpcCalls.Exiled: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.Exiled)} but was not a host"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.Exiled)} to a specific player instead of broadcast"); } // TODO: Not hit? Die(DeathReason.Exile); await _eventManager.CallAsync(new PlayerExileEvent(_game, sender, this)); break; } // Validates the player name at the host. case RpcCalls.CheckName: { if (target == null || !target.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckName)} to the wrong player"); } var name = reader.ReadString(); break; } // Update the name of a player. case RpcCalls.SetName: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} but was not a host"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} to a specific player instead of broadcast"); } PlayerInfo.PlayerName = reader.ReadString(); break; } // Validates the color at the host. case RpcCalls.CheckColor: { if (target == null || !target.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckColor)} to the wrong player"); } var color = reader.ReadByte(); break; } // Update the color of a player. case RpcCalls.SetColor: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetColor)} but was not a host"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetColor)} to a specific player instead of broadcast"); } PlayerInfo.ColorId = reader.ReadByte(); break; } // Update the hat of a player. case RpcCalls.SetHat: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetHat)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetHat)} to a specific player instead of broadcast"); } PlayerInfo.HatId = reader.ReadPackedUInt32(); break; } case RpcCalls.SetSkin: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetSkin)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetHat)} to a specific player instead of broadcast"); } PlayerInfo.SkinId = reader.ReadPackedUInt32(); break; } // TODO: (ANTICHEAT) Location check? // only called by a non-host player on to start meeting case RpcCalls.ReportDeadBody: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.ReportDeadBody)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.ReportDeadBody)} to a specific player instead of broadcast"); } var deadBodyPlayerId = reader.ReadByte(); // deadBodyPlayerId == byte.MaxValue -- means emergency call by button break; } // TODO: (ANTICHEAT) Cooldown check? case RpcCalls.MurderPlayer: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} to a specific player instead of broadcast"); } if (!sender.Character.PlayerInfo.IsImpostor) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} as crewmate"); } if (!sender.Character.PlayerInfo.CanMurder(_game)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} too fast"); } sender.Character.PlayerInfo.LastMurder = DateTimeOffset.UtcNow; var player = reader.ReadNetObject <InnerPlayerControl>(_game); if (!player.PlayerInfo.IsDead) { player.Die(DeathReason.Kill); await _eventManager.CallAsync(new PlayerMurderEvent(_game, sender, this, player)); } break; } case RpcCalls.SendChat: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChat)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChat)} to a specific player instead of broadcast"); } var chat = reader.ReadString(); await _eventManager.CallAsync(new PlayerChatEvent(_game, sender, this, chat)); break; } case RpcCalls.StartMeeting: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.StartMeeting)} but was not a host"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.StartMeeting)} to a specific player instead of broadcast"); } // deadBodyPlayerId == byte.MaxValue -- means emergency call by button var deadBodyPlayerId = reader.ReadByte(); var deadPlayer = deadBodyPlayerId != byte.MaxValue ? _game.GameNet.GameData.GetPlayerById(deadBodyPlayerId)?.Controller : null; await _eventManager.CallAsync(new PlayerStartMeetingEvent(_game, _game.GetClientPlayer(this.OwnerId), this, deadPlayer)); break; } case RpcCalls.SetScanner: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetScanner)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetScanner)} to a specific player instead of broadcast"); } var on = reader.ReadBoolean(); var count = reader.ReadByte(); break; } case RpcCalls.SendChatNote: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChatNote)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChatNote)} to a specific player instead of broadcast"); } var playerId = reader.ReadByte(); var chatNote = (ChatNoteType)reader.ReadByte(); break; } case RpcCalls.SetPet: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetPet)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetPet)} to a specific player instead of broadcast"); } PlayerInfo.PetId = reader.ReadPackedUInt32(); break; } // TODO: Understand this RPC case RpcCalls.SetStartCounter: { if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetStartCounter)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetStartCounter)} to a specific player instead of broadcast"); } // Used to compare with LastStartCounter. var startCounter = reader.ReadPackedUInt32(); // Is either start countdown or byte.MaxValue var secondsLeft = reader.ReadByte(); if (secondsLeft < byte.MaxValue) { await _eventManager.CallAsync(new PlayerSetStartCounterEvent(_game, sender, this, secondsLeft)); } break; } default: { _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerPlayerControl), call); break; } } }
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { switch (call) { case RpcCalls.Close: { if (!await ValidateHost(call, sender)) { return(false); } Rpc22Close.Deserialize(reader); break; } case RpcCalls.VotingComplete: { if (!await ValidateHost(call, sender)) { return(false); } Rpc23VotingComplete.Deserialize(reader, out ReadOnlyMemory <byte> states, out byte playerId, out bool tie); await HandleVotingComplete(sender, states, playerId, tie); break; } case RpcCalls.CastVote: { Rpc24CastVote.Deserialize(reader, out byte playerId, out sbyte suspectPlayerId); return(await HandleCastVote(sender, target, playerId, suspectPlayerId)); } case RpcCalls.ClearVote: { if (!await ValidateHost(call, sender)) { return(false); } Rpc25ClearVote.Deserialize(reader); break; } default: return(await base.HandleRpcAsync(sender, target, call, reader)); } return(true); }
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (!await ValidateOwnership(call, sender) || !await ValidateImpostor(RpcCalls.MurderPlayer, sender, _playerControl.PlayerInfo)) { return(false); } int ventId; switch (call) { case RpcCalls.EnterVent: Rpc19EnterVent.Deserialize(reader, out ventId); break; case RpcCalls.ExitVent: Rpc19EnterVent.Deserialize(reader, out ventId); break; case RpcCalls.CustomRpc: return(await HandleCustomRpc(reader, _game)); default: return(await UnregisteredCall(call, sender)); } await _eventManager.CallAsync(new PlayerVentEvent(_game, sender, _playerControl, (VentLocation)ventId, call == RpcCalls.EnterVent)); return(true); }
public override async ValueTask HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { switch (call) { // Play an animation. case RpcCalls.PlayAnimation: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.PlayAnimation)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.PlayAnimation)} to a specific player instead of broadcast"); } var animation = reader.ReadByte(); break; } // Complete a task. case RpcCalls.CompleteTask: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CompleteTask)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CompleteTask)} to a specific player instead of broadcast"); } var taskId = reader.ReadPackedUInt32(); var task = PlayerInfo.Tasks[(int)taskId]; if (task == null) { // _logger.LogWarning($"Client sent {nameof(RpcCalls.CompleteTask)} with a taskIndex that is not in their {nameof(InnerPlayerInfo)}"); } else { task.Complete = true; await _eventManager.CallAsync(new PlayerCompletedTaskEvent(_game, sender, this, task)); } break; } // Update GameOptions. case RpcCalls.SyncSettings: { if (!sender.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SyncSettings)} but was not a host"); } _game.Options.Deserialize(reader.ReadBytesAndSize()); break; } // Set Impostors. case RpcCalls.SetInfected: { if (!sender.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetInfected)} but was not a host"); } var length = reader.ReadPackedInt32(); for (var i = 0; i < length; i++) { var playerId = reader.ReadByte(); var player = _game.GameNet.GameData.GetPlayerById(playerId); if (player != null) { player.IsImpostor = true; } } if (_game.GameState == GameStates.Starting) { await _game.StartedAsync(); } break; } // Player was voted out. case RpcCalls.Exiled: { if (!sender.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.Exiled)} but was not a host"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.Exiled)} to a specific player instead of broadcast"); } // TODO: Not hit? Die(DeathReason.Exile); await _eventManager.CallAsync(new PlayerExileEvent(_game, sender, this)); break; } // Validates the player name at the host. case RpcCalls.CheckName: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckName)} to an unowned {nameof(InnerPlayerControl)}"); } if (target == null || !target.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckName)} to the wrong player"); } var name = reader.ReadString(); if (name.Length > 10) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckName)} with name exceeding 10 characters"); } if (string.IsNullOrWhiteSpace(name) || !name.All(TextBox.IsCharAllowed)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckName)} with name containing illegal characters"); } if (sender.Client.Name != name) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} with name not matching his name from handshake"); } PlayerInfo.RequestedPlayerName = name; break; } // Update the name of a player. case RpcCalls.SetName: { if (!sender.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} but was not a host"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} to a specific player instead of broadcast"); } var name = reader.ReadString(); if (sender.IsOwner(this)) { if (_game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.PlayerName == name)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} with a name that is already used"); } if (sender.Client.Name != name) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} with name not matching his name from handshake"); } } else { if (PlayerInfo.RequestedPlayerName == null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} for a player that didn't request it"); } var expected = PlayerInfo.RequestedPlayerName !; if (_game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.PlayerName == expected)) { var i = 1; while (true) { string text = expected + " " + i; if (_game.Players.All(x => x.Character == null || x.Character == this || x.Character.PlayerInfo.PlayerName != text)) { expected = text; break; } i++; } } if (name != expected) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetName)} with incorrect name"); } } PlayerInfo.PlayerName = name; PlayerInfo.RequestedPlayerName = null; break; } // Validates the color at the host. case RpcCalls.CheckColor: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckColor)} to an unowned {nameof(InnerPlayerControl)}"); } if (target == null || !target.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckColor)} to the wrong player"); } var color = reader.ReadByte(); if (color > Enum.GetValues <ColorType>().Length) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CheckColor)} with invalid color"); } PlayerInfo.RequestedColorId = color; break; } // Update the color of a player. case RpcCalls.SetColor: { if (!sender.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetColor)} but was not a host"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetColor)} to a specific player instead of broadcast"); } var color = reader.ReadByte(); if (sender.IsOwner(this)) { if (_game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.ColorId == color)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetColor)} with a color that is already used"); } } else { if (PlayerInfo.RequestedColorId == null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetColor)} for a player that didn't request it"); break; } var expected = PlayerInfo.RequestedColorId !.Value; while (_game.Players.Any(x => x.Character != null && x.Character != this && x.Character.PlayerInfo.ColorId == expected)) { expected = (byte)((expected + 1) % Enum.GetValues <ColorType>().Length); } if (color != expected) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetColor)} with incorrect color"); } } PlayerInfo.ColorId = color; PlayerInfo.RequestedColorId = null; break; } // Update the hat of a player. case RpcCalls.SetHat: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetHat)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetHat)} to a specific player instead of broadcast"); } PlayerInfo.HatId = reader.ReadPackedUInt32(); break; } case RpcCalls.SetSkin: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetSkin)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetHat)} to a specific player instead of broadcast"); } PlayerInfo.SkinId = reader.ReadPackedUInt32(); break; } // TODO: (ANTICHEAT) Location check? // only called by a non-host player on to start meeting case RpcCalls.ReportDeadBody: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.ReportDeadBody)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.ReportDeadBody)} to a specific player instead of broadcast"); } var deadBodyPlayerId = reader.ReadByte(); // deadBodyPlayerId == byte.MaxValue -- means emergency call by button break; } // TODO: (ANTICHEAT) Cooldown check? case RpcCalls.MurderPlayer: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} to a specific player instead of broadcast"); } if (!sender.Character.PlayerInfo.IsImpostor) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} as crewmate"); } if (!sender.Character.PlayerInfo.CanMurder(_game)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} too fast"); } sender.Character.PlayerInfo.LastMurder = DateTimeOffset.UtcNow; var player = reader.ReadNetObject <InnerPlayerControl>(_game); if (!player.PlayerInfo.IsDead) { player.Die(DeathReason.Kill); await _eventManager.CallAsync(new PlayerMurderEvent(_game, sender, this, player)); } break; } case RpcCalls.SendChat: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChat)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChat)} to a specific player instead of broadcast"); } var chat = reader.ReadString(); await _eventManager.CallAsync(new PlayerChatEvent(_game, sender, this, chat)); break; } case RpcCalls.StartMeeting: { if (!sender.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.StartMeeting)} but was not a host"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.StartMeeting)} to a specific player instead of broadcast"); } // deadBodyPlayerId == byte.MaxValue -- means emergency call by button var deadBodyPlayerId = reader.ReadByte(); var deadPlayer = deadBodyPlayerId != byte.MaxValue ? _game.GameNet.GameData.GetPlayerById(deadBodyPlayerId)?.Controller : null; await _eventManager.CallAsync(new PlayerStartMeetingEvent(_game, _game.GetClientPlayer(this.OwnerId), this, deadPlayer)); break; } case RpcCalls.SetScanner: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetScanner)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetScanner)} to a specific player instead of broadcast"); } var on = reader.ReadBoolean(); var count = reader.ReadByte(); break; } case RpcCalls.SendChatNote: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChatNote)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SendChatNote)} to a specific player instead of broadcast"); } var playerId = reader.ReadByte(); var chatNote = (ChatNoteType)reader.ReadByte(); break; } case RpcCalls.SetPet: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetPet)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetPet)} to a specific player instead of broadcast"); } PlayerInfo.PetId = reader.ReadPackedUInt32(); break; } // TODO: Understand this RPC case RpcCalls.SetStartCounter: { if (!sender.IsOwner(this)) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetStartCounter)} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetStartCounter)} to a specific player instead of broadcast"); } // Used to compare with LastStartCounter. var startCounter = reader.ReadPackedUInt32(); // Is either start countdown or byte.MaxValue var secondsLeft = reader.ReadByte(); if (secondsLeft < byte.MaxValue) { await _eventManager.CallAsync(new PlayerSetStartCounterEvent(_game, sender, this, secondsLeft)); } break; } default: { // _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerPlayerControl), call); break; } } }
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (call == RpcCalls.SnapTo) { if (!await ValidateOwnership(call, sender) || !await ValidateImpostor(RpcCalls.MurderPlayer, sender, _playerControl.PlayerInfo)) { return(false); } Rpc21SnapTo.Deserialize(reader, out var position, out var minSid); await SnapToAsync(sender, position, minSid); return(true); } return(await UnregisteredCall(call, sender)); }
public override async ValueTask <bool> HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (!await TestRpc(sender, target, call, Rpcs)) { return(false); } if (call == RpcCalls.SnapTo) { if (!_playerControl.PlayerInfo.IsImpostor) { if (await sender.Client.ReportCheatAsync(CheatContext.Deserialize, $"Client sent {nameof(RpcCalls.SnapTo)} as crewmate")) { return(false); } } Rpc21SnapTo.Deserialize(reader, out var position, out var minSid); SnapTo(position, minSid); } return(true); }
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { switch (call) { case RpcCalls.PlayAnimation: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc00PlayAnimation.Deserialize(reader, out TaskTypes task); break; } case RpcCalls.CompleteTask: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc01CompleteTask.Deserialize(reader, out uint taskId); await HandleCompleteTask(sender, taskId); break; } case RpcCalls.SyncSettings: { if (!await ValidateHost(call, sender)) { return(false); } Rpc02SyncSettings.Deserialize(reader, Game.Options); break; } case RpcCalls.SetInfected: { if (!await ValidateOwnership(call, sender) || !await ValidateHost(call, sender)) { return(false); } Rpc03SetInfected.Deserialize(reader, out ReadOnlyMemory <byte> infectedIds); await HandleSetInfected(infectedIds); break; } case RpcCalls.CheckName: { if (!await ValidateOwnership(call, sender) || !await ValidateCmd(call, sender, target)) { return(false); } Rpc05CheckName.Deserialize(reader, out var name); return(await HandleCheckName(sender, name)); } case RpcCalls.SetName: { if (!await ValidateHost(call, sender)) { return(false); } Rpc06SetName.Deserialize(reader, out var name); return(await HandleSetName(sender, name)); } case RpcCalls.CheckColor: { if (!await ValidateOwnership(call, sender) || !await ValidateCmd(call, sender, target)) { return(false); } Rpc07CheckColor.Deserialize(reader, out ColorType color); return(await HandleCheckColor(sender, color)); } case RpcCalls.SetColor: { if (!await ValidateHost(call, sender)) { return(false); } Rpc08SetColor.Deserialize(reader, out ColorType color); return(await HandleSetColor(sender, color)); } case RpcCalls.SetHat: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc09SetHat.Deserialize(reader, out HatType hat); return(await HandleSetHat(sender, hat)); } case RpcCalls.SetSkin: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc10SetSkin.Deserialize(reader, out SkinType skin); return(await HandleSetSkin(sender, skin)); } case RpcCalls.ReportDeadBody: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc11ReportDeadBody.Deserialize(reader, out byte targetId); break; } case RpcCalls.MurderPlayer: { if (!await ValidateOwnership(call, sender) || !await ValidateImpostor(call, sender, PlayerInfo)) { return(false); } Rpc12MurderPlayer.Deserialize(reader, Game, out IInnerPlayerControl? murdered); return(await HandleMurderPlayer(sender, murdered)); } case RpcCalls.SendChat: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc13SendChat.Deserialize(reader, out var message); return(await HandleSendChat(sender, message)); } case RpcCalls.StartMeeting: { if (!await ValidateHost(call, sender)) { return(false); } Rpc14StartMeeting.Deserialize(reader, out byte targetId); await HandleStartMeeting(targetId); break; } case RpcCalls.SetScanner: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc15SetScanner.Deserialize(reader, out bool on, out byte scannerCount); break; } case RpcCalls.SendChatNote: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc16SendChatNote.Deserialize(reader, out byte playerId, out ChatNoteType chatNoteType); break; } case RpcCalls.SetPet: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc17SetPet.Deserialize(reader, out PetType pet); return(await HandleSetPet(sender, pet)); } case RpcCalls.SetStartCounter: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc18SetStartCounter.Deserialize(reader, out int sequenceId, out sbyte startCounter); return(await HandleSetStartCounter(sender, sequenceId, startCounter)); } case RpcCalls.UsePlatform: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc32UsePlatform.Deserialize(reader); break; } default: return(await base.HandleRpcAsync(sender, target, call, reader)); } return(true); }
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { switch (call) { case RpcCalls.Close: { if (!await ValidateHost(call, sender)) { return(false); } Rpc22Close.Deserialize(reader); break; } case RpcCalls.VotingComplete: { if (!await ValidateHost(call, sender)) { return(false); } Rpc23VotingComplete.Deserialize(reader, out var states, out var playerId, out var tie); await HandleVotingComplete(sender, states, playerId, tie); break; } case RpcCalls.CastVote: { Rpc24CastVote.Deserialize(reader, out var playerId, out var suspectPlayerId); return(await HandleCastVote(sender, target, playerId, suspectPlayerId)); } case RpcCalls.ClearVote: { if (!await ValidateHost(call, sender)) { return(false); } Rpc25ClearVote.Deserialize(reader); break; } case RpcCalls.CustomRpc: return(await HandleCustomRpc(reader, _game)); default: return(await UnregisteredCall(call, sender)); } return(true); }
protected async ValueTask <bool?> HandleCustomRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (_customMessageManager.TryGet((byte)call, out var customRpc)) { return(await customRpc.HandleRpcAsync(this, sender, target, reader)); } return(null); }
public abstract ValueTask <bool> HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader);
protected async ValueTask <bool> TestRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, Dictionary <RpcCalls, RpcInfo> rpcs) { if (call == RpcCalls.CustomRpc) { return(true); } if (rpcs.TryGetValue(call, out var rpc)) { if (rpc.CheckOwnership && !sender.IsOwner(this)) { if (await sender.Client.ReportCheatAsync(call, $"Client sent {call} to an unowned {GetType().Name}")) { return(false); } } if (rpc.RequireHost && !sender.IsHost) { if (await sender.Client.ReportCheatAsync(call, $"Client attempted to send {call} as non-host")) { return(false); } } switch (rpc.TargetType) { case RpcTargetType.Target when target == null: { if (await sender.Client.ReportCheatAsync(call, $"Client sent {call} as a broadcast instead to specific player")) { return(false); } break; } case RpcTargetType.Broadcast when target != null: { if (await sender.Client.ReportCheatAsync(call, $"Client sent {call} to a specific player instead of broadcast")) { return(false); } break; } case RpcTargetType.Cmd when target == null || !target.IsHost: { if (await sender.Client.ReportCheatAsync(call, $"Client sent {call} to the wrong player")) { return(false); } break; } case RpcTargetType.Both: break; } return(true); } if (await sender.Client.ReportCheatAsync(call, "Client sent unregistered call")) { return(false); } return(true); }
public override async ValueTask <bool> HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (!await TestRpc(sender, target, call, Rpcs)) { return(false); } switch (call) { case RpcCalls.CloseDoorsOfType: { if (target == null || !target.IsHost) { if (await sender.Client.ReportCheatAsync(RpcCalls.CloseDoorsOfType, $"Client sent {nameof(RpcCalls.CloseDoorsOfType)} to wrong destinition, must be host")) { return(false); } } if (!sender.Character.PlayerInfo.IsImpostor) { if (await sender.Client.ReportCheatAsync(RpcCalls.CloseDoorsOfType, $"Client sent {nameof(RpcCalls.CloseDoorsOfType)} as crewmate")) { return(false); } } Rpc27CloseDoorsOfType.Deserialize(reader, out var systemType); break; } case RpcCalls.RepairSystem: { if (target == null || !target.IsHost) { if (await sender.Client.ReportCheatAsync(RpcCalls.RepairSystem, $"Client sent {nameof(RpcCalls.RepairSystem)} to wrong destinition, must be host")) { return(false); } } Rpc28RepairSystem.Deserialize(reader, _game, out var systemType, out var player, out var amount); if (systemType == SystemTypes.Sabotage && !sender.Character.PlayerInfo.IsImpostor) { if (await sender.Client.ReportCheatAsync(RpcCalls.RepairSystem, $"Client sent {nameof(RpcCalls.RepairSystem)} for {systemType} as crewmate")) { return(false); } } break; } } return(true); }
public override async ValueTask <bool> HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (!await TestRpc(sender, target, call, Rpcs)) { return(false); } switch (call) { case RpcCalls.Close: { Rpc22Close.Deserialize(reader); break; } case RpcCalls.VotingComplete: { Rpc23VotingComplete.Deserialize(reader, out var states, out var playerId, out var tie); await HandleVotingComplete(sender, states, playerId, tie); break; } case RpcCalls.CastVote: { Rpc24CastVote.Deserialize(reader, out var playerId, out var suspectPlayerId); return(await HandleCastVote(sender, target, playerId, suspectPlayerId)); } case RpcCalls.ClearVote: { Rpc25ClearVote.Deserialize(reader); break; } } return(true); }
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (call == RpcCalls.AddVote) { Rpc26AddVote.Deserialize(reader, out var clientId, out var targetClientId); if (clientId != sender.Client.Id) { if (await sender.Client.ReportCheatAsync(RpcCalls.AddVote, $"Client sent {nameof(RpcCalls.AddVote)} as other client")) { return(false); } } return(true); } return(await UnregisteredCall(call, sender)); }
public override async ValueTask <bool> HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (!await TestRpc(sender, target, call, Rpcs)) { return(false); } if (!_playerControl.PlayerInfo.IsImpostor) { if (await sender.Client.ReportCheatAsync(RpcCalls.EnterVent, $"Client sent {call} as crewmate")) { return(false); } } int ventId; switch (call) { case RpcCalls.EnterVent: Rpc19EnterVent.Deserialize(reader, out ventId); break; case RpcCalls.ExitVent: Rpc19EnterVent.Deserialize(reader, out ventId); break; default: return(false); } await _eventManager.CallAsync(new PlayerVentEvent(_game, sender, _playerControl, (VentLocation)ventId, call == RpcCalls.EnterVent)); return(true); }
public override ValueTask HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { switch (call) { case RpcCalls.CloseDoorsOfType: { if (target == null || !target.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CloseDoorsOfType)} to wrong destinition, must be host"); } if (!sender.Character.PlayerInfo.IsImpostor) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CloseDoorsOfType)} as crewmate"); } var systemType = (SystemTypes)reader.ReadByte(); break; } case RpcCalls.RepairSystem: { if (target == null || !target.IsHost) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.RepairSystem)} to wrong destinition, must be host"); } var systemType = (SystemTypes)reader.ReadByte(); if (systemType == SystemTypes.Sabotage && !sender.Character.PlayerInfo.IsImpostor) { // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.RepairSystem)} for {systemType} as crewmate"); } var player = reader.ReadNetObject <InnerPlayerControl>(_game); var amount = reader.ReadByte(); // TODO: Modify data (?) break; } default: { // _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerShipStatus), call); break; } } return(default);
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (!await ValidateHost(call, sender)) { return(false); } switch (call) { case RpcCalls.SetTasks: { Rpc29SetTasks.Deserialize(reader, out var playerId, out var taskTypeIds); SetTasks(playerId, taskTypeIds); break; } case RpcCalls.UpdateGameData: { while (reader.Position < reader.Length) { using var message = reader.ReadMessage(); var player = GetPlayerById(message.Tag); if (player != null) { player.Deserialize(message); } else { var playerInfo = new InnerPlayerInfo(message.Tag); playerInfo.Deserialize(reader); if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo)) { throw new ImpostorException("Failed to add player to InnerGameData."); } } } break; } case RpcCalls.CustomRpc: return(await HandleCustomRpc(reader, _game)); default: return(await UnregisteredCall(call, sender)); } return(true); }
public override ValueTask <bool> HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { throw new System.NotImplementedException(); }
public override ValueTask HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { switch (call) { case RpcCalls.SetTasks: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetTasks)} but was not a host"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetTasks)} to a specific player instead of broadcast"); } var playerId = reader.ReadByte(); var taskTypeIds = reader.ReadBytesAndSize(); SetTasks(playerId, taskTypeIds); break; } case RpcCalls.UpdateGameData: { if (!sender.IsHost) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetTasks)} but was not a host"); } if (target != null) { throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetTasks)} to a specific player instead of broadcast"); } while (reader.Position < reader.Length) { using var message = reader.ReadMessage(); var player = GetPlayerById(message.Tag); if (player != null) { player.Deserialize(message); } else { var playerInfo = new InnerPlayerInfo(message.Tag); playerInfo.Deserialize(reader); if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo)) { throw new ImpostorException("Failed to add player to InnerGameData."); } } } break; } default: { _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerGameData), call); break; } } return(default);
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (!await ValidateCmd(call, sender, target)) { return(false); } switch (call) { case RpcCalls.CloseDoorsOfType: { if (!await ValidateImpostor(call, sender, sender.Character !.PlayerInfo)) { return(false); } Rpc27CloseDoorsOfType.Deserialize(reader, out var systemType); break; } case RpcCalls.RepairSystem: { Rpc28RepairSystem.Deserialize(reader, Game, out var systemType, out var player, out var amount); if (systemType == SystemTypes.Sabotage && !await ValidateImpostor(call, sender, sender.Character !.PlayerInfo)) { return(false); } break; } default: return(await UnregisteredCall(call, sender)); } return(true); }
public override async ValueTask HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (call != RpcCalls.EnterVent && call != RpcCalls.ExitVent) { _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerPlayerPhysics), call); return; } if (!sender.IsOwner(this)) { throw new ImpostorCheatException($"Client sent {call} to an unowned {nameof(InnerPlayerControl)}"); } if (target != null) { throw new ImpostorCheatException($"Client sent {call} to a specific player instead of broadcast"); } if (!sender.Character.PlayerInfo.IsImpostor) { throw new ImpostorCheatException($"Client sent {call} as crewmate"); } var ventId = reader.ReadPackedUInt32(); var ventEnter = call == RpcCalls.EnterVent; _logger.LogTrace($"{sender.Character.NetworkTransform.Position.X}; {sender.Character.NetworkTransform.Position.Y}"); _logger.LogTrace($"{ventId}"); await _eventManager.CallAsync(new PlayerVentEvent(_game, sender, _playerControl, (VentLocation)ventId, ventEnter)); return; }
public override ValueTask HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (call != RpcCalls.AddVote) { _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerVoteBanSystem), call); return(default);
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { if (!await ValidateOwnership(call, sender)) { return(false); } switch (call) { case RpcCalls.EnterVent: case RpcCalls.ExitVent: if (!await ValidateImpostor(call, sender, _playerControl.PlayerInfo)) { return(false); } int ventId; switch (call) { case RpcCalls.EnterVent: Rpc19EnterVent.Deserialize(reader, out ventId); break; case RpcCalls.ExitVent: Rpc20ExitVent.Deserialize(reader, out ventId); break; default: throw new ArgumentOutOfRangeException(nameof(call), call, null); } var vent = Game.GameNet.ShipStatus !.Data.Vents[ventId]; switch (call) { case RpcCalls.EnterVent: await _eventManager.CallAsync(new PlayerEnterVentEvent(Game, sender, _playerControl, vent)); break; case RpcCalls.ExitVent: await _eventManager.CallAsync(new PlayerExitVentEvent(Game, sender, _playerControl, vent)); break; } break; case RpcCalls.ClimbLadder: Rpc31ClimbLadder.Deserialize(reader, out var ladderId, out var lastClimbLadderSid); break; default: return(await UnregisteredCall(call, sender)); } return(true); }
public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader) { switch (call) { case RpcCalls.PlayAnimation: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc00PlayAnimation.Deserialize(reader, out var task); break; } case RpcCalls.CompleteTask: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc01CompleteTask.Deserialize(reader, out var taskId); await HandleCompleteTask(sender, taskId); break; } case RpcCalls.SyncSettings: { if (!await ValidateHost(call, sender)) { return(false); } Rpc02SyncSettings.Deserialize(reader, _game.Options); break; } case RpcCalls.SetInfected: { if (!await ValidateOwnership(call, sender) || !await ValidateHost(call, sender)) { return(false); } Rpc03SetInfected.Deserialize(reader, out var infectedIds); await HandleSetInfected(infectedIds); break; } case RpcCalls.CheckName: { if (!await ValidateOwnership(call, sender) || !await ValidateCmd(call, sender, target)) { return(false); } Rpc05CheckName.Deserialize(reader, out var name); return(await HandleCheckName(sender, name)); } case RpcCalls.SetName: { if (!await ValidateHost(call, sender)) { return(false); } Rpc06SetName.Deserialize(reader, out var name); return(await HandleSetName(sender, name)); } case RpcCalls.CheckColor: { if (!await ValidateOwnership(call, sender) || !await ValidateCmd(call, sender, target)) { return(false); } Rpc07CheckColor.Deserialize(reader, out var color); return(await HandleCheckColor(sender, color)); } case RpcCalls.SetColor: { if (!await ValidateHost(call, sender)) { return(false); } Rpc08SetColor.Deserialize(reader, out var color); return(await HandleSetColor(sender, color)); } case RpcCalls.SetHat: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc09SetHat.Deserialize(reader, out var hat); return(await HandleSetHat(sender, hat)); } case RpcCalls.SetSkin: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc10SetSkin.Deserialize(reader, out var skin); return(await HandleSetSkin(sender, skin)); } case RpcCalls.ReportDeadBody: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc11ReportDeadBody.Deserialize(reader, out var targetId); break; } case RpcCalls.MurderPlayer: { if (!await ValidateOwnership(call, sender) || !await ValidateImpostor(RpcCalls.MurderPlayer, sender, PlayerInfo)) { return(false); } Rpc12MurderPlayer.Deserialize(reader, _game, out var murdered); return(await HandleMurderPlayer(sender, murdered)); } case RpcCalls.SendChat: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc13SendChat.Deserialize(reader, out var message); return(await HandleSendChat(sender, message)); } case RpcCalls.StartMeeting: { if (!await ValidateHost(call, sender)) { return(false); } Rpc14StartMeeting.Deserialize(reader, out var targetId); await HandleStartMeeting(targetId); break; } case RpcCalls.SetScanner: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc15SetScanner.Deserialize(reader, out var on, out var scannerCount); break; } case RpcCalls.SendChatNote: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc16SendChatNote.Deserialize(reader, out var playerId, out var chatNoteType); break; } case RpcCalls.SetPet: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc17SetPet.Deserialize(reader, out var pet); return(await HandleSetPet(sender, pet)); } case RpcCalls.SetStartCounter: { if (!await ValidateOwnership(call, sender)) { return(false); } Rpc18SetStartCounter.Deserialize(reader, out var sequenceId, out var startCounter); return(await HandleSetStartCounter(sender, sequenceId, startCounter)); } case RpcCalls.CustomRpc: return(await HandleCustomRpc(reader, _game)); default: return(await UnregisteredCall(call, sender)); } return(true); }