Example #1
0
    /// <summary>
    /// Builds a LockStepMessage from the given List of NetworkData.
    /// This method guarantees that the constructed message has the correct sequence ID.
    /// </summary>
    /// <param name="dataList">The NetworkData contained in the message</param>
    /// <returns>A new LockStepMessage</returns>
    private LockStepMessage BuildLockStepMessage(List <NetworkData> dataList)
    {
        LockStepMessage msg = new LockStepMessage();

        // When the dataList is empty we need to send a No-Op message (to save bandwidth)
        if (dataList.Count == 0)
        {
            msg.seqID = NO_OP_MSG_ID;
            // We do not need to clone the dataList in this case since it is empty anyways
            // Furthermore,  the special NO_OP_MSG_ID makes sure no NetworkData will be read
            msg.dataList = dataList;
            PrintDebug(DebugLevel.DEBUG, "BuildLockStepMessage NO_OP_MSG_ID");
            return(msg);
        }
        if (IsHost())
        {
            msg.seqID = ServerSideMsgSeqID++;
        }
        else
        {
            // When we are the client we dont need to count MsgSeqID's since the server
            // does no verification of order
            msg.seqID = NO_OP_MSG_ID;
        }
        // We clone the dataList because it might get cleared by the LockStepManager
        msg.dataList = new List <NetworkData>(dataList);
        PrintDebug(DebugLevel.DEBUG, "BuildLockStepMessage seqID={0}, count={1}",
                   msg.seqID, msg.dataList.Count);
        return(msg);
    }
Example #2
0
 /// <summary>
 /// Calls the OnReceive method of all NetworkData within the given LockStepMessage.
 /// </summary>
 /// <param name="msg">The LockStepMessage to execute</param>
 private void ExecuteLockStepMessage(LockStepMessage msg)
 {
     PrintDebug(DebugLevel.DEBUG, "ExecuteLockStepMessage SeqID={0}", msg.seqID);
     foreach (var data in msg.dataList)
     {
         data.OnReceive(this);
     }
 }
Example #3
0
    /// <summary>
    /// Called by the H2LogPlayer when a Client has sent a LockStepMessage over the network.
    /// This method is supposed to buffer the data from the client for the next LockStep.
    /// </summary>
    /// <param name="byteArr">bytes from the network</param>
    public void ServerReceiveMessage(byte[] byteArr)
    {
        PrintDebug(DebugLevel.DEBUG, "ServerReceiveMessage (byte[])");
        List <object> list = SerializationCtrl.Deserialize(byteArr);

        ReactToSerializationError();

        LockStepMessage msg = (LockStepMessage)list[0];

        ServerReceiveMessage(msg);
    }
Example #4
0
    /// <summary>
    /// Called by the H2LogPlayer after byte data was received from the server.
    /// This method is called on all devices, even the server.
    /// </summary>
    /// <param name="byteArr">bytes from the network</param>
    public void ClientProcessLockStep(byte[] byteArr)
    {
        PrintDebug(DebugLevel.DEBUG, "ClientProcessLockStep (byte[])");
        List <object> list = SerializationCtrl.Deserialize(byteArr);

        ReactToSerializationError();

        LockStepMessage msg = (LockStepMessage)list[0];

        ClientProcessLockStep(msg);
    }
Example #5
0
    /// <summary>
    /// Called by the ClientProcessLockStep method if we are playing over the network
    /// and we just received data from the server or by the SendLockStep method if we
    /// are playing locally.
    /// This method should buffer a message received out of order or execute the network
    /// data from a message received in order.
    /// </summary>
    /// <param name="msg">The LockStepMessage to process</param>
    private void ClientProcessLockStep(LockStepMessage msg)
    {
        if (msg.seqID == NO_OP_MSG_ID)
        {
            return;
        }
        PrintDebug(DebugLevel.VERBOSE, "ClientProcessLockStep seqID={0}", msg.seqID);
        if (msg.seqID == ClientSideExpectedMsgSeqID)
        {
            ClientSideExpectedMsgSeqID++;
            ExecuteLockStepMessage(msg);

            if (ClientSideMsgBuffer.Count > 0)
            {
                ClientSideMsgBuffer.Sort(delegate(LockStepMessage m1, LockStepMessage m2)
                {
                    return(m1.seqID.CompareTo(m2.seqID));
                });
                while (ClientSideMsgBuffer.Count > 0)
                {
                    LockStepMessage bufMsg = ClientSideMsgBuffer[0];
                    if (bufMsg.seqID < ClientSideExpectedMsgSeqID)
                    {
                        ClientSideMsgBuffer.RemoveAt(0);
                        ReactToError("Executed buffered LockStepMessage with sequence ID from the past. SeqID={0}", bufMsg.seqID);
                    }
                    else if (bufMsg.seqID == ClientSideExpectedMsgSeqID)
                    {
                        ClientSideMsgBuffer.RemoveAt(0);
                        ExecuteLockStepMessage(bufMsg);
                        ClientSideExpectedMsgSeqID++;
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
        else if (msg.seqID > ClientSideExpectedMsgSeqID)
        {
            ClientSideMsgBuffer.Add(msg);
            PrintDebug(DebugLevel.VERBOSE, "BufferLockStepMessage seqID={0}, currentBufferSize={1}",
                       msg.seqID, ClientSideMsgBuffer.Count);
        }
        else
        {
            ReactToError("Received LockStepMessage with sequence ID from the past. SeqID={0}", msg.seqID);
        }
    }
Example #6
0
    /// <summary>
    /// If this device is the host then all currently buffered messages within the
    /// ServerSideBuffer will be sent out to all devices (including this one!).
    ///
    /// If this device is a client then all currently buffered messages within the
    /// ClientSideBuffer will be sent out to the host device (server).
    ///
    /// If networking is disabled this device will simply execute all local messages
    /// buffered in the ClientSideBuffer.
    /// </summary>
    private void SendLockStep()
    {
        PrintDebug(DebugLevel.DEBUG, "SendLockStep.IsHost={0}", IsHost());
        if (IsHost())
        {
            ServerSideBuffer.AddRange(ClientSideBuffer);

            LockStepMessage msg = BuildLockStepMessage(ServerSideBuffer);
            if (IsNetworkEnabled())
            {
                List <byte> byteList = SerializationCtrl.Serialize(msg);
                ReactToSerializationError();

                byte[] byteArr = byteList.ToArray();
                foreach (var player in H2LogPlayer.instances)
                {
                    player.RpcClientReceiveLockStep(byteArr);
                }
            }
            else
            {
                ClientProcessLockStep(msg);
            }
            ServerSideBuffer.Clear();
        }
        else
        {
            LockStepMessage msg = BuildLockStepMessage(ClientSideBuffer);
            if (IsNetworkEnabled())
            {
                List <byte> byteList = SerializationCtrl.Serialize(msg);
                ReactToSerializationError();

                byte[] byteArr = byteList.ToArray();
                H2LogPlayer.localPlayer.CmdServerReceiveLockStep(byteArr);
            }
            else
            {
                ServerReceiveMessage(msg);
            }
        }
        ClientSideBuffer.Clear();
    }
Example #7
0
 /// <summary>
 /// Called by the ServerReceiveMessage method when we are playing over the network or
 /// the SendLockStep method if we are playing without networking.
 /// </summary>
 /// <param name="msg">A LockStepMessage sent by a client to the server</param>
 private void ServerReceiveMessage(LockStepMessage msg)
 {
     ServerSideBuffer.AddRange(msg.dataList);
 }