Exemplo n.º 1
0
        public void SaveChunks(Chunk[] chunks)
        {
            int width = 32;
            int depth = 32;

            Chunk chunk = chunks[0];
            int   rx    = chunk.X >> 5;
            int   rz    = chunk.Z >> 5;

            string filePath = Path.Combine(this.WorldPath, $@"region/r.{rx}.{rz}.mca");

            if (!File.Exists(filePath))
            {
                Directory.CreateDirectory(this.RegionPath);

                using (var regionFile = File.Open(filePath, FileMode.CreateNew))
                {
                    byte[] buffer = new byte[8192];
                    regionFile.Write(buffer, 0, buffer.Length);
                }
            }

            using (var regionFile = File.Open(filePath, FileMode.Open))
            {
                byte[] buffer = new byte[8192];
                regionFile.Read(buffer, 0, buffer.Length);

                for (int i = 0; i < chunks.Length; i++)
                {
                    chunk = chunks[i];
                    int xi = (chunk.X % width);
                    if (xi < 0)
                    {
                        xi += 32;
                    }
                    int zi = (chunk.Z % depth);
                    if (zi < 0)
                    {
                        zi += 32;
                    }
                    int tableOffset = (xi + zi * width) * 4;

                    regionFile.Seek(tableOffset, SeekOrigin.Begin);

                    byte[] offsetBuffer = new byte[4];
                    regionFile.Read(offsetBuffer, 0, 3);
                    Array.Reverse(offsetBuffer);
                    int  offset      = BitConverter.ToInt32(offsetBuffer, 0) << 4;
                    byte sectorCount = (byte)regionFile.ReadByte();

                    byte[] nbtBuf         = NBTIO.WriteZLIBFile(this.ChunkFormat.NBTSerialize(chunk));
                    int    nbtLength      = nbtBuf.Length;
                    byte   nbtSectorCount = (byte)Math.Ceiling(nbtLength / 4096d);

                    if (offset == 0 || sectorCount == 0 || nbtSectorCount > sectorCount)
                    {
                        regionFile.Seek(0, SeekOrigin.End);
                        offset = (int)((int)regionFile.Position & 0xfffffff0);

                        regionFile.Seek(tableOffset, SeekOrigin.Begin);

                        byte[] bytes = BitConverter.GetBytes(offset >> 4);
                        Array.Reverse(bytes);
                        regionFile.Write(bytes, 0, 3);
                        regionFile.WriteByte(nbtSectorCount);
                    }

                    byte[] lenghtBytes = BitConverter.GetBytes(nbtLength + 1);
                    Array.Reverse(lenghtBytes);

                    regionFile.Seek(offset, SeekOrigin.Begin);
                    regionFile.Write(lenghtBytes, 0, 4);
                    regionFile.WriteByte(0x02);

                    regionFile.Write(nbtBuf, 0, nbtBuf.Length);

                    int reminder;
                    Math.DivRem(nbtLength + 4, 4096, out reminder);

                    byte[] padding = new byte[4096 - reminder];
                    if (padding.Length > 0)
                    {
                        regionFile.Write(padding, 0, padding.Length);
                    }
                }
            }
        }
        public void Write(string filePath, ChunkData[] datas)
        {
            const int width = 32;
            const int depth = 32;

            File.Copy(RegionPath, filePath);

            using (var regionFile = File.Open(filePath, FileMode.Open))
            {
                byte[] buffer = new byte[8192];
                regionFile.Read(buffer, 0, buffer.Length);

                for (int i = 0; i < datas.Length; i++)
                {
                    ChunkData data = datas[i];
                    int       xi   = (data.ChunkOffset.Item1 % width);
                    if (xi < 0)
                    {
                        xi += 32;
                    }
                    int zi = (data.ChunkOffset.Item2 % depth);
                    if (zi < 0)
                    {
                        zi += 32;
                    }
                    int tableOffset = (xi + zi * width) * 4;

                    regionFile.Seek(tableOffset, SeekOrigin.Begin);

                    byte[] offsetBuffer = new byte[4];
                    regionFile.Read(offsetBuffer, 0, 3);
                    Array.Reverse(offsetBuffer);
                    int  offset      = BitConverter.ToInt32(offsetBuffer, 0) << 4;
                    byte sectorCount = (byte)regionFile.ReadByte();

                    byte[] nbtBuf         = NBTIO.WriteZLIBFile(new CompoundTag().PutCompound("", data.Data), NBTEndian.BIG_ENDIAN);
                    int    nbtLength      = nbtBuf.Length;
                    byte   nbtSectorCount = (byte)Math.Ceiling(nbtLength / 4096d);

                    if (offset == 0 || sectorCount == 0 || nbtSectorCount > sectorCount)
                    {
                        regionFile.Seek(0, SeekOrigin.End);
                        offset = (int)((int)regionFile.Position & 0xfffffff0);

                        regionFile.Seek(tableOffset, SeekOrigin.Begin);

                        byte[] bytes = BitConverter.GetBytes(offset >> 4);
                        Array.Reverse(bytes);
                        regionFile.Write(bytes, 0, 3);
                        regionFile.WriteByte(nbtSectorCount);
                    }

                    byte[] lenghtBytes = BitConverter.GetBytes(nbtLength + 1);
                    Array.Reverse(lenghtBytes);

                    regionFile.Seek(offset, SeekOrigin.Begin);
                    regionFile.Write(lenghtBytes, 0, 4);
                    regionFile.WriteByte(0x02);

                    regionFile.Write(nbtBuf, 0, nbtBuf.Length);

                    int reminder;
                    Math.DivRem(nbtLength + 4, 4096, out reminder);

                    byte[] padding = new byte[4096 - reminder];
                    if (padding.Length > 0)
                    {
                        regionFile.Write(padding, 0, padding.Length);
                    }
                }
            }
        }
Exemplo n.º 3
0
        public void Save(Chunk chunk)
        {
            string filePath = this.FilePath;

            int width = 32;
            int depth = 32;

            if (!File.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);

                using (FileStream regionFile = File.Open(filePath, FileMode.CreateNew))
                {
                    byte[] buffer = new byte[8192];
                    regionFile.Write(buffer, 0, buffer.Length);
                }
            }

            using (FileStream regionFile = File.Open(filePath, FileMode.Open))
            {
                byte[] buffer = new byte[8192];
                regionFile.Read(buffer, 0, buffer.Length);

                int xi = (chunk.X % width);
                if (xi < 0)
                {
                    xi += 32;
                }
                int zi = (chunk.Z % depth);
                if (zi < 0)
                {
                    zi += 32;
                }
                int tableOffset = (xi + zi * width) * 4;

                regionFile.Seek(tableOffset, SeekOrigin.Begin);

                byte[] offsetBuffer = new byte[4];
                regionFile.Read(offsetBuffer, 0, 3);
                Array.Reverse(offsetBuffer);
                int  offset      = BitConverter.ToInt32(offsetBuffer, 0) << 4;
                byte sectorCount = (byte)regionFile.ReadByte();

                byte[] nbtBuf         = NBTIO.WriteZLIBFile(this.Provider.SerializeChunk(chunk), NBTEndian.BIG_ENDIAN);
                int    nbtLength      = nbtBuf.Length;
                byte   nbtSectorCount = (byte)Math.Ceiling(nbtLength / 4096d);

                if (offset == 0 || sectorCount == 0 || nbtSectorCount > sectorCount)
                {
                    regionFile.Seek(0, SeekOrigin.End);
                    offset = (int)((int)regionFile.Position & 0xfffffff0);

                    regionFile.Seek(tableOffset, SeekOrigin.Begin);

                    byte[] bytes = BitConverter.GetBytes(offset >> 4);
                    Array.Reverse(bytes);
                    regionFile.Write(bytes, 0, 3);
                    regionFile.WriteByte(nbtSectorCount);
                }

                byte[] lenghtBytes = BitConverter.GetBytes(nbtLength + 1);
                Array.Reverse(lenghtBytes);

                regionFile.Seek(offset, SeekOrigin.Begin);
                regionFile.Write(lenghtBytes, 0, 4);
                regionFile.WriteByte(0x02);

                regionFile.Write(nbtBuf, 0, nbtBuf.Length);

                Math.DivRem(nbtLength + 4, 4096, out int reminder);

                byte[] padding = new byte[4096 - reminder];
                if (padding.Length > 0)
                {
                    regionFile.Write(padding, 0, padding.Length);
                }
            }
        }