NoteData
这一页是签名与行为参考。音符实例基类,注意「所有权边界」。直接做一遍:教程 · 添加新音符类型。
运行时音符基类(api 侧)。自定义类型在 deserialize / onCreateRuntime 中构造并维护它;游玩期宿主把它(或内置类型的只读适配器)交给判定与渲染回调。它不依赖引擎内部模型,模组只依赖 mod-api 即可实现自定义音符。
写语义按所有权分两类(契约,消除"写了却静默无效"):
- 自定义类型:回调拿到的是你在
deserialize里产出的自有子类实例;对它的写入只影响你自己的运行时状态,宿主不消费。宿主的判定/渲染/轨道定位读的是内核音符的time/lane(由谱面 JSON 决定)。 - 内置类型:宿主返回只读适配器。
setTime/setLane/setEndTime转发到内核音符、真实生效(同刻同轨的同组音符会随之移动);setJudged/setExtensionData是无操作(判定状态由判定引擎独占,内核音符无扩展数据槽);其isJudged()恒为false、extensionData()为null。
方法速览
| 方法 | 用途 |
|---|---|
time() / setTime(long) | 音符时间(毫秒) |
lane() / setLane(int) | 所在轨道(0-based) |
typeKey() | 音符类型 key(宿主填的内核类型字符串) |
endTime() / setEndTime(Long) | 长音符结束时间(非长音符为 null) |
isJudged() / setJudged(boolean) | 判定状态(自定义类型自管) |
extensionData() / setExtensionData(Object) | 运行时扩展数据(不参与序列化) |
time()
签名:
public abstract long time();行为:音符时间(毫秒,判定线时刻)。自定义类型即你在解析期写入值;内置适配器实时读内核音符(含运行期被 setTime 改写后的值)。
示例:
long t = note.time();lane()
签名:
public abstract int lane();行为:音符所在轨道(0-based)。与 time() 同源:自定义类型读自有字段,内置适配器读内核音符。
示例:
if (note.lane() == lane) { /* 同轨 */ }typeKey()
签名:
public abstract String typeKey();行为:音符类型 key,与 NoteTypeDefinition.serializationKey() 对应,由宿主填充(内置适配器返回内核音符的原始 type 字符串)。自定义实现通常直接返回 serializationKey()。
示例:
@Override
public String typeKey() {
return "stardust";
}endTime()
签名:
public abstract Long endTime();行为:长音符结束时间(毫秒);非长音符返回 null。注意长按语义的类型必须提供非空 endTime,否则宿主没有终点判定路径。
示例:
Long end = note.endTime();isJudged()
签名:
public abstract boolean isJudged();行为:音符是否已被判定。宿主管线不读写自定义类型实例的这个字段(判定状态在宿主内部队列里);内置适配器恒返回 false。若你需要该状态,请在自有子类中维护并在 onJudgeTick / onJudged 里自行更新。
示例:
@Override
public boolean isJudged() {
return judged;
}extensionData()
签名:
public abstract Object extensionData();行为:运行时扩展数据的读取端。自定义类型的值会在 render 中经 NoteRenderContext.extensionData()、在判定回调中经 NoteView.extensionData() 原样透传(同一实例);内置类型为 null。不参与序列化。
示例:
Object state = note.extensionData();setTime(long time)
签名:
public abstract void setTime(long time);行为:设置音符时间(毫秒)。约定在解析期(deserialize / onCreateRuntime)调用。自定义类型的运行期改写不进入宿主管线;内置适配器会转发到内核音符并真实生效。
示例:
note.setTime(json.get("time").getAsLong());setLane(int lane)
签名:
public abstract void setLane(int lane);行为:设置所在轨道(0-based),语义同 setTime:解析期写入;内置适配器转发内核音符并生效。
示例:
note.setLane(json.get("lane").getAsInt());setEndTime(Long endTime)
签名:
public abstract void setEndTime(Long endTime);行为:设置长音符结束时间;非长音符传 null。内置适配器转发内核音符并生效。
示例:
note.setEndTime(json.has("endTime") ? json.get("endTime").getAsLong() : null);setJudged(boolean judged)
签名:
public abstract void setJudged(boolean judged);行为:设置判定状态。仅对自定义类型有意义(宿主不消费);内置适配器为无操作,避免模组绕过判定引擎改分。
示例:
note.setJudged(true);setExtensionData(Object data)
签名:
public abstract void setExtensionData(Object data);行为:挂载运行时扩展数据(任意对象,不参与序列化)。自定义类型在解析期写入,判定/渲染期经只读透传取回;内置适配器为无操作(数据存不下来)。
示例:
note.setExtensionData(new AimState(angleRad));完整签名
public abstract class NoteData {
public abstract long time();
public abstract int lane();
public abstract String typeKey();
public abstract Long endTime();
public abstract boolean isJudged();
public abstract Object extensionData();
public abstract void setTime(long time);
public abstract void setLane(int lane);
public abstract void setEndTime(Long endTime);
public abstract void setJudged(boolean judged);
public abstract void setExtensionData(Object data);
}线程:源码未声明额外线程约束;实例在解析期写入,游玩期由更新/渲染线程读取。
生命周期阶段:解析期由模组构造并写入;游玩期(判定与渲染回调)读取。
稳定性:2.0 起冻结:2.x 内只增不破(禁止删签名/改签名/改语义)。