MyTown2 集成(已失效)
结论先行
MyTown2 集成在当前源码中永远不会被加载。
Class.forName 请求的类名与实际类名不符(包名和类名都不对),
必然抛 ClassNotFoundException,被 catch 后回退到
HEMyTown2IntegrationDummy——该 Dummy 对任何人都返回 true。
后果:其他玩家的 MyTown2 地皮范围内,水体方块仍可被放置 / 扩散。
缺陷现场
server/mytown2/HEMyTown2Integration.java:12-28:
public static HEMyTown2Integration getInstance() {
if (instance == null) {
if (Loader.isModLoaded(HETags.MyTown2_MODID)) {
try {
instance = Class.forName("com.sinthoras.hydroenergy.server.HEMyTown2Implementation")
.asSubclass(HEMyTown2Integration.class).newInstance();
} catch (Exception e) {
HE.warn("Could not initialize MyTown2 Integration. Pretending MyTown2 is not loaded!");
instance = new HEMyTown2IntegrationDummy();
}
} else {
instance = new HEMyTown2IntegrationDummy();
}
}
return instance;
}
三处不一致
| 项 | Class.forName 请求的 |
实际存在的类 | 一致? |
|---|---|---|---|
| 包名 | com.sinthoras.hydroenergy.server |
com.sinthoras.hydroenergy.server.mytown2 |
❌ 缺 .mytown2 |
| 类名 | HEMyTown2Implementation |
HEMyTown2IntegrationImplementation |
❌ 缺 Integration |
| 构造器 | 无参 newInstance() |
无参 | ✅ |
实测(grep '^package')三个类的真实全限定名:
| 文件 | FQN |
|---|---|
server/mytown2/HEMyTown2Integration.java |
com.sinthoras.hydroenergy.server.mytown2.HEMyTown2Integration(抽象基类) |
server/mytown2/HEMyTown2IntegrationImplementation.java |
com.sinthoras.hydroenergy.server.mytown2.HEMyTown2IntegrationImplementation |
server/mytown2/HEMyTown2IntegrationDummy.java |
com.sinthoras.hydroenergy.server.mytown2.HEMyTown2IntegrationDummy |
正确写法应为
Class.forName("com.sinthoras.hydroenergy.server.mytown2.HEMyTown2IntegrationImplementation")。
📌 注意请求串把类名和包名都写错了,不是单纯的包名笔误。
Dummy 的行为
server/mytown2/HEMyTown2IntegrationDummy.java(全文):
public class HEMyTown2IntegrationDummy extends HEMyTown2Integration {
public boolean hasPlayerModificationRightsForChunk(String residentName, int dimension, int chunkX, int chunkZ) {
return true;
}
}
忽略全部 4 个参数,恒返回 true —— 即「所有人对所有区块都有修改权」。
影响链
唯一的调用点在 server/HEBlockQueue.java:112-122:
boolean[] permissionsChecked = new boolean[HEConfig.maxDams];
boolean[] hasPermissions = new boolean[HEConfig.maxDams];
...
while (!blockStack.isEmpty()) {
QueueEntry entry = blockStack.pop();
int waterId = entry.waterBlock.getWaterId();
if (permissionsChecked[waterId] == false) {
hasPermissions[waterId] = HEMyTown2Integration.getInstance().hasPlayerModificationRightsForChunk(
HEServer.instance.getOwnerName(waterId),
chunk.worldObj.provider.dimensionId,
chunk.xPosition,
chunk.zPosition);
permissionsChecked[waterId] = true;
}
hasPermissions[waterId] 用于决定水体方块能否在该区块被放置 / 保留。
由于恒为 true,MyTown2 的地皮保护对水体完全不生效。
⚠️ 注意权限检查用的
residentName是HEServer.instance.getOwnerName(waterId),即水坝主人的名字, 不是当前操作玩家的名字——即便集成修好,它检查的也是 「坝主人能否改这个区块」,而非「谁点的右键」。
本应生效的实现
server/mytown2/HEMyTown2IntegrationImplementation.java(全文):
package com.sinthoras.hydroenergy.server.mytown2;
import mytown.entities.TownBlock;
import mytown.new_datasource.MyTownUniverse;
public class HEMyTown2IntegrationImplementation extends HEMyTown2Integration {
public boolean hasPlayerModificationRightsForChunk(String residentName, int dimension, int chunkX, int chunkZ) {
TownBlock chunk = MyTownUniverse.instance.blocks.get(dimension, chunkX, chunkZ);
if (chunk == null) {
return true;
}
return chunk.getTown().residentsMap.contains(residentName);
}
}
逻辑本身合理:无人占领 → 放行;否则要求该居民在 town 的 residentsMap 中。
它 import 的是 mytown.*(MyTown2 的真实包),说明作者当初是按 MyTown2 写的。
⚠️ 该类直接 import MyTown2 的类。这正是它必须用
Class.forName延迟加载的原因—— 没装 MyTown2 时直接引用会导致NoClassDefFoundError。 类名写错使这套延迟加载机制从未成功执行过一次。
门控
| 项 | 值 | 行 |
|---|---|---|
| 检测的 modid | HETags.MyTown2_MODID = "MyTown2"(区分大小写) |
HETags.java:38 |
| 检测方式 | Loader.isModLoaded("MyTown2") |
HEMyTown2Integration.java:14 |
| 单例缓存 | private static HEMyTown2Integration instance |
HEMyTown2Integration.java:10 |
| 线程安全 | 无,getInstance() 未同步 |
HEMyTown2Integration.java:12 |
MyTown2 是否在本 wiki 收录范围
data/relation.md 有 mytown2 分类行(驼峰转小写,源码目录为 MyTown2),
但 data/mytown2/ 目录尚未建立——该分类在本 wiki 尚未收录完成。
因此本页不复述 MyTown2 的功能,只记录本 mod 侧的集成代码与缺陷。 跨分类链接见 分类页。