using NewHorizons.Builder.Body; using NewHorizons.Builder.General; using NewHorizons.Builder.Orbital; using NewHorizons.Builder.Props; using NewHorizons.Builder.ShipLog; using NewHorizons.Builder.Updater; using NewHorizons.Components; using NewHorizons.External; using NewHorizons.External.Configs; using NewHorizons.External.VariableSize; using NewHorizons.Handlers; using NewHorizons.Utility; using Newtonsoft.Json.Linq; using OWML.Common; using OWML.ModHelper; using OWML.Utils; using PacificEngine.OW_CommonResources.Game.Player; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using OWML.Common.Menus; using UnityEngine; using UnityEngine.SceneManagement; using Logger = NewHorizons.Utility.Logger; using NewHorizons.Builder.Atmosphere; using PacificEngine.OW_CommonResources.Geometry.Orbits; using NewHorizons.Utility.CommonResources; namespace NewHorizons { public class Main : ModBehaviour { public static AssetBundle ShaderBundle; public static Main Instance { get; private set; } public static bool Debug; private static IModButton _reloadButton; public static Dictionary SystemDict = new Dictionary(); public static Dictionary> BodyDict = new Dictionary>(); public static Dictionary AssetBundles = new Dictionary(); public static List MountedAddons = new List(); public static float FurthestOrbit { get; set; } = 50000f; public string CurrentStarSystem { get { return Instance._currentStarSystem; } } public bool IsWarping { get; private set; } = false; public bool WearingSuit { get; private set; } = false; public static bool HasWarpDrive { get; private set; } = false; private string _defaultStarSystem = "SolarSystem"; private string _currentStarSystem = "SolarSystem"; private bool _isChangingStarSystem = false; private bool _firstLoad = true; private ShipWarpController _shipWarpController; public override object GetApi() { return new NewHorizonsApi(); } public override void Configure(IModConfig config) { Debug = config.GetSettingsValue("Debug"); UpdateReloadButton(); string logLevel = config.GetSettingsValue("LogLevel"); Logger.LogType logType; switch (logLevel) { case "Info": logType = Logger.LogType.Log; break; case "Warning": logType = Logger.LogType.Warning; break; case "Critical": logType = Logger.LogType.Error; break; default: logType = Logger.LogType.Error; break; } Logger.UpdateLogLevel(logType); } public void Start() { SceneManager.sceneLoaded += OnSceneLoaded; Instance = this; GlobalMessenger.AddListener("PlayerDeath", OnDeath); ShaderBundle = Main.Instance.ModHelper.Assets.LoadBundle("AssetBundle/shader"); BodyDict["SolarSystem"] = new List(); SystemDict["SolarSystem"] = new NewHorizonsSystem("SolarSystem", new StarSystemConfig(null), this); Tools.Patches.Apply(); Tools.WarpDrivePatches.Apply(); Tools.OWCameraFix.Apply(); Tools.ShipLogPatches.Apply(); Tools.TranslationPatches.Apply(); Logger.Log("Begin load of config files...", Logger.LogType.Log); try { LoadConfigs(this); } catch (Exception) { Logger.LogWarning("Couldn't find planets folder"); } Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single)); Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => _firstLoad = false); Instance.ModHelper.Menus.PauseMenu.OnInit += InitializePauseMenu; } #region Reloading private void InitializePauseMenu() { _reloadButton = ModHelper.Menus.PauseMenu.OptionsButton.Duplicate(TranslationHandler.GetTranslation("Reload Configs", TranslationHandler.TextType.UI).ToUpper()); _reloadButton.OnClick += ReloadConfigs; UpdateReloadButton(); } private void UpdateReloadButton() { if (_reloadButton != null) { if (Debug) _reloadButton.Show(); else _reloadButton.Hide(); } } private void ReloadConfigs() { BodyDict = new Dictionary>(); SystemDict = new Dictionary(); BodyDict["SolarSystem"] = new List(); SystemDict["SolarSystem"] = new NewHorizonsSystem("SolarSystem", new StarSystemConfig(null), this); foreach (AssetBundle bundle in AssetBundles.Values) { bundle.Unload(true); } AssetBundles.Clear(); Logger.Log("Begin reload of config files...", Logger.LogType.Log); try { foreach (IModBehaviour mountedAddon in MountedAddons) { LoadConfigs(mountedAddon); } } catch (Exception) { Logger.LogWarning("Error While Reloading"); } ChangeCurrentStarSystem(_currentStarSystem); } #endregion public void OnDestroy() { Logger.Log($"Destroying NewHorizons"); SceneManager.sceneLoaded -= OnSceneLoaded; GlobalMessenger.RemoveListener("PlayerDeath", OnDeath); } void OnSceneLoaded(Scene scene, LoadSceneMode mode) { Logger.Log($"Scene Loaded: {scene.name} {mode}"); _isChangingStarSystem = false; if (scene.name == "TitleScreen") { TitleSceneHandler.DisplayBodyOnTitleScreen(BodyDict.Values.ToList().SelectMany(x => x).ToList()); } if(scene.name == "SolarSystem") { HeavenlyBodyBuilder.Reset(); NewHorizonsData.Load(); SignalBuilder.Init(); AstroObjectLocator.RefreshList(); PlanetCreationHandler.Init(BodyDict[CurrentStarSystem]); OWAssetHandler.Init(); LoadTranslations(ModHelper.Manifest.ModFolderPath + "AssetBundle/", this); Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => Locator.GetPlayerBody().gameObject.AddComponent()); // Warp drive StarChartHandler.Init(SystemDict.Values.ToArray()); HasWarpDrive = StarChartHandler.CanWarp(); _shipWarpController = GameObject.Find("Ship_Body").AddComponent(); _shipWarpController.Init(); if (HasWarpDrive == true) EnableWarpDrive(); Logger.Log($"Is the player warping in? {IsWarping}"); if (IsWarping && _shipWarpController) Instance.ModHelper.Events.Unity.FireInNUpdates(() => _shipWarpController.WarpIn(WearingSuit), 5); else Instance.ModHelper.Events.Unity.FireInNUpdates(() => GameObject.FindObjectOfType().DebugWarp(SystemDict[_currentStarSystem].SpawnPoint), 5); IsWarping = false; var map = GameObject.FindObjectOfType(); if (map != null) map._maxPanDistance = FurthestOrbit * 1.5f; } else { // Reset back to original solar system after going to main menu. _currentStarSystem = _defaultStarSystem; } } public void EnableWarpDrive() { Logger.Log("Setting up warp drive"); PlanetCreationHandler.LoadBody(LoadConfig(this, "AssetBundle/WarpDriveConfig.json")); HasWarpDrive = true; } #region Load public void LoadConfigs(IModBehaviour mod) { if (_firstLoad) { MountedAddons.Add(mod); } var folder = mod.ModHelper.Manifest.ModFolderPath; if(Directory.Exists(folder + "planets")) { foreach (var file in Directory.GetFiles(folder + @"planets\", "*.json", SearchOption.AllDirectories)) { var relativeDirectory = file.Replace(folder, ""); var body = LoadConfig(mod, relativeDirectory); if (body != null) { // Wanna track the spawn point of each system if (body.Config.Spawn != null) SystemDict[body.Config.StarSystem].Spawn = body.Config.Spawn; // Add the new planet to the planet dictionary BodyDict[body.Config.StarSystem].Add(body); } } } if(Directory.Exists(folder + @"translations\")) { LoadTranslations(folder, mod); } } private void LoadTranslations(string folder, IModBehaviour mod) { var foundFile = false; foreach (TextTranslation.Language language in Enum.GetValues(typeof(TextTranslation.Language))) { if (language == TextTranslation.Language.UNKNOWN || language == TextTranslation.Language.TOTAL) continue; var relativeFile = $"translations/{language.ToString().ToLower()}.json"; if (File.Exists($"{folder}{relativeFile}")) { Logger.Log($"Registering {language} translation from {mod.ModHelper.Manifest.Name} from {relativeFile}"); var config = new TranslationConfig($"{folder}{relativeFile}"); if (config == null) { Logger.Log($"Found {folder}{relativeFile} but couldn't load it"); continue; } foundFile = true; TranslationHandler.RegisterTranslation(language, config); } } if (!foundFile) Logger.LogWarning($"{mod.ModHelper.Manifest.Name} has a folder for translations but none were loaded"); } public NewHorizonsBody LoadConfig(IModBehaviour mod, string relativeDirectory) { NewHorizonsBody body = null; try { var config = mod.ModHelper.Storage.Load(relativeDirectory); Logger.Log($"Loaded {config.Name}"); if (config.Base.CenterOfSolarSystem) config.Orbit.IsStatic = true; if (!SystemDict.ContainsKey(config.StarSystem)) { // See if theres a star system config var starSystemConfig = mod.ModHelper.Storage.Load($"systems/{config.StarSystem}.json"); if (starSystemConfig == null) starSystemConfig = new StarSystemConfig(null); else Logger.Log($"Loaded system config for {config.StarSystem}"); // Since we only load stuff the first time we can do this now if (starSystemConfig.startHere) { _defaultStarSystem = config.StarSystem; _currentStarSystem = config.StarSystem; } SystemDict.Add(config.StarSystem, new NewHorizonsSystem(config.StarSystem, starSystemConfig, mod)); BodyDict.Add(config.StarSystem, new List()); } body = new NewHorizonsBody(config, mod); } catch (Exception e) { Logger.LogError($"Couldn't load {relativeDirectory}: {e.Message}, is your Json formatted correctly?"); } return body; } #endregion Load #region Change star system public void ChangeCurrentStarSystem(string newStarSystem, bool warp = false) { if (_isChangingStarSystem) return; Logger.Log($"Warping to {newStarSystem}"); if(warp && _shipWarpController) _shipWarpController.WarpOut(); _currentStarSystem = newStarSystem; _isChangingStarSystem = true; IsWarping = warp; WearingSuit = PlayerState.IsWearingSuit(); // We kill them so they don't move as much Locator.GetDeathManager().KillPlayer(DeathType.Meditation); LoadManager.LoadSceneAsync(OWScene.SolarSystem, true, LoadManager.FadeType.ToBlack, 0.1f, true); } void OnDeath(DeathType _) { // We reset the solar system on death (unless we just killed the player) if (!_isChangingStarSystem) { _currentStarSystem = _defaultStarSystem; IsWarping = false; } } #endregion Change star system } #region API public class NewHorizonsApi { [Obsolete("Create(Dictionary config) is deprecated, please use Create(Dictionary config, IModBehaviour mod) instead")] public void Create(Dictionary config) { Create(config, null); } public void Create(Dictionary config, IModBehaviour mod) { Logger.Log("Recieved API request to create planet " + (string)config["Name"], Logger.LogType.Log); var planetConfig = new PlanetConfig(config); var body = new NewHorizonsBody(planetConfig, mod ?? Main.Instance); if (!Main.BodyDict.ContainsKey(body.Config.StarSystem)) Main.BodyDict.Add(body.Config.StarSystem, new List()); Main.BodyDict[body.Config.StarSystem].Add(body); } public void LoadConfigs(IModBehaviour mod) { Main.Instance.LoadConfigs(mod); } public GameObject GetPlanet(string name) { return Main.BodyDict.Values.SelectMany(x => x).ToList().FirstOrDefault(x => x.Config.Name == name).Object; } } #endregion API }