Ich habe ein Online-Spiel, in dem die Spieler die Welt auf irgendeine Weise gestalten können - z. Das Gehäuse von Ultima Online, in dem Sie Ihre Häuser direkt auf bestimmten Teilen der Weltkarte bauen können. Dies sind Veränderungen, die im Laufe der Zeit als Teil der beständigen Welt fortbestehen sollten.
Gleichzeitig fügt das Designteam neue Inhalte hinzu und ändert alte Inhalte, um das Spiel für neue Spieler zu verbessern und zu erweitern. Sie tun dies zuerst während des Testens auf einem Entwicklungsserver und müssen dann später ihre Arbeit mit der "Arbeit" der Spieler auf dem Live-Server zusammenführen.
Angenommen, wir beheben die Probleme mit dem Spieldesign - z. Spieler können nur in bestimmten Bereichen bauen, sodass sie niemals geografisch mit Designer-Bearbeitungen in Konflikt geraten. Was sind gute Möglichkeiten, um mit den Daten umzugehen oder die Datenstrukturen so anzuordnen, dass Konflikte vermieden werden, wenn neue Designer-Daten mit neuen Player-Daten zusammengeführt werden?
Beispiel 1: Ein Spieler stellt einen neuen Gegenstandstyp her und das Spiel weist ihm die ID 123456 zu. Alle Exemplare dieses Gegenstands beziehen sich auf 123456. Stellen Sie sich nun vor, die Spieleentwickler haben ein ähnliches System, und ein Entwickler erstellt einen neuen Gegenstand mit der Nummer 123456. Wie kann dies vermieden werden?
Beispiel 2: Jemand macht einen beliebten Mod, der all Ihren Drachen einen französischen Akzent verleiht. Es enthält ein Skript mit einem neuen Objekt namens, mit assignFrenchAccent
dem die neuen Sprachelemente jedem Drachenobjekt zugewiesen werden. Aber Sie sind dabei, Ihren "Napoleon vs Smaug" -DLC bereitzustellen, der ein Objekt mit dem gleichen Namen hat - wie können Sie dies ohne viele Kundendienstprobleme tun?
Ich habe mir folgende Strategien überlegt:
- Sie können 2 separate Dateien / Verzeichnisse / Datenbanken verwenden, aber dann sind Ihre Lesevorgänge erheblich kompliziert. "Show All Items" muss einen Lesevorgang in der Designer-Datenbank und einen Lesevorgang in der Player-Datenbank ausführen (und muss trotzdem irgendwie zwischen den beiden unterscheiden.)
- Sie können 2 verschiedene Namespaces in einem Geschäft verwenden, z. Das Verwenden von Zeichenfolgen als Primärschlüssel und das Präfixieren mit "DESIGN:" oder "PLAYER:", das Erstellen dieser Namespaces ist jedoch möglicherweise nicht trivial und die Abhängigkeiten sind nicht klar. (In einem RDBMS können Sie möglicherweise Zeichenfolgen nicht effizient als Primärschlüssel verwenden. Sie können Ganzzahlen verwenden und alle Primärschlüssel unter einer bestimmten Zahl, z. B. 1 Million, als Designdaten und alle darüber liegenden Werte zuweisen Spielerdaten. Diese Informationen sind jedoch für das RDBMS nicht sichtbar, und Fremdschlüsselverknüpfungen überschreiten die „Kluft“.
- Sie können immer in Echtzeit an derselben gemeinsam genutzten Datenbank arbeiten, die Leistung ist jedoch möglicherweise schlecht und das Risiko einer Beschädigung der Spielerdaten ist möglicherweise erhöht. Es gilt auch nicht für Spiele, die auf mehr als einem Server mit unterschiedlichen Weltdaten ausgeführt werden.
- ... noch andere Ideen?
Mir fällt ein, dass dies zwar in erster Linie ein Problem für Online-Spiele ist, die Konzepte jedoch möglicherweise auch für Modding gelten, bei dem die Community Mods zur gleichen Zeit erstellt, in der die Entwickler ihr Spiel patchen. Werden hier Strategien angewendet, um die Wahrscheinlichkeit des Abbrechens von Mods zu verringern, wenn neue Patches veröffentlicht werden?
Ich habe dies auch als "Versionskontrolle" getaggt, da dies auf einer Ebene genau das ist - zwei Zweige der Datenentwicklung, die zusammengeführt werden müssen. Vielleicht könnten einige Erkenntnisse aus dieser Richtung kommen.
BEARBEITEN - Einige Beispiele wurden hinzugefügt, um das Problem zu klären. Ich beginne zu glauben, dass es sich wirklich um einen Namensraum handelt, der über zusammengesetzte Schlüssel in einem Geschäft implementiert werden könnte. Das vereinfacht zumindest die Merge-Strategie. Aber es kann Alternativen geben, die ich nicht sehe.
quelle
Antworten:
Ich denke, die Antworten, die DB-Lösungen vorschlagen, springen zu einer bestimmten Implementierung, ohne das Problem zu verstehen. Datenbanken machen das Zusammenführen nicht einfach, sondern bieten lediglich einen Rahmen zum Speichern Ihrer Daten. Ein Konflikt ist immer noch ein Konflikt, auch wenn er sich in einer Datenbank befindet. Und das Auschecken ist die Lösung des Problems für einen armen Mann - es wird funktionieren, aber zu einem lähmenden Preis für Ihre Benutzerfreundlichkeit.
Was Sie hier sagen, fällt in das verteilte Entwicklungsmodell des Problems. Der erste Schritt besteht meiner Meinung nach darin, Player und Designer nicht als separate Arten von Inhaltserstellern zu betrachten. Dadurch wird eine künstliche Dimension Ihres Problems entfernt, die die Lösung nicht beeinträchtigt.
Tatsächlich haben Sie Ihre Hauptlinie - die kanonische, vom Entwickler genehmigte Version. Möglicherweise haben Sie (wahrscheinlich) auch andere Zweige - Live-Server, auf denen Leute Mods entwickeln und gemeinsam nutzen. Inhalte können in jedem Zweig hinzugefügt werden. Entscheidend ist, dass Ihre Designer hier nichts Besonderes sind - sie sind nur zufällige Inhaltsschöpfer, die im eigenen Haus leben (und Sie können sie finden und treffen, wenn sie versauen).
Das Akzeptieren von benutzerdefinierten Inhalten ist dann ein Standardproblem beim Zusammenführen. Sie müssen entweder ihre Änderungen zurück auf die Hauptlinie ziehen, zusammenführen und dann erneut verschieben oder die Hauptlinienänderungen auf ihren Zweig ziehen und zusammenführen (sodass die Hauptlinie von benutzergenerierten Inhalten 'sauber' bleibt). Wie üblich ist es freundlicher, zu Ihrem Zweig zu ziehen und dort zu reparieren, als andere Leute zu bitten, Ihre Änderungen zu übernehmen und dann zu versuchen, sie an ihrem Ende aus der Ferne zu reparieren.
Sobald Sie mit einem solchen Modell arbeiten, gelten alle normalen Prozesse zur Vermeidung von Zusammenführungskonflikten. Einige der offensichtlicheren:
quelle
Speichern Sie alles als Attribut (oder Dekorator) - mit Einhängepunkten. Nehmen wir ein Haus, das der Spieler als Beispiel entworfen hat:
So kann jede Entität einen oder mehrere Einhängepunkte haben - jeder Einhängepunkt kann keine oder mehrere andere Komponenten aufnehmen. Diese Daten würden mit der Version gespeichert, in der sie gespeichert wurden, zusammen mit den relevanten Eigenschaften (wie Verschiebung usw. in meinem Beispiel). - NoSQL würde hier wahrscheinlich eine gute Anpassung finden (Schlüssel = Entitäts-ID, Wert = Serialisierte Binärdatei) Daten).
Jede Komponente müsste dann in der Lage sein, alte Daten aus einer früheren Version zu aktualisieren (niemals Felder aus serialisierten Daten entfernen - nur 'null') - diese Aktualisierung erfolgt in dem Moment, in dem sie geladen wird (sie würde dann sofort wieder in gespeichert werden) die neueste verfügbare Version). Nehmen wir an, unser Haus hat seine Maße geändert. Der Upgrade-Code würde den Abstand zwischen der Nord- und Südwand relativ berechnen und die Verschiebungen aller enthaltenen Entitäten proportional ändern. Als weiteres Beispiel könnte in unserer Fleischschüssel das Feld "Essen" entfernt werden und stattdessen "Vielfalt" (Fleisch) und "Rezept" (Bällchen) angezeigt werden. Das Upgrade-Skript verwandelt "Fleischbällchen" in "Fleisch", "Bällchen". Jede Komponente sollte auch wissen, wie sie mit Änderungen an Einhängepunkten umgeht - z
Damit bleibt genau ein Problem offen: Was passiert, wenn zwei Objekte miteinander kollidieren (nicht ihre Container - Mount Points schützen Sie davor)? Nach einem Upgrade sollten Sie nach Kollisionen suchen und versuchen, diese zu beheben (durch Auseinanderbewegen, ein bisschen wie bei SAT). Wenn Sie nicht herausfinden können, wie die Kollision behoben werden kann, entfernen Sie eines der Objekte und verstauen Sie es. Dort können sie diese entfernten Objekte kaufen (kostenlos) oder verkaufen (zum vollen Preis). und informieren Sie den Player offensichtlich darüber, dass beim Upgrade ein Teil des Layouts beschädigt wurde - möglicherweise mit der Funktion "Vergrößern", damit er das Problem erkennen kann.
Letztendlich sollten Sie komplexe Änderungen in den Händen der Spieler belassen (Fehler schnell), da kein Algorithmus die Ästhetik erklären kann. Sie sollten lediglich in der Lage sein, dem Spieler den Kontext anzugeben, in dem sich der Gegenstand befand (damit sie sich nicht nur erinnern können) lande mit all diesen Gegenständen in ihrem Versteck und weiß nicht, wo sie waren).
quelle
Ich versuche, dies mit etwas in Verbindung zu bringen, das ich verstehe, also denke ich gerade in Bezug auf Minecraft. Ich stelle mir einen Live-Server vor, auf dem Spieler Änderungen in Echtzeit vornehmen, während die Entwickler einen Testserver ausführen, der neue Inhalte repariert / erstellt.
Ihre Frage scheint fast wie 2 eindeutige Fragen:
Ich würde versuchen, # 1 durch ein temporäres Referenzierungssystem zu lösen. Wenn beispielsweise ein neues Objekt von jemandem erstellt wird, kann es als flüchtig oder temporär markiert werden. Ich würde mir vorstellen, dass alle neuen Inhalte, die auf dem Testserver erstellt werden, als flüchtig gekennzeichnet sind (obwohl sie auch auf nicht flüchtige Inhalte verweisen können).
Wenn Sie bereit sind, neuen Inhalt auf den Live-Server zu übertragen, werden die flüchtigen Objekte beim Importvorgang gefunden und den Live-Server-Objekt-IDs zugewiesen, die in Stein gemeißelt sind. Dies unterscheidet sich von einem direkten Import / Zusammenführen, da Sie in der Lage sein müssen, auf vorhandene nichtflüchtige Objekte zu verweisen, wenn Sie diese reparieren oder aktualisieren müssen.
Für # 2 scheint es wirklich notwendig zu sein, dass Sie eine Stufe der Zwischenskripttransmutation haben, die den Funktionsnamen in einen eindeutigen Namespace hasht. dh
Wird
quelle
Wenn es sich bei den Dateien für die Daten nicht um Binärdateien, sondern um Textdateien handelt und die Designer und Player verschiedene Bereiche ändern, können Sie eine SVN-Zusammenführung versuchen.
quelle
Ich denke, dass ein Datenbank- / Dateisystem, das über Umgebungen hinweg mit einem Auscheck-Verfahren repliziert wird, am besten ist.
Wenn ein Designer also Änderungen an der Welt vornehmen möchte, checkt er alle Assets aus / sperrt sie, die er für alle Kopien der Datenbank (Entwicklung und Produktion) erstellen / ändern möchte, damit kein anderer Player oder Designer sie ändern kann . Anschließend arbeitete er an der Entwicklungsdatenbank, bis das neue Design fertig war. Zu diesem Zeitpunkt wurden die Änderungen mit der Produktionsdatenbank zusammengeführt und diese Assets in allen Umgebungen eingecheckt / entsperrt.
Player-Bearbeitungen würden auf die gleiche Weise funktionieren, mit der Ausnahme, dass die Datenbank- / Dateisystemrollen umgekehrt würden - sie funktionieren in der Produktionsdatenbank und alle Aktualisierungen werden nach Abschluss auf dev hochgeladen.
Die Asset-Sperre kann auf die Eigenschaften beschränkt werden, für die Sie keine Konflikte garantieren möchten: In Beispiel 1 würden Sie die Sperre aktivieren,
ID 123456
sobald der Spieler mit der Erstellung beginnt, sodass den Entwicklern diese ID nicht zugewiesen wird. In Beispiel 2 hätten Ihre Entwickler den SkriptnamenassignFrenchAccent
während der Entwicklung gesperrt , sodass der Spieler bei der Entwicklung seiner Modifikation einen anderen Namen wählen müsste (dieses kleine Ärgernis kann durch Namespacing verringert werden, aber das allein vermeidet keine Konflikte, wenn Sie nicht jeden Namen angeben Benutzer / Entwickler einen bestimmten Namespace, und dann haben Sie das gleiche Problem mit der Verwaltung der Namespaces). Dies bedeutet, dass die gesamte Entwicklung aus einer einzelnen Online-Datenbank gelesen werden muss. In diesen Beispielen sind jedoch nur die Objektnamen aus dieser Datenbank erforderlich, sodass die Leistung kein Problem darstellen sollte.In Bezug auf die Implementierung sollte es ausreichen, eine einzige Tabelle mit allen Schlüsseln und dem Asset-Status (verfügbar, von dev gesperrt, von prod gesperrt) zu haben, die in Echtzeit über alle Umgebungen hinweg synchronisiert / zugänglich sind. Eine komplexere Lösung würde ein vollständiges Versionskontrollsystem implementieren - Sie können ein vorhandenes System wie CVS oder SVN verwenden, wenn sich Ihre Assets alle in einem Dateisystem befinden.
quelle
Ich denke, es geht hier darum, Ihre Verantwortung sauber zu übernehmen. 1) Der Server gibt an, was derzeit akzeptabel ist und mit welcher API der Zugriff erfolgen soll. Die Datenbank wird nach bestimmten Regeln geändert. 2) Ersteller dürfen Inhalte erstellen, diese müssen jedoch nach Aktualisierungen wiedergegeben werden können. Dies liegt ausschließlich in Ihrer Verantwortung: Jedes Update muss in der Lage sein, alte Datenstrukturen möglichst sauber und einfach zu analysieren.
Die Mount Point-Idee hat Vorteile, wenn Sie den Überblick über einzigartige Gegenstände und Positionen innerhalb einer formbaren Struktur behalten möchten, insbesondere wenn wir akzeptieren, dass sich die gesamte Heimstruktur eines Spielers dramatisch ändern wird und Sie dies beibehalten möchten kleine Deko-Sachen in ihren jeweiligen Schließfächern.
Es ist eine sehr komplizierte Angelegenheit, viel Glück! Es gibt wahrscheinlich keine Antwort.
quelle
Ich denke nicht, dass das ein großes Problem ist, wie Sie es machen.
Ich würde nur vom Benutzer erstellte Mods überschreiben, mit der Warnung, dass "Mod X mit dieser Version möglicherweise nicht richtig funktioniert". Überlasse es den Mod-Erstellern, ihre Arbeit zu ändern. Ich denke nicht, dass dies eine unrealistische Erwartung ist, dass Updates bestimmte Mods deaktivieren könnten.
Das Gleiche gilt für vom Benutzer erstellte Inhalte. Erstellen Sie einfach eine Sicherungskopie und überschreiben Sie sie.
Ich habe keine wirkliche Erfahrung damit, nur Vorschläge zu machen.
quelle