Grundsätzlich ist eine Migration alter Charakterbögen auf neue Versionen problemlos denkbar. Doch macht eine Eigenheit der Funktionen getAttrs()
und setAttrs()
dem Ganzen einen Strich durch die Rechnung: Asynchronität.
Die Lösung die verschiedenen Migrationsfunktionen über eine Schleife nacheinander durchlaufen zu lassen, führt auf kurz oder lang zu race conditions und/oder inkonsistenten Daten, weil beide Funktionen asynchron sind. Solche Bugs lassen sich quasi nicht reproduzieren und können Spielern den Charakterbogen zerschießen.
Die aktuell von mir favorisierte Lösung ist wenig anwenderfreundlich:
- Beim Öffnen des Sheets wird geprüft, ob mehr als eine Migration nötig wird. Ist dies der Fall, weiter beim nächsten Schritt, sonst die bis zu eine Migration durchführen. Ist der Bogen gesperrt, wird er entsperrt.
- Der Charakterbogen wird "gesperrt", indem via CSS eine entsprechende Meldung ein- und der restliche Teil des Bogens ausgeblendet wird. Ist der Bogen bereits gesperrt, wird die Nachricht aktualisiert.
- Die erste/nächste Migration wird durchgeführt. Der Spieler wird in der Mitteilung dazu aufgefordert den Charakterbogen zu schließen und erneut zu öffnen.
In der Hoffnung, dass vor dem Schließen des Charakterbogens kein Code unausgeführt bleibt, sollte beim erneuten Öffnen stets ein konsistenter Zustand herrschen. Die einzige Alternative dazu, die mir einfällt, ist eine immer größer werdende Migrationsfunktion, die für sämtliche Ausgangsversionen korrekt migriert. Dass das aber bereits nach fünf Versionen kaum mehr wartbar und den Aufwand wert ist, ist hoffentlich leicht einzusehen.
Falls jemand bessere Ideen hat, diese Updates umzusetzen, nur her damit. Möglicherweise verstehe ich auch nur asynchrone Funktionen in JavaScript nicht ausreichend, um zu erkennen, dass ich mir da unnötige Sorgen mache.