minecraft-server-scriptapi について
Minecraft Server ScriptAPI を使う AI エージェント向けの開発スキルです。イベント、エンティティ、コンポーネント、コマンドを扱う開発者を対象に、Microsoft Learn での API 確認と実行制限への対応を重視します。
主な機能
- 01タスクに応じた公式 API 文書の確認
- 02イベント、ディメンション、コンポーネントの使用例
- 03カスタムコマンドとスクリプトイベントの指針
- 04実行権限と早期実行の確認
- 05型安全性とパフォーマンス上の注意
活用シーン
- 01ワールドイベントの購読実装
- 02カスタムコマンドのコールバック作成
- 03重い処理を複数 tick に分散
- 04API の実行制限の確認
MCP 対応
Microsoft Learn MCP エンドポイントを指定し、文書検索に microsoft_docs_search、完全なシグネチャや詳細の取得に microsoft_docs_fetch を使います。
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ kaaariyaaa/ scriptapiserverskill --skill minecraft-server-scriptapiインストール後、Claude Code で/minecraft-server-scriptapiを入力して読み込まれたか確認します。
同梱ファイルSKILL.ja.md
詳細
Minecraft Server ScriptAPI
ワークフロー
- 範囲:タスク(イベント、エンティティ、コンポーネント、コマンド、タイミング)を特定します。ベータ版/プレビュー版が指定されていない場合は、最新の安定版を使用します。
- ドキュメント:モジュールのインデックスから、対象のクラス/インターフェース/イベントへ移動します。Microsoft Learn を信頼できる情報源として使用します。詳細が不足している場合は、MCP で検索します。
- 出力:API 名を正確に引用します。必要なインポートを含む、最小限の実行可能な例を提示します。カスタムヘルパーを作成する前に、公式の代替手段がないことを確認します。
CustomCommandParamTypeなどの列挙型については、Microsoft Learn で利用可能であることを必ず確認してください。@minecraft/vanilla-dataは Microsoft Learn に掲載されていないため、これらの列挙型については MCP での検索を省略してください。
よくあるパターン
イベント
world/systemのイベントを登録/登録解除します。パフォーマンスのため、ロジックにガードを設けます。
ディメンション
world.getDimension(MinecraftDimensionTypes.<Dimension>)を使用し、タスクに適したディメンションを選びます。
コンポーネント
- アクセスする前に存在を確認します。
- 型付き ID を使用します:
EntityComponentTypes、BlockComponentTypes、ItemComponentTypes。
スケジューリング
system.run、system.runTimeout、system.runInterval、system.runJobを使用します。
識別子
@minecraft/vanilla-dataの列挙型を必ず使用してください:MinecraftBlockTypes、MinecraftEntityTypes、MinecraftItemTypes、MinecraftDimensionTypes、MinecraftEffectTypes、potionEffect、potionDelivery、feature、enchantment、cooldownCategory、cameraPresets、biome。- カスタム ID:名前空間プレフィックス(例:
example:cmd)を含める必要があります。アドオンごとに、一貫したプレフィックスを使用してください。
例:
import { world, system } from "@minecraft/server";
import { MinecraftDimensionTypes, MinecraftBlockTypes } from "@minecraft/vanilla-data";
system.runInterval(() => {
const dimensions = [MinecraftDimensionTypes.Overworld, MinecraftDimensionTypes.Nether];
const blocks = [MinecraftBlockTypes.Stone, MinecraftBlockTypes.Sand, MinecraftBlockTypes.GrassBlock];
for (const dimension of dimensions) {
for (const block of blocks) {
world.getDimension(dimension).setBlockType({ x: 0, y: 0, z: 0 }, block);
}
}
});
権限モード
読み取り専用
- シミュレーション/イベント/ティックの開始前です。ワールドに変更を加えることはできません。
- 対処法:
system.run/runTimeout/runJobに処理を委譲します。
ドキュメントの確認
- メソッド/プロパティを使用する際は、読み取り専用で安全か、早期実行で安全かを必ず Microsoft Learn で確認してください。
- API リファレンスにある明示的な注記(読み取り専用/早期実行)を確認し、厳守してください。
- アロー関数のコールバックについてのみ、次のような制限付き実行に関する注記も確認してください:
- 「このクロージャーは、制限付き実行権限で呼び出されます。」
- 「この関数は、制限付き実行モードでは呼び出せません。」
- 制限付き実行に関する注記が適用される場合は、アロー関数の本体を確認し、読み取り専用または早期実行の違反がないことを確かめます。必要に応じて、
system.runに処理を委譲します。
例(読み取り専用の処理委譲):
world.beforeEvents.playerInteractWithBlock.subscribe((event) => {
const player = event.player;
system.run(() => {
player.runCommand("say ok");
});
});
早期実行
- ワールドの読み込み前です。利用できない API が多数あります。
- 対処法:
world.afterEvents.worldLoadまたはsystem.runに処理を委譲します。 - イベントを見逃さないよう、ルートで登録します。
早期実行で安全なもの:
- イベントの登録(
world/systemのbeforeEvents/afterEvents) system.clearJob、clearRun、run、runInterval、runJob、runTimeout、waitTicksBlockComponentRegistry.registerCustomComponent、ItemComponentRegistry.registerCustomComponent
カスタムコマンド
- インターフェース:
CustomCommand(name、description、permissionLevel、mandatoryParameters、optionalParameters)。 - パラメーター:
CustomCommandParameter(name、type、省略可能なenumName)。 - パラメーターの型とアロー関数の引数の型:
String->StringPlayerSelector->PlayerLocation->Vector3ItemType->ItemTypeInteger->NumberFloat->NumberEnum->StringEntityType->EntityTypeEntitySelector->EntityBoolean->BoolBlockType->BlockType
- 列挙型の登録:
CustomCommandRegistry.registerEnum(name, values)。 - コマンドの登録:
CustomCommandRegistry.registerCommand(customCommand, callback)。 - コールバック:
(origin, ...args) => CustomCommandResult。 - カスタムコマンドのコールバックは、実行制限付きの権限で実行されるため、読み取り専用制限のあるメソッドを直接呼び出さないでください。必要に応じて
system.runで後回しにしてください。 - アロー関数を使用する場合は、パラメーター名と順序を
CustomCommandParameter.nameのリストに合わせてください。パラメーターが定義されている場合は、名前の不一致や汎用的なargsの使用を避けてください。
例:
import {
system,
StartupEvent,
CommandPermissionLevel,
CustomCommandParamType,
CustomCommandStatus,
} from "@minecraft/server";
system.beforeEvents.startup.subscribe((init: StartupEvent) => {
init.customCommandRegistry.registerEnum("example:mode", ["on", "off"]);
init.customCommandRegistry.registerCommand(
{
name: "example:demo",
description: "Command demo",
permissionLevel: CommandPermissionLevel.GameDirectors,
cheatsRequired: true,
mandatoryParameters: [
{ type: CustomCommandParamType.String, name: "msg", },
{ type: CustomCommandParamType.Enum, name: "example:mode"},
],
optionalParameters: [
{ type: CustomCommandParamType.Boolean, name: "silent" },
{ type: CustomCommandParamType.Integer, name: "count" },
],
},
(origin, msg, mode, silent, count) => {
const msgValue = String(msg ?? "ok");
const modeValue = String(mode ?? "off");
const silentValue = Boolean(silent ?? false);
const countValue = Number(count ?? 1);
return {
status: CustomCommandStatus.Success,
message: silentValue
? undefined
: `[${origin.sourceType}] ${msgValue} mode=${modeValue} count=${countValue}`,
};
}
);
});
スクリプトイベント
- 送信:
system.sendScriptEvent(id, message)(名前空間付きID、ペイロード文字列)。 - 受信:
system.afterEvents.scriptEventReceive.subscribe(callback, options?)。 - イベント:
ScriptEventCommandMessageAfterEvent(id、message、sourceType、省略可能なsourceEntity/sourceBlock/initiator)。 - フィルター:
ScriptEventMessageFilterOptions.namespaces。
例:
import { system, world, ScriptEventSource } from "@minecraft/server";
system.afterEvents.scriptEventReceive.subscribe((event) => {
const { id, message, sourceType, initiator, sourceEntity, sourceBlock } = event;
if (id !== "example:say") return;
switch (sourceType) {
case ScriptEventSource.Block:
world.sendMessage(`sendBy:${sourceBlock?.typeId ?? "unknown"} ${message}`);
break;
case ScriptEventSource.Entity:
world.sendMessage(`sendBy:${sourceEntity?.typeId ?? "unknown"} ${message}`);
break;
case ScriptEventSource.NPCDialogue:
world.sendMessage(`sendBy:${initiator?.typeId ?? "unknown"} ${message}`);
break;
case ScriptEventSource.Server:
world.sendMessage(`sendBy:server ${message}`);
break;
}
});
パフォーマンス
- イベント内で負荷の高い処理を行う場合は、
system.runJob(generator)を使用して複数のティックに分散させてください。 - 大きな集合を反復処理する前に、早期リターンを行ってください。
system.runの各種メソッド
run:次のティックで実行します。runTimeout(cb, ticks):Nティック遅延させます。誤って使用すると、0によって無限ループが発生することがあります。runInterval(cb, ticks):clearRunが呼び出されるまで、Nティックごとに繰り返します。runJob(generator):長時間実行する処理です。反復処理の単位は小さくしてください。
型安全性
typeIdを確認し、コンポーネントの存在を検証してください。instanceofは、ドキュメントに記載されている@minecraft/serverのクラスに対してのみ使用してください。
最小限のテンプレート
イベントのサブスクリプション:
world.afterEvents.playerJoin.subscribe((event) => {
const player = event.player;
});
ティックループ:
system.runInterval(() => {
// tick logic
}, 1);
ディメンションの取得:
const overworld = world.getDimension(MinecraftDimensionTypes.Overworld);
エンティティのスポーン:
const overworld = world.getDimension(MinecraftDimensionTypes.Overworld);
overworld.spawnEntity(MinecraftEntityTypes.Zombie, { x: 0, y: 80, z: 0 });
アイテムの付与:
const item = new ItemStack(MinecraftItemTypes.Diamond, 1);
player.getComponent("inventory")?.container?.addItem(item);
効果の適用:
player.addEffect(MinecraftEffectTypes.Speed, 200, { amplifier: 1 });
コンポーネントの取得(型指定):
const health = entity.getComponent(EntityComponentTypes.Health);
注意点
- Nullコンポーネント:アクセスする前に存在を確認してください。
- 負荷の高いイベント:
system.runJobを使用してください。 - 権限:読み取り専用や早期実行に関する違反を避けてください。
- 生のID:型指定された列挙型を使用してください。
- 名前空間:アドオンごとに一貫したプレフィックスを使用してください。
MCP ツール
- エンドポイント:https://learn.microsoft.com/api/mcp
- 検索:
microsoft_docs_search(モジュール+クラス+タスク)。 - 取得:
microsoft_docs_fetch(完全なシグネチャ/詳細)。
コメント
Markdown 対応