mcdoc-language

📁 mulverinex/mcdoc-language-skill 📅 7 days ago
1
总安装量
1
周安装量
#41170
全站排名
安装命令
npx skills add https://github.com/mulverinex/mcdoc-language-skill --skill mcdoc-language

Agent 安装分布

amp 1
opencode 1
kimi-cli 1
codex 1
github-copilot 1
gemini-cli 1

Skill 文档

mcdoc Language Guide

mcdoc is a schema format for describing data structures used by Minecraft, including its CODECs, JSONs, and NBTs. It is interpreted by the Spyglass language server.

Core Concepts

Primitive Types

  • boolean – true/false values
  • byte, short, int, long – Integer types (use suffix: 0b, 0s, 0, 0L)
  • float, double – Floating-point types
  • string – Text values
  • any – Accepts any value (use sparingly)

Struct Definitions

Structs define composite types with named fields:

struct EntityData {
    id: string,              // Required field
    pos?: [double] @ 3,      // Optional field (note the ?)
    /// Doc comment shown in hover
    custom_name?: string,
}

Enum Definitions

Enums define fixed sets of values with a backing type:

enum(string) Direction {
    Down = "down",
    Up = "up",
    North = "north",
}

enum(byte) DyeColorByte {
    White = 0,
    Orange = 1,
}

Type Aliases

Type aliases create named references to types, optionally with generics:

type Text = ::java::util::text::Text

type Tag<E> = struct {
    replace?: boolean,
    values: [TagEntry<E>],
}

Union Types

Union types allow a value to be one of several types (using |):

type Color = (
    #[color="hex_rgb"] string |
    #[color="composite_rgb"] int |
)

Arrays and Collections

[Type]           // Array of any length
[Type] @ 3       // Array of exactly 3 elements
[Type] @ 1..5    // Array with 1-5 elements
[Type] @ 1..     // Array with 1+ elements

Numeric Constraints

int @ 0..100       // Inclusive range (0 to 100)
float @ 0<..1      // Exclusive lower bound (>0, <=1)
float @ 0..<1      // Exclusive upper bound (>=0, <1)
int @ 0..          // Minimum only (0 or greater)

Dispatch System

Dispatches map registry entries to specific type schemas:

// Direct dispatch
dispatch minecraft:entity[zombie] to struct Zombie {
    ...super::Monster,
    CanBreakDoors?: boolean,
}

// Multiple keys to same type
dispatch minecraft:item[potion, splash_potion, lingering_potion] to struct PotionItem {
    Potion?: #[id="potion"] string,
}

// Polymorphic dispatch using a type field
struct TreeDecorator {
    type: #[id="worldgen/tree_decorator_type"] string,
    ...minecraft:tree_decorator[[type]],  // Dispatch based on type field value
}

Special Dispatch Keys

  • %unknown – Fallback for unrecognized keys
  • %none – When no key is specified
  • %fallback – Used in NBT path references

Path Variables

Path variables reference values from the data structure in dispatch keys:

  • %parent – The containing struct (chain for ancestors: %parent.%parent)
  • %key – The current map key (in mapped types)
struct CopyState {
    block: #[id="block"] string,
    properties: [mcdoc:block_state_keys[[%parent.block]]],  // References sibling field
}

// Arrays don't count as levels - %parent skips over them
struct Container {
    modifier: ModifierType,
    items: [struct {
        value: minecraft:modifier[[%parent.%parent.modifier]],  // %parent.%parent = Container
    }],
}

Generic Dispatchers

Dispatchers can have type parameters:

// Define generic dispatcher
dispatch minecraft:int_provider[constant]<T> to struct {
    value: T,
}

dispatch minecraft:int_provider[uniform]<T> to struct {
    min_inclusive: T,
    max_inclusive: T,
}

// Use with type parameter passed through
type IntProvider<T> = (
    T |
    struct {
        type: #[id="int_provider_type"] string,
        ...minecraft:int_provider[[type]]<T>,
    } |
)

// Usage with constrained type
log_length: IntProvider<int @ 0..16>,

Structural Composition

Spread Operator

The spread operator (...) includes fields from another struct:

struct Monster {
    Health?: float,
}

dispatch minecraft:entity[zombie] to struct Zombie {
    ...super::Monster,       // Include Monster fields
    CanBreakDoors?: boolean, // Add zombie-specific fields
}

Inline Structs

Structs can be defined inline within fields:

struct Container {
    items: [struct SlottedItem {
        Slot: byte,
        ...ItemStack,
    }],
}

Attributes

Attributes provide metadata using #[name] or #[name="value"] syntax:

Version Control

#[since="1.20"]           // Available from version 1.20
#[until="1.21"]           // Removed in version 1.21
#[deprecated="1.19"]      // Deprecated since 1.19

Registry References

#[id="item"] string                           // Reference to item registry
#[id(registry="block",tags="allowed")] string // Allow tags
#[id(registry="texture",path="entity/")] string // Path prefix

Validation

#[color="composite_rgb"] int    // RGB color as integer
#[color="hex_rgb"] string       // Hex color string
#[regex_pattern] string         // Regex pattern
#[uuid] string                  // UUID format
#[nbt=minecraft:item[[item]]] string // NBT validation

Other Attributes

#[canonical]              // Preferred form in a union
#[id]                     // Mark as identifier

Module System

Use Statements

use ::java::util::text::Text           // Absolute path
use super::block_state::BlockState     // Parent directory
use super::super::HeightmapType        // Grandparent

Module Resolution

A path like use modifier::Type resolves to either:

  • modifier.mcdoc (single-file module) — check first
  • modifier/mod.mcdoc (directory module)

Path Conventions

  • :: prefix for absolute paths from root
  • super:: for parent module
  • No prefix for sibling imports

Mapped Types (String Maps)

Define structs with dynamic string keys:

struct Lang {
    [#[translation_key(definition=true)] string]: #[translation_value] string,
}

struct Criteria {
    [#[criterion(definition=true)] string]: AdvancementCriterion,
}

Comments

// Single-line comment (not included in output)

/// Doc comment (appears in hover/autocomplete)
/// Multiple lines supported
field_name: Type,

Best Practices

  1. Naming: Use PascalCase for NBT/CODEC structs, snake_case for JSON fields
  2. Avoid unnecessary doc comments – Only document complex or non-obvious fields
  3. Use string enums when a string union changes between MC versions
  4. Always name dispatched structs – Named types for all dispatch targets
  5. Limit nesting to 3 levels – Extract deeply nested structs
  6. Use spread operator to avoid code repetition

Additional Resources