From c3a7588b226732c18e9548d57c19046e02b019e0 Mon Sep 17 00:00:00 2001 From: "Nick J. Connors" Date: Sun, 6 Feb 2022 23:47:09 -0500 Subject: [PATCH] Code refactor after PR --- NewHorizons/Builder/General/ShipLogBuilder.cs | 648 ------------------ NewHorizons/Builder/Props/PropBuildManager.cs | 5 +- .../Builder/ShipLog/EntryLocationBuilder.cs | 37 + NewHorizons/Builder/ShipLog/MapModeBuilder.cs | 319 +++++++++ NewHorizons/Builder/ShipLog/RevealBuilder.cs | 89 +++ .../Builder/ShipLog/RumorModeBuilder.cs | 191 ++++++ NewHorizons/Handlers/ShipLogHandler.cs | 46 ++ NewHorizons/Tools/Patches.cs | 24 +- NewHorizons/Utility/CollectionUtilities.cs | 25 + 9 files changed, 723 insertions(+), 661 deletions(-) delete mode 100644 NewHorizons/Builder/General/ShipLogBuilder.cs create mode 100644 NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs create mode 100644 NewHorizons/Builder/ShipLog/MapModeBuilder.cs create mode 100644 NewHorizons/Builder/ShipLog/RevealBuilder.cs create mode 100644 NewHorizons/Builder/ShipLog/RumorModeBuilder.cs create mode 100644 NewHorizons/Handlers/ShipLogHandler.cs create mode 100644 NewHorizons/Utility/CollectionUtilities.cs diff --git a/NewHorizons/Builder/General/ShipLogBuilder.cs b/NewHorizons/Builder/General/ShipLogBuilder.cs deleted file mode 100644 index 1f37f1e6..00000000 --- a/NewHorizons/Builder/General/ShipLogBuilder.cs +++ /dev/null @@ -1,648 +0,0 @@ -using NewHorizons.Components; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Xml.Linq; -using NewHorizons.External; -using NewHorizons.Utility; -using OWML.Common; -using UnityEngine; -using UnityEngine.UI; -using Logger = NewHorizons.Utility.Logger; - -namespace NewHorizons.Builder.General -{ - public static class ShipLogBuilder - { - public static readonly string PAN_ROOT_PATH = "Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/MapMode/ScaleRoot/PanRoot"; - - private static Dictionary astroIdToBody = new Dictionary(); - - private static NewHorizonsBody GetConfigFromEntry(ShipLogEntry entry) - { - return astroIdToBody[entry._astroObjectID]; - } - - #region Map Mode - - public class MapModeBuilder - { - private class MapModeObject - { - public int x; - public int y; - public int branch_width; - public int branch_height; - public int level; - public NewHorizonsBody mainBody; - public ShipLogAstroObject astroObject; - public List children; - public MapModeObject parent; - public MapModeObject lastSibling; - public void increment_width() - { - branch_width++; - parent?.increment_width(); - } - public void increment_height() - { - branch_height++; - parent?.increment_height(); - } - } - - public static string GetAstroBodyShipLogName(string id) - { - if (astroIdToBody.ContainsKey(id)) - { - return astroIdToBody[id].Config.Name; - } - else - { - return id; - } - } - - public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, int layer) - { - MapModeObject rootObject = ConstructPrimaryNode(systemName); - if (rootObject.mainBody != null) - { - MakeAllNodes(ref rootObject, transformParent, layer); - } - - int maxAmount = Main.BodyDict[Main.Instance.CurrentStarSystem].Count; - ShipLogAstroObject[][] navMatrix = new ShipLogAstroObject[maxAmount][]; - for (int i = 0; i < maxAmount; i++) - { - navMatrix[i] = new ShipLogAstroObject[maxAmount]; - } - - CreateNavigationMatrix(rootObject, ref navMatrix); - navMatrix = navMatrix.Where(a => a.Count(c => c != null) > 0).Prepend(new ShipLogAstroObject[1]).ToArray(); - for (var index = 0; index < navMatrix.Length; index++) - { - navMatrix[index] = navMatrix[index].Where(a => a != null).ToArray(); - } - return navMatrix; - } - - private static void CreateNavigationMatrix(MapModeObject root, ref ShipLogAstroObject[][] navMatrix) - { - if (root.astroObject != null) - { - navMatrix[root.y][root.x] = root.astroObject; - } - foreach (MapModeObject child in root.children) - { - CreateNavigationMatrix(child, ref navMatrix); - } - } - - private static void MakeAllNodes(ref MapModeObject parentNode, GameObject parent, int layer) - { - MakeNode(ref parentNode, parent, layer); - for (var i = 0; i < parentNode.children.Count; i++) - { - MapModeObject child = parentNode.children[i]; - MakeAllNodes(ref child, parent, layer); - parentNode.children[i] = child; - } - } - - private static GameObject CreateImage(GameObject nodeGO, IModAssets assets, string imagePath, string name, int layer) - { - GameObject newImageGO = new GameObject(name); - newImageGO.layer = layer; - newImageGO.transform.SetParent(nodeGO.transform); - - RectTransform transform = newImageGO.AddComponent(); - transform.localPosition = Vector3.zero; - transform.localRotation = Quaternion.identity; - transform.localScale = Vector3.one; - - Image newImage = newImageGO.AddComponent(); - if (imagePath == "DEFAULT") - { - newImage.sprite = Locator.GetShipLogManager()._shipLogLibrary.defaultEntrySprite; - } - else - { - Texture2D newTexture = assets.GetTexture(imagePath); - Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); - Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); - newImage.sprite = Sprite.Create(newTexture, rect, pivot); - } - return newImageGO; - } - - public static T KeyByValue(Dictionary dict, W val) - { - T key = default; - foreach (KeyValuePair pair in dict) - { - if (EqualityComparer.Default.Equals(pair.Value, val)) - { - key = pair.Key; - break; - } - } - return key; - } - - private static string GetAstroObjectId(NewHorizonsBody body) - { - if (astroIdToBody.ContainsValue(body)) - { - return KeyByValue(astroIdToBody, body); - } - else - { - return body.Config.Name; - } - } - - private static void CreateShipLogAstroObject(GameObject nodeGO, ref MapModeObject node, GameObject referenceUnviewedSprite, int layer) - { - const float unviewedIconOffset = 15; - ShipLogAstroObject astroObject = nodeGO.AddComponent(); - astroObject._id = GetAstroObjectId(node.mainBody); - - string imagePath = node.mainBody.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; - string outlinePath = node.mainBody.Config.ShipLog?.mapMode?.outlineSprite ?? imagePath; - astroObject._imageObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, imagePath, node.mainBody.Config.Name + " Revealed", layer); - astroObject._outlineObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, outlinePath, node.mainBody.Config.Name + " Outline", layer); - - astroObject._unviewedObj = Object.Instantiate(referenceUnviewedSprite, nodeGO.transform, false); - if (node.mainBody.Config.FocalPoint != null) - { - astroObject._imageObj.GetComponent().enabled = false; - astroObject._outlineObj.GetComponent().enabled = false; - astroObject._unviewedObj.GetComponent().enabled = false; - astroObject.transform.localScale = node.lastSibling.astroObject.transform.localScale; - } - astroObject._invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false; - - Rect imageRect = astroObject._imageObj.GetComponent().rect; - astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0); - node.astroObject = astroObject; - } - - private static void ConnectNodeToLastSibling(MapModeObject node) - { - Vector2 fromPosition = node.astroObject.transform.localPosition; - Vector2 toPosition = node.lastSibling.astroObject.transform.localPosition; - - GameObject newLink = new GameObject("Line_ShipLog"); - newLink.layer = node.astroObject.gameObject.layer; - newLink.SetActive(false); - - RectTransform transform = newLink.AddComponent(); - transform.SetParent(node.astroObject.transform.parent); - Vector2 center = toPosition + (fromPosition - toPosition) / 2; - transform.localPosition = new Vector3(center.x, center.y, -1); - transform.localRotation = Quaternion.identity; - transform.localScale = node.level % 2 == 0 ? new Vector3(node.astroObject.transform.localScale.x / 5f, Mathf.Abs(fromPosition.y - toPosition.y) / 100f, 1) : new Vector3(Mathf.Abs(fromPosition.x - toPosition.x) / 100f, node.astroObject.transform.localScale.y / 5f , 1); - Image linkImage = newLink.AddComponent(); - linkImage.color = new Color(0.28f, 0.28f, 0.5f, 0.28f); - - ShipLogModule.ShipLogDetailInfo linkDetailInfo = new ShipLogModule.ShipLogDetailInfo() - { - invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false - }; - - ShipLogDetail linkDetail = newLink.AddComponent(); - linkDetail.Init(linkDetailInfo, linkImage, linkImage); - - transform.SetParent(node.astroObject.transform); - transform.SetAsFirstSibling(); - newLink.SetActive(true); - } - - private static void MakeDetail(ShipLogModule.ShipLogDetailInfo info, Transform parent, IModAssets assets) - { - GameObject detailGameObject = new GameObject("Detail"); - detailGameObject.transform.SetParent(parent); - detailGameObject.SetActive(false); - - RectTransform detailTransform = detailGameObject.AddComponent(); - detailTransform.localPosition = (Vector2)(info.position ?? new MVector2(0, 0)); - detailTransform.localRotation = Quaternion.Euler(0f, 0f, info.rotation); - detailTransform.localScale = (Vector2)(info.scale ?? new MVector2(0, 0)); - - string revealedPath = info.revealedSprite ?? "DEFAULT"; - string outlinePath = info.outlineSprite ?? revealedPath; - - Image revealedImage = CreateImage(detailGameObject, assets, revealedPath, "Detail Revealed", parent.gameObject.layer).GetComponent(); - Image outlineImage = CreateImage(detailGameObject, assets, outlinePath, "Detail Outline", parent.gameObject.layer).GetComponent(); - - ShipLogDetail detail = detailGameObject.AddComponent(); - detail.Init(info, revealedImage, outlineImage); - detailGameObject.SetActive(true); - } - - private static void MakeDetails(MapModeObject node) - { - if (node.mainBody.Config.ShipLog?.mapMode?.details?.Length > 0) - { - GameObject detailsParent = new GameObject("Details"); - detailsParent.transform.SetParent(node.astroObject.transform); - detailsParent.SetActive(false); - - RectTransform detailsTransform = detailsParent.AddComponent(); - detailsTransform.localPosition = Vector3.zero; - detailsTransform.localRotation = Quaternion.identity; - detailsTransform.localScale = Vector3.one; - - foreach (ShipLogModule.ShipLogDetailInfo detailInfo in node.mainBody.Config.ShipLog.mapMode.details) - { - MakeDetail(detailInfo, detailsTransform, node.mainBody.Mod.Assets); - } - detailsParent.SetActive(true); - } - } - - private static void MakeNode(ref MapModeObject node, GameObject parent, int layer) - { - const float padding = 250f; - - GameObject newNodeGO = new GameObject(node.mainBody.Config.Name + "_ShipLog"); - newNodeGO.layer = layer; - newNodeGO.transform.SetParent(parent.transform); - - RectTransform transform = newNodeGO.AddComponent(); - float scale = node.mainBody.Config.ShipLog?.mapMode?.scale?? 1f; - Vector2 position = Vector2.zero; - if (node.lastSibling != null) - { - ShipLogAstroObject lastAstroObject = node.lastSibling.astroObject; - Vector3 lastPosition = lastAstroObject.transform.localPosition; - position = lastPosition; - float extraDistance = (node.mainBody.Config.ShipLog?.mapMode?.offset ?? 0f) * 100; - if (node.level % 2 == 0) - { - position.y += padding * (node.y - node.lastSibling.y) + extraDistance; - } - else - { - position.x += padding * (node.x - node.lastSibling.x) + extraDistance; - } - } - transform.localPosition = new Vector3(position.x, position.y, 0); - transform.localRotation = Quaternion.identity; - transform.localScale = Vector3.one * scale; - CreateShipLogAstroObject(newNodeGO, ref node, GameObject.Find(PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon"), layer); - if (node.lastSibling != null) ConnectNodeToLastSibling(node); - MakeDetails(node); - transform.SetAsFirstSibling(); - } - - private static MapModeObject ConstructPrimaryNode(string systemName) - { - foreach (NewHorizonsBody body in Main.BodyDict[systemName].Where(b => b.Config.Base.CenterOfSolarSystem)) - { - List searchList = Main.BodyDict[systemName].Where(b => (b.Config.ShipLog?.mapMode?.remove ?? false) == false).ToList(); - searchList.Sort((b, o) => b.Config.Orbit.SemiMajorAxis.CompareTo(o.Config.Orbit.SemiMajorAxis)); - MapModeObject newNode = new MapModeObject - { - mainBody = body, - level = 0, - x = 0, - y = 0 - }; - newNode.children = ConstructChildrenNodes(systemName, newNode, searchList); - return newNode; - } - Logger.LogError("Couldn't find center of system!"); - return new MapModeObject(); - } - - private static List ConstructChildrenNodes(string systemName, MapModeObject parent, List searchList) - { - List children = new List(); - int newX = parent.x; - int newY = parent.y; - int newLevel = parent.level + 1; - MapModeObject lastSibling = parent; - foreach (NewHorizonsBody body in searchList.Where(b => b.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name)) - { - if (body.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name) - { - bool even = newLevel % 2 == 0; - newX = even ? newX : newX + 1; - newY = even ? newY + 1 : newY; - MapModeObject newNode = new MapModeObject() - { - mainBody = body, - level = newLevel, - x = newX, - y = newY, - parent = parent, - lastSibling = lastSibling - }; - newNode.children = ConstructChildrenNodes(systemName, newNode, searchList); - if (even) - { - newY += newNode.branch_height; - parent.increment_height(); - newY += 1; - } - else - { - newX += newNode.branch_width; - parent.increment_width(); - newX += 1; - } - lastSibling = newNode; - children.Add(newNode); - } - } - return children; - } - } - #endregion - - #region Rumor Mode - public static class RumorModeBuilder - { - private static Dictionary curiosityColors = new Dictionary(); - private static Dictionary curiosityHighlightColors = new Dictionary(); - private static Dictionary rawNameToCuriosityName = new Dictionary(); - private static Dictionary entryIdToRawName = new Dictionary(); - - public static void AddCuriosityColors(ShipLogModule.CuriosityColorInfo[] newColors) - { - foreach (ShipLogModule.CuriosityColorInfo newColor in newColors) - { - if (rawNameToCuriosityName.ContainsKey(newColor.id) == false) - { - CuriosityName newName = (CuriosityName) 8 + rawNameToCuriosityName.Count; - rawNameToCuriosityName.Add(newColor.id, newName); - curiosityColors.Add(newName, newColor.color.ToColor()); - curiosityHighlightColors.Add(newName, newColor.highlightColor.ToColor()); - } - } - } - - public static Color GetCuriosityColor(CuriosityName curiosityName, bool highlighted, Color defaultColor, Color defaultHighlight) - { - if (curiosityColors.ContainsKey(curiosityName) && curiosityHighlightColors.ContainsKey(curiosityName)) - { - return (highlighted ? curiosityHighlightColors : curiosityColors)[curiosityName]; - } - else - { - return highlighted? defaultHighlight : defaultColor; - } - } - - public static void AddBodyToShipLog(ShipLogManager manager, NewHorizonsBody body) - { - string systemName = body.Config.StarSystem; - XElement astroBodyFile = XElement.Load(Main.Instance.ModHelper.Manifest.ModFolderPath + body.Config.ShipLog.xmlFile); - XElement astroBodyId = astroBodyFile.Element("ID"); - if (astroBodyId == null) - { - Logger.LogError("Failed to load ship logs for " + systemName + "!"); - } - else - { - astroBodyId.SetValue(systemName + "/" + astroBodyId.Value); - foreach (XElement entryElement in astroBodyFile.DescendantsAndSelf("Entry")) - { - XElement curiosityName = entryElement.Element("Curiosity"); - XElement id = entryElement.Element("ID"); - if (curiosityName != null && id != null && entryIdToRawName.ContainsKey(id.Value) == false) - { - entryIdToRawName.Add(id.Value, curiosityName.Value); - } - AddTranslation(entryElement); - } - TextAsset newAsset = new TextAsset(astroBodyFile.ToString()); - List newBodies = new List(manager._shipLogXmlAssets) {newAsset}; - manager._shipLogXmlAssets = newBodies.ToArray(); - if (astroIdToBody.ContainsKey(astroBodyId.Value) == false) - { - astroIdToBody.Add(astroBodyId.Value, body); - } - } - } - - public static void GenerateEntryData(ShipLogManager manager) - { - const int step = 400; - int colAccumulator = 0; - int rowAccumulator = 0; - foreach(ShipLogEntry entry in manager._entryList) - { - if (manager._entryDataDict.ContainsKey(entry._id) == false) - { - NewHorizonsBody body = GetConfigFromEntry(entry); - Vector2? manualEntryPosition = GetManualEntryPosition(entry._id, body.Config.ShipLog); - Vector2 entryPosition; - if (manualEntryPosition == null) - { - entryPosition = new Vector2(colAccumulator, rowAccumulator); - } - else - { - entryPosition = (Vector2) manualEntryPosition; - } - EntryData newData = new EntryData - { - id = entry._id, - cardPosition = entryPosition, - sprite = body.Config.ShipLog.spriteFolder == null? null : GetEntrySprite(entry._id, body) - }; - entry.SetSprite(newData.sprite == null? manager._shipLogLibrary.defaultEntrySprite : newData.sprite); - manager._entryDataDict.Add(entry._id, newData); - int index = manager._entryList.IndexOf(entry); - if (index < manager._entryList.Count - 2 && manager._entryList[index + 1]._astroObjectID != entry._astroObjectID) - { - rowAccumulator += step; - colAccumulator = 0; - } - else - { - colAccumulator += step; - } - } - } - } - - private static void AddTranslation(XElement entry) - { - Dictionary table = TextTranslation.Get().m_table.theShipLogTable; - XElement nameElement = entry.Element("Name"); - if (nameElement != null) - { - string name = nameElement.Value; - table[name] = name; - foreach (XElement rumorFact in entry.Elements("RumorFact")) - { - XElement rumorName = rumorFact.Element("RumorName"); - if (rumorName != null) - { - table[rumorName.Value] = rumorName.Value; - } - - XElement rumorText = rumorFact.Element("Text"); - if (rumorText != null) - { - table[name + rumorText.Value] = rumorText.Value; - } - } - foreach (XElement exploreFact in entry.Elements("ExploreFact")) - { - XElement exploreText = exploreFact.Element("Text"); - if (exploreText != null) - { - table[name + exploreText.Value] = exploreText.Value; - } - } - } - } - - public static void UpdateEntryCuriosity(ref ShipLogEntry entry) - { - if (entryIdToRawName.ContainsKey(entry._id)) - { - entry._curiosity = rawNameToCuriosityName[entryIdToRawName[entry._id]]; - } - } - - private static Sprite GetEntrySprite(string entryId, NewHorizonsBody body) - { - IModAssets assets = body.Mod.Assets; - string path = body.Config.ShipLog.spriteFolder + "/" + entryId + ".png"; - if (File.Exists(Main.Instance.ModHelper.Manifest.ModFolderPath + path)) - { - Texture2D newTexture = assets.GetTexture(path); - Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); - Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); - return Sprite.Create(newTexture, rect, pivot); - } - else - { - return null; - } - } - - private static Vector2? GetManualEntryPosition(string entryId, ShipLogModule config) - { - if (config.positions == null) return null; - foreach (ShipLogModule.EntryPositionInfo position in config.positions) - { - if (position.id == entryId) - { - return position.position; - } - } - return null; - } - } - #endregion - - #region Fact Reveals - public static class RevealBuilder - { - public static void Make(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) - { - GameObject newRevealGO = MakeGameObject(go, sector, info, mod); - switch (info.revealOn.ToLower()) - { - case "enter": - MakeTrigger(newRevealGO, sector, info, mod); - break; - case "observe": - MakeObservable(newRevealGO, sector, info, mod); - break; - case "snapshot": - MakeSnapshot(newRevealGO, sector, info, mod); - break; - default: - Logger.LogError("Invalid revealOn: " + info.revealOn); - break; - } - - newRevealGO.SetActive(true); - } - - private static SphereShape MakeShape(GameObject go, PropModule.RevealInfo info, Shape.CollisionMode collisionMode) - { - SphereShape newShape = go.AddComponent(); - newShape.radius = info.radius; - newShape.SetCollisionMode(collisionMode); - return newShape; - } - - private static GameObject MakeGameObject(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) - { - GameObject revealTriggerVolume = new GameObject("Reveal Volume (" + info.revealOn + ")"); - revealTriggerVolume.SetActive(false); - revealTriggerVolume.transform.parent = sector?.transform ?? go.transform; - revealTriggerVolume.transform.localPosition = info.position; - return revealTriggerVolume; - } - - private static void MakeTrigger(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) - { - SphereShape newShape = MakeShape(go, info, Shape.CollisionMode.Volume); - OWTriggerVolume newVolume = go.AddComponent(); - newVolume._shape = newShape; - ShipLogFactListTriggerVolume volume = go.AddComponent(); - volume._factIDs = info.reveals; - } - - private static void MakeObservable(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) - { - go.layer = LayerMask.NameToLayer("Interactible"); - SphereCollider newSphere = go.AddComponent(); - newSphere.radius = info.radius; - OWCollider newCollider = go.AddComponent(); - ShipLogFactObserveTrigger newObserveTrigger = go.AddComponent(); - newObserveTrigger._factIDs = info.reveals; - newObserveTrigger._maxViewDistance = info.maxDistance == -1f ? 2f : info.maxDistance; - newObserveTrigger._maxViewAngle = info.maxAngle; - newObserveTrigger._owCollider = newCollider; - newObserveTrigger._disableColliderOnRevealFact = true; - } - - private static void MakeSnapshot(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) - { - SphereShape newShape = MakeShape(go, info, Shape.CollisionMode.Manual); - ShapeVisibilityTracker newTracker = go.AddComponent(); - newTracker._shapes = new Shape[] {newShape}; - ShipLogFactSnapshotTrigger newSnapshotTrigger = go.AddComponent(); - newSnapshotTrigger._maxDistance = info.maxDistance == -1f ? 200f : info.maxDistance; - newSnapshotTrigger._factIDs = info.reveals; - } - } - #endregion - - #region Entry Locations - public static class EntryLocationBuilder - { - private static List locationsToInitialize = new List(); - public static void Make(GameObject go, Sector sector, PropModule.EntryLocationInfo info, IModHelper mod) - { - GameObject entryLocationGameObject = new GameObject("Entry Location (" + info.id + ")"); - entryLocationGameObject.SetActive(false); - entryLocationGameObject.transform.parent = sector?.transform ?? go.transform; - entryLocationGameObject.transform.localPosition = info.position; - ShipLogEntryLocation newLocation = entryLocationGameObject.AddComponent(); - newLocation._entryID = info.id; - newLocation._isWithinCloakField = info.cloaked; - locationsToInitialize.Add(newLocation); - entryLocationGameObject.SetActive(true); - } - - public static void InitializeLocations() - { - locationsToInitialize.ForEach(l => l.InitEntry()); - locationsToInitialize.Clear(); - } - } - #endregion - } -} diff --git a/NewHorizons/Builder/Props/PropBuildManager.cs b/NewHorizons/Builder/Props/PropBuildManager.cs index eadbfe7c..aecb8ad9 100644 --- a/NewHorizons/Builder/Props/PropBuildManager.cs +++ b/NewHorizons/Builder/Props/PropBuildManager.cs @@ -11,6 +11,7 @@ using System.Reflection; using NewHorizons.Builder.General; using NewHorizons.Utility; using OWML.Common; +using NewHorizons.Builder.ShipLog; namespace NewHorizons.Builder.Props { @@ -58,14 +59,14 @@ namespace NewHorizons.Builder.Props { foreach (var revealInfo in config.Props.Reveal) { - ShipLogBuilder.RevealBuilder.Make(go, sector, revealInfo, mod); + RevealBuilder.Make(go, sector, revealInfo, mod); } } if (config.Props.EntryLocation != null) { foreach (var entryLocationInfo in config.Props.EntryLocation) { - ShipLogBuilder.EntryLocationBuilder.Make(go, sector, entryLocationInfo, mod); + EntryLocationBuilder.Make(go, sector, entryLocationInfo, mod); } } } diff --git a/NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs b/NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs new file mode 100644 index 00000000..905b76bd --- /dev/null +++ b/NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs @@ -0,0 +1,37 @@ +using NewHorizons.Components; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using NewHorizons.External; +using NewHorizons.Utility; +using OWML.Common; +using UnityEngine; +using UnityEngine.UI; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Builder.ShipLog +{ + public static class EntryLocationBuilder + { + private static readonly List _locationsToInitialize = new List(); + public static void Make(GameObject go, Sector sector, PropModule.EntryLocationInfo info, IModHelper mod) + { + GameObject entryLocationGameObject = new GameObject("Entry Location (" + info.id + ")"); + entryLocationGameObject.SetActive(false); + entryLocationGameObject.transform.parent = sector?.transform ?? go.transform; + entryLocationGameObject.transform.localPosition = info.position; + ShipLogEntryLocation newLocation = entryLocationGameObject.AddComponent(); + newLocation._entryID = info.id; + newLocation._isWithinCloakField = info.cloaked; + _locationsToInitialize.Add(newLocation); + entryLocationGameObject.SetActive(true); + } + + public static void InitializeLocations() + { + _locationsToInitialize.ForEach(l => l.InitEntry()); + _locationsToInitialize.Clear(); + } + } +} diff --git a/NewHorizons/Builder/ShipLog/MapModeBuilder.cs b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs new file mode 100644 index 00000000..cfe6051d --- /dev/null +++ b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs @@ -0,0 +1,319 @@ +using NewHorizons.Components; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using NewHorizons.External; +using NewHorizons.Utility; +using OWML.Common; +using UnityEngine; +using UnityEngine.UI; +using Logger = NewHorizons.Utility.Logger; +using NewHorizons.Builder.Handlers; + +namespace NewHorizons.Builder.ShipLog +{ + public static class MapModeBuilder + { + private class MapModeObject + { + public int x; + public int y; + public int branch_width; + public int branch_height; + public int level; + public NewHorizonsBody mainBody; + public ShipLogAstroObject astroObject; + public List children; + public MapModeObject parent; + public MapModeObject lastSibling; + public void Increment_width() + { + branch_width++; + parent?.Increment_width(); + } + public void Increment_height() + { + branch_height++; + parent?.Increment_height(); + } + } + + public static string GetAstroBodyShipLogName(string id) + { + return ShipLogHandler.GetConfigFromID(id)?.Config?.Name ?? id; + } + + public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, int layer) + { + MapModeObject rootObject = ConstructPrimaryNode(systemName); + if (rootObject.mainBody != null) + { + MakeAllNodes(ref rootObject, transformParent, layer); + } + + int maxAmount = Main.BodyDict[Main.Instance.CurrentStarSystem].Count; + ShipLogAstroObject[][] navMatrix = new ShipLogAstroObject[maxAmount][]; + for (int i = 0; i < maxAmount; i++) + { + navMatrix[i] = new ShipLogAstroObject[maxAmount]; + } + + CreateNavigationMatrix(rootObject, ref navMatrix); + navMatrix = navMatrix.Where(a => a.Count(c => c != null) > 0).Prepend(new ShipLogAstroObject[1]).ToArray(); + for (var index = 0; index < navMatrix.Length; index++) + { + navMatrix[index] = navMatrix[index].Where(a => a != null).ToArray(); + } + return navMatrix; + } + + private static void CreateNavigationMatrix(MapModeObject root, ref ShipLogAstroObject[][] navMatrix) + { + if (root.astroObject != null) + { + navMatrix[root.y][root.x] = root.astroObject; + } + foreach (MapModeObject child in root.children) + { + CreateNavigationMatrix(child, ref navMatrix); + } + } + + private static void MakeAllNodes(ref MapModeObject parentNode, GameObject parent, int layer) + { + MakeNode(ref parentNode, parent, layer); + for (var i = 0; i < parentNode.children.Count; i++) + { + MapModeObject child = parentNode.children[i]; + MakeAllNodes(ref child, parent, layer); + parentNode.children[i] = child; + } + } + + private static GameObject CreateImage(GameObject nodeGO, IModAssets assets, string imagePath, string name, int layer) + { + GameObject newImageGO = new GameObject(name); + newImageGO.layer = layer; + newImageGO.transform.SetParent(nodeGO.transform); + + RectTransform transform = newImageGO.AddComponent(); + transform.localPosition = Vector3.zero; + transform.localRotation = Quaternion.identity; + transform.localScale = Vector3.one; + + Image newImage = newImageGO.AddComponent(); + if (imagePath == "DEFAULT") + { + newImage.sprite = Locator.GetShipLogManager()._shipLogLibrary.defaultEntrySprite; + } + else + { + Texture2D newTexture = assets.GetTexture(imagePath); + Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); + Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); + newImage.sprite = Sprite.Create(newTexture, rect, pivot); + } + return newImageGO; + } + + private static void CreateShipLogAstroObject(GameObject nodeGO, ref MapModeObject node, GameObject referenceUnviewedSprite, int layer) + { + const float unviewedIconOffset = 15; + ShipLogAstroObject astroObject = nodeGO.AddComponent(); + astroObject._id = ShipLogHandler.GetAstroObjectId(node.mainBody); + + string imagePath = node.mainBody.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; + string outlinePath = node.mainBody.Config.ShipLog?.mapMode?.outlineSprite ?? imagePath; + astroObject._imageObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, imagePath, node.mainBody.Config.Name + " Revealed", layer); + astroObject._outlineObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, outlinePath, node.mainBody.Config.Name + " Outline", layer); + + astroObject._unviewedObj = Object.Instantiate(referenceUnviewedSprite, nodeGO.transform, false); + if (node.mainBody.Config.FocalPoint != null) + { + astroObject._imageObj.GetComponent().enabled = false; + astroObject._outlineObj.GetComponent().enabled = false; + astroObject._unviewedObj.GetComponent().enabled = false; + astroObject.transform.localScale = node.lastSibling.astroObject.transform.localScale; + } + astroObject._invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false; + + Rect imageRect = astroObject._imageObj.GetComponent().rect; + astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0); + node.astroObject = astroObject; + } + + private static void ConnectNodeToLastSibling(MapModeObject node) + { + Vector2 fromPosition = node.astroObject.transform.localPosition; + Vector2 toPosition = node.lastSibling.astroObject.transform.localPosition; + + GameObject newLink = new GameObject("Line_ShipLog"); + newLink.layer = node.astroObject.gameObject.layer; + newLink.SetActive(false); + + RectTransform transform = newLink.AddComponent(); + transform.SetParent(node.astroObject.transform.parent); + Vector2 center = toPosition + (fromPosition - toPosition) / 2; + transform.localPosition = new Vector3(center.x, center.y, -1); + transform.localRotation = Quaternion.identity; + transform.localScale = node.level % 2 == 0 ? new Vector3(node.astroObject.transform.localScale.x / 5f, Mathf.Abs(fromPosition.y - toPosition.y) / 100f, 1) : new Vector3(Mathf.Abs(fromPosition.x - toPosition.x) / 100f, node.astroObject.transform.localScale.y / 5f, 1); + Image linkImage = newLink.AddComponent(); + linkImage.color = new Color(0.28f, 0.28f, 0.5f, 0.28f); + + ShipLogModule.ShipLogDetailInfo linkDetailInfo = new ShipLogModule.ShipLogDetailInfo() + { + invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false + }; + + ShipLogDetail linkDetail = newLink.AddComponent(); + linkDetail.Init(linkDetailInfo, linkImage, linkImage); + + transform.SetParent(node.astroObject.transform); + transform.SetAsFirstSibling(); + newLink.SetActive(true); + } + + private static void MakeDetail(ShipLogModule.ShipLogDetailInfo info, Transform parent, IModAssets assets) + { + GameObject detailGameObject = new GameObject("Detail"); + detailGameObject.transform.SetParent(parent); + detailGameObject.SetActive(false); + + RectTransform detailTransform = detailGameObject.AddComponent(); + detailTransform.localPosition = (Vector2)(info.position ?? new MVector2(0, 0)); + detailTransform.localRotation = Quaternion.Euler(0f, 0f, info.rotation); + detailTransform.localScale = (Vector2)(info.scale ?? new MVector2(0, 0)); + + string revealedPath = info.revealedSprite ?? "DEFAULT"; + string outlinePath = info.outlineSprite ?? revealedPath; + + Image revealedImage = CreateImage(detailGameObject, assets, revealedPath, "Detail Revealed", parent.gameObject.layer).GetComponent(); + Image outlineImage = CreateImage(detailGameObject, assets, outlinePath, "Detail Outline", parent.gameObject.layer).GetComponent(); + + ShipLogDetail detail = detailGameObject.AddComponent(); + detail.Init(info, revealedImage, outlineImage); + detailGameObject.SetActive(true); + } + + private static void MakeDetails(MapModeObject node) + { + if (node.mainBody.Config.ShipLog?.mapMode?.details?.Length > 0) + { + GameObject detailsParent = new GameObject("Details"); + detailsParent.transform.SetParent(node.astroObject.transform); + detailsParent.SetActive(false); + + RectTransform detailsTransform = detailsParent.AddComponent(); + detailsTransform.localPosition = Vector3.zero; + detailsTransform.localRotation = Quaternion.identity; + detailsTransform.localScale = Vector3.one; + + foreach (ShipLogModule.ShipLogDetailInfo detailInfo in node.mainBody.Config.ShipLog.mapMode.details) + { + MakeDetail(detailInfo, detailsTransform, node.mainBody.Mod.Assets); + } + detailsParent.SetActive(true); + } + } + + private static void MakeNode(ref MapModeObject node, GameObject parent, int layer) + { + const float padding = 250f; + + GameObject newNodeGO = new GameObject(node.mainBody.Config.Name + "_ShipLog"); + newNodeGO.layer = layer; + newNodeGO.transform.SetParent(parent.transform); + + RectTransform transform = newNodeGO.AddComponent(); + float scale = node.mainBody.Config.ShipLog?.mapMode?.scale ?? 1f; + Vector2 position = Vector2.zero; + if (node.lastSibling != null) + { + ShipLogAstroObject lastAstroObject = node.lastSibling.astroObject; + Vector3 lastPosition = lastAstroObject.transform.localPosition; + position = lastPosition; + float extraDistance = (node.mainBody.Config.ShipLog?.mapMode?.offset ?? 0f) * 100; + if (node.level % 2 == 0) + { + position.y += padding * (node.y - node.lastSibling.y) + extraDistance; + } + else + { + position.x += padding * (node.x - node.lastSibling.x) + extraDistance; + } + } + transform.localPosition = new Vector3(position.x, position.y, 0); + transform.localRotation = Quaternion.identity; + transform.localScale = Vector3.one * scale; + CreateShipLogAstroObject(newNodeGO, ref node, GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/MapMode/ScaleRoot/PanRoot/TimberHearth/UnviewedIcon"), layer); + if (node.lastSibling != null) ConnectNodeToLastSibling(node); + MakeDetails(node); + transform.SetAsFirstSibling(); + } + + private static MapModeObject ConstructPrimaryNode(string systemName) + { + foreach (NewHorizonsBody body in Main.BodyDict[systemName].Where(b => b.Config.Base.CenterOfSolarSystem)) + { + List searchList = Main.BodyDict[systemName].Where(b => (b.Config.ShipLog?.mapMode?.remove ?? false) == false).ToList(); + searchList.Sort((b, o) => b.Config.Orbit.SemiMajorAxis.CompareTo(o.Config.Orbit.SemiMajorAxis)); + MapModeObject newNode = new MapModeObject + { + mainBody = body, + level = 0, + x = 0, + y = 0 + }; + newNode.children = ConstructChildrenNodes(systemName, newNode, searchList); + return newNode; + } + Logger.LogError("Couldn't find center of system!"); + return new MapModeObject(); + } + + private static List ConstructChildrenNodes(string systemName, MapModeObject parent, List searchList) + { + List children = new List(); + int newX = parent.x; + int newY = parent.y; + int newLevel = parent.level + 1; + MapModeObject lastSibling = parent; + foreach (NewHorizonsBody body in searchList.Where(b => b.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name)) + { + if (body.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name) + { + bool even = newLevel % 2 == 0; + newX = even ? newX : newX + 1; + newY = even ? newY + 1 : newY; + MapModeObject newNode = new MapModeObject() + { + mainBody = body, + level = newLevel, + x = newX, + y = newY, + parent = parent, + lastSibling = lastSibling + }; + newNode.children = ConstructChildrenNodes(systemName, newNode, searchList); + if (even) + { + newY += newNode.branch_height; + parent.Increment_height(); + newY += 1; + } + else + { + newX += newNode.branch_width; + parent.Increment_width(); + newX += 1; + } + lastSibling = newNode; + children.Add(newNode); + } + } + return children; + } + } + +} diff --git a/NewHorizons/Builder/ShipLog/RevealBuilder.cs b/NewHorizons/Builder/ShipLog/RevealBuilder.cs new file mode 100644 index 00000000..ef8c5aae --- /dev/null +++ b/NewHorizons/Builder/ShipLog/RevealBuilder.cs @@ -0,0 +1,89 @@ +using NewHorizons.Components; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using NewHorizons.External; +using NewHorizons.Utility; +using OWML.Common; +using UnityEngine; +using UnityEngine.UI; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Builder.ShipLog +{ + public static class RevealBuilder + { + public static void Make(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + GameObject newRevealGO = MakeGameObject(go, sector, info, mod); + switch (info.revealOn.ToLower()) + { + case "enter": + MakeTrigger(newRevealGO, sector, info, mod); + break; + case "observe": + MakeObservable(newRevealGO, sector, info, mod); + break; + case "snapshot": + MakeSnapshot(newRevealGO, sector, info, mod); + break; + default: + Logger.LogError("Invalid revealOn: " + info.revealOn); + break; + } + + newRevealGO.SetActive(true); + } + + private static SphereShape MakeShape(GameObject go, PropModule.RevealInfo info, Shape.CollisionMode collisionMode) + { + SphereShape newShape = go.AddComponent(); + newShape.radius = info.radius; + newShape.SetCollisionMode(collisionMode); + return newShape; + } + + private static GameObject MakeGameObject(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + GameObject revealTriggerVolume = new GameObject("Reveal Volume (" + info.revealOn + ")"); + revealTriggerVolume.SetActive(false); + revealTriggerVolume.transform.parent = sector?.transform ?? go.transform; + revealTriggerVolume.transform.localPosition = info.position; + return revealTriggerVolume; + } + + private static void MakeTrigger(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + SphereShape newShape = MakeShape(go, info, Shape.CollisionMode.Volume); + OWTriggerVolume newVolume = go.AddComponent(); + newVolume._shape = newShape; + ShipLogFactListTriggerVolume volume = go.AddComponent(); + volume._factIDs = info.reveals; + } + + private static void MakeObservable(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + go.layer = LayerMask.NameToLayer("Interactible"); + SphereCollider newSphere = go.AddComponent(); + newSphere.radius = info.radius; + OWCollider newCollider = go.AddComponent(); + ShipLogFactObserveTrigger newObserveTrigger = go.AddComponent(); + newObserveTrigger._factIDs = info.reveals; + newObserveTrigger._maxViewDistance = info.maxDistance == -1f ? 2f : info.maxDistance; + newObserveTrigger._maxViewAngle = info.maxAngle; + newObserveTrigger._owCollider = newCollider; + newObserveTrigger._disableColliderOnRevealFact = true; + } + + private static void MakeSnapshot(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + SphereShape newShape = MakeShape(go, info, Shape.CollisionMode.Manual); + ShapeVisibilityTracker newTracker = go.AddComponent(); + newTracker._shapes = new Shape[] { newShape }; + ShipLogFactSnapshotTrigger newSnapshotTrigger = go.AddComponent(); + newSnapshotTrigger._maxDistance = info.maxDistance == -1f ? 200f : info.maxDistance; + newSnapshotTrigger._factIDs = info.reveals; + } + } +} diff --git a/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs b/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs new file mode 100644 index 00000000..0c8869c6 --- /dev/null +++ b/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs @@ -0,0 +1,191 @@ +using NewHorizons.Components; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using NewHorizons.External; +using NewHorizons.Utility; +using OWML.Common; +using UnityEngine; +using UnityEngine.UI; +using Logger = NewHorizons.Utility.Logger; +using NewHorizons.Builder.Handlers; + +namespace NewHorizons.Builder.ShipLog +{ + public static class RumorModeBuilder + { + private static readonly Dictionary _curiosityColors = new Dictionary(); + private static readonly Dictionary _curiosityHighlightColors = new Dictionary(); + private static readonly Dictionary _rawNameToCuriosityName = new Dictionary(); + private static readonly Dictionary _entryIdToRawName = new Dictionary(); + + public static void AddCuriosityColors(ShipLogModule.CuriosityColorInfo[] newColors) + { + foreach (ShipLogModule.CuriosityColorInfo newColor in newColors) + { + if (_rawNameToCuriosityName.ContainsKey(newColor.id) == false) + { + CuriosityName newName = (CuriosityName)8 + _rawNameToCuriosityName.Count; + _rawNameToCuriosityName.Add(newColor.id, newName); + _curiosityColors.Add(newName, newColor.color.ToColor()); + _curiosityHighlightColors.Add(newName, newColor.highlightColor.ToColor()); + } + } + } + + public static Color GetCuriosityColor(CuriosityName curiosityName, bool highlighted, Color defaultColor, Color defaultHighlight) + { + if (_curiosityColors.ContainsKey(curiosityName) && _curiosityHighlightColors.ContainsKey(curiosityName)) + { + return (highlighted ? _curiosityHighlightColors : _curiosityColors)[curiosityName]; + } + else + { + return highlighted ? defaultHighlight : defaultColor; + } + } + + public static void AddBodyToShipLog(ShipLogManager manager, NewHorizonsBody body) + { + string systemName = body.Config.StarSystem; + XElement astroBodyFile = XElement.Load(Main.Instance.ModHelper.Manifest.ModFolderPath + body.Config.ShipLog.xmlFile); + XElement astroBodyId = astroBodyFile.Element("ID"); + if (astroBodyId == null) + { + Logger.LogError("Failed to load ship logs for " + systemName + "!"); + } + else + { + astroBodyId.SetValue(systemName + "/" + astroBodyId.Value); + foreach (XElement entryElement in astroBodyFile.DescendantsAndSelf("Entry")) + { + XElement curiosityName = entryElement.Element("Curiosity"); + XElement id = entryElement.Element("ID"); + if (curiosityName != null && id != null && _entryIdToRawName.ContainsKey(id.Value) == false) + { + _entryIdToRawName.Add(id.Value, curiosityName.Value); + } + AddTranslation(entryElement); + } + TextAsset newAsset = new TextAsset(astroBodyFile.ToString()); + List newBodies = new List(manager._shipLogXmlAssets) { newAsset }; + manager._shipLogXmlAssets = newBodies.ToArray(); + ShipLogHandler.AddConfig(astroBodyId.Value, body); + } + } + + public static void GenerateEntryData(ShipLogManager manager) + { + const int step = 400; + int colAccumulator = 0; + int rowAccumulator = 0; + foreach (ShipLogEntry entry in manager._entryList) + { + if (manager._entryDataDict.ContainsKey(entry._id) == false) + { + NewHorizonsBody body = ShipLogHandler.GetConfigFromID(entry._astroObjectID); + Vector2? manualEntryPosition = GetManualEntryPosition(entry._id, body.Config.ShipLog); + Vector2 entryPosition; + if (manualEntryPosition == null) + { + entryPosition = new Vector2(colAccumulator, rowAccumulator); + } + else + { + entryPosition = (Vector2)manualEntryPosition; + } + EntryData newData = new EntryData + { + id = entry._id, + cardPosition = entryPosition, + sprite = body.Config.ShipLog.spriteFolder == null ? null : GetEntrySprite(entry._id, body) + }; + entry.SetSprite(newData.sprite == null ? manager._shipLogLibrary.defaultEntrySprite : newData.sprite); + manager._entryDataDict.Add(entry._id, newData); + int index = manager._entryList.IndexOf(entry); + if (index < manager._entryList.Count - 2 && manager._entryList[index + 1]._astroObjectID != entry._astroObjectID) + { + rowAccumulator += step; + colAccumulator = 0; + } + else + { + colAccumulator += step; + } + } + } + } + + private static void AddTranslation(XElement entry) + { + Dictionary table = TextTranslation.Get().m_table.theShipLogTable; + XElement nameElement = entry.Element("Name"); + if (nameElement != null) + { + string name = nameElement.Value; + table[name] = name; + foreach (XElement rumorFact in entry.Elements("RumorFact")) + { + XElement rumorName = rumorFact.Element("RumorName"); + if (rumorName != null) + { + table[rumorName.Value] = rumorName.Value; + } + + XElement rumorText = rumorFact.Element("Text"); + if (rumorText != null) + { + table[name + rumorText.Value] = rumorText.Value; + } + } + foreach (XElement exploreFact in entry.Elements("ExploreFact")) + { + XElement exploreText = exploreFact.Element("Text"); + if (exploreText != null) + { + table[name + exploreText.Value] = exploreText.Value; + } + } + } + } + + public static void UpdateEntryCuriosity(ref ShipLogEntry entry) + { + if (_entryIdToRawName.ContainsKey(entry._id)) + { + entry._curiosity = _rawNameToCuriosityName[_entryIdToRawName[entry._id]]; + } + } + + private static Sprite GetEntrySprite(string entryId, NewHorizonsBody body) + { + IModAssets assets = body.Mod.Assets; + string path = body.Config.ShipLog.spriteFolder + "/" + entryId + ".png"; + if (File.Exists(Main.Instance.ModHelper.Manifest.ModFolderPath + path)) + { + Texture2D newTexture = assets.GetTexture(path); + Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); + Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); + return Sprite.Create(newTexture, rect, pivot); + } + else + { + return null; + } + } + + private static Vector2? GetManualEntryPosition(string entryId, ShipLogModule config) + { + if (config.positions == null) return null; + foreach (ShipLogModule.EntryPositionInfo position in config.positions) + { + if (position.id == entryId) + { + return position.position; + } + } + return null; + } + } +} diff --git a/NewHorizons/Handlers/ShipLogHandler.cs b/NewHorizons/Handlers/ShipLogHandler.cs new file mode 100644 index 00000000..ff565b54 --- /dev/null +++ b/NewHorizons/Handlers/ShipLogHandler.cs @@ -0,0 +1,46 @@ +using NewHorizons.Components; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using NewHorizons.External; +using NewHorizons.Utility; +using OWML.Common; +using UnityEngine; +using UnityEngine.UI; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Builder.Handlers +{ + public static class ShipLogHandler + { + public static readonly string PAN_ROOT_PATH = "Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/MapMode/ScaleRoot/PanRoot"; + + private static Dictionary _astroIdToBody = new Dictionary(); + + public static NewHorizonsBody GetConfigFromID(string id) + { + return _astroIdToBody.ContainsKey(id) ? _astroIdToBody[id] : null; + } + + public static void AddConfig(string id, NewHorizonsBody body) + { + if (!_astroIdToBody.ContainsKey(id)) + { + _astroIdToBody.Add(id, body); + } + } + + public static string GetAstroObjectId(NewHorizonsBody body) + { + if (_astroIdToBody.ContainsValue(body)) + { + return CollectionUtilities.KeyByValue(_astroIdToBody, body); + } + else + { + return body.Config.Name; + } + } + } +} diff --git a/NewHorizons/Tools/Patches.cs b/NewHorizons/Tools/Patches.cs index 2a74328e..91be6c27 100644 --- a/NewHorizons/Tools/Patches.cs +++ b/NewHorizons/Tools/Patches.cs @@ -17,6 +17,8 @@ using UnityEngine; using Logger = NewHorizons.Utility.Logger; using Object = UnityEngine.Object; using NewHorizons.Handlers; +using NewHorizons.Builder.ShipLog; +using NewHorizons.Builder.Handlers; namespace NewHorizons.Tools { @@ -409,25 +411,25 @@ namespace NewHorizons.Tools { if (body.Config.ShipLog?.curiosities != null) { - ShipLogBuilder.RumorModeBuilder.AddCuriosityColors(body.Config.ShipLog.curiosities); + RumorModeBuilder.AddCuriosityColors(body.Config.ShipLog.curiosities); } } foreach (NewHorizonsBody body in Main.BodyDict[Main.Instance.CurrentStarSystem]) { if (body.Config.ShipLog?.xmlFile != null) { - ShipLogBuilder.RumorModeBuilder.AddBodyToShipLog(__instance, body); + RumorModeBuilder.AddBodyToShipLog(__instance, body); } } } public static void OnShipLogManagerAwakeComplete(ShipLogManager __instance) { - ShipLogBuilder.RumorModeBuilder.GenerateEntryData(__instance); + RumorModeBuilder.GenerateEntryData(__instance); for (var i = 0; i < __instance._entryList.Count; i++) { ShipLogEntry logEntry = __instance._entryList[i]; - ShipLogBuilder.RumorModeBuilder.UpdateEntryCuriosity(ref logEntry); + RumorModeBuilder.UpdateEntryCuriosity(ref logEntry); } Logger.Log("Ship Log Generation Complete For: " + Main.Instance.CurrentStarSystem, Logger.LogType.Log); } @@ -472,7 +474,7 @@ namespace NewHorizons.Tools __instance.RevealFact(fact, false, false); } } - ShipLogBuilder.EntryLocationBuilder.InitializeLocations(); + EntryLocationBuilder.InitializeLocations(); return false; } } @@ -485,23 +487,23 @@ namespace NewHorizons.Tools } else { - __result = ShipLogBuilder.RumorModeBuilder.GetCuriosityColor(__0, __1, __instance._neutralColor, __instance._neutralHighlight); + __result = RumorModeBuilder.GetCuriosityColor(__0, __1, __instance._neutralColor, __instance._neutralHighlight); return false; } } private static void DeleteDetail(string name) { - Object.Destroy(GameObject.Find(ShipLogBuilder.PAN_ROOT_PATH + "/" + name)); + Object.Destroy(GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + name)); } public static void OnShipLogMapModeInitialize(ShipLogMapMode __instance) { if (Main.Instance.CurrentStarSystem != "SolarSystem") { - GameObject panRoot = GameObject.Find(ShipLogBuilder.PAN_ROOT_PATH); - GameObject sunObject = GameObject.Find(ShipLogBuilder.PAN_ROOT_PATH + "/Sun"); - ShipLogAstroObject[][] navMatrix = ShipLogBuilder.MapModeBuilder.ConstructMapMode(Main.Instance.CurrentStarSystem, panRoot, sunObject.layer); + GameObject panRoot = GameObject.Find(ShipLogHandler.PAN_ROOT_PATH); + GameObject sunObject = GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/Sun"); + ShipLogAstroObject[][] navMatrix = MapModeBuilder.ConstructMapMode(Main.Instance.CurrentStarSystem, panRoot, sunObject.layer); if (navMatrix.Length <= 1) { Logger.LogWarning("No planets suitable for map mode found! Defaulting to vanilla menu (expect weirdness!)."); @@ -530,7 +532,7 @@ namespace NewHorizons.Tools } else { - __result = ShipLogBuilder.MapModeBuilder.GetAstroBodyShipLogName(__instance.GetID()); + __result = MapModeBuilder.GetAstroBodyShipLogName(__instance.GetID()); return false; } } diff --git a/NewHorizons/Utility/CollectionUtilities.cs b/NewHorizons/Utility/CollectionUtilities.cs new file mode 100644 index 00000000..e4b49e6d --- /dev/null +++ b/NewHorizons/Utility/CollectionUtilities.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.Utility +{ + public static class CollectionUtilities + { + public static T KeyByValue(Dictionary dict, W val) + { + T key = default; + foreach (KeyValuePair pair in dict) + { + if (EqualityComparer.Default.Equals(pair.Value, val)) + { + key = pair.Key; + break; + } + } + return key; + } + } +}