/// <summary> /// manipulate the given savefile by setting the value at the given path /// </summary> /// <param name="save">The save to manipulate</param> /// <param name="Runtime">True if the following Id is runtime, false if it is a scene id</param> /// <param name="ObjectIdentifier">The Id of the object to find</param> /// <param name="ComponentIdentifier">The Identifier of the Component from which this field will be saved</param> /// <param name="FieldName">The Name of the Field from which the value was extracted</param> /// <param name="Value">The Value to save. Must derive from JSSerializable</param> public bool SaveValue(Save save, bool Runtime, string ObjectIdentifier, string ComponentIdentifier, string FieldName, JSSerializable Value) { JSDictionary <JSSerializable> ToSave = Runtime ? save.Runtime : save.Static; //following the path through the Savefile, creating additional Entries if necessary, then adding or replacing the value to the field name return(((JSDictionary <JSSerializable>)(((JSDictionary <JSSerializable>)(ToSave.GetOrCreateValueByKey(ObjectIdentifier))) .GetOrCreateValueByKey(ComponentIdentifier))).AddOrReplaceValueByKey(FieldName, Value)); }
public Save() { Savedata = new JSDictionary <JSDictionary <JSSerializable> >(); //this Dictionary will store all the information, about where pooled objects have been spawned Savedata.AddOrReplaceValueByKey("Runtime", new JSDictionary <JSSerializable>()); Runtime = Savedata.GetValueByKey("Runtime"); //this Dictionary will store all the object-specific information, it will get the fields marked "autosave" and map them to an object identifier Savedata.AddOrReplaceValueByKey("Static", new JSDictionary <JSSerializable>()); Static = Savedata.GetValueByKey("Static"); }
/// <summary> /// Interprets a given save and applies the data to the Application /// </summary> /// <param name="source">The save to interpret</param> /// <returns>True if the method reached the end of the calculation without fatal errors</returns> public bool InterpretSave(Save source) { List <int> arrayList = new List <int>(); //getting references to spawning and autosaves JSDictionary <JSSerializable> Runtime = source.Runtime; JSDictionary <JSSerializable> Static = source.Static; //use this dictionary to remember once scanned classes for later use Dictionary <Type, FieldInfo[]> RememberedFields = new Dictionary <Type, FieldInfo[]>(); //preparing references and despawning runtime objects JustSaveId[] JSManagedObjects = UnityEngine.Object.FindObjectsOfType <JustSaveId>(); List <JustSaveSceneId> JSManagedSceneObjects = new List <JustSaveSceneId>(); foreach (JustSaveId JustSaveManagedObject in JSManagedObjects) { if (JustSaveManagedObject is JustSaveRuntimeId) { ((JustSaveRuntimeId)JustSaveManagedObject).Despawn(); //despawns every runtime object } else { JSManagedSceneObjects.Add((JustSaveSceneId)JustSaveManagedObject); //saves every scene object reference } } if (Dbug.Is(DebugMode.DEBUG)) { Debug.Log("Save Interpreter despawned old runtime objects"); } //loading scene objects foreach (JustSaveSceneId IdObj in JSManagedSceneObjects) { SyncObject(source, false, IdObj, RememberedFields); } if (Dbug.Is(DebugMode.DEBUG)) { Debug.Log("Save Interpreter synced scene objects"); } //iterating through spawned objects string[] idInfo = new string[2]; foreach (Tuple <String, JSSerializable> RuntimeObjectInfo in Runtime.GetValuePairs()) { idInfo = RuntimeObjectInfo.Item1.Split('_'); GameObject spawnedPrefab = JustSaveManager.Instance.Spawn(idInfo[0], Vector3.zero); JustSaveRuntimeId spawnedIdObj = spawnedPrefab.GetComponent <JustSaveRuntimeId>(); spawnedIdObj.SetId(Guid.Parse(idInfo[1])); SyncObject(source, true, spawnedPrefab.GetComponent <JustSaveRuntimeId>(), RememberedFields); } if (Dbug.Is(DebugMode.DEBUG)) { Debug.Log("Save Interpreter spawned and synced runtime objects"); Debug.Log("Save Interpreter finished loading Save"); } return(true); }
/// <summary> /// assembles a new JustSave.Save from the current application and returns this Save. /// </summary> /// <returns>the assembled Save</returns> /// public Save GetCurrentSave() { Save newSave = new Save(); int OverwriteCounter = 0; //use this dictionary to remember once scanned classes for later use Dictionary <Type, FieldInfo[]> RememberedFields = new Dictionary <Type, FieldInfo[]>(); //getting references to spawning and autosaves JSDictionary <JSSerializable> Runtime = newSave.Runtime; JSDictionary <JSSerializable> Static = newSave.Static; JustSaveId[] JSManagedObjects = UnityEngine.Object.FindObjectsOfType <JustSaveId>(); bool IsRuntime; foreach (JustSaveId IdObj in JSManagedObjects) { //its either a JustSaveRuntime Id if (IdObj is JustSaveRuntimeId) { IsRuntime = true; } //or a SceneId else { IsRuntime = false; } GameObject Search = IdObj.gameObject; Component[] Components = Search.GetComponentsInChildren <Component>(); List <Attribute> Attributes = new List <Attribute>(); FieldInfo[] FieldInfos; //getting the attributes foreach (Component m_Comp in Components) { //calling JSOnSave on every class implementing the ISavable interface if (m_Comp is ISavable) { ((ISavable)m_Comp).JSOnSave(); } if (!RememberedFields.TryGetValue(m_Comp.GetType(), out FieldInfos)) { FieldInfos = m_Comp.GetType().GetFields(); RememberedFields.Add(m_Comp.GetType(), FieldInfos); } foreach (FieldInfo Field in FieldInfos) { if (Attribute.IsDefined(Field, typeof(Autosaved))) { Type AutosaveFieldType = Field.FieldType; // already serializable Types if (AutosaveFieldType.IsSerializable) { if (!(SaveValue(newSave, IsRuntime, IdObj.GetSaveIdentifier(), m_Comp.GetType().Name, Field.Name, JSBasic.GetFromObject(Field.GetValue(m_Comp))))) { OverwriteCounter++; } } // support for unitys vector-types else if (AutosaveFieldType == typeof(Vector2)) { if (!(SaveValue(newSave, IsRuntime, IdObj.GetSaveIdentifier(), m_Comp.GetType().Name, Field.Name, JSNTuple.GetFromVector2((Vector2)Field.GetValue(m_Comp))))) { OverwriteCounter++; } } else if (AutosaveFieldType == typeof(Vector3)) { if (!(SaveValue(newSave, IsRuntime, IdObj.GetSaveIdentifier(), m_Comp.GetType().Name, Field.Name, JSNTuple.GetFromVector3((Vector3)Field.GetValue(m_Comp))))) { OverwriteCounter++; } } else if (AutosaveFieldType == typeof(Vector4)) { if (!(SaveValue(newSave, IsRuntime, IdObj.GetSaveIdentifier(), m_Comp.GetType().Name, Field.Name, JSNTuple.GetFromVector4((Vector4)Field.GetValue(m_Comp))))) { OverwriteCounter++; } } else if (AutosaveFieldType == typeof(Quaternion)) { if (!(SaveValue(newSave, IsRuntime, IdObj.GetSaveIdentifier(), m_Comp.GetType().Name, Field.Name, JSNTuple.GetFromQuaternion((Quaternion)Field.GetValue(m_Comp))))) { OverwriteCounter++; } } // no support else { if (Dbug.Is(DebugMode.WARN)) { Debug.LogWarning("Field " + Field.Name + " of Type " + AutosaveFieldType.Name + " is not serializable and will be skipped."); } } } } } } if (Dbug.Is(DebugMode.DEBUG)) { Debug.Log("______Assembled Save______"); Debug.Log(newSave.ToString()); Debug.Log("__________________________"); Debug.Log("______Short Form Save______"); Debug.Log(newSave.ToShortString()); Debug.Log("__________________________"); Debug.Log("Scanned a total of " + RememberedFields.Keys.Count + " different classes."); Debug.Log("Overwritten: " + OverwriteCounter + " Fields. Perfect!"); } if (OverwriteCounter > 0 && Dbug.Is(DebugMode.WARN)) { Debug.LogWarning("Overwritten: " + OverwriteCounter + " Fields. You should look into this."); } return(newSave); }