Exemplo n.º 1
0
    public void EnqueueOnConnect(string connectionId, string token)
    {
        XrossPeer.TimeAssert(Develop.TIME_ASSERT, "connectionIdとplayerDataが揃った状態でくる。ので、ここで照会を行ってしまおう。token:" + token);

        var playerId = token;

        XrossPeer.Log("playerId:" + playerId + " connectionId:" + connectionId);

        // set connectionId to reserved playerId.
        var succeeded = gameLayer.SetConnectionIdOfPlayerId(playerId, connectionId);

        if (!succeeded)
        {
            return;
        }

        if (playerId == "_empty_")
        {
            XrossPeer.Log("接続時にプレイヤーIDが空のユーザーが接続してきた。追い返すようにしてある。");
            return;
        }

        var data = new Commands.OnConnected(playerId).ToData();

        if (true)
        {
            gameLayer.EnqueOnReceive(connectionId, data);
        }
    }
Exemplo n.º 2
0
    /*
     *      C#のtickで動くThread。
     *      UnityEditorのUpdateと違い、UnityPlayerと同期しないため、
     *      UnityPlayer側が重くなっても構わず動く。
     *
     *      で、UnityPlayer側が遅れてかつUnityServer側が動くと、unsyncエラーが多発する。
     *      このUnity内でのUnityPlayerと合わせてUnityEditor上で使うには都合が悪い。
     *
     *      別のUnityPlayerに対してのServerインスタンスとしては行けると思う。
     *      あとはCoreCLRにするとか。
     */
    public Updater(string loopId, Func <bool> OnUpdate)
    {
        var framePerSecond     = RolePlayingChatDefinitions.FRAMERATE;
        var mainThreadInterval = 1000f / framePerSecond;

        continuation = true;

        Action loopMethod = () => {
            try {
                double nextFrame = (double)System.Environment.TickCount;

                var before    = 0.0;
                var tickCount = (double)System.Environment.TickCount;

                while (true)
                {
                    tickCount = System.Environment.TickCount * 1.0;
                    if (nextFrame - tickCount > 1)
                    {
                        // XrossPeer.Log("wait:" + (int)(nextFrame - tickCount));
                        Thread.Sleep((int)(nextFrame - tickCount) / 2);

                        /*
                         *      waitを半分くらいにすると特定フレームで安定した。
                         */
                        continue;
                    }

                    if (tickCount >= nextFrame + mainThreadInterval)
                    {
                        nextFrame += mainThreadInterval;
                        continue;
                    }

                    if (!continuation)
                    {
                        break;
                    }

                    // run action for update.
                    continuation = OnUpdate();
                    if (!continuation)
                    {
                        break;
                    }

                    nextFrame += mainThreadInterval;
                    before     = tickCount;
                }
                XrossPeer.Log("loopId:" + loopId + " is finished.");
            } catch (Exception e) {
                XrossPeer.LogError("loopId:" + loopId + " error:" + e);
            }
        };

        var thread = new Thread(new ThreadStart(loopMethod));

        thread.Start();
    }
Exemplo n.º 3
0
 public void EnqueueOnMessage(string connectionId, byte[] data)
 {
     XrossPeer.TimeAssert(Develop.TIME_ASSERT, "とりあえずすべてのconnectionIdに対して、このreserveレイヤに登録があった、みたいなみなしをしてうけいれる。実際にはReservationLayerが複数のGameLayerをもっていて、特定の情報を元にGameContextLayerへとメッセージをふり分ける。");
     if (true)
     {
         gameLayer.EnqueOnReceive(connectionId, data);
     }
 }
Exemplo n.º 4
0
    /**
     *      main loop of GameContext.
     */
    public bool UpdateGameLayer()
    {
        switch (state)
        {
        case BattleState.STATE_READY: {
            XrossPeer.TimeAssert(Develop.TIME_ASSERT, "絶賛準備中のステート、2フレームくらい回してみよう。clientのリトライを試す、、のはあとで。");
            if (true)
            {
                XrossPeer.TimeAssert(Develop.TIME_ASSERT, "Server起動中、準備中など。いろんなConnectionとかロードが完了したらプレイヤーがいない世界へ遷移");
                state = BattleState.STATE_NOPLAYERS;
            }
            break;
        }


        /*
         *      ゲームが稼働しているステート
         */
        case BattleState.STATE_NOPLAYERS:
        case BattleState.STATE_PLAYERS_EXISTS: {
            // worldにいるユーザー = dummyの挙動を開始する。

            world.UpdateWorld(gameFrame, StackPublish);

            UpdateXrossPeer(gameFrame);



            gameFrame++;
            break;
        }

        case BattleState.STATE_ENDING: {
            XrossPeer.TimeAssert(Develop.TIME_ASSERT, "とりあえずリセットをかける。クライアント側にはサーバリセット後の通信が届くので、そこから勝手に復帰させるといい感じになる。");

            // 時間稼ぎとか。UniRxで10秒とかを計ると良いんだと思う。 STATE_ENDED
            state = BattleState.STATE_ENDED;
            break;
        }

        case BattleState.STATE_ENDED: {
            // do nothing yet.
            return(false);                   //SAYONARA!!!
        }

        default: {
            XrossPeer.Log("message received at missing state:" + state);
            break;
        }
        }

        /*
         *      send stacked data to players.
         */
        PublishStackedData();

        return(true);
    }
Exemplo n.º 5
0
    public void Setup(Action <string, byte[]> Send)
    {
        XrossPeer.Log("server ready:" + serverContextId);
        XrossPeer.TimeAssert(Develop.TIME_ASSERT, "リセットを兼ねることはしない方が良いんだろうか。");

        // 仮の、ゲームに参加するconnectionIdを保持しておくレイヤ
        reservationLayer = new ReservationLayer(Send);
        this.Send        = Send;
    }
Exemplo n.º 6
0
    public ServerInitializer()
    {
        XrossPeer.SetupLog(Path.Combine(Directory.GetParent(Application.dataPath).ToString(), "server.log"));

        // Setup();
        DisquuunTests.Start();

        EditorApplication.playmodeStateChanged += DetectPlayStart;
        EditorApplication.update += DetectCompileStart;
    }
Exemplo n.º 7
0
    /**
     *      文字列のパターンによって、AIにお願いをすることができる。
     */
    private void GenerateAnswer(string dummyPlayerId, string senderPlayerId, string message, string senderConnectionId)
    {
        XrossPeer.Log("この時点で、このAIが忙しくなければ、っていう判断をしてもいいかもしれない。localとremoteのAutoのあり方をどうするかな。");
        if (!message.EndsWith("?"))
        {
            StackPublish(new Commands.Messaging(dummyPlayerId, senderPlayerId, "村人:" + dummyPlayerId + ":" + message + " って何?"), new string[] { senderConnectionId });
            return;
        }

        // ?で終わってる場合、Queryとみて、動作開始。

        // 今回は問答なしで、追いかけて行って云々っていう感じにする。まずカメラ引いてしまおう。

        var ourIds = new List <string> {
            dummyPlayerId, senderPlayerId
        };
        var anotherTargetId = world.ExceptPlayerIds(ourIds)[0];

        StackPublish(new Commands.Messaging(dummyPlayerId, senderPlayerId, "村人_" + dummyPlayerId + ":" + "お、わかった〜、" + anotherTargetId + "に、\"" + message.Substring(0, message.Length - 1) + "\" って伝えとく。"), new string[] { senderConnectionId });

        // メッセージを保持、実際にターゲットに向かって歩いてく。近づいて行って、最終的にメッセージを伝える。
        var reservedMessage = "あのね〜 " + senderPlayerId + "からの伝言で、" + "\"" + message + "\"" + "ってさ。";

        XrossPeer.Log("reservedMessage:" + reservedMessage);

        // サーバ側でAutoをどうやって組もうかな。

        /*
         *      ・サーバ側でのAutoを持つ
         *      ・Autoを初期化する
         *      ・Autoを適当にスタックする(デフォルト状態もAutoとして持った方がいいのかな。)
         *      ・Autoからの発信を行う
         *      とかか。全部協調動作する必要ないんで、サーバ側で適当なフレームで動かしつつ、時間がきたら実行、っていう感じかな。
         *
         *      Queryの部分をAutoで積む?
         *      ・何時頃 とか
         *      ・何回 とか
         *      ・どのくらいしつこく とか
         */
        world.StackAutoName(dummyPlayerId, "DoStalk", new List <string> {
            anotherTargetId, reservedMessage
        });                                                                                                       // 付け回して、相手にメッセージ投げて、それが済んだら
        world.StackAutoName(dummyPlayerId, "DoNotify", new List <string> {
            senderPlayerId, anotherTargetId, reservedMessage
        });                                                                                                                        // 終わったよーって通知を出す
        world.StackAutoName(dummyPlayerId, "DoStalk", new List <string> {
            senderPlayerId, reservedMessage
        });                                                                                                      // メッセージを渡したやつに会いに行く

        var playerContext = world.GetPlayerInfo(dummyPlayerId);
        var newAuto       = new DoOrder <PlayerContext, List <PlayerContext> >(gameFrame, playerContext);

        world.SetAuto(dummyPlayerId, newAuto, gameFrame);
    }
Exemplo n.º 8
0
    public void StackAutoName(string playerId, string autoName, List <string> parameters)
    {
        var playerContext = GetPlayerInfo(playerId);

        if (playerContext == null)
        {
            XrossPeer.Log("対象のplayer:" + playerId + " nullだったのでstackに失敗");
            return;
        }

        playerContext.stackedDummyAutos.Add(new AutoInfo(autoName, parameters));
    }
Exemplo n.º 9
0
    public void SetAuto(string playerId, Auto <PlayerContext, List <PlayerContext> > newAuto, int frame)
    {
        var playerContext = GetPlayerInfo(playerId);

        if (playerContext == null)
        {
            XrossPeer.Log("対象のplayer:" + playerId + " nullだったのでstackに失敗");
            return;
        }

        playerContext.auto = newAuto;
    }
Exemplo n.º 10
0
    public bool DiscardConnectionIdOfPlayerId(string playerId)
    {
        var playerSlotIndex = Array.FindIndex(connections, connection => connection.playerId == playerId);

        if (-1 < playerSlotIndex)
        {
            connections[playerSlotIndex].connectionId = string.Empty;
            return(true);
        }

        XrossPeer.Log("failed to discard connectionId to playerId:" + playerId);
        return(false);
    }
Exemplo n.º 11
0
    public bool SetConnectionIdOfPlayerId(string playerId, string connectionId)
    {
        var playerSlotIndex = Array.FindIndex(connections, connection => connection.playerId == playerId);

        if (-1 < playerSlotIndex)
        {
            connections[playerSlotIndex].connectionId = connectionId;
            return(true);
        }

        XrossPeer.Log("failed to set connectionId to playerId:" + playerId);
        return(false);
    }
Exemplo n.º 12
0
    /*
     *      enque data on receive.
     */
    public void EnqueOnReceive(string connectionId, byte[] data)
    {
        XrossPeer.TimeAssert(Develop.TIME_ASSERT, "接続者が他人のplayerIdでデータを送ってきた場合、データを展開した瞬間にバレさせることができる。一度発見したら強制切断しよう。");

        var playerId = PlayerIdFromConnectionId(connectionId);

        if (string.IsNullOrEmpty(playerId))
        {
            XrossPeer.Log("不明なconnectionIdからのデータ:" + connectionId + " 内容は、:" + Encoding.UTF8.GetString(data));
            return;
        }

        lock (gameDataQueue) gameDataQueue.Enqueue(new DataPack(playerId, data));
    }
Exemplo n.º 13
0
    public void Setup()
    {
        XrossPeer.Log("\n\n");
        XrossPeer.Log("----------");
        XrossPeer.Log("initializing server context....");
        XrossPeer.Log("----------");

        var settings = (StandardAssetsConnectorSettings)ScriptableObject.CreateInstance("StandardAssetsConnectorSettings");

        sContext = new ServerContext(settings.ClientToContextKey());

        transformLayer = new ConnectionServerTransformLayer(settings.ClientToContextKey());
        transformLayer.SetContext(sContext);
    }
Exemplo n.º 14
0
 public void Teardown()
 {
     XrossPeer.Log("\n\n");
     XrossPeer.Log("----------");
     XrossPeer.Log("teardown server context....");
     XrossPeer.Log("----------");
     if (sContext != null)
     {
         sContext.Teardown();
     }
     if (transformLayer != null)
     {
         transformLayer.Disconnect();
     }
 }
Exemplo n.º 15
0
    public ReservationLayer(Action <string, byte[]> publish)
    {
        XrossPeer.TimeAssert(Develop.TIME_ASSERT, "とりあえず通過できるtokenとして特定のplayerIdを直書きしてある。");

        var reservedPlayerIds = new List <string> {
            "_empty_",
        };

        /*
         *      acceptable id is 100 ~ 199
         */
        for (var i = 100; i < 200; i++)
        {
            reservedPlayerIds.Add(i.ToString());
        }

        reservationLayerId = Guid.NewGuid().ToString();
        gameLayer          = new GameContextLayer(reservedPlayerIds, publish);
    }
Exemplo n.º 16
0
    public void OnConnected(string connectionId, byte[] data)
    {
        XrossPeer.Log("OnConnected!");

        /*
         *      接続時にidentityを確立する手段が2つ考えられて、
         *      1.接続時にconnectionServer側で予約と付き合わせてなんとかする
         *      2.このレイヤーで予約と付き合わせてなんとかする
         *      責務分解的には、接続してきたらすぐキャッシュと照合、っていうので良い気はするんだけど。
         *      どっちにしてもconnectedで情報が必要なので、reservationレイヤーでそれを受け止めるのは悪くない。
         *
         *      ServerContextはゲームに集中させたい。
         *      ConnectionServerはコネクションに集中させたい。
         *      うーーん、、別のContextがあってそっちにつなぎにいけばいいのか。domain的にはConnection側だな、、
         */
        var playerIdString = Encoding.UTF8.GetString(data);

        if (reservationLayer != null)
        {
            reservationLayer.EnqueueOnConnect(connectionId, playerIdString);
        }
    }
Exemplo n.º 17
0
    public void EnqueueOnDisconnect(string connectionId, string token, string reason)
    {
        XrossPeer.TimeAssert(Develop.TIME_ASSERT, "tokenそのまま使ってるんで、このままの構造だと、他人が偽って他プレイヤーの通信切断できちゃうな。プレイヤーしかしらないパラメータを使ってplayerIdを読みだす仕組みをつくらんとな。 具体的にはtokenが");

        var playerId = token;
        var data     = new Commands.OnDisconnected(playerId, reason).ToData();

        XrossPeer.TimeAssert(Develop.TIME_ASSERT, "disconnect. とりあえずすべてのconnectionIdに対して、このreserveレイヤに登録があった、みたいなみなしをしてうけいれる。");
        if (true)
        {
            // remove connectionId from reserved playerId.
            var succeeded = gameLayer.DiscardConnectionIdOfPlayerId(playerId);
            if (!succeeded)
            {
                XrossPeer.Log("playerId:" + playerId + " のconnectionの廃棄に失敗した。存在しないプレイヤーからの切断っぽい。");
            }

            /*
             *      すでに切断されているので、このプレイヤーへの通信はこの時点で不可能。
             */
            gameLayer.EnqueOnDisconnect(playerId, data);
        }
    }
Exemplo n.º 18
0
    public void UpdateWorld(int frame, Action <Commands.BaseData, string[]> pub)
    {
        foreach (var player in playerContextsInServer)
        {
            if (player.auto == null)
            {
                continue;
            }

            if (!player.isDummy)
            {
                if (player.auto.ShouldFalldown(frame))
                {
                    continue;
                }
            }
            else
            {
                // dummy.
                if (player.auto.ShouldFalldown(frame))
                {
                    if (player.stackedDummyAutos.Count == 0)
                    {
                        continue;
                    }
                    var stackedAutoInfo = player.stackedDummyAutos[0];
                    player.stackedDummyAutos.RemoveAt(0);

                    // stackedAutoName
                    XrossPeer.Log("next stackedAutoName:" + stackedAutoInfo.autoName);
                    switch (stackedAutoInfo.autoName)
                    {
                    case "DoStalk": {
                        player.dummyTargetId = stackedAutoInfo.parameters[0];
                        player.dummyMessage  = stackedAutoInfo.parameters[1];
                        player.auto          = player.auto.ChangeTo(new DoStalk <PlayerContext, List <PlayerContext> >(frame, player));
                        break;
                    }

                    default: {
                        XrossPeer.Log("未定義の状態:" + stackedAutoInfo.autoName);
                        break;
                    }
                    }
                }
            }

            player.auto.Update(frame, playerContextsInServer);

            if (player.stackedCommands.Any())
            {
                var allPlayerIds = playerContextsInServer.Where(p => !p.isDummy).Select(p => p.playerId).ToArray();

                foreach (var stackedCommand in player.stackedCommands)
                {
                    StackPublish(stackedCommand, allPlayerIds);
                }
                player.stackedCommands.Clear();
            }
        }
    }
Exemplo n.º 19
0
    public const int CONNECTION_ID_LEN = 36;    // 65D76DEE-0E68-424E-A18F-6D2CC9656FB3

    /**
     *      受け取ったjobを解釈、contextへと入力する。APIレイヤーはserverContext側にあるので、データを扱うこの辺は変更なしで行けるはず。
     */
    public void InputDatasToContext(List <byte[]> datas)
    {
        // XrossPeer.Log("datas received. datas:" + datas.Count);

        /*
         *      messageとして受け取ったjobを、list化して読み込む。
         */
        foreach (var dataArray in datas)
        {
            var len = dataArray.Length;
            if (len < 1 /*state param*/ + CONNECTION_ID_LEN /*connectionId*/)
            {
                var invalidMessage = Encoding.ASCII.GetString(dataArray);
                XrossPeer.Log("illigal format invalidMessage1:" + invalidMessage);
                continue;
            }

            var state = (char)dataArray[0];

            // dataArray[2-38] is connectionId, length = definitely CONNECTION_ID_LEN.
            var connectionId = Encoding.ASCII.GetString(dataArray, 1, CONNECTION_ID_LEN);

            switch (state)
            {
            case STATE_CONNECT: {
                XrossPeer.Log("STATE_CONNECT");
                if (1 + CONNECTION_ID_LEN < len)
                {
                    var dataLen = len - (1 + CONNECTION_ID_LEN);
                    var data    = new byte[dataLen];
                    Buffer.BlockCopy(dataArray, (1 + CONNECTION_ID_LEN), data, 0, dataLen);
                    context.OnConnected(connectionId, data);
                }
                break;
            }

            case STATE_STRING_MESSAGE: {
                // if (1 + CONNECTION_ID_LEN < len) {
                //  var data = Encoding.UTF8.GetString(dataArray, 2 + CONNECTION_ID_LEN, len - (2 + CONNECTION_ID_LEN));
                //  context.OnMessage(connectionId, data);
                // }
                break;
            }

            case STATE_BINARY_MESSAGE: {
                if (1 + CONNECTION_ID_LEN < len)
                {
                    var dataLen = len - (1 + CONNECTION_ID_LEN);
                    var data    = new byte[dataLen];
                    Buffer.BlockCopy(dataArray, (1 + CONNECTION_ID_LEN), data, 0, dataLen);
                    context.OnMessage(connectionId, data);
                }
                break;
            }

            case STATE_DISCONNECT_INTENT: {
                if (1 + CONNECTION_ID_LEN < len)
                {
                    var dataLen = len - (2 + CONNECTION_ID_LEN);
                    var data    = new byte[dataLen];
                    Buffer.BlockCopy(dataArray, (1 + CONNECTION_ID_LEN), data, 0, dataLen);
                    XrossPeer.Log("client closed");
                    context.OnDisconnected(connectionId, data, "intentional disconnect.");
                }
                break;
            }

            case STATE_DISCONNECT_ACCIDT: {
                if (1 + CONNECTION_ID_LEN < len)
                {
                    var dataLen = len - (2 + CONNECTION_ID_LEN);
                    var data    = new byte[dataLen];
                    Buffer.BlockCopy(dataArray, (1 + CONNECTION_ID_LEN), data, 0, dataLen);

                    context.OnDisconnected(connectionId, data, "accidential disconnect.");
                }
                break;
            }

            case STATE_DISCONNECT_DISQUE_ACKFAILED: {
                if (1 + CONNECTION_ID_LEN < len)
                {
                    var dataLen = len - (1 + CONNECTION_ID_LEN);
                    var data    = new byte[dataLen];
                    Buffer.BlockCopy(dataArray, (1 + CONNECTION_ID_LEN), data, 0, dataLen);

                    context.OnDisconnected(connectionId, data, "accidential disconnect.");
                }
                break;
            }

            case STATE_DISCONNECT_DISQUE_ACCIDT_SENDFAILED: {
                if (1 + CONNECTION_ID_LEN < len)
                {
                    var dataLen = len - (1 + CONNECTION_ID_LEN);
                    var data    = new byte[dataLen];
                    Buffer.BlockCopy(dataArray, (1 + CONNECTION_ID_LEN), data, 0, dataLen);

                    context.OnDisconnected(connectionId, data, "send failed to client. disconnect.");
                }
                break;
            }

            default: {
                XrossPeer.Log("undefined websocket state:" + state);
                break;
            }
            }
        }
    }
Exemplo n.º 20
0
    /**
     *      ServerContext Core.
     *      このレイヤがXrossPeerの外側一枚。
     */
    private void InputToXrossPeer(int frame, string playerId, byte[] data)
    {
        /*
         *      validate data.
         */
        var commandAndPlayerId = Commands.ReadCommandAndSourceId(data);
        var command            = commandAndPlayerId.command;
        var commandPlayerId    = commandAndPlayerId.playerId;

        if (commandPlayerId != playerId)
        {
            XrossPeer.Log("実行者と送付者のidがマッチしない、BANする");
            return;
        }

        /*
         *      extract.
         *      この部分で、
         *      ・XrossPeer内の対象のAutoが状況変化を受けいれること
         *      ・対象変化を受け入れた場合、そのコマンドを全員に配ること
         *      ・受け入れない場合ここで黙殺すること
         *      を決める。
         */

        /*
         *      サーバでしか受け取らず、サーバでないと他のユーザーに反射しないシリーズ。
         *      ユーザーの有無っていう究極的な可否を判定する根っこ。
         *
         *      だいたいConnectionServerが吐いてる
         */
        switch (command)
        {
        case Commands.CommandEnum.OnConnected: {
            var onConnected         = Commands.FromData <Commands.OnConnected>(data);
            var onConnectedPlayerId = onConnected.playerId;

            XrossPeer.Log("connected playerId:" + onConnectedPlayerId);

            /*
             *      このタイミングで、サーバへのプレイヤーのログインが完了してる。
             */
            {
                var pos = new Commands.StructVector3(0, 0, 30);
                // 適当な位置をでっち上げる
                var newPlayer = new PlayerContext(onConnectedPlayerId, pos, DirectionEnum.East);
                world.AddPlayer(newPlayer);
                StackPublish(new Commands.EntriedId(onConnectedPlayerId, pos, newPlayer.forward), AllConnectedIds());
            }


            /*
             *      ダミーを10人くらい降らせよう。
             */
            if (AllConnectedIds().Length == 1)
            {
                XrossPeer.Log("最初の接続者 onConnectedPlayerId:" + onConnectedPlayerId + " が来たので、ダミーを降らせる。ランダムシードがすげえーー怪しい時があるな。");

                var dummyCount = 2;

                var xRand = new byte[dummyCount];
                var zRand = new byte[dummyCount];

                var r1 = new System.Random();
                r1.NextBytes(xRand);

                var r2 = new System.Random();
                r2.NextBytes(zRand);


                {
                    var dummyPlayerId = Guid.NewGuid().ToString();
                    var dir           = DirectionEnum.South;
                    var pos           = new Commands.StructVector3(10, 10, 30);
                    var dummyPlayer   = new PlayerContext(dummyPlayerId, pos, dir);
                    dummyPlayer.isDummy = true;
                    world.AddPlayer(dummyPlayer);
                }

                {
                    var dummyPlayerId = Guid.NewGuid().ToString();
                    var dir           = DirectionEnum.South;
                    var pos           = new Commands.StructVector3(10, 0, 30);
                    var dummyPlayer   = new PlayerContext(dummyPlayerId, pos, dir);
                    dummyPlayer.isDummy = true;
                    world.AddPlayer(dummyPlayer);
                }
            }

            /*
             *      receive world info.
             */
            var playersInfos = world.PlayersInfos();
            StackPublish(new Commands.WorldData(onConnectedPlayerId, playersInfos), new string[] { ConnectionIdFromPlayerId(onConnectedPlayerId) });

            return;
        }

        case Commands.CommandEnum.OnDisconnected: {
            var onDisconnected       = Commands.FromData <Commands.OnDisconnected>(data);
            var disconnectedPlayerId = onDisconnected.playerId;
            var reason = onDisconnected.reason;

            var reasonCode = 0;

            XrossPeer.Log("disconnected この時点で通信対象リストからは外されている。 disconnectedPlayerId:" + disconnectedPlayerId + " reason:" + reason + " まだなんにもしてない。");
            // StackPublish(new Commands.PlayerLeft(disconnectedPlayerId, reasonCode), AllConnectedIds());
            return;
        }
        }


        switch (command)
        {
        case Commands.CommandEnum.SpawnRequest: {
            var spawnData = Commands.FromData <Commands.SpawnRequest>(data);

            var spawnPlayerId = spawnData.playerId;
            XrossPeer.Log("spawnがきた spawnPlayerId:" + spawnPlayerId);

            /*
             *      すでにSpawnしてないかとかみて、OKだったらSpawnを返す
             */
            StackPublish(new Commands.Spawn(spawnPlayerId), AllConnectedIds());
            return;
        }

        // 移動データとかを扱う。
        case Commands.CommandEnum.Walk: {
            var walkData        = Commands.FromData <Commands.Walk>(data);
            var walkingPlayerId = walkData.playerId;
            var walkingDir      = walkData.direction;
            var walkBasePos     = walkData.pos;

            StackPublish(new Commands.Walk(walkingPlayerId, walkingDir, walkBasePos), AllConnectedIds());


            if (!world.IsDummyPlayer(walkingPlayerId))
            {
                var playerInfo = world.GetPlayerInfo(walkingPlayerId);
                playerInfo.auto = new Walk <PlayerContext, List <PlayerContext> >(gameFrame, playerInfo);
            }
            return;
        }

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

            // サーバまで届いているので、そのことの反射をする。
            var senderConnectionId = ConnectionIdFromPlayerId(senderPlayerId);
            StackPublish(new Commands.Messaging(senderPlayerId, senderPlayerId, "我:" + senderPlayerId + ":" + message), new string[] { senderConnectionId });

            XrossPeer.Log("message:" + message + " from playerId:" + senderPlayerId + " to targetPlayerId:" + targetPlayerId);

            /*
             *      is bot, message turns to "order".
             */
            if (world.IsDummyPlayer(targetPlayerId))
            {
                GenerateAnswer(targetPlayerId, senderPlayerId, message, senderConnectionId);
                return;
            }

            var connectionId = ConnectionIdFromPlayerId(targetPlayerId);
            StackPublish(new Commands.Messaging(senderPlayerId, targetPlayerId, "相手:" + senderPlayerId + ":" + message), new string[] { connectionId });
            return;
        }

        default: {
            XrossPeer.Log("gameContextLayer unhandled command:" + command);
            break;
        }
        }
    }
Exemplo n.º 21
0
 /**
  *      ServerContextの終了手続き
  */
 public void Teardown()
 {
     XrossPeer.TimeAssert(Develop.TIME_ASSERT, "ContextのTeardown処理、なんか必要かな、、");
 }
Exemplo n.º 22
0
    private const int CONNECTION_ID_LEN = 36;    // 65D76DEE-0E68-424E-A18F-6D2CC9656FB3

    private void ParseData(byte[] dataArray)
    {
        var len = dataArray.Length;

        if (len < 1 /*s or b or c*/ + 1 /*state param*/ + CONNECTION_ID_LEN /*connectionId*/)
        {
            var invalidMessage = Encoding.ASCII.GetString(dataArray);
            XrossPeer.Log("illigal format invalidMessage1:" + invalidMessage);
            return;
        }

        var header = (char)dataArray[0];

        switch (header)
        {
        case HEADER_CONTROL:
        case HEADER_STRING:
        case HEADER_BINARY: {
            break;
        }

        default: {
            var invalidMessage = Encoding.ASCII.GetString(dataArray);
            XrossPeer.Log("illigal format invalidMessage2:" + invalidMessage);
            return;
        }
        }

        var state = (char)dataArray[1];

        // dataArray[2-38] is connectionId, length = definitely CONNECTION_ID_LEN.
        var connectionId = Encoding.ASCII.GetString(dataArray, 2, CONNECTION_ID_LEN);

        switch (state)
        {
        case STATE_CONNECT: {
            if (2 + CONNECTION_ID_LEN < len)
            {
                var dataLen = len - (2 + CONNECTION_ID_LEN);
                var data    = new byte[dataLen];
                Buffer.BlockCopy(dataArray, (2 + CONNECTION_ID_LEN), data, 0, dataLen);
                OnConnected(connectionId, data);
            }
            break;
        }

        case STATE_STRING_MESSAGE: {
            // ignored.
            break;
        }

        case STATE_BINARY_MESSAGE: {
            if (2 + CONNECTION_ID_LEN < len)
            {
                var dataLen = len - (2 + CONNECTION_ID_LEN);
                var data    = new byte[dataLen];
                Buffer.BlockCopy(dataArray, (2 + CONNECTION_ID_LEN), data, 0, dataLen);
                OnMessage(connectionId, data);
            }
            break;
        }

        case STATE_DISCONNECT_INTENT: {
            if (2 + CONNECTION_ID_LEN < len)
            {
                var dataLen = len - (2 + CONNECTION_ID_LEN);
                var data    = new byte[dataLen];
                Buffer.BlockCopy(dataArray, (2 + CONNECTION_ID_LEN), data, 0, dataLen);

                OnDisconnected(connectionId, data, "intentional disconnect.");
            }
            break;
        }

        case STATE_DISCONNECT_ACCIDT: {
            if (2 + CONNECTION_ID_LEN < len)
            {
                var dataLen = len - (2 + CONNECTION_ID_LEN);
                var data    = new byte[dataLen];
                Buffer.BlockCopy(dataArray, (2 + CONNECTION_ID_LEN), data, 0, dataLen);

                OnDisconnected(connectionId, data, "accidential disconnect.");
            }
            break;
        }

        case STATE_DISCONNECT_DISQUE_ACKFAILED: {
            if (2 + CONNECTION_ID_LEN < len)
            {
                var dataLen = len - (2 + CONNECTION_ID_LEN);
                var data    = new byte[dataLen];
                Buffer.BlockCopy(dataArray, (2 + CONNECTION_ID_LEN), data, 0, dataLen);

                OnDisconnected(connectionId, data, "accidential disconnect.");
            }
            break;
        }

        case STATE_DISCONNECT_DISQUE_ACCIDT_SENDFAILED: {
            if (2 + CONNECTION_ID_LEN < len)
            {
                var dataLen = len - (2 + CONNECTION_ID_LEN);
                var data    = new byte[dataLen];
                Buffer.BlockCopy(dataArray, (2 + CONNECTION_ID_LEN), data, 0, dataLen);

                OnDisconnected(connectionId, data, "send failed to client. disconnect.");
            }
            break;
        }

        default: {
            XrossPeer.Log("undefined websocket state:" + state);
            break;
        }
        }
    }
Exemplo n.º 23
0
    public ServerContext(string serverQueueId)
    {
        serverContextId = Guid.NewGuid().ToString();

        XrossPeer.Log("server generated! serverContextId:" + serverContextId + " serverQueueId:" + serverQueueId);

        // Updater queueGetJobber = null;

        // ちょうどDisqueConnectionControllerとDisquuunのあいだをいったりきたりしてるんで齟齬がある。
        var disqueId = Guid.NewGuid().ToString();
        // disquuun = new Disquuun(
        //  disqueId,
        //  "127.0.0.1",
        //  7711,
        //  102400,
        //  connectedConId => {
        //      Action<string, byte[]> Send = (string connectionId, byte[] data) => {
        //          disquuun.AddJob(connectionId, data);
        //      };

        //      Setup(Send);

        //      XrossPeer.Log("同期的にコンテキストの用意が終わったつもり。 ほんとはいろんな接続があるはず。");
        //      queueGetJobber = new Updater(
        //          "disquuunGetJobber",
        //          () => {
        //              disquuun.GetJob(new string[]{serverQueueId}, "COUNT", 1000, "NOHANG");
        //              return true;
        //          }
        //      );

        //  },
        //  (command, byteDatas) => {
        //      switch (command) {
        //          case Disquuun.DisqueCommand.INFO: {
        //              var stringData = byteDatas[0];
        //              var info = Encoding.UTF8.GetString(stringData.bytesArray[0], 0, stringData.bytesArray[0].Length);
        //              XrossPeer.Log("info:" + info);
        //              break;
        //          }
        //          case Disquuun.DisqueCommand.GETJOB: {
        //              var jobIds = new List<string>();
        //              foreach (var bytes in byteDatas) {
        //                  var jobId = Encoding.UTF8.GetString(bytes.bytesArray[0]);
        //                  jobIds.Add(jobId);

        //                  ParseData(bytes.bytesArray[1]);
        //              }

        //              if (jobIds.Any()) disquuun.FastAck(jobIds.ToArray());
        //              break;
        //          }
        //          case Disquuun.DisqueCommand.FASTACK: {
        //              // do nothing.
        //              break;
        //          }
        //          default: {
        //              break;
        //          }
        //      }
        //  },
        //  (failedCommand, reason) => {
        //      XrossPeer.LogError("failedCommand:" + failedCommand + " reason:" + reason);
        //  },
        //  e => {
        //      XrossPeer.LogError("Disque error:" + e);
        //      if (queueGetJobber != null) queueGetJobber.Quit();
        //  },
        //  disconnectedConId => {
        //      XrossPeer.Log("Disque disconnected:" + disqueId);
        //  }
        // );
    }