Example #1
0
    void StartServer()
    {
        started = true;
        OperationNetwork.isServer = true;

        myServer = new ServerAcceptor();
        myServer.StartServer();

        // This is to get the server player to connect:
        OperationNetwork.initialConnected = 0;         // The server player doesn't necessarily have to connect first.


        // Demo maker:
        ServerPerson sP = new ServerPerson(myServer);

        sP.setDemo();
        // Revert addID:
        ServerPerson.addID--;

        RunGame.myServerThreads.Add(sP);
        // PlayerListHandler does not consider demo client.

        // Instantly connect the demo client:
        sP.connected = true;
    }
    static int runMovementCommandData(ServerPerson theClient, short packetID, byte[] data, bool runPlayerInput, short index)
    {
        byte numFrames = data [0];
        int  endPoint  = 1;

        for (int i = 0; i < numFrames; i++)
        {
            byte   length             = data [endPoint++];
            byte[] dataForPlayerInput = new byte[length];
            Buffer.BlockCopy(data, endPoint, dataForPlayerInput, 0, length);
            endPoint += length;

            if (index != -1 && runPlayerInput)
            {
                operationObjects [index].GetComponent <PlayerMove> ().movementData(packetID, dataForPlayerInput);
            }
        }
        return(endPoint);
    }
    void sendGameStatesToPlayer(GameState serverState, ServerPerson theClient)
    {
        if (theClient.connected)
        {
            // This is easy enough, we send both game states every time, so both game states are expected in the 1, 2 order each time.
            bool changedData = theClient.lastSentGameState[theClient.lastSentGameState.Length - 1] != null;             // Obviously server overrides this

            // First, we strip serverState of its playerData when getting its data:


            byte[] data1 = serverState.getDataWithoutPlayerData(changedData, theClient.id, theClient.shouldNextSendOutBeFullSendOut);
            theClient.shouldNextSendOutBeFullSendOut = false;

            // Now, we create the player gamestate, and send that:
            Interp.shiftBuffer(theClient.lastSentGameState);
            theClient.lastSentGameState[0] = new GameState(theClient.lastSentGameState, ServerState.tickNumber, theClient.id);             // lastSentGameState is used to determine if changedData here
            byte[] data2 = theClient.lastSentGameState[0].getChangedData();

            byte[] data = new byte[data1.Length + data2.Length];
            Buffer.BlockCopy(data1, 0, data, 0, data1.Length);
            Buffer.BlockCopy(data2, 0, data, data1.Length, data2.Length);
            theClient.SendData(data, false);
        }
    }
    public static void serverReceivedInput(byte[] data, int fromWho, short packetID)
    {
        // We need to go out and find the index for this object:
        short index = -1;

        if (GameManager.GetPlayer((short)fromWho).playerObject != null)
        {
            index = GameManager.GetPlayer((short)fromWho).playerObject.GetComponent <SyncGameState> ().objectID;
        }

        // In the model where commands are sent more than once to avoid excessive lag due to packet loss,
        // We must check that the packetID is not the same.
        ServerPerson thisClient = getClient((short)fromWho);


        bool runPlayerInput = true;

        if ((short)(thisClient.lastPlayerInputGroupID + 1) == packetID)
        {
            // Good to go
            thisClient.lastPlayerInputGroupID++;

            // By definition, this should never happen:
            if (thisClient.inputCommands.ContainsKey(packetID))
            {
                Debug.LogError("Packet existed but wasn't run! OperationNetwork -> serverReceivedInput");
                thisClient.inputCommands.Remove(packetID);
            }

            // I would assume its limited to 30ish (20)
            for (int i = 1; i < 30; i++)
            {
                if (thisClient.inputCommands.ContainsKey((short)(packetID + i)))
                {
                    thisClient.lastPlayerInputGroupID = (short)(packetID + i);
                    runMovementCommandData(thisClient, packetID, thisClient.inputCommands [(short)(packetID + i)], true, index);
                    thisClient.inputCommands.Remove((short)(packetID + i));
                }
                else
                {
                    break;
                }
            }


            // This allows for a maximum of (8) buffered input commands, which is WAY more than we should ever have.. probably.. -but now out of order needs to be considered
        }
        else
        {
            bool found = false;

            // OLD packets: (This includes the same packet, of course).
            for (int i = 0; i < 160; i++)
            {
                if ((short)(thisClient.lastPlayerInputGroupID - i) == packetID)
                {
                    found          = true;
                    runPlayerInput = false;
                    break;
                }
            }
            // We assume that these are simply packets that are slightly out of order..
            if (!found)
            {
                // FUTURE packets. Note that 30 means that in the current system, after not receiving a certain packet in 400ms, you will rubber band for that entire second. TODO make it so it runs what it can when rubber banding occurs
                for (int i = 2; i < 20; i++)
                {
                    if ((short)(thisClient.lastPlayerInputGroupID + i) == packetID)
                    {
                        found          = true;
                        runPlayerInput = false;
                        if (!thisClient.inputCommands.ContainsKey(packetID))
                        {
                            thisClient.inputCommands.Add(packetID, data);
                        }
                        break;
                    }
                }
                // First, we are going to check if the command was from before. These simply need to be skipped


                // Otherwise, we assume the command is too late and we run all buffered input commands including this one to "catch up"
                if (!found)
                {
                    Debug.LogError("Rubber Banding!!! " + thisClient.lastPlayerInputGroupID + " / " + packetID);

                    thisClient.inputCommands.Clear();

                    // And start off input from hereon out:
                    runPlayerInput = true;
                    thisClient.lastPlayerInputGroupID = packetID;
                }
            }


            // Note that packets more out of order than the above limit will cause all previous packets to be skipped.
            // Running an out of order packet will cause all packets available to run, regardless if +1 order is maintained.
        }
        // The code after this will run to iterate through the data, but with a bool to see if the code should actually be simulated.

        int endPoint = runMovementCommandData(thisClient, packetID, data, runPlayerInput, index);

        if (endPoint < data.Length)
        {
            // And then the next input command is read: (We technically don't have to run this if the player doesn't exist)
            byte[] nextData = new byte[data.Length - endPoint];
            Buffer.BlockCopy(data, endPoint, nextData, 0, data.Length - endPoint);
            serverReceivedInput(nextData, fromWho, (short)(packetID + 1));
        }
    }
Example #5
0
    public void ReadMessages()
    {
        for (int i = 0; i < 5000; i++)
        {
            try {
                int              recHostId;
                int              recConnectionId;
                int              recChannelId;
                byte[]           recBuffer  = new byte[2048];
                int              bufferSize = 2048;
                int              dataSize;
                byte             error;
                NetworkEventType networkEvent = NetworkTransport.Receive(out recHostId, out recConnectionId, out recChannelId, recBuffer, bufferSize, out dataSize, out error);

                NetworkError networkError = (NetworkError)error;
                if (networkError != NetworkError.Ok)
                {
                    Debug.LogError(string.Format("Error recieving event: {0} with recHostId: {1}, recConnectionId: {2}, recChannelId: {3}", networkError, recHostId, recConnectionId, recChannelId));
                }

                switch (networkEvent)
                {
                case NetworkEventType.Nothing:
                    return;

                case NetworkEventType.ConnectEvent:
                    Debug.LogError(string.Format("incoming connection event received with connectionId: {0}, recHostId: {1}, recChannelId: {2}", recConnectionId, recHostId, recChannelId));

                    if (!serverClients.ContainsKey(recConnectionId))
                    {
                        // Add server client:
                        ServerPerson sP = new ServerPerson(this);
                        RunGame.myServerThreads.Add(sP);
                        // hmm...  player.players.Add(sP.id, new OtherPlayerInfo()); // Stick to default settings until a RPC is received.
                        sP.recConnectionId = recConnectionId;
                        serverClients.Add(recConnectionId, sP);
                    }
                    break;

                case NetworkEventType.DataEvent:
                    // Player Input!
                    // Delegate this to the "ServerClientData" first:
                    if (serverClients.ContainsKey(recConnectionId))
                    {
                        short id = serverClients [recConnectionId].id;

                        if (dataSize > 500)
                        {
                            Debug.LogError("Nearing Data limit on server: " + dataSize + ": " + recChannelId + "(" + reliableSequencedChannelId + " / " + unreliableChannelId + ")");
                        }

                        // todo: When removing RPCs, we're going to make this into a proper ref index sorta thing:
                        byte[] rpcData = new byte[dataSize];
                        Buffer.BlockCopy(recBuffer, 0, rpcData, 0, dataSize);

                        if (recChannelId == reliableSequencedChannelId)
                        {
                            OperationNetwork.serverReceivedData(rpcData, id);
                        }
                        else
                        {
                            short  packetID = BitConverter.ToInt16(rpcData, 0);
                            byte[] sData    = new byte[rpcData.Length - 2];
                            // This might be one of the most inefficient things on the server, TODO!! The copy of byte data!!
                            Buffer.BlockCopy(rpcData, 2, sData, 0, sData.Length);
                            OperationNetwork.serverReceivedInput(sData, id, packetID);
                        }
                    }
                    else
                    {
                        Debug.LogError("Client not connected: " + recConnectionId);
                    }
                    break;

                case NetworkEventType.DisconnectEvent:
                    Debug.LogError("remote client " + recConnectionId + " disconnected");
                    if (serverClients.ContainsKey(recConnectionId))
                    {
                        RunGame.myServerThreads.Remove(serverClients [recConnectionId]);
                        serverClients [recConnectionId].disconnect();
                        serverClients.Remove(recConnectionId);
                    }
                    break;
                }
            } catch (Exception e) {
                Debug.LogError("Error on client data receive: " + e.Message);
            }
        }
        Debug.LogError("Missing Messages on Server!");
    }