ModernUO/Projects/UOContent/Commands/Object Creation/CAGLoader.cs
2026-03-05 19:36:54 -08:00

168 lines
6 KiB
C#

/*************************************************************************
* ModernUO *
* Copyright 2019-2026 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: CAGLoader.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using Server.Items;
using Server.Json;
using Server.Logging;
namespace Server.Commands;
public static class CAGLoader
{
private static readonly ILogger logger = LogFactory.GetLogger(typeof(CAGLoader));
public static CAGCategory Load()
{
var root = new CAGCategory("Add Menu");
var path = Path.Combine(Core.BaseDirectory, "Data/categorization.json");
var list = JsonConfig.Deserialize<List<CAGJson>>(path);
if (list == null)
{
throw new JsonException($"Failed to deserialize {path}.");
}
// Not an optimized solution
foreach (var cag in list)
{
var parent = root;
// Navigate through the dot notation categories until we find the last one
var categories = cag.Category.Split(".");
for (var i = 0; i < categories.Length; i++)
{
var category = categories[i];
// No children, so let's make one
if (parent.Nodes == null)
{
var cat = new CAGCategory(category, parent);
parent.Nodes = new CAGNode[] { cat };
parent = cat;
continue;
}
var oldParent = parent;
for (var j = 0; j < parent.Nodes.Length; j++)
{
var node = parent.Nodes[j];
if (category == node.Title && node is CAGCategory cat)
{
parent = cat;
break;
}
}
// Didn't find the child, let's add it
if (oldParent == parent)
{
var nodes = parent.Nodes;
parent.Nodes = new CAGNode[nodes.Length + 1];
Array.Copy(nodes, parent.Nodes, nodes.Length);
var cat = new CAGCategory(category, parent);
parent.Nodes[^1] = cat;
parent = cat;
}
}
// Set the objects associated with the child most node
var pooledList = new List<CAGNode>(cag.Objects.Length);
for (var i = 0; i < cag.Objects.Length; i++)
{
var cagObj = cag.Objects[i];
cagObj.Parent = parent;
// Set ItemID and Hue
if (cagObj.Hue == null || cagObj.ItemID == null)
{
var type = cagObj.Type;
try
{
if (type.IsAssignableTo(typeof(Item)))
{
var item = cagObj.Type.CreateInstance<Item>();
if (cagObj.ItemID == null)
{
var itemID = item.ItemID;
if (item is BaseAddon addon && addon.Components.Count == 1)
{
itemID = addon.Components[0].ItemID;
}
if (itemID > TileData.MaxItemValue)
{
itemID = 1;
}
cagObj.ItemID = itemID;
}
if (cagObj.Hue == null)
{
var hue = item.Hue & 0x7FFF;
hue = (hue & 0x4000) != 0 ? 0 : hue;
cagObj.Hue = hue == 0 ? null : hue;
}
item.Delete();
}
if (type.IsAssignableTo(typeof(Mobile)))
{
var m = cagObj.Type.CreateInstance<Mobile>();
cagObj.ItemID ??= ShrinkTable.Lookup(m, 1);
if (cagObj.Hue == null)
{
var hue = m.Hue & 0x7FFF;
hue = (hue & 0x4000) != 0 ? 0 : hue;
cagObj.Hue = hue == 0 ? null : hue;
}
m.Delete();
}
}
catch (Exception e)
{
logger.Warning(e, "Failed to instantiate type {Type}.", type);
continue;
}
}
pooledList.Add(cagObj);
}
parent.Nodes = pooledList.ToArray();
}
return root;
}
}
public record CAGJson
{
[JsonPropertyName("category")]
public string Category { get; init; }
[JsonPropertyName("objects")]
public CAGObject[] Objects { get; init; }
}