Bin auf der Suche nach Ideen, wie man folgendes macht: Ich möchte eine einfache "Welt" in Java schreiben. Eine, mit der ich später beginnen und dann neue Objekte hinzufügen könnte, um verschiedene Verhaltensweisen zwischen vorhandenen Objekten zu simulieren / zu beobachten. Der Plan ist dann, neuere Objekte zu codieren, nachdem Sie die alten für eine Weile angesehen haben, und sie dann in die bestehende Welt zu laden / fallen zu lassen. Das Problem ist, dass ich die Welt nach dem Start nicht mehr anhalten oder neu starten möchte. Ich möchte, dass sie ein paar Wochen lang ausgeführt wird, aber ich muss Objekte ablegen und sie wiederholen / umschreiben / löschen / erstellen / mutieren können im Laufe der Zeit, ohne einen Neustart zu benötigen. Die Welt könnte so einfach sein wie ein 100 x 100-Array von X / Y-Standorten, mit einer möglichen GUI mit gekachelten Karten, um die Welt visuell darzustellen. Ich weiß, ich brauche eine Art Ticktimer-Prozess, um Objekte zu überwachen und jedem eine Chance zum Handeln zu geben.
Beispiel: Ich verschlüssele World.java am Montag und lasse es laufen. Dann schreibe ich am Dienstag eine neue Klasse namens Rock.java (die sich nicht bewegt). Ich lade / lasse es dann (irgendwie?) In diese bereits laufende Welt (die es einfach irgendwo zufällig in der Weltmatrix ablegt und sich nie bewegt). Dann erstelle ich am Mittwoch eine neue Klasse mit dem Namen Cat.java und lasse diese in die Welt fallen, wieder zufällig platziert, aber dieses neue Objekt kann sich über einen gewissen Zeitraum um die Welt bewegen. Am Donnerstag schreibe ich dann eine Klasse mit dem Namen Dog. Java, das sich ebenfalls bewegt, aber auf ein anderes Objekt "einwirken" kann, wenn es sich am Nachbarort befindet und umgekehrt.
Hier ist das Ding. Ich weiß nicht, welche Art von Struktur / Design ich benötigen würde, um die tatsächliche Weltklasse zu codieren, um zu wissen, wie zukünftige (und derzeit nicht vorhandene) Objekte erkannt / geladen / verfolgt werden.
Irgendwelche Ideen, wie Sie so etwas mit Java machen würden?
Antworten:
Was Sie im Grunde suchen, ist ein Hot-Plug-System. Sie führen eine Hauptanwendung aus und fügen dann zur Laufzeit Plug-Ins hinzu, die in die Ereignisschleife integriert werden. Überlegen Sie sich zunächst, was Ihre Welt von einer Spieleinheit erwartet. Zum Beispiel (basierend auf Ihrer Beschreibung):
Natürlich können Sie auch andere Methoden hinzufügen, die Sie für notwendig halten. Notieren Sie den Parameter World mit den beiden relevanten Methoden. Dies ermöglicht Ihrer neuen Entität, die Welt beim Einrichten oder Aktualisieren zu berücksichtigen. In Ihrer Hundeklasse können Sie zum Beispiel die Welt nach allen Katzen in der Nachbarschaft fragen. Als Nächstes erstellen Sie Ihre Welt, die mit dieser Schnittstelle und einem System zum dynamischen Kompilieren und Laden von Java-Code funktioniert. Ein Beispiel dafür finden Sie hier .
Rufen Sie diese Methode über die Welt-GUI auf, um neue Entitäten hinzuzufügen. Abhängig von Ihrer World-Implementierung kann eine Entity-Init-Funktion folgendermaßen aussehen:
quelle
Wir haben so etwas in Stendhal für Razzien gemacht.
Neustarts wollten wir nicht ganz vermeiden. Änderungen an unseren Kerninfrastrukturdiensten wie der Client / Server-Kommunikation erfordern daher einen Neustart. Das Hinzufügen von Entitäten, Kreaturen und NPCs sowie das Ändern vorhandener Objekte funktioniert jedoch. (Oh, und manchmal kann die Reflexion zur Behebung von Live-Fehlern verwendet werden, um sogar private Felder zu manipulieren.)
Da wir nicht nur ein neues Objekt basierend auf neuen Daten (wie ein anderes Skin) wollen, sondern auch neues Verhalten hinzufügen wollen, muss das Weltprogramm in der Lage sein, neue Klassendateien zu laden . Wir nennen sie "Skripte", aber es handelt sich um echte kompilierte Java-Klassen. Diese Klassen implementieren die Script.java- Schnittstelle.
Maria.java ist ein einfaches Beispiel. Sie ist ein neuer NPC, der Getränke und Essen an Spieler verkauft. Wir können dort auch sehr komplexe Objekte definieren .
Eine neue Klasse wird folgendermaßen geladen:
Wenn Sie eindeutige Namen sicherstellen können und keine Klassen mehr entladen möchten, sind Sie mit der Arbeit auf niedriger Ebene fertig.
Das Entladen scheint jedoch ziemlich wichtig zu sein. Um dies zu erreichen, müssen Sie immer dann ein neues Klassenladeprogramm instanziieren, wenn Sie neuen Code einfügen möchten. Damit der GC seine Arbeit erledigen kann, nachdem der letzte Verweis auf diesen Code gelöscht wurde.
Wir haben den Befehl / unload , der eine Entlademethode in unserer Schnittstelle aufruft, damit Skripte bereinigt werden können. Das eigentliche Entladen erfolgt automatisch durch den GC.
Bei Überfällen erstellen wir häufig viele temporäre Objekte . Und wir möchten, dass alle von ihnen entfernt werden, nachdem der Überfall beendet ist. Zum Beispiel verwenden wir den Gnome-Raid, der eine Reihe von Gnomen in der Nähe des unsichtbaren Administrators erzeugt, diesen Code: GnomeRaid.java erweitert CreateRaid.java .
Das Skript könnte direkt auf die Welt zugreifen (wie das erste Beispiel zeigt) und seine eigene Bereinigung in der Methode unload () durchführen. Java-Codierer werden jedoch nicht zum Aufräumen verwendet, und es ist ärgerlich. Deshalb haben wir eine Sandbox erstellt , die von Skripten verwendet werden kann. Beim Entladen werden alle Objekte entfernt, die der Welt über die Sandbox-Klasse hinzugefügt wurden.
quelle
Rette die Welt (kein Wortspiel beabsichtigt) und all ihren Zustand (Positionen, Geschwindigkeiten, alle Variablen).
Dies ist jedoch eine allgemeine Lösung. Ich möchte nicht wissen, ob Sie Codeblöcke und -klassen dynamisch implementieren können, wie Sie es sich erhoffen ...
Option 2 besteht darin, eine Skriptsprache zu binden, die im laufenden Betrieb geladen werden kann.
quelle
Für Java benötigen Sie lediglich eine OSGi-Plattform . Damit ist es einfach, Module oder Anwendungen im laufenden Betrieb auszutauschen und sogar Remote-Management oder Teil-Upgrades durchzuführen.
quelle