Aufgeteilt auf 2 Beiträge.
Hey,
da ich gerade an einem erweiterten Map-editor arbeite (github.com/Malekblubb/twl | github.com/Malekblubb/twlu), wollte ich die Gelengeheit nutzen, um in diesem "Tutorial" etwas näher auf den Aufbau einer Teeworlds Map einzugehen.
Das einzige was ich zu diesem Thema in Internet gefunde habe, war die TML dokumentation von SushiTee (sushitee.github.io/tml/mapformat.html), die meiner Meinung nach etwas kurz ist.
Etwas Erfahrung in der Programmierung(bits, bytes, byteorder, usw.) wären beim lesen von Vorteil.
Inhalt:
0. Teeworlds Map Format
Das Teeworlds Map Format beseteht wie jedes andere "Datafile" Format rein aus Binären bzw., für den Menschen besser lesbar, Hexdezimalen "Code".
Damit man die rohen Daten besser verstehen kann, habe ich die Map in verschiedene Bereiche aufgeteilt (s.o.).
Zu Beginn ein kleiner Einblick in eine Map-Datei via Hex-Editor.
1. Grundstruktur einer Map
1.0 Bereiche
Wie ich zuvor schon geschrieben habe, habe ich die Map-Datei in verschiedene Bereiche eingeteilt.
Rot, Dunkelgrün, Blau, Orange und Cyan gehören zum "Info-Hauptbereich", der Hellgrün eingerahmte "Code" ist der Item-Hauptbereich und der Rote Teil ist der Daten-Hauptbereich(der nich ganz abgebebildet ist).
Alle bereiche haben eine Variable Länge, die logischerweise von der Anzahl an Items/Daten abhängt.
1.0.0 Infobereich
1.0.0.0 Header
Der Header (oben Rot) ist einer der wichtigsten Bereiche,
er enthält wichtige Informationen und ist (mit Ausnahme der Items) der einzige Bereich, dessen Länge immer gleich ist, nämlich 36Bytes.
Die Ersten 4Bytes sollten der Zeichenkette "DATA" (oder in Big endian "ATAD") entsprechen, das ist mehr oder weniger die Kennung einer Teeworlds Map.
Der nächste Integer(4 Bytes) enthält die Version der Map, die in der jetztigen TW-Version 0.6.x, 4 sein sollte.
Integer 5-9 enthalten wichtige Informationen, die zum lesen/parsen der Map notwendig sind.
Mit Hilfe des Headers kann errechnet werden, wie weit man lesen muss, um den Itembereich und den Datenbereich vollständig zu lesen.
Folgende "Formel" ist anzuwenden:
Die Zahl 12 in der Formel kommt vom datentyp "map_datafile_iteminfo" und wird in Punkt 1.0.0.1 "Item Infos" erklärt.
Der Header zusammengefasst in einem POD
[cpp]
struct map_datafile_header
{
char m_sig[4];
int m_ver;
int m_size;
int m_swaplen;
int m_num_itemtypes;
int m_num_items;
int m_num_rawdata;
int m_item_area_size;
int m_data_area_size;
bool valid() const noexcept {return ((std::memcmp(m_sig, "DATA", 4) == 0) && (m_ver == 4));}
int body_size() const noexcept
{
return (m_num_itemtypes * 12) +
(m_num_items * sizeof(int)) +
((m_num_rawdata * sizeof(int)) * 2) +
m_item_area_size + m_data_area_size;
}
};
[/cpp]
Hey,
da ich gerade an einem erweiterten Map-editor arbeite (github.com/Malekblubb/twl | github.com/Malekblubb/twlu), wollte ich die Gelengeheit nutzen, um in diesem "Tutorial" etwas näher auf den Aufbau einer Teeworlds Map einzugehen.
Das einzige was ich zu diesem Thema in Internet gefunde habe, war die TML dokumentation von SushiTee (sushitee.github.io/tml/mapformat.html), die meiner Meinung nach etwas kurz ist.
Etwas Erfahrung in der Programmierung(bits, bytes, byteorder, usw.) wären beim lesen von Vorteil.
Inhalt:
- 0. Teeworlds Map Format
- 1. Grundstruktur einer Map
- 1.0 Bereiche
- 1.0.0 Infobereich
- 1.0.0.0 Header
- 1.0.0.1 Item Infos
- 1.0.0.2 Item Offsets
- 1.0.0.3 Komprimierte Daten Offsets
- 1.0.0.4 Unkomprimierte Daten Längen
- 1.0.1 Itembereich
- 1.0.1.0 Itemsortierung
- 1.0.1.1 Item: Version
- 1.0.1.2 Item: Info
- 1.0.1.3 Item: Bild
- 1.0.1.4 Item: Envelope
- 1.0.1.5 Item: Gruppe
- 1.0.1.6 Item: Ebene/Layer
- 1.0.1.7 Item: Envpunkt
- 1.0.2 Datenbereich
- 1.0.2.0 Komprimierte Daten
- 1.0.0 Infobereich
- 1.0 Bereiche
- 2. Lesen einer Map in C++
0. Teeworlds Map Format
Das Teeworlds Map Format beseteht wie jedes andere "Datafile" Format rein aus Binären bzw., für den Menschen besser lesbar, Hexdezimalen "Code".
Damit man die rohen Daten besser verstehen kann, habe ich die Map in verschiedene Bereiche aufgeteilt (s.o.).
Zu Beginn ein kleiner Einblick in eine Map-Datei via Hex-Editor.
1. Grundstruktur einer Map
1.0 Bereiche
Wie ich zuvor schon geschrieben habe, habe ich die Map-Datei in verschiedene Bereiche eingeteilt.
Rot, Dunkelgrün, Blau, Orange und Cyan gehören zum "Info-Hauptbereich", der Hellgrün eingerahmte "Code" ist der Item-Hauptbereich und der Rote Teil ist der Daten-Hauptbereich(der nich ganz abgebebildet ist).
Alle bereiche haben eine Variable Länge, die logischerweise von der Anzahl an Items/Daten abhängt.
1.0.0 Infobereich
1.0.0.0 Header
Der Header (oben Rot) ist einer der wichtigsten Bereiche,
er enthält wichtige Informationen und ist (mit Ausnahme der Items) der einzige Bereich, dessen Länge immer gleich ist, nämlich 36Bytes.
Die Ersten 4Bytes sollten der Zeichenkette "DATA" (oder in Big endian "ATAD") entsprechen, das ist mehr oder weniger die Kennung einer Teeworlds Map.
Der nächste Integer(4 Bytes) enthält die Version der Map, die in der jetztigen TW-Version 0.6.x, 4 sein sollte.
Integer 5-9 enthalten wichtige Informationen, die zum lesen/parsen der Map notwendig sind.
Mit Hilfe des Headers kann errechnet werden, wie weit man lesen muss, um den Itembereich und den Datenbereich vollständig zu lesen.
Folgende "Formel" ist anzuwenden:
[cpp]
struct map_datafile_header
{
char m_sig[4];
int m_ver;
int m_size;
int m_swaplen;
int m_num_itemtypes;
int m_num_items;
int m_num_rawdata;
int m_item_area_size;
int m_data_area_size;
bool valid() const noexcept {return ((std::memcmp(m_sig, "DATA", 4) == 0) && (m_ver == 4));}
int body_size() const noexcept
{
return (m_num_itemtypes * 12) +
(m_num_items * sizeof(int)) +
((m_num_rawdata * sizeof(int)) * 2) +
m_item_area_size + m_data_area_size;
}
};
[/cpp]