dayz-agentic-modding-mcp
dayz-agentic-modding-mcp
Ein MCP-Server, der es einem Agenten ermöglicht, einen DayZ-Mod zu bauen, zu prüfen, dass der Client kompiliert, einen Testserver zu starten und ein strukturiertes Urteil statt eines Logs zu erhalten.
Der Server erledigt die Arbeit selbst: Er ruft FileBank, das Signierungswerkzeug und die Diagnose-Executable direkt auf. Ein Projekt benötigt kein eigenes Build-Skript.
Warum ein Profil
Der Server weiß nichts über einen bestimmten Mod. Alles Spezifische lebt in einem zweiteiligen Profil:
dayz-mcp.toml— portabel, im Mod-Repository eingecheckt: welche Mods gepackt werden sollen, wie ein gesunder Boot aussieht.dayz-mcp.local.toml— maschinenspezifisch, niemals eingecheckt: wo das Spiel, die Werkzeuge und der Teststand leben.
Das Mischen der Hälften wird beim Laden abgelehnt: So hört ein Repository auf, auf der Maschine eines anderen zu bauen. Beginnen Sie mit dayz-mcp.example.toml.
Ein Mod wird einmal deklariert, per Name: Quellen standardmäßig in <root>/Name, Ausgabe @Name/addons/Name.pbo. build.sources kann die Quelle eines Mods woandershin umleiten (z. B. "." für einen Mod, dessen config.cpp direkt im Repository-Root liegt).
Die portable Hälfte — dayz-mcp.toml
Key | Bedeutung |
| wie dieses Projekt genannt werden soll |
| ein Eintrag pro Mod, per Name; Quelle, PBO und |
| wo die Quelle eines Mods tatsächlich liegt, relativ zum Profil ( |
| was niemals gepackt werden darf. Das Auflisten ersetzt die Standardliste vollständig; die Standardliste ist |
| eine gefilterte Kopie packen, anstatt zu verweigern, wenn etwas Ausgeschlossenes vorhanden ist — das Layout, das ein Root-Layout-Mod benötigt |
| das Verzeichnis, gegen das jeder Modellpfad aufgelöst wird, relativ zu dieser Datei. Es muss den Präfix-Ordner des Mods enthalten. Wird von den Modellwerkzeugen benötigt und von sonst nichts — siehe „Die Asset-Pipeline“ |
| ein PowerShell-Skript, das vor dem Packen ausgeführt wird, für Projekte, die zuerst Code generieren |
| die Zeile, die der Mod ausgibt, wenn er das Laden abgeschlossen hat — siehe unten |
|
|
| Warnungsbudget; den Schlüssel weglassen, um die Prüfung zu deaktivieren |
| Teilzeichenfolgen, die einen Lauf unabhängig von allem anderen schlecht machen |
| reguläre Ausdrücke, die Skriptfehler markieren, die zu Ihnen gehören, verwendet von der Client-Kompilierungsprüfung |
| zusätzliches Engine-Rauschen, das ignoriert werden soll, zusätzlich zur eingebauten Liste |
Die Maschinenhälfte — dayz-mcp.local.toml, niemals eingecheckt
Key | Bedeutung |
| die Spielinstallation; wird automatisch erkannt, wenn nicht vorhanden |
| DayZ Tools; werden automatisch erkannt, wenn nicht vorhanden |
| die Blender-Executable, nur für |
| der vorbereitete Teststand. Der Server bootet dagegen und seine Logs werden aus |
| der Dateiname der Serverkonfiguration im Stand (Standard |
| der Port, den |
| Mod-Ordnernamen, aufgelöst unter dem eigenen |
| vollständige Pfade zu allem anderen, das geladen werden soll, für Mods, die nicht in |
| Ordnernamen, die an |
Die Bereitschaftszeile
server_start endet, wenn expect.ready_line in einem Log erscheint, das nach diesem Boot-Beginn geschrieben wurde. Es ist das Einzige, das der Server nicht selbst herausfinden kann, und ohne es ändern sich zwei Dinge: Es kann nichts abgewartet werden, also startet der Boot-Job den Server, bestätigt einen Moment später, dass er noch lebt, und endet mit dieser Aussage; und log_verdict hat keine Zeile, von der Zähler abgelesen werden können, also passt expect.counters nie auf etwas. Fehler, Abstürze und das Warnungsbudget werden weiterhin beurteilt. Ein Profil ohne Bereitschaftszeile wird unterstützt, ist nicht kaputt — project_open sagt das in seinen Notizen.
Related MCP server: DayZ API MCP Server
Werkzeuge
Tool | Was es tut |
| das Profil lesen, das Spiel und die Werkzeuge erkennen, melden, was fehlt |
| aktuelles Projekt, laufender Server, letzte Aufträge |
| jedes deklarierte Mod packen und signieren; gibt eine Auftrags-ID zurück. Verweigert einen zweiten Build desselben Projekts, solange noch einer läuft |
| den Testserver starten, fertig sein, wenn er bereit ist. Verweigert, wenn die Mission, die die Konfiguration nennt, nicht unter |
| pid, ob der Prozess lebt, ob das Protokoll wächst (im Abstand von |
| den Server stoppen, den diese Sitzung gestartet hat (optionale pid für verwaiste Server) |
| das |
| den Diagnose-Client ausführen und seine Protokolle lesen |
| bestanden/nicht bestanden mit Gründen: Zähler, verbotene Zeichenfolgen, Warnbudget. |
| letzte Zeilen, optional gefiltert; dieselben zwei Quellen |
| Status eines lang laufenden Auftrags |
| auf das Ende eines Auftrags warten |
| Ausgaben eines abgeschlossenen Auftrags abrufen |
| das Bridge-Mod packen, dessen Quellen mit diesem Server ( |
| tickt die Bridge im laufenden Spiel noch: meldet die Tick-Nummer und ob sie sich über |
| den im Postfach feststeckenden Befehl verwerfen und benennen, was verworfen wurde. Verweigert, solange die Bridge lebendig aussieht, außer |
| warten, bis die Bridge im Spiel tatsächlich Befehle beansprucht. Einmal aufrufen, nachdem der Boot-Auftrag abgeschlossen ist, vor dem ersten Weltbefehl — siehe „Server bereit ist nicht Bridge bereit" unten |
| Momentaufnahme der Welt aus der einmal-pro-Sekunde-Veröffentlichung der Bridge: Spieler, Position, Gesundheit, Hände. Ohne Argumente kostenlos; mit |
| ein Objekt auf dem Boden erzeugen (ohne Lebensdauer, sodass es mitten in der Prüfung nicht verschwinden kann), in den Händen des Spielers oder in seinem Inventar |
| den Spieler zu |
|
|
| Objekte einer Klasse in der Nähe löschen. Erfordert die Klasse; löscht nie einen echten Spieler |
| welche Objekte in der Nähe sind, nicht wie viele: Klasse, Position, Entfernung und Gesundheit für jedes. Eine Seite, und es sagt es — die wahre Gesamtzahl kommt neben der Liste zurück |
| die Weltuhr bewegen. Jedes Feld, das auf -1 bleibt, behält seinen aktuellen Wert, der zuerst von der Engine zurückgelesen wird, weil die Engine ein Datum als fünf Zahlen auf einmal setzt |
| Bewölkung, Regen, Nebel, Schneefall oder Wind bewegen. Ein Anstoß, keine Sperre: Die Engine simuliert das Wetter danach weiter, und sowohl das Tool als auch das Mod sagen das |
| eine eigene Aktion eines Mods durch das Tor der Engine ausführen — siehe unten |
| die Notluke: ein beliebiges Verb über denselben Transport, in jeder Antwort als nicht standardmäßig markiert |
| den Spiel-Client starten und mit dem Stand verbinden; gibt eine Auftrags-ID zurück. Immer im Fenstermodus. Endet, wenn die Bridge |
| client_status() | PID, Fenstergeometrie, ob das Fenster minimiert oder im Vordergrund ist, die Hintergrundeinstellung, die Spieleranzahl und ob ein virtueller Controller angeschlossen ist |
| client_stop() | den Client stoppen, den diese Session gestartet hat, und den virtuellen Controller abziehen |
| client_shot(path) | das Fenster des Clients als PNG erfassen, mit lit_fraction — der Zahl, die ein echtes Bild von einem komplett schwarzen unterscheidet. Kein Fokus nötig |
| client_move(x, y, seconds) | die Spielfigur mit dem linken Stick laufen lassen. Analog, und der einzige Weg, der die Figur überhaupt bewegt. Kein Fokus nötig |
| client_look(x, y, seconds) | die Kamera mit dem rechten Stick drehen. Kein Fokus nötig |
| client_press(button, seconds) | eine Gamepad-Taste, aus einer geschlossenen Tabelle von vierzehn Namen. Kein Fokus nötig |
| client_chat(text, color) | eine Zeile in den Chat schreiben — serverseitig von der Bridge zugestellt, also keine Tastatur, kein Fenster, kein Fokus |
| client_type(text, submit) | in ein clientseitiges Eingabefeld mit echten Tastendrücken tippen. Das einzige Werkzeug hier, das in den Vordergrund tritt, und das sagt es auch in seiner Antwort |
| client_verdict(since) | den laufenden Client anhand seiner eigenen .RPT beurteilen — ein Urteil über Fehler und Abstürze; siehe unten |
| ui_menu() | was die Benutzeroberfläche des Clients gerade macht: offene Menüklasse, Cursor, Dialog. Kostenlos — wird bei jedem Tick neu veröffentlicht |
| ui_tree(root, depth, limit) | der Widget-Baum des Clients: Pfad, Klasse, Name, Sichtbarkeit, Bildschirmrechteck, Tiefe und Text. Eine Seite, und das sagt es auch |
| ui_find(name, class_name, text, root) | derselbe Durchlauf, im Client gefiltert, sodass der ganze Baum nie reisen muss |
| ui_click(path, expect_name, expect_class, via) | ein Widget drücken. via="script" geht ohne Fokus durch den Handler des geöffneten Menüs; via="cursor" setzt die echte Maus auf zugehörige Rechteck |
| ui_text(path, text, expect_name) | in ein Eingabefeld schreiben und den Wert aus dem Widget zurücklesen |
| mod_lint(mod, strict) | das Enforce-Skript beurteilen, ohne irgendetwas zu packen oder zu starten. mod_build führt es zuerst aus und lehnt das ab, was es ablehnt |
| knowledge_build(layer, full, only) | eine Ebene des API-Index bauen oder aktualisieren; gibt eine Job-ID zurück. only=[path] liest genau die Dateien erneut, die du nennst |
| knowledge_status() | Übe, was jede Ebene enthält, wie alt sie ist und ob sie noch dem entspricht, was auf der Platte liegt |
| knowledge_find(name, kind, owner, layer, prefix, limit) | eine Klasse, Methode, Konstante, Enum oder Konfigurationsklasse anhand eines Namens finden |
| knowledge_show(name, ..., body) | eine Deklaration vollständig: Signatur, Mitglieder, Vererbungskette und der Quelltext selbst — direkt aus einem Archiv gelesen, falls es darin lebt |
| knowledge_overrides(name, owner, layer) | wer diese Klasse oder Methode überschreibt |
| knowledge_callers(name, kind, owner, layer) | wer diese Methode au (ruft oder diese Klasse baut — jede Aufrufstelle, samt Klasse und Methode, die den Aufruf ausgeführt hat |
| asset_export(blend, mod, source, name) | ein Modell aus einer .blend in build.headless exportieren, ohne Benutzeroberfläche; gibt eine Job-ID zurück. Die optional erste Schritt — siehe unten |
| asset_build(mod, source, deploy) | die Modelle eines Mods aus ihren MLOD-Quellen binarisieren, prüfen, was das herausgekommen, und erst dann in den Mod geben; gibt eine Job-ID zurück |
| asset_check(mod, model) | die Modelle und Texturen beurteilen, die ein Mod bereits mitliefert. Baut nichts, braucht keine DayZ-Tools, antwortet in Millisekunden |
| asset_convert(source, output) | eine Textur zwischen .png und .paa konvertieren und das Ergebnis beurteilen |
Signaturen – und warum die eigene Meldung der Engine auf die falsche Fährte führt. Unter verifySignatures = 2 lehnt eine Instanz jede Client, bei Code 118 und *"missing dta bin.pbo"* ab — ein Vanilla-Dateiname, ganz ohne Erwähnung von Signaturen. Die Ursache ist normalerweise der Schlüsselbund: Dieses Tool startet die Diagnose-Programmdatei aus der CLIENT-Installation, also liest die Engine die keysneben *dieser* ausführbaren Datei, währenddayz.bikey— der Schlüssel, der die eigenen Pbos des Spiels signiert — mit der separaten DayZServer-Installation geliefert wird. Einkeys-Ordner, der fehlt oder nur einen eigenen Mod-Schlüssel enthält, lässt den Server nichts mehr verifizieren, Vanilla eingeschlossen. client_startweigert sich und nennt dafür, welche der drei Fälle vorliegt;server_startbir warnt nur, weil eine Headless-Instanz bootst auch ohne Client noch nützlich ist. Eine unsignierte Pbo in der-mod`-Zeile des Clients wird auf eigene Weise benannt — einschließlich der Bridge dieses Servers, die absichtlich unsigniert gebaut ist.
Drei Grenzen, die die Engine den UI-Werkzeugen auferlegt, keine davon umgangen: eine schlichte TextWidget hat SetText und kein GetText in enwidgets.c, also eine BEDEMMA label überhaupt nicht gelesen werden kann — was die Bedeutung einer Mod-Oberfläche ist, bleibt eine Frage an die serverseitige, bei der die Daten real sind. Ein Klick auf Skriptebene erreicht nur das offene Skriptmenü, denn Widget hat SetHandler und kein GetHandler; viakurzur ist für alles andere da. Und der Client muss die Bridge laden: eine pbo trägt beide Hälften, wobei ein Profil, das sie unter mods.server_only führt, sie von der -mod-Zeile des Clients fernhält — diese Fall wird vor allem anderen mit Namen benannt, und nicht mit einem leeren Baum beantwortet.
job_wait ist das Werkzeug zum Warten, und sein timeout ist bei 600 Sekunden gedeckelt, egal wie groß der übergebene Wert ist. Zwei andere Werkzeuge schlafen: server_statusden Log zweimal abtastet,pulse_secondsAbstand, gedeckelt auf 10 Sekunden — diese Pause ist zu unterscheiden, das langsames oder hängendes Booten ist — undbridge_statuszweimal den tickt der Bridge ab mitwindow` Abstand, gedeckelt auf den gleichen 10 Sekunden, aus demselben Grund. Alles andere kehrt sofort zurück; Arbeit, die Minuten dauert, dass diese hinter einer Job-ID passiert.
Die Bridge-Mod
bridge_build packt das bridge/ aus dem eigenen Repository dieses Servers in das danebenliegende distance_Distribution-Bridge. Es ist der Mod dieses Servers, nicht deiner: Eine Kopie dient allen Projekten, nichts wird in dein Repository geschrieben außer dem Job-Protokoll, und auch kein Unterschlüssel eines Projekts benutzt — eine -serverMod pbo wird nie einem Client zu Prüfung übergeben, deshalb ist sie unsigniert gebaut, und das Ordner bleibt frei von Signaturen und SchlKennen.
Das Build lädt sie nicht. Das bleibt beweg deines Profils, denn die Bridge ist eine Extra-P0 in der Instanz, und ein Lauf ohne sie bleibt mögliche. Zum Ankoppeln fügst du data-plugins-local. das sind die Zeilen, die bridge_lint auch in der Job-Zusammenfassung druckt:
[mods]
extra = ["<path printed by bridge_build>/@DZMCP_Bridge"]
server_only = ["@DZMCP_Bridge"]server_only ist Hairbei das, was sie zu lowerServerMod leitet statt zu -mod. Ohne das boot die Instanz ganz normal, und bridge_status meldet, dass die Bridge keinerlei Zustand geschrieben hat – ehrliches true, das leicht broken nur verwege für eine kaputte Bridge gehalten wird.
bridge_status meldet auch die command-Mailbox. In der Spielumgebung verlässt sie nur der Mod, indem er sich das Kommando geht; auf dieser Seite machen das bridge_clear und das Vorway- -putzen von server_start. Eine Kommando also, die geschickt wurde, während die Instanz unten war, wird nicht demandelt und verfällt nicht von selbst – es blockiert weiterhin den nächsten send, und eine shop, dieser Tools gebootete wird es aufgreifen. server_start räumt vor jedem Neustart beide Transferdateien ab, sodass ein über diesem Tool gestalteter Server or kein Kommando von einer vorherigen Session ausführt; das dient der Hygiene, nicht als Ersatz für das Wissen, dass das Kommando noch da ist. Der Zustand kommt als stale_command zurück, und bridge_clear() ist der Weg raus. Das Leeren ist vorsätzlich eigener Tool: Ein wartendes Kommando wegzuwerfen ist eine Entscheidung, keine Sache, die eine Statusabfrage überhinweg erledigen sollte. Es lehnt ab, so lange die Brücke lebendig aussieht, varias force=True übergibst, und meldet in jedem Fall die ID des Verw% discarded.
Was bridge_status mit einschwachen auseinanderhalten kann
Der Tick alleine reicht nicht aus, um eine Bridge zu beurteilen, denn er startet bei jedem Boot bei 0 neu, mentre die Zustandsdatei im Profilverzeichnis weiterlebt. Jede Antwort trägt das eigene Urteil des Kanals in heartbeat, und die vier sind tatsächlich _:
|
| Bedeutung |
|
| Der Tick zeigte sich innerhalb einer Session — die einzige |
|
| Eine neue Welt kam zwischen den beiden Proben auf: lebendig, nicht eingefroren, und alles, was an die alte Session gesendet wurde, ist weg |
|
| dieselbe Welt zweimal gesehen, nicht bewegend — ein Problem auf Skript-Seite, also ist |
|
| MessSample konnte nicht gelesen werden (oder |
Jede Antwort, die eine Probe gelesen hat, trägt auch session_id — Die Id der gelebten Welt — und eine restarted Antwort trägt zusätzlich previous_session_id, damit der Aufrufer sagen kann, welche Welt verschwand.
no_server stale_command no_state_file invalid_state unreadable_state und outdated_bridge kommen all diesen vorweg: Nichts läuft, ein Kommando hängt fest, der Mod nicht geladen ist, das Zustandsdokument ist gültiges JSON mit einem falsch benannten Feld (das Tool hat das Feld genannt und prüft zweimal, bevor es es sagt), die Datei parst sie komplett nicht, oder sie parst, aber stammt aus einer Zeit zuvor als das Protokoll dieses Servers (dann mit bridge_build neu bauen).
Die Weltkommandos
Die Weltwerkzeuge sprechen mit der Bridge über zwei JSON-Dateien im -profiles-Verzeichnis des Servers: eine Kommando-Mailbox (von hier aus atomar geschrieben, von der Mod als Anspruch entfernt) und eine Zustandsdatei, die der Mod jeder Sekunde überschreibt. Enforce Script hat kein "rename", also kann der Mod nicht atomar schreiben – der Leser toleriert stattdessen anrissene Geschreibungen, eine fehlgeschlagene lesung ist nie Neu. Vier → Tatsachen, alle an einem Live-Server gemessen, legen fest:
Server-Bereit ist nicht Bridge-Bereit. Die Brücke beginnt Kommandos zig Sekunden, nachdem der Server reif gemeldet hat — die bisherige Spanne liegt bei 18 und 38 Sekunden und ändert sich Boot zu Boot. Ein in dieses Fenster gesendet Kommando wird nicht abgelehnt — es wird spät geholt und ausgeführt nachdem der Aufrufer längst aufgegeben hat. Also: server_start, warte auf Boot-Job, dann world_ready(), dann die richtigen Kommandos. Jedes Weltwerkzeug lehnt au Achtung sofort ab, wenn der Tick sich nicht bewegt, und nennt world_ready.
**Jeder Argumentwert reist als String über die Leitung. Der Parser des Linns ist strikt: eine JSON-Zahl irgendwo in args lehnt den ganzen args-Block ab. Die Tools erstellen Zahlen und boolesche Werte selbst und lehnen Werte ohne echt String-Darstellung ab (Listen, dicts, None). Positionen gehen als ein einziger String "x: y: z".
Weigerung ist ein Ergebnis. Die natives Satz des Mods kommen unverändert als Fehler aus („no player is on the server", „the class is Next", „the action's own Can() said no"). Niemand mit verbunden, ist der Normalfall einer Headless-Instanz, und jedes Verb, das eine gebrauchliche Spieler sagt das auch, statt still nichts zu tun.
Die SessionId schützt vor den Kommando von gestern. Jedes Kommando trägt die WorldMost – die Session, die die Brücke zuletzt veröffentlicht hat; der Mod lehnt jedes an eine andere Session gerichtete Kommando (oder ohne Session) ab, ohne es auszuführen. Ein Kommando, das geschrieben wurde, während die Instanz unten war, kann also nie in eine frisches gebootete Welt ausgelöst werden. Die Tools stempeln die Session automatisch — wichtig ist sie nur, wenn du das Maildrohnen von Hand belegst.
Ein semantisches Verb wie "die Probe abgeben" täuscht: In einer echten Mod bedeuten dieselben Wörter je nachdem, welches Gerät in der Nähe ist, welche Fraktion der Spieler hat und was bereits freigeschaltet ist, verschiedene Dinge. Dieser Kontext ist nicht aufzählbar, also versucht es die Bridge nicht. world_action nimmt den Klassennamen einer Aktion, ein Ziel und das gehaltene Item und bittet die Engine, es durch ihr eigenes Tor zu schicken — dasselbe, durch das ein Tastendruck geht. Die Anwendbarkeit entscheidet das eigene Can() der Aktion, und seine Ablehnung ist ein aussagekräftiges Testergebnis, kein Werkzeugfehler. Die unterscheidbaren Antworten: Manager beschäftigt, Spieler handelt bereits, Spieler sprintet, unbekannte Aktionsklasse und "das eigene Can() der Aktion sagte nein". "Akzeptiert" ist ebenfalls kein Erfolg — der Befehl läuft weiter, bis die Engine die Aktion tatsächlich freigibt, und jeder Fehlerpfad gibt den Manager frei, damit der Spieler danach weiter handeln kann.
world_exec ist der Notausstieg
Alles, was eine Mod offenlegt, das keine Aktion ist — "wie viele Punkte im Fraktionspool" — geht durch world_exec(verb, args): ein beliebiges Verb über denselben Transport. Jede Antwort ist als non_standard markiert: Dieser Server kennt das Verb nicht, validiert es nicht und steht nicht dafür ein, was die Mod damit tut. Ein Verb, das der Bridge-Build nicht kennt, kommt zurück und listet die Verben, die er kennt. Ein Projekt, das ein eigenes Verb braucht, bearbeitet seine eigene Kopie des Dispatchers der Bridge (der Kommentar über KnownVerbs() in bridge/scripts/5_Mission sagt genau, wo); es gibt bewusst keine Registrierungsmechanik — ein Verb, das dieser Server typisiert und validiert hat, wäre ein Verb, für das dieser Server einsteht.
Der Client: drei Eingabeebenen, und warum es drei sind
Die Bridge erreicht den Server. Was sie nicht kann, ist auf den Bildschirm des Clients zu schauen oder durch den Client zu handeln — eine Figur über den Boden laufen lassen, ein Menü öffnen, ein Feld ausfüllen, das eine Mod gezeichnet hat. Die client_*-Werkzeuge sind das, und sie nutzen drei verschiedene Wege, weil keiner von ihnen die Arbeit der anderen beiden erledigen kann. Jede Zeile unten ist eine Messung an einem laufenden Client, keine Designabsicht.
Weg | Was er tut | Braucht den Vordergrund |
die Bridge ( | die Welt, und Text in den Chat | nein |
ein virtuelles Gamepad, ViGEmBus ( | Bewegung, Kamera und Teile der Oberfläche | nein |
echte Tastendrücke, | Text in ein Feld, das nur auf dem Client existiert | ja, und es nimmt ihn |
Tastaturemulation bewegt die Figur nicht, und Fensternachrichten bewirken gar nichts. SendInput-Scancodes mit verifiziertem Vordergrund: 25 s vorwärts, 0 m. PostMessage/SendMessage WM_KEYDOWN in das Hauptfenster und seine Kinder: 0 m, und auch keine Reaktion von den Menüs. Die Engine liest Bewegung aus Raw Input und ignoriert emulierte Tasten, weshalb hier kein Werkzeug eine Fensternachricht anbietet.
Das virtuelle Gamepad bewegt sie, ohne Fokus, und es ist ANALOG — der Grund, warum es bleibt, selbst wo eine Taste genügen würde. Gemessen in einem Lauf, bei dem eine Drittanbieteranwendung durchgehend den Vordergrund hielt:
stick fully forward, 10.0 s -> 38.40 m (3.84 m/s)
stick at 0.3 forward, 8.0 s -> 11.34 m (1.42 m/s)Gleicher Weg, gleiche Figur, die 2,7-fache Geschwindigkeit allein durch Stick-Ausschlag. "Die Figur geht, nicht rennt" lässt sich mit einer Taste nicht ausdrücken, die nur an und aus kennt. Im selben Lauf lief die Figur etwa 141 m von selbst, und die eigene Zählung der Mod von Objekten in ihrem 10-m-Umkreis ging von 1 → 0 → 1, als sie den Ort verließ und zurückkam — eine Zustandsänderung, die durch Präsenz verursacht wird, die ein Teleport nicht erzeugen kann.
Ein Teil der Oberfläche reagiert auf das Pad, ein Teil nicht. Gemessen, während das Spielfenster die ganze Zeit hinter einer anderen Anwendung lag: back öffnet und schließt das Inventar, start öffnet das Pausemenü, b schließt es — alle bei einem Standard-Tap von 0,1 s, ein Tap also lang genug ist, damit die Engine es erfasst. Aber a bewegte nichts, weder bei 0,1 s noch bei 0,5 s, und das Steuerkreuz in diesen Bildschirmen auch nicht: Der Client wechselte nicht in den Controller-Navigationsmodus, es gab also kein fokussiertes Element, auf das eine Bestätigung wirken konnte. Behandle das Schließen von Menüs als Gamepad-Aufgabe und die Bestätigung von Menüs als unbewiesen.
Die Augen brauchen ebenfalls keinen Fokus. Eine Aufnahme ist ein Live-Frame mit dem Fenster ganz unten in der Z-Reihenfolge (lit_fraction 0,9997 ohne Fokus, 0,9997 mit Fokus in derselben Sitzung). Der eine Zustand, der sie besiegt, ist ein minimiertes Fenster, dessen Clientbereich auf 0×0 kollabiert — mit einem Grund abgelehnt, statt als gültig aussehendes leeres Bild gespeichert.
All dieses Hintergrundverhalten beruht auf einer Client-Einstellung, pauseMode (GAME → UPDATE IN BACKGROUND). Bei dem hier gemessenen Wert zeichnet und simuliert der Client weiter, während er keinen Fokus hat, weshalb der Frame live ist und der Stick die Figur weiter bewegt. Bei "keine Grafik" würden beide still stoppen — ein eingefrorener Frame sieht genauso aus wie ein lebendiger. Also LESEN client_start und client_status diese Einstellung und warnen; sie schreiben sie nie, weil sie dem gehört, dem die Maschine gehört.
client_type ist das einzige Werkzeug, das den Bildschirm übernimmt, und es ist ehrlich dabei: Die Antwort trägt foreground_taken und einen Satz, der besagt, dass die Person an der Maschine während des Laufs nicht in ihr eigenes Fenster tippen konnte. Es verifiziert den Vordergrund mit GetForegroundWindow, nachdem es darum gebeten hat, weil SetForegroundWindow Erfolg zurückgibt, ohne etwas getan zu haben, wenn Windows sich weigert — und blindes Tippen sendet die Tastendrücke in das Fenster, das die Person tatsächlich verwendet. Wenn der Vordergrund nicht erlangt werden kann, wird nichts getippt, und die Ablehnung nennt den Prozess, der ihn hält.
ViGEm ist die Emulation eines echten Geräts, und dies ist ein Prüfstand. Der Treiber ist signiert und installiert ohne Neustart, und das Gamepad ist ein neues Gerät, kein Filter über der eigenen Tastatur und Maus der Maschine — ein Filtertreiber wurde hier einmal ausprobiert und kostete den Besitzer der Maschine die gesamte Tastatur- und Mauseingabe, bis er von Hand rückgängig gemacht wurde. Nichts davon ist ein Versprechen bezüglich Anticheat auf einem Live-Server, und nichts in dieser Phase macht eines.
Der Wissensindex
Ein Agent, der eine Mod schreibt, stellt dem Spiel immer wieder dieselben Fragen: Gibt es eine solche API, wie heißt sie, wo ist sie deklariert, wer überschreibt sie. Sie zu beantworten bedeutete, scripts.pbo zu entpacken und den Text zu durchsuchen — und jede Sitzung zahlte erneut. knowledge_* verwandelt diese Arbeit in eine Frage.
Es ist eine einfache SQLite-Datei im eigenen .dayz-mcp/ des Projekts, gebaut von diesem Server aus dem Spiel, den Mods, die ein Projekt deklariert, und den eigenen Quellen des Projekts. Keine Einbettungen, kein externer Dienst, kein Schlüssel.
Drei Ebenen, und warum ihre Rhythmen sich unterscheiden
Ebene | Quelle | Wird veraltet, wenn |
| das Spiel: | das Spiel aktualisiert wird |
| die Archive der Mods, die das Profil deklariert, gelesen ohne sie zu entpacken | eine Abhängigkeit aktualisiert wird oder sich die deklarierte Menge ändert |
| die eigenen Quellen der Mod, gelesen, wo sie liegen | jede Bearbeitung |
Ein Index, der in einem Zug gebaut wird, wäre innerhalb einer Minute nach dem Richtigsein falsch: Das Spiel bewegt sich ein paar Mal im Jahr, eine Abhängigkeit ein paar Mal im Monat und das Projekt zwischen einem Agentenzug und dem nächsten. Also wird jede Ebene separat gebaut, gealtert und gemessen, und jeder Build ist inkrementell — unveränderte Quellen werden nach Größe und Änderungszeit übersprungen, und only=[path] überspringt sogar den Durchlauf, der sie entdeckt.
Eine Antwort trägt das Alter der Ebene, aus der sie stammt
Veraltung wird gemessen, nicht geraten: Eine Ebene erfasst Größe und Änderungszeit jeder Quelle, die sie gelesen hat, und das wird mit den Dateien verglichen, wie sie jetzt sind.
Jede Antwort nennt die Ebenen, die sie verwendet hat, und wie alt jede ist. Eine Antwort mit keinen Ergebnissen nennt jede Ebene, die sie durchsucht hat — "nicht gefunden" ist genau so viel wert, wie die Ebenen dahinter aktuell sind.
Die Aktualität der Projekt-Ebene wird bei jeder Suche gemessen, ob sie beigetragen hat oder nicht. Das ist der gefährliche Fall: Ein Agent fügt eine Klasse hinzu, fragt danach, und eine vor einer Minute gebaute Ebene sagt "nicht gefunden" — eine selbstbewusste Aussage über Code, der existiert.
Eine Suche über eine Ebene, die nie gebaut wurde, wird abgelehnt, und die Ablehnung nennt den Aufruf, der sie baut. "Nicht gefunden" und "nicht gesucht" sind verschiedene Tatsachen, und nur auf eine davon ist es sicher zu handeln.
Eingrenzung trägt dieselbe Falle eine Ebene tiefer, also meldet eine leere eingegrenzte Antwort, wo der Name tatsächlich existiert: Wenn man
kind='class'nach einem Namen fragt, den das Spiel nur in einer Konfiguration deklariert, erhält man ein echtes "Nein", das sich liest als "das Spiel hat keine solche Klasse".
Konfigurationsklassen liegen unter kind='config', nicht unter kind='class'. Gezählt im eigenen Index dieser Maschine des Spiels: 88 102 Konfigurationsklassen gegen 43 595 Skriptdeklarationen aller Art zusammen, in eine Art gemischt, begraben sie also jede Skriptantwort. Getrennt ist "hat das Spiel eine Item-Klasse namens X" eine Frage, die man genau stellen kann.
Was er nicht beantwortet
Der Index beantwortet, was existiert: Klasse, Methode, Signatur, wo deklariert, wer überschreibt. Er beantwortet nicht, was richtig ist — dass modded class X extends X kompiliert und still nicht angewendet wird, dass _co den Alphakanal kostet, dass binarize Verzeichnisse statt Dateien nimmt. Nichts davon ist aus den Quellen ableitbar; es wurde auf die harte Tour gelernt und lebt in der Modding-Skill und in der Mod selbst. Der Index versucht nicht, eines von beiden zu ersetzen, und er versucht nicht zu verstehen, was ein Feld bedeutet oder warum eine Klasse da ist.
Semantische Suche ist bewusst nicht hier
Die Entscheidung wurde durch Messung getroffen, nicht durch Vorsicht: Jede Suche, die die früheren Phasen dieses Servers geprägt hat, war eine Suche nach Namen. Und ein Einbettungsindex würde die Regel brechen, die der Rest dieses Servers einhält — installieren und es funktioniert, ohne externen Dienst und ohne Schlüssel. Das Vorgängerprojekt, auf dem dieses bewusst nicht aufbaut, dokumentiert seine Wissensebene als lokal und kostenlos, während sein Code einen kostenpflichtigen Einbettungs-Client importiert, ohne Schlüssel scheitert und fest verdrahtete Preise trägt. Seine beiden Suchwerkzeuge hängen auch für immer, weil der Client dahinter ohne Timeout erstellt wurde; daher die Obergrenze, unter der jede Suche hier läuft. Wenn sich exakte Suche als nicht ausreichend erweist, ist semantische Suche eine separate Phase mit einer Bedingung: Das Modell wird innerhalb der Auslieferung mitgeliefert.
Die gemessenen Zahlen
Auf dieser Maschine — das Spiel mit 2810 Skriptdateien, 35 installierten Mods, einem echten Projekt mit 41 Quellen — durch die Werkzeuge, nicht durch deren Interna:
Build | Ergebnis | Zeit |
| 2927 Quellen, 131 697 Deklarationen (41 ergaben nichts) | 70,2 s |
| 8 Archive, 10 925 Deklarationen | 0,9 s |
| 523 Archive, 204 768 Deklarationen, 3 Archive nicht lesbar und benannt | 139–147 s |
| 41 Quellen, 1196 Deklarationen | 0,12 s |
Der Index auf der Platte: 74,7 MB für die drei Ebenen eines echten Projekts; 110 MB für die 523 Abhängigkeitsarchive allein. Diese Archive sind 92 GB, und keines davon ist entpackt.
Aufrufstellen sind das, wofür der Index bezahlt. Die eigenen Skripte des Spiels enthalten 43 579 Deklarationen und 113 703 Aufrufstellen, und das Aufzeichnen der zweiten Menge verdoppelt den Index grob: allein auf der Spiel-Ebene gemessen 23,8 MB und 3,7 s zum Bauen ohne sie, 49,6 MB und 4,5 s mit. Das ist der Preis dafür, beantworten zu können, „wer ruft das auf“, und er wird hier genannt, statt später auf einer vollen Festplatte entdeckt zu werden.
Antwort | Zeit |
| 4,2 ms Ende zu Ende, davon 3,0 ms für den Projekt-Durchlauf |
| 3,2 ms Abfragezeit |
| 4,2 ms |
| 0,38 ms Abfragezeit |
| 277 ms Textprüfungen, 7 ms Indexprüfungen |
Gemessen an einem Live-Stand, drei Bootvorgänge: world_time_set(hour=3, minute=7) setzte die Uhr
auf 2026-09-20 03:07 und ließ das Datum unverändert; world_weather_set("fog", 0.9, seconds=2)
änderte den veröffentlichten Nebel von 0,085 auf 0,900 und hielt ihn; world_entities(pos="7500 0 7500", radius=150, limit=5)
listete 5 von 171 Objekten mit truncated: true. Die Entfernungen kamen bei einem Radius von 150 m
als 320 m zurück, bis sie horizontal gemacht wurden, was der eigene Radiustest der Engine misst.
| knowledge_show, eine Klasse mit 400 Mitgliedern und ihrer Vererbungshierarchie | 6,8 ms |
| knowledge_status, alle drei Ebenen gemessen | 41 ms (110 ms beim ersten Aufruf nach einem Build) |
Inkrementalität, im echten Projekt: ein vollständiger Rebuild 136 ms; eine bearbeitete Datei, die
durch den Durchlauf gefunden wurde, 8,8 ms (15×); dieselbe Datei, die über only= benannt
wurde, 5,8 ms (23×). Bei einem Baum mit 2810 Dateien dominiert der Durchlauf, und only= ist
weit mehr wert — aber bei einem Projekt dieser Größe ist 15× das, was ein gewöhnlicher Rebuild
tatsächlich einbringt.
Die Obergrenze schlägt tatsächlich zu: Eine Abfrage, die mit 77 ms gemessen wurde, wurde unter einer Obergrenze von 19,3 ms bei 19,9 ms gestoppt, und die Verbindung antwortete weiterhin.
Die Asset-Pipeline
Ein Modell aus Blender in einen Mod zu bringen, sind zehn Schritte, und bis zu dieser Phase wurden alle von Hand ausgeführt. Der Wert liegt nicht darin, die Werkzeuge zu starten. Er liegt darin, dass jedes Werkzeug in dieser Kette strukturell nicht in der Lage ist, einen Fehler zu melden, und jedes dieser Schweigen hatte bereits Tage gekostet.
Gemessen an den echten Binärdateien, nicht angenommen:
Was geschah | Was das Werkzeug zurückgab |
| 0, ein leeres Ausgabeverzeichnis, keine einzige Textzeile |
| 0, ein ODOL von 46.190 Bytes, wo ein korrekter Build 58.644 Bytes umfasst |
|
|
der Blender-Exporter mit seinen eigenen Standardargumenten |
|
Also lautet die Regel, auf der dieser gesamte Namensraum aufbaut: Das Urteil wird vom Artefakt abgelesen, niemals vom Bericht des Werkzeugs. Der Exit-Code wird aufgezeichnet, aber weder als Erfolg noch als Fehler gewertet.
Die Wurzel wird deklariert, nicht angenommen
binarize hat überhaupt keine Projektwurzel-Option — die vollständige Schalterliste wurde
anhand der echten Binärdatei ermittelt. Die Wurzel ist das Arbeitsverzeichnis des Prozesses.
Derselbe Befehl, dieselbe Eingabe, ein anderes Verzeichnis, und heraus kommt ein gültiges ODOL mit
plausiblen Texturpfaden, das die Engine untexturiert rendert, mit einem Erfolgscode und ohne
Beschwerde. Das exportierende Blender-Add-on hat dieselbe Wurzel in einer eigenen Einstellung, die
von dem zuletzt geöffneten Projekt gespeichert ist: Auf dem Rechner, auf dem dies entwickelt wurde,
zeigte sie auf ein Verzeichnis aus einer nicht zusammenhängenden Sitzung, und bei einer falschen
Wurzel schlägt auch das Add-on nicht fehl — es entfernt den Laufwerksbuchstaben, behält den Rest
und schreibt Pfade, die wie Pfade aussehen.
build.project_root ist dieses Verzeichnis, einmal im portablen Teil des Profils angegeben. Der
Server setzt es als Arbeitsverzeichnis des Binarizers und schiebt es für die Dauer des Laufs in das
Add-on, sodass das, was das Add-on gespeichert hat, nichts entscheidet (es wird berichtet, damit du
es beheben kannst). Genau das macht eine falsche Wurzel unmöglich statt nur erkennbar, und
deshalb ist der Schlüssel erforderlich, bevor überhaupt etwas Modellbezogenes läuft.
Die Ablehnungen, die es erzeugt, geschehen, bevor ein Prozess existiert — gemessen bei 0,0003 s — und ein abgelehnter Build lässt das Modell, das der Mod bereits ausliefert, byte für byte unberührt.
Zwölf Prüfungen am Artefakt, und vier davon verweigern
asset_check führt sie aus, ohne etwas zu bauen und ohne DayZ Tools, denn ein frischer Klon muss
in der Lage sein zu fragen, ob das, was er ausliefert, gesund ist. Vier verweigern: Ein gebautes
Modell ist vorhanden und ist ein ODOL (C1), keine Referenz verlässt den Mod (C3), ein Material
wurde tatsächlich eingebettet (C4), und nichts bereits Binarisiertes wird binarize erneut
angeboten (C10). Der Rest warnt: verwaiste Referenzen, ein rvmat, das in einen anderen Mod zeigt,
eine durch DXT1 verlorene Transparenz (C7), eine Animation, die das Artefakt nie erreicht hat, eine
model.cfg, die nicht diejenige ist, aus der das Artefakt gebaut wurde, ein struktureller
Fingerabdruck, der nicht mehr dem entspricht, was der letzte Build bereitgestellt hat. Jeder Befund
sagt, was zu tun ist.
C4 ist diejenige, über die man Bescheid wissen sollte. Wenn binarize ein rvmat auflöst, kopiert
es die eigenen Stufentexturen dieses Materials in das Modell — fresnel, #(argb,8,8,3),
env_land_co.paa, _nohq, _smdi — Zeichenketten, die kein MLOD enthält. Sechs von sechs
Artefakten wurden durch diesen einen Test korrekt unterschieden, und er fand auf diesem Rechner ein
defektes Modell, von dem niemand wusste.
Der Blender-Schritt ist optional
asset_export ist das einzige Werkzeug hier, das Blender benötigt, und alles nachgelagerte
funktioniert mit einer .p3d von überall her — einem Hand-Export, einer Datei von einem Partner,
einem vor Jahren eingecheckten Modell. Ein Rechner ohne Blender baut und liefert einen Mod
einwandfrei; die Verweigerung sagt genau das, statt sie als kaputte Installation darzustellen. Es
erfordert jedoch, dass das Export-Add-on im gefundenen Blender aktiviert ist, und es schreibt
niemals Blender-Benutzereinstellungen zurück (verifiziert: Die Einstellungsdatei war nach jedem
Lauf byte-identisch).
Export und Build sind zwei Aufrufe statt einem, weil jede Hälfte ihr eigenes Urteil hat, und ein Build, der von der einen verweigert und von der anderen erlaubt wird, ist keine Entscheidung.
Byte-Gleichheit wird nie versprochen
Keine Hälfte dieser Pipeline ist reproduzierbar, und das Design sagt genau das, statt etwas anderes vorzugeben:
Der Export. Sieben Exporte derselben unveränderten Quelldatei — drei aus einer Sitzung, drei aus einer anderen und einer, der Monate zuvor von Hand in der GUI erstellt wurde — ergaben sieben verschiedene SHA-256-Hashes bei konstanten 334.032 Bytes. Der Unterschied ist die Reihenfolge eines internen Blocks.
binarize. Vier Läufe mit einer unveränderten Eingabe ergaben drei verschiedene Ergebnisse: Die Größe änderte sich um 5 Bytes, und zwei 8-Byte-Fragmente entkamen komprimierten Bereichen.
Ein Modell wird also nie über einen Inhalts-Hash gecacht oder verglichen. Was verglichen wird, ist ein struktureller Fingerabdruck — die Art der Datei, ihre LOD-Anzahl und ihre Menge an Namen. Über alle sieben dieser Exporte hinweg war dieser Fingerabdruck ein einziger Wert.
Die gemessenen Werte
Ein kleines Modell, auf diesem Rechner, durch die Werkzeuge:
Schritt | Ergebnis | Zeit |
| MLOD, 334.032 B, 5 LODs, sauber | 2,1 s (etwa 8 s bei einem Kaltstart) |
| ODOL v55, 58.646 B, 4 LODs, alle fünf C4-Marker | 43,8 s (75,6–78,7 s, gemessen bei vier früheren Läufen) |
| 1 Modell und 10 Texturpaare bewertet | Millisekunden |
| ein PNG zu DXT1, 50.764 B | 0,52 s |
eine Ablehnung bei falscher Wurzel | bevor irgendein Prozess gestartet ist | 0,0003 s |
Beide Logs sind fast vollständig Standardtext, und was stummgeschaltet ist, wird gezählt statt
verworfen: Blenders 169 Zeilen wurden auf 4 reduziert und binarizes 91 auf 6 — eine
dieser sechs war die einzige echte Beschwerde des Modells.
Ende an Ende verkettet reproduzierten der Export und der Build ein Modell, das Monate zuvor von Hand erstellt worden war: gleiche Art, gleiche 4 LODs, dieselben 50 Strings und eine Größe, die ein Byte auseinanderlag.
Was nichts davon beantwortet
Ob das Modell richtig aussieht, richtig skaliert ist, richtig gewickelt ist, eine Kollision hat. Nichts außerhalb des Spiels beantwortet das. C1–C12 verkürzen den Weg dorthin; sie ersetzen ihn nicht.
Bekannte Einschränkungen
Stale-pbo-Erkennung basiert auf der mtime, nicht auf dem Inhalt.
mod_buildlehnt ein frisch gebautes pbo ab, das älter ist als seine Quellen – die übliche Ursache ist ein laufender Server, der die alte Datei noch offen hält, sodass das Packen stillschweigend nichts erzeugt hat. Abergit checkoutändert die Änderungszeit einer Datei, ohne den Inhalt zu ändern; ein einwandfreies pbo, das direkt nach dem Branchwechsel gebaut wurde, kann diese Prüfung daher ebenfalls auslösen. Wennmod_buildunmittelbar nach einem Branchwechsel „stale pbo“ meldet, ist das der wahrscheinliche Grund, kein echter Packungsfehler – neu bauen, dann besteht die Prüfung. Ein ausgereiftes Werkzeug in diesem Bereich ist genau aus diesem Grund auf einen Inhalts-Hash umgestiegen; das ist hier künftige Arbeit, nicht in dieser Phase erledigt (siehepacker.py,pack_one).Ein Mod-Quellordner wird als Ganzes gepackt.
mod_buildweigert sich, einen Mod zu packen, dessen Quellordner etwas enthält, das aufbuild.excludepasst (die Standardliste mit sieben Mustern ist oben aufgeführt), anstatt es stillschweigend in das veröffentlichte pbo zu packen. Es verweigert das Packen unabhängig vonbuild.exclude, wenn die Quelle die eigenen Artefakte dieses Servers enthält – die Signatsschlüssel, die eine oder andere Hälfte des Profils, den Job-Speicher, den vorherigen Build des Mods –, denn sich diese Dateien zu packen veröffentlicht den privaten Signatsschlüssel, und kein Projekt sollte das erst wegkonfigurieren müssen. Standardmäßig wird nicht zuerst eine gefilterte Kopie angelegt: Eine Kopie ist immer neuer als die Quellen und würde die Stale-pbo-Prüfung oben dauerhaft deaktivieren, wenn diese Prüfung die Kopie messen würde.build.stage = truewählt das Kopieren trotzdem – das ist nur sicher, weil der Stale-pbo-Vergleich immer den Original-Quellbaum misst und nie die Kopie. Das ist die Struktur, die ein Mod braucht, dessen Quelle das Repository-Wurzelverzeichnis ist (es enthält immer mindestens.git).Ein Valeur 1 beurteilt das gesamte Log, nicht nur die Zeilen deines Mods.**
log_verdictliest das Log der Instanz, auf die es gerichtet ist. Wenn sich eine Instanz mit anderen Mods geteilt wird, werden deren Warnungen gegen deinexpect.max_warnings-Budget gerechnet und ihre Fehler als Ablehnungsgründe gezählt. Zwei Projekte, die sich einenmachine.stand_rootteilen, sehen die Baseline des jeweils anderen. Entweder bekommt jedes Projekt eine eigene Instanz, oder du setzt das Budget in dem Wissen, was sonst noch geladen ist. Eine projektbezogene Filter, die symmetrisch zuexpect.error_regexist, wäre die offensichtliche Weiterentwicklung eine Filterung, ist aber nicht implementiert.expect.noisekann eine Zeile, die bereits als Fehler zählt, nicht retten. Die Klassifizierung ist geordnetforbid→ crash → error → noise → warning; eine Zeile, dieERRORoderFATAL(oder einen deinerforbid-Strings) enthält, wird also entschieden, bevor noise überhaupt herangezogen wird. Diese Reihenfolge ist absichtlich so – würde zuerst Noise passen, könnte eine harmlose Teilzeichenkette eine fatale Zeile schlucken – aber sie bedeutet, dassnoisenur Warnungen und harmlose Zeilen unterdrücken kann, niemals eine Fehlerklassierung bestzur:client_verdictist ein Fehler-und-Absturz-Verdikt, kein Bereitschafts-Verdikt.[expect]beschreibt das Log des Servers: Dessen Bereitschaftszeile und die Zähler stammen von der serverseitigen Initialisierung eines Mods, undmax_warningsis a Budget, das über dieses selbe Log verklärt. Ein Client-.RPTenthält davon nichts. Diese drei Schlüssel werden hier deshalb bewusst nicht angewandt, und die Antwort listet sie innot_appliedauf.forbid,error_regexundnoisebetreffen den Text einer Logzeile und gelten weiterhin. Es gibt keine client-seitige Bereitschaftszeile zu melden; ob der Client es ins Spiel geschafft hat, wird durch die Spielerzahl beantwortet, auf dieclient_startwartet, nicht durch sein Log.Chat ist vom Gamepad aus nicht erreichbar – und eine Menü-Bestätigung auch nicht. Das Spiel bindet seine Chatzeile ausschließlich an Enter, es gibt keine Bildschirmtastatur; Text ist also entweder eine Bridge-Nachricht (
client_chat, kostenlos) oder echte Tastenanschläge (client_type, kostet den Vordergrund).client_type("", submit=True)sendet allein Enter; so wird die Chatzeile geöffnet – das ist, nach dem obigen Beleg, die einzige Bestätigung, die das Toolset hatgot get.Jede Wissenssuche bezahlt einen Durchlauf durch den Projektbaum. Mit diesem Durchlauf wird bei jeder Antwort die Veraltung der Projektebene gemessen; das ist die eine Eigenschaft, für die der Index überhaupt existiert. Er kostet 3,0 ms bei einem echten 41-Quellen-Mod (der Baum hat etwa 1800 Einträge) und 21 ms auf einem Baum mit 2810 Dateien. Wer das für ein bis zwei Sekunden, entfallen auf den Kosten und stellen genau das Fenster der Stille wieder her, das das Design nicht zulässt; wenn es irgendwann zu teuer wird, muss dieser Kompromiss bewusst eingegangen werden, nicht versehentlich.
Ein Build läuft immer über einen Job, und der Job kostet mehr als ein kleiner Build. Gemessene Durchlaufzeit: 70 – 95 ms bei einem Projekt-Rebuild von 6 ms:
job_waitpollt alle 100 ms. Diese eine Form ist beabsichtigt – ein Aufrufer muss nicht wissen, welcher Build blockiert – und niemand zwingt ihn zu warten, denn die nächste Suche misst die Ebene selbst.Die Abhängigkeitsebene wird gegen das Profil in dessen aktuellen Zustand gemessen. Fügst du einen Mod zu
mods.requiredhinzu, kommen dessen Archive alsadded; entfernst du einen, lauten seine Archivemissing. Das ist die Anforderung (die deklariert Menge gehört zum Aufbau der Ebene), aber es wirkt so, als wäre der Index veraltet, wenn sich in Wirklichkeit das Profil geändert hat.coreenthält immer die Konfigurationen des Spiels, und das ist der größte Teil seiner Kosten. 70 s mit ihnen, gegen circa 4 s für die Scripts allein. Es gibt keinen Schalter: Ohne die Configs lässt sich die Frage „Gibt es eine Item-Klasse X?“ nicht beantworten, und ein zweite Achse würde die Alterungsmessung mehrdeutig machen – der Durchlauf wüsste nicht, ob dieAddons-Archive zu erwarten sind.knowledge_showantwortet die nächste Ebene zuerst. Bei einer Klasse, die eine Abhängigkeit mitmodded classwiedereröffnet, kommt die Deklaration des Mods vor der des eigentlichen Spiels. Das ist die richtige Reihenfolge, aber auch eine überraschende; für die eigene des Spiels übergibt manlayer='core'.Bedingte Kompilierung wird indexiert, nicht aufgelöst. 4,9 % der Scripteilzeichen des Spiels liegen in
#ifdef-Blöcken, darunter auch etwa hundert Klassen-Deklarationen. Dieser Server Treibserver-, Client- und Diagnose-Builds, also gibt es keine einzige korrekte Defines-Menge: Es wird alles indexiert und die Guard-Bedingung an der Deklaration vermerkt. Ein Name kann also gemeldet werden, den ein bestimmter Build ausschließt – die Alternative, nach einer einzigen Schätzung der Defines zu filtern, würde die Existenz von Methoden verleugnen, die im tatsächlichen Build vorhanden sind.Der Fingerabdruck von C12 enthält die Größe, und die Größe von
binarizeist nicht stabil. Das Neubauen eines Modells, das niemand verändert hat, erzeugte ein Artefakt, das ein Byte größer war als das ausgelieferte, mit demselben Typ, der gleichen LOD-Zahl und den gleichen fünfzig Linux-Strings – und a different digest, because size is part of it. Darum kann C12 vor einem Rebuild wahrnehmen das nichts gab. C12 warnt und verweigert nicht – genau aus diesem Grund – und the parts of which it is made are reported last, so can compare be done by hand. The obvious refinement, to then the digest into a stable half and a size, is not done.A partial export warns, not refuses. With the exporter's own default arguments, a model came out with 2 of its 5 LODs and passed every other check. This server does not pass those arguments, so should it actually not happen; but if an object as a LOD is marked and not in the scene is integrated, it counters on one side of the comparison and not on the other, for an which there is a legitimate reason, quindi eine Verweigerung hätte falsche Positive. Sieh dir
E3an.Die Containment-Regel kann nicht jede falsch Wurzel erkennen. It refuses roots that does not have the mod's prefix folder; that is the failure that is measured. A root however, which does contain a folder with this name — for example a repository whose own mod directory is named like the prefix – passes it, and then is that case by C10 or C3/C4 a layer deeper. Measured: With such a root the build refused, then nothing was deployed and the shipped artifact remained, but the refusal came from the job rather than the call.
asset_exportneeds the exporting add-on is enabled in Blender, and cannot install it. Blender is launched with the real settings of the machine owner, because a launch with--withfactory-startupwould cause the add-on disappearing. Its root is kicked other add-ons from the search path for this run (two of the ones installed should reach the network at startup and are supposed to be or the crashes called), which Blender as "Add-on not loaded" into the log – that line is the server's own doing, not a fault.A binarized config has no body to show.
knowledge_show(body=True)reads a declaration back out of the file or archive which is the one index came, but aconfig.bincontains the binary form while the index exists whatCfgConverthas made. The answer says instead of returning nothing.
Install
python -m pip install -e ".[dev]"
python -m pytestRegister it in your MCP client:
{ "mcpServers": { "dayz": { "command": "dayz-mcp" } } }Licence
mit GPL-3.0-or-later. In NOTICE.md see.
Maintenance
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceAn MCP server for Arma Reforger and Enfusion engine modding that enables users to create mods, search API classes, and generate scripts through natural language. It provides a comprehensive suite of tools for scaffolding addons, generating prefabs, and building projects using the Workbench CLI.1,74214
- AlicenseAqualityCmaintenanceMCP server for DayZ Enforce Script that gives AI coding assistants deep knowledge of the DayZ scripting API with semantic search, code validation, class hierarchy, and reverse call graphs.81MIT
- AlicenseAqualityAmaintenanceAn MCP server that empowers AI coding agents to work effectively with Minecraft mod development, providing static analysis of decompiled source code and runtime interaction with a running Minecraft instance.313913MIT
- FlicenseNot gradedqualityCmaintenanceMCP server that helps AI agents inspect Minecraft project evidence (crash logs, mod files, datapacks) before writing development code.3
Related MCP Connectors
An MCP server that gives your AI access to the source code and docs of all public github repos
A MCP server built for developers enabling Git based project management with project and personal…
Augments MCP Server - A comprehensive framework documentation provider for Claude Code
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/covalschi/dayz-agentic-modding-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server