Ejemplo n.º 1
0
        public Map Load(string fileName)
        {
            if (fileName == null)
            {
                throw new ArgumentNullException("fileName");
            }
            using (FileStream mapStream = File.OpenRead(fileName)) {
                byte[] temp = new byte[8];
                Map    map  = null;

                mapStream.Seek(-4, SeekOrigin.End);
                mapStream.Read(temp, 0, 4);
                mapStream.Seek(0, SeekOrigin.Begin);
                int    uncompressedLength = BitConverter.ToInt32(temp, 0);
                byte[] data = new byte[uncompressedLength];
                using (GZipStream reader = new GZipStream(mapStream, CompressionMode.Decompress, true)) {
                    reader.Read(data, 0, uncompressedLength);
                }

                for (int i = 0; i < uncompressedLength - 1; i++)
                {
                    if (data[i] != 0xAC || data[i + 1] != 0xED)
                    {
                        continue;
                    }

                    // bypassing the header crap
                    int pointer = i + 6;
                    Array.Copy(data, pointer, temp, 0, 2);
                    pointer += IPAddress.HostToNetworkOrder(BitConverter.ToInt16(temp, 0));
                    pointer += 13;

                    int headerEnd;
                    // 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;
                    int      width = 0, length = 0, height = 0;
                    Position spawn = new Position();
                    while (pointer < headerEnd)
                    {
                        switch ((char)data[pointer])
                        {
                        case 'Z':
                            offset++;
                            break;

                        case 'F':
                        case 'I':
                            offset += 4;
                            break;

                        case 'J':
                            offset += 8;
                            break;
                        }

                        pointer += 1;
                        Array.Copy(data, pointer, temp, 0, 2);
                        short skip = IPAddress.HostToNetworkOrder(BitConverter.ToInt16(temp, 0));
                        pointer += 2;

                        // look for relevant variables
                        Array.Copy(data, headerEnd + offset - 4, temp, 0, 4);
                        if (BufferUtil.MemCmp(data, pointer, "width"))
                        {
                            width = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt32(temp, 0));
                        }
                        else if (BufferUtil.MemCmp(data, pointer, "depth"))
                        {
                            height = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt32(temp, 0));
                        }
                        else if (BufferUtil.MemCmp(data, pointer, "height"))
                        {
                            length = (ushort)IPAddress.HostToNetworkOrder(BitConverter.ToInt32(temp, 0));
                        }
                        else if (BufferUtil.MemCmp(data, pointer, "xSpawn"))
                        {
                            spawn.X = (short)(IPAddress.HostToNetworkOrder(BitConverter.ToInt32(temp, 0)) * 32 + 16);
                        }
                        else if (BufferUtil.MemCmp(data, pointer, "ySpawn"))
                        {
                            spawn.Z = (short)(IPAddress.HostToNetworkOrder(BitConverter.ToInt32(temp, 0)) * 32 + 16);
                        }
                        else if (BufferUtil.MemCmp(data, pointer, "zSpawn"))
                        {
                            spawn.Y = (short)(IPAddress.HostToNetworkOrder(BitConverter.ToInt32(temp, 0)) * 32 + 16);
                        }

                        pointer += skip;
                    }

                    map = new Map(null, width, length, height, false)
                    {
                        Spawn = spawn
                    };

                    if (!map.ValidateHeader())
                    {
                        throw new MapFormatException("MapDAT: One or more of the map dimensions are invalid.");
                    }

                    // find the start of the block array
                    bool foundBlockArray = false;
                    offset = Array.IndexOf <byte>(data, 0x00, headerEnd);
                    while (offset != -1 && offset < data.Length - 2)
                    {
                        if (data[offset] == 0x00 && data[offset + 1] == 0x78 && data[offset + 2] == 0x70)
                        {
                            foundBlockArray = true;
                            pointer         = offset + 7;
                        }
                        offset = Array.IndexOf <byte>(data, 0x00, offset + 1);
                    }

                    // copy the block array... or fail
                    if (foundBlockArray)
                    {
                        map.Blocks = new byte[map.Volume];
                        Array.Copy(data, pointer, map.Blocks, 0, map.Blocks.Length);
                        map.ConvertBlockTypes(Mapping);
                    }
                    else
                    {
                        throw new MapFormatException("MapDAT: Could not locate block array.");
                    }
                    break;
                }
                return(map);
            }
        }