public CommandAndPlayerId(Commands.CommandEnum command, string playerId)
 {
     this.command  = command;
     this.playerId = playerId;
 }
    private void ExecuteCommandFromBytes(string commandSourcePlayerId, Commands.CommandEnum command, byte[] data)
    {
        switch (command)
        {
        case Commands.CommandEnum.EntriedId: {
            var entriedData = Commands.FromData <Commands.EntriedId>(data);

            // 新規参加ユーザーを生成
            {
                var entriedPlayerId = entriedData.playerId;
                var pos             = entriedData.pos;
                var dir             = entriedData.dir;

                // Debug.LogError("EntriedIdをサーバから受け取った entriedPlayerId:" + entriedPlayerId);

                var playerContext = NewPlayerContext(entriedPlayerId, pos, dir);
                players.Add(playerContext);

                /*
                 *      カメラセッティング
                 */
                if (entriedPlayerId == this.playerId)
                {
                    var cinemachineCamera    = GameObject.Find("CinemachineVirtualCamera") as GameObject;
                    var cinemachineComponent = cinemachineCamera.GetComponent <CinemachineVirtualCamera>() as CinemachineVirtualCamera;
                    cinemachineComponent.CameraTransposerTarget = playerModels[entriedPlayerId].transform;
                }
            }

            if (commandSourcePlayerId == this.playerId)
            {
                Debug.LogError("自分がエントリーしたのでSpawnRequestを送る");
                StackPublish(new Commands.SpawnRequest(playerId));
            }
            return;
        }

        case Commands.CommandEnum.Spawn: {
            var spawnData     = Commands.FromData <Commands.Spawn>(data);
            var spawnPlayerId = spawnData.playerId;

            // Debug.LogError("誰かspawnしたんで、Autoの状態を変更する。自分以外のspawnって意味あるのかな、、あー、入室とかか。spawnPlayerId:" + spawnPlayerId);
            var targetPlayerContext = ChoosePlayerContext(spawnPlayerId);
            targetPlayerContext.auto = targetPlayerContext.auto.ChangeTo(new Default <PlayerContext, List <PlayerContext> >(clientFrame, targetPlayerContext));
            return;
        }

        case Commands.CommandEnum.WorldData: {
            var worldData = Commands.FromData <Commands.WorldData>(data);

            var currentPlayersIds = players.Select(p => p.playerId).ToArray();
            foreach (var playerData in worldData.players)
            {
                if (playerData.playerId == this.playerId)
                {
                    continue;
                }
                if (currentPlayersIds.Contains(playerData.playerId))
                {
                    continue;
                }

                var playerId  = playerData.playerId;
                var playerPos = playerData.pos;
                var playerDir = playerData.dir;

                var playerContext = NewPlayerContext(playerId, playerPos, playerDir);

                Debug.LogError("とりあえず適当に、default状態にしておく。特に問題ないはず。");
                playerContext.auto = new Default <PlayerContext, List <PlayerContext> >(clientFrame, playerContext);

                players.Add(playerContext);
            }
            return;
        }

        case Commands.CommandEnum.Walk: {
            var walkData        = Commands.FromData <Commands.Walk>(data);
            var walkingPlayerId = walkData.playerId;
            var walkingDir      = walkData.direction;
            var walkBasePos     = walkData.pos;

            if (walkingPlayerId == this.playerId)
            {
                // ignore.
                // Debug.LogError("自分が歩いてる");
                return;
            }

            var playerContext = ChoosePlayerContext(walkingPlayerId);
            playerContext.x       = walkBasePos.x;
            playerContext.z       = walkBasePos.z;
            playerContext.height  = walkBasePos.height;
            playerContext.forward = walkingDir;

            playerContext.auto = new Walk <PlayerContext, List <PlayerContext> >(clientFrame, playerContext);
            return;
        }

        case Commands.CommandEnum.ForceMove: {
            var forceMoveData   = Commands.FromData <Commands.ForceMove>(data);
            var movingPlayerId  = forceMoveData.playerId;
            var movingPlayerDir = forceMoveData.direction;
            var movingPlayerPos = forceMoveData.pos;

            var playerContext = ChoosePlayerContext(movingPlayerId);
            playerContext.x       = movingPlayerPos.x;
            playerContext.z       = movingPlayerPos.z;
            playerContext.height  = 0;
            playerContext.forward = movingPlayerDir;
            return;
        }

        case Commands.CommandEnum.Messaging: {
            var messageData         = Commands.FromData <Commands.Messaging>(data);
            var messageTargetPlayer = messageData.targetPlayerId;
            var messageSender       = messageData.playerId;

            /*
             *      自分宛だったら、表示する。
             *      GUIつくるところが重いな、、最初から生成しとくか、、
             */
            if (messageTargetPlayer == this.playerId)
            {
                var message = messageData.message;
                if (windowInstance == null)
                {
                    StartTalking();
                }
                textView.text = textView.text + "\n\n" + message;
            }

            /*
             *      強制的に、会話をしてきた人との会話になってる。
             *      現在会話している人がすでに存在する場合、そのへんを加味して吹き出し化とかするかな。
             */
            var myContext = ChoosePlayerContext(this.playerId);
            if (myContext.auto.Contains(AutoConditions.Talkable.Receivable))
            {
                Debug.LogError("receiver(me)'s talkingPlayerIdd:" + myContext.talkingPlayerId);
                // マッチしなかったら、だれか別の人と喋ってる。

                myContext.talkingPlayerId = messageSender;
                myContext.auto            = new Talk <PlayerContext, List <PlayerContext> >(clientFrame, myContext);
            }
            return;
        }

        /*
         *      unhandled
         */
        default: {
            Debug.LogError("client unhandled command:" + command);
            return;
        }
        }
    }