コード例 #1
0
ファイル: SaveLoad.cs プロジェクト: PhoenixICE/Multiplayer
        public static void SendCurrentGameData(bool async)
        {
            var mapsData = new Dictionary <int, byte[]>(OnMainThread.cachedMapData);
            var gameData = OnMainThread.cachedGameData;

            void Send()
            {
                var writer = new ByteWriter();

                writer.WriteInt32(mapsData.Count);
                foreach (var mapData in mapsData)
                {
                    writer.WriteInt32(mapData.Key);
                    writer.WritePrefixedBytes(GZipStream.CompressBuffer(mapData.Value));
                }

                writer.WritePrefixedBytes(GZipStream.CompressBuffer(gameData));

                byte[] data = writer.ToArray();

                OnMainThread.Enqueue(() => Multiplayer.Client.SendFragmented(Packets.Client_AutosavedData, data));
            };

            if (async)
            {
                ThreadPool.QueueUserWorkItem(c => Send());
            }
            else
            {
                Send();
            }
        }
コード例 #2
0
        public void Add(SyncInfo info)
        {
            if (Multiplayer.session.desynced)
            {
                return;
            }
            if (TickPatch.Skipping)
            {
                return;
            }

            if (buffer.Count == 0)
            {
                buffer.Add(info);
                return;
            }

            if (buffer[0].local == info.local)
            {
                buffer.Add(info);
                if (buffer.Count > 30)
                {
                    buffer.RemoveAt(0);
                }
            }
            else
            {
                while (buffer.Count > 0 && buffer[0].startTick < info.startTick)
                {
                    buffer.RemoveAt(0);
                }

                if (buffer.Count == 0)
                {
                    buffer.Add(info);
                }
                else if (buffer.First().startTick == info.startTick)
                {
                    var first = buffer.RemoveFirst();
                    var error = first.Compare(info);

                    if (error != null)
                    {
                        MpLog.Log($"Desynced {lastValidTick}: {error}");
                        Multiplayer.session.desynced = true;
                        OnMainThread.Enqueue(() => OnDesynced(first, info, error));
                    }
                    else
                    {
                        lastValidTick    = first.startTick;
                        lastValidArbiter = Multiplayer.session.ArbiterPlaying;
                    }
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Adds a client opinion to the <see cref="knownClientOpinions"/> list and checks that it matches the most recent currently in there. If not, a desync event is fired.
        /// </summary>
        /// <param name="newOpinion">The <see cref="ClientSyncOpinion"/> to add and check.</param>
        public void AddClientOpinionAndCheckDesync(ClientSyncOpinion newOpinion)
        {
            //If we've already desynced, don't even bother
            if (Multiplayer.session.desynced)
            {
                return;
            }

            //If we're skipping ticks, again, don't bother
            if (TickPatch.Skipping)
            {
                return;
            }

            //If this is the first client opinion we have nothing to compare it with, so just add it
            if (knownClientOpinions.Count == 0)
            {
                knownClientOpinions.Add(newOpinion);
                return;
            }

            if (knownClientOpinions[0].isLocalClientsOpinion == newOpinion.isLocalClientsOpinion)
            {
                knownClientOpinions.Add(newOpinion);
                if (knownClientOpinions.Count > 30)
                {
                    knownClientOpinions.RemoveAt(0);
                }
            }
            else
            {
                //Remove all opinions that started before this one, as it's the most up to date one
                while (knownClientOpinions.Count > 0 && knownClientOpinions[0].startTick < newOpinion.startTick)
                {
                    knownClientOpinions.RemoveAt(0);
                }

                //If there are none left, we don't need to compare this new one
                if (knownClientOpinions.Count == 0)
                {
                    knownClientOpinions.Add(newOpinion);
                }
                else if (knownClientOpinions.First().startTick == newOpinion.startTick)
                {
                    //If these two contain the same tick range - i.e. they start at the same time, cause they should continue to the current tick, then do a comparison.

                    var oldOpinion = knownClientOpinions.RemoveFirst();

                    //Actually do the comparison to find any desync
                    var desyncMessage = oldOpinion.CheckForDesync(newOpinion);

                    if (desyncMessage != null)
                    {
                        MpLog.Log($"Desynced after tick {lastValidTick}: {desyncMessage}");
                        Multiplayer.session.desynced = true;
                        OnMainThread.Enqueue(() => HandleDesync(oldOpinion, newOpinion, desyncMessage));
                    }
                    else
                    {
                        //Update fields
                        lastValidTick = oldOpinion.startTick;
                        arbiterWasPlayingOnLastValidTick = Multiplayer.session.ArbiterPlaying;
                    }
                }
            }
        }