diff --git a/Projects/UOContent/Gumps/Go/GoCategory.cs b/Projects/UOContent/Gumps/Go/GoCategory.cs index 6d1588884..ed381872e 100644 --- a/Projects/UOContent/Gumps/Go/GoCategory.cs +++ b/Projects/UOContent/Gumps/Go/GoCategory.cs @@ -1,15 +1,14 @@ using System.Text.Json.Serialization; -namespace Server.Gumps +namespace Server.Gumps; + +public class GoCategory { - public class GoCategory - { - public GoCategory Parent { get; set; } + public GoCategory Parent { get; set; } - [JsonPropertyName("locations")] public GoLocation[] Locations { get; set; } + [JsonPropertyName("locations")] public GoLocation[] Locations { get; set; } - [JsonPropertyName("categories")] public GoCategory[] Categories { get; set; } + [JsonPropertyName("categories")] public GoCategory[] Categories { get; set; } - [JsonPropertyName("name")] public string Name { get; set; } - } -} + [JsonPropertyName("name")] public string Name { get; set; } +} \ No newline at end of file diff --git a/Projects/UOContent/Gumps/Go/GoGump.cs b/Projects/UOContent/Gumps/Go/GoGump.cs index 30f152a92..5f22c6dbd 100644 --- a/Projects/UOContent/Gumps/Go/GoGump.cs +++ b/Projects/UOContent/Gumps/Go/GoGump.cs @@ -3,268 +3,235 @@ using Server.Network; using static Server.Gumps.PropsConfig; -namespace Server.Gumps +namespace Server.Gumps; + +public class GoGump : Gump { - public class GoGump : Gump + private const int PrevLabelOffsetX = PrevWidth + 1; + private const int PrevLabelOffsetY = 0; + + private const int NextLabelOffsetX = -29; + private const int NextLabelOffsetY = 0; + + private const int EntryWidth = 180; + private const int EntryCount = 15; + + private const int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; + + private const int BackWidth = BorderSize + TotalWidth + BorderSize; + + private readonly GoCategory _node; + private readonly int _page; + + private readonly LocationTree _tree; + + private GoGump(int page, Mobile from, LocationTree tree, GoCategory node) : base(50, 50) { - private static LocationTree Felucca; - private static LocationTree Trammel; - private static LocationTree Ilshenar; - private static LocationTree Malas; - private static LocationTree Tokuno; - private static LocationTree TerMur; + from.CloseGump(); - private static readonly int PrevLabelOffsetX = PrevWidth + 1; - private static readonly int PrevLabelOffsetY = 0; - - private static readonly int NextLabelOffsetX = -29; - private static readonly int NextLabelOffsetY = 0; - - private static readonly int EntryWidth = 180; - private static readonly int EntryCount = 15; - - private static readonly int TotalWidth = OffsetSize + EntryWidth + OffsetSize + SetWidth + OffsetSize; - - private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize; - - private readonly GoCategory m_Node; - private readonly int m_Page; - - private readonly LocationTree m_Tree; - - private GoGump(int page, Mobile from, LocationTree tree, GoCategory node) : base(50, 50) + if (node == tree.Root) { - from.CloseGump(); + tree.LastBranch.Remove(from); + } + else + { + tree.LastBranch[from] = node; + } - if (node == tree.Root) + _page = page; + _tree = tree; + _node = node; + + var x = BorderSize + OffsetSize; + var y = BorderSize + OffsetSize; + + var count = Math.Clamp(node.Categories.Length + node.Locations.Length - page * EntryCount, 0, EntryCount); + + var totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); + + AddPage(0); + + AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); + AddImageTiled( + BorderSize, + BorderSize, + TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), + totalHeight, + OffsetGumpID + ); + + if (OldStyle) + { + AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + } + else + { + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + } + + if (node.Parent != null) + { + AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); + + if (PrevLabel) { - tree.LastBranch.Remove(from); - } - else - { - tree.LastBranch[from] = node; + AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); } + } - m_Page = page; - m_Tree = tree; - m_Node = node; + x += PrevWidth + OffsetSize; - var x = BorderSize + OffsetSize; - var y = BorderSize + OffsetSize; + var emptyWidth = TotalWidth - PrevWidth * 2 - NextWidth - OffsetSize * 5 - + (OldStyle ? SetWidth + OffsetSize : 0); - var count = Math.Clamp(node.Categories.Length + node.Locations.Length - page * EntryCount, 0, EntryCount); - - var totalHeight = OffsetSize + (EntryHeight + OffsetSize) * (count + 1); - - AddPage(0); - - AddBackground(0, 0, BackWidth, BorderSize + totalHeight + BorderSize, BackGumpID); + if (!OldStyle) + { AddImageTiled( - BorderSize, - BorderSize, - TotalWidth - (OldStyle ? SetWidth + OffsetSize : 0), - totalHeight, - OffsetGumpID + x - (OldStyle ? OffsetSize : 0), + y, + emptyWidth + (OldStyle ? OffsetSize * 2 : 0), + EntryHeight, + EntryGumpID ); + } - if (OldStyle) + AddHtml(x + TextOffsetX, y, emptyWidth - TextOffsetX, EntryHeight, $"
{node.Name}
"); + + x += emptyWidth + OffsetSize; + + if (OldStyle) + { + AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); + } + else + { + AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); + } + + if (page > 0) + { + AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 2); + + if (PrevLabel) { - AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); - } - else - { - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - } - - if (node.Parent != null) - { - AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 1); - - if (PrevLabel) - { - AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); - } - } - - x += PrevWidth + OffsetSize; - - var emptyWidth = TotalWidth - PrevWidth * 2 - NextWidth - OffsetSize * 5 - - (OldStyle ? SetWidth + OffsetSize : 0); - - if (!OldStyle) - { - AddImageTiled( - x - (OldStyle ? OffsetSize : 0), - y, - emptyWidth + (OldStyle ? OffsetSize * 2 : 0), - EntryHeight, - EntryGumpID - ); - } - - AddHtml(x + TextOffsetX, y, emptyWidth - TextOffsetX, EntryHeight, $"
{node.Name}
"); - - x += emptyWidth + OffsetSize; - - if (OldStyle) - { - AddImageTiled(x, y, TotalWidth - OffsetSize * 3 - SetWidth, EntryHeight, HeaderGumpID); - } - else - { - AddImageTiled(x, y, PrevWidth, EntryHeight, HeaderGumpID); - } - - if (page > 0) - { - AddButton(x + PrevOffsetX, y + PrevOffsetY, PrevButtonID1, PrevButtonID2, 2); - - if (PrevLabel) - { - AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); - } - } - - x += PrevWidth + OffsetSize; - - if (!OldStyle) - { - AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); - } - - if ((page + 1) * EntryCount < node.Categories.Length + node.Locations.Length) - { - AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 3, GumpButtonType.Reply, 1); - - if (NextLabel) - { - AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); - } - } - - var totalEntryCount = node.Categories.Length + node.Locations.Length; - - for (int i = 0, index = page * EntryCount; i < EntryCount && index < totalEntryCount; ++i, ++index) - { - x = BorderSize + OffsetSize; - y += EntryHeight + OffsetSize; - - var name = index >= node.Categories.Length - ? node.Locations[index - node.Categories.Length].Name - : node.Categories[index].Name; - - AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); - AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, name); - - x += EntryWidth + OffsetSize; - - if (SetGumpID != 0) - { - AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); - } - - AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, index + 4); + AddLabel(x + PrevLabelOffsetX, y + PrevLabelOffsetY, TextHue, "Previous"); } } - public static void DisplayTo(Mobile from) + x += PrevWidth + OffsetSize; + + if (!OldStyle) { - LocationTree tree; + AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID); + } - if (from.Map == Map.Ilshenar) - { - tree = Ilshenar ??= new LocationTree("ilshenar", Map.Ilshenar); - } - else if (from.Map == Map.Felucca) - { - tree = Felucca ??= new LocationTree("felucca", Map.Felucca); - } - else if (from.Map == Map.Trammel) - { - tree = Trammel ??= new LocationTree("trammel", Map.Trammel); - } - else if (from.Map == Map.Malas) - { - tree = Malas ??= new LocationTree("malas", Map.Malas); - } - else if (from.Map == Map.Tokuno) - { - tree = Tokuno ??= new LocationTree("tokuno", Map.Tokuno); - } - else - { - tree = TerMur ??= new LocationTree("termur", Map.TerMur); - } + if ((page + 1) * EntryCount < node.Categories.Length + node.Locations.Length) + { + AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 3, GumpButtonType.Reply, 1); - if (!tree.LastBranch.TryGetValue(from, out var branch)) + if (NextLabel) { - branch = tree.Root; - } - - if (branch != null) - { - from.SendGump(new GoGump(0, from, tree, branch)); + AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next"); } } - public override void OnResponse(NetState state, in RelayInfo info) + var totalEntryCount = node.Categories.Length + node.Locations.Length; + + for (int i = 0, index = page * EntryCount; i < EntryCount && index < totalEntryCount; ++i, ++index) { - var from = state.Mobile; + x = BorderSize + OffsetSize; + y += EntryHeight + OffsetSize; - switch (info.ButtonID) + var name = index >= node.Categories.Length + ? node.Locations[index - node.Categories.Length].Name + : node.Categories[index].Name; + + AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID); + AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, name); + + x += EntryWidth + OffsetSize; + + if (SetGumpID != 0) { - case 1: - { - if (m_Node.Parent != null) - { - from.SendGump(new GoGump(0, from, m_Tree, m_Node.Parent)); - } - - break; - } - case 2: - { - if (m_Page > 0) - { - from.SendGump(new GoGump(m_Page - 1, from, m_Tree, m_Node)); - } - - break; - } - case 3: - { - if ((m_Page + 1) * EntryCount < m_Node.Categories.Length + m_Node.Locations.Length) - { - from.SendGump(new GoGump(m_Page + 1, from, m_Tree, m_Node)); - } - - break; - } - default: - { - var index = info.ButtonID - 4; - - if (index < 0) - { - break; - } - - if (index < m_Node.Categories.Length) - { - from.SendGump(new GoGump(0, from, m_Tree, m_Node.Categories[index])); - } - else - { - index -= m_Node.Categories.Length; - if (index < m_Node.Locations.Length) - { - from.MoveToWorld(m_Node.Locations[index].Location, m_Tree.Map); - } - } - - break; - } + AddImageTiled(x, y, SetWidth, EntryHeight, SetGumpID); } + + AddButton(x + SetOffsetX, y + SetOffsetY, SetButtonID1, SetButtonID2, index + 4); + } + } + + public static void DisplayTo(Mobile from) + { + LocationTree tree = GoLocations.GetLocations(from.Map); + + if (!tree.LastBranch.TryGetValue(from, out var branch)) + { + branch = tree.Root; + } + + if (branch != null) + { + from.SendGump(new GoGump(0, from, tree, branch)); + } + } + + public override void OnResponse(NetState state, in RelayInfo info) + { + var from = state.Mobile; + + switch (info.ButtonID) + { + case 1: + { + if (_node.Parent != null) + { + from.SendGump(new GoGump(0, from, _tree, _node.Parent)); + } + + break; + } + case 2: + { + if (_page > 0) + { + from.SendGump(new GoGump(_page - 1, from, _tree, _node)); + } + + break; + } + case 3: + { + if ((_page + 1) * EntryCount < _node.Categories.Length + _node.Locations.Length) + { + from.SendGump(new GoGump(_page + 1, from, _tree, _node)); + } + + break; + } + default: + { + var index = info.ButtonID - 4; + + if (index < 0) + { + break; + } + + if (index < _node.Categories.Length) + { + from.SendGump(new GoGump(0, from, _tree, _node.Categories[index])); + } + else + { + index -= _node.Categories.Length; + if (index < _node.Locations.Length) + { + from.MoveToWorld(_node.Locations[index].Location, _tree.Map); + } + } + + break; + } } } } diff --git a/Projects/UOContent/Gumps/Go/GoLocation.cs b/Projects/UOContent/Gumps/Go/GoLocation.cs index 50039a755..c766f9e63 100644 --- a/Projects/UOContent/Gumps/Go/GoLocation.cs +++ b/Projects/UOContent/Gumps/Go/GoLocation.cs @@ -1,13 +1,12 @@ using System.Text.Json.Serialization; -namespace Server.Gumps +namespace Server.Gumps; + +public class GoLocation { - public class GoLocation - { - public GoCategory Parent { get; set; } + public GoCategory Parent { get; set; } - [JsonPropertyName("name")] public string Name { get; set; } + [JsonPropertyName("name")] public string Name { get; set; } - [JsonPropertyName("location")] public Point3D Location { get; set; } - } -} + [JsonPropertyName("location")] public Point3D Location { get; set; } +} \ No newline at end of file diff --git a/Projects/UOContent/Gumps/Go/GoLocations.cs b/Projects/UOContent/Gumps/Go/GoLocations.cs new file mode 100644 index 000000000..ad45b66ec --- /dev/null +++ b/Projects/UOContent/Gumps/Go/GoLocations.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Server.Json; +using Server.Logging; + +namespace Server.Gumps; + +public static class GoLocations +{ + private static readonly ILogger logger = LogFactory.GetLogger(typeof(GoLocations)); + + private static LocationTree _felucca; + private static LocationTree _trammel; + private static LocationTree _ilshenar; + private static LocationTree _malas; + private static LocationTree _tokuno; + private static LocationTree _terMur; + + public static LocationTree GetLocations(Map map) + { + if (map == Map.Ilshenar) + { + return _ilshenar ??= LoadLocations("ilshenar", Map.Ilshenar); + } + + if (map == Map.TerMur) + { + return _terMur ??= LoadLocations("termur", Map.TerMur); + } + + if (map == Map.Trammel) + { + return _trammel ??= LoadLocations("trammel", Map.Trammel); + } + + if (map == Map.Malas) + { + return _malas ??= LoadLocations("malas", Map.Malas); + } + + if (map == Map.Tokuno) + { + return _tokuno ??= LoadLocations("tokuno", Map.Tokuno); + } + + return _felucca ??= LoadLocations("felucca", Map.Felucca); + } + + private static LocationTree LoadLocations(string fileName, Map map) + { + var lastBranch = new Dictionary(); + + var path = Path.Combine($"Data/Locations/{fileName}.json"); + + try + { + var root = JsonConfig.Deserialize(path); + if (root == null) + { + throw new JsonException($"Failed to deserialize {path}."); + } + + return new LocationTree(map, lastBranch, root); + } + catch (Exception e) + { + logger.Error(e, "Failed to load file {Path}.", path); + return new LocationTree(map, [], null); + } + } +} diff --git a/Projects/UOContent/Gumps/Go/LocationTree.cs b/Projects/UOContent/Gumps/Go/LocationTree.cs index defd4908d..7fdfdd66a 100644 --- a/Projects/UOContent/Gumps/Go/LocationTree.cs +++ b/Projects/UOContent/Gumps/Go/LocationTree.cs @@ -1,65 +1,43 @@ -using System; using System.Collections.Generic; -using System.IO; -using System.Text.Json; -using Server.Json; -namespace Server.Gumps +namespace Server.Gumps; + +public class LocationTree { - public class LocationTree + public LocationTree(Map map, Dictionary lastBranch, GoCategory root) { - public LocationTree(string fileName, Map map) + LastBranch = lastBranch; + Map = map; + Root = root; + + if (root != null) { - LastBranch = new Dictionary(); - Map = map; + SetParents(root); + } + } - var path = Path.Combine($"Data/Locations/{fileName}.json"); + public Dictionary LastBranch { get; } - if (!File.Exists(path)) - { - Console.WriteLine("Go Locations: {0} does not exist", path); - return; - } + public Map Map { get; } - try - { - Root = JsonConfig.Deserialize(path); - if (Root == null) - { - throw new JsonException($"Failed to deserialize {path}."); - } - SetParents(Root); - } - catch (Exception e) - { - Console.WriteLine("Go Locations: Error in deserializing {0}", path); - Console.WriteLine(e); - } + public GoCategory Root { get; } + + private static void SetParents(GoCategory parent) + { + // Deserialization may leave these null + parent.Categories ??= []; + parent.Locations ??= []; + + for (var i = 0; i < parent.Categories.Length; i++) + { + var category = parent.Categories[i]; + category.Parent = parent; + SetParents(category); } - public Dictionary LastBranch { get; } - - public Map Map { get; } - - public GoCategory Root { get; } - - private static void SetParents(GoCategory parent) + for (var j = 0; j < parent.Locations.Length; j++) { - // Deserialization may leave these null - parent.Categories ??= Array.Empty(); - parent.Locations ??= Array.Empty(); - - for (var i = 0; i < parent.Categories.Length; i++) - { - var category = parent.Categories[i]; - category.Parent = parent; - SetParents(category); - } - - for (var j = 0; j < parent.Locations.Length; j++) - { - parent.Locations[j].Parent = parent; - } + parent.Locations[j].Parent = parent; } } } diff --git a/Projects/UOContent/Gumps/Props/PropsConfig.cs b/Projects/UOContent/Gumps/Props/PropsConfig.cs index e0a2ec815..4f525bc74 100644 --- a/Projects/UOContent/Gumps/Props/PropsConfig.cs +++ b/Projects/UOContent/Gumps/Props/PropsConfig.cs @@ -1,46 +1,45 @@ -namespace Server.Gumps +namespace Server.Gumps; + +public static class PropsConfig { - public static class PropsConfig - { - public static readonly bool OldStyle = false; + public const bool OldStyle = false; - public static readonly int GumpOffsetX = 30; - public static readonly int GumpOffsetY = 30; + public const int GumpOffsetX = 30; + public const int GumpOffsetY = 30; - public static readonly int TextHue = 0; - public static readonly int TextOffsetX = 2; + public const int TextHue = 0; + public const int TextOffsetX = 2; - public static readonly int OffsetGumpID = 0x0A40; // Pure black + public const int OffsetGumpID = 0x0A40; // Pure black - public static readonly int - HeaderGumpID = OldStyle ? 0x0BBC : 0x0E14; // Light off-white, textured : Dark navy blue, textured + // Light off-white, textured : Dark navy blue, textured + public const int HeaderGumpID = OldStyle ? 0x0BBC : 0x0E14; - public static readonly int EntryGumpID = 0x0BBC; // Light offwhite, textured - public static readonly int BackGumpID = 0x13BE; // Gray slate/stoney - public static readonly int SetGumpID = OldStyle ? 0x0000 : 0x0E14; // Empty : Dark navy blue, textured + public const int EntryGumpID = 0x0BBC; // Light offwhite, textured + public const int BackGumpID = 0x13BE; // Gray slate/stoney + public const int SetGumpID = OldStyle ? 0x0000 : 0x0E14; // Empty : Dark navy blue, textured - public static readonly int SetWidth = 20; - public static readonly int SetOffsetX = OldStyle ? 4 : 2, SetOffsetY = 2; - public static readonly int SetButtonID1 = 0x15E1; // Arrow pointing right - public static readonly int SetButtonID2 = 0x15E5; // " pressed + public const int SetWidth = 20; + public const int SetOffsetX = OldStyle ? 4 : 2, SetOffsetY = 2; + public const int SetButtonID1 = 0x15E1; // Arrow pointing right + public const int SetButtonID2 = 0x15E5; // " pressed - public static readonly int PrevWidth = 20; - public static readonly int PrevOffsetX = 2, PrevOffsetY = 2; - public static readonly int PrevButtonID1 = 0x15E3; // Arrow pointing left - public static readonly int PrevButtonID2 = 0x15E7; // " pressed + public const int PrevWidth = 20; + public const int PrevOffsetX = 2, PrevOffsetY = 2; + public const int PrevButtonID1 = 0x15E3; // Arrow pointing left + public const int PrevButtonID2 = 0x15E7; // " pressed - public static readonly int NextWidth = 20; - public static readonly int NextOffsetX = 2, NextOffsetY = 2; - public static readonly int NextButtonID1 = 0x15E1; // Arrow pointing right - public static readonly int NextButtonID2 = 0x15E5; // " pressed + public const int NextWidth = 20; + public const int NextOffsetX = 2, NextOffsetY = 2; + public const int NextButtonID1 = 0x15E1; // Arrow pointing right + public const int NextButtonID2 = 0x15E5; // " pressed - public static readonly int OffsetSize = 1; + public const int OffsetSize = 1; - public static readonly int EntryHeight = 20; - public static readonly int BorderSize = 10; - public static readonly int ApplySize = 30; + public const int EntryHeight = 20; + public const int BorderSize = 10; + public const int ApplySize = 30; - public static readonly bool PrevLabel = false; - public static readonly bool NextLabel = false; - } + public const bool PrevLabel = false; + public const bool NextLabel = false; }