diff --git a/.voidbot/state/aetheria.cc b/.voidbot/state/aetheria.cc index df5e0f10d..35312cb14 100644 Binary files a/.voidbot/state/aetheria.cc and b/.voidbot/state/aetheria.cc differ diff --git a/Assets/Scripts/UI/Menu/TradeMenuDebug.cs b/Assets/Scripts/UI/Menu/TradeMenuDebug.cs deleted file mode 100644 index e9576eb29..000000000 --- a/Assets/Scripts/UI/Menu/TradeMenuDebug.cs +++ /dev/null @@ -1,481 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Runtime.Remoting.Contexts; -using TMPro; -using UnityEngine; -using UnityEngine.UI; -using Unity.Mathematics; -using static Unity.Mathematics.math; - -public class TradeMenuDebug : MonoBehaviour -{ - public ActionGameManager GameManager; - public ContextMenu ContextMenu; - public ConfirmationDialog Dialog; - public Button NewFilterButton; - public Prototype FilterPrototype; - public SizeFilter MinimumSizeFilter; - public SizeFilter MaximumSizeFilter; - public PropertiesPanel Properties; - public Spreadsheet Spreadsheet; - public TextMeshProUGUI TargetCargoLabel; - public Button FoldoutButton; - - private EquippedCargoBay _targetCargo; - private (ItemFilter filter, HardpointType type) _hardpointFilter; - private (ItemFilter filter, SimpleCommodityCategory type) _commodityFilter; - private (ItemFilter filter, CompoundCommodityCategory type) _compoundCommodityFilter; - private List<(ItemFilter filter, Type type)> _behaviorFilters = new List<(ItemFilter filter, Type type)>(); - - private void OnEnable() - { - _targetCargo = GameManager.DockingBay; - TargetCargoLabel.text = "Docking Bay"; - Properties.GameManager = GameManager; - MinimumSizeFilter.Width.onEndEdit.AddListener(_ => Populate()); - MinimumSizeFilter.Height.onEndEdit.AddListener(_ => Populate()); - MaximumSizeFilter.Width.onEndEdit.AddListener(_ => Populate()); - MaximumSizeFilter.Height.onEndEdit.AddListener(_ => Populate()); - NewFilterButton.onClick.AddListener(() => - { - ContextMenu.Clear(); - IEnumerable hardpointTypes = (HardpointType[]) Enum.GetValues(typeof(HardpointType)); - if (_hardpointFilter.filter != null) - hardpointTypes = hardpointTypes.Where(x => x != _hardpointFilter.type); - - IEnumerable commodityTypes = (SimpleCommodityCategory[]) Enum.GetValues(typeof(SimpleCommodityCategory)); - if (_commodityFilter.filter != null) - commodityTypes = commodityTypes.Where(x => x != _commodityFilter.type); - - IEnumerable compoundCommodityTypes = (CompoundCommodityCategory[]) Enum.GetValues(typeof(CompoundCommodityCategory)); - if (_compoundCommodityFilter.filter != null) - compoundCommodityTypes = compoundCommodityTypes.Where(x => x != _compoundCommodityFilter.type); - - ContextMenu.AddDropdown("Gear Type", hardpointTypes - .Select(x => (Enum.GetName(typeof(HardpointType), x), () => - { - if (_hardpointFilter.filter == null) - { - _hardpointFilter.filter = FilterPrototype.Instantiate(); - _hardpointFilter.filter.OnDisable += () => - { - _hardpointFilter.filter = null; - Populate(); - }; - } - if(_commodityFilter.filter != null) - { - _commodityFilter.filter.GetComponent().ReturnToPool(); - _commodityFilter.filter = null; - } - if(_compoundCommodityFilter.filter != null) - { - _compoundCommodityFilter.filter.GetComponent().ReturnToPool(); - _compoundCommodityFilter.filter = null; - } - - _hardpointFilter.filter.Label.text = $"Hardpoint: {Enum.GetName(typeof(HardpointType), x)}"; - _hardpointFilter.type = x; - Populate(); - }, true))); - ContextMenu.AddDropdown("Simple Commodity", commodityTypes - .Select(x => (Enum.GetName(typeof(SimpleCommodityCategory), x), () => - { - if (_commodityFilter.filter == null) - { - _commodityFilter.filter = FilterPrototype.Instantiate(); - _commodityFilter.filter.OnDisable += () => - { - _commodityFilter.filter = null; - Populate(); - }; - } - if(_hardpointFilter.filter != null) - { - _hardpointFilter.filter.GetComponent().ReturnToPool(); - _hardpointFilter.filter = null; - } - if(_compoundCommodityFilter.filter != null) - { - _compoundCommodityFilter.filter.GetComponent().ReturnToPool(); - _compoundCommodityFilter.filter = null; - } - - _commodityFilter.filter.Label.text = $"Hardpoint: {Enum.GetName(typeof(SimpleCommodityCategory), x)}"; - _commodityFilter.type = x; - Populate(); - }, true))); - ContextMenu.AddDropdown("Compound Commodity", compoundCommodityTypes - .Select(x => (Enum.GetName(typeof(CompoundCommodityCategory), x), () => - { - if (_compoundCommodityFilter.filter == null) - { - _compoundCommodityFilter.filter = FilterPrototype.Instantiate(); - _compoundCommodityFilter.filter.OnDisable += () => - { - _compoundCommodityFilter.filter = null; - Populate(); - }; - } - if(_hardpointFilter.filter != null) - { - _hardpointFilter.filter.GetComponent().ReturnToPool(); - _hardpointFilter.filter = null; - } - if(_commodityFilter.filter != null) - { - _commodityFilter.filter.GetComponent().ReturnToPool(); - _commodityFilter.filter = null; - } - - _compoundCommodityFilter.filter.Label.text = $"Hardpoint: {Enum.GetName(typeof(CompoundCommodityCategory), x)}"; - _compoundCommodityFilter.type = x; - Populate(); - }, true))); - ContextMenu.AddDropdown("Item Behavior", typeof(BehaviorData).GetAllChildClasses() - .Where(x=> x.GetCustomAttribute() != null && _behaviorFilters.All(f => f.type != x)) - .Select(x=> (x.Name.FormatTypeName(), () => - { - var matchingType = _behaviorFilters.FirstOrDefault(y => y.type.IsAssignableFrom(x) || x.IsAssignableFrom(y.type)); - if (matchingType.filter != null) matchingType.filter.DisableButton.onClick.Invoke(); - var filter = FilterPrototype.Instantiate(); - filter.Label.text = x.Name.FormatTypeName(); - filter.OnDisable += () => - { - _behaviorFilters.Remove((filter, x)); - Populate(); - }; - _behaviorFilters.Add((filter, x)); - Populate(); - }, true))); - if(!MinimumSizeFilter.gameObject.activeSelf) - ContextMenu.AddOption("Minimum Size", - () => - { - MinimumSizeFilter.gameObject.SetActive(true); - MinimumSizeFilter.OnDisable += () => Populate(); - }); - if(!MaximumSizeFilter.gameObject.activeSelf) - ContextMenu.AddOption("Maximum Size", - () => - { - MaximumSizeFilter.gameObject.SetActive(true); - MaximumSizeFilter.OnDisable += () => Populate(); - }); - ContextMenu.Show(); - }); - Populate(); - } - - void Populate() - { - var columns = new List<(string name, int size, Func> output, Func sortKey)>(); - - columns.Add(("Name", 3, - data => () => data.Name, - data => data.Name)); - if(_hardpointFilter.filter==null) - columns.Add(("Type", 2, - data => () => - { - if (data is SimpleCommodityData s) return Enum.GetName(typeof(SimpleCommodityCategory), s.Category); - if(data is CompoundCommodityData c) return Enum.GetName(typeof(CompoundCommodityCategory), c.Category); - if(data is EquippableItemData e) return Enum.GetName(typeof(HardpointType), e.HardpointType); - return "None"; - }, - data => - { - if (data is SimpleCommodityData s) return (int) s.Category; - var offset = Enum.GetValues(typeof(SimpleCommodityCategory)).Length; - if(data is CompoundCommodityData c) return (int) c.Category + offset; - offset += Enum.GetValues(typeof(CompoundCommodityCategory)).Length; - if(data is EquippableItemData e) return (int) e.HardpointType + offset; - return 0; - })); - columns.Add(("Mass", 1, - data => () => ActionGameManager.PlayerSettings.Format(data.Mass), - data => data.Mass)); - columns.Add(("Price", 1, - data => () => data.Price.ToString("N0"), - data => data.Price)); - columns.Add(("Size", 1, - data => () => $"{data.Shape.Width}x{data.Shape.Height}", - data => data.Shape.Width*data.Shape.Height)); - - var items = ActionGameManager.RuntimeCatalog.TradeItems - .Select(HydrateLegacyItem) - .Where(i => i != null); - - if (MinimumSizeFilter.gameObject.activeSelf) - items = items.Where(i => - !(MinimumSizeFilter.Width.text.Length > 0 && i.Shape.Width < int.Parse(MinimumSizeFilter.Width.text) || - MinimumSizeFilter.Height.text.Length > 0 && i.Shape.Height < int.Parse(MinimumSizeFilter.Height.text))); - - if (MaximumSizeFilter.gameObject.activeSelf) - items = items.Where(i => - !(MaximumSizeFilter.Width.text.Length > 0 && i.Shape.Width > int.Parse(MaximumSizeFilter.Width.text) || - MaximumSizeFilter.Height.text.Length > 0 && i.Shape.Height > int.Parse(MaximumSizeFilter.Height.text))); - - if(_commodityFilter.filter != null) - items = items.Where(i => i is SimpleCommodityData s && s.Category == _commodityFilter.type); - - if(_compoundCommodityFilter.filter != null) - items = items.Where(i => i is CompoundCommodityData c && c.Category == _compoundCommodityFilter.type); - - if (_hardpointFilter.filter != null) - items = items.Where(i => i is EquippableItemData e && e.HardpointType == _hardpointFilter.type); - - foreach (var (_, type) in _behaviorFilters) - { - items = items.Where(i => i is EquippableItemData e && e.Behaviors.Any(b => type.IsInstanceOfType(b))); - - foreach (var field in type.GetFields().Where(f => f.GetCustomAttribute() != null)) - { - var fieldType = field.FieldType; - if (fieldType == typeof(float)) - columns.Add((field.Name, 1, data => - { - var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b)); - return () => ActionGameManager.PlayerSettings.Format((float) field.GetValue(behavior)); - }, data => - { - var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b)); - return (float) field.GetValue(behavior); - })); - else if (fieldType == typeof(int)) - columns.Add((field.Name, 1, data => - { - var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b)); - return () => ((int) field.GetValue(behavior)).ToString(); - }, data => - { - var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b)); - return (int) field.GetValue(behavior); - })); - else if (fieldType == typeof(PerformanceStat)) - { - columns.Add((field.Name, 1, data => - { - var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b)); - return () => ActionGameManager.PlayerSettings.Format(((PerformanceStat) field.GetValue(behavior)).Max); - }, data => - { - var behavior = ((EquippableItemData) data).Behaviors.FirstOrDefault(b => type.IsInstanceOfType(b)); - return ((PerformanceStat) field.GetValue(behavior)).Max; - })); - } - } - } - - columns.Add(("Owned", 1, - data => () => - { - if (data is HullData) - return GameManager.DockedEntity.Children.Count(s => s.Hull.Data.LinkID == data.ID && s is Ship {IsPlayerShip: true}).ToString(); - if(data is SimpleCommodityData) - return (_targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Cast().Sum(s=>s.Quantity) : 0).ToString(); - return (_targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Count : 0).ToString(); - }, - data => - { - if (data is HullData) - return GameManager.DockedEntity.Children.Count(s => s.Hull.Data.LinkID == data.ID && s is Ship {IsPlayerShip: true}); - if(data is SimpleCommodityData) - return _targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Cast().Sum(s=>s.Quantity) : 0; - return _targetCargo.ItemsOfType.ContainsKey(data.ID) ? _targetCargo.ItemsOfType[data.ID].Count : 0; - })); - - Spreadsheet.ShowData( - columns.Select(x => x.name).ToArray(), - columns.Select(x => x.size).ToArray(), - items.Select(i => new SpreadsheetEntryRow - { - Columns = columns.Select(x => new SpreadsheetEntryColumn - { - Output = x.output(i), - SortKey = x.sortKey(i) - }).ToArray(), - OnClick = () => - { - Properties.Inspect(i); - }, - OnDoubleClick = () => - { - switch (i) - { - case HullData h: - Buy(h); - break; - case CraftedItemData c: - Buy(c,1); - break; - case SimpleCommodityData s: - Buy(s, 1); - break; - } - - Populate(); - }, - OnRightClick = () => - { - if (!(i is HullData)) - { - ContextMenu.Clear(); - ContextMenu.AddOption("Buy Quantity", - () => - { - int quantity = 1; - Dialog.Clear(); - Dialog.Title.text = $"Buying {i.Name}"; - Dialog.AddField("Quantity", () => quantity, q => quantity = min(q, GameManager.Credits/i.Price)); - Dialog.Show(() => - { - switch (i) - { - case CraftedItemData c: - Buy(c,quantity); - break; - case SimpleCommodityData s: - Buy(s, quantity); - break; - } - - Populate(); - }); - Dialog.MoveToCursor(); - }); - ContextMenu.Show(); - } - } - })); - } - - private ItemData HydrateLegacyItem(GameCult.Aetheria.State.Unity.AetheriaRuntimeCatalogItem item) - { - return Guid.TryParse(item.LegacyId, out var legacyId) - ? GameManager.ItemManager.GetCatalogEntry(legacyId) - : null; - } - - private void Buy(HullData data) - { - if (data.Price < GameManager.Credits) - { - var hull = GameManager.ItemManager.CreateInstance(data) as EquippableItem; - Entity entity; - if(data.HullType==HullType.Ship) - entity = new Ship(GameManager.ItemManager, GameManager.Zone, hull, GameManager.Settings.GameplaySettings.DefaultEntitySettings) {IsPlayerShip = true}; - else entity = new OrbitalEntity(GameManager.ItemManager, GameManager.Zone, hull, Guid.Empty, GameManager.Settings.GameplaySettings.DefaultEntitySettings); - entity.SetParent(GameManager.DockedEntity); - - GameManager.Credits -= data.Price; - } - else - { - Dialog.Clear(); - Dialog.Title.text = "Unable to buy: Insufficient Credits!"; - Dialog.Show(); - Dialog.MoveToCursor(); - } - } - - private void Buy(CraftedItemData data, int quantity) - { - for (int i = 0; i < quantity; i++) - { - if (data.Price < GameManager.Credits) - { - if (_targetCargo.TryStore(GameManager.ItemManager.CreateInstance(data))) - { - GameManager.Credits -= data.Price; - } - else - { - Dialog.Clear(); - Dialog.Title.text = "Unable to buy: Insufficient Cargo Space!"; - Dialog.Show(); - Dialog.MoveToCursor(); - return; - } - } - else - { - Dialog.Clear(); - Dialog.Title.text = "Unable to buy: Insufficient Credits!"; - Dialog.Show(); - Dialog.MoveToCursor(); - return; - } - } - } - - private void Buy(SimpleCommodityData data, int quantity) - { - // Up-rounded integer division from https://stackoverflow.com/a/503201 - int lots = (quantity - 1) / data.MaxStack + 1; - int remaining = quantity; - for (int i = 0; i < lots; i++) - { - int q = min(remaining, data.MaxStack); - if (q * data.Price < GameManager.Credits) - { - if (_targetCargo.TryStore(GameManager.ItemManager.CreateInstance(data, q))) - { - GameManager.Credits -= q * data.Price; - remaining -= q; - } - else - { - Dialog.Clear(); - Dialog.Title.text = "Unable to buy: Insufficient Cargo Space!"; - Dialog.Show(); - Dialog.MoveToCursor(); - return; - } - } - else - { - Dialog.Clear(); - Dialog.Title.text = "Unable to buy: Insufficient Credits!"; - Dialog.Show(); - Dialog.MoveToCursor(); - return; - } - - - } - } - - void Start() - { - FoldoutButton.onClick.AddListener(() => - { - ContextMenu.Clear(); - if(_targetCargo != GameManager.DockingBay) - ContextMenu.AddOption("Docking Bay", - () => - { - _targetCargo = GameManager.DockingBay; - TargetCargoLabel.text = "Docking Bay"; - }); - foreach (var ship in GameManager.CurrentEntity.Parent.Children.Where(e => e is Ship {IsPlayerShip: true})) - { - foreach (var bay in ship.CargoBays.Select((bay, index) => (bay, index))) - ContextMenu.AddOption($"{ship.Name} Bay {bay.index}", - () => - { - _targetCargo = bay.bay; - TargetCargoLabel.text = $"{ship.Name} Bay {bay.index}"; - }); - } - }); - } - - void Update() - { - - } -} diff --git a/Assets/Scripts/UI/Menu/TradeMenuDebug.cs.meta b/Assets/Scripts/UI/Menu/TradeMenuDebug.cs.meta deleted file mode 100644 index f5bd7bf73..000000000 --- a/Assets/Scripts/UI/Menu/TradeMenuDebug.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 6eed32eb39c04a31b81e8a55685b222c -timeCreated: 1616191013 \ No newline at end of file diff --git a/docs/aetheria-perfect-machine-map.md b/docs/aetheria-perfect-machine-map.md index 05c5b760a..7a4fd0a61 100644 --- a/docs/aetheria-perfect-machine-map.md +++ b/docs/aetheria-perfect-machine-map.md @@ -100,9 +100,9 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. `EquippableItemData` by ID only for `ItemManager.CreateInstance`. `LoadoutGenerator` also receives the typed runtime catalog and uses it to own item candidate selection before hydrating selected legacy item DTOs by ID for - exact fitting checks and behavior construction. - `TradeMenuDebug` uses the typed trade catalog for rows and only hydrates - legacy `ItemData` by ID for its old inspect/buy UI callbacks. + exact fitting checks and behavior construction. The unused `TradeMenuDebug` + script has been deleted instead of preserving an old uGUI debug path that + turned typed trade rows back into legacy `ItemData` objects. - `Galaxy` generation no longer accepts `ILegacyCatalogReader` or `ItemManager`. Sector and tutorial generation receive the package-owned typed runtime catalog. `Galaxy` projects typed corporation v2 records into temporary legacy @@ -268,8 +268,7 @@ legacy catalog cache, and legacy UI paths should be migration-only or deleted. owns simulation. The legacy cache no longer has a public mutation surface, but it still materializes `ItemManager`. Item properties manufacturer display is a typed snapshot consumer; the give console command, loadout generation, and - trade debug are typed-selection consumers with temporary legacy item - instantiation or UI callback hydration. No live caller can enumerate legacy + old trade debug UI has been deleted. No live caller can enumerate legacy catalog entries through `ItemManager` or `ILegacyCatalogReader`. - Inputs: Unity gameplay code, legacy catalog files, typed state documents, and CultMesh server state. @@ -428,8 +427,8 @@ First Aetheria surfaces to publish: - Done: move `LoadoutGenerator` item candidate selection to the typed runtime catalog; legacy item DTO hydration remains only for exact fitting checks and behavior construction. - - Done: move `TradeMenuDebug` row selection to the typed trade catalog; - legacy item DTO hydration remains only for old inspect/buy callbacks. + - Done: delete unused `TradeMenuDebug`; the old debug uGUI trade path no + longer hydrates typed trade rows back into legacy `ItemData` objects. - Done: delete `ItemManager.GetCatalogEntries` after all live callers moved to typed catalog selection. - Done: delete `ILegacyCatalogReader.GetAll` and the type/global indexes