Back to mods
Chasm api project artwork

CurseForge · Minecraft mod

Chasm api

Chasm api brings modding back to its essence with a declarative API – define features in a few lines, and the framework handles registration, assets, and extensibility, so you focus on gameplay, not boilerplate.

Choose a version Pick your version below, then grab the matching file.

Quick answer

Which Chasm api release should I use?

Updated 17 days ago
Latest stable file chasm-1.1.2.jar
Game version 1.21.1
Loader Fabric

Chasm api chasm-1.1.2.jar targets 1.21.1 with Fabric. The project page does not say whether this file belongs on the client, dedicated server, or both. All 1 required mods have matching files.

Where it goes

Is Chasm api required on the client, server, or both?

The project page does not say whether this file belongs on the client, dedicated server, or both.

Client Source doesn’t say
Dedicated server Source doesn’t say
Loader for this release Fabric
Required install it here Optional supported, not mandatory Not supported do not install here Source doesn’t say do not assume

The source does not explicitly classify this release as client-only or server-only.

What else does Chasm api chasm-1.1.2.jar need?

chasm-1.1.2.jar. Change the file and its required mods may change too.

All 1 required mods have matching files

Install Fabric API first. We found matching files for this game-version and loader setup.

Fabric API Needed by Chasm api chasm-1.1.2.jar
required
Matching file found Matched file: [1.21.1] Fabric API 0.116.17+1.21.1

We only count dependency files that match this setup. A file for another loader does not fill the gap.

Before you install it

Add Chasm api without breaking your instance.

Built for Chasm api chasm-1.1.2.jar. Pick another file and the loader, install side or required mods may change.

  1. 01

    Stick to this file

    Use chasm-1.1.2.jar. It targets 1.21.1 with Fabric; another release may have different loader, side or dependency requirements.

  2. 02

    Bring the mods it needs

    Install Fabric API first. We found matching files for this game-version and loader setup.

  3. 03

    Put it on the correct side

    The project page does not say whether this file belongs on the client, dedicated server, or both.

  4. 04

    Pick the file you checked

    Use the “Get this file” button beside chasm-1.1.2.jar. It opens that exact file at the source.

About this project

What does Chasm api add?

Chasm api – A Modding Framework

Item creation via chained declarations

No inheritance or manual registration. The framework handles registration, models, language files, and recipes.

Chasm.item()
    .type(SWORD).attackDamage(10)
    .name("Blazing Blade").texture("minecraft:item/diamond_sword")
    .onAttack(ctx -> ctx.target().setOnFire(5))
    .register();

Declarative configuration

Data components, enchantment pools, GUI windows, and durability can be configured declaratively. No need to write NBT or network packets directly.

Asset generation

Run runDatagen to generate models, language files, recipes, and loot tables into your resources folder.

SPI-based extension

Other mods can add behaviors through SPI, without subclassing or exposing internal APIs.


Chasm 2.0 aims to reduce boilerplate so you can focus on gameplay.


Chasm api – 模组开发框架

链式声明创建物品

无需继承或手动注册,框架会处理注册、模型、语言文件和配方。

Chasm.item()
    .type(SWORD).attackDamage(10)
    .name("烈焰之刃").texture("minecraft:item/diamond_sword")
    .onAttack(ctx -> ctx.target().setOnFire(5))
    .register();

声明式配置

数据组件、附魔池、GUI 窗口、耐久消耗等都可以通过声明式配置完成,不需要直接处理 NBT 或网络包。

资源文件生成

运行 runDatagen,模型、语言文件、配方和掉落表会自动生成到资源目录。

SPI 扩展

其他模组可以通过 SPI 追加物品行为,不需要继承或暴露内部接口。


Chasm 2.0 希望减少样板代码,让开发者把时间放在玩法设计上。


code wiki

Chasm 2.0 Code Wiki(开发者手册)

适用版本:Chasm core v1.1.2(mod_version),基于 Minecraft 1.21.1 / Fabric Loader 0.19.3 / Fabric API 0.116.15+1.21.1 / Java 21生成日期:2026-09-05。 读者:所有使用 Chasm 开发模组的作者。本文所有签名与行为均核对自当前源码;标注为"已知限制"的条目是刻意保留/尚未实现的能力,使用时请留意。


目录

  1. 项目是什么
  2. 快速开始:5 分钟跑通一个 Chasm 模组
  3. 核心心智模型与代码地图
  4. 物品 Item
  5. 物品类型系统 ItemType
  6. 数据组件 Data Component
  7. 行为特质 Trait
  8. 方块 Block
  9. 合成配方 Recipe
  10. 伤害类型与伤害计算
  11. 属性 Attribute
  12. 自定义附魔 Enchantment(数据驱动)
  13. 玩家持久化变量 PlayerVar
  14. 声明式 GUI
  15. 自定义按键 Custom Key
  16. JSON 软编码(物品 / GUI)
  17. 日志系统
  18. DataGen 自动化
  19. 跨模组扩展(SPI)
  20. 测试
  21. 已知限制与注意事项(当前代码核实)
  22. 版本变更记录(2026-09 重构说明)
  23. 附录

1. 项目是什么

Chasm(api.chasm)是一套 "玩法优先"的 Minecraft Fabric 模组开发 API,把"声明一个物品/方块 → 组合玩法行为 → 绑定数据 → 自动注册 → 自动生成资源"做成一行行链式声明,目标是消灭样板代码与手写 JSON,同时保留原版语义(横扫、附魔池、挖掘等级、剥皮/耕地、容器界面、按键、存档持久化…)。

1.1 模块结构

模块 内容 规模(当前)
chasm-core API 库本体(api.chasm.*,含 api.chasm.item.contextapi.chasm.net 等) 85 个 Java 文件 ≈ 8.9k 行
chasm-core/src/test P0 纯 JVM 单元测试(JUnit 5) 4 个文件 ≈ 288 行
chasm-example 演示模组(com.example.chasm,modId=mymod):魔法剑/杖/水晶/镐/斧/法杖 + 自定义附魔 + 自定义类型 + GUI + 按键 + JSON 软编码 3 个文件 ≈ 452 行

1.2 技术要点

  • 依赖:gradle.properties 定义 minecraft_version=1.21.1loader_version=0.19.3loom_version=1.17-SNAPSHOTfabric_api_version=0.116.15+1.21.1mod_version=1.1.2
  • chasm-example 通过 modImplementation project(':chasm-core') 依赖 core(chasm-example/build.gradle:47),并在 fabric.mod.json 声明 "chasm-core": "*"
  • 零 Mixin:框架不注入任何原版类;附魔台/附魔池集成完全依赖 1.21.1 数据驱动标签。core 的 fabric.mod.json 只有 main(api.chasm.ChasmInit) 与 client(ChasmGuiClientChasmKeyClient) 入口点。
  • 构建命令:
    • ./gradlew :chasm-example:build(build 会自动先跑 runDatagen 再编译)
    • ./gradlew :chasm-example:runClient / runServer / runDatagen
    • ./gradlew :chasm-core:test(跑 P0 单测)
    • ./gradlew :chasm-core:publishToMavenLocal

2. 快速开始

2.1 工程骨架

一个 Chasm 模组 = 1 个 @ChasmMod 入口类 + 若干 @Register 静态字段 + onInitialize 里扫描一次:

package com.example.mymod;

import api.chasm.Chasm;
import api.chasm.ChasmMod;
import api.chasm.data.DataComponent;
import api.chasm.item.ItemBuilder;
import api.chasm.registry.ChasmRegistrar;
import api.chasm.registry.Register;
import net.fabricmc.api.ModInitializer;
import net.minecraft.world.item.Item;

@ChasmMod(id = "mymod")                                  // ★ modId 命名空间
public class MyMod implements ModInitializer {

    // —— 数据组件(record + 注解,Codec 自动生成)——
    @DataComponent("mana")
    public static final ManaData MANA = ManaData.EMPTY;

    // —— 物品:声明即注册(id = mymod:mana_sword)——
    @Register("mana_sword")
    public static final Item MANA_SWORD = Chasm.item()
        .type(ChasmTypes.SWORD)          // 成为真正的 SwordItem(横扫/剑类附魔池)
        .maxStackSize(1)
        .durability(1200)
        .attackDamage(10.0f)             // 总攻击伤害(自动换算原版修饰符)
        .name("Mana Sword")              // DataGen 自动生成语言文件
        .texture("minecraft:item/diamond_sword")  // DataGen 自动生成模型
        .register();                     // 只构建实例;真正注册由 scan 完成
        // 给 Record 组件绑默认值见 6.3 节:.component(ManaData.class, new ManaData(50, 50))

    @Override
    public void onInitialize() {
        ChasmRegistrar.scan(this.getClass());   // ★ 扫描本类全部 @Register / @DataComponent
        Chasm.itemLoader().loadAll();           // 可选:JSON 软编码物品
    }

    public record ManaData(int current, int max) {
        public static final ManaData EMPTY = new ManaData(0, 0);
    }
}

注意:上面 .component(...) 一行仅示意占位——给 Record 组件绑默认值请用 .component(ManaData.class, new ManaData(50, 50))(延迟解析重载),不要传 null。 完整可运行写法见第 4 章示例。

2.2 需要什么

  • 注册表冻结规则ChasmRegistrar.scan 必须在 onInitialize(或更早静态初始化)内执行——原版注册表在 onInitialize 结束后冻结。
  • 客户端/服务端:声明代码(物品/数据/特质/按键/伤害类型…)是共享安全的,不要触碰客户端类;客户端专属初始化放在 ClientModInitializer
  • DataGen:接入 ExampleDataGen 同样写法,入口类实现 DataGeneratorEntrypoint 并调用 ChasmDataGen.generate(generator, MyMod.class)

3. 核心心智模型与代码地图

3.1 一句话心智模型

声明(@ChasmMod/@Register/@DataComponent)→ 行为(Builder)→ 数据(Codec)→ 注册(自动)→ 暴露(SPI 可扩展)→ 资源(DataGen 自动生成)

3.2 门面入口(api.chasm.Chasm,全 static)

入口 返回 说明
Chasm.item() ItemBuilder 声明物品
Chasm.block() BlockBuilder 声明方块
Chasm.recipe(String id) RecipeBuilder 声明合成配方(DataGen 出 json)
Chasm.gui(modId, name) ChasmGuiBuilder 声明式界面
Chasm.keys() ChasmKeys 自定义按键注册表
Chasm.traits() ChasmTraits 行为特质注册表(use/attack/inventoryTick)
Chasm.data() ChasmData 数据组件类型安全读写
Chasm.playerVar(modId, name, codec) PlayerVar.Builder 玩家持久化变量
Chasm.damageTypes() ChasmDamageTypes 伤害类型注册表
Chasm.attributes() ChasmAttributes 属性注册表
Chasm.types() ChasmTypes 物品类型注册表
Chasm.enchantments() ChasmEnchantments 自定义附魔注册表
Chasm.itemLoader() / Chasm.guiLoader() 加载器单例 JSON 软编码加载
Chasm.mod(modId) / Chasm.mods() ModContext / 集合 按 modId 隔离的上下文(SPI 扩展点)

3.3 代码地图(chasm-core)

内容
api.chasm 门面 Chasm、注解 @ChasmMod、core 入口 ChasmInit
registry ChasmRegistrar(注解扫描)、ChasmRegistration(极简注册)、@Register
context ChasmContextRegistry(mod 上下文多例)、ModContext(聚合根)
item ItemBuilderChasmItemBehavior(行为枢纽)、6 个物品子类、ItemType/ChasmTypesChasmItemControllerChasmKeyBinding(按键句柄)
item/context 行为回调上下文:UseContext/AttackContext/InventoryTickContext/KeyContext(★ 已从 item/key 抽出,专用于打破包环)
trait ChasmTraits 注册表 + UseTrait/AttackTrait/InventoryTickTrait/ItemTraitEvent
data ChasmDataChasmCodec(record 自动 Codec)、ChasmCodecs@DataComponent
block ChasmBlockBlockBuilderChasmBlockControllerLootBuilder/LootDeclarationBlockUseContext
recipe RecipeBuilder/RecipeDeclaration
damage ChasmDamageTypesChasmDamageTypeBuilderDamageTypeInfoDamageSourcesResolverDamageContext
attribute ChasmAttributesAttributeInfo
enchantment ChasmEnchantmentsEnchantmentDeclarationEnchantmentConfig
gui(+gui/client ChasmGuiBuilder/ChasmGui/ChasmMenu/ChasmGuiChannel/ChasmGuiRegistry/ChasmGuiActions;客户端 ChasmGuiClient/ChasmScreen
key(+key/client ChasmKeysChasmKeyChannelKeyPressC2SPayload;客户端 ChasmKeyClient
player PlayerVar
loader ChasmItemLoader/ChasmGuiLoader/ChasmResources(JSON 软编码)
log ChasmLogger/ChasmFileLogger/AsyncLogWriter
net RateLimiter(服务端网络限流,GUI/按键通道共用)
datagen ChasmDataGen(7 个 Provider + 覆写机制)

3.4 生命周期

  • 运行时ChasmRegistrar.scan(class)@Register 字段 → 按类型路由注册进原版注册表(BuiltInRegistries.ITEM/BLOCK/MENU/DATA_COMPONENT_TYPE/ATTRIBUTE…)→ 暴露到 ModContext
  • DataGen 期ChasmDataGen.generate 内部调用 scan(modClass, false, false) 只收集声明不注册(注册表已冻结),随后 7 个 Provider 根据各 ModContext 输出 JSON 到 src/main/generated

4. 物品 Item

4.1 ItemBuilder 完整方法表

创建:Chasm.item()register()构建物品实例(注册交给 @Register 扫描),返回 Item(实际为绑定的类型子类)。

方法 语义
type(ItemType) 绑定物品类型(见第 5 章);null = 普通物品
tier(Tier) 指定原版 Tier(仅工具类类型生效;缺省用类型内置默认铁级)
maxStackSize(int) 堆叠上限,默认 64
durability(int) 耐久,默认无限
attackDamage(float total) 攻击伤害。自动写主手修饰符 = total − BASE(BASE = 原版 ATTACK_DAMAGE 默认值,1.21.1 为 2.0)。total == BASE 时不加修饰符。例:attackDamage(10) → 修饰符 +8
attackSpeed(float total) 总攻击速度,修饰符 = total − 4.0。例:0.5 → −3.5
armor/armorToughness/movementSpeed/knockbackResistance(float) 便捷属性(见第 11 章槽位组语义)
attribute(Attribute, amount, slot) 等 3 个重载 任意属性修饰符(自动 id chasm:item_<attr>_<n>ADD_VALUE
name(String) 显示名(DataGen 语言文件)
texture(String) 贴图路径(DataGen 模型),如 minecraft:item/diamond_sword
onRightClick(Consumer<UseContext>) 右键行为(可多个,按声明顺序执行)
onAttack(Consumer<AttackContext>) 攻击行为(可多个)
component(DataComponentType<T>, T) 默认数据组件(写进 Item.Properties
component(Class<T> recordClass, T value) 延迟绑定 record 组件默认值(解决静态初始化时序,运行时 getDefaultInstance 才解析)
useTrait(id) / useTrait(modId, name) 绑定 USE 特质(见第 7 章)
attackTrait(...) 绑定 ATTACK 特质
inventoryTrait(...) 绑定 INVENTORY_TICK 特质(持续效果)
onKeyPress(ChasmKeyBinding, Consumer<KeyContext>) / onKeyPress(ResourceLocation, ...) 绑定自定义按键(见第 15 章)
enchant(Holder/ResourceKey/EnchantmentDeclaration, level) 物品自带附魔(写 ENCHANTMENTS 组件;注册键运行时解析)
enchantable(key/decl, minLevel, maxLevel, weight[, treasureOnly]) 把附魔加进本物品所绑类型的附魔池(必须先 .type(...)
register() 构建并返回 Item

4.2 属性换算与"覆盖而非累加"

  • register() 会把「类型默认属性模板 + 物品自身声明」合并,同 (属性+槽位+运算) 时物品覆盖类型默认(丢弃类型项),再统一写入 DataComponents.ATTRIBUTE_MODIFIERS。因此工具提示、整合包、附魔/重铸系统都能读到真实属性。
  • 攻击伤害面板 = 原版基础 2.0 + 修饰符;ChasmSwordItem 等子类还暴露 getAttackDamage() 供特质计算差额。

4.3 六个内置物品类(都委托共享的 ChasmItemBehavior

原版父类 用途
ChasmItem Item 普通物品(NONE 类型)
ChasmSwordItem SwordItem 横扫 / 剑类附魔池
ChasmPickaxeItem PickaxeItem 挖掘等级
ChasmAxeItem AxeItem 剥皮(useOn 原版)
ChasmShovelItem ShovelItem 铺路(useOn 原版)
ChasmHoeItem HoeItem 耕地(useOn 原版)

五个工具/剑子类都完整覆写并委托:usehurtEnemyinventoryTickgetDefaultInstanceappendHoverText右键/物品栏/攻击特质与回调在工具物品上都有效。

⚠️ 真实边界(务必阅读):工具/剑子类刻意不覆写 useOn,以保留剥皮/铺路/耕地等原版右键行为。因此右键指向一个该工具可作用的方块(如斧→原木)时,原版 useOn 会返回成功并短路 use()——绑定的 useTrait/onRightClick 不会触发;右键空中或不可作用方块才进入 use()。需要"点击方块也触发玩法"时请改用方块事件(第 8 章)或特质只做服务端结算。

4.4 行为上下文(api.chasm.item.context,回调参数)

UseContext(右键/use):level()/player()/hand()/stack()sendMessage(String)(仅服务端)、serverOnly(Runnable)clientOnly(Runnable)swingArm()consumeItem()/consumeItem(int)damageItem(int)(返回是否仍可用)。

AttackContext(攻击/hurtEnemy):stack()/target()/attacker()/level()/isServer()serverOnlysendMessage(仅服务端且攻击者为玩家)、damageItem(int)

InventoryTickContext(物品栏 tick):level()/player()/stack()/slotId()/selected()isServer()sendMessageserverOnlyclientOnly

KeyContext(record):(Level, Player, ItemStack, ResourceLocation keyId),服务端主线程执行。

惯例:数值结算(扣法力、伤害、改存档)一律放 serverOnly;客户端回调只做表现。

4.5 完整示例

// 字段声明顺序:数据组件/特质/附魔等要先于引用它们的物品
@DataComponent("mana")
public static final ManaData MANA = ManaData.EMPTY;             // new ManaData(50,50)

public static final ItemType WAND = Chasm.types()
    .register("mymod", "wand", ctx -> new ChasmItem(ctx.behavior(), ctx.properties()))
    .tag("mymod:magic").build();

@Register("arcane_wand")
public static final Item ARCANE_WAND = Chasm.item()
    .type(WAND)
    .maxStackSize(1).durability(300)
    .name("Arcane Wand").texture("minecraft:item/blaze_rod")
    .component(ManaData.class, new ManaData(50, 50))           // 延迟绑定默认组件
    .useTrait("mymod", "mana_use")                             // 绑定特质
    .onKeyPress(MAGIC_KEY, ctx -> ctx.player().sendSystemMessage(Component.literal("按下自定义键!")))
    .register();

5. 物品类型系统 ItemType

类型 ≠ 继承哪个类,而是一份可复用模板:原版类映射工厂 + 默认属性 + 自动标签 + 专属附魔池。

5.1 内置类型(ChasmTypes 静态字段)

常量 id 实例化类 默认标签 默认属性(主手)
NONE chasm:none ChasmItem
SWORD chasm:sword ChasmSwordItem c:swords, minecraft:swords 攻 +1.0,攻速 −2.4
PICKAXE chasm:pickaxe ChasmPickaxeItem c:pickaxes, minecraft:pickaxes 攻 +1.0,攻速 −2.8
AXE chasm:axe ChasmAxeItem c:axes, minecraft:axes 攻 +5.0,攻速 −3.0
SHOVEL chasm:shovel ChasmShovelItem c:shovels, minecraft:shovels 攻 +1.5,攻速 −3.0
HOE chasm:hoe ChasmHoeItem c:hoes, minecraft:hoes 攻 +0.0,攻速 −3.0

内置默认 Tier:ChasmSwordTier/ChasmToolTier(耐久/速度 ≈ 铁级、附魔等级 15、铁锭修复、攻击加成 0——伤害全交给属性修饰符)。物品可用 .tier(Tiers.DIAMOND) 覆盖。

5.2 注册自定义类型

// 工厂决定原版类映射:可用内置类、自定义子类、或 ChasmItem 直接包装
Chasm.types().register("mymod", "staff",
        ctx -> new ChasmItem(ctx.behavior(), ctx.properties()))
    .tag("mymod:magic").tag("chasm:staffs")                  // 类型自动标签
    .defaultAttribute(Attributes.ATTACK_DAMAGE.value(), 1.0f) // 默认属性模板
    .enchantment(MANA_VAMPIRE, 1, 3, 10)                     // 专属附魔池(附魔台可刷)
    .build();                                                 // build 即登记进 ChasmTypes

ItemType.Builder 方法:defaultAttribute(a, amount[, slot])(完整重载支持自定义 modifierId+operation,同 id 覆盖)、tag/tags(...)enchantment(decl|key, min, max, weight[, treasureOnly])(treasureOnly=true 只进战利品不进附魔台)、build()

查询:Chasm.types().get(id)OptionalgetOrThrowall()get("sword") 自动补 chasm: 前缀。类型 id 形如 mymod:staff,绑定 .type(WAND) 的普通物品亦可 @Register("wand_item") 复用。


6. 数据组件 Data Component

数据组件(1.21 Data Component)用于给"每个物品栈"挂类型安全的附加数据,自动序列化/同步/存档。

6.1 声明方式(三种等价)

  1. @DataComponent("mana") record 字段(最常用,推荐):
@DataComponent("mana")                                  // id 相对 modId → mymod:mana
public static final ManaData MANA = ManaData.EMPTY;     // 字段值通常是默认实例

public record ManaData(int current, int max) {
    public static final ManaData EMPTY = new ManaData(50, 50);
}

扫描器(ChasmRegistrar.scan)遇到 @DataComponent 字段:ChasmCodec.codecFor(ManaData.class) 自动生成 Codec → ChasmData.register(modId, "mana", ManaData.class, codec) → 组件类型注册进原版 DATA_COMPONENT_TYPE(id mymod:mana),并按类建索引。

  1. 纯 Codec 组件(标量,无需 record 类索引):
public static final DataComponentType<Integer> SOULS =
    ChasmData.register("mymod", "souls", ChasmCodecs.INT);
// 物品里 .component(SOULS, 100)
  1. record 自带 CODEC(完全自定义编解码时):record 内放 static final Codec<T> CODEC 或静态 codec() 方法,ChasmCodec.codecFor 优先使用。

6.2 ChasmCodec 自动编解码规则

  • 仅接受 record 类型(非 record 抛异常)。
  • 支持字段类型:基本类型、String、枚举(按 name())、嵌套 record(递归)。
  • 编码为「字段名→值」映射;解码反射调用规范构造器。
  • 递归深度上限 64(防止恶意深度嵌套导致 StackOverflowError,超限抛异常/返回 error)。
  • 需要自定义时给 record 提供静态 CODEC 字段或 codec() 方法即可。

6.3 类型安全读写(Chasm.data()

ManaData m = Chasm.data().get(stack, ManaData.class);                       // 无则 null
ManaData m2 = Chasm.data().getOrDefault(stack, ManaData.class, ManaData.EMPTY);
Chasm.data().set(stack, ManaData.class, new ManaData(5, 10));
DataComponentType<ManaData> t = Chasm.data().componentType(ManaData.class); // 未注册抛异常

类索引 BY_CLASS 只对 register(modId, id, Class, Codec) 重载建立;纯 Codec 注册(重载 2)读不出类访问器。

6.4 内部组件

框架自己注册了 3 个 chasm 命名空间组件:USE_TRAIT_ID / ATTACK_TRAIT_ID / INVENTORY_TICK_TRAIT_ID(存 ResourceLocation 特质 id),不要占用 chasm: 前缀


7. 行为特质 Trait

解决什么:高频右键/攻击场景用全局注册的特质替代 List<Consumer> 遍历——物品栈只存一个 ResourceLocation 特质 id,运行时从 ChasmTraits O(1) 查回执行。

7.1 注册特质

// 右键使用特质(ctx 是 UseContext)
public static final ResourceLocation MANA_USE =
    Chasm.traits().registerUse("mymod", "mana_use", ctx -> {
        if (ctx.player() == null) return InteractionResult.PASS;
        ctx.swingArm();                       // 双侧播放动画
        final InteractionResult[] r = { InteractionResult.PASS };
        ctx.serverOnly(() -> {                // 数值结算只在服务端
            PlayerMana.tryConsume(ctx.player(), 5);
            r[0] = InteractionResult.SUCCESS;
        });
        return r[0];
    });

// 攻击特质(ctx 是 AttackContext)
Chasm.traits().registerAttack("mymod", "mana_attack", ctx -> { ... });

// 物品栏 tick 特质(ctx 是 InventoryTickContext,仅 Player 持有者触发)
Chasm.traits().registerInventoryTick("mymod", "crystal_tick", ctx -> { ... });

7.2 绑定到物品 / 触发顺序

  • 绑定:.useTrait(id) / .attackTrait(id) / .inventoryTrait(id)register() 时写入对应内部数据组件)。
  • 触发(见 ChasmItemBehavior):特质优先,回调兜底
    • handleUse:特质返回 SUCCESS/CONSUME/FAIL/PASS → 分别映射 success/consume/fail/pass 结果;特质异常/未注册 → 记 error 并回退回调列表。
    • handleAttack:特质返回 SUCCESS|CONSUME → 返回 true 短路 super.hurtEnemy(不再执行原版命中副作用/耐久损耗)。
    • handleInventoryTick:仅当实体是 Player 才触发。

7.3 查询与预留

  • ChasmTraits.INSTANCE.get(ItemTraitEvent.USE, id) 等(返回特质或 null);注册返回 modId:name 的 id。
  • ItemTraitEvent 预留 ENTITY_INTERACT / BLOCK_INTERACT / FINISH_USING / CUSTOM_ACTION(注册表骨架已通用支持,但绑定方法/物品覆写尚未接线——目前只能用已上线的三类)。

8. 方块 Block

8.1 BlockBuilder 方法表

创建 Chasm.block()register() 返回 ChasmBlock只 new 不注册,注册由 @Register 字段+扫描完成,BlockItem 自动生成同 id)。

方法 语义
strength(destroy, explosion) 硬度/爆炸抗性(3,3 ≈ 石头)
requiresPickaxe()/requiresAxe()/requiresShovel() 需要对应工具(写入 mineable 标签)
requiresTool(String tag) 任意挖掘标签(如 mymod:mineable/magic
sound(SoundType) 声音类型
name/texture 显示名/贴图(DataGen 生成语言/模型)
dropsSelf() 掉落自身(默认)
drops(item, count) / drops(item) / dropsRandom(item, min, max) 简单掉落
loot(Consumer<LootBuilder>) 多工具多样掉落(与 requires* 互斥)
onUse/onPlace/onBreak/onStep(Consumer<BlockUseContext>) 四类事件(可叠加多个)
register() 返回 ChasmBlock 实例

requiresTool 与 loot(…) 互斥:前者是"需正确工具才掉落",后者管理多工具条件掉落;不要同时声明。

8.2 多工具掉落(LootBuilder)

Chasm.block()
    .strength(3.0f, 3.0f)
    .name("Mana Crystal").texture("minecraft:block/amethyst_block")
    .loot(l -> l
        .onTool(Items.DIAMOND_PICKAXE, r -> r.dropsSelf())
        .onToolTag("minecraft:mineable/pickaxe", r -> r.dropsRandom(Items.AMETHYST_SHARD, 1, 3))
        .onTool(Items.GOLDEN_HOE, r -> r.chance(0.5f).dropsSelf())
        .otherwise(r -> r.nothing()))
    .onUse(ctx -> ctx.sendMessage("The crystal hums!"))
    .register();

掉落规则类型:SELF(自身)/ ITEM(固定数量)/ ITEM_RANDOM(随机区间)/ NOTHING;可带 chance 概率。DataGen 的 LootProvider 据此生成 loot table。

8.3 ChasmBlock 事件与原版方法映射

原版覆写 事件
useWithoutItem(空手右键) use 回调(恒返回 sidedSuccess)
setPlacedBy place 回调
playerWillDestroy break 回调
stepOn step 回调

上下文 BlockUseContextlevel()/pos()/player()/state()/hit()/entity()(entity 回退到 player)、swingArm()sendMessage(String)(仅服务端)。player() 在踩踏等事件可为 null;hit() 仅右键事件有值。


9. 合成配方 Recipe

Chasm.recipe("mana_sword")                       // id 不含命名空间
    .shaped(" D ", " D ", " S ",                 // 图案(三行便捷重载)
        'D', Items.DIAMOND, 'S', Items.STICK)    // (字符, 材料) 成对,材料须 Item/Ingredient
    .result(MANA_SWORD)                          // Item 或 ItemStack
    .register();                                 // void:只写当前 mod 配方空间
  • 其他重载:shaped(List<String>, Object...)shaped(String[], Object...)define(char, Object);材料只接受 Item 或 Ingredient。
  • register() 不注册原版配方,只记录到 ModContext,由 DataGen 的 RecipeProvider 生成 data/<ns>/recipe/*.json(解锁条件自动取第一个材料)。必须在 scan 之后 / onInitialize 中调用(需要当前 mod 上下文)。
  • 产物分类当前固定 RecipeCategory.COMBAT。

10. 伤害类型与伤害计算

10.1 声明自定义伤害类型

public static final DamageTypeInfo ARCANE_BURN = Chasm.damageTypes()
    .register("mymod", "arcane_burn", DamageTypeKind.MAGIC)   // kind=来源类别
    .message("was consumed by arcane fire")                   // 死亡消息(需真实 DamageType 才生效)
    .bypassesArmor(true)
    .tag("magic").tag("fire")                                 // 聚合标签(查询用)
    .build();                                                 // 写入 ChasmDamageTypes 内存注册表

DamageTypeKind:PLAYER_ATTACK / MOB_ATTACK / MAGIC / FIRE / LIGHTNING / INDIRECT_MAGIC。内置模板 ChasmDamageTypes.PHYSICALChasmDamageTypes.MAGIC

10.2 生效机制(务必阅读)

  • build() 只写内存注册表(ChasmDamageTypes.INSTANCE),不会自动产生原版 DamageType;当前 DataGen 也不输出 damage_type JSON。
  • DamageSourcesResolver.resolve(sourceEntity, info)
    1. 优先真实注册类型:若 data/<ns>/damage_type/<path>.json 已随数据包加载(动态注册表存在该 Holder),返回 new DamageSource(registered, source)——此时 message()/bypassesArmor()/exhaustion() 由原版承担、全部生效;
    2. 否则回退按 kind 调原版便捷源(playerAttack/mobAttack/indirectMagic/onFire/lightningBolt/generic)——自定义 message/bypass/exhaustion 不生效,但护甲/魔抗/附魔结算正常。
  • 结论:想让自定义死亡消息等生效,需自行把 DamageType JSON 放进模组资源 data/<ns>/damage_type/<name>.json(Resolve 会自动优先使用)。tag() 仅用于 hasTag/聚合查询,不是原版 damage_type 标签。

10.3 DamageContext(伤害计算器)

float dealt = new DamageContext(ARCANE_BURN)
    .base(8.0f)                    // 基础伤害
    .multiplier(1.0f)              // 倍率
    .critChance(0.3f, 2.0f)        // 30% 概率 ×2
    .onApply(() -> { /* 音效/粒子等副作用 */ })
    .apply(player, target, level.getRandom());  // 返回名义伤害(护甲等换算后的实际值由原版结算)

查询:expected()(base×multiplier)、calculate(random)resolveSource(attacker)(只解析不施伤)、type()


11. 属性 Attribute

11.1 内置投影常量(ChasmAttributes)

ATTACK_DAMAGE(默认值≈2.0)、ATTACK_SPEED(4.0)、ARMOR(0)、ARMOR_TOUGHNESS(0)、MOVEMENT_SPEED(0.1)、KNOCKBACK_RESISTANCE(0)。每个 AttributeInfo 持有真实原版 Attribute 引用,可用于 Entity.getAttribute。

11.2 注册自定义属性(真实写进原版注册表)

AttributeInfo spellPower = Chasm.attributes()
    .registerRanged("mymod", "spell_power", 5.0f, 0.0f, 100.0f);
// 需要注册期钩子(如挂实体属性)用 registerHook(modId, name, def, min, max, consumer)

查询:get(ResourceLocation) → Optional;get(name)(缺省命名空间 minecraft);getOrThrowsize()

物品侧使用:ItemBuilder 的 attribute(…)/便捷方法把修饰符写进 ATTRIBUTE_MODIFIERS 组件(面板/重铸系统可读的真实属性来源)。


12. 自定义附魔 Enchantment(数据驱动)

1.21.1 附魔是数据驱动动态注册表:必须存在 data/<ns>/enchantment/*.json 才会被加载。Chasm 用"声明 + DataGen 自动输出"闭环。

12.1 声明

// 静态字段声明(顺序先于引用它的类型/物品)
public static final EnchantmentDeclaration MANA_VAMPIRE =
    Chasm.enchantments().register("mymod", "mana_vampire")
        .weight(10).maxLevel(3).anvilCost(1)
        .minCost(5, 10).maxCost(15, 10)     // (base, perLevelAboveFirst)
        .slot("mainhand")                    // 可 slot/slots(...) 多组
        // .treasure()                       // 可选:宝藏附魔(仅战利品/自带)
        .build();                            // 登记声明并输出日志

12.2 让附魔生效(三条链路)

  1. DataGen 输出:自动生成 data/mymod/enchantment/mana_vampire.json(description/supported_items/weight/max_level/min_cost/max_cost/anvil_cost/slots)。
  2. 附魔台候选:把附魔加进某物品类型的附魔池——ItemType.Builder 的 .enchantment(decl, min, max, weight),或物品就地 .enchantable(...)(需先 .type(…))。DataGen 再聚合出 supported_items 物品标签(mymod:enchantable/mana_vampire)→ 原版附魔台天然可刷出。treasureOnly 成员不进标签。
  3. 物品自带.enchant(MANA_VAMPIRE, 1)(运行时注册表冻结后解析 Holder 写入 ENCHANTMENTS 组件)。

运行时解析附魔等级:Chasm.enchantments().holderFor(key) → Optional<Holder.Reference>(服务端启动后可用)。

已知缺口:EnchantmentDeclaration 输出的 description 引用翻译键 enchantment.<ns>.<name>,但 DataGen 的语言 Provider 不生成该键——游戏内附魔名会显示为原始键。请在语言文件自行补充,例如 "enchantment.mymod.mana_vampire": "魔力汲取"


13. 玩家持久化变量 PlayerVar

基于 Fabric DataAttachment:类型安全、随世界存档持久化、死亡重生保留、可选 min/max 自动钳制。所有读写只在服务端(ServerPlayer)

public static final PlayerVar<Integer> MANA =
    Chasm.playerVar("mymod", "mana", ChasmCodecs.INT)
        .defaultValue(50)     // 开局/未初始化值
        .min(0).max(100)      // 写入自动钳制(T 需 Comparable)
        .build();             // build 即注册(没有 register 方法)

API:get(客户端返回默认值并 WARN)、getOrSet(未初始化则写默认值)、setmodify(UnaryOperator)hasclientSafeGet(客户端读只读缓存、不打 WARN,HUD 用)、cacheReadOnly(仅供数据包同步链路手动刷缓存)、isServerOnly/isClientSafe

已知限制:clientSafeGet 的缓存只在服务端读写过的同一 JVM(单人/集成服)有意义;纯多人模式没有自动的客户端同步发送端——客户端 UI 实时显示数值需自行实现同步。


14. 声明式 GUI

14.1 声明(一个界面 = 一段链式代码)

public static final ChasmGui MAGIC_BOX = Chasm.gui("mymod", "magic_box")
    .title("魔法盒")
    .size(9, 3)                          // 列 [1,18] × 行 [1,6]
    .slot(0, 0, 2, 2)                    // 左上 2x2 存储区(槽索引 0..3,行主序)
    .button("传送", 5, 0, (player, click) -> player.teleportTo(
        player.getX(), player.getY() + 10.0, player.getZ()))   // 回调在服务端主线程
    .buttonCooldown(20)                  // 冷却 tick(作用于下一个按钮)
    .button("治疗", 7, 0, (p, c) -> p.heal(10.0f))
    .onOpen(ctx -> {                     // 打开即预填(服务端)
        ctx.setItem(0, Items.EMERALD, 5);
        ctx.player().sendSystemMessage(Component.literal("已打开"));
    })
    .onClose(() -> {})
    .register();                         // 返回 ChasmGui;MenuType 注册进原版 MENU

打开:player.openMenu(MAGIC_BOX.provider())(或 Chasm.gui("mymod","magic_box").provider(),未注册会自动 register)。

14.2 要点

  • 网格单元:未声明任何单元时整网格默认全是存储槽;显式声明过的单元按行主序获得连续索引。
  • 按钮是"虚拟按钮"(不占容器槽):客户端命中 → 发 ChasmButtonClickC2SPayload → 服务端校验后主线程回调。
  • 服务端校验链(ChasmGuiChannel):界面存在 → 玩家确实打开着该界面 → 按钮索引与 label 一致 → 两级限流(每按钮 250ms + 每玩家全局 50ms,RateLimiter)→ 回调;任一不过静默忽略。防刷已内置。
  • ChasmMenu.stillValid:return player == null || player.isAlive()——客户端副本恒 true;服务端玩家死亡即失效;不校验距离/维度(轻量容器设计)。
  • 客户端屏幕自动绑定(ChasmGuiClient 在 client 入口遍历注册表 MenuScreens.register)。若在客户端初始化后才注册 GUI,则该界面无屏幕——尽量在 main 入口注册。
  • 背景贴图:.background(ResourceLocation),32×32 九宫格 8px 边框;缺省灰色面板。
  • 命名动作按钮:ChasmGuiActions.register(modId, name, handler) 注册可复用动作(ConcurrentHashMap、同名覆盖),JSON 界面经 buttonAction 引用。

15. 自定义按键 Custom Key

把交互从左右键扩展到任意键(默认如 O=79、L=76 的 GLFW 码)。

15.1 声明 + 绑定

// 静态声明(共享/服务端安全;请直接传键码字面量,避免在服务端加载 GLFW 类)
public static final ChasmKeyBinding MAGIC_KEY =
    Chasm.keys().register("mymod", "magic_blast", 79, "Magic Blast");

@Register("wand")
public static final Item WAND = Chasm.item()
    .onKeyPress(MAGIC_KEY, ctx -> ctx.player().sendSystemMessage(
        Component.literal("魔法弹射出!(服务端)")))
    .register();

15.2 机制与安全

  • 声明侧(ChasmKeys,api.chasm.key):只记录 id/键码/显示名;句柄 ChasmKeyBinding 放在 api.chasm.item 包(不引用客户端类,服务端可安全链接)。
  • 客户端(ChasmKeyClient,api.chasm.key.client):为每个声明创建原版 KeyMapping(分类 key.category.chasm,玩家可改键),在 END_CLIENT_TICK 用 consumeClick() 做上升沿检测发包(每帧只在下按瞬间发一次)。
  • 服务端(ChasmKeyChannel)校验链:物品非 AIR → 玩家确实在该手持有该物品 → 物品是 ChasmItemSupport 且绑定过该按键 handler → 每玩家×每按键 250ms 限流(RateLimiter)→ server.execute 主线程回调,异常记日志。
  • 显示名翻译:DataGen 自动生成 key.chasm.<modId>.<name> 与分类 key.category.chasm

16. JSON 软编码(物品 / GUI)

机制:把 data/<ns>/chasm/items/*.jsondata/<ns>/chasm/gui/*.json 放在模组资源里,运行时 Chasm.itemLoader().loadAll() / Chasm.guiLoader().loadAll()(onInitialize 中)即自动构建并注册——可以不写 Java 代码加物品/界面。内部由 ChasmResources 扫描 classpath(目录与 jar 均支持)。

16.1 物品 JSON schema(chasm/items/*.json)

字段 类型 必填 默认 说明
id string 注册 id(namespace:path)
type string 普通物品 类型 id:chasm:sword/pickaxe/axe/none…(未命中快捷分支仅 sword/none/pickaxe/axe;shovel/hoe 走注册表查询,注册表存在则命中)
tier string 类型默认 minecraft:diamond 等(Tiers.valueOf,注意大写解析)
attack_damage number 1.0 总攻击伤害
attack_speed number 总攻速(内部 −4.0)
max_stack / durability int 64 / 无限 堆叠/耐久
name / texture string 显示名 / 贴图
traits object { "use": "mymod:id", "attack": "mymod:id", "inventory": "mymod:id" }
enchant array [{ "id": "minecraft:fire_aspect", "level": 2 }](level 缺省 1)
components object 组件 id → 值(按已注册 DATA_COMPONENT_TYPE 用 Codec 从 Gson 解码)
{
  "id": "mymod:flame_sword",
  "type": "chasm:sword",
  "tier": "minecraft:diamond",
  "attack_damage": 12.0,
  "attack_speed": 1.6,
  "name": "Flame Sword",
  "texture": "minecraft:item/diamond_sword",
  "max_stack": 1,
  "durability": 1200,
  "traits": { "attack": "mymod:mana_attack" },
  "enchant": [ { "id": "minecraft:fire_aspect", "level": 2 } ]
}

行为:运行时真实注册进 BuiltInRegistries.ITEM(重复 id 跳过并 warn);DataGen 期只收集声明(注册表冻结);单文件失败不影响其他文件;幂等。

16.2 GUI JSON schema(chasm/gui/*.json)

字段 默认 说明
id 必填 namespace:path(MenuType 只能注册一次,重复跳过)
title / cols / rows / background — / 9 / 1 / — 标题/网格/背景
slots [{ col, row, width, height }](width/height 缺省 1)
buttons [{ label, col, row, action, cooldown }];须有 action 或 label(都无则跳过);action 驱动经 ChasmGuiActions 反查(label 缺省用 action 的 path);纯文字按钮为空 handler
{
  "id": "mymod:simple_box",
  "title": "简单宝盒",
  "cols": 9, "rows": 3,
  "slots": [ { "col": 0, "row": 0, "width": 2, "height": 2 } ],
  "buttons": [ { "label": "传送", "col": 5, "row": 0, "action": "mymod:teleport", "cooldown": 20 } ]
}

注意:动作须先 ChasmGuiActions.register("mymod","teleport", handler) 再 loadAll;GUI 在 DataGen 期不加载(MenuType 注册表已冻结)。


17. 日志系统

ChasmLogger:按 modId 隔离的 SLF4J 增强包装——每行自动带 [modId] 前缀 + 结构化记录 + 异步会话文件落盘<游戏目录>/chasm-logs/<时间戳>/session.log),文件 IO 全部吞异常,绝不影响游戏主流程。

方法 输出形态
info/warn/error/debug(modId, fmt, args...) [INFO] [mymod] ...(debug 需开调试模式)
call(modId, cls, method, detail, args...) [mymod] CALL X.y: ...
injection(modId, targetCls, targetMethod, mixin) [mymod] INJECT ... <- ...
event(modId, cls, method, event) [mymod] EVENT X.y z
setDebugMode(true) 开 DEBUG 输出
flushAndClose() 显式 flush(JVM 关闭钩子已自动做)

底层:ChasmFileLogger(会话目录)+ AsyncLogWriter(守护线程 + ConcurrentLinkedQueue,close 排空)。日志行未做换行清洗,请勿把玩家可写文本未经处理直接进日志(避免日志注入/伪造行)。


18. DataGen 自动化

角色:所有"声明"都会自动产出资源 JSON,消灭手写:

Provider 产出
ChasmModelProvider 物品/方块模型(texture 声明;含 sword/pickaxe/axe/shovel/hoe 用手持模板)
ChasmLanguageProvider en_us 语言(item/block name;key.category.chasm 与按键翻译;不含附魔 description
ChasmRecipeProvider 配方 json(配方声明)
ChasmLootProvider 方块掉落 loot table(掉落声明)
ChasmTagProvider 方块挖掘标签(requiresTool)
ChasmEnchantmentProvider 附魔 json(声明)
ChasmEnchantableTagProvider 每附魔 supported_items 物品标签(类型附魔池聚合,treasureOnly 跳过)

接入:入口类实现 DataGeneratorEntrypointonInitializeDataGeneratorChasmDataGen.generate(generator, MyMod.class)chasm-examplebuild 已 dependsOn runDatagen(编译前自动再生成)。输出目录 src/main/generated(已纳入资源集)。

JSON 覆写(第十二步):ChasmDataGen.setOverrides(map -> map.put("mymod/enchantment/mana_vampire.json", json))overrideFile(path, json),可整体替换某个生成文件(目前附魔路径已接入)。


19. 跨模组扩展(SPI)

Chasm 的"每个声明都暴露"设计使任意模组(含闭源)都能被扩展——只要它用 Chasm 声明过:

// 1) 拿到目标模组的隔离上下文
ModContext other = Chasm.mod("targetmod");          // 不存在则按需创建,恒非 null

// 2) 物品控制台:追加/覆写右键行为
ChasmItemController ctrl = other.item("mana_sword"); // null = 未注册
if (ctrl != null) {
    ctrl.appendRightClick(ctx -> { /* 追加行为(不覆盖) */ });
    // ctrl.replaceRightClick(...)  // 覆写全部
}

// 3) 方块控制台
ChasmBlockController bc = other.block("mana_crystal");
if (bc != null) bc.appendUse(ctx -> { ... });

// 4) 全局聚合查询
for (ModContext ctx : Chasm.mods()) { ... }          // Chasm.mod 按 modId
Chasm.damageTypes().get("othermod", "arcane");       // 跨模组查伤害类型
Chasm.types().get("othermod", "staff");              // 查物品类型
Chasm.attributes().get("spell_power");               // 属性投影
Chasm.enchantments().holderFor(key);                 // 附魔 Holder(服务端启动后)

要点:ModContext 聚合了 items/blocks/recipes 与数据空间(data());append 系列保留原有行为;所有 SPI 修改建议在初始化期完成(行为列表为 ArrayList,运行期并发修改存在竞争)。


20. 测试

chasm-core 已内置 P0 纯 JVM 单元测试(JUnit 5 + fabric-loader-junit;chasm-core/build.gradle 已配置 test 任务并 useJUnitPlatform):

测试类 覆盖点
api.chasm.data.ChasmCodecTest record 自动 Codec:基本类型/枚举/嵌套 record 编解码往返、静态 CODEC 字段优先、非 record 拒绝、深度上限防 StackOverflowError
api.chasm.trait.ChasmTraitsTest USE/ATTACK/INVENTORY_TICK 三类注册与 O(1) 查询、事件类型隔离、未注册返回 null、重复注册覆盖
api.chasm.log.AsyncLogWriterTest 父目录创建、行落盘、close 排空、close 后 enqueue no-op、close 幂等
api.chasm.log.ChasmLoggerTest 调试模式开关、按 modId Logger 缓存、结构化方法不抛异常、flushAndClose 幂等

运行:./gradlew :chasm-core:test

无需启动游戏(fabric-loader-junit 提供最小 loader 环境)。建议继续补的高价值纯逻辑:ItemBuilder.register() 的属性合并去重与 attackDamage 换算、ChasmData 类索引读写、RecipeBuilder 参数校验、RateLimiter 冷却语义。


21. 已知限制与注意事项(当前代码核实 2026-09-02)

本清单逐条对照当前源码核实过;标注"尚未实现/仍存在"的项请勿当作框架缺陷误用。

  1. 工具物品右键方块边界:工具/剑保留原版 useOn 语义(剥皮/耕地/铺路),右键"可作用方块"时会短路 use()——此时 useTrait/onRightClick 不触发(见 4.3)。需要方块侧交互请用方块事件(第 8 章)。
  2. 自定义伤害类型不会自动注册为原版 DamageType(见 10.2):build() 只写内存注册表,DataGen 也不输出 damage_type JSON;自定义 message/bypass/exhaustion 需自行提供 data/<ns>/damage_type/*.json 才会被 Resolver 采用。
  3. 附魔 description 翻译键缺失(见 12.2):DataGen 不生成 enchantment.<ns>.<name> 语言键,需模组在语言文件补充(如 "enchantment.mymod.mana_vampire": "魔力汲取")。
  4. ChasmData 类索引 BY_CLASS 以 Class 为键:两个模组若声明同名同结构 record,后注册者会覆盖前者的类索引(get/set 会读错组件类型);组件注册表侧的 id 含 modId 前缀不受影响。多模组协作时建议 record 类名全局唯一。
  5. DataGen 期静态初始化仍会真实注册:@DataComponent/物品字段的类初始化(含静态 Codec 注册)会在 DataGen 的 scan 触发时执行,当前靠"组件注册表在 DataGen 期未冻结"侥幸通过。不要在 static 块里写 ITEM/MENU 等注册表,否则 DataGen 会崩。
  6. PlayerVar 纯多人客户端无自动同步(见第 13 章):clientSafeGet 的缓存只在服务端同 JVM 读写后有意义。
  7. GUI:ChasmMenu.stillValid 无距离校验(轻量容器);ChasmGuiRegistry 用 LinkedHashMap(仅初始化期读写是安全约定);客户端初始化之后才注册的 GUI 没有屏幕。
  8. 回调列表线程模型:ItemBuilder/BlockBuilder 的行为列表为 ArrayList,SPI 追加/覆写请放在初始化期;运行期并发修改存在竞争。
  9. 伤害语义澄清:handleAttack 返回 true 是短路 super.hurtEnemy(跳过原版命中副作用/耐久),物理伤害本身已由 Player.attack 结算。
  10. ChasmEnchantments javadoc 残留 EnchantmentMenuMixin 引用:框架零 Mixin,附魔台集成实为数据驱动标签——该注释属历史残留(无此类)。
  11. ItemType 默认 Tier 为铁级模板(耐久/速度≈铁、附魔等级 15、铁锭修复):需要更高挖掘等级请显式 .tier(Tiers.DIAMOND)。

22. 版本变更记录(2026-09 重构说明)

本 Wiki 相对 2026-08-15 旧版 CodeWiki(v0.1.0、24 文件时代)与早期审计结论的差异核实。模组近两周经历较大重构,以本文件为准

22.1 已落地的新能力/修复(当前代码确认)

位置 说明
P0 单元测试 chasm-core/src/test(4 文件)+ build.gradle JUnit5 此前 0 测试;现覆盖 ChasmCodec/ChasmTraits/AsyncLogWriter/ChasmLogger
包级解耦重构 item/context(Use/Attack/InventoryTick/KeyContext 迁入);ChasmKeyBinding 移至 api.chasm.item 打破 item↔trait、item↔key 包级循环依赖(依赖方向单向化:trait/key → item)
服务端网络限流器 api.chasm.net.RateLimiter GUI 与按键通道共用(有界冷却表 + TTL 清理)
按键通道防刷 ChasmKeyChannel 每玩家×每按键 250ms 冷却(修复安全审计 High:无服务端限流)
GUI 两级冷却 ChasmGuiChannel 每按钮 250ms + 每玩家全局 50ms(修复审计 Medium:按索引冷却可被轮换绕过)
Codec 深度上限 ChasmCodec MAX_CODEC_DEPTH=64 编/解码递归限深,防恶意深嵌套 StackOverflowError(修复审计 Medium)
日志器失败防递归 ChasmLogger.fileInitFailed 会话文件初始化失败后静默降级且不递归重试

22.2 早期审计结论的澄清/更正(勿引用旧说法)

  • 「工具/剑子类未覆写 use()/inventoryTick(),右键/物品栏特质静默失效」→ 证伪:五个子类全部覆写并委托 ChasmItemBehavior;真实边界仅为"右键可作用方块时 useOn 短路 use()"。
  • 「ChasmMenu.stillValid 恒真」→ 不准确:实际为 player==null || player.isAlive()(服务端存活校验,只是不校验距离)。
  • 「项目 0 测试、无测试基础设施」→ 已过时:现已有 P0 JUnit 5 测试。

22.3 尚未处理(见第 21 章)

伤害类型仅内存投影、附魔翻译键缺失、BY_CLASS 跨模组同名 record 覆盖、DataGen 静态初始化注册风险、PlayerVar 多人同步缺失。


23. 附录

23.1 关键类速查(按包)

  • 门面/注解:Chasm、ChasmMod、ChasmInit;registry(ChasmRegistrar、ChasmRegistration、Register)
  • 上下文:ChasmContextRegistry、ModContext
  • 物品:ItemBuilder、ChasmItem、ChasmSwordItem、ChasmPickaxeItem、ChasmAxeItem、ChasmShovelItem、ChasmHoeItem、ChasmItemBehavior、ChasmItemController、ChasmKeyBinding、AttributeDeclaration、ChasmTooltipUtil
  • 回调上下文:item/context(UseContext、AttackContext、InventoryTickContext、KeyContext)
  • 类型:ItemType(+Builder)、ChasmTypes(+6 工厂)、ChasmItemFactory、ChasmItemBuildContext、ChasmItemSupport
  • 特质:ChasmTraits、ItemTraitEvent、ItemTrait、UseTrait、AttackTrait、InventoryTickTrait
  • 数据:ChasmData、ChasmCodec、ChasmCodecs、DataComponent
  • 方块:ChasmBlock、BlockBuilder、ChasmBlockController、BlockUseContext、LootBuilder、LootDeclaration
  • 配方:RecipeBuilder、RecipeDeclaration
  • 伤害:ChasmDamageTypes、ChasmDamageTypeBuilder、DamageTypeInfo、DamageTypeKind、DamageSourcesResolver、DamageContext
  • 属性:ChasmAttributes、AttributeInfo
  • 附魔:ChasmEnchantments(+EnchantmentBuilder)、EnchantmentDeclaration、EnchantmentConfig
  • GUI:ChasmGuiBuilder、ChasmGui、ChasmMenu、ChasmButton、ChasmStorageSlot、ChasmGuiRegistry、ChasmGuiActions、ChasmGuiChannel、ChasmOpenContext、ChasmGuiClick、ChasmButtonHandler;client(ChasmGuiClient、ChasmScreen)
  • 按键:ChasmKeys、ChasmKeyChannel、KeyPressC2SPayload;client(ChasmKeyClient)
  • 玩家:PlayerVar(+Builder)
  • 加载:ChasmItemLoader、ChasmGuiLoader、ChasmResources
  • 日志:ChasmLogger、ChasmFileLogger、AsyncLogWriter
  • 网络工具:RateLimiter
  • DataGen:ChasmDataGen(7 个 Provider + setOverrides/overrideFile)

23.2 常用术语

术语 含义
@Register / @ChasmMod 声明注册标记;@Register 字段类型自动路由到对应原版注册表
@DataComponent record 数据组件声明(自动 Codec、自动注册、按类建索引)
ModContext / 控制台 按 modId 隔离的注册物视图;ChasmItemController / ChasmBlockController 是 SPI 扩展句柄
Trait 全局注册、O(1) 查回执行的行为单元(use / attack / inventoryTick)
ItemType 类型模板(原版类映射 + 默认属性 + 标签 + 附魔池),不等于继承关系
内置类型 id chasm:none / sword / pickaxe / axe / shovel / hoe
DataGen 收集模式 scan(class, false, false):只暴露声明不真实注册(注册表冻结期)
serverOnly 仅服务端执行的回调包装——数值结算(扣法力/伤害/存档)的唯一正确位置

23.3 一条完整链路(记忆锚点)

@ChasmMod(id=mymod) → 静态字段声明(@DataComponent 数据 / @Register 物品与方块 / 特质·类型·附魔·按键句柄) → onInitialize:ChasmRegistrar.scan + itemLoader/guiLoader 加载 JSON → 注册进原版注册表并暴露到 ModContext → 其他模组 Chasm.mod("mymod").item("xxx").append/… 做 SPI 扩展 → build 时 runDatagen 自动补模型/语言/配方/掉落/附魔 JSON。

Project description from CurseForge.

Pick your setup

Chasm api by Minecraft version and loader

Choose the version and loader you play, then open the matching release.

1 available setups

Check the dependencies, then try the file in a copied instance before changing a world you care about.

Recent files

Chasm api versions and loaders

1 of 1 releases match

Looking for an older file? The official CurseForge project page is in Resources.