工具类

三组互不相关的通用工具:反射字段访问、定长数组列表、CraftTweaker 桥接。

基本信息

属性 值
包 wanion.lib.common
类数量 3(Util、FixedSizeList<E>、MineTweakerHelper)
共同点 Util 与 MineTweakerHelper 为 final + 私有构造 + 全 static;FixedSizeList 可实例化

wanion.lib.common.Util

成员 签名 行为
读字段 public static <T, E extends T> E getField(Class clas, String name, Object instance, Class<T> expectedClass) getDeclaredField(name) + setAccessible(true) + expectedClass.cast(field.get(instance));catch (Exception e) → printStackTrace() 后返回 null
写字段 public static <E> void setField(Class clas, String name, Object instance, E newInstance) getDeclaredField(name) + setAccessible(true) + field.set(...);catch (Exception e) → printStackTrace(),无返回值
取 modid public static String getModName(ItemStack itemStack) GameData.getItemRegistry().getNameForObject(itemStack.getItem()) 后 substring(0, indexOf(58))

⚠️ getField 的类型参数写法为 <T, E extends T>,返回类型是子类 E,即调用方可写 Util.<ItemStack, ItemStack>getField(...) 之类的显式形式;直接 Util.getField(cls, "f", o, ItemStack.class) 由目标类型推断。

⚠️ getField 只 getDeclaredField,不沿继承链向上找 —— 父类私有/受保护字段取不到,须逐级指定类。indexOf(58) 中的 58 是字符 ':',故 getModName 依赖注册名带命名空间;对无命名空间的条目会得到 substring(0, -1) 并抛 StringIndexOutOfBoundsException。

wanion.lib.common.FixedSizeList<E>

public class FixedSizeList<E> extends AbstractList<E> —— 底层是裸 E[],容量构造时固定,add 满后返回 false 而不是抛异常。

成员 签名 行为
默认容量 private static final int DEFAULT_CAPACITY = 64
构造 public FixedSizeList() capacity = 64
构造 public FixedSizeList(int capacity) capacity <= 0 时回落到 64(注意:赋给的是形参,this.capacity 由 new Object[this.capacity = capacity] 取已修正值)
构造 private FixedSizeList(@Nonnull Collection<E> collection) 私有;capacity = size = collection.size(),精确容量
大小 public int size()
空判定 public boolean isEmpty() size == 0
尾部添加 public boolean add(E e) size == capacity 时返回 false;否则写入并 size++ 返回 true
按下标写 public void add(int index, E e) 直接覆盖 allTheData[index],不检查越界、不改 size、不检查容量
读 public E get(int index) index > size 时返回 null;否则返回 allTheData[index]
删 public E remove(int index) index >= size 时 throw new IndexOutOfBoundsException();否则 modCount++、System.arraycopy 左移、末位置 null、size--,返回被删元素
转数组 @Nonnull public Object[] toArray() Arrays.copyOf(allTheData, size)
清空 public void clear() modCount++,逐个置 null 至 size == 0

⚠️ get 的边界是 index > size(非 >=):当 index == size 且该槽已因 remove 被置 null 时返回 null(不抛异常);若该槽尚有值则会返回「逻辑上已越界」的元素。AbstractList 契约要求越界抛异常,此处未遵守。

⚠️ add(int index, E e) 与 List 契约相反:它不插入、不扩容,纯粹是数组下标写。

⚠️ 类未覆写 set / addAll / iterator 等,继承来的实现可能与底层数组语义不一致。

wanion.lib.common.MineTweakerHelper

把 CraftTweaker 脚本 API 对象还原成 Minecraft 侧对象。依赖是 compileOnly(CraftTweaker 3.4.6 / ZenScript 1.0.1-GTNH),运行时缺 CraftTweaker 则本类不可加载。

成员 签名 行为
取栈 public static ItemStack toStack(IItemStack item) item == null → null;item.getInternal() 非 ItemStack 时 MineTweakerAPI.getLogger().logError("Not a valid item stack: " + item);仍返回 null
批量取 public static Object[] toObjects(IIngredient[] list) list == null → null;逐项 toObject(...)
取实际对象 public static Object toActualObject(IIngredient ingredient) IOreDictEntry → OreDictionary.getOres(name)(ItemStack[]);IItemStack → toStack(...);其余 → null
取通用对象 public static Object toObject(IIngredient ingredient) IOreDictEntry → 矿辞名字符串 name;IItemStack → toStack(...);其余 → null
取矿辞名 public static String toString(IOreDictEntry entry) entry.getName()

toActualObject 与 toObject 的关键差异:

输入 toActualObject toObject
IOreDictEntry OreDictionary.getOres(name) → 已解析的 ItemStack[] name → String
IItemStack toStack(item) → ItemStack toStack(item) → ItemStack
null null null
其它 IIngredient 实现 null null

toObject 的矿辞分支返回字符串而非解析结果,因此它能安全地喂给 Forge 形状数组(IRecipe 接受矿辞名字符串);toActualObject 需要的是已展开的物品列表。

相关条目