mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-28 07:56:20 -04:00
Map: modularise .dat parsing somewhat
This commit is contained in:
parent
b52848530d
commit
a190d64162
@ -45,6 +45,9 @@ namespace MCGalaxy.Levels.IO {
|
|||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const byte MAGIC1 = 0xAC, MAGIC2 = 0xED;
|
||||||
|
const byte TYPE_END_BLOCK = 0x78, TYPE_NULL = 0x70;
|
||||||
|
|
||||||
public override Level Read(Stream src, string name, bool metadata) {
|
public override Level Read(Stream src, string name, bool metadata) {
|
||||||
byte[] temp = new byte[8];
|
byte[] temp = new byte[8];
|
||||||
Level lvl = new Level(name, 0, 0, 0);
|
Level lvl = new Level(name, 0, 0, 0);
|
||||||
@ -58,71 +61,67 @@ namespace MCGalaxy.Levels.IO {
|
|||||||
reader.Read(data, 0, length);
|
reader.Read(data, 0, length);
|
||||||
|
|
||||||
for (int i = 0; i < length - 1; i++) {
|
for (int i = 0; i < length - 1; i++) {
|
||||||
if (data[i] == 0xAC && data[i + 1] == 0xED) {
|
if (data[i] != MAGIC1 || data[i + 1] != MAGIC2) continue;
|
||||||
// bypassing the header crap
|
int pointer = 0, headerEnd = 0;
|
||||||
int pointer = i + 6;
|
ReadHeader(data, ref pointer, ref headerEnd, i);
|
||||||
Array.Copy(data, pointer, temp, 0, sizeof(short));
|
ReadFields(data, ref pointer, ref headerEnd, lvl);
|
||||||
pointer += IPAddress.HostToNetworkOrder(BitConverter.ToInt16(temp, 0));
|
|
||||||
pointer += 13;
|
|
||||||
|
|
||||||
int headerEnd = 0;
|
|
||||||
// find the end of serialization listing
|
|
||||||
for (headerEnd = pointer; headerEnd < data.Length - 1; headerEnd++) {
|
|
||||||
if (data[headerEnd] == 0x78 && data[headerEnd + 1] == 0x70) {
|
|
||||||
headerEnd += 2; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// start parsing serialization listing
|
|
||||||
int offset = 0;
|
|
||||||
while (pointer < headerEnd) {
|
|
||||||
if (data[pointer] == 'Z') offset++;
|
|
||||||
else if (data[pointer] == 'I' || data[pointer] == 'F') offset += 4;
|
|
||||||
else if (data[pointer] == 'J') offset += 8;
|
|
||||||
|
|
||||||
pointer += 1;
|
|
||||||
Array.Copy(data, pointer, temp, 0, sizeof(short));
|
|
||||||
short skip = IPAddress.HostToNetworkOrder(BitConverter.ToInt16(temp, 0));
|
|
||||||
pointer += 2;
|
|
||||||
|
|
||||||
// look for relevant variables
|
|
||||||
Array.Copy(data, headerEnd + offset - 4, temp, 0, sizeof(int));
|
|
||||||
if (MemCmp(data, pointer, "width")) {
|
|
||||||
lvl.Width = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt32(temp, 0));
|
|
||||||
} else if (MemCmp(data, pointer, "depth")) {
|
|
||||||
lvl.Height = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt32(temp, 0));
|
|
||||||
lvl.EdgeLevel = lvl.Height / 2;
|
|
||||||
} else if (MemCmp(data, pointer, "height")) {
|
|
||||||
lvl.Length = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt32(temp, 0));
|
|
||||||
}
|
|
||||||
pointer += skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
lvl.spawnx = (ushort)(lvl.Width / 1.3);
|
lvl.spawnx = (ushort)(lvl.Width / 1.3);
|
||||||
lvl.spawny = (ushort)(lvl.Height / 1.3);
|
lvl.spawny = (ushort)(lvl.Height / 1.3);
|
||||||
lvl.spawnz = (ushort)(lvl.Length / 1.3);
|
lvl.spawnz = (ushort)(lvl.Length / 1.3);
|
||||||
|
|
||||||
// find the start of the block array
|
// find the start of the block array
|
||||||
bool foundBlockArray = false;
|
int offset = Array.IndexOf<byte>(data, 0x00, headerEnd);
|
||||||
offset = Array.IndexOf<byte>(data, 0x00, headerEnd);
|
|
||||||
while (offset != -1 && offset < data.Length - 2) {
|
while (offset != -1 && offset < data.Length - 2) {
|
||||||
if (data[offset] == 0x00 && data[offset + 1] == 0x78 && data[offset + 2] == 0x70) {
|
if (data[offset] == 0x00 && data[offset + 1] == TYPE_END_BLOCK && data[offset + 2] == TYPE_NULL) {
|
||||||
foundBlockArray = true;
|
|
||||||
pointer = offset + 7;
|
pointer = offset + 7;
|
||||||
|
CopyBlocks(lvl, data, pointer);
|
||||||
|
return lvl;
|
||||||
}
|
}
|
||||||
offset = Array.IndexOf<byte>(data, 0x00, offset + 1);
|
offset = Array.IndexOf<byte>(data, 0x00, offset + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy the block array... or fail
|
|
||||||
if (foundBlockArray) {
|
|
||||||
CopyBlocks(lvl, data, pointer);
|
|
||||||
} else {
|
|
||||||
throw new InvalidDataException("Could not locate block array.");
|
throw new InvalidDataException("Could not locate block array.");
|
||||||
}
|
}
|
||||||
break;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReadHeader(byte[] data, ref int pointer, ref int headerEnd, int i) {
|
||||||
|
pointer = i + 6; // skip magic, version, and typecodes
|
||||||
|
ushort classNameLen = NetUtils.ReadU16(data, pointer);
|
||||||
|
pointer += classNameLen; // skip class name
|
||||||
|
pointer += 13; // skip class description
|
||||||
|
|
||||||
|
headerEnd = pointer;
|
||||||
|
// find the end of serialization listing
|
||||||
|
for (; headerEnd < data.Length - 1; headerEnd++) {
|
||||||
|
if (data[headerEnd] == TYPE_END_BLOCK && data[headerEnd + 1] == TYPE_NULL) {
|
||||||
|
headerEnd += 2; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lvl;
|
}
|
||||||
|
|
||||||
|
static void ReadFields(byte[] data, ref int pointer, ref int headerEnd, Level lvl) {
|
||||||
|
// start parsing serialization listing
|
||||||
|
int offset = 0;
|
||||||
|
while (pointer < headerEnd) {
|
||||||
|
byte type = data[pointer]; pointer += 1;
|
||||||
|
if (type == 'Z') offset++;
|
||||||
|
else if (type == 'I' || type == 'F') offset += 4;
|
||||||
|
else if (type == 'J') offset += 8;
|
||||||
|
ushort nameLen = NetUtils.ReadU16(data, pointer); pointer += 2;
|
||||||
|
|
||||||
|
// look for relevant variables
|
||||||
|
int valueOffset = headerEnd + offset - 4;
|
||||||
|
if (MemCmp(data, pointer, "width")) {
|
||||||
|
lvl.Width = (ushort)NetUtils.ReadI32(data, valueOffset);
|
||||||
|
} else if (MemCmp(data, pointer, "depth")) {
|
||||||
|
lvl.Height = (ushort)NetUtils.ReadI32(data, valueOffset);
|
||||||
|
lvl.EdgeLevel = lvl.Height / 2;
|
||||||
|
} else if (MemCmp(data, pointer, "height")) {
|
||||||
|
lvl.Length = (ushort)NetUtils.ReadI32(data, valueOffset);
|
||||||
|
}
|
||||||
|
pointer += nameLen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool MemCmp( byte[] data, int offset, string value ) {
|
static bool MemCmp( byte[] data, int offset, string value ) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user