API 参考 / spi 包:音符与判定 SPI
最小自定义音符类型骨架
一个可编译的最小实现:自定义 NoteData 子类 + 定义对象(解析 / 判定等级钩子 / 渲染)。注册在 onPreInit(示例省略 Mod 外壳,完整模组骨架见 开发指南 3.3 节)。
java
import com.google.gson.JsonObject;
import com.seecmd.mod.api.render.RenderCanvas;
import com.seecmd.mod.api.spi.JudgeInput;
import com.seecmd.mod.api.spi.JudgeSink;
import com.seecmd.mod.api.spi.NoteData;
import com.seecmd.mod.api.spi.NoteParseContext;
import com.seecmd.mod.api.spi.NoteRenderContext;
import com.seecmd.mod.api.spi.NoteTypeDefinition;
import java.awt.Color;
public final class StardustNoteType implements NoteTypeDefinition {
@Override
public String displayName() {
return "星尘";
}
@Override
public String serializationKey() {
return "stardust";
}
@Override
public NoteData deserialize(JsonObject json, NoteParseContext ctx) {
StardustNote note = new StardustNote();
note.setTime(json.get("time").getAsLong());
note.setLane(json.get("lane").getAsInt());
if (json.has("endTime") && !json.get("endTime").isJsonNull()) {
note.setEndTime(json.get("endTime").getAsLong());
}
note.setTypeKey(serializationKey());
note.setExtensionData(Double.valueOf(ctx.contentScale()));
return note;
}
@Override
public void onJudge(JudgeInput input, JudgeSink sink) {
// 不产出等级 = 使用宿主内置判定等级;命中与否仍由宿主时间窗口决定
}
@Override
public void render(RenderCanvas canvas, NoteRenderContext ctx) {
double size = Math.min(ctx.width(), 48);
canvas.save();
canvas.setColor(new Color(160, 120, 255));
canvas.fillRect(ctx.x() - size / 2, ctx.y() - size / 2, size, size);
canvas.restore();
}
/** api 侧最小运行时音符。 */
static final class StardustNote extends NoteData {
private long time;
private int lane;
private String typeKey;
private Long endTime;
private boolean judged;
private Object extensionData;
@Override public long time() { return time; }
@Override public int lane() { return lane; }
@Override public String typeKey() { return typeKey; }
@Override public Long endTime() { return endTime; }
@Override public boolean isJudged() { return judged; }
@Override public Object extensionData() { return extensionData; }
@Override public void setTime(long time) { this.time = time; }
@Override public void setLane(int lane) { this.lane = lane; }
@Override public void setEndTime(Long endTime) { this.endTime = endTime; }
@Override public void setJudged(boolean judged) { this.judged = judged; }
@Override public void setExtensionData(Object data) { this.extensionData = data; }
void setTypeKey(String typeKey) { this.typeKey = typeKey; }
}
}