feat: Adds item graphic size to Bounds.bin and makes item graphic offset available to gumps (#2115)
This commit is contained in:
parent
772511d1e8
commit
40479c946a
12 changed files with 96 additions and 50 deletions
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2024 - ModernUO Development Team *
|
||||
* Copyright 2019-2025 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: ArtData.cs *
|
||||
* *
|
||||
|
|
@ -50,18 +50,18 @@ public class ArtData : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
public Rectangle2D GetStaticBounds(int index)
|
||||
public (ushort Width, ushort Height, Rectangle2D Bounds) GetStaticBounds(int index)
|
||||
{
|
||||
if (index is < 0 or > 0x10000)
|
||||
{
|
||||
return Rectangle2D.Empty;
|
||||
return (0, 0, Rectangle2D.Empty);
|
||||
}
|
||||
|
||||
index += 16384;
|
||||
|
||||
if (!_dataRanges.TryGetValue(index, out var entry))
|
||||
{
|
||||
return Rectangle2D.Empty;
|
||||
return (0, 0, Rectangle2D.Empty);
|
||||
}
|
||||
|
||||
Span<ushort> buffer = stackalloc ushort[entry.Size / 2];
|
||||
|
|
@ -73,10 +73,10 @@ public class ArtData : IDisposable
|
|||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
return Rectangle2D.Empty;
|
||||
return (0, 0, Rectangle2D.Empty);
|
||||
}
|
||||
|
||||
return GetBoundsFromRGBA1555Bitmap(width, height, buffer[4..]);
|
||||
return (width, height, GetBoundsFromRGBA1555Bitmap(width, height, buffer[4..]));
|
||||
}
|
||||
|
||||
private static Dictionary<int, UOPEntry> LoadMulRanges(string idxPath)
|
||||
|
|
|
|||
|
|
@ -2346,7 +2346,7 @@ public class Item : IHued, IComparable<Item>, ISpawnable, IObjectPropertyListEnt
|
|||
};
|
||||
}
|
||||
|
||||
var bounds = ItemBounds.Table[itemID & 0x3FFF];
|
||||
var bounds = ItemBounds.Bounds[itemID & 0x3FFF];
|
||||
|
||||
if (doubled)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2023 - ModernUO Development Team *
|
||||
* Copyright 2019-2025 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: ItemBounds.cs *
|
||||
* *
|
||||
|
|
@ -17,13 +17,15 @@ using System;
|
|||
using System.IO;
|
||||
using System.Threading;
|
||||
using Server.Logging;
|
||||
using Size = System.ValueTuple<ushort, ushort>;
|
||||
|
||||
namespace Server;
|
||||
|
||||
public static class ItemBounds
|
||||
{
|
||||
private static readonly ILogger logger = LogFactory.GetLogger(typeof(ItemBounds));
|
||||
private static readonly string _pathToBounds = Path.Combine(Core.BaseDirectory, "Data", "Binary", "Bounds.bin");
|
||||
private const string _boundsFileName = "ItemBounds.bin";
|
||||
private static readonly string _boundsFolder = Path.Combine(Core.BaseDirectory, "Data", "Items");
|
||||
private static bool _isGenerating;
|
||||
|
||||
public static void Configure()
|
||||
|
|
@ -32,7 +34,7 @@ public static class ItemBounds
|
|||
}
|
||||
|
||||
[Usage("GenBounds")]
|
||||
[Description("Asynchronously generates the bounds.bin file from art.mul/artidx.mul or artLegacyMUL.uop to determine container boundaries.")]
|
||||
[Description("Asynchronously generates the ItemBounds.bin file from art.mul/artidx.mul or artLegacyMUL.uop to determine graphic sizes and boundaries.")]
|
||||
private static void GenBounds_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
GenerateBoundsFileAsync(e.Mobile);
|
||||
|
|
@ -40,19 +42,20 @@ public static class ItemBounds
|
|||
|
||||
static ItemBounds()
|
||||
{
|
||||
Table = new Rectangle2D[TileData.ItemTable.Length];
|
||||
|
||||
if (!File.Exists(_pathToBounds))
|
||||
if (!File.Exists(Path.Combine(_boundsFolder, _boundsFileName)))
|
||||
{
|
||||
logger.Information("Generating {BoundsFilePath}...", "Bounds.bin");
|
||||
logger.Information("Generating {BoundsFilePath}...", _boundsFileName);
|
||||
try
|
||||
{
|
||||
GenerateBoundsFile();
|
||||
logger.Information("Generated {BoundsFilePath} successfully.", "Bounds.bin");
|
||||
GenerateBoundsFile(out var sizes, out var bounds);
|
||||
Sizes = sizes;
|
||||
Bounds = bounds;
|
||||
|
||||
logger.Information("Generated {BoundsFilePath} successfully.", _boundsFileName);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(ex, "Failed to generate {BoundsFilePath}", "Bounds.bin");
|
||||
logger.Error(ex, "Failed to generate {BoundsFilePath}", _boundsFileName);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -61,7 +64,9 @@ public static class ItemBounds
|
|||
GenerateTable();
|
||||
}
|
||||
|
||||
public static Rectangle2D[] Table { get; private set; }
|
||||
public static Size[] Sizes { get; private set; }
|
||||
|
||||
public static Rectangle2D[] Bounds { get; private set; }
|
||||
|
||||
private static void GenerateBoundsFileAsync(Mobile m)
|
||||
{
|
||||
|
|
@ -76,16 +81,21 @@ public static class ItemBounds
|
|||
state =>
|
||||
{
|
||||
var from = state as Mobile;
|
||||
logger.Information("Generating {BoundsFilePath}...", "Bounds.bin");
|
||||
logger.Information("Generating {BoundsFilePath}...", _boundsFileName);
|
||||
if (from != null)
|
||||
{
|
||||
Core.LoopContext.Post(() => from?.SendMessage("Generating bounds file..."));
|
||||
Core.LoopContext.Post(() => from.SendMessage("Generating bounds file..."));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var table = GenerateBoundsFile();
|
||||
Core.LoopContext.Post(() => Table = table);
|
||||
GenerateBoundsFile(out var sizes, out var bounds);
|
||||
Core.LoopContext.Post(() =>
|
||||
{
|
||||
Sizes = sizes;
|
||||
Bounds = bounds;
|
||||
}
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -93,21 +103,21 @@ public static class ItemBounds
|
|||
{
|
||||
Core.LoopContext.Post(() =>
|
||||
{
|
||||
from?.SendMessage("Failed to generate bounds file:");
|
||||
from?.SendMessage(ex.Message);
|
||||
from.SendMessage("Failed to generate bounds file:");
|
||||
from.SendMessage(ex.Message);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
logger.Error(ex, "Failed to generate {BoundsFilePath}", "Bounds.bin");
|
||||
logger.Error(ex, "Failed to generate {BoundsFilePath}", _boundsFileName);
|
||||
return;
|
||||
}
|
||||
|
||||
if (from != null)
|
||||
{
|
||||
Core.LoopContext.Post(
|
||||
() => from?.SendMessage(
|
||||
$"Bounds file saved to {Path.GetRelativePath(Core.BaseDirectory, _pathToBounds)}."
|
||||
() => from.SendMessage(
|
||||
$"Bounds file saved to {Path.GetRelativePath(Core.BaseDirectory, Path.Combine(_boundsFolder, _boundsFileName))}."
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -119,48 +129,57 @@ public static class ItemBounds
|
|||
);
|
||||
}
|
||||
|
||||
private static Rectangle2D[] GenerateBoundsFile()
|
||||
private static void GenerateBoundsFile(out Size[] sizes, out Rectangle2D[] bounds)
|
||||
{
|
||||
var table = new Rectangle2D[TileData.ItemTable.Length];
|
||||
bounds = new Rectangle2D[TileData.ItemTable.Length];
|
||||
sizes = new Size[TileData.ItemTable.Length];
|
||||
|
||||
using var artData = new ArtData();
|
||||
if (!artData.IsInitialized)
|
||||
{
|
||||
throw new FileNotFoundException("Unable to load art.mul/artidx.mul or artLegacyMUL.uop");
|
||||
}
|
||||
|
||||
using var fs = new FileStream(_pathToBounds, FileMode.Create, FileAccess.Write);
|
||||
PathUtility.EnsureDirectory(_boundsFolder);
|
||||
using var fs = new FileStream(Path.Combine(_boundsFolder, _boundsFileName), FileMode.Create, FileAccess.Write);
|
||||
using var bw = new BinaryWriter(fs);
|
||||
|
||||
for (var i = 0; i < table.Length; i++)
|
||||
for (var i = 0; i < bounds.Length; i++)
|
||||
{
|
||||
var bounds = artData.GetStaticBounds(i);
|
||||
var (w, h, b) = artData.GetStaticBounds(i);
|
||||
|
||||
bw.Write((short)bounds.X);
|
||||
bw.Write((short)bounds.Y);
|
||||
bw.Write((short)(bounds.X + bounds.Width + 1));
|
||||
bw.Write((short)(bounds.Y + bounds.Height + 1));
|
||||
bw.Write(w);
|
||||
bw.Write(h);
|
||||
bw.Write((short)b.X);
|
||||
bw.Write((short)b.Y);
|
||||
bw.Write((short)(b.X + b.Width + 1));
|
||||
bw.Write((short)(b.Y + b.Height + 1));
|
||||
|
||||
table[i] = bounds;
|
||||
bounds[i].Set(b.X, b.Y, b.Width, b.Height);
|
||||
sizes[i] = (w, h);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
private static void GenerateTable()
|
||||
{
|
||||
using var fs = new FileStream(_pathToBounds, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
Bounds = new Rectangle2D[TileData.ItemTable.Length];
|
||||
Sizes = new Size[TileData.ItemTable.Length];
|
||||
|
||||
using var fs = new FileStream(Path.Combine(_boundsFolder, _boundsFileName), FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
using var bin = new BinaryReader(fs);
|
||||
|
||||
var count = Math.Min(Table.Length, (int)(fs.Length / 8));
|
||||
var count = Math.Min(Bounds.Length, (int)(fs.Length / 8));
|
||||
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
Sizes[i] = (bin.ReadUInt16(), bin.ReadUInt16());
|
||||
|
||||
int xMin = bin.ReadInt16();
|
||||
int yMin = bin.ReadInt16();
|
||||
int xMax = bin.ReadInt16();
|
||||
int yMax = bin.ReadInt16();
|
||||
|
||||
Table[i].Set(xMin, yMin, xMax - xMin, yMax - yMin);
|
||||
Bounds[i].Set(xMin, yMin, xMax - xMin, yMax - yMin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue