private IDictionary<string, object> SerializePretty(Frame frame, JavaScriptSerializer serializer)
        {
            List<UInt32> deletedActorStateIds = new List<UInt32>();
            Dictionary<UInt32, ActorStateJson> updatedActorStates = new Dictionary<UInt32, ActorStateJson>();

            foreach (var a in frame.ActorStates.Where(x => x.State == ActorStateState.Deleted))
            {
                _existingActorStates.Remove(a.Id);
                deletedActorStateIds.Add(a.Id);
            }

            foreach (var a in frame.ActorStates.Where(x => x.State == ActorStateState.New))
            {
                // Skip anything thats not truly new. Dont want keyframes in our json (for now)
                // (If there are property changes for a "new" actor we already have, they'll be caught below)
                if (!_existingActorStates.ContainsKey(a.Id))
                {
                    var actorState = new RocketLeagueReplayParser.Serializers.JsonSerializer.ActorStateJson();
                    actorState.Id = a.Id;
                    actorState.UnknownBit = a.Unknown1;
                    actorState.TypeName = a.TypeName;
                    actorState.ClassName = a.ClassName;
                    actorState.InitialPosition = a.Position;
                    actorState.Properties = new List<ActorStateProperty>();

                    _existingActorStates[a.Id] = actorState;
                    updatedActorStates[a.Id] = actorState;
                }
            }

            foreach (var a in frame.ActorStates.Where(x => x.State == ActorStateState.Existing))
            {
                var existingActorState = _existingActorStates[a.Id];
                RocketLeagueReplayParser.Serializers.JsonSerializer.ActorStateJson actorState = null;
                if (updatedActorStates.ContainsKey(a.Id))
                {
                    // Actor that's new as of this frame. Use the object we created above.

                    actorState = updatedActorStates[a.Id];
                }
                else
                {
                    // Existing actor. Start a new state object to track changes

                    actorState = new RocketLeagueReplayParser.Serializers.JsonSerializer.ActorStateJson();
                    actorState.Id = a.Id;
                    actorState.Properties = new List<RocketLeagueReplayParser.Serializers.JsonSerializer.ActorStateProperty>();

                    // Maybe skip some of the following for existing actors
                    //actorState.UnknownBit = existingActorState.UnknownBit;
                    //actorState.TypeName = existingActorState.TypeName;
                    //actorState.ClassName = existingActorState.ClassName;
                    //actorState.InitialPosition = existingActorState.InitialPosition;
                }

                foreach (var p in a.Properties)
                {
                    var property = new RocketLeagueReplayParser.Serializers.JsonSerializer.ActorStateProperty
                    {
                        Name = p.PropertyName,
                        Data = p.Data
                    };

                    var existingProperty = existingActorState.Properties.Where(ep => ep.Name == property.Name).FirstOrDefault();
                    if (existingProperty == null)
                    {
                        // new property

                        actorState.Properties.Add(property);
                        existingActorState.Properties.Add(property);
                    }
                    else
                    {
                        // Existing property.
                        if (/* property.Name == "TAGame.Ball_TA:HitTeamNum" // Keep "Event" properties. TODO: Check if keyframes have this no matter what
                            || property.Name.Contains("Music") // Kind of guessing at some of these event properties. We'll see how they turn out.
                            || property.Name.Contains("Sound")
                            || property.Name.Contains("Event")
                            || */ !existingProperty.IsDeepEqual(property))  // Only keep if it is truly different
                        {
                            actorState.Properties.Add(property);

                            // replace the property in our main set of data, so we have it for the next frame
                            existingActorState.Properties = existingActorState.Properties.Where(ep => ep.Name != property.Name).ToList();
                            existingActorState.Properties.Add(property);
                        }
                    }
                }

                // Dont keep this state if we havent found any properties worth keeping
                if (actorState.Properties.Any())
                {
                    updatedActorStates[a.Id] = actorState;
                }
            }

            if (deletedActorStateIds.Any() || updatedActorStates.Any())
            {
                Dictionary<string, object> result = new Dictionary<string, object>();
                result["Time"] = frame.Time;
                result["DeletedActorIds"] = deletedActorStateIds;
                result["ActorUpdates"] = updatedActorStates.Values;
                return result;
            }
            else
            {
                return null;
            }
        }
Example #2
0
        public static Frame Deserialize(int maxChannels, ref List<ActorState> existingActorStates, string[] objectIdToName, IDictionary<string, ClassNetCache> classNetCacheByName, UInt32 versionMajor, UInt32 versionMinor, BitReader br)
        {
            var f = new Frame();

            f.Position = br.Position;

            f.Time = br.ReadFloat();
            f.Delta = br.ReadFloat();

            if (f.Time < 0 || f.Delta < 0
                || (f.Time > 0 && f.Time < 1E-10)
                || (f.Delta > 0 && f.Delta < 1E-10))
            {
                string error = string.Format("\"Frame\" at postion {0} has time values that are negative or suspicious. The parser got lost. Check the previous frame for bad data. Time {1}, Delta {2}", f.Position, f.Time, f.Delta);
            #if DEBUG
                Console.WriteLine(error);
                f.Failed = true;
                return f;
            #endif
                throw new Exception(error);
            }

            f.ActorStates = new List<ActorState>();

            ActorState lastActorState = null;
            while (br.ReadBit())
            {
                lastActorState = ActorState.Deserialize(maxChannels, existingActorStates, f.ActorStates, objectIdToName, classNetCacheByName, versionMajor, versionMinor, br);

                var existingActor = existingActorStates.Where(x => x.Id == lastActorState.Id).SingleOrDefault();
                if (lastActorState.State != ActorStateState.Deleted)
                {
                    if (existingActor == null)
                    {
                        existingActorStates.Add(lastActorState);
                    }
                }
                else
                {
                    existingActorStates = existingActorStates.Where(x => x.Id != lastActorState.Id).ToList();
                }

                f.ActorStates.Add(lastActorState);

            #if DEBUG
                if(!lastActorState.Complete)
                {
                    break;
                }
            #endif
            }
            #if DEBUG
            if (lastActorState == null || lastActorState.Complete)
            {
                f.Complete = true;
            }

            if (lastActorState != null && lastActorState.Failed)
            {
                f.Failed = true;
            }

            f.RawData = br.GetBits(f.Position, br.Position - f.Position).ToArray();
            #endif
            return f;
        }
        private IDictionary<string, object> SerializeRaw(Frame frame, JavaScriptSerializer serializer)
        {
            List<UInt32> deletedActorStateIds = new List<UInt32>();
            List<ActorStateJson> newActorStates = new List<ActorStateJson>();
            List<ActorStateJson> updatedActorStates = new List<ActorStateJson>();

            Dictionary<int, ActorStateJson> actor = new Dictionary<int, ActorStateJson>();

            foreach (var a in frame.ActorStates.Where(x => x.State == ActorStateState.Deleted))
            {
                deletedActorStateIds.Add(a.Id);
            }

            foreach (var a in frame.ActorStates.Where(x => x.State == ActorStateState.New))
            {
                var actorState = new ActorStateJson();
                actorState.Id = a.Id;
                actorState.UnknownBit = a.Unknown1;
                actorState.TypeName = a.TypeName;
                actorState.ClassName = a.ClassName;
                actorState.InitialPosition = a.Position;
                actorState.Properties = new List<ActorStateProperty>();
                newActorStates.Add(actorState);
            }

            foreach (var a in frame.ActorStates.Where(x => x.State == ActorStateState.Existing))
            {
                var actorState = new ActorStateJson();
                actorState.Id = a.Id;
                actorState.Properties = new List<ActorStateProperty>();

                actorState.Properties = a.Properties.Select(p => new ActorStateProperty { Name = p.PropertyName, Data = p.Data }).ToList();

                updatedActorStates.Add(actorState);
            }

            Dictionary<string, object> result = new Dictionary<string, object>();
            result["Time"] = frame.Time;
            result["DeletedActorIds"] = deletedActorStateIds;
            result["NewActors"] = newActorStates;
            result["UpdatedActors"] = updatedActorStates;
            return result;
        }