Esempio n. 1
0
        private bool StartGameMsg(Dictionary <string, object> json)
        {
            // This is complicated so will do my best to comment, even for myself in the future
            // There are 4 players allowed to drop in/out per game, this tries to cover all possible scenarios that I could think of

            /*
             * There are a number of different conditionns that need to be considered
             * - The player needs to have an account and be logged in to start a game
             * - If the above conditions are not met, he will simply get an error message explainig why
             * - This may be the first play that starts the game, if so the level will be constructed, he will be sent a packet for info on his playe
             * - If there are already clients online, then they need to know about this new player who has joined, and he needs to know about himself and them
             * - Next... need to consider the fact that the other clients on the server are in game or not, if they are not in a game, and in the lobby then they
             *   do NOT need to know about this new player until they have started their own game
             * - If all players reach the exit, then the game simulation is cleared from memory
             * - Up to 4 players can join the same game at any time, and the game session is considered over when all players have either reached the goal or quit out
             * - In an edge case situation.... two players start a game >> player 1 finished level and goes back to lobby >> player 2 is still playing >> player 1 can re-enter
             *   using the same internal game object, the player count will still  be incremented as this could go on forever otherwise
             */

            int clientId = -1;

            // Extract the id of the sender
            if (json.ContainsKey("id"))
            {
                clientId = (int)((long)json["id"]);
            }
            else
            {
                Logger.Log("Error Parsing client id in start game packet", Logger.LogPrio.Error);
            }

            // Check that this id is in our client hash table
            if (!m_ServerManager.ClientExists(clientId))
            {
                Logger.Log(string.Format("Error client id {0} does not exist", clientId), Logger.LogPrio.Error);
                return(false);
            }

            // Client must be logged in!!
            if (Server.ServerManager.instance.GetClient(clientId).loggedIn == false)
            {
                PacketDefs.msgPacket returnPack = new PacketDefs.msgPacket();
                returnPack.msg     = "Error: not logged in";
                returnPack.success = false;
                ServerManager.instance.SendTcp(ServerManager.instance.GetClient(clientId).tcpSocket, fastJSON.JSON.ToJSON(returnPack, PacketDefs.JsonParams()));
                return(false);
            }
            // Game must not be full !!
            else if (m_GameSimulation.GetPlayersInGame() >= 4)
            {
                PacketDefs.msgPacket returnPack = new PacketDefs.msgPacket();
                returnPack.msg     = "Game is full please wait";
                returnPack.success = false;
                ServerManager.instance.SendTcp(ServerManager.instance.GetClient(clientId).tcpSocket, fastJSON.JSON.ToJSON(returnPack, PacketDefs.JsonParams()));
                return(false);
            }
            else
            {
                // This is first client so load level data
                if (!m_GameSimulation.IsGameDataLoaded())
                {
                    m_GameSimulation.LoadLevel(0);
                }

                GameClient thisClient = ServerManager.instance.GetClient(clientId);

                // Check if he is re-entering the same game
                if (thisClient.playerObjectHandle > -1)
                {
                    // Do we have a match
                    foreach (GameObject go in GameSimulation.instance.GetPlayers())
                    {
                        if (go.UnqId() == thisClient.playerObjectHandle && go.Active == false)
                        {
                            // The players already on will get an update to activate this in next tick
                            go.Active = true;

                            // Increment counter
                            GameSimulation.instance.AddNewPlayerToSession();
                        }
                    }
                }
                // Weird edge case: Previous client quit, but we still have a re-useable game object in memory so give him that
                else if (GameSimulation.instance.GetPlayers().Count == ServerManager.instance.NumClients())
                {
                    foreach (GameObject go in GameSimulation.instance.GetPlayers())
                    {
                        if (go.Active == false)
                        {
                            // The players already on will get an update to activate this in next tick
                            go.Active = true;

                            // Increment counter
                            GameSimulation.instance.AddNewPlayerToSession();

                            // Set the internal memoory handle store in client data
                            m_ServerManager.SetPlayerHandle(clientId, go.UnqId());

                            go.IsClient = 1;
                        }
                    }
                }
                else
                {
                    // This client is new to this game

                    // Set the internal memoory handle store in client data
                    m_ServerManager.SetPlayerHandle(clientId, m_GameSimulation.NumObjects());

                    // Add new client to game sim

                    GameObject newPlayer = new Player(Player.SpawnPosition(), GameObjectType.Player, m_GameSimulation.NumObjects(), 1, true, clientId,
                                                      new Vector2(96, 96), new ColliderOffset(26, 26, 30, 0));
                    //new Vector2(128, 128), new ColliderOffset(46,46,50,0));
                    m_GameSimulation.AddGameObject(newPlayer);

                    // Create Packet of one game object (this player) to send to other clients already on server with just this player. *note* last param (isClient) is set to 0 intentionally
                    PacketDefs.MultiGameObjectPacket thisClientPacket = new PacketDefs.MultiGameObjectPacket(1);
                    thisClientPacket.objects[0] = new PacketDefs.GameObjectPacket(
                        (int)newPlayer.TypeId(), newPlayer.UnqId(), newPlayer.Position.X, newPlayer.Position.Y, 0);

                    // This flag signifies if we actually need to  load the level,m because the other client is either in game or lobby then we don't want this
                    thisClientPacket.loadLevel = false;

                    // 1 - Send any clients on the server the new one that has been added
                    string data = fastJSON.JSON.ToJSON(thisClientPacket, PacketDefs.JsonParams());
                    foreach (KeyValuePair <int, GameClient> kvp in ServerManager.instance.GetClients())
                    {
                        // - Make sure it is not this client: He is included in the all clients packet and doesnt need to know
                        // - Make sure they are logged : Because they need to be
                        // - Make sure they are in game: Because they will get duplicates when they call this function otherwise

                        // This basically allows controls over the different stages, handles whether we are logged in or not and allows
                        // to drop in the game at any time
                        if (kvp.Key != clientId && kvp.Value.loggedIn && kvp.Value.inGame)
                        {
                            ServerManager.instance.SendTcp(kvp.Value.tcpSocket, data);
                        }
                    }
                }

                // Create Packet for list of all clients now to send to new player including himself
                PacketDefs.MultiGameObjectPacket allClientsPacket =
                    new PacketDefs.MultiGameObjectPacket(m_ServerManager.NumClients());
                allClientsPacket.loadLevel = true;

                // Fill it with data
                int i = 0;
                foreach (GameObject p in m_GameSimulation.GetObjects())
                {
                    if (p.TypeId() == GameObjectType.Player)
                    {
                        allClientsPacket.objects[i] = new PacketDefs.GameObjectPacket(
                            (int)p.TypeId(),
                            p.UnqId(),
                            p.Position.X,
                            p.Position.Y,
                            p.IsClient
                            );

                        ++i;
                    }
                }

                // Prevents duplicates
                thisClient.inGame = true;

                // 2 - Send the new client his own player details and the other players in the game
                m_ServerManager.SendTcp(thisClient.tcpSocket, fastJSON.JSON.ToJSON(allClientsPacket, PacketDefs.JsonParams()));

                // Set all players 'isClient' flag to null now that packets are sent
                foreach (GameObject player in GameSimulation.instance.GetPlayers())
                {
                    player.IsClient = 0;
                }

                return(true);
            }
        }