From c55e4eaf8be35c9095b09269150f01dfea6181bd Mon Sep 17 00:00:00 2001 From: lyizai <3945107889@qq.com> Date: Wed, 19 Aug 2026 13:09:42 +0800 Subject: [PATCH] =?UTF-8?q?v1.2.1:=20=E4=BF=AE=E5=A4=8D=E9=A3=9E=E5=9C=B0?= =?UTF-8?q?=E6=A3=80=E6=B5=8B=E2=80=94=E2=80=94=E6=8C=89=20dynmap=20even-o?= =?UTF-8?q?dd=20=E8=A7=84=E5=88=99=E8=A7=A3=E6=9E=90=E9=A2=86=E5=9C=9F?= =?UTF-8?q?=E5=A4=9A=E8=BE=B9=E5=BD=A2=EF=BC=8C=E5=86=85=E5=9C=88=E5=AD=94?= =?UTF-8?q?=E6=B4=9E=EF=BC=88=E5=9B=BD=E4=B8=AD=E9=A3=9E=E5=9C=B0=E8=BE=B9?= =?UTF-8?q?=E7=95=8C=EF=BC=89=E4=B8=8D=E5=86=8D=E8=A2=AB=E5=B9=B6=E9=9B=86?= =?UTF-8?q?=E5=A1=AB=E5=85=85=E6=8E=A9=E7=9B=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +-- gradle.properties | 2 +- .../territory/TerritoryDataService.java | 51 ++++++++++++------- src/main/resources/fabric.mod.json | 2 +- 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 61cebee..e8795da 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,13 @@ - 实时地图 GUI(通过 Ctrl+R 打开) - 监听聊天/字幕消息判断开垦结果 - 刷新地图时与最新 `markers.json` 核对已占领区块,丢弃地图未确认的超期假占领,避免高地扩地残留空洞 -- 飞地(疏漏区块)检测:自动扫描每个邦国内外接矩形内"四周被同邦国占领但自身未占领"的区块,内置地图用红色标出己方飞地,自动扩地时优先填补这些缺口 +- 飞地(疏漏区块)检测:按 dynmap 奇偶填充规则解析领土多边形,正确识别国中由边界围出的内圈空腔;内置地图用红色标出己方飞地,自动扩地时优先填补这些缺口 - 日志导出:GUI 右上角“导出日志”按钮,或 `/autostore log` 命令,记录寻路、坐标、状态、路径事件等 ## 安装 1. 安装 Fabric Loader 0.16.14+ 和 Fabric API -2. 将 `autostore-1.2.0.jar` 放入 `.minecraft/mods/` 目录 +2. 将 `autostore-1.2.1.jar` 放入 `.minecraft/mods/` 目录 3. 启动游戏,按 `Ctrl+R` 打开 GUI ## 构建 @@ -31,7 +31,7 @@ ./build_mod.sh ``` -输出文件:`autostore-1.2.0.jar` +输出文件:`autostore-1.2.1.jar` ## 赞助支持 diff --git a/gradle.properties b/gradle.properties index 9692199..c62ab19 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ yarn_mappings=1.21.4+build.8 loader_version=0.19.3 # Mod Properties -mod_version=1.2.0 +mod_version=1.2.1 maven_group=autostore archives_base_name=autostore diff --git a/src/main/java/autostore/client/territory/TerritoryDataService.java b/src/main/java/autostore/client/territory/TerritoryDataService.java index 17fc798..2d3cd24 100644 --- a/src/main/java/autostore/client/territory/TerritoryDataService.java +++ b/src/main/java/autostore/client/territory/TerritoryDataService.java @@ -269,9 +269,9 @@ public final class TerritoryDataService { return; } Set chunks = claims.computeIfAbsent(name, ignored -> new HashSet()); - for (List polygon : TerritoryDataService.extractPolygons(marker.get("points"))) { - TerritoryDataService.fillPolygon(chunks, polygon); - } + // 一个 marker 的多个多边形遵循 dynmap 的 even-odd 填充规则: + // 外圈为正,内圈多边形(国中飞地的边界)作为孔洞被减去,而非作为独立领土并集填充。 + TerritoryDataService.fillPolygonEvenOdd(chunks, TerritoryDataService.extractPolygons(marker.get("points"))); colors.putIfAbsent(name, TerritoryDataService.parseColor(TerritoryDataService.stringOr(marker, "color", "#75bd20"))); } @@ -337,31 +337,46 @@ public final class TerritoryDataService { } /** - * 将多边形覆盖的区块填充进集合: - * 先算出多边形外接矩形(换算为区块坐标),再逐区块用"点在多边形内"算法判断, - * 以区块中心点(cx*16+8, cz*16+8)是否落在多边形内为准。 - * 面积超过 600 万区块时直接放弃,防止异常数据导致卡死。 + * 将多边形组覆盖的区块按 even-odd 规则填充进集合。 + * + *

一个 marker 里的多个多边形遵循 dynmap 的奇偶填充:区块落入奇数个多边形内时才视为领土; + * 这样内圈多边形(国中飞地/孔洞的边界)会被正确减去,而不是像并集那样把孔洞也填成领土。

+ * + * @param output 输出集合(该邦国的区块集合) + * @param polygons 该 marker 的全部多边形,第一个为外圈、可为多个内圈孔洞 */ - private static void fillPolygon(Set output, List polygon) { - int area; + private static void fillPolygonEvenOdd(Set output, List> polygons) { + if (polygons.isEmpty()) { + return; + } int minX = Integer.MAX_VALUE; int maxX = Integer.MIN_VALUE; int minZ = Integer.MAX_VALUE; int maxZ = Integer.MIN_VALUE; - for (int[] point : polygon) { - minX = Math.min(minX, Math.floorDiv(point[0], 16)); - maxX = Math.max(maxX, Math.floorDiv(point[0], 16)); - minZ = Math.min(minZ, Math.floorDiv(point[1], 16)); - maxZ = Math.max(maxZ, Math.floorDiv(point[1], 16)); + for (List polygon : polygons) { + for (int[] point : polygon) { + minX = Math.min(minX, Math.floorDiv(point[0], 16)); + maxX = Math.max(maxX, Math.floorDiv(point[0], 16)); + minZ = Math.min(minZ, Math.floorDiv(point[1], 16)); + maxZ = Math.max(maxZ, Math.floorDiv(point[1], 16)); + } } - int n = area = ((maxX - minX) + 1L) * ((maxZ - minZ) + 1L) > Integer.MAX_VALUE ? Integer.MAX_VALUE : (maxX - minX + 1) * (maxZ - minZ + 1); - if (area > 6000000) { + // 面积超过 600 万区块时直接放弃,防止异常数据导致卡死 + if ((long)(maxX - minX + 1) * (maxZ - minZ + 1) > 6000000L) { return; } for (int cx = minX; cx <= maxX; ++cx) { for (int cz = minZ; cz <= maxZ; ++cz) { - if (!TerritoryDataService.pointInPolygon(cx * 16 + 8, cz * 16 + 8, polygon)) continue; - output.add(new ChunkPos(cx, cz)); + // 奇偶填充:落在奇数个多边形内则为领土;否则(含恰好落在偶数个内圈孔洞中)忽略 + boolean inside = false; + for (List polygon : polygons) { + if (TerritoryDataService.pointInPolygon(cx * 16 + 8, cz * 16 + 8, polygon)) { + inside = !inside; + } + } + if (inside) { + output.add(new ChunkPos(cx, cz)); + } } } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 669172c..012583e 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1 +1 @@ -{"schemaVersion":1,"id":"autostore","version":"1.2.0","name":"AutoStore","description":"","authors":[],"contact":{},"license":"All-Rights-Reserved","environment":"client","entrypoints":{"fabric-datagen":["autostore.client.AutoStoreModDataGenerator"],"client":["autostore.client.AutoStoreModClient"],"main":["autostore.AutoStoreMod"]},"mixins":["autostore.mixins.json",{"config":"autostore.client.mixins.json","environment":"client"}],"depends":{"fabricloader":">=0.16.14","fabric-api":"*","minecraft":"1.21.4"},"jars":[{"file":"META-INF/jars/baritone-api-fabric-1.13.1.jar"}]} \ No newline at end of file +{"schemaVersion":1,"id":"autostore","version":"1.2.1","name":"AutoStore","description":"","authors":[],"contact":{},"license":"All-Rights-Reserved","environment":"client","entrypoints":{"fabric-datagen":["autostore.client.AutoStoreModDataGenerator"],"client":["autostore.client.AutoStoreModClient"],"main":["autostore.AutoStoreMod"]},"mixins":["autostore.mixins.json",{"config":"autostore.client.mixins.json","environment":"client"}],"depends":{"fabricloader":">=0.16.14","fabric-api":"*","minecraft":"1.21.4"},"jars":[{"file":"META-INF/jars/baritone-api-fabric-1.13.1.jar"}]} \ No newline at end of file