高级配方注册表
跳过 Forge 形状数组,直接拿 InventoryCrafting 的内容做运行时匹配的配方框架。适用于槽位非固定的机器类配方。
基本信息
| 属性 | 值 |
|---|---|
| 接口 | wanion.lib.recipe.advanced.IAdvancedRecipe |
| 注册表 | wanion.lib.recipe.advanced.AbstractRecipeRegistry<R extends IAdvancedRecipe> |
| 存储 | 两个 TShortObjectMap<List<R>>(Trove,TShortObjectHashMap) |
| 泛型参数 | R 必须是 IAdvancedRecipe 的子类型 |
IAdvancedRecipe 接口
public interface IAdvancedRecipe extends IRemovable {
short getRecipeKey();
short getRecipeSize();
boolean recipeMatch(@Nonnull InventoryCrafting inventoryCrafting, int offSetX, int offSetY);
@Nonnull ItemStack getOutput();
}
| 成员 | 返回类型 | 契约 |
|---|---|---|
getRecipeKey() |
short |
0 表示无序(shapeless),非 0 表示有序,键 = recipeSize | (width << 8) | (height << 12) |
getRecipeSize() |
short |
非空格占用的物品总数,作为 shapeless 桶的键 |
recipeMatch(InventoryCrafting, int offSetX, int offSetY) |
boolean |
由消费方实现;offSetX / offSetY 是工作台内第一个非空格位的列/行坐标 |
getOutput() |
@Nonnull ItemStack |
产物 |
继承自 IRemovable 的成员:
| 成员 | 签名 | 说明 |
|---|---|---|
removed() |
boolean |
软删除标记,供消费方过滤已注销配方 |
setRemoved(boolean) |
void |
写该标记 |
AbstractRecipeRegistry不检查removed()—— 移除必须由消费方显式调 移除方法。
注册表成员
| 成员 | 签名 | 行为 |
|---|---|---|
| 有序桶 | public final TShortObjectMap<List<R>> shapedRecipes |
键 = recipeKey |
| 无序桶 | public final TShortObjectMap<List<R>> shapelessRecipes |
键 = recipeSize |
| 添加 | public final void addRecipe(@Nonnull R recipe) |
getRecipeKey() != 0 → 进 shapedRecipes;否则取 getRecipeSize() 进 shapelessRecipes。桶不存在时 new ArrayList<>() |
| 移除 | public final void removeRecipe(@Nullable R recipe) |
recipe == null 直接 return;按同一分流规则 List.remove(recipe),列表为 null 时静默跳过 |
| 匹配 | public final R findMatchingRecipe(@Nonnull InventoryCrafting inventoryCrafting) |
见下 |
findMatchingRecipe 流程
root = (int) Math.sqrt(inventoryCrafting.getSizeInventory())—— 3×3 工作台得root = 3。- 求
offSetX:外层x、内层y扫y * root + x,找到第一个非空格位即停,取该x。 - 求
offSetY:外层y、内层x扫同一索引式,取该y。 - 求
width/height:以(offSetX - 1, offSetY - 1)为原点量出包围盒,超界即停。 - 数
recipeSize:遍历height × width内非空格格数。 - 算
recipeKey = recipeSize | (width << 8) | (height << 12)。 - 先查
shapedRecipes.get(recipeKey),未命中回落shapelessRecipes.get(recipeSize)。 - 桶非
null时逐个recipe.recipeMatch(inventoryCrafting, offSetX, offSetY),命中即返回;全不命中返回null。
⚠️ 键位宽:
width落在位 8~11、height落在位 12~15,各占 4 bit,故两者都隐含被限制在0~15;recipeSize占位 0~7。recipeKey为short(有符号),height == 8起会置符号位。⚠️
AbstractRecipeRegistry是abstract但没有任何抽象方法 —— 它是可直接实例化的容器基类,抽象只是留给消费方当命名空间/类型参数锚点。
使用流程
- 实现
IAdvancedRecipe:getRecipeKey()返回(size | (w << 8) | (h << 12))或0(无序),recipeMatch()里自行遍历InventoryCrafting比对。 class MyRegistry extends AbstractRecipeRegistry<MyRecipe> {}。registry.addRecipe(new MyRecipe(...))。- 在
Container/ GUI 的 slot 变化回调里registry.findMatchingRecipe(inventoryCrafting)。
相关条目
- 配方形状转换 - 另一条配方路线:生成 Forge 形状数组
- MetaItem 物品键编码 - 若在
recipeMatch内比对物品,优先用它 - 主类入口与依赖注入 -
IRemovable接口定义处 - 工具类 - 库内通用工具