1 Punkte von GN⁺ 2024-12-27 | 1 Kommentare | Auf WhatsApp teilen
  • CobolCraft ist ein in COBOL implementierter Minecraft-Server und unterstützt die zum Zeitpunkt der Erstellung aktuelle Version Minecraft 1.21.4
  • Bereits implementiert sind unendliche Terrain-Generierung, dynamisches Chunk-Loading, Speichern von Welt- und Spielerdaten auf der Festplatte, Import bestehender Welten, Multiplayer, Serverstatusanzeige, Abbauen und Platzieren von Blöcken, Inventar, Crafting, Aufheben von Items, Chat, Befehle und mehr
  • Blöcke mit mehreren Zuständen, Richtungen und Interaktionen benötigen für korrektes Verhalten viel spezifischen Code; viele Blöcke werden noch nicht unterstützt
  • Entwickelt wurde es mit GnuCOBOL unter Linux x86_64 oder arm64; Deployment per Docker ist ebenfalls möglich, Unterstützung für andere Betriebssysteme wie Windows wurde jedoch nicht getestet
  • JSON-Daten werden aus dem Standard-datapack von Minecraft sowie aus den offiziellen Server- und Client-.jar-Dateien extrahiert und beim Kompilieren zur COBOL-Codegenerierung sowie zur Laufzeit zum Laden von Daten verwendet

Von CobolCraft implementierte Minecraft-Server-Funktionen

  • CobolCraft ist ein in COBOL geschriebener Minecraft-Server und unterstützt Minecraft 1.21.4
  • Zu den implementierten Funktionen gehören:
    • unendliche Terrain-Generierung und dynamisches Chunk-Loading
    • Speichern von Welt- und Spielerdaten auf der Festplatte
    • Unterstützung für Minecraft-Dateiformate und Import bestehender Welten
    • Multiplayer mit konfigurierbarer Anzahl gleichzeitig verbundener Spieler
    • Ping/Server Status, damit der Server in der Serverliste als online erscheint
    • Abbauen und Platzieren von Blöcken sowie automatisch generierter Loot-Table-Code
    • Blockinteraktionen per Rechtsklick
    • Spielerinventar
    • 2x2- und 3x3-Crafting
    • Item-Entities und Aufheben von Items
    • Chat
    • In-Game-Befehle und interaktive Konsolenbefehle
    • Konfiguration über server.properties
    • persistente Whitelist, gespeichert in whitelist.json
    • sehr grundlegende Block-/Spieler-Kollision und Entity-Physik
    • Fallschaden, Void-Schaden, Tod und Respawn

Umfang und Grenzen der Blockunterstützung

  • Blöcke mit mehreren Zuständen, Richtungen und Interaktionen benötigen für korrektes Verhalten viel spezialisierten Code
  • Viele Blöcke werden noch nicht unterstützt
  • Zu den funktionierenden Blöcken gehören:
    • torches
    • slabs
    • stairs
    • rotated pillars wie logs
    • nicht interaktive buttons
    • doors
    • trapdoors
    • beds
    • signs

Build- und Laufzeitumgebung

  • CobolCraft wurde mit GnuCOBOL entwickelt und ist für die Ausführung unter Linux vorgesehen
    • Zielarchitekturen sind x86_64 und arm64
    • Unterstützung für andere Betriebssysteme wie Windows wurde nicht getestet
    • Mit Docker ist ein plattformunabhängiges Deployment möglich
  • Für eine Linux-Distribution werden folgende Komponenten benötigt:
    • GnuCOBOL 3.1.2 oder neuer
    • aus Performancegründen wird GnuCOBOL 3.2 oder neuer empfohlen
    • make
    • gcc, g++
    • zlib
    • curl zum Herunterladen der offiziellen Server-.jar
    • Java 21 oder neuer zum Extrahieren von Daten aus der Server-.jar
  • Build- und Ausführungsbefehle:
make --jobs=$(nproc)
make run
  • Das Docker-Hub-Image kann verwendet oder das Image selbst gebaut und ausgeführt werden
docker pull meyfa/cobolcraft:latest

git clone https://github.com/meyfa/CobolCraft.git cobolcraft && cd cobolcraft
docker build --tag meyfa/cobolcraft .

Serverkonfiguration und Netzwerkzugriff

  • Die Serverkonfiguration erfolgt durch Bearbeiten der Datei server.properties
  • Diese Datei wird beim ersten Start automatisch mit den Standardwerten aller unterstützten Optionen erzeugt
    • server-port: Standardwert 25565
    • level-name: Standardwert "world"
    • white-list: Standardwert false
    • motd: Standardwert "CobolCraft"
    • max-players: Standardwert 10, maximal 100
  • Standardmäßig ist der Server nur vom eigenen System über localhost:25565 erreichbar
  • Um ihn von außen zugänglich zu machen, etwa über lokales Netzwerk, VPN, Port-Forwarding oder einen gemieteten Server, kann der Port beim Docker-Start an 0.0.0.0:25565:25565 gebunden werden
docker run --rm -it -p 0.0.0.0:25565:25565 meyfa/cobolcraft

Warum ein Minecraft-Server in COBOL gebaut wurde

  • Der Entwickler hatte zuvor keinerlei COBOL-Erfahrung, wollte die Sprache aber wegen der Gerüchte und des Stigmas rund um COBOL besser kennenlernen
  • Als beste Methode zum Lernen einer Sprache wählte er, selbst etwas zu schreiben
  • Wegen der Komplexität und Größe des Minecraft-Codes bewertet er die Entscheidung, einen Minecraft-Server in COBOL zu schreiben, zugleich als gute und schlechte Idee
  • Aufgaben, die in anderen Sprachen einfach sind, mussten von Grund auf erstellt werden:
    • JSON-Parsing und -Encoding
    • Verarbeitung verschiedener Arten binärer Daten
    • Echtzeit-Multiplayer-Networking
    • Übertragung der objektorientierten Minecraft-Systeme in eine prozedurale Sprache
  • Die steile Lernkurve führte dazu, dass er COBOL und seine Konzepte gründlich untersuchte und verstand; diesen Prozess bezeichnet er als lohnend
  • Für COBOL-Einsteiger empfiehlt er den GnuCOBOL Programmer's Guide
  • Als Lernmaterial zum Minecraft-Protokoll eignet sich die wiki.vg documentation
  • Je nach Fall kann es auch helfen, mit Tools wie Wireguard den tatsächlichen Server-Traffic anzusehen, um den Informationsfluss zu verstehen

Quellcode-Struktur und ausführbares Binary

  • Der COBOL-Quellcode befindet sich hauptsächlich im Verzeichnis src/
    • src/main.cob ist der Einstiegspunkt
    • src/server.cob enthält den Code zum Starten des Servers und die Spiellogik
  • Das Verzeichnis codegen/ enthält den in COBOL geschriebenen Codegenerator
    • Er erzeugt zusätzlichen Quellcode aus JSON-Daten wie dem Standard-datapack von Minecraft
  • Das Verzeichnis cpp/ enthält C++-Quellcode für Betriebssystem-Integration, die in COBOL schwer umzusetzen ist
    • Low-Level-Verwaltung von TCP-Sockets
    • präzises Timing
    • Behandlung von Prozesssignalen
  • Sämtlicher COBOL- und C++-Quellcode wird zu einem einzigen cobolcraft-Binary kompiliert

Extraktion von Minecraft-Daten und JSON-Verarbeitung

  • Die offiziellen Server- und Client-Anwendungen der Minecraft Java Edition enthalten viele Daten
    • Blöcke, Items, Entity-Typen
    • biomes
    • Paket-Protocol-IDs
    • tags, etwa Blöcke, die mit einer Spitzhacke abgebaut werden können
    • recipes
    • loot tables, die angeben, welche Items unter welchen Bedingungen beim Abbauen eines Blocks droppen
  • Das Makefile von CobolCraft enthält Targets zum Herunterladen der offiziellen .jar und zum Extrahieren der Daten als JSON
  • Die extrahierten JSON-Daten werden auf zwei Arten verwendet:
    • automatische Generierung von COBOL-Code, etwa für Block-Loot-Tables, zur Kompilierzeit
    • Laden von Daten in den Speicher zur Laufzeit
  • Beide Aufgaben verwenden einen in COBOL geschriebenen und per Unit Tests geprüften universellen JSON-Parser

Tests und Updates

  • Unit Tests befinden sich im Verzeichnis tests/
  • Die Tests verwenden ein copybook-basiertes eigenes Test-Framework
    • Es verfolgt Test-Suites, Units und Assertions
    • Am Ende der Ausführung liefert es eine Zusammenfassung
  • Der Befehl zum Ausführen der Tests lautet make test
  • Das Hauptziel der Tests ist die Verifikation von Bereichen, die schwer zu debuggen sind, etwa JSON- und binäres Daten-Encoding und -Decoding
  • Tests der eigentlichen Spiellogik werden als entsprechend weniger wichtig angesehen
  • Die Schritte zum Aktualisieren des Servers auf eine neue Minecraft-Version und die Testschritte stehen in Updating.md

Lizenz und Marken

  • CobolCraft wird unter der MIT License veröffentlicht
  • „Minecraft“ ist eine Marke von Mojang Synergies AB
  • CobolCraft ist nicht mit Mojang verbunden und wird nicht von Mojang unterstützt

1 Kommentare

 
GN⁺ 2024-12-27
Hacker-News-Kommentare
  • Es gibt viele Gerüchte und Stigmata rund um COBOL; es wäre schön, wenn jemand aufschreiben würde, welche Einsichten er tatsächlich gewonnen hat.
    Ich kenne auch nur solche Geschichten und bin neugierig, worauf ein COBOL-Einsteiger gestoßen ist, als er ein ziemlich komplexes erstes Projekt umgesetzt hat.

    • Es gibt das halb scherzhafte Stigma, dass die objektorientierte Variante von COBOL den sperrigen Namen ADD ONE TO COBOL YIELDING COBOL trägt.
      Immerhin ignorierte es nicht wie altes FORTRAN Leerzeichen, sodass DO 10 I=1.10 nicht als Syntaxfehler in einer Schleife auffiel, sondern still als Zuweisung DO10I = 1.10 kompiliert wurde. Gemeint war wohl DO 10 I=1,10.
    • Solche Einsichten finde ich gut.
      Falls es dich interessiert: Hier sind Erkenntnisse aus dem Bau eines Compilers von COBOL nach C#: https://github.com/otterkit/otterkit-cobol/issues/40
      Inzwischen bin ich überzeugt: COBOL ist nur ein High-Level-Assembler.
  • Wirklich großartig.
    Für mein Abschlussprojekt an der Highschool habe ich ein komplettes COBOL-System gebaut, das Quoten für Fußballwetten automatisierte. Die Technik war schon damals überholt, aber die Schule war noch nicht auf der Höhe der Zeit.
    Es war absurd unpassend, aber ich mochte jede einzelne Zeile. Eine Sprache, die dir bei jedem Tippen „Erinnerst du dich an Lochkarten?“ zuflüstert, hat etwas seltsam Befriedigendes.

    • Dass du für ein Highschool-Projekt GROSSGESCHRIEBENES COBOL verwendet hast, passt zeitlich wirklich perfekt. Das dürfte eine großartige Highschool-Erinnerung geworden sein. Ich hoffe, du hast alle Variablennamen nach griechischen Göttern benannt.
  • Vielleicht täusche ich mich, aber ich habe das Gefühl, dass man recht oft kleine, beeindruckende Nebenprojekte sieht, die in einfachen, schlichten Sprachen wie C oder hier COBOL geschrieben sind.
    Umgekehrt scheinen ähnliche Rust-Projekte oft etwa zehnmal so viele Codezeilen zu haben und trotzdem kaum zu funktionieren.
    Meine Hypothese ist, dass einfache Sprachen es leichter machen, eine Idee schnell wie einen Bauplan festzuhalten und auch mit einer schmutzigen Codebasis erst einmal etwas zum Laufen zu bringen. Moderne Sprachen dagegen zwingen einen, Code zu schreiben, der länger Bestand hat. Oder vielleicht machen moderne Sprachen auch irgendetwas falsch.

    • Ein Minecraft-Server ist genau genommen kein kleines Nebenprojekt.
      Es gibt Server, die seit 3–5 Jahren entwickelt werden und immer noch nicht fertig sind, und andere wie https://github.com/MCHPR/MCHPRS, die sich für Redstone-Demonstrationen auf bestimmte Funktionen konzentrieren.
      Dieser COBOL-Server hat die Beleuchtungsverarbeitung noch nicht implementiert, und die Mob-Erzeugung hängt ebenfalls davon ab; das ist also einer der schwierigsten Teile. Einige Blöcke sind auch noch nicht vollständig umgesetzt. Um einen Minecraft-Server fertigzustellen, braucht man Jahre; schnell etwas zu bauen ist also nicht immer der beste Weg.
    • Ich glaube nicht, dass das unbedingt eine Täuschung ist.
      Ich arbeite an zwei Spielen in Rust, und wenn man die passende Engine wählt, war ein wirklich minimaler Gameplay-Prototyp ziemlich einfach. Aber je mehr Funktionen dazukamen, desto stärker blähte sich der Code auf, und die Umstellung von Singleplayer auf Multiplayer war ein Chaos. Ich habe auch Zeit damit verschwendet, Trends zu folgen und sie später wieder zu entfernen.
      Rust mag komplex vernetzte Graphstrukturen von Spielobjekten wirklich nicht. Jedes Mal, wenn ein Spielereignis Aktualisierungen mehrerer Typen auslöst, entsteht Reibung. Eine Möglichkeit wäre gewesen, das einfach zu akzeptieren und etwas mehr Code zu schreiben; eine andere, schon früh mehr Code zu schreiben, um eine systematische Lösung zu finden, die später Zeit spart.
      Ich habe mich für Letzteres entschieden und ein paar Experimente gemacht, aber der Break-even-Punkt wirkt für kleine Projekte mit einer Person viel zu weit entfernt.
      Selbst innerhalb derselben Sprache können die Unterschiede mehr als eine Größenordnung betragen. In Rust gibt es zwei brauchbare 3D-Engines: Eine ist bekannt, hat viele Contributors und erhält Sponsoring, das ein Bay-Area-Gehalt ersetzen könnte. Die andere wird fast von einer einzelnen Person gebaut, die entweder von Ersparnissen lebt oder abwechselnd Vollzeit arbeitet.
      Trotzdem konzentriert sich die erste Engine stark auf PR, verspricht seit Jahren viele Funktionen und hat wenig vorzuweisen, während die zweite sowohl bei der Anzahl der Funktionen als auch bei der Implementierungsqualität vorn liegt.
      Am Ende ist es meiner Meinung nach eine Frage der Haltung. Es gibt Leute, die zum Spaß coden, Leute mit klaren Zielen, die auf deren Umsetzung fokussiert sind, Leute, die es wegen des Geldes tun, und Leute, die von öffentlicher Anerkennung angezogen werden. Eine schmutzige Codebasis ist nicht zwingend nötig, aber es gibt eine produktive Mitte. Wer stärker auf Selbstdarstellung fokussiert ist, jagt eher Trends und glänzender Architektur hinterher.
    • Rust hat sich im Game Development ziemlich schwergetan, den Durchbruch zu finden.
      Die Grundannahme von Rust ist, Entwicklungsgeschwindigkeit und Flexibilität gegen Speichersicherheit einzutauschen; im Game Development hat sich aber gezeigt, dass Entwicklungsgeschwindigkeit und Flexibilität sehr viel wichtiger sind als Speichersicherheit.
      Wenn man an einem formal spezifizierten Microkernel arbeitet, dessen Details schon bis ins Kleinste durchgeplant sind, kann Rust eine ausgezeichnete Wahl sein. Wenn man dagegen schnell Schlamm an die Wand werfen muss, um zu sehen, was zu spaßigem Gameplay wird, macht Rust diesen Prozess schwerer als fast jede andere Sprache, ohne dass der Nutzen klar wäre. Am Ende hat man nur ein schnelleres, schmutziges Gameplay-Stück, dessen Erstellung länger gedauert hat und das etwas speichersicherer ist.
      Ich bin nicht der Einzige, der nach Game Development mit Rust diesem Einsatzgebiet klar den Rücken gekehrt hat. Zum Beispiel gibt es „Leaving Rust gamedev after 3 years“ [0], einen der bislang meistdiskutierten und am häufigsten gelikten Rust-bezogenen Beiträge auf Hacker News.
      Allgemeiner gesagt ist offensichtlich, dass Rust viel stärker gehypt wird als Cobol. Deshalb gibt es viele Beispiele von Entwicklern, die für Hypes anfällig sind – meist begeisterte Anfänger –, die sich mutig an Open-Source- oder Hobbyprojekte in Rust gewagt haben. Einen Minecraft-Server in Cobol zu schreiben, erfordert dagegen etwas mehr Eigenwilligkeit und Mut, was im Allgemeinen eher mit mehr Erfahrung einhergeht.
      [0] https://news.ycombinator.com/item?id=40172033
    • Am Ende wirkt es wie der Unterschied zwischen echten Hackern™, die einfache Sprachen mögen und mit allem, was man ihnen gibt, ein ganzes Universum erschaffen, und Code-Monkeys, die dem neuesten Trend hinterherlaufen.
      Zur Einordnung: Ich zähle mich selbst zur zweiten Gruppe.
    • Leute, die Dinge fertigbekommen, kümmern sich normalerweise nicht allzu sehr um Codequalität.
      Ich war irgendwann an dem Punkt, dass ich versuchte, Code zu schreiben, der lange Bestand hat, und dadurch gar nichts mehr fertigbekam. Über die Jahre habe ich ein Gleichgewicht gefunden und gelernt, dass sich Müllcode durch iterative Verbesserung letztlich in etwas Ordentliches verwandelt; seitdem mache ich es so.
  • https://raw.githubusercontent.com/meyfa/CobolCraft/main/src/...
    Für jemanden mit Hintergrund in prozeduralen Sprachen ist das tatsächlich nicht allzu schwer zu verstehen, und es erinnert ein wenig an in VB geschriebene Game-Server, die ich vor etwa 20 Jahren gesehen habe.

  • Seit ich 1978 aufgehört habe, COBOL zu verwenden, habe ich auch nie wieder zugegeben, diese Sprache zu kennen.
    Ich hoffe, ich sehe mir diesen Code nicht an, bekreuzige mich und gehe einen starken Kaffee trinken :-)
    Trotzdem ist es beeindruckend, dass das gelungen ist.

  • Man kann sich darüber lustig machen, aber der Code ist ziemlich gut lesbar.
    Das steht im Gegensatz zu manchen modernen Sprachen, bei denen man minutenlang hinschauen muss, um zu verstehen, was passiert.

    • Ich habe einmal bei einem FAANG-Unternehmen gearbeitet und hatte Zugriff auf weltweit führende C++-Experten. Einige von ihnen waren in internationalen Sprachstandardisierungsgremien.
      Ich fragte auf einer internen C++-Liste, ob eine bestimmte Codezeile ein Memory Leak erzeugen würde; es war Code, der rein STL-Templates und Typumwandlungen verwendete. Aber die Experten konnten sich nicht darauf einigen, ob ich es richtig machte. Einige meinten, es würde ein Leak geben, andere sahen das nicht so.
      Diese kleine wahre Geschichte sagt viel über C++ aus. JavaScript ist ebenfalls voll von solchen Dingen.
    • Das war die Stärke von COBOL.
      Ich begann 1976 mit dem Programmieren, lernte COBOL und ICL PLAN, nutzte erst Lochkarten und nach Abschluss der Ausbildung Terminals. Die Programme waren zu 100 % Batch-Programme.
      Es gab eine sehr starke Ausrichtung auf Lesbarkeit, damit jeder den Quellcode lesen und verstehen konnte. Allerdings wurde diese Lesbarkeit teilweise dadurch relativiert, dass man die Core Dumps lesen und verstehen musste, die erzeugt wurden, wenn ein Programm fehlschlug. Im besten Fall konnte man den Fehler bis zu einer bestimmten Codezeile zurückverfolgen, und deshalb wurde es zur Gewohnheit, Programme im Kopf auszuführen.
      Auch als ich die Regierungsbehörde verließ und in die kommerzielle Programmierung wechselte, waren es bis in die frühen 80er weiterhin COBOL und Batch-Programme. Ich machte drei Jahre lang Nachtsupport, und da zeigte sich der Wert von COBOL. Selbst wenn ich ein mir unbekanntes Listing und einen Core Dump in die Hand bekam, konnte ich das Problem meistens recht schnell beheben. Natürlich immer unter dem Vorbehalt, dass es eine taktische Korrektur war.
    • Deshalb mag ich Ada und VHDL.
      Sie können zwar etwas ausführlich sein, sind aber deutlich leichter zu lesen als „modernere“ Sprachen.
    • COBOL wurde so entworfen, dass auch Nicht-Programmierer es schreiben und lesen können.
      Zumindest in der Theorie war das so.
    • MOVE FUNCTION MIN(BLOCK-ENTRY-MINIMUM-STATE-ID(LK-BLOCK), STATE-ID) TO BLOCK-ENTRY-MINIMUM-STATE-ID(LK-BLOCK)
  • In der Highschool habe ich in einer kleinen Stadt in Pakistan ein wenig COBOL gelernt.
    Es war nicht schlecht, und ich machte ein Projekt, das Jahresabschlüsse nachahmte. Es hatte seine seltsamen Seiten, aber für die meisten Menschen, also Nicht-Programmierer, dürfte jede Programmiersprache ziemlich seltsam wirken; daher verstehe ich das Stigma rund um COBOL nicht so recht.
    Zur gleichen Zeit lernte ich auch C, und das ist geblieben :-)

  • Ich höre immer wieder, dass Cobol-Programmierer selten sind und deshalb hohe Gehälter bekommen.
    Ich frage mich, ob wegen dieses Projekts die Jobangebote nur so hereingekommen sind.

    • Selten sind nicht Cobol-Programmierer, sondern Menschen, die die Geschäftslogik verstehen.
      Cobol wird häufig in sehr komplexen Geschäftsabläufen eingesetzt.
    • Wie andere gesagt haben, geht es eher um die Komplexität der bestehenden Geschäftslogik und um das Verständnis der Mainframe-Systeme, auf denen dieser Code normalerweise läuft.
      Sonst hätte man einfach einen Cross-Compiler gebaut und wäre fertig gewesen.
    • Solche Leute sind nicht wegen ihrer Programmierfähigkeiten wertvoll, sondern wegen ihres Wissens über sehr komplexe, meist undokumentierte Systeme und deren fachliches Umfeld.
  • COBOL sieht tatsächlich nach einer ziemlich coolen Sprache aus.
    Der Code ist auch wirklich gut organisiert.

  • Mir gefällt, dass es Unit-Tests gibt.