Esempio n. 1
0
        public ReplayConnection(string replayFilename)
        {
            Filename = replayFilename;

            // Parse replay data into a struct that can be fed to the game in chunks
            // to avoid issues with all immediate orders being resolved on the first tick.
            using (var rs = File.OpenRead(replayFilename))
            {
                var chunk = new Chunk();

                while (rs.Position < rs.Length)
                {
                    var client = rs.ReadInt32();
                    if (client == ReplayMetadata.MetaStartMarker)
                        break;
                    var packetLen = rs.ReadInt32();
                    var packet = rs.ReadBytes(packetLen);
                    var frame = BitConverter.ToInt32(packet, 0);
                    chunk.Packets.Add(Pair.New(client, packet));

                    if (packet.Length == 5 && packet[4] == 0xBF)
                        continue; // disconnect
                    else if (packet.Length >= 5 && packet[4] == 0x65)
                        continue; // sync
                    else if (frame == 0)
                    {
                        // Parse replay metadata from orders stream
                        var orders = packet.ToOrderList(null);
                        foreach (var o in orders)
                        {
                            if (o.OrderString == "StartGame")
                                IsValid = true;
                            else if (o.OrderString == "SyncInfo" && !IsValid)
                                LobbyInfo = Session.Deserialize(o.TargetString);
                        }
                    }
                    else
                    {
                        // Regular order - finalize the chunk
                        chunk.Frame = frame;
                        chunks.Enqueue(chunk);
                        chunk = new Chunk();

                        TickCount = Math.Max(TickCount, frame);
                    }
                }
            }

            ordersFrame = LobbyInfo.GlobalSettings.OrderLatency;
        }
Esempio n. 2
0
        static void SendNextChunk(Connection c)
        {
            try
            {
                var data = c.Stream.Read(Math.Min(DownloadChunkSize, c.RemainingBytes));
                if (data.Length != 0)
                {
                    var chunk = new Chunk
                    {
                        Index = c.NextChunk++,
                        Count = c.NumChunks,
                        Data = Convert.ToBase64String(data)
                    };

                    DispatchOrdersToClient(c, 0, 0,
                        new ServerOrder("FileChunk",
                            FieldSaver.Save(chunk).Nodes.WriteToString()).Serialize());
                }

                c.RemainingBytes -= data.Length;
                if (c.RemainingBytes == 0)
                {
                    GetClient(c).State = Session.ClientState.NotReady;
                    c.Stream.Dispose();
                    c.Stream = null;

                    SyncLobbyInfo();
                }
            }
            catch (Exception e) { DropClient(c, e); }
        }
Esempio n. 3
0
        public ReplayConnection(string replayFilename)
        {
            Filename = replayFilename;

            // Parse replay data into a struct that can be fed to the game in chunks
            // to avoid issues with all immediate orders being resolved on the first tick.
            using (var rs = File.OpenRead(replayFilename))
            {
                var chunk = new Chunk();

                while (rs.Position < rs.Length)
                {
                    var client = rs.ReadInt32();
                    if (client == ReplayMetadata.MetaStartMarker)
                        break;
                    var packetLen = rs.ReadInt32();
                    var packet = rs.ReadBytes(packetLen);
                    var frame = BitConverter.ToInt32(packet, 0);
                    chunk.Packets.Add(Pair.New(client, packet));

                    if (frame != int.MaxValue &&
                        (!lastClientsFrame.ContainsKey(client) || frame > lastClientsFrame[client]))
                        lastClientsFrame[client] = frame;

                    if (packet.Length == 5 && packet[4] == 0xBF)
                        continue; // disconnect
                    else if (packet.Length >= 5 && packet[4] == 0x65)
                        continue; // sync
                    else if (frame == 0)
                    {
                        // Parse replay metadata from orders stream
                        var orders = packet.ToOrderList(null);
                        foreach (var o in orders)
                        {
                            if (o.OrderString == "StartGame")
                                IsValid = true;
                            else if (o.OrderString == "SyncInfo" && !IsValid)
                                LobbyInfo = Session.Deserialize(o.TargetString);
                        }
                    }
                    else
                    {
                        // Regular order - finalize the chunk
                        chunk.Frame = frame;
                        chunks.Enqueue(chunk);
                        chunk = new Chunk();

                        TickCount = Math.Max(TickCount, frame);
                    }
                }

                var lastClientToDisconnect = lastClientsFrame.MaxBy(kvp => kvp.Value).Key;

                // 2nd parse : replace all disconnect packets without frame with real
                // disconnect frame
                // NOTE: to modify/remove if a reconnect feature is set
                foreach (var tmpChunk in chunks)
                {
                    foreach (var tmpPacketPair in tmpChunk.Packets)
                    {
                        var client = tmpPacketPair.First;

                        // Don't replace the final disconnection packet - we still want this to end the replay.
                        if (client == lastClientToDisconnect)
                            continue;

                        var packet = tmpPacketPair.Second;
                        if (packet.Length == 5 && packet[4] == 0xBF)
                        {
                            var lastClientFrame = lastClientsFrame[client];
                            var lastFramePacket = BitConverter.GetBytes(lastClientFrame);
                            Array.Copy(lastFramePacket, packet, lastFramePacket.Length);
                        }
                    }
                }
            }

            ordersFrame = LobbyInfo.GlobalSettings.OrderLatency;
        }