public void Deserialize(IMessageReader reader) { PlayerName = reader.ReadString(); Color = (ColorType)reader.ReadPackedInt32(); Hat = (HatType)reader.ReadPackedUInt32(); Pet = (PetType)reader.ReadPackedUInt32(); Skin = (SkinType)reader.ReadPackedUInt32(); var flag = reader.ReadByte(); Disconnected = (flag & 1) > 0; IsImpostor = (flag & 2) > 0; IsDead = (flag & 4) > 0; var taskCount = reader.ReadByte(); if (Tasks.Count != taskCount) { Tasks = new List <InnerGameData.TaskInfo>(taskCount); } for (var i = 0; i < taskCount; i++) { Tasks[i] ??= new InnerGameData.TaskInfo(); Tasks[i].Deserialize(reader); } }
public Vector3 ReadByteAngles(IMessageReader reader) { float angleX = AngleByteToFloat(reader.ReadByte()); float angleY = (reader.ReadByte()); return new Vector3(angleX, angleY, 0); }
public async 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(); if (amount == 7 || amount == 3 || amount == 14 || systemType == SystemTypes.Sabotage) { await _eventManager.CallAsync(new PlayerSabotageEvent(_game, _game.GetClientPlayer(player.OwnerId), player, amount)); } // TODO: Modify data (?) break; } default: { _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerShipStatus), call); break; } } return; }
public void Deserialize(IMessageReader reader, bool initialState) { Countdown = reader.ReadSingle(); UserConsolePairs.Clear(); // TODO: Thread safety int count = reader.ReadPackedInt32(); for (int i = 0; i < count; i++) { UserConsolePairs.Add(new Tuple <byte, byte>(reader.ReadByte(), reader.ReadByte())); } }
private static void HandleToServer(string source, IMessageReader packet) { var tagName = TagMap.ContainsKey(packet.Tag) ? TagMap[packet.Tag] : "Unknown"; Console.ForegroundColor = ConsoleColor.White; Console.WriteLine($"{source,-15} Server received: {packet.Tag,-2} {tagName}"); switch (packet.Tag) { case 0: Console.WriteLine("- GameInfo length " + packet.ReadBytesAndSize().Length); break; case 1: Console.WriteLine("- GameCode " + packet.ReadInt32()); Console.WriteLine("- Unknown " + packet.ReadByte()); break; case 5: case 6: Console.WriteLine("- GameCode " + packet.ReadInt32()); Console.WriteLine(HexUtils.HexDump(packet.Buffer.ToArray().Take(packet.Length).ToArray())); // packet.Position = packet.Length; break; } }
public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer?target, IMessageReader reader, bool initialState) { if (!await ValidateHost(CheatContext.Deserialize, sender)) { return; } var votes = _votes; var unknown = reader.ReadByte(); if (unknown != 0) { for (var i = 0; i < unknown; i++) { var v4 = reader.ReadInt32(); if (v4 == 0) { break; } if (!votes.TryGetValue(v4, out var v12)) { v12 = new int[3]; votes[v4] = v12; } for (var j = 0; j < 3; j++) { v12[j] = reader.ReadPackedInt32(); } } } }
public static void Deserialize(IMessageReader reader, out uint netId, out string id, out string version, out PluginSide side) { netId = reader.ReadPackedUInt32(); id = reader.ReadString(); version = reader.ReadString(); side = (PluginSide)reader.ReadByte(); }
public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer?target, IMessageReader reader, bool initialState) { if (!await ValidateHost(CheatContext.Deserialize, sender)) { return; } if (initialState) { var num = reader.ReadPackedInt32(); for (var i = 0; i < num; i++) { var playerId = reader.ReadByte(); var playerInfo = new InnerPlayerInfo(playerId); playerInfo.Deserialize(reader); if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo)) { throw new ImpostorException("Failed to add player to InnerGameData."); } } } else { throw new NotImplementedException("This shouldn't happen, according to Among Us disassembly."); } }
/// <summary> /// Reads the equipment data from a message reader /// </summary> /// <param name="reader"></param> protected override void readData(IMessageReader reader) { int numArmorSlots = reader.ReadInt(); for (int i = 0; i < numArmorSlots; i++) { ArmorType type = (ArmorType)reader.ReadByte(); string frameId = reader.ReadString(); Frame frame = Frame.FindFrameById(frameId); if (frame != null) { StartCoroutine(equipAmorDeferred(frame)); } } int numCombatItemSlots = reader.ReadInt(); for (int i = 0; i < numCombatItemSlots; i++) { int index = reader.ReadInt(); Frame frame = Frame.FindFrameById(reader.ReadString()); if (frame != null) { StartCoroutine(equipCombatItemDeferred(index, frame)); } } }
public static void Deserialize(IMessageReader reader, out int announcementVersion, out int id, out Language language) { reader.ReadByte(); // SendOption header, probably added by accident announcementVersion = reader.ReadPackedInt32(); id = reader.ReadPackedInt32(); language = (Language)reader.ReadPackedInt32(); }
/// <summary> /// Deserialize a packet. /// </summary> /// <param name="reader"><see cref="IMessageReader" /> with <see cref="IMessageReader.Tag" /> 0.</param> /// <param name="chatType">The chat type selected in the client of the player.</param> /// <returns>Deserialized <see cref="GameOptionsData" />.</returns> public static GameOptionsData Deserialize(IMessageReader reader, out ChatType chatType) { var gameOptionsData = GameOptionsData.DeserializeCreate(reader); chatType = (ChatType)reader.ReadByte(); return(gameOptionsData); }
public void Deserialize(IMessageReader reader, bool initialState) { byte num = reader.ReadByte(); for (int i = 0; i < num; i++) { SystemTypes systemType = (SystemTypes)reader.ReadByte(); float value = reader.ReadSingle(); _timers[systemType] = value; } for (int j = 0; j < _doors.Count; j++) { _doors[j] = reader.ReadBoolean(); } }
/// <summary> /// Deserialize a packet. /// </summary> /// <param name="reader"><see cref="IMessageReader" /> with <see cref="IMessageReader.Tag" /> 0.</param> /// <param name="chatMode">The chat type selected in the client of the player.</param> /// <returns>Deserialized <see cref="GameOptionsData" />.</returns> public static GameOptionsData Deserialize(IMessageReader reader, out QuickChatModes chatMode) { var gameOptionsData = GameOptionsData.DeserializeCreate(reader); chatMode = (QuickChatModes)reader.ReadByte(); return(gameOptionsData); }
public void Deserialize(IMessageReader reader) { var num = reader.ReadByte(); VotedFor = (sbyte)((num & VoteMask) - 1); IsDead = (num & DeadBit) > 0; DidVote = (num & VotedBit) > 0; DidReport = (num & ReportedBit) > 0; }
public void Deserialize(IMessageReader reader) { PlayerName = reader.ReadString(); ColorId = reader.ReadByte(); HatId = reader.ReadPackedUInt32(); PetId = reader.ReadPackedUInt32(); SkinId = reader.ReadPackedUInt32(); var flag = reader.ReadByte(); Disconnected = (flag & 1) > 0; IsImpostor = (flag & 2) > 0; IsDead = (flag & 4) > 0; var taskCount = reader.ReadByte(); for (var i = 0; i < taskCount; i++) { Tasks[i] ??= new InnerGameData.TaskInfo(); Tasks[i].Deserialize(reader); } }
public void Deserialize(IMessageReader reader, bool initialState) { UsersList.Clear(); var num = reader.ReadPackedInt32(); for (var i = 0; i < num; i++) { UsersList.Add(reader.ReadByte()); } }
public void Deserialize(IMessageReader reader, bool initialState) { Countdown = reader.ReadSingle(); Timer = reader.ReadSingle(); ActiveConsoles.Clear(); // TODO: Thread safety CompletedConsoles.Clear(); // TODO: Thread safety uint activeCount = reader.ReadPackedUInt32(); for (int i = 0; i < activeCount; i++) { ActiveConsoles.Add(new Tuple <byte, byte>(reader.ReadByte(), reader.ReadByte())); } uint completedCount = reader.ReadPackedUInt32(); for (int i = 0; i < completedCount; i++) { CompletedConsoles.Add(reader.ReadByte()); } }
public PlayerInfo(IMessageReader reader) { Name = reader.ReadString(); Color = reader.ReadByte(); Hat = reader.ReadPackedUInt32(); Pet = reader.ReadPackedUInt32(); Skin = reader.ReadPackedUInt32(); var flags = reader.ReadByte(); Disconnected = (flags & 1) != 0; IsImpostor = (flags & 2) != 0; IsDead = (flags & 4) != 0; var capacity = reader.ReadByte(); for (var i = 0; i < capacity; i++) { var id = reader.ReadPackedUInt32(); //var typeId = reader.ReadByte(); // idk if this is written var complete = reader.ReadBoolean(); } }
public override void Deserialize(IClientPlayer sender, IClientPlayer?target, IMessageReader reader, bool initialState) { if (!sender.IsHost) { // throw new ImpostorCheatException($"Client attempted to send data for {nameof(InnerPlayerControl)} as non-host"); } if (initialState) { IsNew = reader.ReadBoolean(); } PlayerId = reader.ReadByte(); }
public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer?target, IMessageReader reader, bool initialState) { if (!await ValidateHost(CheatContext.Deserialize, sender)) { return; } if (initialState) { IsNew = reader.ReadBoolean(); } PlayerId = reader.ReadByte(); }
public static void Deserialize(IMessageReader reader, out ISet <Mod> mods) { var length = reader.ReadPackedInt32(); mods = new HashSet <Mod>(length); for (var i = 0; i < length; i++) { var id = reader.ReadString(); var version = reader.ReadString(); var pluginSide = (PluginSide)reader.ReadByte(); mods.Add(new Mod(id, version, pluginSide)); } }
public static bool Deserialize(IMessageReader reader, [NotNullWhen(true)] out ReactorProtocolVersion?version, [NotNullWhen(true)] out int?modCount) { if (reader.Length > reader.Position) { version = (ReactorProtocolVersion)reader.ReadByte(); modCount = reader.ReadPackedInt32(); return(true); } version = null; modCount = null; return(false); }
public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer?target, IMessageReader reader, bool initialState) { if (!await ValidateHost(CheatContext.Deserialize, sender)) { return; } if (initialState) { var num = reader.ReadPackedInt32(); for (var i = 0; i < num; i++) { var playerId = reader.ReadByte(); var playerInfo = new InnerPlayerInfo(playerId); playerInfo.Deserialize(reader); if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo)) { throw new ImpostorException("Failed to add player to InnerGameData."); } } } else { while (reader.Position < reader.Length) { var inner = reader.ReadMessage(); var playerInfo = this.GetPlayerById(inner.Tag); if (playerInfo != null) { playerInfo.Deserialize(inner); } else { playerInfo = new InnerPlayerInfo(inner.Tag); playerInfo.Deserialize(inner); if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo)) { throw new ImpostorException("Failed to add player to InnerGameData."); } } } } }
public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer?target, IMessageReader reader, bool initialState) { if (!sender.IsHost) { if (await sender.Client.ReportCheatAsync(CheatContext.Deserialize, $"Client attempted to send data for {nameof(InnerPlayerControl)} as non-host")) { return; } } if (initialState) { IsNew = reader.ReadBoolean(); } PlayerId = reader.ReadByte(); }
public override async ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer?target, IMessageReader reader, bool initialState) { if (!sender.IsHost) { if (await sender.Client.ReportCheatAsync(CheatContext.Deserialize, $"Client attempted to send data for {nameof(InnerShipStatus)} as non-host")) { return; } } var votes = _votes; var unknown = reader.ReadByte(); if (unknown != 0) { for (var i = 0; i < unknown; i++) { var v4 = reader.ReadInt32(); if (v4 == 0) { break; } if (!votes.TryGetValue(v4, out var v12)) { v12 = new int[3]; votes[v4] = v12; } for (var j = 0; j < 3; j++) { v12[j] = reader.ReadPackedInt32(); } } } }
public static void Deserialize(IMessageReader reader, out bool on, out byte scannerCount) { on = reader.ReadBoolean(); scannerCount = reader.ReadByte(); }
public void Deserialize(IMessageReader reader, bool initialState, IEventManager eventManager) { InUse = reader.ReadByte(); }
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 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 static void Deserialize(IMessageReader reader, out int clientVersion, out Platforms platform, out string clientId) { clientVersion = reader.ReadInt32(); platform = (Platforms)reader.ReadByte(); clientId = reader.ReadString(); }
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; } } }