Atelier 结构编辑
原生分片放置、可恢复版本、大平原地标与游戏内结构编辑器。
Atelier 以有界的原生 NBT 分片导出和放置结构。编辑任务逐一执行;自然地标由区块工作线程在地物和结构之前生成,二者使用同一套局部坐标。
它做什么
创造模式管理员可用/ise dev atelier block取得isekaiexpansion:atelier_structure_block。把编辑器放在选区外,再打开界面。界面沿用现有开发者编辑器框架和主题设置。
选择BUNDLED、IMPORT或EXPORT,输入结构包 ID 和版本,再检查资源。检查会填入尺寸和地形数据,并记录清单摘要。更改放置设置后需要重新检查。预览显示世界包围盒;放置时设置必须与检查结果一致。
导出读取实时方块及带类型的方块实体数据,也包含显式空气。导出结束前请保持选区不变。导出使用世界轴向,旋转必须为0。导出不包含普通实体;外部传入的分片若含普通实体则会被拒绝。NPC 和游戏实体由各自系统定义。
交换目录
以下路径相对于 Fabric 游戏目录:
data/isekaiexpansion/atelier/exports/<namespace>/<id path>/<revision>/
data/isekaiexpansion/atelier/imports/<namespace>/<id path>/<revision>/
每个版本包含manifest.json和pieces/文件。清单最后写入,未完成的导出无法导入。已有导出版本不能覆盖;中断后需要换一个版本名。
在 Atelier 编辑完成后,将新版本送到导入目录,选择IMPORT,检查并放置。再次导出游戏内修改时,保留局部原点和体积,另取版本名。更改已检查版本的名称时,编辑器会将原版本记为父版本。
运行时模型
api.atelier中的AtelierAPI把调用交给内部服务。仅在SERVER_STARTED之后的服务器线程调用。任务由END_SERVER_TICK驱动。注册表和方块访问留在服务器线程,单个 IO 工作线程负责分片校验与压缩。编辑器数据包要求玩家是附近的创造模式管理员,并拒绝过期编辑器版本。
放置先请求一小组区块,在修改前保存原始格数据及校验值,然后写入分片。全部分片就位后,再遍历一次以解析相邻状态并安排流体更新。此过程不广播全量红石更新。用状态按钮刷新进度。
恢复数据存于<world>/isekaiexpansion/atelier/jobs/<UUID>/。/ise dev atelier pause、/ise dev atelier resume <UUID>和/ise dev atelier undo <UUID>在当前维度执行。继续会按原版本重放,并保留最初的修改前快照;撤销恢复记录中的格数据。撤销可能覆盖这些格子之后的手工修改。它们不等于完整世界备份,也不回滚普通实体。重启后,中断的放置任务会暂停,不会自动重放。
自然地标
KTM2 地形绑定时,地标选择未探索的大平原中心,并保存 ID、版本、摘要和坐标。预留建造半径覆盖完整结构矩形及余量,即使地形设置较低也能容纳结构。位置会避开世界树和已有预留区。
LandmarkGeneration在ChunkGenerator.generateFeatures之前填入当前区块。ChunkPieceIndex索引相交分片;写入器将每格严格裁剪到当前区块,支持负坐标与跨区块分片,不请求相邻区块。每个地标的并发解码缓存最多保留262144格。修改区块前会先解码全部相交分片;读取或写入失败会中止生成,不能把残缺结构标记为完成。周围区块就绪后,由原版区块后处理解析方块连接与流体。
结构矩形及余量保护整列高度。完全位于保护范围内的区块跳过自然装饰;边界区块仍在范围外正常装饰。ChunkRegion保护世界生成写入、方块实体访问和实体放置;异常安全的工作线程作用域同时阻止地物直接修改受保护区块。相交的结构起点在建立引用及地形适配前被拒绝,放置检查也保护已存在的起点。
保护范围内禁止自然刷怪、区块种群、巡逻、结构生物、增援和骑乘组合生成。命令、刷怪蛋、繁殖、刷怪笼和地牢主动EVENT生成仍然可用。这些规则阻止新增自然生物,不删除既有生物,也不阻止动物走入城镇。
原版区块状态负责生成进度和重启恢复。进服不会排队放置地标,也不会修改玩家位置或重生点。/ise dev atelier landmarks报告预留边界,不加载对应区块。首个结构区块加载时,服务器通过CityAPI注册城市配置,不加载其余城镇。isekaiexpansion:lucentrystel对应isekaiexpansion:lucentrystel_outpost配置。资源摘要固定保存在存档中;资源变化会导致校验失败。平坦世界只提供手动编辑。
第三方 Arona Layers Gen 还会在区块转为运行时区块时添加地形层。可选兼容注入在其直接写入区块分段及转换植物前调用LandmarkProtectionAPI.blocksDecoration,保留占地范围内的人工层块和空气,范围外的地形装饰照常执行。注入目标已对照已安装的1.2.2+mc1.20.1模组包检查;仅在加载aronalayersgen时启用。
地标保护
游戏运行时沿用同一份不可变占地边界和余量,保护整列高度。集成代码可通过LandmarkProtectionAPI.contains和canBreak查询服务器规则。客户端工具在预测挖掘前可查询api.client.atelier.LandmarkProtectionClientAPI.canBreak。只有权限等级至少为2的创造模式玩家可以绕过挖掘保护。编辑器、命令和受信任的游戏逻辑仍使用各自的权限;绕过原版破坏流程直接写入方块的工具必须先查询此 API。
服务器在接收挖掘动作和最终移除方块前分别检查权限。拒绝操作时,先重发目标、相邻6格及可用的方块实体更新,再确认客户端预测序号。客户端根据服务器快照阻止开始挖掘、持续挖掘及预测移除。在支持此协议的服务器上,当前维度快照到达前会暂时禁止挖掘;旧连接或旧维度的数据不能授予编辑权。绕过保护还要求本地当前处于创造模式管理员状态,因此退出创造模式后,无须等待下一份保护数据包即可停止预测挖掘。
进服、重生和切换维度时同步边界。服务器每刻比较玩家维度、创造模式管理员状态及不可变索引对象,未变化时不发送数据。客户端在连接初始化和断开时清空状态,并拒绝上一连接延迟到达的数据包。检查不扫描地形,也不加载区块。索引使用原始数值区块键,分配前限制为最多256个区域、262144个区块引用,重叠部分重复计数。
爆炸在破坏方块及发送爆炸数据包前移除受保护坐标,实体伤害仍生效。生物和投射物更新作用域禁止替换受保护方块或改变植物年龄。保护区内的生物破坏规则读取会被局部拒绝,包括末影人4格拾取范围;世界游戏规则本身不变。门和压力板等同种方块状态交互仍可使用。火焰不能烧毁受保护方块,也不能从范围外引燃它们。活塞不能移动或破坏受保护格,包括跨边界移动。流体不能冲毁受保护实体方块;空气、已有流体和含水状态仍可参与流动。异常和乘客切换都会恢复先前的破坏作用域。
landmark_protection快照使用严格二进制协议;landmark_protection_request的数据体为空,不能授予权限:
| 字段 | 类型 | 默认值 | 含义 |
|---|---|---|---|
protocol | VarInt | 是 | 必须为1;拒绝旧值。 |
dimension | identifier | 是 | 此包替换哪个维度的边界。 |
editor | boolean | 是 | 服务器计算的创造模式管理员权限。 |
count | VarInt | 是 | 0–256个矩形。 |
bounds | count × 4个有符号整数 | 是 | 包含端点的minX、minZ、maxX、maxZ,各为-30000000…30000000。拒绝反向边界、超出索引预算和多余字节。 |
约定
结构包清单
内置版本的资源路径为data/<namespace>/atelier/bundles/<id path>/<revision>/manifest.json。分片坐标相对结构包共同原点;每个 NBT 分片内的方块坐标从自身最小角开始。编辑器原点为编辑器方块位置加原点偏移,旋转围绕该原点进行。
| 字段 | 类型 | 默认值 | 作用 |
|---|---|---|---|
schema | integer | 必填 | 必须为2。 |
id | identifier | 必填 | 结构包标识,包含命名空间;拒绝路径跳转。 |
revision | string | 必填 | 不可变版本名,匹配[a-z0-9_-]{1,64}。 |
parentRevision | string | 必填 | 前一版本;没有则留空。 |
stage | string | 必填 | 发布阶段,最多128个字符。 |
min | array<integer> | 必填 | 局部 XYZ 最小值;各坐标为-8192…8192。 |
size | array<integer> | 必填 | XYZ 长度,各为1–4096;总体积不超过64000000格。最大边界不包含在体积内。 |
center | array<integer> | 必填 | 局部地形中心;XZ 必须在占地范围内。 |
terrainDatum | integer | 必填 | 与预留平原表面对齐的局部 Y;必须在垂直边界内。 |
clearance | integer | 必填 | 水平保护余量,0–256格;预留半径覆盖扩展后的矩形。 |
pieces | array<object> | 必填 | 非空列表,最多8192个互不重叠的分片包围盒。 |
pieces[].file | string | 必填 | 唯一的pieces/[a-z0-9_-]+.nbt路径。 |
pieces[].pos | array<integer> | 必填 | 相对结构包共同原点的 XYZ 偏移。 |
pieces[].size | array<integer> | 必填 | XYZ 尺寸,最多32 × 256 × 32;必须位于结构包边界内。 |
pieces[].sha256 | string | 必填 | 压缩 NBT 字节的 SHA-256 小写值。 |
pieces[].blocks | integer | 必填 | 显式格数,1–250000,不超过分片体积。 |
加载器拒绝无效边界、重叠包围盒、缺失文件、校验值变化、未知方块 ID 或属性,以及错误 NBT 类型。分片使用 Minecraft 数据版本3465。空气删除方块;未列出的格子和结构空位保留目标现状。清单表中每个字段均为必填。未知键(包括已移除的到达字段)会被拒绝。结构包、编辑草稿、放置日志和地标存档统一使用版本2,没有旧原型数据的兼容读取器。此次格式变更后,自然生成测试应使用新世界。
常规导出保留方块实体 NBT。放置按配置重置编辑器运行状态,撤销则跳过重置。相对门控目标、结构空间区域、门的显示状态和 Jigsaw 最终状态都会随旋转调整。旋转放置在修改世界前拒绝没有适配器的模组方块实体,以及原版结构方块数据。旋转为0时,其他数据仅更新目标 XYZ,其余保持不变。结构空间标记保留编辑数据;房产空间需通过对应编辑器或结构空间 API 绑定。
服务器配置
atelier属于服务器本地IsekaiConfig。编辑器预算在每刻读取,地标位置和不可变生成方案在世界绑定时准备。无效配置会校验失败,不会自动截断到范围内。
| 选项 | 类型 | 默认值 | 作用 |
|---|---|---|---|
blocksPerTick | integer | 4096 | 编辑器每刻处理格数上限,64–32768。 |
millisecondsPerTick | integer | 6 | 格循环时间预算,1–15毫秒;区块生成和文件提交仍有各自开销。 |
generateLandmark | boolean | true | 为自然区块生成预留指定地标;已有预留区继续生效。 |
landmark | identifier | isekaiexpansion:lucentrystel | 用于自然生成的结构包。 |
revision | string | exterior-v1 | 新预留位置使用的内置版本;已有位置保留保存的版本。 |
searchRings | integer | 8 | 候选地形网格的搜索圈数,1–32。 |
resetEditorRuntimeOnPlacement | boolean | true | 重置导出的地牢传送门 ID、门控进度和已开宝箱状态;保留编辑配置。撤销恢复原始 NBT。 |
扩展方式
添加新的不可变资源版本,保留坐标约定,再在服务器设置中选择该版本。内置isekaiexpansion:lucentrystel / exterior-v1标记为exterior-foundation-work-in-progress。发布阶段只是元数据,不代表玩法完整性检查已通过。
为含相对坐标的新方块实体添加支持时,同时扩展EditorNbtProcessor和预检查适配列表,并在tools/atelier/dev/AtelierCheck.java增加往返与旋转测试。AtelierAPI提供编辑器动作、状态、暂停、继续和撤销;调用方不应直接管理内部任务表。
验证
在模组仓库运行原生结构包与恢复约定检查:
./gradlew.bat -I tools/atelier/verify.gradle checkAtelier assembleLanguageFiles --offline --console=plain
然后在临时世界中加载模组验证:导出包含空气、容器和地牢编辑器的体积;检查并以各个旋转角度放置;暂停、重启、继续并撤销。撤销后核对原始格数据。在新的 KTM2 地形世界中,通过普通探索检查区块生成、分片接缝、边界保护、自然刷怪抑制、城市注册和不变的进服位置。重启后确认区块及玩家编辑保留。离线测试在正负原点校验全部外景方块的区块归属,并比较顺序、乱序、并行写入及方块实体。以上是运行时验收步骤,离线任务通过不能代替这些检查。