minecraft-server-scriptapi
0
总安装量
6
周安装量
安装命令
npx skills add https://github.com/kaaariyaaa/scriptapiserverskill --skill minecraft-server-scriptapi
Agent 安装分布
amp
5
opencode
5
kimi-cli
5
github-copilot
5
gemini-cli
5
Skill 文档
Minecraft Server ScriptAPI
Workflow
- Scope: Identify task (events, entities, components, commands, timing). Default to latest stable version unless beta/preview requested.
- Docs: Navigate from module index to specific class/interface/event. Use Microsoft Learn as source of truth. Search via MCP when details missing.
- Output: Quote exact API names. Provide minimal working example with required imports. Verify no official equivalent exists before creating custom helpers.
- For enums like
CustomCommandParamType, always check Microsoft Learn to confirm availability. @minecraft/vanilla-datais not on Microsoft Learn, so skip MCP searches for those enums.
- For enums like
Common patterns
Events
- Subscribe/unsubscribe on
world/systemevents. Guard logic for performance.
Dimensions
- Use
world.getDimension(MinecraftDimensionTypes.<Dimension>)and pick the appropriate dimension for the task.
Components
- Check existence before access.
- Use typed IDs:
EntityComponentTypes,BlockComponentTypes,ItemComponentTypes.
Scheduling
- Use
system.run,system.runTimeout,system.runInterval,system.runJob.
Identifiers
- MUST use
@minecraft/vanilla-dataenums:MinecraftBlockTypes,MinecraftEntityTypes,MinecraftItemTypes,MinecraftDimensionTypes,MinecraftEffectTypes,potionEffect,potionDelivery,feature,enchantment,cooldownCategory,cameraPresets,biome. - Custom IDs: Must include namespace prefix (e.g.,
example:cmd). One consistent prefix per addon.
Example:
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);
}
}
});
Permission modes
Read-only
- Before simulation/events/tick start. No world mutations.
- Fix: defer to
system.run/runTimeout/runJob.
Doc verification
- When using any method/property, always check Microsoft Learn to confirm whether it is read-only safe or early-execution safe.
- Look for explicit notes in the API reference (read-only / early-execution) and follow them strictly.
- For arrow-function callbacks only, also check for restricted-execution notes like:
- “This closure is called with restricted-execution privilege.”
- “This function can’t be called in restricted-execution mode.”
- If a restricted-execution note applies, review the arrow-function body to ensure no read-only or early-execution violations; defer with
system.runif needed.
Example (read-only deferral):
world.beforeEvents.playerInteractWithBlock.subscribe((event) => {
const player = event.player;
system.run(() => {
player.runCommand("say ok");
});
});
Early-execution
- Before world loads. Many APIs unavailable.
- Fix: defer to
world.afterEvents.worldLoadorsystem.run. - Subscribe at root to avoid missing events.
Safe in early-execution:
- Event subscriptions (
world/systembeforeEvents/afterEvents) system.clearJob,clearRun,run,runInterval,runJob,runTimeout,waitTicksBlockComponentRegistry.registerCustomComponent,ItemComponentRegistry.registerCustomComponent
Custom commands
- Interface:
CustomCommand(name,description,permissionLevel,mandatoryParameters,optionalParameters). - Parameters:
CustomCommandParameter(name,type, optionalenumName). - Param types and arrow-function argument types:
String->StringPlayerSelector->PlayerLocation->Vector3ItemType->ItemTypeInteger->NumberFloat->NumberEnum->StringEntityType->EntityTypeEntitySelector->EntityBoolean->BoolBlockType->BlockType
- Register enums:
CustomCommandRegistry.registerEnum(name, values). - Register cmd:
CustomCommandRegistry.registerCommand(customCommand, callback). - Callback:
(origin, ...args) => CustomCommandResult. - Custom command callbacks run with restricted-execution privileges, so do not call read-only-restricted methods directly; defer with
system.runif needed. - When using an arrow function, align parameter names and order with the
CustomCommandParameter.namelist; avoid mismatched names or genericargswhen parameters are defined.
Example:
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}`,
};
}
);
});
Script events
- Send:
system.sendScriptEvent(id, message)(namespaced ID, payload string). - Receive:
system.afterEvents.scriptEventReceive.subscribe(callback, options?). - Event:
ScriptEventCommandMessageAfterEvent(id,message,sourceType, optionalsourceEntity/sourceBlock/initiator). - Filter:
ScriptEventMessageFilterOptions.namespaces.
Example:
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;
}
});
Performance
- Expensive work in events: use
system.runJob(generator)to spread across ticks. - Short-circuit before iterating large sets.
system.run variants
run: next tick.runTimeout(cb, ticks): delay N ticks.0can cause tight loops if misused.runInterval(cb, ticks): repeat every N ticks untilclearRun.runJob(generator): long-running work. Keep iterations small.
Type safety
- Use
typeIdchecks and verify component existence. instanceofonly for documented@minecraft/serverclasses.
Minimal templates
Event subscription:
world.afterEvents.playerJoin.subscribe((event) => {
const player = event.player;
});
Tick loop:
system.runInterval(() => {
// tick logic
}, 1);
Get dimension:
const overworld = world.getDimension(MinecraftDimensionTypes.Overworld);
Spawn entity:
const overworld = world.getDimension(MinecraftDimensionTypes.Overworld);
overworld.spawnEntity(MinecraftEntityTypes.Zombie, { x: 0, y: 80, z: 0 });
Give item:
const item = new ItemStack(MinecraftItemTypes.Diamond, 1);
player.getComponent("inventory")?.container?.addItem(item);
Apply effect:
player.addEffect(MinecraftEffectTypes.Speed, 200, { amplifier: 1 });
Get component (typed):
const health = entity.getComponent(EntityComponentTypes.Health);
Pitfalls
- Null components: Check existence before access.
- Heavy events: Use
system.runJob. - Permissions: Avoid read-only/early-execution violations.
- Raw IDs: Use typed enums.
- Namespaces: One consistent prefix per addon.
MCP tools
- Endpoint: https://learn.microsoft.com/api/mcp
- Search:
microsoft_docs_search(module + class + task). - Fetch:
microsoft_docs_fetch(full signatures/details).