Ejemplo n.º 1
0
        /// <summary>
        /// Opens an existing NBT file from a stream.
        /// </summary>
        /// <param name="stream">The stream to get the NBT file from.</param>
        /// <param name="version">The compression version of the NBT, specify '1' for the original gzip compression, '2' for the mcregion zlib compression.</param>
        /// <returns>An opened NBT file.</returns>
        public static NBTFile OpenFile(Stream stream, int version)
        {
            NBTFile file = new NBTFile();

            Stream compressStream;

            if (version == 1)
            {
                compressStream = new GZipStream(stream, CompressionMode.Decompress);
            }
            else
            {
                stream.ReadByte();
                stream.ReadByte();

                compressStream = new DeflateStream(stream, CompressionMode.Decompress);
            }

            BinaryReader reader = new BinaryReader(compressStream);

            {
                Encoding textEncoding = Encoding.UTF8;

                file.NamedNBT = reader.ReadByte() == 10;
                file.RootName = textEncoding.GetString(reader.ReadBytes(EndiannessConverter.ToInt16(reader.ReadInt16())));

                if (file.NamedNBT)
                {
                    byte type;

                    while ((type = reader.ReadByte()) != 0)
                    {
                        string name = textEncoding.GetString(reader.ReadBytes(EndiannessConverter.ToInt16(reader.ReadInt16())));

                        file.InsertTag(new NBTTag(name, type, file.ReadPayload(ref reader, type)));
                    }
                }
                else
                {
                    byte type = reader.ReadByte();
                    int  size = EndiannessConverter.ToInt32(reader.ReadInt32());

                    for (int i = 0; i < size; i++)
                    {
                        file.InsertTag(new NBTTag("", type, file.ReadPayload(ref reader, type)));
                    }
                }
            }
            reader.Dispose();
            compressStream.Dispose();

            return(file);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Opens the region file from a stream.
        /// </summary>
        /// <param name="stream">The stream the region file will read from.</param>
        /// <returns>The parsed region file.</returns>
        public static RegionFile OpenRegion(Stream stream)
        {
#if DEBUG
            DateTime wStart;
#endif
            RegionFile region = new RegionFile();

            using (BinaryReader reader = new BinaryReader(stream))
            {
                int[] sectors = new int[1024];
                int[] tstamps = new int[1024];

                for (int i = 0; i < 1024; i++)
                {
                    sectors[i] = reader.ReadInt32();
                }

                for (int i = 0; i < 1024; i++)
                {
                    tstamps[i] = reader.ReadInt32();
                }

                Thread offsetThread = new Thread(new ThreadStart(() =>
                {
                    int sector = 0;

                    lock (sectors)
                        for (int i = 0; i < 1024; i++)
                        {
                            sector = EndiannessConverter.ToInt32(sectors[i]);

                            region.offsets[i] = new McrOffset()
                            {
                                SectorSize   = (byte)(sector & 0xFF),
                                SectorOffset = sector >> 8,
                            };
                        }

                    sectors = null;
                }));
                offsetThread.Name = "offset calculator thread";
                offsetThread.Start();

                offsetThread.Join();

                Thread tstampThread = new Thread(() =>
                {
                    int tstamp = 0;
                    lock (tstamps)
                        for (int i = 0; i < 1024; i++)
                        {
                            tstamp            = EndiannessConverter.ToInt32(tstamps[i]);
                            region.tstamps[i] = new McrtStamp
                            {
                                Timestamp = tstamp,
                            };
                        }

                    tstamps = null;
                })
                {
                    Name = "timestamp calculator thread"
                };
                tstampThread.Start();
                tstampThread.Join();
#if DEBUG
                wStart = DateTime.Now;
#endif
                byte[][] chunkBuffer = new byte[1024][];
                {
                    int       length;
                    McrOffset offset;

                    for (int i = 0; i < 1024; i++)
                    {
                        offset = region.offsets[i];

                        if (offset.SectorOffset != 0)
                        {
                            stream.Seek(offset.SectorOffset * 4096, SeekOrigin.Begin);

                            length = EndiannessConverter.ToInt32(reader.ReadInt32());
                            reader.ReadByte();

                            chunkBuffer[i] = reader.ReadBytes(length - 1);
                        }
                    }
                }

                int      chunkSlice    = 1024 / MaxTHREADS;
                Thread[] workerThreads = new Thread[MaxTHREADS];
                {
                    for (int i = 0; i < MaxTHREADS; i++)
                    {
                        byte[][] chunkWorkerBuffer = new byte[chunkSlice][];
                        Array.Copy(chunkBuffer, i * chunkSlice, chunkWorkerBuffer, 0, chunkSlice);

                        int index = i;

                        workerThreads[i] = new Thread(new ThreadStart(() =>
                        {
#if DEBUG
                            DateTime start = DateTime.Now;
#endif

                            int offset            = index * (1024 / MaxTHREADS);
                            MemoryStream mmStream = null;

                            for (int n = 0; n < chunkWorkerBuffer.Length; n++)
                            {
                                byte[] chunk = chunkWorkerBuffer[n];

                                if (chunk == null)
                                {
                                    continue;
                                }

                                mmStream = new MemoryStream(chunk);
                                region.chunks[n + offset] = NBTFile.OpenFile(mmStream, 2);
                                mmStream.Dispose();
                            }

                            chunkWorkerBuffer = null;

#if DEBUG
                            Console.WriteLine("Thread worker " + (index + 1) + " is complete! Took " + (int)(DateTime.Now - start).TotalMilliseconds + "ms to process.");
                        }));

                        workerThreads[i].Name = "chunk worker thread " + (index + 1);
#else
                        }));
Ejemplo n.º 3
0
        private void SavePayload(ref BinaryWriter writer, byte type, dynamic payload)
        {
            switch (type)
            {
            case 0:
                writer.Write((byte)0);
                break;

            case 1:
                writer.Write((byte)payload);
                break;

            case 2:
                writer.Write(EndiannessConverter.ToInt16(payload));
                break;

            case 3:
                writer.Write(EndiannessConverter.ToInt32(payload));
                break;

            case 4:
                writer.Write(EndiannessConverter.ToInt64(payload));
                break;

            case 5:
                writer.Write(EndiannessConverter.ToSingle(payload));
                break;

            case 6:
                writer.Write(EndiannessConverter.ToDouble(payload));
                break;

            case 7:
                writer.Write(EndiannessConverter.ToInt32(payload.Length));

                for (int i = 0; i < payload.Length; i++)
                {
                    writer.Write(payload[i]);
                }
                break;

            case 8:
                writer.Write(EndiannessConverter.ToInt16((short)payload.Length));

                byte[] oString = Encoding.UTF8.GetBytes(payload);

                for (int i = 0; i < oString.Length; i++)
                {
                    writer.Write(oString[i]);
                }
                break;

            case 9:

                writer.Write(payload[0].Type);
                writer.Write(EndiannessConverter.ToInt32(payload.Count));

                foreach (NBTTag tag in payload)
                {
                    SavePayload(ref writer, tag.Type, tag.Payload);
                }

                break;

            case 10:

                foreach (KeyValuePair <string, NBTTag> tag in payload)
                {
                    writer.Write(tag.Value.Type);
                    writer.Write(EndiannessConverter.ToInt16((short)tag.Key.Length));

                    byte[] cString = Encoding.UTF8.GetBytes(tag.Key);

                    for (int i = 0; i < cString.Length; i++)
                    {
                        writer.Write(cString[i]);
                    }

                    SavePayload(ref writer, tag.Value.Type, tag.Value.Payload);
                }
                writer.Write((byte)0);

                break;
            }
        }
Ejemplo n.º 4
0
        private dynamic ReadPayload(ref BinaryReader reader, byte type)
        {
            switch (type)
            {
            case 0:
                return(0);

            case 1:
                return(reader.ReadByte());

            case 2:
                return(EndiannessConverter.ToInt16(reader.ReadInt16()));

            case 3:
                return(EndiannessConverter.ToInt32(reader.ReadInt32()));

            case 4:
                return(EndiannessConverter.ToInt64(reader.ReadInt64()));

            case 5:
                return(EndiannessConverter.ToSingle(reader.ReadSingle()));

            case 6:
                return(EndiannessConverter.ToDouble(reader.ReadDouble()));

            case 7:
                return(reader.ReadBytes(EndiannessConverter.ToInt32(reader.ReadInt32())));

            case 8:
                return(Encoding.UTF8.GetString(reader.ReadBytes(EndiannessConverter.ToInt16(reader.ReadInt16()))));

            case 9:
            {
                List <NBTTag> ret = new List <NBTTag>();
                {
                    byte containerType = reader.ReadByte();
                    int  containerSize = EndiannessConverter.ToInt32(reader.ReadInt32());

                    for (int i = 0; i < containerSize; i++)
                    {
                        ret.Add(new NBTTag("", containerType, ReadPayload(ref reader, containerType)));
                    }
                }
                return(ret);
            }

            case 10:
            {
                Dictionary <string, NBTTag> dic = new Dictionary <string, NBTTag>();
                {
                    byte containerType;

                    while ((containerType = reader.ReadByte()) != 0)
                    {
                        string containerName = Encoding.UTF8.GetString(reader.ReadBytes(EndiannessConverter.ToInt16(reader.ReadInt16())));

                        dic.Add(containerName, new NBTTag(containerName, containerType, ReadPayload(ref reader, containerType)));
                    }
                }
                return(dic);
            }

            default:
                throw new NotSupportedException("Tag type is invalid!");
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Saves this NBT file in a stream.
        /// </summary>
        /// <param name="stream">The output stream this NBT file will write onto.</param>
        /// <param name="version">The compression version of the NBT, specify '1' for the original gzip compression, '2' for the mcregion zlib compression.</param>
        public void SaveTag(Stream stream, int version)
        {
            Stream compressStream;

            if (version == 1)
            {
                compressStream = new GZipStream(stream, CompressionMode.Compress);
            }
            else
            {
                stream.WriteByte(0);
                stream.WriteByte(0);

                compressStream = new DeflateStream(stream, CompressionMode.Compress);
            }

            BinaryWriter writer = new BinaryWriter(compressStream);

            {
                writer.Write((byte)(NamedNBT ? 10 : 9));
                writer.Write(EndiannessConverter.ToInt16((short)RootName.Length));

                byte[] oString = Encoding.UTF8.GetBytes(RootName);

                for (int i = 0; i < oString.Length; i++)
                {
                    writer.Write(oString[i]);
                }

                if (this.NamedNBT)
                {
                    foreach (KeyValuePair <string, NBTTag> tag in _dict)
                    {
                        writer.Write(tag.Value.Type);
                        writer.Write(EndiannessConverter.ToInt16((short)tag.Value.Name.Length));

                        oString = Encoding.UTF8.GetBytes(tag.Value.Name);

                        for (int i = 0; i < oString.Length; i++)
                        {
                            writer.Write(oString[i]);
                        }

                        SavePayload(ref writer, tag.Value.Type, tag.Value.Payload);
                    }
                    writer.Write((byte)0);
                }
                else
                {
                    writer.Write(_list[0].Type);
                    writer.Write(EndiannessConverter.ToInt32(_list.Count));

                    for (int i = 0; i < _list.Count; i++)
                    {
                        SavePayload(ref writer, _list[0].Type, _list[i].Payload);
                    }
                }
            }
            writer.Dispose();
            compressStream.Dispose();
        }