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.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);
        }