/// <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));
        }
示例#2
0
        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);
        }