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); } }
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; } }