From 6c50ef687e8071d944bfeaf2357e58e6ad3c7f8f Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 17:24:19 +0800 Subject: [PATCH 01/14] Fix 1.4.5 map generation compatibility --- src/GenerateMap/MapGenerator.cs | 39 ++++++++++++++++++++++++------ src/GenerateMap/Plugin.cs | 43 ++++++++++++++------------------- 2 files changed, 50 insertions(+), 32 deletions(-) diff --git a/src/GenerateMap/MapGenerator.cs b/src/GenerateMap/MapGenerator.cs index 19b90ea83..cb6f71c3e 100644 --- a/src/GenerateMap/MapGenerator.cs +++ b/src/GenerateMap/MapGenerator.cs @@ -19,7 +19,7 @@ internal static void Init() WorldMapIndexerHook.Apply(); MapHelper.Initialize(); Main.mapEnabled = true; - Main.Map = new WorldMap(Main.maxTilesX, Main.maxTilesY) { _tiles = new MapTile[Main.maxTilesX, Main.maxTilesY] }; + Main.Map = CreateWorkingMap(); Main.ActivePlayerFileData = new PlayerFileData { Name = "GenerateMap", _path = Main.GetPlayerPathFromName("GenerateMap", false) }; Main.MapFileMetadata = FileMetadata.FromCurrentSettings(FileType.Map); Utils.TryCreatingDirectory(MapsPath); @@ -31,19 +31,43 @@ internal static void Dispose() WorldMapIndexerHook.Dispose(); } - private static MapTile NewWorldMapIndexer(Func orig, WorldMap self, int x, int y) + private static WorldMap CreateWorkingMap() { - return self._tiles[x, y]; + var edge = WorldMap.BlackEdgeWidth; + return new WorldMap(Main.maxTilesX, Main.maxTilesY) + { + _tiles = new MapTile[Main.maxTilesX + edge * 2, Main.maxTilesY + edge * 2] + }; + } + + private static MapTile NewWorldMapIndexer(Func _, WorldMap self, int x, int y) + { + if (self._tiles == null) + { + return default; + } + + var edge = WorldMap.BlackEdgeWidth; + var rawX = x + edge; + var rawY = y + edge; + if ((uint) rawX >= (uint) self._tiles.GetLength(0) || (uint) rawY >= (uint) self._tiles.GetLength(1)) + { + return default; + } + + return self._tiles[rawX, rawY]; } private static void LightUpWholeMap() { - Main.Map = new WorldMap(Main.maxTilesX, Main.maxTilesY) { _tiles = new MapTile[Main.maxTilesX, Main.maxTilesY] }; + Main.Map = CreateWorkingMap(); + var edge = WorldMap.BlackEdgeWidth; for (var x = 0; x < Main.maxTilesX; x++) { for (var y = 0; y < Main.maxTilesY; y++) { - Main.Map._tiles[x, y] = MapHelper.CreateMapTile(x, y, byte.MaxValue); + var tile = MapHelper.CreateMapTile(x, y, byte.MaxValue); + Main.Map._tiles[x + edge, y + edge] = tile; } } } @@ -52,11 +76,12 @@ private static Image CreateMapImg() { Image image = new (Main.maxTilesX, Main.maxTilesY); LightUpWholeMap(); + var edge = WorldMap.BlackEdgeWidth; for (var x = 0; x < Main.maxTilesX; x++) { for (var y = 0; y < Main.maxTilesY; y++) { - var tile = Main.Map[x, y]; + var tile = Main.Map._tiles[x + edge, y + edge]; var col = MapHelper.GetMapTileXnaColor(tile); image[x, y] = new Rgba32(col.R, col.G, col.B, col.A); } @@ -104,4 +129,4 @@ internal static string SaveMapFile() File.Copy(mapPath, path); return path; } -} \ No newline at end of file +} diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index 1d3d4ae7a..245a00394 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -71,34 +71,27 @@ private static void Generate(CommandArgs args) switch (args.Parameters[0]) { case "img": - Task.Run(() => + try { - try - { - var fileName = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png"; - var path = MapGenerator.SaveMapImg(fileName); - args.Player.SendSuccessMessage(GetString($"[GenerateMap]地图图片已保存到: {path}")); - } - catch (Exception ex) - { - TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); - } - - }); + var fileName = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png"; + var path = MapGenerator.SaveMapImg(fileName); + args.Player.SendSuccessMessage(GetString($"[GenerateMap]地图图片已保存到: {path}")); + } + catch (Exception ex) + { + TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); + } break; case "file": - Task.Run(() => + try + { + var path = MapGenerator.SaveMapFile(); + args.Player.SendSuccessMessage(GetString($"[GenerateMap]地图文件已保存到: {path}")); + } + catch (Exception ex) { - try - { - var path = MapGenerator.SaveMapFile(); - args.Player.SendSuccessMessage(GetString($"[GenerateMap]地图文件已保存到: {path}")); - } - catch (Exception ex) - { - TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); - } - }); + TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); + } break; default: ShowHelp(); @@ -134,4 +127,4 @@ void ShowHelp() } #endregion -} \ No newline at end of file +} From 0fa310c7553f5d66315b6b992edb3513ff833ef4 Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 18:05:13 +0800 Subject: [PATCH 02/14] Remove MonoMod detour dependency from GenerateMap --- src/GenerateMap/MapGenerator.cs | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/GenerateMap/MapGenerator.cs b/src/GenerateMap/MapGenerator.cs index cb6f71c3e..dedc5d663 100644 --- a/src/GenerateMap/MapGenerator.cs +++ b/src/GenerateMap/MapGenerator.cs @@ -1,4 +1,3 @@ -using MonoMod.RuntimeDetour; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using System.IO.Streams; @@ -10,13 +9,10 @@ namespace GenerateMap; internal static class MapGenerator { - private static readonly Hook WorldMapIndexerHook = new (typeof(WorldMap).GetMethod("get_Item")!, NewWorldMapIndexer); - private const string MapsPath = @"GenerateMap"; private const string ImagesPath = @"GenerateMap\Images"; internal static void Init() { - WorldMapIndexerHook.Apply(); MapHelper.Initialize(); Main.mapEnabled = true; Main.Map = CreateWorkingMap(); @@ -28,7 +24,6 @@ internal static void Init() internal static void Dispose() { - WorldMapIndexerHook.Dispose(); } private static WorldMap CreateWorkingMap() @@ -40,24 +35,6 @@ private static WorldMap CreateWorkingMap() }; } - private static MapTile NewWorldMapIndexer(Func _, WorldMap self, int x, int y) - { - if (self._tiles == null) - { - return default; - } - - var edge = WorldMap.BlackEdgeWidth; - var rawX = x + edge; - var rawY = y + edge; - if ((uint) rawX >= (uint) self._tiles.GetLength(0) || (uint) rawY >= (uint) self._tiles.GetLength(1)) - { - return default; - } - - return self._tiles[rawX, rawY]; - } - private static void LightUpWholeMap() { Main.Map = CreateWorkingMap(); From 001c6e60186564c576c58b54d9e843ec1bf4593d Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 19:02:04 +0800 Subject: [PATCH 03/14] Change /map file to export .wld world file --- src/GenerateMap/MapGenerator.cs | 56 +++++++++++++++++++++++---------- src/GenerateMap/Plugin.cs | 2 +- 2 files changed, 40 insertions(+), 18 deletions(-) diff --git a/src/GenerateMap/MapGenerator.cs b/src/GenerateMap/MapGenerator.cs index dedc5d663..d2526bbba 100644 --- a/src/GenerateMap/MapGenerator.cs +++ b/src/GenerateMap/MapGenerator.cs @@ -39,12 +39,26 @@ private static void LightUpWholeMap() { Main.Map = CreateWorkingMap(); var edge = WorldMap.BlackEdgeWidth; + var width = Main.Map._tiles.GetLength(0); + var height = Main.Map._tiles.GetLength(1); for (var x = 0; x < Main.maxTilesX; x++) { for (var y = 0; y < Main.maxTilesY; y++) { var tile = MapHelper.CreateMapTile(x, y, byte.MaxValue); - Main.Map._tiles[x + edge, y + edge] = tile; + + // 1.4.5+ on different runtimes may read either raw or edge-offset coordinates during save. + if ((uint) x < (uint) width && (uint) y < (uint) height) + { + Main.Map._tiles[x, y] = tile; + } + + var rawX = x + edge; + var rawY = y + edge; + if ((uint) rawX < (uint) width && (uint) rawY < (uint) height) + { + Main.Map._tiles[rawX, rawY] = tile; + } } } } @@ -68,17 +82,16 @@ private static Image CreateMapImg() } internal static byte[] CreatMapImgBytes() - { - return File.ReadAllBytes(CreatMapFile()); - } - - internal static byte[] CreatMapFileBytes() { var image = CreateMapImg(); using var stream = new MemoryStream(); image.SaveAsPng(stream); return stream.ToArray(); - + } + + internal static byte[] CreatMapFileBytes() + { + return File.ReadAllBytes(GetWorldFilePath()); } internal static string SaveMapImg(string fileName) @@ -89,21 +102,30 @@ internal static string SaveMapImg(string fileName) return path; } - private static string CreatMapFile() + private static string GetWorldFilePath() { - LightUpWholeMap(); - MapHelper.SaveMap(); - var playerPath = Main.playerPathName[..^4] + Path.DirectorySeparatorChar; - var mapFileName = !Main.ActiveWorldFileData.UseGuidAsMapName ? Main.worldID + ".map" : Main.ActiveWorldFileData.UniqueId + ".map"; - var mapFilePath = Path.Combine(playerPath, mapFileName); - return mapFilePath; + var worldFilePath = Main.worldPathName; + if (string.IsNullOrWhiteSpace(worldFilePath) || !File.Exists(worldFilePath)) + { + throw new FileNotFoundException("World file not found.", worldFilePath); + } + + return worldFilePath; } internal static string SaveMapFile() { - var mapPath = CreatMapFile(); - var path = Path.Combine(ImagesPath, Path.GetFileName(mapPath)); - File.Copy(mapPath, path); + var worldPath = GetWorldFilePath(); + var worldName = Path.GetFileNameWithoutExtension(worldPath); + var ext = Path.GetExtension(worldPath); + if (string.IsNullOrWhiteSpace(ext)) + { + ext = ".wld"; + } + + var fileName = $"{worldName}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}{ext}"; + var path = Path.Combine(MapsPath, fileName); + File.Copy(worldPath, path, true); return path; } } diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index 245a00394..c04c79390 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -104,7 +104,7 @@ private static void Generate(CommandArgs args) void ShowHelp() { args.Player.SendSuccessMessage(GetString("GenerateMap帮助: ")); - args.Player.SendSuccessMessage(GetString("/map file --- 生成地图文件")); + args.Player.SendSuccessMessage(GetString("/map file --- 导出世界文件(.wld)")); args.Player.SendSuccessMessage(GetString("/map img --- 生成地图图片")); } } From 06386ca525bafdf323eac3506e73a3205f2ee5c4 Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 19:11:30 +0800 Subject: [PATCH 04/14] Restore Task.Run for map commands --- src/GenerateMap/Plugin.cs | 40 ++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index c04c79390..261acb68d 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -71,27 +71,33 @@ private static void Generate(CommandArgs args) switch (args.Parameters[0]) { case "img": - try + Task.Run(() => { - var fileName = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png"; - var path = MapGenerator.SaveMapImg(fileName); - args.Player.SendSuccessMessage(GetString($"[GenerateMap]地图图片已保存到: {path}")); - } - catch (Exception ex) - { - TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); - } + try + { + var fileName = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.png"; + var path = MapGenerator.SaveMapImg(fileName); + args.Player.SendSuccessMessage(GetString($"[GenerateMap]地图图片已保存到: {path}")); + } + catch (Exception ex) + { + TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); + } + }); break; case "file": - try - { - var path = MapGenerator.SaveMapFile(); - args.Player.SendSuccessMessage(GetString($"[GenerateMap]地图文件已保存到: {path}")); - } - catch (Exception ex) + Task.Run(() => { - TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); - } + try + { + var path = MapGenerator.SaveMapFile(); + args.Player.SendSuccessMessage(GetString($"[GenerateMap]地图文件已保存到: {path}")); + } + catch (Exception ex) + { + TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); + } + }); break; default: ShowHelp(); From 9516159330e82269d901a779e6bb691bc47a6ca5 Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 19:20:25 +0800 Subject: [PATCH 05/14] Use GenerateMap/Maps and GenerateMap/Images directories --- src/GenerateMap/MapGenerator.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/GenerateMap/MapGenerator.cs b/src/GenerateMap/MapGenerator.cs index d2526bbba..614b7987c 100644 --- a/src/GenerateMap/MapGenerator.cs +++ b/src/GenerateMap/MapGenerator.cs @@ -9,8 +9,9 @@ namespace GenerateMap; internal static class MapGenerator { - private const string MapsPath = @"GenerateMap"; - private const string ImagesPath = @"GenerateMap\Images"; + private const string BasePath = "GenerateMap"; + private static readonly string MapsPath = Path.Combine(BasePath, "Maps"); + private static readonly string ImagesPath = Path.Combine(BasePath, "Images"); internal static void Init() { MapHelper.Initialize(); @@ -18,6 +19,7 @@ internal static void Init() Main.Map = CreateWorkingMap(); Main.ActivePlayerFileData = new PlayerFileData { Name = "GenerateMap", _path = Main.GetPlayerPathFromName("GenerateMap", false) }; Main.MapFileMetadata = FileMetadata.FromCurrentSettings(FileType.Map); + Utils.TryCreatingDirectory(BasePath); Utils.TryCreatingDirectory(MapsPath); Utils.TryCreatingDirectory(ImagesPath); } From 7c80498f7a6c5b5645f7dd8d81787ccfc901d9f1 Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 19:24:10 +0800 Subject: [PATCH 06/14] Update version and README --- src/GenerateMap/Plugin.cs | 2 +- src/GenerateMap/README.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index 261acb68d..26c1c57bb 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -14,7 +14,7 @@ public class Plugin(Main game) : TerrariaPlugin(game) public override string Name => Assembly.GetExecutingAssembly().GetName().Name!; public override string Description => GetString("生成地图图片"); - public override Version Version => new (2, 0, 0); + public override Version Version => new (2, 1, 0); public override void Initialize() { diff --git a/src/GenerateMap/README.md b/src/GenerateMap/README.md index 9d1803dd9..9d82388db 100644 --- a/src/GenerateMap/README.md +++ b/src/GenerateMap/README.md @@ -1,6 +1,6 @@ # GenerateMap 将地图保存至图片 -- 作者: 少司命, Cai +- 作者: 少司命, Cai,千亦 - 出处: 无 - 生成地图图片 @@ -26,6 +26,10 @@ ## 更新日志 +### v2.1.0 +- 适配 1.4.5 +- 修复在 Linux, macOS 下的保存路径错误 + ### v2.0.0 - 移除CaiLib依赖,重构 From 3b8f18107b68dc8607ad547ab84b2a76a7d3eff0 Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 19:26:14 +0800 Subject: [PATCH 07/14] Update author field --- src/GenerateMap/Plugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index 26c1c57bb..dde414482 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -9,7 +9,7 @@ namespace GenerateMap; [ApiVersion(2, 1)] public class Plugin(Main game) : TerrariaPlugin(game) { - public override string Author => "少司命, Cai"; + public override string Author => "少司命, Cai,千亦"; public override string Name => Assembly.GetExecutingAssembly().GetName().Name!; public override string Description => GetString("生成地图图片"); From 413c5bed72323a923213b8a6ebdf45a1bc35ea1f Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 19:27:12 +0800 Subject: [PATCH 08/14] Update author field --- src/GenerateMap/Plugin.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index dde414482..077635c0a 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -9,7 +9,7 @@ namespace GenerateMap; [ApiVersion(2, 1)] public class Plugin(Main game) : TerrariaPlugin(game) { - public override string Author => "少司命, Cai,千亦"; + public override string Author => "少司命, Cai, 千亦"; public override string Name => Assembly.GetExecutingAssembly().GetName().Name!; public override string Description => GetString("生成地图图片"); From 932cf2c4392fc43279765a3c5eee32e3629531ef Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 19:51:36 +0800 Subject: [PATCH 09/14] Switch map file export back to .map --- src/GenerateMap/MapGenerator.cs | 33 +++++++++++++++++---------------- src/GenerateMap/Plugin.cs | 2 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/GenerateMap/MapGenerator.cs b/src/GenerateMap/MapGenerator.cs index 614b7987c..58fd95c2c 100644 --- a/src/GenerateMap/MapGenerator.cs +++ b/src/GenerateMap/MapGenerator.cs @@ -93,7 +93,7 @@ internal static byte[] CreatMapImgBytes() internal static byte[] CreatMapFileBytes() { - return File.ReadAllBytes(GetWorldFilePath()); + return File.ReadAllBytes(CreateMapFile()); } internal static string SaveMapImg(string fileName) @@ -104,30 +104,31 @@ internal static string SaveMapImg(string fileName) return path; } - private static string GetWorldFilePath() + private static string CreateMapFile() { - var worldFilePath = Main.worldPathName; - if (string.IsNullOrWhiteSpace(worldFilePath) || !File.Exists(worldFilePath)) + LightUpWholeMap(); + MapHelper.SaveMap(); + + var playerPath = Main.playerPathName[..^4] + Path.DirectorySeparatorChar; + var mapFileName = !Main.ActiveWorldFileData.UseGuidAsMapName + ? Main.worldID + ".map" + : Main.ActiveWorldFileData.UniqueId + ".map"; + var mapFilePath = Path.Combine(playerPath, mapFileName); + if (!File.Exists(mapFilePath)) { - throw new FileNotFoundException("World file not found.", worldFilePath); + throw new FileNotFoundException("Map file not found.", mapFilePath); } - return worldFilePath; + return mapFilePath; } internal static string SaveMapFile() { - var worldPath = GetWorldFilePath(); - var worldName = Path.GetFileNameWithoutExtension(worldPath); - var ext = Path.GetExtension(worldPath); - if (string.IsNullOrWhiteSpace(ext)) - { - ext = ".wld"; - } - - var fileName = $"{worldName}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}{ext}"; + var mapPath = CreateMapFile(); + var mapName = Path.GetFileNameWithoutExtension(mapPath); + var fileName = $"{mapName}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.map"; var path = Path.Combine(MapsPath, fileName); - File.Copy(worldPath, path, true); + File.Copy(mapPath, path, true); return path; } } diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index 077635c0a..4ac66f291 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -110,7 +110,7 @@ private static void Generate(CommandArgs args) void ShowHelp() { args.Player.SendSuccessMessage(GetString("GenerateMap帮助: ")); - args.Player.SendSuccessMessage(GetString("/map file --- 导出世界文件(.wld)")); + args.Player.SendSuccessMessage(GetString("/map file --- 生成地图文件(.map)")); args.Player.SendSuccessMessage(GetString("/map img --- 生成地图图片")); } } From 9a7a1daf5cfd82d0e6e5be5cbe8e5b6e932a2e9f Mon Sep 17 00:00:00 2001 From: arispex Date: Sun, 15 Feb 2026 19:56:54 +0800 Subject: [PATCH 10/14] Remove unused MapGenerator.Dispose --- src/GenerateMap/MapGenerator.cs | 4 ---- src/GenerateMap/Plugin.cs | 1 - 2 files changed, 5 deletions(-) diff --git a/src/GenerateMap/MapGenerator.cs b/src/GenerateMap/MapGenerator.cs index 58fd95c2c..8b07378fa 100644 --- a/src/GenerateMap/MapGenerator.cs +++ b/src/GenerateMap/MapGenerator.cs @@ -24,10 +24,6 @@ internal static void Init() Utils.TryCreatingDirectory(ImagesPath); } - internal static void Dispose() - { - } - private static WorldMap CreateWorkingMap() { var edge = WorldMap.BlackEdgeWidth; diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index 4ac66f291..52f005246 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -30,7 +30,6 @@ protected override void Dispose(bool disposing) { if (disposing) { - MapGenerator.Dispose(); ((List) typeof(Rest) .GetField("commands", BindingFlags.NonPublic | BindingFlags.Instance)! .GetValue(TShock.RestApi)!) From 74a3c0bdd3c3c138d57f8c821d3c0578e57ca70a Mon Sep 17 00:00:00 2001 From: Cai <13110818005@qq.com> Date: Tue, 17 Feb 2026 19:57:37 +0800 Subject: [PATCH 11/14] chore: clean up --- src/GenerateMap/MapGenerator.cs | 29 ++++++++++------------------ src/GenerateMap/Plugin.cs | 34 ++++++++++++++------------------- 2 files changed, 24 insertions(+), 39 deletions(-) diff --git a/src/GenerateMap/MapGenerator.cs b/src/GenerateMap/MapGenerator.cs index 8b07378fa..62a1d914c 100644 --- a/src/GenerateMap/MapGenerator.cs +++ b/src/GenerateMap/MapGenerator.cs @@ -12,6 +12,8 @@ internal static class MapGenerator private const string BasePath = "GenerateMap"; private static readonly string MapsPath = Path.Combine(BasePath, "Maps"); private static readonly string ImagesPath = Path.Combine(BasePath, "Images"); + private const int Edge = WorldMap.BlackEdgeWidth; + internal static void Init() { MapHelper.Initialize(); @@ -26,17 +28,12 @@ internal static void Init() private static WorldMap CreateWorkingMap() { - var edge = WorldMap.BlackEdgeWidth; - return new WorldMap(Main.maxTilesX, Main.maxTilesY) - { - _tiles = new MapTile[Main.maxTilesX + edge * 2, Main.maxTilesY + edge * 2] - }; + return new WorldMap(Main.maxTilesX, Main.maxTilesY) { _tiles = new MapTile[Main.maxTilesX + (Edge * 2), Main.maxTilesY + (Edge * 2)] }; } private static void LightUpWholeMap() { Main.Map = CreateWorkingMap(); - var edge = WorldMap.BlackEdgeWidth; var width = Main.Map._tiles.GetLength(0); var height = Main.Map._tiles.GetLength(1); for (var x = 0; x < Main.maxTilesX; x++) @@ -51,8 +48,8 @@ private static void LightUpWholeMap() Main.Map._tiles[x, y] = tile; } - var rawX = x + edge; - var rawY = y + edge; + var rawX = x + Edge; + var rawY = y + Edge; if ((uint) rawX < (uint) width && (uint) rawY < (uint) height) { Main.Map._tiles[rawX, rawY] = tile; @@ -61,16 +58,15 @@ private static void LightUpWholeMap() } } - private static Image CreateMapImg() + private static Image CreateMapImg() { Image image = new (Main.maxTilesX, Main.maxTilesY); LightUpWholeMap(); - var edge = WorldMap.BlackEdgeWidth; for (var x = 0; x < Main.maxTilesX; x++) { for (var y = 0; y < Main.maxTilesY; y++) { - var tile = Main.Map._tiles[x + edge, y + edge]; + var tile = Main.Map._tiles[x + Edge, y + Edge]; var col = MapHelper.GetMapTileXnaColor(tile); image[x, y] = new Rgba32(col.R, col.G, col.B, col.A); } @@ -86,7 +82,7 @@ internal static byte[] CreatMapImgBytes() image.SaveAsPng(stream); return stream.ToArray(); } - + internal static byte[] CreatMapFileBytes() { return File.ReadAllBytes(CreateMapFile()); @@ -110,12 +106,7 @@ private static string CreateMapFile() ? Main.worldID + ".map" : Main.ActiveWorldFileData.UniqueId + ".map"; var mapFilePath = Path.Combine(playerPath, mapFileName); - if (!File.Exists(mapFilePath)) - { - throw new FileNotFoundException("Map file not found.", mapFilePath); - } - - return mapFilePath; + return !File.Exists(mapFilePath) ? throw new FileNotFoundException("Map file not found.", mapFilePath) : mapFilePath; } internal static string SaveMapFile() @@ -127,4 +118,4 @@ internal static string SaveMapFile() File.Copy(mapPath, path, true); return path; } -} +} \ No newline at end of file diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index 52f005246..ff9f74acb 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -7,6 +7,7 @@ namespace GenerateMap; [ApiVersion(2, 1)] +// ReSharper disable once UnusedType.Global public class Plugin(Main game) : TerrariaPlugin(game) { public override string Author => "少司命, Cai, 千亦"; @@ -25,38 +26,31 @@ public override void Initialize() TShock.RestApi.RegisterRedirect("/generatemap", "/generatemap/img"); Commands.ChatCommands.Add(new Command("generatemap", Generate, "map", "生成地图", "generatemap")); } - + protected override void Dispose(bool disposing) { if (disposing) { ((List) typeof(Rest) - .GetField("commands", BindingFlags.NonPublic | BindingFlags.Instance)! - .GetValue(TShock.RestApi)!) + .GetField("commands", BindingFlags.NonPublic | BindingFlags.Instance)! + .GetValue(TShock.RestApi)!) .RemoveAll(x => x.UriTemplate.Contains("generatemap")); - + Commands.ChatCommands.RemoveAll(x => x.CommandDelegate == Generate); AppDomain.CurrentDomain.AssemblyResolve -= this.CurrentDomain_AssemblyResolve; } + base.Dispose(disposing); } - + private static RestObject RestGenerateMapFile(RestRequestArgs args) { - return new RestObject("200") - { - { "response", GetString("生成地图文件成功") }, - { "base64", Convert.ToBase64String(MapGenerator.CreatMapFileBytes()) } - }; + return new RestObject("200") { { "response", GetString("生成地图文件成功") }, { "base64", Convert.ToBase64String(MapGenerator.CreatMapFileBytes()) } }; } private static RestObject RestGenerateMapImg(RestRequestArgs args) { - return new RestObject("200") - { - { "response", GetString("生成地图图片成功") }, - { "base64", Convert.ToBase64String(MapGenerator.CreatMapImgBytes()) } - }; + return new RestObject("200") { { "response", GetString("生成地图图片成功") }, { "base64", Convert.ToBase64String(MapGenerator.CreatMapImgBytes()) } }; } private static void Generate(CommandArgs args) @@ -66,7 +60,7 @@ private static void Generate(CommandArgs args) ShowHelp(); return; } - + switch (args.Parameters[0]) { case "img": @@ -80,7 +74,7 @@ private static void Generate(CommandArgs args) } catch (Exception ex) { - TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); + TShock.Log.ConsoleError(GetString("[GenerateMap]生成地图出错: ") + ex); } }); break; @@ -94,7 +88,7 @@ private static void Generate(CommandArgs args) } catch (Exception ex) { - TShock.Log.ConsoleError( GetString("[GenerateMap]生成地图出错: ") + ex); + TShock.Log.ConsoleError(GetString("[GenerateMap]生成地图出错: ") + ex); } }); break; @@ -113,7 +107,7 @@ void ShowHelp() args.Player.SendSuccessMessage(GetString("/map img --- 生成地图图片")); } } - + #region 加载前置 private Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args) @@ -132,4 +126,4 @@ void ShowHelp() } #endregion -} +} \ No newline at end of file From 96fe358342b545cdd7162fbdcaa50483ef368bb7 Mon Sep 17 00:00:00 2001 From: Cai <13110818005@qq.com> Date: Tue, 17 Feb 2026 20:03:56 +0800 Subject: [PATCH 12/14] =?UTF-8?q?feat(GenerateMap):=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=B9=E5=8C=BA=E5=88=86=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/GenerateMap/MapGenerator.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/GenerateMap/MapGenerator.cs b/src/GenerateMap/MapGenerator.cs index 62a1d914c..871e63da8 100644 --- a/src/GenerateMap/MapGenerator.cs +++ b/src/GenerateMap/MapGenerator.cs @@ -113,8 +113,10 @@ internal static string SaveMapFile() { var mapPath = CreateMapFile(); var mapName = Path.GetFileNameWithoutExtension(mapPath); - var fileName = $"{mapName}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.map"; - var path = Path.Combine(MapsPath, fileName); + var fileName = $"{mapName}.map"; + var mapPathWithTime = Path.Combine(MapsPath, $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}"); + Utils.TryCreatingDirectory(mapPathWithTime); + var path = Path.Combine(mapPathWithTime, fileName); File.Copy(mapPath, path, true); return path; } From 6be08a26e5c07f417ad222999e17a9e3374c38f3 Mon Sep 17 00:00:00 2001 From: Cai <13110818005@qq.com> Date: Tue, 17 Feb 2026 20:39:59 +0800 Subject: [PATCH 13/14] =?UTF-8?q?refactor(CaiBotLite):=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8GenerateMap=E6=8F=92=E4=BB=B6=E6=8F=90=E4=BE=9B?= =?UTF-8?q?=E7=94=9F=E6=88=90=E5=9C=B0=E5=9B=BE=E6=9C=8D=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CaiBotLite/CaiBotLite.cs | 3 +- src/CaiBotLite/CaiBotLite.csproj | 6 +- src/CaiBotLite/Common/CaiBotApi.cs | 24 +++--- src/CaiBotLite/Common/MapGenerator.cs | 80 -------------------- src/CaiBotLite/Common/MapGeneratorSupport.cs | 38 ++++++++++ src/CaiBotLite/Common/WebsocketManager.cs | 19 ++++- src/GenerateMap/MapGenerator.cs | 16 +++- src/GenerateMap/Plugin.cs | 9 ++- 8 files changed, 85 insertions(+), 110 deletions(-) delete mode 100644 src/CaiBotLite/Common/MapGenerator.cs create mode 100644 src/CaiBotLite/Common/MapGeneratorSupport.cs diff --git a/src/CaiBotLite/CaiBotLite.cs b/src/CaiBotLite/CaiBotLite.cs index 945f02291..633781c5d 100644 --- a/src/CaiBotLite/CaiBotLite.cs +++ b/src/CaiBotLite/CaiBotLite.cs @@ -39,7 +39,7 @@ public override void Initialize() GeneralHooks.ReloadEvent += GeneralHooksOnReloadEvent; PlayerHooks.PlayerPostLogin += PlayerHooksOnPlayerPostLogin; GetDataHandlers.KillMe.Register(KillMe, HandlerPriority.Highest); - MapGenerator.Init(); + MapGeneratorSupport.Init(); EconomicSupport.Init(); BossLockSupport.Init(); ProgressControlSupport.Init(); @@ -63,7 +63,6 @@ protected override void Dispose(bool disposing) GeneralHooks.ReloadEvent -= GeneralHooksOnReloadEvent; PlayerHooks.PlayerPostLogin -= PlayerHooksOnPlayerPostLogin; GetDataHandlers.KillMe.UnRegister(KillMe); - MapGenerator.Dispose(); WebsocketManager.StopWebsocket(); } diff --git a/src/CaiBotLite/CaiBotLite.csproj b/src/CaiBotLite/CaiBotLite.csproj index 9138cb47a..97bf73135 100644 --- a/src/CaiBotLite/CaiBotLite.csproj +++ b/src/CaiBotLite/CaiBotLite.csproj @@ -4,18 +4,14 @@ - - - SixLabors.ImageSharp.dll - - + diff --git a/src/CaiBotLite/Common/CaiBotApi.cs b/src/CaiBotLite/Common/CaiBotApi.cs index 3f60eed16..766182935 100644 --- a/src/CaiBotLite/Common/CaiBotApi.cs +++ b/src/CaiBotLite/Common/CaiBotApi.cs @@ -1,7 +1,6 @@ using CaiBotLite.Enums; using CaiBotLite.Models; using Microsoft.Xna.Framework; -using SixLabors.ImageSharp.Formats.Png; using Terraria; using TerrariaApi.Server; using TShockAPI; @@ -11,7 +10,7 @@ namespace CaiBotLite.Common; internal static class CaiBotApi { - internal static async Task HandleMessageAsync(string receivedData) + internal static void HandleMessage(string receivedData) { var package = Package.Parse(receivedData); var packetWriter = new PackageWriter(package.Type, package.IsRequest, package.RequestId); @@ -161,23 +160,18 @@ internal static async Task HandleMessageAsync(string receivedData) break; case PackageType.MapImage: - var bitmap = MapGenerator.CreateMapImg(); - using (MemoryStream ms = new ()) - { - await bitmap.SaveAsync(ms, new PngEncoder()); - var imageBytes = ms.ToArray(); - var base64 = Convert.ToBase64String(imageBytes); - packetWriter - .Write("base64", Utils.CompressBase64(base64)) - .Send(); - } + var imageBytes = MapGeneratorSupport.CreatMapImgBytes(); + packetWriter + .Write("base64", Utils.CompressBase64(Convert.ToBase64String(imageBytes))) + .Send(); + break; case PackageType.MapFile: - var mapFile = MapGenerator.CreateMapFile(); + var mapFile = MapGeneratorSupport.CreateMapFile(); packetWriter .Write("name", mapFile.Item2) - .Write("base64", Utils.CompressBase64(mapFile.Item1)) + .Write("base64", Utils.CompressBase64(Convert.ToBase64String(mapFile.Item1))) .Send(); break; @@ -339,7 +333,7 @@ internal static async Task HandleMessageAsync(string receivedData) $"源数据包: {receivedData}"); packetWriter.Package.Type = PackageType.Error; - packetWriter.Write("error", ex) + packetWriter.Write("error", ex.ToString()) .Send(); } } diff --git a/src/CaiBotLite/Common/MapGenerator.cs b/src/CaiBotLite/Common/MapGenerator.cs deleted file mode 100644 index 57c45de00..000000000 --- a/src/CaiBotLite/Common/MapGenerator.cs +++ /dev/null @@ -1,80 +0,0 @@ -using MonoMod.RuntimeDetour; -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; -using Terraria; -using Terraria.IO; -using Terraria.Map; -using Image = SixLabors.ImageSharp.Image; - -namespace CaiBotLite.Common; - -internal static class MapGenerator -{ - private static readonly Hook WorldMapIndexerHook = new (typeof(WorldMap).GetMethod("get_Item")!, NewWorldMapIndexer); - - internal static void Init() - { - WorldMapIndexerHook.Apply(); - MapHelper.Initialize(); - Main.mapEnabled = true; - Main.Map = new WorldMap(Main.maxTilesX, Main.maxTilesY) { _tiles = new MapTile[Main.maxTilesX, Main.maxTilesY] }; - Main.ActivePlayerFileData = new PlayerFileData { Name = "CaiBot", _path = Main.GetPlayerPathFromName("CaiBot", false) }; - Main.MapFileMetadata = FileMetadata.FromCurrentSettings(FileType.Map); - } - - internal static void Dispose() - { - WorldMapIndexerHook.Dispose(); - } - - private static MapTile NewWorldMapIndexer(Func orig, WorldMap self, int x, int y) - { - try - { - return self._tiles[x, y]; - } - catch (IndexOutOfRangeException) - { - return new MapTile(); - } - } - - private static void LightWholeMap() - { - Main.Map = new WorldMap(Main.maxTilesX, Main.maxTilesY) { _tiles = new MapTile[Main.maxTilesX, Main.maxTilesY] }; - for (var x = 0; x < Main.maxTilesX; x++) - { - for (var y = 0; y < Main.maxTilesY; y++) - { - Main.Map._tiles[x, y] = MapHelper.CreateMapTile(x, y, byte.MaxValue); - } - } - } - - internal static Image CreateMapImg() - { - Image image = new (Main.maxTilesX, Main.maxTilesY); - LightWholeMap(); - for (var x = 0; x < Main.maxTilesX; x++) - { - for (var y = 0; y < Main.maxTilesY; y++) - { - var tile = Main.Map[x, y]; - var col = MapHelper.GetMapTileXnaColor(tile); - image[x, y] = new Rgba32(col.R, col.G, col.B, col.A); - } - } - - return image; - } - - internal static (string, string) CreateMapFile() - { - LightWholeMap(); - MapHelper.SaveMap(); - var playerPath = Main.playerPathName[..^4] + Path.DirectorySeparatorChar; - var mapFileName = !Main.ActiveWorldFileData.UseGuidAsMapName ? Main.worldID + ".map" : Main.ActiveWorldFileData.UniqueId + ".map"; - var mapFilePath = Path.Combine(playerPath, mapFileName); - return (Utils.FileToBase64String(mapFilePath), mapFileName); - } -} \ No newline at end of file diff --git a/src/CaiBotLite/Common/MapGeneratorSupport.cs b/src/CaiBotLite/Common/MapGeneratorSupport.cs new file mode 100644 index 000000000..99eb103da --- /dev/null +++ b/src/CaiBotLite/Common/MapGeneratorSupport.cs @@ -0,0 +1,38 @@ +using TerrariaApi.Server; + +namespace CaiBotLite.Common; + +internal static class MapGeneratorSupport +{ + private static bool Support { get; set; } + internal static void Init() + { + var pluginContainer = ServerApi.Plugins.FirstOrDefault(x => x.Plugin.Name == "GenerateMap"); + if (pluginContainer is not null) + { + Support = true; + } + } + + private static void ThrowIfNotSupported() + { + if (!Support) + { + throw new NotSupportedException("需要安装GenerateMap插件"); + } + } + + + internal static byte[] CreatMapImgBytes() + { + ThrowIfNotSupported(); + return GenerateMap.MapGenerator.CreatMapImgBytes(); + } + + internal static (byte[], string) CreateMapFile() + { + ThrowIfNotSupported(); + var mapFile = GenerateMap.MapGenerator.CreatMapFile(); + return (mapFile.File, mapFile.Name); + } +} \ No newline at end of file diff --git a/src/CaiBotLite/Common/WebsocketManager.cs b/src/CaiBotLite/Common/WebsocketManager.cs index e5cd5b01d..cdbfb3db8 100644 --- a/src/CaiBotLite/Common/WebsocketManager.cs +++ b/src/CaiBotLite/Common/WebsocketManager.cs @@ -14,8 +14,7 @@ public static class WebsocketManager public static ClientWebSocket? WebSocket; private const string BotServerUrl = "api.terraria.ink:22338"; - - //private const string BotServerUrl = "127.0.0.1:8080"; + internal static bool IsWebsocketConnected => WebSocket?.State == WebSocketState.Open; private static bool _isStopWebsocket; @@ -137,7 +136,21 @@ public static void StopWebsocket() TShock.Log.ConsoleInfo($"[CaiBotLite]收到BOT数据包: {receivedData}"); } - await CaiBotApi.HandleMessageAsync(receivedData); + _ = Task.Run(() => + { + try + { + CaiBotApi.HandleMessage(receivedData); + } + catch (Exception e) + { + TShock.Log.ConsoleError("[CaiBotLite]处理消息时发生错误: \n" + + $"{e}"); + } + + }); + + } } catch (Exception ex) diff --git a/src/GenerateMap/MapGenerator.cs b/src/GenerateMap/MapGenerator.cs index 871e63da8..28040c748 100644 --- a/src/GenerateMap/MapGenerator.cs +++ b/src/GenerateMap/MapGenerator.cs @@ -7,7 +7,7 @@ namespace GenerateMap; -internal static class MapGenerator +public static class MapGenerator { private const string BasePath = "GenerateMap"; private static readonly string MapsPath = Path.Combine(BasePath, "Maps"); @@ -75,17 +75,25 @@ private static Image CreateMapImg() return image; } - internal static byte[] CreatMapImgBytes() + public static byte[] CreatMapImgBytes() { var image = CreateMapImg(); using var stream = new MemoryStream(); image.SaveAsPng(stream); return stream.ToArray(); } + + public class MapFile(byte[] file, string name) + { + public readonly byte[] File = file; + public readonly string Name = name; + } - internal static byte[] CreatMapFileBytes() + public static MapFile CreatMapFile() { - return File.ReadAllBytes(CreateMapFile()); + var mapFilePath = CreateMapFile(); + var mapFile = new MapFile(File.ReadAllBytes(mapFilePath), Path.GetFileName(mapFilePath)); + return mapFile; } internal static string SaveMapImg(string fileName) diff --git a/src/GenerateMap/Plugin.cs b/src/GenerateMap/Plugin.cs index ff9f74acb..a4774d522 100644 --- a/src/GenerateMap/Plugin.cs +++ b/src/GenerateMap/Plugin.cs @@ -45,7 +45,14 @@ protected override void Dispose(bool disposing) private static RestObject RestGenerateMapFile(RestRequestArgs args) { - return new RestObject("200") { { "response", GetString("生成地图文件成功") }, { "base64", Convert.ToBase64String(MapGenerator.CreatMapFileBytes()) } }; + var mapFile = MapGenerator.CreatMapFile(); + + return new RestObject("200") + { + { "response", GetString("生成地图文件成功") }, + { "map_name", mapFile.Name }, + { "base64", Convert.ToBase64String(mapFile.File) } + }; } private static RestObject RestGenerateMapImg(RestRequestArgs args) From 525f027bd1dd26baeb198b9f440b2c7c1f0b4f32 Mon Sep 17 00:00:00 2001 From: Cai <13110818005@qq.com> Date: Tue, 17 Feb 2026 20:44:51 +0800 Subject: [PATCH 14/14] =?UTF-8?q?fix(CaiBotLite):=20=E4=BF=AE=E5=A4=8DMySQ?= =?UTF-8?q?L=E5=BB=BA=E8=A1=A8=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CaiBotLite/CaiBotLite.cs | 2 +- src/CaiBotLite/Models/BossKillInfo.cs | 1 + src/CaiBotLite/Models/CaiCharacterInfo.cs | 1 + src/CaiBotLite/Models/Mail.cs | 1 + src/CaiBotLite/README.md | 4 ++++ 5 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/CaiBotLite/CaiBotLite.cs b/src/CaiBotLite/CaiBotLite.cs index 633781c5d..167cfd134 100644 --- a/src/CaiBotLite/CaiBotLite.cs +++ b/src/CaiBotLite/CaiBotLite.cs @@ -13,7 +13,7 @@ namespace CaiBotLite; // ReSharper disable once ClassNeverInstantiated.Global public class CaiBotLite(Main game) : TerrariaPlugin(game) { - public static readonly Version VersionNum = new (2026, 02, 14, 0); //日期+版本号(0,1,2...) + public static readonly Version VersionNum = new (2026, 02, 17, 0); //日期+版本号(0,1,2...) internal static int InitCode = -1; internal static bool DebugMode = Program.LaunchParameters.ContainsKey("-caidebug"); private const string CharacterInfoKey = "CaiBotLite.CharacterInfo"; diff --git a/src/CaiBotLite/Models/BossKillInfo.cs b/src/CaiBotLite/Models/BossKillInfo.cs index 8a9d93e1c..a9b07f9cc 100644 --- a/src/CaiBotLite/Models/BossKillInfo.cs +++ b/src/CaiBotLite/Models/BossKillInfo.cs @@ -7,6 +7,7 @@ public class BossKillInfo { [PrimaryKey] [Identity] + [NotNull] [Column("id")] public int Id; diff --git a/src/CaiBotLite/Models/CaiCharacterInfo.cs b/src/CaiBotLite/Models/CaiCharacterInfo.cs index b8e42680c..dac29f7e6 100644 --- a/src/CaiBotLite/Models/CaiCharacterInfo.cs +++ b/src/CaiBotLite/Models/CaiCharacterInfo.cs @@ -7,6 +7,7 @@ namespace CaiBotLite.Models; public class CaiCharacterInfo { [PrimaryKey] + [NotNull] [Column("account_name")] public string AccountName = null!; diff --git a/src/CaiBotLite/Models/Mail.cs b/src/CaiBotLite/Models/Mail.cs index f07694d10..3258b5505 100644 --- a/src/CaiBotLite/Models/Mail.cs +++ b/src/CaiBotLite/Models/Mail.cs @@ -9,6 +9,7 @@ public class Mail { [PrimaryKey] [Identity] + [NotNull] [Column("id")] public int Id; diff --git a/src/CaiBotLite/README.md b/src/CaiBotLite/README.md index 24e23e0dc..fb6c82c09 100644 --- a/src/CaiBotLite/README.md +++ b/src/CaiBotLite/README.md @@ -33,6 +33,10 @@ https://docs.terraria.ink/zh/caibot/CaiBotLite.html ## 更新日志 +### v2026.02.17.0 + +- 改用GenerateMap生成地图,异步处理数据包 + ### v2026.02.15.0 - 适配Terraria 1.4.5