Example #1
0
        private static void DoSaveFile(bool auto = false)
        {
            if (Player.Self == null || Module <Player> .Self == null || Module <Player> .Self.actor == null)
            {
                return;
            }

            string path = GetSavesPath();

            Dbgl($"Checking directory {path}");

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            if (!Directory.Exists(path))
            {
                Dbgl($"Directory {path} does not exist and could not be created!");
                return;
            }

            isSaving = true;


            Dbgl("Building save file");

            SummaryPlayerIdentity curPlayerIdentity = Module <SummaryModule> .Self.GetCurPlayerIdentity();

            DateTime now           = DateTime.Now;
            TimeSpan totalPlayTime = Module <SummaryModule> .Self.GetTotalPlayTime();

            GameDateTime dateTime = Module <TimeManager> .Self.DateTime;
            //Dbgl("Building base name");
            string fileName = (string)Singleton <Archive> .Instance.GetType().GetMethod("GenSaveFileName", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(Singleton <Archive> .Instance, new object[] { curPlayerIdentity, now, dateTime, totalPlayTime });

            //Dbgl(fileName);
            string name = Module <Player> .Self.ActorName;
            //Dbgl(name);
            string timeOfDay = $"{dateTime.Hour}h{dateTime.Minute}m";
            //Dbgl(timeOfDay);
            string sceneName = Module <ScenarioModule> .Self.CurrentScenarioName;
            //Dbgl(sceneName);
            string position = Module <Player> .Self.GamePos.ToString("F4").Trim(new char[] { '(', ')' });

            fileName = $"{name}_{fileName}_{timeOfDay}_{sceneName}_{position}{(auto?"_auto":"")}";
            //Dbgl(fileName);
            string filePath = Path.Combine(path, fileName);

            // meta file

            Quaternion playerRot = Player.Self.GameRot;

            List <NPCMeta> npcs = new List <NPCMeta>();

            foreach (NpcData data in Module <NpcRepository> .Self.NpcInstanceDatas)
            {
                int   instanceId = data.id;
                Actor actor      = Module <ActorMgr> .Self.Get(instanceId);

                if (actor == null)
                {
                    continue;
                }
                string  scene = actor.SceneName;
                string  pos   = actor.gamePos.ToString().Trim(new char[] { '(', ')' });
                NPCMeta npc   = new NPCMeta();
                npc.id    = instanceId;
                npc.scene = scene;
                npc.pos   = pos;
                npcs.Add(npc);
            }
            List <RideableMeta> rideables = new List <RideableMeta>();

            foreach (int uid in Module <RidableModuleManager> .Self.GetAllRidableUid())
            {
                IRidable r = Module <RidableModuleManager> .Self.GetRidable(uid);

                if (r == null)
                {
                    continue;
                }
                string       pos      = r.GetPos().ToString().Trim(new char[] { '(', ')' });
                RideableMeta rideable = new RideableMeta
                {
                    id    = uid,
                    pos   = pos,
                    state = r.GetRidableState().ToString()
                };
                rideables.Add(rideable);
            }

            List <StoreMeta> stores = new List <StoreMeta>();

            foreach (Store store in AccessTools.FieldRefAccess <StoreManagerV40, List <Store> >(Module <StoreManagerV40> .Self, "storeList"))
            {
                stores.Add(new StoreMeta()
                {
                    id           = store.id,
                    money        = store.ownMoney,
                    recycleCount = store.recycleCount
                });
            }


            SaveMeta save = new SaveMeta();

            save.playerRot           = playerRot.ToString();
            save.NPClist             = npcs;
            save.RideableList        = rideables;
            save.StoreList           = stores;
            save.FishBowlConsumeHour = (int)typeof(FishBowl).GetField("consumeHour", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
            save.WeatherState        = (int)Module <WeatherModule> .Self.CurWeatherState;
            save.CurPriceIndex       = Module <StoreManagerV40> .Self.CurPriceIndex;

            System.Xml.Serialization.XmlSerializer writer = new System.Xml.Serialization.XmlSerializer(typeof(SaveMeta));


            Dbgl("Saving file " + filePath);

            Singleton <Archive> .Instance.SaveArchive(filePath);

            var        path2 = Path.Combine(GetSavesPath(), $"{fileName}.xml");
            FileStream file  = File.Create(path2);

            writer.Serialize(file, save);
            file.Close();

            if (auto)
            {
                Dbgl("Getting old autosaves");
                string createPlayerTime = (string)Singleton <Archive> .Instance.GetType().GetMethod("GenDateFilename", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(Singleton <Archive> .Instance, new object[] { curPlayerIdentity.createPlayerTime });

                List <string> autoFiles = new List <string>();
                foreach (CustomSaveFile csf in saveFiles)
                {
                    if (csf.auto && createPlayerTime == csf.creationTime)
                    {
                        autoFiles.Add(Path.Combine(GetSavesPath(), $"{csf.fileName}"));
                    }
                }
                int del = 0;
                while (autoFiles.Count - del >= settings.maxAutoSaves)
                {
                    File.Delete(autoFiles[del]);
                    File.Delete(autoFiles[del] + ".xml");
                    del++;
                }
            }

            DoBuildSaveList();
            isSaving = false;
            resetLastSave();
        }
        private static void OnSceneLoaded(ScenarioModule.Arg arg)
        {
            Module <ScenarioModule> .Self.EndLoadEventor -= OnSceneLoaded;
            if (!isLoading)
            {
                return;
            }

            Module <Player> .Self.GamePos = VectorFromString(lastLoadedSave.position);

            Dbgl("input solution: " + Module <InputSolutionModule> .Self.CurSolutionType + "");
            Module <InputSolutionModule> .Self.Pop();

            Module <InputSolutionModule> .Self.Push(SolutionType.Gaming);


            //Module<SleepModule>.Self.GetType().GetMethod("PlayerWakeUpAfterArchive", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(Module<SleepModule>.Self, new object[] { });

            //Module<SleepModule>.Self.GetType().GetMethod("ShowSleepMask", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(Module<SleepModule>.Self, new object[] { false });
            //MessageManager.Instance.Dispatch("WakeUpScreen", null, DispatchType.IMME, 2f);

            //Module<SleepModule>.Self.WakeUpScreenMaskFinishedEvent?.Invoke();

            Singleton <SleepTipMgr> .Self.SleepState(false);

            Dbgl("Checking DLC");

            // stuff that needs to be recreated after save

            GameDLCRewardsModule.Self.GetType().GetMethod("CheckAndOpenAllDlc", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(Module <GameDLCRewardsModule> .Self, new object[] { });

            Dbgl("Checking Engagement");

            if (Module <EGMgr> .Self.IsEngagement())
            {
                Dbgl("Engagement is active");
                EGDate       date      = AccessTools.FieldRefAccess <EGMgr, EGDate>(Module <EGMgr> .Self, "mDate");
                GameDateTime dateBegin = AccessTools.FieldRefAccess <EGDate, GameDateTime>(date, "mBeginTimer");
                if (Module <TimeManager> .Self.DateTime > dateBegin)
                {
                    date.GetType().GetMethod("InitProjectMap", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(date, new object[] { });
                    Actor mActor = AccessTools.FieldRefAccess <EGDate, Actor>(date, "mActor");
                    AccessTools.FieldRefAccess <EGDate, Actor>(date, "mActor").SetBehaviorValue("EGActor", Module <Player> .Self.actor);
                    AccessTools.FieldRefAccess <EGDate, Actor>(date, "mActor").SetBehaviorValue("EGDate", EGData.GetDatePlace(AccessTools.FieldRefAccess <EGDate, int>(date, "mDateID")));
                    AccessTools.FieldRefAccess <EGDate, SharedInt>(date, "mForceValue")     = mActor.GetBehaviorVariable <SharedInt>("EGForce");
                    AccessTools.FieldRefAccess <EGDate, SharedInt>(date, "mMoodValue")      = mActor.GetBehaviorVariable <SharedInt>("EGMood");
                    AccessTools.FieldRefAccess <EGDate, SharedIntList>(date, "mEventCount") = mActor.GetBehaviorVariable <SharedIntList>("EGEventIDs");
                    AccessTools.FieldRefAccess <EGDate, List <EGRoot> >(date, "mRoots")     = mActor.behavior.FindTasks <EGRoot>();
                    date.Start();
                    Dbgl("Engagement starts with " + mActor.ActorName);
                }
                else if (Module <TimeManager> .Self.DateTime > dateBegin - EGConst.Spawn_Hour_1)
                {
                    Dbgl("Less than one hour before engagement starts!");
                    date.GetType().GetMethod("InitProjectMap", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(date, new object[] { });
                    Actor mActor = AccessTools.FieldRefAccess <EGDate, Actor>(date, "mActor");
                    AccessTools.FieldRefAccess <EGDate, Actor>(date, "mActor").SetBehaviorValue("EGActor", Module <Player> .Self.actor);
                    AccessTools.FieldRefAccess <EGDate, Actor>(date, "mActor").SetBehaviorValue("EGDate", EGData.GetDatePlace(AccessTools.FieldRefAccess <EGDate, int>(date, "mDateID")));
                    AccessTools.FieldRefAccess <EGDate, SharedInt>(date, "mForceValue")     = mActor.GetBehaviorVariable <SharedInt>("EGForce");
                    AccessTools.FieldRefAccess <EGDate, SharedInt>(date, "mMoodValue")      = mActor.GetBehaviorVariable <SharedInt>("EGMood");
                    AccessTools.FieldRefAccess <EGDate, SharedIntList>(date, "mEventCount") = mActor.GetBehaviorVariable <SharedIntList>("EGEventIDs");
                    AccessTools.FieldRefAccess <EGDate, List <EGRoot> >(date, "mRoots")     = mActor.behavior.FindTasks <EGRoot>();
                    Singleton <TipsMgr> .Instance.SendSystemTip(string.Format(TextMgr.GetStr(100507, -1), TextMgr.GetStr(AccessTools.FieldRefAccess <EGDate, int>(date, "mTipTypeID"), -1)), SystemTipType.warning);
                }
                else if (Module <TimeManager> .Self.DateTime > dateBegin - EGConst.Spawn_Hour_2)
                {
                    Dbgl("Less than two hours hour before engagement starts!");
                    date.GetType().GetMethod("InitProjectMap", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(date, new object[] { });
                    Actor mActor = AccessTools.FieldRefAccess <EGDate, Actor>(date, "mActor");
                    AccessTools.FieldRefAccess <EGDate, Actor>(date, "mActor").SetBehaviorValue("EGActor", Module <Player> .Self.actor);
                    AccessTools.FieldRefAccess <EGDate, Actor>(date, "mActor").SetBehaviorValue("EGDate", EGData.GetDatePlace(AccessTools.FieldRefAccess <EGDate, int>(date, "mDateID")));
                    AccessTools.FieldRefAccess <EGDate, SharedInt>(date, "mForceValue")     = mActor.GetBehaviorVariable <SharedInt>("EGForce");
                    AccessTools.FieldRefAccess <EGDate, SharedInt>(date, "mMoodValue")      = mActor.GetBehaviorVariable <SharedInt>("EGMood");
                    AccessTools.FieldRefAccess <EGDate, SharedIntList>(date, "mEventCount") = mActor.GetBehaviorVariable <SharedIntList>("EGEventIDs");
                    AccessTools.FieldRefAccess <EGDate, List <EGRoot> >(date, "mRoots")     = mActor.behavior.FindTasks <EGRoot>();
                    Singleton <TipsMgr> .Instance.SendSystemTip(string.Format(TextMgr.GetStr(100506, -1), TextMgr.GetStr(AccessTools.FieldRefAccess <EGDate, int>(date, "mTipTypeID"), -1)), SystemTipType.warning);
                }
            }

            if (arg.IsMain)
            {
                Dbgl("Checking Ridables");
                Module <FarmModule> .Self.ForeachUnit(delegate(Unit unit, bool isFloor)
                {
                    if (unit != null && unit is RidableTamingUnit)
                    {
                        RidableTamingUnit ru            = unit as RidableTamingUnit;
                        GameObject unitGameObjectByUnit = Module <FarmModule> .Self.GetUnitGameObjectByUnit(unit);
                        if (unitGameObjectByUnit == null)
                        {
                            return;
                        }
                        RidableTamingUnitViewer uv = (RidableTamingUnitViewer)unitGameObjectByUnit.GetComponentInChildren <UnitViewer>();

                        AccessTools.FieldRefAccess <RidableTamingUnitViewer, List <IRidable> >(uv, "ridableList").Clear();

                        typeof(RidableTamingUnitViewer).GetMethod("CreateShit", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(uv, new object[] { });
                        typeof(RidableTamingUnitViewer).GetMethod("CreateAllWorkableRidable", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(uv as RidableTamingUnitViewer, new object[] { });
                        typeof(RidableTamingUnitViewer).GetMethod("UpdateAllRidableInfo", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(uv as RidableTamingUnitViewer, new object[] { });
                    }
                });

                typeof(RidableModuleManager).GetMethod("InitIdGenerator", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(Module <RidableModuleManager> .Self, new object[] { });

                Dictionary <int, RidableTransactionSaveData> rideDic = AccessTools.FieldRefAccess <RidableModuleManager, Dictionary <int, RidableTransactionSaveData> >(Module <RidableModuleManager> .Self, "ridableTransactionDataDic");
                int[] rideKeys = new int[rideDic.Count];
                rideDic.Keys.CopyTo(rideKeys, 0);
                foreach (int key in rideKeys)
                {
                    if (rideDic[key].RidableSource == RidableSource.NPC)
                    {
                        AccessTools.FieldRefAccess <RidableModuleManager, Dictionary <int, RidableTransactionSaveData> >(Module <RidableModuleManager> .Self, "ridableTransactionDataDic").Remove(key);
                    }
                }

                Scene sceneByName = SceneManager.GetSceneByName(arg.scenarioName);
                if (sceneByName.IsValid() && sceneByName.isLoaded)
                {
                    GameObject[] gos = sceneByName.GetRootGameObjects();
                    foreach (GameObject go in gos)
                    {
                        Component co = go.GetComponentInChildren(typeof(NpcsRidableManager));
                        if (co != null)
                        {
                            Dbgl("Got NpcsRidableManager");
                            (co as NpcsRidableManager).DestoryAllRidable();
                            AccessTools.FieldRefAccess <RidableFences, Dictionary <IRidable, RidableFence> >((co as NpcsRidableManager), "ridableDic").Clear();
                            typeof(NpcsRidableManager).GetMethod("AfterPlayerWakeUpEvent", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(co as NpcsRidableManager, new object[] { });
                        }
                    }
                }
            }

            Dbgl("Checking wishes");
            AccessTools.FieldRefAccess <DynamicWishManager, List <int> >(Module <DynamicWishManager> .Self, "hasTalkToday").AddRange(from it in AccessTools.FieldRefAccess <DynamicWishManager, List <DoubleInt> >(Module <DynamicWishManager> .Self, "curWishData") select it.id0);

            //Module<RidableModuleManager>.Self.InitNpcRidableBehaviourValue();

            // stuff that needs to be carried over but isnt, use meta file

            Dbgl("Loading Meta");
            string filePath = Path.Combine(GetSavesPath(), $"{lastLoadedSave.fileName}.xml");

            try
            {
                System.Xml.Serialization.XmlSerializer reader = new System.Xml.Serialization.XmlSerializer(typeof(SaveMeta));
                StreamReader file = new StreamReader($"{filePath}");
                SaveMeta     save = (SaveMeta)reader.Deserialize(file);
                file.Close();

                Dbgl("Loading Player Meta");

                if (save.playerRot != null)
                {
                    string[]   rotStrings = save.playerRot.Replace("(", "").Replace(")", "").Replace(" ", "").Split(',');
                    Quaternion rot        = new Quaternion(float.Parse(rotStrings[0]), float.Parse(rotStrings[1]), float.Parse(rotStrings[2]), float.Parse(rotStrings[3]));
                    Player.Self.GameRot = rot;
                }

                Dbgl("Loading NPC Meta");

                foreach (NPCMeta npc in save.NPClist)
                {
                    Actor actor = Module <ActorMgr> .Self.Get(npc.id);

                    if (actor != null)
                    {
                        Module <ActorMgr> .Self.MoveToScenario(actor, npc.scene, VectorFromString(npc.pos));
                    }
                }

                Dbgl("Loading Ridable Meta");

                if (save.RideableList != null)
                {
                    foreach (RideableMeta r in save.RideableList)
                    {
                        IRidable rideable = Module <RidableModuleManager> .Self.GetRidable(r.id);

                        if (rideable == null)
                        {
                            Dbgl("null rideable " + r.id);

                            rideable = Module <RidableModuleManager> .Self.GetRidable(r.id);

                            continue;
                        }
                        Dbgl("got rideable " + r.id);
                        Actor actor = rideable.GetActor();
                        if (actor != null)
                        {
                            Dbgl("got rideable actor for " + rideable.GetNickName());
                            actor.gamePos = VectorFromString(r.pos);
                            actor.RefreshPos();
                        }
                        switch (r.state)
                        {
                        case "None":
                            rideable.SetRidableState(RidableState.None);
                            break;

                        case "Idle":
                            rideable.SetRidableState(RidableState.Idle);
                            break;

                        case "Ride":
                            if (rideable.BelongToPlayer)
                            {
                                int otherNPCID = Module <EGMgr> .Self.GetEngagementStartNpcID();

                                if (RideUtils.TestRideWithNpcID > 0)
                                {
                                    otherNPCID = RideUtils.TestRideWithNpcID;
                                    RideUtils.TestRideWithNpcID = -1;
                                }
                                Module <Player> .Self.RideRidable(rideable, otherNPCID);
                            }
                            else if (rideable.GetBelongRider() is ActorRiderAdapter)
                            {
                                Actor          belongActor    = (rideable.GetBelongRider() as ActorRiderAdapter).actor;
                                RideController rideController = belongActor.RideController;
                                rideController.RideOn(rideable);
                            }
                            break;

                        case "Follow":
                            rideable.SetRidableState(RidableState.Follow);
                            break;

                        case "Stay":
                            rideable.SetRidableState(RidableState.Stay);
                            break;
                        }
                    }
                }

                Dbgl("Loading Fishbowl Meta");

                if (save.FishBowlConsumeHour != -1)
                {
                    typeof(FishBowl).GetField("consumeHour", BindingFlags.NonPublic | BindingFlags.Static).SetValue(Module <FishBowl> .Self, save.FishBowlConsumeHour);
                }

                Dbgl("Loading Store Meta");

                AccessTools.FieldRefAccess <StoreManagerV40, float>(Module <StoreManagerV40> .Self, "curPriceIndex") = save.CurPriceIndex;

                if (save.StoreList != null)
                {
                    foreach (StoreMeta sMeta in save.StoreList)
                    {
                        Module <StoreManagerV40> .Self.GetStore(sMeta.id).recycleCount = sMeta.recycleCount;

                        Module <StoreManagerV40> .Self.GetStore(sMeta.id).ownMoney = sMeta.money;
                    }
                }

                Dbgl("Loading Weather Meta");

                if (save.WeatherState != -1)
                {
                    AccessTools.FieldRefAccess <WeatherModule, WeatherCtr>(Module <WeatherModule> .Self, "weatherCtr").SetWeather((WeatherState)save.WeatherState);
                }
            }
            catch (Exception ex)
            {
                Dbgl("Problem with meta file: " + ex);
            }
            isLoading = false;
            resetLastSave();
        }