public Hypervisor() { if (RulesManager.Instance == null) { ModConsole.LogError("[MOP] Rule Files haven't been loaded! Please exit to the main menu and start the game again."); return; } MopSettings.LoadedOnce = true; loadScreen = gameObject.AddComponent <LoadScreen>(); loadScreen.Activate(); loadScreenWorkaround = InfiniteLoadscreenWorkaround(); StartCoroutine(loadScreenWorkaround); playerController = GameObject.Find("PLAYER").GetComponent <CharacterController>(); playerController.enabled = false; FsmManager.PlayerInMenu = true; // Disable rule files if user wants it. if (!RulesManager.Instance.LoadRules) { RulesManager.Instance.Unload(); } ExceptionManager.SessionTimeStart = DateTime.Now; // Start the delayed initialization routine StartCoroutine(DelayedInitializaitonRoutine()); }
/// <summary> /// Every 10 seconds check if the coroutine is still active. /// If not, try to restart it. /// It is checked by two values - ticks and lastTick /// Ticks are added by coroutine. If the value is different than the lastTick, everything is okay. /// If the ticks and lastTick is the same, that means coroutine stopped. /// </summary> /// <returns></returns> IEnumerator ControlCoroutine() { while (MopSettings.IsModActive) { yield return(new WaitForSeconds(10)); if (lastTick == ticks) { if (retries >= MaxRetries) { ModConsole.LogError("[MOP] Restart attempt failed. Enabling Safe Mode."); ModConsole.LogError("[MOP] Please contact mod developer. Make sure you send output_log and last MOP crash log!"); try { ToggleAll(true); } catch { } MopSettings.EnableSafeMode(); yield break; } retries++; restartSucceedMessaged = false; ModConsole.LogWarning($"[MOP] MOP has stopped working! Restart attempt {retries}/{MaxRetries}..."); StopCoroutine(currentLoop); currentLoop = LoopRoutine(); StartCoroutine(currentLoop); } else { lastTick = ticks; } } }
IEnumerator InfiniteLoadscreenWorkaround() { yield return(new WaitForSeconds(20)); if (FsmManager.PlayerInMenu) { ModConsole.LogError("[MOP] MOP failed to load in time. Please go into MOP settings and use \"I found a bug\" button."); FinishLoading(); } }
/// <summary> /// Creates then new error dump file /// </summary> /// <param name="ex"></param> public static void New(Exception ex, bool isCritical, string message) { // Don't save errors that already occured. if (erorrsContainer.Contains(message)) { return; } string fileName = $"{DefaultErrorLogName}_{DateTime.Now:yyyy-MM-dd-HH-mm}"; if (File.Exists($"{LogFolder}/{fileName}.txt")) { int crashesInFolder = 0; while (File.Exists($"{LogFolder}/{fileName}_{crashesInFolder}.txt")) { crashesInFolder++; } fileName += $"_{crashesInFolder}"; } string logFilePath = $"{LogFolder}/{fileName}.txt"; string gameInfo = GetGameInfo(); string errorInfo = $"{ex.Message}\n{ex.StackTrace}\nTarget Site: {ex.TargetSite}"; using (StreamWriter sw = new StreamWriter(logFilePath)) { sw.Write($"{gameInfo}\n=== ERROR ===\n\n// " + $"{WittyComments.GetErrorWittyText()}\n\n" + $"{message}{(message.Length > 0 ? "\n\n" : "")}" + $"{errorInfo}"); } string errorMessage = $"[MOP] An error has occured. Log has been saved into My Summer Car folder into:\n\n{logFilePath}.\n\n" + $"Please go into MOP Settings and click \"<b>I found a bug</b>\" button, in order to generate bug report and then follow the instructions.\n"; if (isCritical) { ModConsole.LogError(errorMessage); } else { ModConsole.LogWarning(errorMessage + "\nYou can continue playing."); } erorrsContainer.Add(message); }
/// <summary> /// Reands and parses the string to Vector3. /// </summary> /// <param name="s"></param> /// <returns></returns> Vector3 ParseToVector3(string s) { try { float x, y, z; string[] split = s.Split(','); x = float.Parse(split[0]); y = float.Parse(split[1]); z = float.Parse(split[2]); return(new Vector3(x, y, z)); } catch { ModConsole.LogError($"[MOP] Incorrect vector format! Refer to MOP wiki."); return(Vector3.zero); } }
internal void Initialize() { try { instance = this; fpsMesh = GameObject.Find("GUI").transform.Find("HUD/FPS/HUDValue").GetComponent <TextMesh>(); if (samples == null) { samples = new List <float>(); } currentFrameRateWait = FrameWait(); StartCoroutine(currentFrameRateWait); } catch (Exception ex) { ModConsole.LogError(ex.ToString()); } }
// You know the rules and so do I // A full commitment's what I'm thinking of // You wouldn't get this from any other guy // I just wanna tell you how I'm feeling // Gotta make you understand // Never gonna give you up // Never gonna let you down // Never gonna run around and desert you // Never gonna make you cry // Never gonna say goodbye // Never gonna tell a lie and hurt you void ReadRulesFromFile(string rulePath) { try { string[] content = File.ReadAllLines(rulePath).Where(s => s.Length > 0 && !s.StartsWith("##")).ToArray(); string fileName = Path.GetFileName(rulePath); int lines = File.ReadAllLines(rulePath).Where(s => s.StartsWith("##")).ToArray().Length; int currentLine = 0; foreach (string s in content) { lines++; currentLine++; string[] splitted = s.Split(':'); // Read flag and rules. string flag = splitted[0]; string[] objects = new string[0]; if (splitted.Length > 1) { // Support for object names that have space in it, using quotation mark, instead of using %20. if (splitted[1].Contains("\"")) { // Check if there is an odd number of quotation marks. if (splitted[1].Count(f => f == '\"') % 2 != 0) { ModConsole.LogError($"[MOP] Quote hasn't been closed properly: {s} in rule file {fileName}({lines})."); continue; } splitted[1] = Regex.Match(splitted[1], "\"[^\"]*\"").Value.Replace(" ", "%20").Replace("\"", ""); } // Split all objects with space char. objects = splitted[1].Trim().Split(' '); // Replace the %20 in object names to space. for (int i = 0; i < objects.Length; i++) { objects[i] = objects[i].Replace("%20", " "); } } if (objects.Length > 0 && objects.ContainsAny(illegalValues)) { ModConsole.LogError($"[MOP] Illegal object: {objects[0]} in rule file {fileName}."); continue; } // Apply these rules switch (flag) { default: ModConsole.LogError($"[MOP] Unrecognized flag '{flag}' in {fileName} ({lines})."); break; case "ignore": // Ignore at place bool fullIgnore = false; if (objects.Length > 1) { if (objects[1].ToLower() == "fullignore") { fullIgnore = true; } else { RulesManager.Instance.IgnoreRulesAtPlaces.Add(new IgnoreRuleAtPlace(objects[0], objects[1])); break; } } // Disabling some of the root object is pointless, so we inform abot that the user. RulesManager.Instance.IgnoreRules.Add(new IgnoreRule(objects[0], fullIgnore)); break; case "ignore_full": ObsoleteWarning(flag, fileName, lines, s, "ignore: <object_name> fullIgnore"); RulesManager.Instance.IgnoreRules.Add(new IgnoreRule(objects[0], true)); break; case "toggle": ToggleModes mode = ToggleModes.Simple; if (objects.Length > 1) { switch (objects[1]) { default: ModConsole.LogError($"[MOP] Unrecognized method '{objects[1]}' in {fileName} ({lines})."); break; case "renderer": mode = ToggleModes.Renderer; break; case "item": mode = ToggleModes.Item; break; case "vehicle": mode = ToggleModes.Vehicle; break; case "vehicle_physics": mode = ToggleModes.VehiclePhysics; break; } } RulesManager.Instance.ToggleRules.Add(new ToggleRule(objects[0], mode)); break; case "satsuma_ignore_renderer": RulesManager.Instance.SpecialRules.SatsumaIgnoreRenderers = true; break; case "dont_destroy_empty_beer_bottles": ObsoleteWarning(flag, fileName, lines, s, "dont_destroy_empty_bottles"); RulesManager.Instance.SpecialRules.DontDestroyEmptyBeerBottles = true; break; case "dont_destroy_empty_bottles": RulesManager.Instance.SpecialRules.DontDestroyEmptyBeerBottles = true; break; case "sector": Vector3 pos = ParseToVector3(objects[0]); Vector3 scale = ParseToVector3(objects[1]); Vector3 rot = ParseToVector3(objects[2]); string[] whitelist = GetWhitelist(objects); RulesManager.Instance.NewSectors.Add(new NewSector(pos, scale, rot, whitelist)); break; case "min_ver": if (fileName == CustomFile) { break; } if (currentLine != 1) { ModConsole.Log($"\n=================================" + $"\n\n<color=cyan>[MOP] Flag '{flag}' must be first in the order!\n\n" + $"File: {fileName}\n" + $"Line: {lines}\n" + $"You can ignore that message.</color>"); } int major, minor, revision = 0; string[] verSplitted = objects[0].Split('.'); major = int.Parse(verSplitted[0]); minor = int.Parse(verSplitted[1]); if (verSplitted.Length == 3) { revision = int.Parse(verSplitted[2]); } int modMajor, modMinor, modRevision = 0; string[] modVersionSpliited = MOP.ModVersionShort.Split('.'); modMajor = int.Parse(modVersionSpliited[0]); modMinor = int.Parse(modVersionSpliited[1]); if (modVersionSpliited.Length == 3) { modRevision = int.Parse(modVersionSpliited[2]); } bool isOutdated = false; if (major > modMajor) { isOutdated = true; } else { if (minor > modMinor && major == modMajor) { isOutdated = true; } else { if (revision > modRevision && minor == modMinor && major == modMajor) { isOutdated = true; } } } if (isOutdated) { ModConsole.LogError($"[MOP] Rule file {fileName} is for the newer version of MOP. Please update MOP right now!\n\n" + $"Your MOP version: {modMajor}.{modMinor}.{modRevision}\n" + $"Required version: {major}.{minor}.{revision}"); return; } break; // Custom.txt exclusives. case "ignore_mod_vehicles": if (fileName != CustomFile) { ModConsole.LogError($"[MOP] Flag: {flag} is only allowed to be used in custom rule file."); continue; } RulesManager.Instance.SpecialRules.IgnoreModVehicles = true; break; case "toggle_all_vehicles_physics_only": if (fileName != CustomFile) { ModConsole.LogError($"[MOP] Flag: {flag} is only allowed to be used in custom rule file."); continue; } RulesManager.Instance.SpecialRules.ToggleAllVehiclesPhysicsOnly = true; break; } } } catch (Exception ex) { ModConsole.LogError($"[MOP] Error loading rule {Path.GetFileName(rulePath)}: {ex}."); NewMessage($"<color=red>MOP: Error loading rule :("); } }
IEnumerator DownloadAndUpdateRoutine() { string lastModList = File.Exists(lastModListPath) ? File.ReadAllText(lastModListPath) : ""; Mod[] mods = ModLoader.LoadedMods.Where(m => !m.ID.ContainsAny("MSCLoader_", "MOP")).ToArray(); string modListString = ""; ModConsole.Log("[MOP] Checking for new mods..."); bool isUpdateTime = !File.Exists(lastDateFilePath) || IsUpdateTime(); if (isUpdateTime) { ModConsole.Log("[MOP] Looking for updates..."); } foreach (Mod mod in mods) { string modId = mod.ID; modListString += $"{modId}\n"; string ruleUrl = $"{RemoteServer}/{modId}{RuleExtension}"; string filePath = $"{MOP.ModConfigPath}/{modId}{RuleExtension}"; // Continue if it's not time for an update, and the mod is in the list of last mods. if (lastModList.Contains(mod.ID) && !isUpdateTime) { continue; } // Check if rule file for mod is on the server. // If not, continue. if (!IsFileOnServer(modId)) { continue; } // Check if the newer file is available on the server. if (!overrideUpdateCheck) { if (serverContent == null) { GetServerContent(); } DateTime lastLocalFileWrite = GetFileWriteTime(filePath); ServerContentData data = serverContent.First(t => t.ID == modId); DateTime lastRemoteFileWrite = data.UpdateTime; if (lastRemoteFileWrite <= lastLocalFileWrite) { ModConsole.Log($"<color=orange>[MOP] Skipping {modId}, because local file and remote file are the same.</color>"); continue; } } // Check if file actually exists on remote server. if (!RemoteFileExists(ruleUrl)) { ModConsole.LogError($"[MOP] Rule file for mod doesn't exist!\nID: {modId}\nURL: {ruleUrl}"); continue; } fileDownloadCompleted = false; using (WebClient web = new WebClient()) { ModConsole.Log($"<color=yellow>[MOP] Downloading new rule file for {mod.Name}...</color>"); NewMessage($"MOP: Downloading new rule file for {mod.Name}..."); #if DEBUG web.Headers.Add("user-agent", $"MOP/{MOP.ModVersion}_DEBUG {ExceptionManager.GetSystemInfo()}"); #else web.Headers.Add("user-agent", $"MOP/{MOP.ModVersion} {ExceptionManager.GetSystemInfo()}"); #endif if (File.Exists(filePath)) { File.Delete(filePath); } web.DownloadFileCompleted += DownloadFileCompleted; web.DownloadFileAsync(new Uri(ruleUrl), filePath); int waitTime = 0; while (!fileDownloadCompleted) { yield return(new WaitForSeconds(.5f)); waitTime++; // If wait time is longer than 30 seconds, abandon downloading. if (waitTime > 60) { ModConsole.LogError("[MOP] Downloading failed. Skipping downloading."); NewMessage("MOP: Downloading failed. Skipping downloading."); GetAndReadRules(); yield break; } } } ModConsole.Log("<color=green>[MOP] Downloading completed!</color>"); } File.WriteAllText(lastModListPath, modListString); if (isUpdateTime) { File.WriteAllText(lastDateFilePath, DateTime.Now.ToString()); } // File downloading and updating completed! // Start reading those files. GetAndReadRules(); }
void Initialize() { instance = this; ModConsole.Log("[MOP] Loading MOP..."); // Initialize the worldObjectManager list worldObjectManager = new WorldObjectManager(); // Looking for player and yard player = GameObject.Find("PLAYER").transform; // Add GameFixes MonoBehaviour. try { gameObject.AddComponent <GameFixes>(); } catch (Exception ex) { ExceptionManager.New(ex, false, $"GAME_FIXES_INITIALIZAITON | {ex}"); } // Loading vehicles vehicleManager = new VehicleManager(); // World Objects try { worldObjectManager.Add("CABIN", DisableOn.Distance | DisableOn.IgnoreInQualityMode); worldObjectManager.Add("COTTAGE", DisableOn.Distance, 400); worldObjectManager.Add("DANCEHALL", DisableOn.Distance, 500); worldObjectManager.Add("PERAJARVI", DisableOn.Distance | DisableOn.IgnoreInQualityMode, 400); worldObjectManager.Add("SOCCER", DisableOn.Distance); worldObjectManager.Add("WATERFACILITY", DisableOn.Distance, 300); worldObjectManager.Add("DRAGRACE", DisableOn.Distance, 1100); worldObjectManager.Add("StrawberryField", DisableOn.Distance, 400); worldObjectManager.Add("MAP/Buildings/DINGONBIISI", DisableOn.Distance, 400); worldObjectManager.Add("RALLY/PartsSalesman", DisableOn.Distance, 400); worldObjectManager.Add("LakeSmallBottom1", DisableOn.Distance, 500); worldObjectManager.Add("machine", DisableOn.Distance, 200, silent: true); ModConsole.Log("[MOP] World objects (1) loaded"); } catch (Exception ex) { ExceptionManager.New(ex, false, "WORLD_OBJECTS_1_INITIALIZAITON_FAIL"); } // Initialize places. placeManager = new PlaceManager(); // Fixes GameFixes.Instance.MainFixes(); //Things that should be enabled when out of proximity of the house try { worldObjectManager.Add("NPC_CARS", DisableOn.PlayerInHome); worldObjectManager.Add("TRAFFIC", DisableOn.PlayerInHome); worldObjectManager.Add("TRAIN", DisableOn.PlayerInHome | DisableOn.IgnoreInQualityMode); worldObjectManager.Add("Buildings", DisableOn.PlayerInHome); worldObjectManager.Add("TrafficSigns", DisableOn.PlayerInHome); worldObjectManager.Add("StreetLights", DisableOn.PlayerInHome); worldObjectManager.Add("HUMANS", DisableOn.PlayerInHome); worldObjectManager.Add("TRACKFIELD", DisableOn.PlayerInHome); worldObjectManager.Add("SkijumpHill", DisableOn.PlayerInHome | DisableOn.IgnoreInQualityMode); worldObjectManager.Add("Factory", DisableOn.PlayerInHome); worldObjectManager.Add("WHEAT", DisableOn.PlayerInHome); worldObjectManager.Add("RAILROAD", DisableOn.PlayerInHome); worldObjectManager.Add("AIRPORT", DisableOn.PlayerInHome); worldObjectManager.Add("RAILROAD_TUNNEL", DisableOn.PlayerInHome); worldObjectManager.Add("PierDancehall", DisableOn.PlayerInHome); worldObjectManager.Add("PierRiver", DisableOn.PlayerInHome); worldObjectManager.Add("PierStore", DisableOn.PlayerInHome); worldObjectManager.Add("BRIDGE_dirt", DisableOn.PlayerInHome); worldObjectManager.Add("BRIDGE_highway", DisableOn.PlayerInHome); worldObjectManager.Add("BirdTower", DisableOn.Distance, 400); worldObjectManager.Add("RYKIPOHJA", DisableOn.PlayerInHome); worldObjectManager.Add("COMPUTER", DisableOn.PlayerAwayFromHome); ModConsole.Log("[MOP] World objects (2) loaded"); } catch (Exception ex) { ExceptionManager.New(ex, false, "WORLD_OBJECTS_2_INITIALIZAITON_FAIL"); } // Adding area check if Satsuma is in the inspection's area try { SatsumaInArea inspectionArea = GameObject.Find("INSPECTION").AddComponent <SatsumaInArea>(); inspectionArea.Initialize(new Vector3(20, 20, 20)); } catch (Exception ex) { ExceptionManager.New(ex, false, "SATSUMA_AREA_CHECK_INSPECTION_FAIL"); } // Check for when Satsuma is on the lifter try { SatsumaInArea lifterArea = GameObject.Find("REPAIRSHOP/Lifter/Platform").AddComponent <SatsumaInArea>(); lifterArea.Initialize(new Vector3(5, 5, 5)); } catch (Exception ex) { ExceptionManager.New(ex, false, "SATSUMA_AREA_CHECK_REPAIRSHOP_FAIL"); } // Area for the parc ferme. try { GameObject parcFermeTrigger = new GameObject("MOP_ParcFermeTrigger"); parcFermeTrigger.transform.parent = GameObject.Find("RALLY").transform.Find("Scenery"); parcFermeTrigger.transform.position = new Vector3(-1383f, 3f, 1260f); SatsumaInArea parcFerme = parcFermeTrigger.AddComponent <SatsumaInArea>(); parcFerme.Initialize(new Vector3(41, 12, 35)); } catch (Exception ex) { ExceptionManager.New(ex, false, "PARC_FERME_TRIGGER_FAIL"); } ModConsole.Log("[MOP] Satsuma triggers loaded"); // Jokke's furnitures. // Only renderers are going to be toggled. try { if (GameObject.Find("tv(Clo01)")) { string[] furnitures = { "tv(Clo01)", "chair(Clo02)", "chair(Clo05)", "bench(Clo01)", "bench(Clo02)", "table(Clo02)", "table(Clo03)", "table(Clo04)", "table(Clo05)", "desk(Clo01)", "arm chair(Clo01)" }; foreach (string furniture in furnitures) { GameObject g = GameObject.Find(furniture); if (g) { g.transform.parent = null; worldObjectManager.Add(g, DisableOn.Distance, 100, ToggleModes.Renderer); } } ModConsole.Log("[MOP] Jokke's furnitures found and loaded"); } } catch (Exception ex) { ExceptionManager.New(ex, false, "JOKKE_FURNITURE_ERROR"); } // Haybales. // First we null out the prevent it from reloading the position of haybales. try { GameObject haybalesParent = GameObject.Find("JOBS/HayBales"); if (haybalesParent != null) { haybalesParent.GetComponent <PlayMakerFSM>().Fsm.RestartOnEnable = false; // And now we add all child haybale to world objects. foreach (Transform haybale in haybalesParent.transform.GetComponentInChildren <Transform>()) { worldObjectManager.Add(haybale.gameObject.name, DisableOn.Distance | DisableOn.IgnoreInQualityMode, 120); } } } catch (Exception ex) { ExceptionManager.New(ex, false, "HAYBALES_FIX_ERROR"); } // Logwalls try { foreach (GameObject wall in Resources.FindObjectsOfTypeAll <GameObject>().Where(g => g.name == "LogwallLarge")) { worldObjectManager.Add(wall, DisableOn.Distance, 300); } } catch (Exception ex) { ExceptionManager.New(ex, false, "LOGWALL_LOAD_ERROR"); } // Perajarvi Church. try { if (MopSettings.Mode != PerformanceMode.Performance) { GameObject church = GameObject.Find("PERAJARVI").transform.Find("CHURCH").gameObject; church.transform.parent = null; GameObject churchLOD = church.transform.Find("LOD").gameObject; church.GetComponent <PlayMakerFSM>().enabled = false; worldObjectManager.Add(churchLOD, DisableOn.Distance, 300); } } catch (Exception ex) { ExceptionManager.New(ex, false, "CHURCH_LOD_ERROR"); } // Lake houses. try { if (MopSettings.Mode == PerformanceMode.Quality) { GameObject.Find("PERAJARVI").transform.Find("TerraceHouse").transform.parent = null; } } catch (Exception ex) { ExceptionManager.New(ex, false, "LAKE_HOUSE_ERROR"); } // VehiclesHighway renderers. try { Transform vehiclesHighway = GameObject.Find("TRAFFIC").transform.Find("VehiclesHighway"); foreach (var f in vehiclesHighway.GetComponentsInChildren <Transform>(true).Where(f => f.parent == vehiclesHighway)) { worldObjectManager.Add(f.gameObject, DisableOn.Distance, 600, ToggleModes.MultipleRenderers); } // Also we gonna fix the lag on initial traffic load. vehiclesHighway.gameObject.SetActive(true); } catch (Exception ex) { ExceptionManager.New(ex, false, "TRAFFIC_VEHICLES_ERROR"); } // FITTAN renderers. try { worldObjectManager.Add(GameObject.Find("TRAFFIC").transform.Find("VehiclesDirtRoad/Rally/FITTAN").gameObject, DisableOn.Distance, 600, ToggleModes.MultipleRenderers); } catch (Exception ex) { ExceptionManager.New(ex, false, "FITTAN_RENDERERS_ERROR"); } // Initialize Items class try { new ItemsManager(); ItemsManager.Instance.Initialize(); ModConsole.Log("[MOP] Items class initialized"); } catch (Exception ex) { ExceptionManager.New(ex, true, "ITEMS_CLASS_ERROR"); } try { DateTime now = DateTime.Now; if (now.Day == 1 && now.Month == 4) { GameObject fpsObject = GameObject.Find("GUI").transform.Find("HUD/FPS/HUDValue").gameObject; PlayMakerFSM[] fsms = fpsObject.GetComponents <PlayMakerFSM>(); foreach (var fsm in fsms) { fsm.enabled = false; } fpsObject.GetComponent <TextMesh>().text = "99999999 :)"; fpsObject.transform.Find("HUDValueShadow").GetComponent <TextMesh>().text = "99999999 :)"; } } catch { } HookPreSaveGame(); ModConsole.Log("[MOP] Loading rules..."); foreach (ToggleRule v in RulesManager.Instance.ToggleRules) { try { switch (v.ToggleMode) { default: ModConsole.LogError($"[MOP] Unrecognized toggle mode for {v.ObjectName}: {v.ToggleMode}."); break; case ToggleModes.Simple: if (GameObject.Find(v.ObjectName) == null) { ModConsole.LogError($"[MOP] Couldn't find world object {v.ObjectName}"); continue; } worldObjectManager.Add(v.ObjectName, DisableOn.Distance); break; case ToggleModes.Renderer: if (GameObject.Find(v.ObjectName) == null) { ModConsole.LogError($"[MOP] Couldn't find world object {v.ObjectName}"); continue; } worldObjectManager.Add(v.ObjectName, DisableOn.Distance, 200, ToggleModes.Renderer); break; case ToggleModes.Item: GameObject g = GameObject.Find(v.ObjectName); if (g == null) { ModConsole.LogError($"[MOP] Couldn't find item {v.ObjectName}"); continue; } if (g.GetComponent <ItemBehaviour>() == null) { g.AddComponent <ItemBehaviour>(); } break; case ToggleModes.Vehicle: if (RulesManager.Instance.SpecialRules.IgnoreModVehicles) { continue; } if (GameObject.Find(v.ObjectName) == null) { ModConsole.LogError($"[MOP] Couldn't find vehicle {v.ObjectName}"); continue; } vehicleManager.Add(new Vehicle(v.ObjectName)); break; case ToggleModes.VehiclePhysics: if (RulesManager.Instance.SpecialRules.IgnoreModVehicles) { continue; } if (GameObject.Find(v.ObjectName) == null) { ModConsole.LogError($"[MOP] Couldn't find vehicle {v.ObjectName}"); continue; } vehicleManager.Add(new Vehicle(v.ObjectName)); Vehicle veh = vehicleManager[vehicleManager.Count - 1]; veh.Toggle = veh.ToggleUnityCar; break; } } catch (Exception ex) { ExceptionManager.New(ex, false, "TOGGLE_RULES_LOAD_ERROR"); } } ModConsole.Log("[MOP] Rules loading complete!"); // Initialzie sector manager try { gameObject.AddComponent <SectorManager>(); } catch (Exception ex) { ExceptionManager.New(ex, true, "SECTOR_MANAGER_ERROR"); } // Add DynamicDrawDistance component. try { gameObject.AddComponent <DynamicDrawDistance>(); } catch (Exception ex) { ExceptionManager.New(ex, false, "DYNAMIC_DRAW_DISTANCE_ERROR"); } try { if (MopSettings.Mode != PerformanceMode.Safe) { ToggleAll(false, ToggleAllMode.OnLoad); } } catch (Exception ex) { ExceptionManager.New(ex, true, "TOGGLE_ALL_ERROR"); } // Initialize the coroutines. currentLoop = LoopRoutine(); StartCoroutine(currentLoop); currentControlCoroutine = ControlCoroutine(); StartCoroutine(currentControlCoroutine); ModConsole.Log("<color=green>[MOP] MOD LOADED SUCCESFULLY!</color>"); Resources.UnloadUnusedAssets(); GC.Collect(); // If generate-list command is set to true, generate the list of items that are disabled by MOP. if (MopSettings.GenerateToggledItemsListDebug) { if (System.IO.File.Exists("world.txt")) { System.IO.File.Delete("world.txt"); } string world = ""; foreach (var w in worldObjectManager.GetList()) { if (world.Contains(w.GetName())) { continue; } world += w.GetName() + ", "; } System.IO.File.WriteAllText("world.txt", world); System.Diagnostics.Process.Start("world.txt"); if (System.IO.File.Exists("vehicle.txt")) { System.IO.File.Delete("vehicle.txt"); } string vehiclez = ""; foreach (var w in vehicleManager.List()) { vehiclez += w.gameObject.name + ", "; } System.IO.File.WriteAllText("vehicle.txt", vehiclez); System.Diagnostics.Process.Start("vehicle.txt"); if (System.IO.File.Exists("items.txt")) { System.IO.File.Delete("items.txt"); } string items = ""; foreach (var w in ItemsManager.Instance.All()) { if (items.Contains(w.gameObject.name)) { continue; } items += w.gameObject.name + ", "; } System.IO.File.WriteAllText("items.txt", items); System.Diagnostics.Process.Start("items.txt"); if (System.IO.File.Exists("place.txt")) { System.IO.File.Delete("place.txt"); } string place = ""; foreach (var w in placeManager.GetList()) { place += w.GetName() + ": "; foreach (var f in w.GetDisableableChilds()) { if (place.Contains(f.gameObject.name)) { continue; } place += f.gameObject.name + ", "; } place += "\n\n"; } System.IO.File.WriteAllText("place.txt", place); System.Diagnostics.Process.Start("place.txt"); } }
public override void Run(string[] args) { if (args.Length == 0) { ModConsole.Log("See \"mop help\" for command list."); return; } switch (args[0]) { default: ModConsole.Log("Invalid command. Type \"mop help\" for command list."); break; case "help": if (args.Length > 1) { string[] helpList = HelpList.Split('\n'); bool commandsFound = false; foreach (string s in helpList) { if (s.Split('-')[0].Contains(args[1])) { ModConsole.Log(s); commandsFound = true; } } if (!commandsFound) { ModConsole.Log($"Command {args[1]} not found."); } return; } ModConsole.Log(HelpList); break; case "rules": if (args.Length > 1 && args[1] == "roll") { ModConsole.Log("\n<color=yellow>You know the rules and so do I\n" + "A full commitment's what I'm thinking of\n" + "You wouldn't get this from any other guy\n" + "I just wanna tell you how I'm feeling\n" + "Gotta make you understand\n" + "Never gonna give you up\n" + "Never gonna let you down\n" + "Never gonna run around and desert you\n" + "Never gonna make you cry\n" + "Never gonna say goodbye\n" + "Never gonna tell a lie and hurt you</color>\n\n"); return; } if (RulesManager.Instance.IgnoreRules.Count > 0) { ModConsole.Log("<color=yellow><b>Ignore Rules</b></color>"); foreach (IgnoreRule r in RulesManager.Instance.IgnoreRules) { ModConsole.Log($"<b>Object:</b> {r.ObjectName}"); } } if (RulesManager.Instance.IgnoreRulesAtPlaces.Count > 0) { ModConsole.Log("\n<color=yellow><b>Ignore Rules At Place</b></color>"); foreach (IgnoreRuleAtPlace r in RulesManager.Instance.IgnoreRulesAtPlaces) { ModConsole.Log($"<b>Place:</b> {r.Place} <b>Object:</b> {r.ObjectName}"); } } if (RulesManager.Instance.ToggleRules.Count > 0) { ModConsole.Log("\n<color=yellow><b>Toggle Rules</b></color>"); foreach (ToggleRule r in RulesManager.Instance.ToggleRules) { ModConsole.Log($"<b>Object:</b> {r.ObjectName} <b>Toggle Mode:</b> {r.ToggleMode}"); } } if (RulesManager.Instance.NewSectors.Count > 0) { ModConsole.Log("\n<color=yellow><b>New Sectors</b></color>"); foreach (NewSector r in RulesManager.Instance.NewSectors) { ModConsole.Log($"<b>Pos:</b> {r.Position} <b>Scale:</b> {r.Scale} <b>Rot:</b> {r.Rotation} <b>Ignore:</b> {string.Join(", ", r.Whitelist)}"); } } ModConsole.Log("\n<color=yellow><b>Special Rules</b></color>"); // Obtain all fields FieldInfo[] fields = typeof(SpecialRules).GetFields(); // Loop through fields foreach (var field in fields) { ModConsole.Log($"<b>{field.Name}</b>: {field.GetValue(RulesManager.Instance.SpecialRules)}"); } // List rule files. string output = "\n<color=yellow><b>Rule Files</b></color>\n"; foreach (string ruleFile in RulesManager.Instance.RuleFileNames) { output += $"{ruleFile}\n"; } ModConsole.Log(output); break; case "reload": if (ModLoader.CurrentScene != CurrentScene.MainMenu) { ModConsole.Log("You can only reload rule files in the main menu"); return; } RulesManager.Instance.WipeAll(false); break; case "new": string path = $"{MOP.ModConfigPath}/Custom.txt"; if (args.Length > 1) { path = $"{MOP.ModConfigPath}/{args[1]}.mopconfig"; } if (File.Exists(path)) { ModConsole.Log("Custom file already exists. Use \"mop open\" to edit it now."); return; } File.WriteAllText(path, "## Every line which starts with ## will be ignored.\n" + "## All new flags MUST be written in a new line.\n" + "## Visit http://athlon.kkmr.pl/mop/wiki/#/rulefiles_commands for documentation.\n" + "## WARNING: Using custom rule files may cause issues. Use only at your own risk!"); Process.Start(path); if (path.EndsWith("Custom.txt")) { ModConsole.Log("A custom rule file has been created. You can find it as Custom.txt.\n" + "<color=red>Careless use of rule files may cause bugs and glitchess. Use only at yout own risk!</color>"); } else { ModConsole.Log($"A rule file for {args[1]} mod has been created."); } break; case "version": ModConsole.Log(MOP.ModVersion); break; case "cowsay": string say = string.Join(" ", args, 1, args.Length - 1); switch (say.ToLower()) { case "tell me your secrets": say = "all pls fix and no appreciation makes Athlon an angry boy"; break; case "tell me your wisdoms": say = "people saying that MOP is just improved KruFPS are straight up wrong"; break; case "wieski": say = "it really do be like dat doe sometimes"; break; case "embu": say = "pee vee good"; break; case "owo": say = "UwU"; break; case "uwu": say = "OwO"; break; case "mop sucks": say = "no u"; Process.Start("https://www.youtube.com/watch?v=dQw4w9WgXcQ"); break; } ModConsole.Log($"< {say} >\n" + " \\ ^__^\n" + " \\ (oo)\\____\n" + " (__)\\ )\\/\\\n" + " || ----w |\n" + " || || "); break; case "open-config": Process.Start(MOP.ModConfigPath); break; case "open": if (args.Length == 1) { ModConsole.Log($"Missing argument."); return; } if (args[1].StartsWith("Custom") || args[1].StartsWith("custom")) { if (!args[1].EndsWith(".txt")) { args[1] += ".txt"; } } else { if (!args[1].EndsWith(".mopconfig")) { args[1] += ".mopconfig"; } } if (!File.Exists($"{MOP.ModConfigPath}/{args[1]}")) { ModConsole.Log($"File {args[1]} doesn't exist."); return; } Process.Start($"{MOP.ModConfigPath}/{args[1]}"); break; case "delete": if (args.Length == 1) { ModConsole.Log($"Missing argument."); return; } if (args[1].StartsWith("Custom") && !args[1].EndsWith(".txt")) { args[1] += ".txt"; } else { if (!args[1].EndsWith(".mopconfig")) { args[1] += ".mopconfig"; } } if (!File.Exists($"{MOP.ModConfigPath}/{args[1]}")) { ModConsole.Log($"File {args[1]} doesn't exist."); return; } File.Delete($"{MOP.ModConfigPath}/{args[1]}"); break; case "cat": if (args.Length == 1) { ModConsole.Log($"Missing argument."); return; } if (args[1].StartsWith("Custom") && !args[1].EndsWith(".txt")) { args[1] += ".txt"; } else { if (!args[1].EndsWith(".mopconfig")) { args[1] += ".mopconfig"; } } if (!File.Exists($"{MOP.ModConfigPath}/{args[1]}")) { ModConsole.Log($"File {args[1]} doesn't exist."); return; } ModConsole.Log(File.ReadAllText($"{MOP.ModConfigPath}/{args[1]}")); break; case "generate-list": if (args.Length > 1) { if (RulesManager.Instance.LoadRules && (RulesManager.Instance.IgnoreRules.Count > 0 || RulesManager.Instance.IgnoreRulesAtPlaces.Count > 0 || RulesManager.Instance.NewSectors.Count > 0 || RulesManager.Instance.ToggleRules.Count > 0) ) { ModConsole.Log("<color=red>WARNING:</color> For accurate results, use \"mop load-rules false\" to prevent MOP from using rule files."); } MopSettings.GenerateToggledItemsListDebug = args[1].ToLower() == "true"; } ModConsole.Log($"Generating toggled elements list is set to " + $"<color={(MopSettings.GenerateToggledItemsListDebug ? "green" : "red")}>{MopSettings.GenerateToggledItemsListDebug}</color>"); break; case "load-rules": if (args.Length > 1) { RulesManager.Instance.LoadRules = args[1].ToLower() == "true"; if (!RulesManager.Instance.LoadRules) { ModConsole.Log("\n\n<color=red>WARNING:</color>\nDisabling rule files may cause serious issues with game, or even break your game save.\n\n" + "<b><color=red>!!! USE ONLY AT YOUR OWN RISK !!!</color></b>\n\n"); } } ModConsole.Log($"Loading rule files is set to " + $"<color={(RulesManager.Instance.LoadRules ? "green" : "red")}>{RulesManager.Instance.LoadRules}</color>"); break; case "force-crash": bool isCritical = false; if (args.Length > 1 && args[1].ToLower() == "critical") { isCritical = true; } ExceptionManager.New(new System.Exception("Test exception"), isCritical, "Test exception: " + System.Guid.NewGuid()); break; case "resolution": try { int width = int.Parse(args[1]); int height = int.Parse(args[2]); Screen.SetResolution(width, height, false); } catch { ModConsole.LogError("Failed setting resolution."); } break; case "quality-settings": try { QualitySettings.SetQualityLevel(int.Parse(args[1]), true); } catch { ModConsole.LogError("Failed setting quality settings."); } break; } }