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
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
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.
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.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:
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.
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 wiecan_start.moves: standardmäßigtrue. Eine Verhaltensweise mit Bewegung läuft nicht zusammen mit einer anderen bewegenden; die weiter oben in der Liste gewinnt. Nutzefalsefü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:
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_itemplus 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). Einerideable-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:
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:falselässt es geradeaus fliegen.on_hit:fun(e), wird beim Aufprall aufgerufen, mit demselbenewie beim Ereignishit:e.projectile,e.shooterunde.entityodere.block.texture: Das Projektil fliegt mit dem Aussehen seines Gegenstands, also nutzt es standardmäßigtextures/item/<id>.png; mittexturenimmst 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.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.
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:
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
behaviourverhä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
sizeangibst. - Eine eigene Kreatur ist ein lebendes Objekt wie jedes andere: Sie bekommt die Events
spawn,damageundentity_death, hatdata, und du steuerst sie mit dem, was in Die Welt und die Spieler steht.
In Kotlin
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.
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.
{ "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 optionalesparent(er bewegt sich mit ihm),pivot(der Punkt, um den er sich dreht) undcubes. - Würfel:
origin(seine unterste Ecke),sizeunduv(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:
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:
{ "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:rotationin Grad,positionin Pixeln (y nach oben) undscale(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. |
"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 |