Eco: Defekte Welt retten

02.10.2016
Dieser Inhalt ist bereits etwas älter.
This content is already a bit old.
Eco Welt

Diese Anleitung funktioniert nur, wenn zumindest eine Sicherung eurer Welt vorliegt (diese liegt standardmäßig im Unterverzeichnis "Backup" im "Storage" Verzeichnis)!

Vor kurzem ist mit der PC abgestürzt und somit leider auch der Eco Server. Leider hat in diesem Moment der Server gerade die Welt auf der SSD gespeichert und deshalb konnte die Welt nicht mehr korrekt geladen werden. Es erschien nach dem Laden der "Plants 100%" folgender Stack:

Exception
System.AggregateException: Mindestens ein Fehler ist aufgetreten. ---> System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> System.Exception: Error(s) occurred when loading Plants
   bei Eco.Core.Serialization.DataStore.LoadAsync[T](String folder, Action`2 createFunc)
   bei Eco.Simulation.PlantSim..ctor()
   bei Eco.Simulation.EcoSim.Initialize()
   bei Eco.Simulation.EcoSim..ctor()
   --- Ende der internen Ausnahmestapelüberwachung ---
   bei System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   bei System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   bei System.Activator.CreateInstance(Type type, Boolean nonPublic)
   bei System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
   bei System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   bei System.Activator.CreateInstance(Type type, Object[] args)
   bei Eco.Server.PluginManager.AddPlugin(Type pluginType, Object[] p)
   bei Eco.Server.PluginManager.<.ctor>b__10_3()
   bei System.Threading.Tasks.Task.Execute()
   --- Ende der internen Ausnahmestapelüberwachung ---
   bei System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken)
   bei Eco.Server.PluginManager..ctor()
   bei Eco.Server.Startup.Start(String[] args)
   bei Eco.Server.MainClass.Main(String[] args)
---> (Interne Ausnahme #0) System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> System.Exception: Error(s) occurred when loading Plants
   bei Eco.Core.Serialization.DataStore.LoadAsync[T](String folder, Action`2 createFunc)
   bei Eco.Simulation.PlantSim..ctor()
   bei Eco.Simulation.EcoSim.Initialize()
   bei Eco.Simulation.EcoSim..ctor()
   --- Ende der internen Ausnahmestapelüberwachung ---
   bei System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   bei System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   bei System.Activator.CreateInstance(Type type, Boolean nonPublic)
   bei System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)
   bei System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
   bei System.Activator.CreateInstance(Type type, Object[] args)
   bei Eco.Server.PluginManager.AddPlugin(Type pluginType, Object[] p)
   bei Eco.Server.PluginManager.<.ctor>b__10_3()
   bei System.Threading.Tasks.Task.Execute()<---

Also machte ich mich mal auf die Suche und fand folgende sehr interessanten Dinge heraus:

  • Jede Welt besteht aus einer SQLite-Datenbank (*.db) sowie einer ZIP-Datei (*.eco)
  • In der ZIP-Datei sind in einer Ordnerstruktur alle Objekte in einem modularen Format gespeichert. Hier gibt es z.B. einen Ordner "Plants" für die Flora, sowie auch einen Ordner "World" für alle Blöcke mit den jeweiligen Rohstoffen.

Da ich die Datei  mit 7-ZIP öffnen konnte, war der Header zumindest nicht defekt. Als erstes prüfte ich die ECO-Datei auf CRC-Fehler im Archiv. Hier wurde ich auch gleich fündig und eine Liste von defekten Dateien wurde ausgegeben. Diese Auflistung notierte ich mir.

Nun versuchte ich (leider vergeblich) mit den einschlägigen ZIP-Wiederherstellungstools die Datei wieder in den Griff zu bekommen, aber leider ohne Erfolg.

Nun öffnete ich in einer Instanz von 7-Zip (mit einem anderen Software müsste es natürlich auch funktionieren) eine Backup-Datei auf der linken Seite des Bildschirms. Auf der rechten Seite des Bildschirms öffnete ich die defekte Datei.

Da die Dateien modular aufgebaut waren hatte ich nun folgende Idee: Wenn ich die defekten Dateien im Archiv in der aktuellen Version durch die Dateien in der alten gesicherten Version ersetze, müsste die Datei an sich wieder in Ordnung sein und die meisten Aktionen sowie Objekte müssten noch auf Zustand vor dem Crash sein. Nun ging ich also die Liste der Prüfsummenfehler durch und ersetze jede defekte Datei mit der Datei aus der Sicherung. Da funktioniert ganz einfach, indem die jeweilige Datei von links nach rechts per Drag & Drop in das andere Fenster gezogen wird. Hier ein Screenshot der Ordnerstrukur:

Bild

Wie auf dem Screenshot sehr gut zu sehen ist, ist die Datei wirklich relativ logisch aufgebaut.

Nach dem ich alle defekten Dateien ersetzt hatte, konnte ich den Eco Server wieder fehlerfrei starten.

Nach diesem Vorfall habe ich den automatischen Backup-Intervall in den Servereinstellungen auf 1 Stunden gesetzt. Ich hätte zwar gerne alle 20 Minuten ein rotierendes Backup gehabt, allerdings ist das aktuell leider nicht möglich.

Ich muss hier erwähnen, dass ich es sehr vorbildlich finde, wie die Welt hier gespeichert wird. Somit ist eine "Rettung" der Welt zumindest in Teilen noch gut möglich. Wäre hier ein spezielles Dateiformat genutzt worden, wäre die Welt (oder zumindest das Delta bis zum letzten korrekten Backup) verloren gewesen.


 

Feedback, Verbesserungsvorschläge, weitere Ideen?

Einfach das Kontaktformular verwenden oder direkt eine E-Mail an info@kirgus.net.