Crate Pile System
基本信息
| 属性 | 值 |
|---|---|
| 包路径 | net.mcft.betterstorage.tile.crate |
| 类数量 | 6 |
| 核心常量 | TileEntityCrate.slotsPerCrate = 18 |
| 世界 Tick 钩子 | CratePileCollection.onTick() |
来源:src/main/java/net/mcft/betterstorage/tile/crate/。
功能
木箱的堆叠(pile)系统是本 mod 唯一不依赖固定槽位的容器模型。与箱子不同,木箱可以自由堆叠成 1×1 到 3×3 的立方体,同一堆的所有木箱共享同一份物品数据——拆掉其中一箱不会丢失内容。
类清单
| 类 | 职责 |
|---|---|
CratePileData |
单个堆叠的数据:箱数、容量、内容、已占用槽位 |
CratePileCollection |
世界内所有堆叠的集合,负责落盘 |
CratePileMap |
坐标 → 堆叠的索引,支持快速查找 |
CrateItems |
物品内容容器(Map<ItemIdentifier, ItemStack>) |
TileCrate |
方块类 |
TileEntityCrate |
TileEntity 类 |
容量计算
public int getCapacity() {
return numCrates * TileEntityCrate.slotsPerCrate;
}
来源:src/main/java/net/mcft/betterstorage/tile/crate/CratePileData.java:53-55;常量定义 src/main/java/net/mcft/betterstorage/tile/crate/TileEntityCrate.java:34。
| 堆叠规模 | 箱数 | 容量(槽位) |
|---|---|---|
| 1×1 | 1 | 18 |
| 2×2 | 4 | 72 |
| 3×3 | 9 | 162 |
物品存储模型
CrateItems 用 Map<ItemIdentifier, ItemStack> 存储,每种物品只有一个条目(src/main/java/net/mcft/betterstorage/tile/crate/CrateItems.java:19):
get(ItemIdentifier)返回该物品数量,0 表示不存在(:39-42)set(ItemIdentifier, int)增删物品并自动更新totalStacks(:51-74)getUniqueItems()返回物品种类数(:29-31)getTotalStacks()返回总占用槽位数(:34-36)getItems()遍历全部内容(:80-82)getRandomStacks()/getRandomStacks(int)返回随机顺序的栈(:88-110),用于破坏时掉落
CrateItems 内部维护一个 NavigableMap<Integer, ItemStack> weightedMap(:22),按栈数累加建立权重索引,使随机选取与堆大小成比例(:112-119)。源码注释指出这是一个待优化的实现:
// TODO: Find a better way than recreating the weighted map every time something changes.
来源:CrateItems.java:25-26。
随机掉落
ItemsIterator(CrateItems.java:121-154)实现随机且不重复的遍历:
- 用
TreeSet<Integer> picked记录已选索引 - 每次随机取一个未选索引(
:139) - 返回的栈会按
maxStackSize拆分(:146)
落盘
CratePileData 的保存流程(src/main/java/net/mcft/betterstorage/tile/crate/CratePileData.java):
| 方法 | 行 | 作用 |
|---|---|---|
isDirty() |
98 | 是否已标记为脏 |
markDirty() |
103 | 标记为脏(已脏或已销毁则跳过) |
save() |
115 | 若为脏则写入 collection 并清除标记 |
markDirty / save 在 crateDebugMessages 开启时输出日志,格式为 [CRATE DEBUG] Marked crate pile at [x,y,z] as dirty.(:106-111, 119)。
世界级保存由 CratePileCollection.onTick() 在世界 tick 的服务端侧触发(src/main/java/net/mcft/betterstorage/proxy/CommonProxy.java:316-319):
if (event.side == Side.SERVER) CratePileCollection.getCollection(event.world).onTick();
GUI 行数
木箱 GUI 的行数随堆叠规模变化(src/main/java/net/mcft/betterstorage/tile/crate/TileEntityCrate.java:233-241):
PlayerUtils.openGui(player, getName(), getColumns(),
2 * Math.min(data.getNumCrates(), 3), getContainerTitle(), createContainer(player));
即行数 = 2 × min(箱数, 3),最多 6 行。列数取自容器。
比较器输出
getComparatorSignalStengthInternal(TileEntityCrate.java:252-257):
return ((data.getOccupiedSlots() > 0) ? (1 + data.getOccupiedSlots() * 14 / data.getCapacity()) : 0);
无物品时为 0,否则为 1 + 已占用 * 14 / 容量,范围 1–15。
方块视图
InventoryCrateBlockView(src/main/java/net/mcft/betterstorage/inventory/InventoryCrateBlockView.java)把堆叠内容暴露为标准 IInventory:
getSizeInventory()返回numStacksStored + 1(:39-41),第 0 槽为过滤槽- 构造时通过
data.addWatcher(this)注册为ICrateWatcher(:33-37) - 维护
changed与accessed两个标志(:25, 29)
该视图受 general.enableCrateInventoryInterface 控制(TileEntityCrate.java:296, 303)。