API 与兼容
基本信息
| 属性 | 值 |
|---|---|
| API 根包 | com.github.lunatrius.schematica.api |
| API 声明 | @API(owner = "Schematica", apiVersion = "1.1", provides = "SchematicaAPI")(api/package-info.java:1) |
| 核心接口 | api/ISchematic.java(16 个方法) |
| 事件数 | 2(PreSchematicSaveEvent、PostSchematicCaptureEvent) |
| 兼容探针数 | 4(LOTR、ForgeMultipart、GTNH/DreamCraft、打印机放置注册表) |
| 编译期依赖 | com.github.GTNewHorizons:LunatriusCore:1.2.1-GTNH(dependencies.gradle:4) |
| 编译期可选依赖 | curse.maven:lotr-423748:4091561(compileOnly,dependencies.gradle:5) |
| 硬前置(运行时) | required-after:LunatriusCore;(reference/Reference.java:11) |
功能
对外 API:ISchematic
api/ISchematic.java 是蓝图的数据模型接口,16 个方法(按源码声明顺序):
| 方法 | 行 | 用途 |
|---|---|---|
Block getBlock(int x, int y, int z) |
:20 |
读方块;越界返回 Air(:13 javadoc) |
boolean setBlock(int x, int y, int z, Block block) |
:33 |
写方块(无 meta 重载) |
boolean setBlock(int x, int y, int z, Block block, int metadata) |
:46 |
写方块 + meta |
TileEntity getTileEntity(int x, int y, int z) |
:56 |
读 TileEntity |
List<TileEntity> getTileEntities() |
:63 |
取全部 TileEntity |
void setTileEntity(int x, int y, int z, TileEntity tileEntity) |
:73 |
写 TileEntity |
void removeTileEntity(int x, int y, int z) |
:82 |
删 TileEntity |
int getBlockMetadata(int x, int y, int z) |
:92 |
读元数据 |
boolean setBlockMetadata(int x, int y, int z, int metadata) |
:104 |
写元数据 |
List<Entity> getEntities() |
:111 |
取全部实体 |
void addEntity(Entity entity) |
:118 |
加实体 |
void removeEntity(Entity entity) |
:125 |
删实体 |
ItemStack getIcon() |
:132 |
读图标 |
void setIcon(ItemStack icon) |
:139 |
设图标 |
int getWidth() / int getLength() / int getHeight() |
:146/:153/:160 |
三轴尺寸 |
事件
两个事件都继承 FML Event 并实现 Cancelable/HasResult 语义之外的最小形式,字段为 public final ISchematic schematic:
| 事件 | 文件 | 触发点 |
|---|---|---|
PostSchematicCaptureEvent |
api/event/PostSchematicCaptureEvent.java:12 |
写文件前,SchematicFormat.writeToFile 投递(world/schematic/SchematicFormat.java:77-78) |
PreSchematicSaveEvent |
api/event/PreSchematicSaveEvent.java:15 |
写 NBT 前,SchematicAlpha.writeToNBT 两处投递(world/schematic/SchematicAlpha.java:273、:385) |
PreSchematicSaveEvent 额外暴露 public final NBTTagCompound extendedMetadata(:27)与 boolean replaceMapping(String oldName, String newName) throws DuplicateMappingException(:53),供其他 mod 在保存前改写方块 ID 映射。
⚠️ PostSchematicCaptureEvent 的 getResult() 未被检查——writeToFile 只是无条件 MinecraftForge.EVENT_BUS.post(event) 后继续写盘(world/schematic/SchematicFormat.java:77-89),监听方无法通过 event 阻止写入。
配套异常 api/event/DuplicateMappingException.java:3 继承 Exception,由 replaceMapping 在映射冲突时抛出。
打印机放置注册表(PlacementRegistry)
client/printer/registry/PlacementRegistry.java 是单例(INSTANCE,:25),静态块中调 populatePlacementMaps() 填充三张表(:175-177)。查询优先级为 item → block → block 类(getPlacementData,:155-173)。
| 表 | 字段 | 填充方式 |
|---|---|---|
| 类表 | classPlacementMap |
addPlacementMapping(Class<? extends Block>, PlacementData)(:131) |
| 方块表 | blockPlacementMap |
addPlacementMapping(Block, PlacementData)(:139) |
| 物品表 | itemPlacementMap |
addPlacementMapping(Item, PlacementData)(:147) |
populatePlacementMaps()(:31-129)预置 11 个类级 + 24 个方块级 + 4 个物品级映射,类级为 BlockButton/BlockChest/BlockDispenser/BlockEnderChest/BlockFurnace/BlockHopper/BlockPistonBase/BlockPumpkin/BlockRotatedPillar/BlockStairs/BlockTorch(:38-71),物品级为 Items.wooden_door/iron_door/repeater/comparator(:117-128)。
PlacementData(client/printer/registry/PlacementData.java:11)含 PlacementType 枚举(:13)、maskOffset(默认 0x0)、maskMeta(默认 0xF)、offsetLowY/offsetHighY(默认 0.0f/1.0f)与 Map<ForgeDirection, Integer> mapping(:21-27)。setOffset / setMaskMeta / setExtraClick 均为链式 setter(:39、:46、:85)。
IExtraClick(client/printer/registry/IExtraClick.java:4-6)是函数式接口 int getExtraClicks(Block, int metadata),用于按方块属性决定额外点击次数。预置两处使用:双层石/木台阶各自挂 block.isOpaqueCube() ? 1 : 0(:36、:81、:110)。
数值
跨 mod 兼容探针
| 目标 mod | 探针 | 来源 |
|---|---|---|
lotr(Lord of the Rings Mod) |
Loader.isModLoaded("lotr") → 反射实例化 Reference.LOTR_PROXY |
proxy/ClientProxy.java:383-388 |
ForgeMultipart |
Loader.isModLoaded("ForgeMultipart") |
nbt/ForgeMultipart.java:39 |
dreamcraft(GTNH) |
Loader.isModLoaded("dreamcraft") → CommonProxy.GTNH |
proxy/CommonProxy.java:48 |
LOTR 兼容:ILOTRPresent(compat/ILOTRPresent.java:10)只定义 Boolean isBlackListed(Block, ItemStack)(:17)。LOTRProxy 实现把 LOTRMod.chisel 与 LOTRMod.chiselIthildin 拉黑(compat/LOTRProxy.java:16),因为凿子有多个变体方块。加载失败或未装 LOTR 时回退 NoLOTRProxy,其 isBlackListed 恒返回 false(compat/NoLOTRProxy.java:9-11)。
⚠️ ILOTRPresent 的 proxy 创建是反射而非直接 new(proxy/ClientProxy.java:385-388),且整个块包在 try/catch 中,异常时打 warn "Failed to create lotr proxy in the normal way" 并回退(:392-395)。ILOTRPresent 的 javadoc 注明这是基于 Forge 论坛 diesieben07 的帖子的标准做法(compat/ILOTRPresent.java:7-8),并留有 // TODO:fix printer functionality with weapon racks/ armour stands/ plates etc.(:18)。
ForgeMultipart 兼容:nbt/ForgeMultipart.java 在 postInit 调 init()(proxy/CommonProxy.java:65)。init() 用 ReflectionHelper 反射取 codechicken 的 Scala 单例与方法(:48-93),客户端与服务端走不同路径(:105-115):客户端手工遍历 parts 复合标签重建(:124-160),服务端直接 methodCreateFromNBT.invoke(:162-170)。反射失败则打 error "Something went wrong, disabling FMP integration." 并自我禁用 enabled = false(:95-96)。
客户端路径在 parts 数量不匹配时打 info 并返回 null(:142-145),parts 为空同样返回 null(:147-149)。
GTNH 探针:CommonProxy.GTNH = Loader.isModLoaded("dreamcraft")(proxy/CommonProxy.java:48)——用 modid 猜整合包,若整合包改名即失效。
Litematica 格式翻译层
compat/ 包的 4 张映射表服务于 .litematic 读取(见 蓝图格式),均为本仓库自建,不依赖 Litematica mod:
| 表 | 条目数 | 来源 |
|---|---|---|
DirectBlockMappings |
258 | ^ m( 计数(compat/DirectBlockMappings.java) |
VanillaBlockRenames |
302 | put( 计数(compat/VanillaBlockRenames.java) |
VanillaPropertyMeta |
234 | ^ p( 计数(compat/VanillaPropertyMeta.java) |
BlockStateTranslator.KEEP_PROPERTIES |
20 | KEEP_PROPERTIES.put 计数(compat/BlockStateTranslator.java) |
DirectBlockMappings 刻意绕过字符串查注册表、直接引用 Blocks.xxx 静态字段,因为某些方块注册名与预期不符(如 minecraft:stone_bricks → Blocks.stonebrick,compat/DirectBlockMappings.java:14-16 注释)。
VanillaBlockMappings 暴露 getBlockName_1_7_10(String modernName) 与 getMetadata(String blockName, String properties)(compat/VanillaBlockMappings.java:27-37),后者在查不到时返回 -1(:33、:36)。颜色系列方块通过 registerColorMeta 按白=0、橙=1、品红=2……展开(:44-50)。
交互
其他 mod 使用本 API 的推荐路径:
- 监听
PreSchematicSaveEvent,调replaceMapping把不能被打印机放置的方块映射到替代方块——例:compat/LOTRProxy用黑名单方式处理,见上。 - 调
PlacementRegistry.INSTANCE.addPlacementMapping(...)为自家方块补放置朝向规则(client/printer/registry/PlacementRegistry.java:131-153)。 - 直接构造
world/storage/Schematic(ISchematic实现)读写蓝图数据模型。
跨 mod 内容隔离说明
以下内容不属于本仓库,本条目不收录其行为:
- Litematica mod(1.21):本仓库只自行解析
.litematic文件格式,不依赖、不集成 Litematica mod。 schematica分类(wiki 中已存在的另一个条目):对应mirror/Schematica仓库的上游版本,modid 同为Schematica,但源码树、commit 与注册内容均不同。本条目全部内容来自/Users/evlos/a/mirror/Schematica-Plus/。- LunatriusCore(硬前置):
com.github.lunatrius.core.util.vector.Vector3i等工具类来自外部仓库,本仓库只消费其 API。