API

Kreaturen

Eine eigene Kreatur nutzt den Körper einer Kreatur aus dem Spiel (ihr Modell, ihre Animationen, ihre Größe und ihre Art, sich zu bewegen), mit deiner Textur darübergemalt, deinen Werten, deinem Verhalten und deiner Beute. Du deklarierst sie wie den Rest deiner Inhalte: als Liste von Eigenschaften.

Eine Kreatur deklarieren

content/creatures.craftCraftScript
creature "ghost" {
    body: "minecraft:zombie"
    texture: "entity/ghost"
    health: 40
    speed: 0.3
    attack: 4
    behaviour: ["swim", "melee_attack", { wander: 0.8 }, { look_at_players: 10 }, "look_around"]
    targets: ["hurt_by", "minecraft:pig"]
    loot: [ { item: "ghostmod:ecto", count: [1, 2] } ]
}
Eigenschaft Werte Standard
body ID einer Kreatur aus dem Spiel: minecraft:zombie, minecraft:wolf, minecraft:cow… Pflicht
texture Pfad der Textur, über das Modell des Körpers gemalt: entity/ghost ist textures/entity/ghost.png der Mod das Aussehen des Körpers
model dein eigenes 3D-Modell: entity/robot ist models/entity/robot.json der Mod (siehe unten) das Modell des Körpers
size [width, height] in Blöcken: womit sie kollidiert und wo man sie anklickt (siehe unten) die des Körpers
health Lebenspunkte die des Körpers
speed Laufgeschwindigkeit (ein Zombie läuft mit 0.23, ein Wolf mit 0.3) die des Körpers
attack Schaden im Nahkampf der des Körpers
follow_range aus wie vielen Blöcken Entfernung sie ihre Ziele erkennt die des Körpers
behaviour Liste von Verhaltensweisen, von der wichtigsten zur unwichtigsten (siehe unten) das Verhalten des Körpers
targets wen sie angreift, nach Priorität geordnet (siehe unten) niemanden
loot [{ item, count, chance }, …], wie bei Blöcken: Jeder Gegenstand wird einzeln ausgewürfelt nichts
spawns Biome, in denen sie von selbst erscheint, mit Gewicht und Gruppengröße (unten) erscheint nicht von selbst
breed_item Gegenstand, mit dem sich zwei von ihnen fortpflanzen (unten) keine Zucht
tame_item Gegenstand, der sie zähmt (unten) nicht zähmbar
rideable true erlaubt Spielern, sie zu reiten (unten) false

Verhaltensweisen

Die Liste ist die Priorität: Wollen zwei gleichzeitig handeln, gewinnt die frühere. Schreib jede als Namen, als { name: number } für ihre Haupteinstellung oder als Map mit allen Einstellungen.

Verhalten Was es macht Einstellungen
"swim" Bleibt im Wasser oben.
"look_around" Schaut sich um, wenn sie nichts tut.
"wander", { wander: 0.8 } Streift umher. speed, Standard 1
"look_at_players", { look_at_players: 10 } Schaut Spieler in der Nähe an. range in Blöcken, Standard 8
"melee_attack", { melee_attack: 1.2 } Verfolgt und schlägt ihr Ziel. speed, Standard 1
"panic", { panic: 1.5 } Rennt weg, wenn sie Schaden nimmt. speed, Standard 1.25
{ avoid: "minecraft:wolf", distance: 8, speed: 1.2 } Hält sich von dieser Kreatur fern. distance in Blöcken, speed
{ follow: "minecraft:wheat", speed: 1 } Folgt dem, der diesen Gegenstand hält. speed
{ ranged_attack: "minecraft:snowball", interval: 20, range: 14, damage: 3 } Schießt ein Projektil auf ihr Ziel (unten). projectile, interval, range, speed, power, damage
"breed", { breed: 1 } Paart sich mit einer Artgenossin, wenn sie gefüttert wurde. speed
"follow_parent", { follow_parent: 1.1 } Ein Junges bleibt in der Nähe seines Elternteils. speed
{ follow_owner: 1.2, distance: 8 } Eine gezähmte Kreatur folgt ihrem Besitzer. speed, distance in Blöcken
{ fly_around: 1 } Fliegt umher; für fliegende Körper (Papagei, Biene, Allay). speed
{ can_start: …, tick: … } Dein eigener Code (unten). can_start, tick, keep_going, moves

Geschwindigkeitszahlen multiplizieren die Grundgeschwindigkeit der Kreatur: { wander: 0.8 } streift etwas langsamer umher, als sie läuft.

Ziele

targets sagt, wen sie angreift, von der höchsten zur niedrigsten Priorität. "hurt_by" ist, wer ihr Schaden zufügt. Eine Objekt-ID ist das nächste Objekt dieser Art ("minecraft:player" für Spieler, "minecraft:pig" für Schweine). Damit der Angriff stattfindet, braucht die Kreatur ein Verhalten, das ihn ausführt, etwa "melee_attack".

Sie erscheinen lassen

commands/haunt.craftCraftScript
command haunt requires "ghostmod.haunt" describe "Einen Geist an deiner Position beschwören" {
    if player == null { return "Nur für Spieler" }
    world().spawn("ghostmod:ghost", player.location)
    return "&7Ein Geist erscheint…"
}

Die ID gehört deiner Mod: ghostmod:ghost. Der Spielbefehl /summon ghostmod:ghost funktioniert auch.

Von selbst erscheinen

Füge spawns hinzu, und die Kreatur taucht von selbst in der Welt auf, wie die Kreaturen des Spiels.

content/ghost.craftCraftScript
creature "ghost" {
    body: "minecraft:zombie"
    spawns: [ { biomes: ["minecraft:dark_forest", "#minecraft:is_forest"], weight: 20, group: [1, 2] } ]
}

Jeder Eintrag nennt die biomes, in denen sie erscheint (eine ID oder ein #Tag für eine ganze Biomgruppe), ein weight (Gewicht: wie oft, verglichen mit den anderen Kreaturen dieses Bioms; eine Kuh hat 8, ein Zombie 95) und einen Bereich für die Gruppengröße group.

Sie folgt den Spawn-Regeln ihres Körpers: Mit Zombie-Körper erscheint sie im Dunkeln, mit Kuh-Körper auf Gras bei Licht. Das gilt sowohl beim Erzeugen der Welt als auch später.

Spawn-Ei. Jede Kreatur bekommt außerdem ein Spawn-Ei, ihre ID plus _spawn_egg (ghost_spawn_egg), im Kreativ-Tab für Spawn-Eier. Seine Textur ist textures/item/ghost_spawn_egg.png der Mod, falls vorhanden; sonst sieht es aus wie das Ei ihres Körpers.

In Kotlin:

content/Creatures.ktKotlin
content.creature("ghost") {
    body = "minecraft:zombie"
    spawn("minecraft:dark_forest", "#minecraft:is_forest", weight = 20, group = 1..2)
}

Eine Kreatur per Code steuern

Die Kreaturen, die du deklarierst, und jeder andere Mob sind eine Creature. Aus einem Event, einem Befehl oder einem Timer kannst du ihnen Befehle geben:

Mitglied Was es macht
target Wen sie angreift. Lesen oder setzen.
moveTo(location, speed), move_to Läuft zu einer Position. Die Geschwindigkeit multipliziert ihre normale Geschwindigkeit.
stop() Hört auf zu laufen.
isMoving, is_moving Ob sie gerade irgendwohin läuft.
lookAt(location), look_at Dreht sich, um eine Position anzusehen.
canSee(entity), can_see Ob sie freie Sicht auf diese Entität hat.
isBaby Ob sie ein Junges ist.
ownerId Die ID ihres Besitzers, sobald sie gezähmt ist.
tame(player) Macht diesen Spieler zu ihrem Besitzer.
isSitting Ob sie sitzt.
playAnimation(name), play_animation Spielt eine der Animationen ihres Modells ab (siehe unten).

Jede Entität hat eine velocity, einen Vector in Blöcken pro Tick. Lies oder setze sie, um die Entität anzustoßen: entity.velocity = vector(0, 0.6, 0) schleudert sie nach oben.

In CraftScript grenzt ein typisiertes let eine Entität auf eine Kreatur ein. Das wird bei der Ausführung geprüft:

commands/pup.craftCraftScript
command pup requires "dogmod.pup" describe "Get a pet dog" {
    if player == null { return "Players only" }
    let dog: Creature = world().spawn("dogmod:dog", player.location)
    dog.tame(player)
    dog.look_at(player.location)
    dog.velocity = vector(0, 0.6, 0)      // a little hop
    return "&7Good dog!"
}

Eigene Verhaltensweisen

Reichen die fertigen nicht aus, schreibe eine mit eigenem Code. Sie steht in der behaviour-Liste wie jede andere, ihre Position ist also ihre Priorität.

content/herder.craftCraftScript
creature "herder" {
    body: "minecraft:wolf"
    targets: ["minecraft:pig"]
    behaviour: [
        "swim",
        {
            can_start: fun(c) { return c.target != null && c.can_see(c.target) },
            tick: fun(c) {
                if c.target != null {
                    c.look_at(c.target.location)
                    if !c.is_moving { c.move_to(c.target.location, 1.2) }
                }
            }
        },
        { wander: 1 }
    ]
}
  • can_start: wird alle paar Ticks gefragt; gib zurück, ob sie beginnen soll.
  • tick: läuft jeden Tick, solange die Verhaltensweise aktiv ist.
  • keep_going: sagt, ob sie weiterlaufen soll. Fehlt es, gilt dasselbe wie can_start.
  • moves: standardmäßig true. Eine Verhaltensweise mit Bewegung läuft nicht zusammen mit einer anderen bewegenden; die weiter oben in der Liste gewinnt. Nutze false für solche, die nur schauen oder reagieren.

In Kotlin: Behaviour.Custom(canStart = { … }, tick = { … }, keepGoing = …, moves = true)

Tiere: züchten, zähmen, reiten und fliegen

Ein paar Eigenschaften und Verhaltensweisen machen aus einer Kreatur ein Tier. Dieses wird mit Äpfeln gezüchtet, mit einem Knochen gezähmt und kann geritten werden:

content/mooble.craftCraftScript
creature "mooble" {
    body: "minecraft:cow"
    tame_item: "minecraft:bone"
    breed_item: "minecraft:apple"
    rideable: true
    behaviour: ["swim", { breed: 1 }, { follow_parent: 1.1 }, { follow_owner: 1.2, distance: 8 }, { wander: 0.8 }]
}
  • Züchten. breed_item plus die Verhaltensweise "breed": Mit diesem Gegenstand gefüttert, bekommen zwei der gleichen Art ein Junges dieser Art. Dafür braucht es einen Tierkörper (Kuh, Wolf, Huhn …). Junge nutzen "follow_parent", um bei den Eltern zu bleiben.
  • Zähmen. tame_item: Jeder Versuch klappt mit einer Wahrscheinlichkeit von eins zu drei. Der Besitzer wird gemerkt, und eine gezähmte Kreatur greift ihren Besitzer nie an. Schleichen und mit leerer Hand benutzen lässt sie sich hinsetzen oder aufstehen. { follow_owner: 1.2, distance: 8 } lässt sie ihrem Besitzer folgen.
  • Reiten. rideable: true: Mit leerer Hand benutzen, um aufzusteigen (nach dem Zähmen nur der Besitzer). Gesteuert wird mit den Bewegungstasten und der Maus; zum Absteigen schleichen.
  • Fliegen. { fly_around: 1 } für fliegende Körper (Papagei, Biene, Allay). Eine rideable-Kreatur mit fliegendem Körper steigt, wenn ihr Reiter nach oben schaut, und sinkt, wenn er nach unten schaut.

In Kotlin: breedItem = …, tameItem = …, rideable = true und die Verhaltensweisen Behaviour.Breed(), Behaviour.FollowParent(), Behaviour.FollowOwner(speed, distance) und Behaviour.FlyAround().

Eigene Projektile

Neben den Projektilen des Spiels kann ein Mod eigene deklarieren. Es hat eigenen Schaden, eigene Schwerkraft und eigene Wirkung beim Aufprall:

content/frost_bolt.craftCraftScript
projectile "frost_bolt" {
    damage: 4
    gravity: false
    on_hit: fun(e) {
        let at = e.entity?.location ?? e.block?.location
        if at != null { e.projectile.world.spawn_particle("minecraft:snowflake", at.add(0.5, 1, 0.5), 12, 0.4, 0.02) }
    }
}
  • damage: Schaden an dem, was es trifft.
  • gravity: false lässt es geradeaus fliegen.
  • on_hit: fun(e), wird beim Aufprall aufgerufen, mit demselben e wie beim Ereignis hit: e.projectile, e.shooter und e.entity oder e.block.
  • texture: Das Projektil fliegt mit dem Aussehen seines Gegenstands, also nutzt es standardmäßig textures/item/<id>.png; mit texture nimmst du eine andere.

Nutze es wie jedes andere Projektil: world.shoot("mymod:frost_bolt", from, velocity, shooter), oder in einer Kreatur { ranged_attack: "mymod:frost_bolt" }. In Kotlin:

content/FrostBolt.ktKotlin
content.projectile("frost_bolt") {
    damage = 4.0
    gravity = false
    onHit = { e -> /* … */ }
}

Fernangriffe und Projektile

Die Verhaltensweise ranged_attack lässt eine Kreatur schießen. Sie nähert sich, bis ihr Ziel in Reichweite und in Sicht ist, und feuert dann.

content/frost_spirit.craftCraftScript
creature "frost_spirit" {
    body: "minecraft:snow_golem"
    behaviour: [{ ranged_attack: "minecraft:snowball", interval: 20, range: 14, damage: 3 }, { wander: 0.6 }]
    targets: ["minecraft:zombie", "hurt_by"]
}

on hit(e) {
    if e.shooter?.type == "frostmod:frost_spirit" && e.entity != null {
        e.entity.velocity = vector(0, 0.2, 0)      // knocked up
    }
}
Einstellung Bedeutung
ranged_attack ranged_attack: das Projektil (minecraft:arrow, minecraft:snowball, minecraft:small_fireball, minecraft:wind_charge …).
interval interval: Ticks zwischen den Schüssen.
range range: Entfernung in Blöcken, aus der sie schießt.
speed speed: Laufgeschwindigkeit beim Annähern.
power power: wie schnell das Projektil fliegt.
damage damage: zusätzlicher Schaden bei einem Treffer.

Um per Code zu schießen, für Kreaturen oder für die Fähigkeit eines Spielers, nutze world().shoot(projectile, from, velocity, shooter, damage).

In Kotlin:

content/FrostSpirit.ktKotlin
creature("frost_spirit") {
    body = "minecraft:snow_golem"
    behaviour(Behaviour.RangedAttack(Identifier.parse("minecraft:snowball"), interval = 20, range = 14.0, damage = 3.0))
    target(TargetRule.Nearest(Identifier.parse("minecraft:zombie")))
}

// From code, e.g. a player's ability:
world.shoot(Identifier.parse("minecraft:small_fireball"), from, Vector(0.0, 0.0, 1.5), shooter = player, damage = 4.0)

Das Event hit (ProjectileHitEvent) wird ausgelöst, wenn ein Projektil auftrifft. Es hat e.projectile, e.shooter und entweder e.entity oder e.block, je nachdem, was getroffen wurde. Brichst du es ab, fliegt das Projektil hindurch. Siehe Events.

Gut zu wissen

  • Jeder Körper hat seine Grenzen. Manchen Kreaturen aus dem Spiel fehlt ein Wert: Eine Kuh hat keinen Angriffsschaden. Setzt du ihn, wird er ignoriert und Crafting warnt im Log.
  • Körper, die nicht laufen. Körper, die selbst keinen Weg finden können, ignorieren Laufverhalten (umherstreifen, verfolgen, Panik, folgen, ausweichen). Der Rest funktioniert.
  • Ohne behaviour verhält sich die Kreatur wie der Körper, den sie nutzt. Sobald du die Liste schreibst, macht sie nur, was darin steht.
  • Das Modell ändert nur das Aussehen. Bewegung und Verhalten kommen immer vom Körper, und die Größe auch, solange du nicht size angibst.
  • Eine eigene Kreatur ist ein lebendes Objekt wie jedes andere: Sie bekommt die Events spawn, damage und entity_death, hat data, und du steuerst sie mit dem, was in Die Welt und die Spieler steht.

In Kotlin

content/Creatures.ktKotlin
package com.example.rubies.content

object Creatures {
    fun register(content: ContentBuilder) {
        content.creature("ruby_golem") {
            body = "minecraft:zombie"
            texture = "entity/ruby_golem"
            health = 60.0
            speed = 0.25
            attackDamage = 6.0
            behaviour(Behaviour.Swim)
            behaviour(Behaviour.MeleeAttack())
            behaviour(Behaviour.Wander(0.6))
            behaviour(Behaviour.LookAtPlayers(12f))
            behaviour(Behaviour.LookAround)
            target(TargetRule.HurtBy)
            target(TargetRule.Nearest(Identifier.parse("minecraft:player")))
            drop(Items.RUBY, 2..4)
        }
    }
}

Verhaltensweisen: Behaviour.Swim, LookAround, Wander(speed), LookAtPlayers(range), MeleeAttack(speed), Panic(speed), Avoid(entity, distance, speed), Follow(item, speed). Ziele: TargetRule.HurtBy und TargetRule.Nearest(id). Beute fügst du mit drop(item, count, chance) hinzu, wie bei Blöcken.

Dein eigenes 3D-Modell

Gib model an, und die Kreatur wird mit deinem Modell statt dem des Körpers gezeichnet. Der Körper liefert weiterhin Größe, Bewegung und Verhalten; das Modell ändert nur, wie sie aussieht.

content/robot.craftCraftScript
creature "robot" {
    body: "minecraft:pig"
    model: "entity/robot"
    texture: "entity/robot"
    behaviour: ["swim", { wander: 0.8 }, { look_at_players: 10 }]
}

Das Modell ist models/entity/robot.json der Mod und seine Textur ist textures/entity/robot.png. In Kotlin: creature("robot") { body = "minecraft:pig"; model = "entity/robot"; texture = "entity/robot" }. Das Format ist in allen Spielversionen dasselbe.

models/entity/robot.jsonJSON
{ "texture_size": [64, 64],
  "bones": [
    { "name": "body", "pivot": [0, 6, 0], "cubes": [ { "origin": [-5, 6, -3], "size": [10, 10, 6], "uv": [0, 0] } ] },
    { "name": "head", "parent": "body", "pivot": [0, 16, 0], "cubes": [ { "origin": [-4, 16, -4], "size": [8, 8, 8], "uv": [0, 16] } ] },
    { "name": "left_leg", "pivot": [2.5, 6, 0], "cubes": [ { "origin": [1, 0, -1.5], "size": [3, 6, 3], "uv": [32, 0] } ] },
    { "name": "right_leg", "pivot": [-2.5, 6, 0], "cubes": [ { "origin": [-4, 0, -1.5], "size": [3, 6, 3], "uv": [32, 16] } ] }
  ],
  "animations": { "head": "look", "left_leg": "walk", "right_leg": "walk_opposite", "body": "idle" } }

Größen sind in Pixeln (16 ist ein Block), mit y nach oben ab den Füßen der Kreatur.

  • Knochen: name, ein optionales parent (er bewegt sich mit ihm), pivot (der Punkt, um den er sich dreht) und cubes.
  • Würfel: origin (seine unterste Ecke), size und uv (wo seine Textur im Bild beginnt). Das Layout ist das übliche für Boxen: Ein Würfel mit Breite w, Höhe h und Tiefe d belegt eine Fläche von 2(w+d) mal (d+h) Pixeln.
  • Animationen gehören zu je einem Knochen, als Name oder als Liste von Namen:
Animation Was sie macht
look Dreht sich dorthin, wohin die Kreatur schaut; für Köpfe.
walk, walk_opposite Schwingt beim Laufen; die zweite in Gegenphase, für das andere Glied.
idle Ein leichtes Wiegen.
spin Dreht sich unablässig.

Lässt sich ein Modell nicht zeichnen, sieht die Kreatur wie ihr Körper aus, und das Log nennt den Grund.

Größe

Eine Kreatur ist so groß wie ihr Körper. Ist dein Modell kleiner oder größer, gib size: [width, height] in Blöcken an, damit das, womit sie kollidiert, und die Stelle, an der man sie anklickt, zu dem passen, was die Spieler sehen:

content/drake.craftCraftScript
creature "drake" {
    body: "minecraft:bee"
    model: "entity/drake"
    texture: "entity/drake"
    size: [1.4, 1.1]
}

In Kotlin: size = 1.4 to 1.1.

Keyframe-Animationen

Für Bewegungen jenseits der fertigen Animationen füge neben bones und animations einen Abschnitt clips hinzu:

models/entity/robot.jsonJSON
{ "bones": [ … ],
  "animations": { … },
  "clips": {
    "idle": { "length": 2.0, "bones": { "head": { "position": { "0": [0, 0, 0], "1": [0, 0.6, 0], "2": [0, 0, 0] } } } },
    "walk": { "length": 1.0, "bones": { "body": { "rotation": { "0": [0, 0, -6], "0.5": [0, 0, 6], "1": [0, 0, -6] } } } },
    "roar": { "length": 1.5, "bones": {
      "head": { "rotation": { "0": [0, 0, 0], "0.4": [-35, 0, 0], "1.1": [-35, 0, 0], "1.5": [0, 0, 0] },
                "scale": { "0": 1, "0.4": 1.35, "1.1": 1.35, "1.5": 1 } },
      "body": { "position": { "0": [0, 0, 0], "0.3": [0, 4, 0], "0.6": [0, 0, 0] } } } }
  } }
  • Jeder Clip hat eine length (Länge) in Sekunden und pro Bone bis zu drei Kanäle: rotation in Grad, position in Pixeln (y nach oben) und scale (eine Zahl oder [x, y, z]).
  • Die Schlüssel sind Zeiten in Sekunden. Zwischen den Schlüsseln werden die Werte geradlinig überblendet; füge einem Clip "interpolation": "smooth" hinzu, und er läuft stattdessen auf einer Kurve durch seine Schlüssel. Ein Kanal darf auch ein einzelner Wert für den ganzen Clip sein.
Clip Wann er abgespielt wird
walk Läuft in Schleife, solange sie geht, im Takt ihrer Füße.
idle Läuft in Schleife, solange sie still steht.
attack Wird abgespielt, wenn sie zuschlägt.
Jeder andere Name Wird abgespielt, wenn Code es verlangt: c.play_animation("roar"). Nahe Spieler mit Crafting sehen es.
Smooth clipJSON
"idle": { "length": 1.2, "interpolation": "smooth", "bones": {
  "left_wing": { "rotation": { "0": [0, 0, -20], "0.6": [0, 0, 25], "1.2": [0, 0, -20] } } } }

Ein Clip, der aus Code gestartet wird, läuft über walk, idle und attack, statt sie zu ersetzen, und sie addieren sich: Eine Kreatur kann brüllen, während sie läuft.

Junge einer Kreatur mit eigenem Modell werden in halber Größe gezeichnet.

Texturen

Ohne Modell hat die Textur denselben Aufbau wie die des gewählten Körpers (ein Zombie, ein Wolf…), also kannst du von einer Vorlage für diesen Körper ausgehen und darübermalen. Sie gehört in die Mod, wie die Texturen von Gegenständen und Blöcken:

Mod Wo
CraftScript (Ordner) mods/ghostmod/textures/entity/ghost.png
Kotlin oder Java src/main/resources/assets/ghostmod/textures/entity/ghost.png