Zum Hauptinhalt springen

Haustier-Verhaltensmodule

Ein Haustier-Verhaltensmodul ist eine Lua-Datei, die Haustieren sagt, was sie tun sollen: ihrem Besitzer folgen, driften, ein Lagerfeuer umkreisen, stechen. Jede Haustier-Artdatei listet die Module auf, die ihre Haustiere ausführen, und gibt ihnen Einstellungen. Diese Seite richtet sich an Kreaturen-Autoren, die ein Modul ändern oder ein neues schreiben wollen. Um die mitgelieferten Module zu verwenden und anzupassen, siehe Haustiere.

Module verwenden denselben Lua-Dialekt wie die EliteMobs-Verhaltensprogramme: ai.module, ai.behavior, ai.sensor, ai.controls, typisierte Speicherwerte und den Kontext c.memory, c.perception, c.actuator und c.entity. Jene Seite behandelt die gemeinsamen Regeln. Diese Seite behandelt, was Haustiere hinzufügen: die Moduldateien, c.pet, c.settings und die Grenzen, unter denen Haustiere laufen.

Dateien​

  • Module liegen in plugins/FreeMinecraftModels/pet_behaviors/, in diesem Ordner oder einem beliebigen Unterordner. Jede .lua-Datei dort ist ein Modul.
  • Der Name eines Moduls ist sein Dateiname ohne .lua, kleingeschrieben. Er darf nur Buchstaben, Ziffern, ., _ und - enthalten. Haustierdateien listen Module unter diesem Namen auf.
  • Die id eines Moduls muss fmm:pet/ gefolgt von seinem Namen sein, pet_behaviors/mine/slow_drift.lua deklariert also id = 'fmm:pet/slow_drift'. Ein Modul, dessen ID nicht zu seinem Dateinamen passt, wird mit einer Warnung übersprungen.
  • Teilen sich zwei Dateien einen Namen, wird die geladen, deren Pfad zuerst sortiert, und die Konsole meldet zur anderen die Warnung Duplicate content filename. Eine byteidentische Kopie wird stillschweigend übersprungen.
  • Eine Datei oder ein Ordner, der aus pet_behaviors/ hinausverweist, wird übersprungen.
  • FreeMinecraftModels schreibt jedes seiner 15 mitgelieferten Module, wenn nirgends im Ordner eine Datei dieses Namens existiert. Ein gelöschtes kommt beim nächsten Laden mit der aktuellen mitgelieferten Version zurück. Eine bereits vorhandene Datei wird nie überschrieben, bearbeitet oder nicht, auch nicht, nachdem du sie in einen Unterordner verschoben hast. Sie behält also deine Änderungen und verpasst auch spätere Updates des mitgelieferten Moduls.
  • /fmm reload liest jedes Modul und jede Haustierdatei neu ein, holt die Haustiere aus der Welt und bringt sie mit den neuen Modulen zurück. Ihre Speicherwerte beginnen leer. Du musst die revision eines Moduls nach dem Bearbeiten nicht erhöhen.

Von einer Kopie ausgehen​

Die mitgelieferten Module sind die besten Beispiele: drift.lua bewegt einen Flieger, wander.lua läuft, night_glow.lua ist ein einzelner Sensor und sting.lua hat zwei. Beginne mit dem, das deinem Ziel am nächsten kommt.

  1. Kopiere es unter einem neuen Namen, zum Beispiel pet_behaviors/mine/slow_drift.lua aus drift.lua.
  2. Ändere seine id zu fmm:pet/slow_drift.
  3. Benenne seine Speicherwerte, Verhalten und Sensoren so um, dass sie mit dem neuen Namen beginnen: drift_to wird zu slow_drift_to, in memories und in jedem Aufruf von c.memory, und die id = 'fmm:pet/drift' des Verhaltens wird zu fmm:pet/slow_drift. Zwei Module auf einer Kreatur können sich keinen Speichernamen, keine Verhaltens-ID und keine Sensor-ID teilen; das zweite aufgelistete wird mit einer Warnung ausgelassen. Durch das Umbenennen kann die Kopie neben dem Original laufen.
  4. Liste es in der Haustierdatei anstelle des Originals auf: - slow_drift, oder mit Einstellungen - slow_drift: { speed: 0.03 }.
  5. Führe /fmm reload aus und prüfe die Konsole.

Ein mitgeliefertes Modul an Ort und Stelle zu bearbeiten funktioniert auch, ändert aber jede Art, die es auflistet.

Eine Moduldatei​

Dieses Modul ist klein, aber vollständig. Nachts lässt sich das Haustier auf einer Stelle nahe seinem Anker nieder, statt zu driften, und spielt ab dem Moment, in dem es diese Stelle wählt, alle 10 Sekunden eine Animation ab.

-- At night: settles on one spot near its anchor (its owner, or home when wild) and plays an animation now and then.
return ai.module {
id = 'fmm:pet/night_rest', revision = 1,
-- radius: blocks around the anchor. speed: blocks per tick for a flyer, at species speed 1.
settings = { radius = 3, speed = 0.04, animation = 'interact' },
memories = { night_rest_to = 'position', night_rest_retry = 'integer' },
behaviors = {
ai.behavior {
id = 'fmm:pet/night_rest', priority = 12, probe_interval = 10,
controls = { ai.controls.move, ai.controls.look },
can_start = function(c)
return c.pet.night and not c.pet.staying and c.pet.anchor ~= nil
and c.tick >= (c.memory:get('night_rest_retry') or 0)
end,
can_continue = function(c)
return c.pet.night and not c.pet.staying and c.memory:contains('night_rest_to')
end,
start = function(c)
local anchor = c.pet.anchor
local to = anchor and c.pet:rest_point(anchor, c.settings.radius)
if to ~= nil then
c.memory:set('night_rest_to', to)
else
-- Nothing fits here: look again in 5 seconds instead of every tick.
c.memory:set('night_rest_retry', c.tick + 100)
end
end,
tick = function(c)
local to = c.memory:get('night_rest_to')
if to ~= nil then c.pet:steer_to(to, c.settings.speed * c.pet.species.speed) end
end,
stop = function(c)
c.memory:forget('night_rest_to')
c.pet:stop()
end
}
},
sensors = {
ai.sensor {
id = 'fmm:pet/night_rest_animation', interval = 200,
sense = function(c)
if c.memory:contains('night_rest_to') then c.pet:play_animation(c.settings.animation) end
end
}
}
}

Eine Haustierdatei listet es dann als - night_rest auf, oder als - night_rest: { radius: 5, animation: idle }.

FeldHinweise
idErforderlich. fmm:pet/ und der Dateiname
revisionErforderlich. Eine beliebige positive ganze Zahl
settingsOptional. Die Standardwerte, die Haustierdateien ändern können. Der Typ jedes Standardwerts ist der Typ, den eine Haustierdatei angeben muss: eine Zahl, true/false, Text oder eine Liste aus Text. Siehe Einstellungswerte
memoriesOptional. Was sich das Modul für jedes Haustier merkt, nach Name und Typ: integer, number, boolean, string, uuid oder position. Beginne jeden Namen mit dem Namen des Moduls. Siehe Speicherwerte
dependenciesOptional. IDs anderer Module in pet_behaviors/, die dieses braucht. Sie laufen auf jeder Kreatur, die dieses auflistet, mit ihren Standardeinstellungen, sofern die Haustierdatei sie nicht ebenfalls auflistet
behaviorsOptional. Einträge ai.behavior { ... }, die das Haustier bewegen oder drehen
sensorsOptional. Einträge ai.sensor { ... }, die das Haustier nie bewegen

Code oberhalb von return, etwa lokale Funktionen und Konstanten, ist erlaubt; wander.lua und idle_look.lua enthalten solchen Code.

Was ein Callback erhält​

NameWas es ist
c.petDas Haustier, nur lesbar. Siehe c.pet
c.settingsDie Einstellungen dieses Moduls: seine Standardwerte, überlagert von den Werten der Haustierdatei und der Variante, wie in c.settings.radius. Jedes Haustier hat seine eigene Kopie, Schreiben darauf ändert also nur dieses Haustier
c.memoryget(name), set(name, value), forget(name) und contains(name) für die Namen in memories. Jedes Haustier hat seine eigenen
c.tickDer aktuelle Spiel-Tick, für Timer
c.perception, c.actuator, c.entityDer Mind-Kontext von MagmaCore, wie in den EliteMobs-Verhaltensprogrammen. c.entity ist der verborgene Körper, nicht das Modell. Siehe Kontext eines Mind-Programms. idle_look.lua verwendet c.perception:nearest_player(range) und c.actuator:look_at(point)

c.pet​

Ein Punkt ist eine Tabelle mit x, y und z und optional world, wie c.pet.position. Ein Punkt ohne world liegt in der Welt des Haustiers. Ein Punkt in einer anderen Welt zählt als nichts: Methoden antworten nil, false oder 0, und distance_to antwortet math.huge. Die Punkte, die c.pet zurückgibt, liegen immer in der Welt des Haustiers, und einer, der woanders läge, wird als nil gelesen.

  • Methoden werden mit einem Doppelpunkt aufgerufen: c.pet:distance_to(point).
  • Zahlenargumente müssen endlich sein. Radien, Tiefen, Höhen, Verstärker, Dauern und die anderen Bereiche sind wie unten aufgeführt begrenzt. Keine Methode lädt einen Chunk.
  • c.pet und c.pet.species sind nur lesbar. Eine Zuweisung darauf löst einen Fehler aus; halte Werte pro Haustier in c.memory.
  • Die Eigenschaften und route_target() sind eine Momentaufnahme: Jede wird einmal pro Haustier-Tick gelesen und bleibt in jedem Callback dieses Ticks gleich. c.pet:teleport_near_owner und c.pet:stop aktualisieren sie. Eine auf andere Weise vorgenommene Bewegung, etwa durch c.entity:teleport, zeigt sich im nächsten Tick. speed ist die Ausnahme und wird immer frisch gelesen.
  • Jedes Lesen einer Position liefert eine neue Tabelle, die das Modul ändern darf.

Eigenschaften​

NameTypWert
wildbooltrue für ein wildes Haustier, false für eines im Besitz
stayingboolIhm wurde befohlen zu bleiben
settledboolFrei umherstreifend: Ihm wurde nicht befohlen zu bleiben, und es ist wild oder innerhalb von follow.distance seines Besitzers
babyboolEin Baby
migratingboolFliegt eine nächtliche Wanderroute
modelstringDas Modell seiner Variante. Ein Baby mit babyModel liest weiterhin seine Variante
positionpointWo sein Körper ist
homepoint/nilWo ein wildes Haustier lebt; nil bei einem Haustier im Besitz
anchorpoint/nilWorum es streift: sein Besitzer, bei einem wilden Haustier seine Heimat oder, falls es keine hat, sein aktueller Ort. nil, wenn der Besitzer offline oder in einer anderen Welt ist
stay_anchorpoint/nilDer Platz, an dem es bleiben sollte; nil, wenn es nicht bleibt
owner_locationpoint/nilnil bei einem wilden Haustier oder wenn der Besitzer offline, tot oder in einer anderen Welt ist
owner_distancenumberBlöcke bis zum Besitzer; math.huge, wenn es in dieser Welt keinen gibt
night, dayboolday nur bei Tageslicht in einer normalen Welt; Abenddämmerung, Morgendämmerung, der Nether und das End zählen als night
rainingboolRegen fällt auf das Haustier, höchstens alle 10 Ticks geprüft
speednumberDie aktuelle Geschwindigkeit seines Körpers in Blöcken pro Tick
route_cruisenumberDie Reisegeschwindigkeit seines Schwarms bei einer Wanderung, sonst 0
speciestableDie Zahlen aus der Haustierdatei, unten

c.pet.species enthält:

FeldSchlüssel der Haustierdatei
idspecies
speedfollow.speed
hover_heightfloat.hoverHeight
hover_variancefloat.hoverVariance
roam_radiusfollow.roamRadius
follow_distancefollow.distance
leash_distancefollow.leashDistance
teleport_distancefollow.teleportDistance
scalescale
baby_scalebabyScale

Bewegung​

Rufe diese nur aus start, tick oder stop eines Verhaltens auf, in einem Verhalten, dessen controls das Nötige auflisten. Aus can_start oder einem Sensor lösen steer_to und stop einen Fehler aus, der sagt, wohin sie gehören.

MethodeGibt zurückWas sie tut
steer_to(point, cruise)boolEin Tick in Richtung des Punktes, rufe sie also in jedem Tick auf. Braucht move und look. Ein Flieger fliegt mit cruise Blöcken pro Tick (0 bis 4) und wird beim Ankommen langsamer. Ein Läufer oder Schwimmer findet dorthin nativ seinen Weg mit dem 4 × cruise-Fachen der Bewegungsgeschwindigkeit seines Körpertyps, nie unter einem Viertel davon; ein cruise von 0 hält ihn an und gibt false zurück. false, wenn es dort nicht hingelangen kann
stop()nilHört auf, sich zu bewegen. Braucht move
teleport_near_owner(radius)boolSetzt den Körper neben seinen Besitzer, innerhalb von radius Blöcken (bis zu 64), in seinem eigenen Medium; ein Schwimmer sucht Wasser innerhalb von radius oder 6 Blöcken, je nachdem, was größer ist. Ein Läufer oder Schwimmer landet mindestens einen Block vom Besitzer entfernt. false, wenn der Besitzer fort oder in einer anderen Welt ist, nichts passt oder der Ort nicht mindestens einen Block näher am Besitzer liegt, als das Haustier ist. Sie braucht keine Steuerung, rufe sie aber aus einem Verhalten auf, das move hält, wie es follow_owner tut, damit sie das Haustier nicht von einem anderen Verhalten wegzieht

Orte und Entfernungen​

Diese funktionieren aus jedem Callback. Die, die einen Punkt zurückgeben, geben nil zurück, wenn nichts passt oder der Chunk nicht geladen ist. Radien reichen bis 64.

MethodeGibt zurückWas sie tut
hover_point(center, radius)point/nilEin Punkt in seinem Schwebebereich innerhalb von radius
rest_point(center, radius)point/nilEin Ruheplatz in seinem eigenen Medium: der Schwebebereich bei einem Flieger, Standboden bei einem Läufer oder einem stationären Körper, Wasser bei einem Schwimmer (auf der Höhe von center, wenn center im Wasser liegt, sonst 0,5 bis 2 Blöcke unter der Oberfläche) und Boden oder sonst Wasser bei einem amphibischen Körper
ground_point(center, radius)point/nilEin Standplatz, von etwa 5 Blöcken unter bis 4 über center. nil über Flüssigkeit oder einem tiefen Fall
water_point(center, radius, min_depth, max_depth)point/nilEine Schwimmstelle zwischen den beiden Tiefen unter der Oberfläche (0 bis 16)
ground_below(point, depth)number/nilDie Höhe der Oberseite des Bodens innerhalb von depth Blöcken nach unten (1 bis 64). Eine Wasser- oder Lavaoberfläche zählt als Boden, außer die Art ist AQUATIC. Ohne Boden in Reichweite die Höhe des Punktes minus depth
trail_point(back, height)point/nilback Blöcke hinter der Blickrichtung des Besitzers, height über seinen Füßen bei einer FLYING-Art und sonst an seinen Füßen. nil, wenn der Besitzer fort oder in einer anderen Welt ist
distance_to(point)numberBlöcke von seinem Körper
route_target()point/nilWohin seine Wanderroute es in diesem Tick haben will. nil, wenn es nicht wandert oder die Route zu Ende ist
find_perch(height, radius)point/nilheight Blöcke (0 bis 8) über dem nächsten Laub unter ihm, bis zu radius Blöcke (0 bis 4) zur Seite, oder über dem Boden direkt unter ihm. Ein Haustier im Besitz erhält nur einen Sitzplatz innerhalb von follow.distance seines Besitzers
nearest_campfire(radius, keep_ticks, blocks, soul_variants, height)point/nilDer Block des nächsten brennenden Feuers, das es innerhalb von radius (1 bis 32) nutzen darf. blocks listet die Feuerarten auf, die es nimmt, CAMPFIRE, SOUL_CAMPFIRE oder beide, und eine Liste, die keine von beiden nennt, nimmt beide; soul_variants listet die Modelle auf, die nur Seelen-Lagerfeuer nehmen, und jedes andere Modell nimmt dann nur normale. Ein Haustier im Besitz nimmt nur ein Feuer, dessen Punkt height darüber innerhalb von follow.distance minus 1 von seinem Besitzer liegt. Die Suche jedes Chunks wird keep_ticks (20 bis 1200) lang gehalten und von allen Haustieren geteilt
campfire_usable(fire, blocks, soul_variants, height)boolOb ein zuvor gefundenes Feuer noch brennt und noch passt

Effekte​

Diese funktionieren aus jedem Callback; Sensoren sind der übliche Ort.

MethodeGibt zurückWas sie tut
set_glow(light, lantern_bone, animation)nilBeleuchtet die Anzeige-Bones des Modells mit light (0 bis 15), für Java-Spieler. Ein Modell mit einem Bone namens lantern_bone loopt außerdem animation. Die letzten beiden sind optional
clear_glow()nilZurück zum Weltlicht, beendet diese Animation
scale_toward(target, span, ticks, elapsed)nilLässt die Größe des Körpers sanft auf target mal seine Basisgröße zugehen. Eine volle Änderung von 1 auf span dauert ticks (mindestens 2); elapsed sind die Ticks seit dem letzten Aufruf. Multiplikatoren 0.1 bis 16
sting_contacts(on, effect, duration, amplifier, damage, cooldown)numberSticht die Spieler, deren Berührung das Modell eines wilden Haustiers in der letzten Sekunde erreicht hat, nie einen im Kreativ- oder Zuschauermodus, und gibt zurück, wie viele. Sie löscht die Berührungen auch bei on gleich false. Haustiere im Besitz zeichnen keine Berührungen auf
sting_enemies(reach, effect, duration, amplifier, damage, cooldown)numberSticht feindliche Mobs innerhalb von reach Blöcken (0 bis 4) von der Hitbox des Modells, nie Spieler oder Haustiere, und gibt zurück, wie viele
drizzle(depth, chance)boolSchwebt das Haustier ruhig über einer Nutzpflanze innerhalb von depth Blöcken (1 bis 8), gibt es Wasserpartikel und eine Wahrscheinlichkeit chance (0 bis 1), dass die Pflanze eine Stufe wächst. true, wenn es über einer Nutzpflanze ist
owner_effect(effect, duration, amplifier, range)boolGibt dem Besitzer den Trankeffekt für duration Ticks (1 bis 6000), wenn er sich innerhalb von range Blöcken befindet, ohne Partikel. Ein Effekt, den der Besitzer schon hat und der mindestens gleich stark ist und mindestens gleich lange hält, bleibt unangetastet. false, wenn der Besitzer fort, in einer anderen Welt oder außer Reichweite ist oder der Effekt nicht existiert
play_animation(name)boolSpielt eine der Animationen des Modells einmal ab. false, wenn das Modell sie nicht hat

Bei beiden Stichen ist effect ein Trankeffektname oder NONE, duration in Ticks (1 bis 6000), amplifier 0 ist Stufe I (bis zu 255), damage in halben Herzen, und cooldown sind die Ticks (mindestens 1), bevor dieses Haustier dasselbe Opfer erneut stechen kann. Ein Stich zeigt Funken und spielt ein Bienenstich-Geräusch ab, und ein ausgewachsenes Tier spielt seine Animation attack ab. Zu einem Trankeffektnamen, den es nicht gibt, erscheint pro Art und Name einmal eine Warnung, und er wendet nichts an.

Verhalten und Sensoren​

  • Ein Verhalten bewegt oder dreht das Haustier. Es listet die Steuerungen auf, die es braucht, ai.controls.move und ai.controls.look für die Bewegungsaufrufe von c.pet, und nur ein Verhalten hält eine Steuerung gleichzeitig. Solange es gestoppt ist, fragt MagmaCore sein can_start. Gibt das true zurück und sind die Steuerungen frei, übernimmt es sie und führt start aus, dann in jedem Tick tick, solange can_continue true zurückgibt (ohne can_continue entscheidet can_start), dann stop. Siehe Lebenszyklus.
  • Die niedrigere priority-Zahl kommt zuerst. Ein Verhalten nimmt einem laufenden mit einer höheren Zahl die Steuerungen ab, dessen stop dann läuft. Die 12 aus dem Beispiel lässt Folgen und Bleiben vor dem Modul stehen und stellt es vor Driften und Schweben, aber auch vor campfire; ein Haustier, das beide auflistet, besucht nachts also nie ein Feuer. Eine Zahl über 15 würde das Feuer gewinnen lassen.
  • Ein Verhalten konkurriert nur um die Steuerungen, die es auflistet. idle_look nimmt nur look, läuft also, solange kein Verhalten den Blick hält; jedes mitgelieferte Bewegungsverhalten nimmt look ebenfalls, daher gewinnt Bewegung immer darüber.
  • Eine Haustierdatei kann keine Priorität ändern. Zum Umordnen kopiere das Modul und ändere die Zahl.
  • probe_interval ist optional, in Ticks: Solange das Verhalten gestoppt ist, wird can_start nur alle so vielen Ticks gefragt, auf der eigenen Phase jedes Haustiers. Das spart Serverzeit, wenn viele Haustiere draußen sind, auf Kosten eines um bis zu so viele Ticks verspäteten Starts. Der Standard ist 1; Werte über 200 zählen als 200. Ein laufendes Verhalten läuft weiterhin in jedem Tick.
  • Ein Sensor bewegt das Haustier nie. Er führt sense im ersten Tick aus, in dem der Körper des Haustiers tickt, dann alle interval Ticks auf der eigenen Phase des Haustiers, egal was die Verhalten gerade tun. Leuchten, Anschwellen, Stiche, Nieselregen und Besitzereffekte sind Sensoren.

Die mitgelieferten Module verwenden:

ModulPrioritätprobe_intervalSensor-interval
migrate110
stay54
follow_owner104
campfire1510
day_perch1810
rain_bloom19104 (Anschwellen)
drift, wander, swim2010
hover304
idle_look3010
night_glow40
sting4 (Spieler), 10 (Mobs)
crop_drizzle20
owner_effect20

Regeln​

  • Rufe steer_to und stop nur aus start, tick oder stop eines Verhaltens auf, in einem Verhalten, das die Steuerungen auflistet, die sie brauchen.
  • Halte Zustand pro Haustier in c.memory, deklariert unter memories, mit Namen, die mit dem Namen des Moduls beginnen.
  • Schreibe nicht in c.pet; eine Zuweisung darauf löst einen Fehler aus.
  • Halte Callbacks kurz. Jedes Haustier läuft unter diesen festen Grenzen, die Module und Haustierdateien nicht ändern können:
GrenzeWert
Ein Callback1,5 ms
Die Callbacks eines Haustiers in einem Tick3 ms, höchstens 32 Callbacks
Die Callbacks aller Haustiere in einem Tick10 ms
CPU-Zeit eines Callbacks, harte Grenze20 ms
Lua-Anweisungen eines Callbacks, harte Grenze20.000

Erreicht ein Haustier eine der ersten drei Grenzen, warten seine übrigen Callbacks auf den nächsten Tick. Ein Callback, der eine harte Grenze überschreitet, wird gestoppt und schlägt wie ein Fehler fehl. Siehe Budgets.

Wenn etwas nicht stimmt​

Nichts hiervon stoppt den Server oder die anderen Kreaturen. Suche in der Konsole nach pet behavior, pet_behaviors und .pet.yml, um diese Warnungen zu finden.

  • Ein Modul wird nicht geladen. Ein Modul, das nicht kompiliert, dessen ID nicht zu seinem Dateinamen passt oder dessen Dateiname andere Zeichen enthält, wird mit einer Warnung übersprungen, die die Datei nennt, bei einem Lua-Fehler auch die Zeile. Jedes andere Modul wird weiterhin geladen.
  • Eine Haustierdatei nennt ein Modul, das es nicht gibt. Die Warnung nennt die Haustierdatei und schlägt den nächstliegenden Modulnamen vor, wenn einer nur um ein oder zwei Buchstaben abweicht. Die Kreatur wird ohne es geladen. Existiert das Modul, ließ sich aber nicht laden, verweist die Warnung auf die Warnung zu seiner Datei.
  • Eine Einstellung ist falsch. Eine Einstellung, die das Modul nicht hat, oder ein Wert des falschen Typs wird mit dem Namen der Haustierdatei gemeldet, und der Standardwert bleibt. Siehe Einstellungswerte.
  • Zwei Module kollidieren. Deklarieren zwei Module einer Kreatur denselben Speichernamen, dieselbe Verhaltens-ID oder dieselbe Sensor-ID, behält die Kreatur das erste in der Liste und läuft mit einer Warnung ohne das andere.
  • Ein Callback schlägt fehl, während Haustiere laufen. Das wird bis zum nächsten Reload einmal pro Programm, Callback und Fehlerart protokolliert. Programme heißen fmm:pet/creature/<species>/<variant>, und Callbacks nach ihrer Verhaltens- oder Sensor-ID, etwa fmm:pet/drift.tick. Ein fehlgeschlagenes Verhalten wird gestoppt oder nicht gestartet und ab dem nächsten Tick erneut versucht; solange es weiter fehlschlägt, laufen Verhalten mit höheren Prioritätszahlen, die das Haustier bewegen oder drehen, womöglich nicht. Ein fehlgeschlagener Sensor läuft in seinem nächsten Intervall erneut.
  • Ein Aufruf von c.pet schlägt in FreeMinecraftModels fehl. Die Ursache wird einmal pro Art und Aufruf mit ihrem Stacktrace protokolliert, und der Callback schlägt mit c.pet:<method> failed; the server log has the cause fehl.
  • Ein Trankeffektname existiert nicht. Dazu erscheint einmal pro Art und Name eine Warnung, und der Aufruf wendet keinen Effekt an.

Führe nach einer Korrektur /fmm reload aus.