v1.2.5: 策略3落地为玩家周围扩地(按距离铺开);状态机switch改为具名分支;修复rings命令设置重启后失效
这个提交包含在:
@@ -45,10 +45,10 @@ public final class ConfigStore {
|
|||||||
if (loaded == null) {
|
if (loaded == null) {
|
||||||
return new ExpansionConfig();
|
return new ExpansionConfig();
|
||||||
}
|
}
|
||||||
// 以下字段为固定默认值,防止旧配置文件中的异常值影响运行
|
// autoEat/eatThreshold 字段为固定默认值,防止旧配置文件中的异常值影响运行;
|
||||||
|
// 注意:maxRings 由 /autostore rings 命令持久化,不得在此覆盖,否则命令设置会在重启后失效
|
||||||
loaded.autoEat = true;
|
loaded.autoEat = true;
|
||||||
loaded.eatThreshold = 14;
|
loaded.eatThreshold = 14;
|
||||||
loaded.maxRings = 0;
|
|
||||||
return loaded;
|
return loaded;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 解析失败时回退到默认配置
|
// 解析失败时回退到默认配置
|
||||||
|
|||||||
@@ -302,35 +302,36 @@ implements SubtitleChatMonitor.Listener, BaritoneBridge.PathListener {
|
|||||||
this.tickSideStep();
|
this.tickSideStep();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (this.state.ordinal()) {
|
switch (this.state) {
|
||||||
case 1: {
|
case PLANNING: {
|
||||||
this.plan();
|
this.plan();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 2: {
|
case PATHING: {
|
||||||
this.tickPathing();
|
this.tickPathing();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 3: {
|
case WAITING: {
|
||||||
this.tickWaiting();
|
this.tickWaiting();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 4: {
|
case SUCCESS: {
|
||||||
this.tickSuccess();
|
this.tickSuccess();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 5: {
|
case FAIL: {
|
||||||
this.tickFail();
|
this.tickFail();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 6: {
|
case NEXT: {
|
||||||
this.tickNext();
|
this.tickNext();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 7: {
|
case RETURNING: {
|
||||||
this.tickReturning();
|
this.tickReturning();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// IDLE / COMPLETE / STOPPED 无需每帧驱动
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,12 @@ import net.fabricmc.api.Environment;
|
|||||||
/**
|
/**
|
||||||
* 扩地规划器:根据当前邦国领土、配置与玩家位置,计算下一步要占领的区块列表。
|
* 扩地规划器:根据当前邦国领土、配置与玩家位置,计算下一步要占领的区块列表。
|
||||||
*
|
*
|
||||||
* <p>支持三种扩地策略:
|
* <p>支持四种扩地策略:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>策略 1:方形外扩(优先填内部空洞,再向外一圈圈扩展)</li>
|
* <li>策略 1:方形外扩(优先填内部空洞,再向外一圈圈扩展)</li>
|
||||||
|
* <li>策略 3:玩家周围扩地(围绕玩家从近到远铺开)</li>
|
||||||
* <li>策略 4:绕国一圈(沿领土边界按角度均匀向外扩张)</li>
|
* <li>策略 4:绕国一圈(沿领土边界按角度均匀向外扩张)</li>
|
||||||
* <li>其他(2/3):直线推进(沿一个方向连续向外延伸)</li>
|
* <li>其他(2 无圈选区域 / 未知值):直线推进(沿一个方向连续向外延伸)</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
public final class ExpansionPlanner {
|
public final class ExpansionPlanner {
|
||||||
@@ -45,6 +46,8 @@ public final class ExpansionPlanner {
|
|||||||
result = this.generateHolePriority(model, config, playerChunk);
|
result = this.generateHolePriority(model, config, playerChunk);
|
||||||
} else if (config.strategy == 4) {
|
} else if (config.strategy == 4) {
|
||||||
result = this.generatePerimeter(model, config, playerChunk);
|
result = this.generatePerimeter(model, config, playerChunk);
|
||||||
|
} else if (config.strategy == 3) {
|
||||||
|
result = this.generateAroundPlayer(model, config, playerChunk);
|
||||||
} else if (config.strategy == 2 && config.regionMaxX >= config.regionMinX) {
|
} else if (config.strategy == 2 && config.regionMaxX >= config.regionMinX) {
|
||||||
result = this.generateRectangle(model, config, playerChunk);
|
result = this.generateRectangle(model, config, playerChunk);
|
||||||
} else {
|
} else {
|
||||||
@@ -164,7 +167,32 @@ public final class ExpansionPlanner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 策略 2/3:直线推进。
|
* 策略 3:玩家周围扩地。
|
||||||
|
*
|
||||||
|
* <p>收集所有与己方领土相邻的合法区块,以玩家当前位置为中心,
|
||||||
|
* 按与玩家的曼哈顿距离由近到远排序(距离相同者优先邻居数多、形状更紧实的),
|
||||||
|
* 围绕玩家一圈圈向外铺开,而非沿固定方向直线推进。</p>
|
||||||
|
*/
|
||||||
|
private List<ChunkPos> generateAroundPlayer(TerritoryModel model, ExpansionConfig config, ChunkPos playerChunk) {
|
||||||
|
Set<ChunkPos> actualOwn = this.ownChunks(model);
|
||||||
|
Set<ChunkPos> allClaimed = model.allClaimedChunks();
|
||||||
|
if (actualOwn.isEmpty()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
int limit = config.targetCount > 0 ? config.targetCount : 64;
|
||||||
|
HashSet<ChunkPos> plannedOwn = new HashSet<ChunkPos>(actualOwn);
|
||||||
|
HashSet<ChunkPos> candidates = new HashSet<ChunkPos>();
|
||||||
|
this.addNeighbors(plannedOwn, candidates, allClaimed, config);
|
||||||
|
if (candidates.isEmpty()) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
Comparator<ChunkPos> byDistance = Comparator.comparingInt(playerChunk::manhattanDistance)
|
||||||
|
.thenComparingInt(chunk -> -this.ownNeighbors(chunk, plannedOwn));
|
||||||
|
return candidates.stream().sorted(byDistance).limit((long)limit).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 策略 2(无圈选区域时)/ 未知策略回退:直线推进。
|
||||||
*
|
*
|
||||||
* <p>从玩家当前位置出发,沿一个方向连续向外延伸占领区块(形成一条"线")。
|
* <p>从玩家当前位置出发,沿一个方向连续向外延伸占领区块(形成一条"线")。
|
||||||
* 每步从候选集中挑选评分最优的区块:距离越近、越贴合当前方向、邻居越多、形状越规整越好。
|
* 每步从候选集中挑选评分最优的区块:距离越近、越贴合当前方向、邻居越多、形状越规整越好。
|
||||||
@@ -456,7 +484,7 @@ public final class ExpansionPlanner {
|
|||||||
return chunk.x() >= config.regionMinX && chunk.x() <= config.regionMaxX
|
return chunk.x() >= config.regionMinX && chunk.x() <= config.regionMaxX
|
||||||
&& chunk.z() >= config.regionMinZ && chunk.z() <= config.regionMaxZ;
|
&& chunk.z() >= config.regionMinZ && chunk.z() <= config.regionMaxZ;
|
||||||
}
|
}
|
||||||
// 回退到圆形区域(中心+半径)
|
// 回退到以中心+半径限定的正方形区域(切比雪夫距离,与"圈数"距离定义一致)
|
||||||
int dx = Math.abs(chunk.x() - config.regionCenterX);
|
int dx = Math.abs(chunk.x() - config.regionCenterX);
|
||||||
return Math.max(dx, dz = Math.abs(chunk.z() - config.regionCenterZ)) <= Math.max(1, config.regionRadius);
|
return Math.max(dx, dz = Math.abs(chunk.z() - config.regionCenterZ)) <= Math.max(1, config.regionRadius);
|
||||||
}
|
}
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户