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);
        }
示例#2
0
        private async ValueTask <bool> HandleCastVote(ClientPlayer sender, ClientPlayer?target, byte playerId, sbyte suspectPlayerId)
        {
            if (sender.IsHost)
            {
                if (target != null)
                {
                    if (await sender.Client.ReportCheatAsync(RpcCalls.CastVote, $"Client sent {nameof(RpcCalls.CastVote)} to a specific player instead of broadcast"))
                    {
                        return(false);
                    }
                }
            }
            else
            {
                if (target == null || !target.IsHost)
                {
                    if (await sender.Client.ReportCheatAsync(RpcCalls.CastVote, $"Client sent {nameof(RpcCalls.CastVote)} to wrong destinition, must be host"))
                    {
                        return(false);
                    }
                }
            }

            if (playerId != sender.Character.PlayerId)
            {
                if (await sender.Client.ReportCheatAsync(RpcCalls.CastVote, $"Client sent {nameof(RpcCalls.CastVote)} to an unowned {nameof(InnerPlayerControl)}"))
                {
                    return(false);
                }
            }

            return(true);
        }
示例#3
0
        private async ValueTask MigrateHost()
        {
            // Pick the first player as new host.
            ClientPlayer?host = _players
                                .Select(p => p.Value)
                                .FirstOrDefault();

            if (host == null)
            {
                return;
            }

            foreach (var player in _players.Values)
            {
                player.Character?.RequestedPlayerName.Clear();
                player.Character?.RequestedColorId.Clear();
            }

            HostId = host.Client.Id;
            _logger.LogInformation("{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 <bool> HandleCastVote(ClientPlayer sender, ClientPlayer?target, byte playerId, sbyte suspectPlayerId)
        {
            if (sender.IsHost)
            {
                if (!await ValidateBroadcast(RpcCalls.CastVote, sender, target))
                {
                    return(false);
                }
            }
            else
            {
                if (!await ValidateCmd(RpcCalls.CastVote, sender, target))
                {
                    return(false);
                }
            }

            if (playerId != sender.Character !.PlayerId)
            {
                if (await sender.Client.ReportCheatAsync(RpcCalls.CastVote, $"Client sent {nameof(RpcCalls.CastVote)} to an unowned {nameof(InnerPlayerControl)}"))
                {
                    return(false);
                }
            }

            return(true);
        }
示例#5
0
        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)
        {
            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 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);
        }
示例#8
0
        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);
        }
        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);
        }
示例#10
0
        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);
        }
示例#11
0
        public override async ValueTask <bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader)
        {
            if (call == RpcCalls.SnapTo)
            {
                if (!await ValidateOwnership(call, sender))
                {
                    return(false);
                }

                Rpc21SnapTo.Deserialize(reader, out var position, out var minSid);

                if (Game.GameNet.ShipStatus is InnerAirshipStatus airshipStatus)
                {
                    // As part of airship spawning, clients are sending snap to -25 40 for no reason(?), cancelling it works just fine
                    if (Approximately(position, airshipStatus.PreSpawnLocation))
                    {
                        return(false);
                    }

                    if (_spawnSnapAllowed && airshipStatus.SpawnLocations.Any(location => Approximately(position, location)))
                    {
                        _spawnSnapAllowed = false;
                        return(true);
                    }
                }

                if (!await ValidateImpostor(call, sender, _playerControl.PlayerInfo))
                {
                    return(false);
                }

                var vents = Game.GameNet.ShipStatus !.Data.Vents.Values;

                var vent = vents.SingleOrDefault(x => Approximately(x.Position, position + ColliderOffset));

                if (vent == null)
                {
                    if (await sender.Client.ReportCheatAsync(call, "Failed vent position check"))
                    {
                        return(false);
                    }
                }
                else
                {
                    await _eventManager.CallAsync(new PlayerVentEvent(Game, sender, _playerControl, vent));
                }

                await SnapToAsync(sender, position, minSid);

                return(true);
            }

            return(await UnregisteredCall(call, sender));
        }
示例#12
0
        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);
        }
示例#13
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;
        }
示例#14
0
        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 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);
        }
示例#16
0
        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));
        }
示例#17
0
        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));
        }
示例#18
0
        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);
                }

                if (player != null)
                {
                    await _eventManager.CallAsync(new PlayerRepairSystemEvent(Game, sender, player, systemType, amount));
                }

                break;
            }

            default:
                return(await UnregisteredCall(call, sender));
            }

            return(true);
        }
示例#19
0
        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);
        }
示例#20
0
        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 byte playerId, out ReadOnlyMemory <byte> taskTypeIds);
                SetTasks(playerId, taskTypeIds);
                break;
            }

            default:
                return(await base.HandleRpcAsync(sender, target, call, reader));
            }

            return(true);
        }
示例#21
0
        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 SystemTypes systemType);
                break;
            }

            case RpcCalls.RepairSystem:
            {
                Rpc28RepairSystem.Deserialize(reader, Game, out SystemTypes systemType, out IInnerPlayerControl? player, out byte amount);

                if (systemType == SystemTypes.Sabotage && !await ValidateImpostor(call, sender, sender.Character !.PlayerInfo))
                {
                    return(false);
                }

                break;
            }

            default:
                return(await base.HandleRpcAsync(sender, target, call, reader));
            }

            return(true);
        }
示例#22
0
        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);
        }
示例#23
0
        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);
        }
示例#24
0
        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);
        }
示例#25
0
        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;
            }
            }
        }
示例#26
0
        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);
示例#27
0
        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;
            }
            }
        }
示例#28
0
 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)
 {
     if (call != RpcCalls.AddVote)
     {
         _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerVoteBanSystem), call);
         return(default);
示例#30
0
 public abstract ValueTask <bool> HandleRpc(ClientPlayer sender, ClientPlayer?target, RpcCalls call, IMessageReader reader);