Es geht weiter!

Nach fast einem Jahr Pause geht es nun weiter mit dem Projekt OctoAwesome! Das NoobDevTv-Team versucht wieder regelmäßig Donnerstags um 19 Uhr einen OctoAwesome-Stream auf den Streaming-Kanäle von NoobDevTv: Twitch, Youtube und Mixer. zu veranstalten! Die neu produzierten Folgen der nun dritten Staffel werden ab jetzt auf deren Youtube-Kanal veröffentlicht.

Chunk Serializer: Unterschied zwischen den Versionen

Aus OctoAwesome Wiki
Wechseln zu: Navigation, Suche
K (Link korrigiert)
(Aktuelles Dateiformat, Hinweis auf Überarbeitung entfernt)
Zeile 1: Zeile 1:
 
[[Kategorie:Seitenindex]][[Kategorie:OctoAwesome.Runtime]][[Kategorie:Dokumentation]]
 
[[Kategorie:Seitenindex]][[Kategorie:OctoAwesome.Runtime]][[Kategorie:Dokumentation]]
{{Überarbeiten}}
+
Zur Serialisierung einer ganzen Chunk-Column wird ein eigenes, selbst entwickeltes und speziell auf unsere Anforderungen optimiertes Dateiformat verwendet. '''Der Chunk-Serializer''' schreibt die Daten binär mit Hilfe des BinaryWriters in einen Stream; beim lokalen Spiel landen diese als .dat-Datei im Planetenordner. Es wird immer ein 1x1 Chunks großer Teil der Welt in der gesamten Höhe in eine Datei gespeichert. Der Speicherverbrauch einer unkomprimierten ChunkCOlumn beträgt ca. 250KB; mit GZip komprimiert (bei lokalen Psielen und Netzwerk-Spielen der Fall) ca. 1 bis 3 KB.
Zur Chunk-Serialisierung wird ein eigenes, selbst entwickeltes und speziell auf unsere Anforderungen optimiertes Dateiformat verwendet. '''Der Chunk-Serializer''' schreibt die daten binär mit Hilfe des BinaryWriters in die .chunk-Datei. Wie der Name schon sagt, wird jeweils nur ein Chunk auf einmal serialisiert. Der Speicherverbrauch einer Chunkdatei beträgt ~33KB.
 
  
== Header ==
+
== Header (Phase 0) ==
Im Header wird dem Programm mitgeteilt, welche Blocktypen auf dem Chunk verwendet werden. Zuerst wird ein Flag als byte geschrieben, was angibt ob mehr (1) oder weniger (0) als 255 Blocktypen verwendet werden. Heute immer 0 (mangels Angebot an Plugins). Danach wird die eigentliche Anzahl der Blocktypen entweder als byte (<255 Blocktypen) oder als ushort (>255 Blocktypen) geschrieben. Anschließend werden die Namen der Blocktypen als string geschrieben (z.B. OctoAwesome.Basics.GrassBlockDefinition).
+
Im Header wird ein Flag als byte geschrieben, das angibt ob mehr (1) oder weniger (0) als 255 Blocktypen in der Column verwendet werden. Zur Zeit ist dieses immer 0 (mangels Angebot an Plugins).
  
== Daten ==
+
== Metadaten (Phase 1) ==
Jetzt werden die eigentlichen Daten der Blöcke als lineares Array geschrieben: Zuerst der Index der BlockDefinition (Typumstellung genauso bei 255 Blocktypen, siehe oben). Blocktyp 0 ist ein leerer Luftblock. Dann folgt ein int mit beliebigen Metadaten, falls der Blocktyp dies mit BlockDefinition.HasMetadata anfordert.
+
Nach dem Header werden Metadaten in den Stream geschrieben. Zuerst ein byte das die Anzahl der Chunks in der Column (also die Höhe) angbit. Anschließend ein boolescher Wert, der angibt, ob der Chunk bereits durch ChunkPopulatoren mit Bäuemen etc. versehen wurde.
 +
 
 +
Anschließend folgen Höheninformationen der aktuellen Column: y-zeilenweise wird die Höhe an Position (x, y) der Säule als ushort (2 bytes) geschrieben.
 +
 
 +
Zum Abschluss von Phase 1 wird der aktuelle Wert des Änderungscounters (4 bytes, int) geschrieben.
 +
 
 +
== Definitionen (Phase 2) ==
 +
Zu erst wird die Anzahl der verwendeten Blocktypen entweder als byte (<255 Blocktypen) oder als ushort (>255 Blocktypen) geschrieben. Anschließend werden die Namen der Blocktypen als string geschrieben (z.B. OctoAwesome.Basics.GrassBlockDefinition). Die Reihenfolge des Schreibens dient als Basis für den Index, der in Phase 3 zur Angabe der Blocktypen verwendet wird.
 +
 
 +
== Blockdaten (Phase 3) ==
 +
Beginnend mit Chunk 0 bis ''n'' werden nun die eigentlichen Blockdaten als lineares Array (vgl. interne Repräsentation) geschrieben: Zuerst der 1-basierte Index der BlockDefinition (Typumstellung genauso bei 255 Blocktypen, siehe oben) auf Basis der Reihenfolge der Definitions aus Phase 2. Blocktyp 0 ist ein leerer Luftblock. Dann folgt ein int (4 bytes) mit beliebigen Metadaten, falls der Blocktyp dies mit BlockDefinition.HasMetadata anfordert.
 +
 
 +
== Entitätsdaten (Phase 4) ==
 +
Zum Schluss werden die sich derzeit auf diesem Chunk befinden Entitäten serialisiert. Zuerst wird ein 4-byte-Integer mit der Anzahl der Entitäten auf dieser Säule geschrieben.
 +
 
 +
Anschließend wird pro Entität der AssemblyQualifiedName des Entity-Typs als String geschrieben. Darauf folgt jeweils ein Datenblock, der von der Entity sowohl in der Länge als auch von Inhalt selbst verwaltet wird.
  
 
== Links ==
 
== Links ==
* [https://github.com/tomwendel/octoawesome/blob/master/OctoAwesome/OctoAwesome.Runtime/ChunkSerializer.cs Die Implementierung auf GitHub]
+
* [https://github.com/OctoAwesome/octoawesome/blob/develop/OctoAwesome/OctoAwesome/ChunkColumn.cs#L227 Die Implementierung auf GitHub]
* [http://doc.octoawesome.net/develop/html/T_OctoAwesome_Runtime_ChunkSerializer.htm Dokumentation]
+
* [http://doc.octoawesome.net/api/develop/OctoAwesome.ChunkColumn.html Dokumentation]
 
 
[[Kategorie:Überarbeiten]]
 

Version vom 11. Mai 2018, 16:02 Uhr

Zur Serialisierung einer ganzen Chunk-Column wird ein eigenes, selbst entwickeltes und speziell auf unsere Anforderungen optimiertes Dateiformat verwendet. Der Chunk-Serializer schreibt die Daten binär mit Hilfe des BinaryWriters in einen Stream; beim lokalen Spiel landen diese als .dat-Datei im Planetenordner. Es wird immer ein 1x1 Chunks großer Teil der Welt in der gesamten Höhe in eine Datei gespeichert. Der Speicherverbrauch einer unkomprimierten ChunkCOlumn beträgt ca. 250KB; mit GZip komprimiert (bei lokalen Psielen und Netzwerk-Spielen der Fall) ca. 1 bis 3 KB.

Header (Phase 0)

Im Header wird ein Flag als byte geschrieben, das angibt ob mehr (1) oder weniger (0) als 255 Blocktypen in der Column verwendet werden. Zur Zeit ist dieses immer 0 (mangels Angebot an Plugins).

Metadaten (Phase 1)

Nach dem Header werden Metadaten in den Stream geschrieben. Zuerst ein byte das die Anzahl der Chunks in der Column (also die Höhe) angbit. Anschließend ein boolescher Wert, der angibt, ob der Chunk bereits durch ChunkPopulatoren mit Bäuemen etc. versehen wurde.

Anschließend folgen Höheninformationen der aktuellen Column: y-zeilenweise wird die Höhe an Position (x, y) der Säule als ushort (2 bytes) geschrieben.

Zum Abschluss von Phase 1 wird der aktuelle Wert des Änderungscounters (4 bytes, int) geschrieben.

Definitionen (Phase 2)

Zu erst wird die Anzahl der verwendeten Blocktypen entweder als byte (<255 Blocktypen) oder als ushort (>255 Blocktypen) geschrieben. Anschließend werden die Namen der Blocktypen als string geschrieben (z.B. OctoAwesome.Basics.GrassBlockDefinition). Die Reihenfolge des Schreibens dient als Basis für den Index, der in Phase 3 zur Angabe der Blocktypen verwendet wird.

Blockdaten (Phase 3)

Beginnend mit Chunk 0 bis n werden nun die eigentlichen Blockdaten als lineares Array (vgl. interne Repräsentation) geschrieben: Zuerst der 1-basierte Index der BlockDefinition (Typumstellung genauso bei 255 Blocktypen, siehe oben) auf Basis der Reihenfolge der Definitions aus Phase 2. Blocktyp 0 ist ein leerer Luftblock. Dann folgt ein int (4 bytes) mit beliebigen Metadaten, falls der Blocktyp dies mit BlockDefinition.HasMetadata anfordert.

Entitätsdaten (Phase 4)

Zum Schluss werden die sich derzeit auf diesem Chunk befinden Entitäten serialisiert. Zuerst wird ein 4-byte-Integer mit der Anzahl der Entitäten auf dieser Säule geschrieben.

Anschließend wird pro Entität der AssemblyQualifiedName des Entity-Typs als String geschrieben. Darauf folgt jeweils ein Datenblock, der von der Entity sowohl in der Länge als auch von Inhalt selbst verwaltet wird.

Links