diff --git a/BossMod/BossMod.csproj b/BossMod/BossMod.csproj
index b10c11ccbc..94632f22f3 100644
--- a/BossMod/BossMod.csproj
+++ b/BossMod/BossMod.csproj
@@ -94,7 +94,6 @@
-
-
+
diff --git a/BossMod/Debug/DebugObstacles.cs b/BossMod/Debug/DebugObstacles.cs
index eae95bc331..cff5e49cd4 100644
--- a/BossMod/Debug/DebugObstacles.cs
+++ b/BossMod/Debug/DebugObstacles.cs
@@ -51,7 +51,8 @@ protected override void DrawSidebar()
ImGui.SameLine();
if (ImGui.Button("Reload"))
{
- CheckpointNoClone(new(owner.Obstacles.RootPath + e.Filename));
+ using var stream = File.OpenRead(owner.Obstacles.RootPath + e.Filename);
+ CheckpointNoClone(new(stream));
}
ImGui.SetNextItemWidth(100);
@@ -162,6 +163,7 @@ public void Draw()
private void DrawEntries(List entries)
{
Action? modifications = null;
+ using var disableScope = ImRaii.Disabled(!Obstacles.CanEditDatabase());
for (int i = 0; i < entries.Count; ++i)
{
using var id = ImRaii.PushId(i);
@@ -174,9 +176,8 @@ private void DrawEntries(List entries)
if (ImGui.Button("Move down"))
modifications += () => (entries[index], entries[index + 1]) = (entries[index + 1], entries[index]);
ImGui.SameLine();
- using (ImRaii.Disabled(!Obstacles.CanEditDatabase()))
- if (ImGui.Button("Delete"))
- modifications += () => DeleteMap(entries, index);
+ if (ImGui.Button("Delete"))
+ modifications += () => DeleteMap(entries, index);
ImGui.SameLine();
if (ImGui.Button("Edit"))
OpenEditor(entries[index]);
@@ -230,7 +231,8 @@ private string GenerateMapName()
private void OpenEditor(ObstacleMapDatabase.Entry entry)
{
- var editor = new Editor(this, new(Obstacles.RootPath + entry.Filename), entry);
+ using var stream = File.OpenRead(Obstacles.RootPath + entry.Filename);
+ var editor = new Editor(this, new(stream), entry);
_ = new UISimpleWindow($"Obstacle map {entry.Filename}", editor.Draw, true, new(1000, 1000));
}
}
diff --git a/BossMod/Pathfinding/ObstacleMapDatabase.cs b/BossMod/Pathfinding/ObstacleMapDatabase.cs
index c4076ddf1b..a2d5fab3ce 100644
--- a/BossMod/Pathfinding/ObstacleMapDatabase.cs
+++ b/BossMod/Pathfinding/ObstacleMapDatabase.cs
@@ -1,5 +1,4 @@
using System.IO;
-using System.Reflection;
using System.Text.Json;
namespace BossMod.Pathfinding;
@@ -20,36 +19,10 @@ public sealed record class Entry(Vector3 MinBounds, Vector3 MaxBounds, WPos Orig
public readonly Dictionary> Entries = [];
- public void LoadFromAssembly()
- {
- try
- {
- using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BossMod.Pathfinding.ObstacleMaps.maplist.json") ?? throw new InvalidDataException("Embedded obstacle map file missing");
- LoadInternal(stream);
- }
- catch (Exception ex)
- {
- Service.Log($"Failed to load embedded obstacle map database: {ex}");
- }
- }
-
- public void LoadFromFile(string listPath)
- {
- using var fstream = File.OpenRead(listPath);
- try
- {
- LoadInternal(fstream);
- }
- catch (Exception ex)
- {
- Service.Log($"Failed to load obstacle map database '{listPath}': {ex}");
- }
- }
-
- private void LoadInternal(Stream stream)
+ public void Load(Stream stream)
{
Entries.Clear();
- using var json = JsonDocument.Parse(stream, new JsonDocumentOptions() { AllowTrailingCommas = true, CommentHandling = JsonCommentHandling.Skip });
+ using var json = Serialization.ReadJson(stream);
foreach (var jentries in json.RootElement.EnumerateObject())
{
var sep = jentries.Name.IndexOf('.', StringComparison.Ordinal);
diff --git a/BossMod/Pathfinding/ObstacleMapManager.cs b/BossMod/Pathfinding/ObstacleMapManager.cs
index 52e7b3a292..7b9662fc49 100644
--- a/BossMod/Pathfinding/ObstacleMapManager.cs
+++ b/BossMod/Pathfinding/ObstacleMapManager.cs
@@ -1,4 +1,5 @@
-using System.Reflection;
+using System.IO;
+using System.Reflection;
namespace BossMod.Pathfinding;
@@ -45,17 +46,18 @@ public void Dispose()
public void ReloadDatabase()
{
- if (LoadFromSource)
+ Service.Log($"Loading obstacle database from {(_config.LoadFromSource ? _config.SourcePath : "")}");
+ RootPath = _config.LoadFromSource ? _config.SourcePath[..(_config.SourcePath.LastIndexOfAny(['\\', '/']) + 1)] : "";
+
+ try
{
- var dbPath = _config.SourcePath;
- Service.Log($"Loading obstacle database from '{dbPath}'");
- Database.LoadFromFile(dbPath);
- RootPath = dbPath[..(dbPath.LastIndexOfAny(['\\', '/']) + 1)];
+ using var dbStream = _config.LoadFromSource ? File.OpenRead(_config.SourcePath) : GetEmbeddedResource("maplist.json");
+ Database.Load(dbStream);
}
- else
+ catch (Exception ex)
{
- Service.Log($"Loading embedded obstacle database");
- Database.LoadFromAssembly();
+ Service.Log($"Failed to load obstacle database: {ex}");
+ Database.Entries.Clear();
}
LoadMaps(World.CurrentZone, World.CurrentCFCID);
@@ -76,38 +78,19 @@ private void LoadMaps(ushort zoneId, ushort cfcId)
{
foreach (var e in entries)
{
- if (LoadFromSource)
+ try
{
- var filename = RootPath + e.Filename;
- try
- {
- var bitmap = new Bitmap(filename);
- _entries.Add((e, bitmap));
- }
- catch (Exception ex)
- {
- Service.Log($"Failed to load map {filename} for {zoneId}.{cfcId}: {ex}");
- }
+ using var eStream = _config.LoadFromSource ? File.OpenRead(RootPath + e.Filename) : GetEmbeddedResource(e.Filename);
+ var bitmap = new Bitmap(eStream);
+ _entries.Add((e, bitmap));
}
- else
+ catch (Exception ex)
{
- using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream($"BossMod.Pathfinding.ObstacleMaps.{e.Filename}");
- if (stream == null)
- {
- Service.Log($"Embedded map missing for {zoneId}.{cfcId}");
- continue;
- }
- try
- {
- var bitmap = new Bitmap(stream);
- _entries.Add((e, bitmap));
- }
- catch (Exception ex)
- {
- Service.Log($"Failed to load embedded map for {zoneId}.{cfcId}: {ex}");
- }
+ Service.Log($"Failed to load map {e.Filename} from {(_config.LoadFromSource ? RootPath : "")} for {zoneId}.{cfcId}: {ex}");
}
}
}
}
+
+ private Stream GetEmbeddedResource(string name) => Assembly.GetExecutingAssembly().GetManifestResourceStream($"BossMod.Pathfinding.ObstacleMaps.{name}") ?? throw new InvalidDataException($"Missing embedded resource {name}");
}
diff --git a/BossMod/Util/Bitmap.cs b/BossMod/Util/Bitmap.cs
index a1f0edfe48..6a530236c4 100644
--- a/BossMod/Util/Bitmap.cs
+++ b/BossMod/Util/Bitmap.cs
@@ -150,28 +150,28 @@ public Bitmap(int width, int height, Color color0, Color color1, int resolution
Pixels = new byte[height * BytesPerRow];
}
- public Bitmap(Stream fstream, string filename = "")
+ public Bitmap(Stream stream)
{
- using var reader = new BinaryReader(fstream);
- var fileHeader = fstream.ReadStruct();
+ using var reader = new BinaryReader(stream);
+ var fileHeader = stream.ReadStruct();
if (fileHeader.Type != Magic)
- throw new ArgumentException($"File '{filename}' is not a bitmap: magic is {fileHeader.Type:X4}");
+ throw new ArgumentException($"Not a bitmap: magic is {fileHeader.Type:X4}");
- var header = fstream.ReadStruct();
+ var header = stream.ReadStruct();
if (header.SizeInBytes != Marshal.SizeOf())
- throw new ArgumentException($"Bitmap '{filename}' has unsupported header size {header.SizeInBytes}");
+ throw new ArgumentException($"Bitmap has unsupported header size {header.SizeInBytes}");
if (header.Width <= 0)
- throw new ArgumentException($"Bitmap '{filename}' has non-positive width {header.Width}");
+ throw new ArgumentException($"Bitmap has non-positive width {header.Width}");
if (header.Height >= 0)
- throw new ArgumentException($"Bitmap '{filename}' is not top-down (height={header.Height})");
+ throw new ArgumentException($"Bitmap is not top-down (height={header.Height})");
if (header.BitCount != 1)
- throw new ArgumentException($"Bitmap '{filename}' is not 1bpp (bitcount={header.BitCount})");
+ throw new ArgumentException($"Bitmap is not 1bpp (bitcount={header.BitCount})");
if (header.Compression != 0)
- throw new ArgumentException($"Bitmap '{filename}' has unsupported compression method {header.Compression:X8}");
+ throw new ArgumentException($"Bitmap has unsupported compression method {header.Compression:X8}");
if (header.XPixelsPerMeter != header.YPixelsPerMeter || header.XPixelsPerMeter <= 0)
- throw new ArgumentException($"Bitmap '{filename}' has inconsistent or non-positive resolution {header.XPixelsPerMeter}x{header.YPixelsPerMeter}");
+ throw new ArgumentException($"Bitmap has inconsistent or non-positive resolution {header.XPixelsPerMeter}x{header.YPixelsPerMeter}");
if (header.ColorUsedCount is not 0 or 2)
- throw new ArgumentException($"Bitmap '{filename}' has wrong palette size {header.ColorUsedCount}");
+ throw new ArgumentException($"Bitmap has wrong palette size {header.ColorUsedCount}");
Width = header.Width;
Height = -header.Height;
@@ -182,8 +182,6 @@ public Bitmap(Stream fstream, string filename = "")
Pixels = reader.ReadBytes(Height * BytesPerRow);
}
- public Bitmap(string filename) : this(File.OpenRead(filename), filename) { }
-
public void Save(string filename)
{
using var fstream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.Read);
diff --git a/BossMod/Util/Serialization.cs b/BossMod/Util/Serialization.cs
index 97e48dc8d9..01c72b2d32 100644
--- a/BossMod/Util/Serialization.cs
+++ b/BossMod/Util/Serialization.cs
@@ -26,9 +26,10 @@ public class JsonTypeConverter : JsonConverter
public static JsonDocument ReadJson(string path)
{
using var fstream = File.OpenRead(path);
- return JsonDocument.Parse(fstream, new JsonDocumentOptions() { AllowTrailingCommas = true, CommentHandling = JsonCommentHandling.Skip });
+ return ReadJson(fstream);
}
+ public static JsonDocument ReadJson(Stream stream) => JsonDocument.Parse(stream, new JsonDocumentOptions() { AllowTrailingCommas = true, CommentHandling = JsonCommentHandling.Skip });
public static Utf8JsonWriter WriteJson(Stream fstream, bool indented = true) => new(fstream, new JsonWriterOptions() { Indented = indented });
public static unsafe T ReadStruct(this Stream stream) where T : unmanaged
diff --git a/TODO b/TODO
index bef64be35f..5c5907301d 100644
--- a/TODO
+++ b/TODO
@@ -44,8 +44,6 @@ general:
- zone modules: module info ui
- refactor ipc/dtr
- questbattles
-- collisions for pathfinding
--- embedded mode
boss modules:
- timers
diff --git a/UIDev/BitmapEditorTest.cs b/UIDev/BitmapEditorTest.cs
index da4601fc6f..1c6e0dcf94 100644
--- a/UIDev/BitmapEditorTest.cs
+++ b/UIDev/BitmapEditorTest.cs
@@ -1,5 +1,6 @@
using BossMod;
using ImGuiNET;
+using System.IO;
namespace UIDev;
@@ -43,7 +44,8 @@ protected override void DrawSidebar()
if (ImGui.Button("load"))
{
- CheckpointNoClone(new("D:\\test.bmp"));
+ using var stream = File.OpenRead("D:\\test.bmp");
+ CheckpointNoClone(new(stream));
}
}