UUID 身份模型
基本信息
| 属性 | 值 |
|---|---|
| 核心类 | User、Group、CapeConfig |
| 管理器 | UserManager、GroupManager(均为单例) |
| 标识方式 | 玩家 UUID 字符串(不是玩家名) |
| 配置 ID 容量 | BitSet(256),ID 从 1 起 |
README 说明为何用 UUID:可以用 MCUUID.NET 手工查,或用 MCAPI 从 JSON 批量取。
User
public class User {
public List<ICape> capes;
public final String userUUID;
}
userUUID是 36 位带连字符的 UUID 字符串。capes是列表而非单个引用——一个玩家可以同时拥有多个披风(例如同时命中一个组和一条单人规则)。UserManager是全局单例,按 UUID 索引;解析与渲染都经由UserManager.getInstance().getUser(uuid)查找。
Group
public class Group {
protected HashMap<String, User> users;
protected ICape cape;
public final String name;
}
一个组 = 一个共享披风 + 一组 UUID。关键行为在 addUser:
public void addUser(User user) {
if (!this.users.containsValue(user)) {
user.capes.add(this.cape); // 把组披风挂到玩家身上
this.users.put(user.userUUID, user);
}
}
注意守卫用的是 containsValue(按 equals 查已存在的 User 对象)而写入用的是 userUUID。由于 User 没有覆写 equals/hashCode,同一 UUID 解析出的两个 User 实例会被判定为不同,从而在 capes 列表里出现重复条目。
setCape 会先把旧披风从所有成员身上移除再替换,但它没有把新披风加回去——只做 user.capes.remove(this.cape),随后设 this.cape = cape,成员身上不会自动获得新披风。
一个玩家的多披风与渲染取舍
渲染管线 里的 RenderEventHandler 只取 user.capes.get(0):
ICape cape = user.capes.get(0);
因此即使配置让一个玩家有多个披风,实际渲染的永远只有列表里的第一个。而 Group.addUser 是在解析期间按组出现的顺序 add 的,组在 JSON 里的先后决定哪个披风胜出(单人规则走 UserManager.parse,同样是 capes.add)。
配置 ID 分配
CapeConfigManager 用 HashBiMap<Integer, CapeConfig> 双向映射配置与整数 ID,ID 池是 BitSet availableIds = new BitSet(256):
| 规则 | 实现 | 结果 |
|---|---|---|
| 取新 ID | getUniqueId() = availableIds.nextClearBit(1) |
从 1 开始,跳过 0 |
| 占用校验 | claimId(id) |
id <= 0 抛 InvalidCapeConfigIdException |
| 重复占用 | claimId 检查 availableIds.get(id) |
抛 The config ID %d is already claimed. |
| 越界 | UnsignedBytes.checkedCast(id)(字节范围 0–255) |
异常被 printStackTrace() 吞掉,不向上抛 |
[!NOTE]
claimId里UnsignedBytes.checkedCast的catch只printStackTrace()不重抛,所以传入 ≥256 的 ID 会打印栈但继续正常占用该位。这是源码里的一个宽松处理。