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);
            }
        }
Пример #2
0
        private void SerializePretty(JsonWriter writer, Frame frame, Newtonsoft.Json.JsonSerializer 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);
            }

            // It doesn't make a lot of sense to keep new and updated actor data separate
            // since every "new" actor has a corresponding "update" with the actual properties.
            // So for the "pretty" JSON I'm putting them all in the "ActorUpdates" property.
            // New actors will have type, class, and initial position data in addition to all of their properties.

            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.NameId          = a.NameId;
                    actorState.UnknownBit      = a.Unknown1;
                    actorState.TypeId          = a.TypeId;
                    actorState.ClassId         = a.ClassId;
                    actorState.InitialPosition = a.Position;

                    _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;

                    // 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.Values)
                {
                    ActorStateProperty existingProperty;
                    if (!existingActorState.Properties.TryGetValue(p.PropertyId, out existingProperty))
                    {
                        // new property
                        actorState.Properties[p.PropertyId]         = p;
                        existingActorState.Properties[p.PropertyId] = p;
                    }
                    else
                    {
                        // Existing property.
                        var compareResult = DeepCompare.Compare(existingProperty, p);
                        if (!compareResult.AreEqual)  // Only keep if it is truly different
                        {
                            actorState.Properties.Add(p.PropertyId, p);

                            // replace the property in our main set of data, so we have it for the next frame
                            existingActorState.Properties[p.PropertyId] = p;
                        }
                    }
                }

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

            // If theres no property changes the frame is useless, so dont bother writing it
            if (deletedActorStateIds.Any() || updatedActorStates.Any())
            {
                writer.WriteStartObject();
                writer.WriteKeyValue("Time", frame.Time, serializer);
                writer.WriteKeyValue("Delta", frame.Delta, serializer);
                writer.WriteKeyValue("DeletedActorIds", deletedActorStateIds, serializer);
                writer.WriteKeyValue("ActorUpdates", updatedActorStates.Values, serializer);
                writer.WriteEndObject();
            }
        }
        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;
            }
        }