From 60ced631ba1212b4a9ffb74e15d5e8727fa512ab Mon Sep 17 00:00:00 2001 From: Tara Date: Tue, 3 Jan 2023 15:46:38 -0700 Subject: [PATCH] Make NBT Serialization binary compatible with NBT GUI editors --- LibZNI.csproj | 2 +- Serialization/NBTReader.cs | 236 +++++++++++++++++++++++ Serialization/NBTWriter.cs | 263 ++++++++++++++++++++++++++ Serialization/SerializingHelper.cs | 162 ++++++++++++++++ Serialization/TagIO.cs | 24 ++- Serialization/ZNIFile/BoolTag.cs | 43 +++-- Serialization/ZNIFile/ByteArrayTag.cs | 33 ++-- Serialization/ZNIFile/ByteTag.cs | 27 ++- Serialization/ZNIFile/DoubleTag.cs | 29 +-- Serialization/ZNIFile/FloatTag.cs | 25 ++- Serialization/ZNIFile/Folder.cs | 89 ++++++--- Serialization/ZNIFile/Header.cs | 52 ----- Serialization/ZNIFile/IntArrayTag.cs | 35 ++-- Serialization/ZNIFile/IntTag.cs | 26 ++- Serialization/ZNIFile/ListTag.cs | 97 +++++++--- Serialization/ZNIFile/LongArrayTag.cs | 32 ++-- Serialization/ZNIFile/LongTag.cs | 28 +-- Serialization/ZNIFile/ShortTag.cs | 28 +-- Serialization/ZNIFile/StringTag.cs | 28 +-- Serialization/ZNIFile/Tag.cs | 10 +- Serialization/ZNIFile/TagType.cs | 37 ++-- Serialization/ZNIFile/UUIDTag.cs | 38 ++-- Serialization/ZNIFile/ulongTag.cs | 36 ++-- 23 files changed, 1101 insertions(+), 279 deletions(-) create mode 100644 Serialization/NBTReader.cs create mode 100644 Serialization/NBTWriter.cs create mode 100644 Serialization/SerializingHelper.cs delete mode 100644 Serialization/ZNIFile/Header.cs diff --git a/LibZNI.csproj b/LibZNI.csproj index 5c2cd29..32309d8 100644 --- a/LibZNI.csproj +++ b/LibZNI.csproj @@ -2,7 +2,7 @@ Library - net6.0 + net7.0 true false Debug;Release;DebPub;KVPBuild diff --git a/Serialization/NBTReader.cs b/Serialization/NBTReader.cs new file mode 100644 index 0000000..e5338e5 --- /dev/null +++ b/Serialization/NBTReader.cs @@ -0,0 +1,236 @@ +// DISCLAIMER: Taken from fNBT to be altered to fit the needs of ZNI NBT +// All credit for the implementation of this file should go to the fNBT Authors, unless stated otherwise by comment! + + +using LibZNI.Serialization.ZNIFile; +using System; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Text; + +namespace LibZNI.Serialization +{ + /// BinaryReader wrapper that takes care of reading primitives from an NBT stream, + /// while taking care of endianness, string encoding, and skipping. + public sealed class NBTReader : BinaryReader + { + readonly byte[] buffer = new byte[sizeof(double)]; + + byte[] seekBuffer; + const int SeekBufferSize = 8 * 1024; + readonly bool swapNeeded; + readonly byte[] stringConversionBuffer = new byte[64]; + + + public NBTReader(Stream input, bool bigEndian) + : base(input) + { + swapNeeded = (BitConverter.IsLittleEndian == bigEndian); + } + + + public TagType ReadTagType() + { + int type = ReadByte(); + if (type < 0) + { + throw new EndOfStreamException(); + } + else if (type > (int)TagType.UUID) // ZNI: Other data types are supported + { + throw new Exception("NBT tag type out of range: " + type); + } + return (TagType)type; + } + + + public override short ReadInt16() + { + if (swapNeeded) + { + return Swap(base.ReadInt16()); + } + else + { + return base.ReadInt16(); + } + } + + + public override int ReadInt32() + { + if (swapNeeded) + { + return Swap(base.ReadInt32()); + } + else + { + return base.ReadInt32(); + } + } + + + public override long ReadInt64() + { + if (swapNeeded) + { + return Swap(base.ReadInt64()); + } + else + { + return base.ReadInt64(); + } + } + + + public override float ReadSingle() + { + if (swapNeeded) + { + FillBuffer(sizeof(float)); + Array.Reverse(buffer, 0, sizeof(float)); + return BitConverter.ToSingle(buffer, 0); + } + else + { + return base.ReadSingle(); + } + } + + + public override double ReadDouble() + { + if (swapNeeded) + { + FillBuffer(sizeof(double)); + Array.Reverse(buffer); + return BitConverter.ToDouble(buffer, 0); + } + return base.ReadDouble(); + } + + + public override string ReadString() + { + short length = ReadInt16(); + if (length < 0) + { + throw new Exception("Negative string length given!"); + } + if (length < stringConversionBuffer.Length) + { + int stringBytesRead = 0; + while (stringBytesRead < length) + { + int bytesToRead = length - stringBytesRead; + int bytesReadThisTime = BaseStream.Read(stringConversionBuffer, stringBytesRead, bytesToRead); + if (bytesReadThisTime == 0) + { + throw new EndOfStreamException(); + } + stringBytesRead += bytesReadThisTime; + } + return Encoding.UTF8.GetString(stringConversionBuffer, 0, length); + } + else + { + byte[] stringData = ReadBytes(length); + if (stringData.Length < length) + { + throw new EndOfStreamException(); + } + return Encoding.UTF8.GetString(stringData); + } + } + + + public void Skip(int bytesToSkip) + { + if (bytesToSkip < 0) + { + throw new ArgumentOutOfRangeException("bytesToSkip"); + } + else if (BaseStream.CanSeek) + { + BaseStream.Position += bytesToSkip; + } + else if (bytesToSkip != 0) + { + if (seekBuffer == null) seekBuffer = new byte[SeekBufferSize]; + int bytesSkipped = 0; + while (bytesSkipped < bytesToSkip) + { + int bytesToRead = Math.Min(SeekBufferSize, bytesToSkip - bytesSkipped); + int bytesReadThisTime = BaseStream.Read(seekBuffer, 0, bytesToRead); + if (bytesReadThisTime == 0) + { + throw new EndOfStreamException(); + } + bytesSkipped += bytesReadThisTime; + } + } + } + + + new void FillBuffer(int numBytes) + { + int offset = 0; + do + { + int num = BaseStream.Read(buffer, offset, numBytes - offset); + if (num == 0) throw new EndOfStreamException(); + offset += num; + } while (offset < numBytes); + } + + + public void SkipString() + { + short length = ReadInt16(); + if (length < 0) + { + throw new Exception("Negative string length given!"); + } + Skip(length); + } + + + [DebuggerStepThrough] + static short Swap(short v) + { + unchecked + { + return (short)((v >> 8) & 0x00FF | + (v << 8) & 0xFF00); + } + } + + + [DebuggerStepThrough] + static int Swap(int v) + { + unchecked + { + var v2 = (uint)v; + return (int)((v2 >> 24) & 0x000000FF | + (v2 >> 8) & 0x0000FF00 | + (v2 << 8) & 0x00FF0000 | + (v2 << 24) & 0xFF000000); + } + } + + + [DebuggerStepThrough] + static long Swap(long v) + { + unchecked + { + return (Swap((int)v) & uint.MaxValue) << 32 | + Swap((int)(v >> 32)) & uint.MaxValue; + } + } + + // ZNI Removed selector. Not needed for the ZNI NBT implementation + } +} diff --git a/Serialization/NBTWriter.cs b/Serialization/NBTWriter.cs new file mode 100644 index 0000000..80cc669 --- /dev/null +++ b/Serialization/NBTWriter.cs @@ -0,0 +1,263 @@ +// DISCLAIMER: Taken from fNBT to be altered to fit the needs of ZNI NBT +// All credit for the implementation of this file should go to the fNBT Authors, unless stated otherwise by comment! + +using LibZNI.Serialization.ZNIFile; +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Text; + +namespace LibZNI.Serialization +{ + /// BinaryWriter wrapper that writes NBT primitives to a stream, + /// while taking care of endianness and string encoding, and counting bytes written. + public sealed unsafe class NBTWriter + { + // Write at most 4 MiB at a time. + public const int MaxWriteChunk = 4 * 1024 * 1024; + + // Encoding can be shared among all instances of NbtBinaryWriter, because it is stateless. + static readonly UTF8Encoding Encoding = new UTF8Encoding(false, true); + + // Each instance has to have its own encoder, because it does maintain state. + readonly Encoder encoder = Encoding.GetEncoder(); + + public Stream BaseStream + { + get + { + stream.Flush(); + return stream; + } + } + + readonly Stream stream; + + // Buffer used for temporary conversion + const int BufferSize = 256; + + // UTF8 characters use at most 4 bytes each. + const int MaxBufferedStringLength = BufferSize / 4; + + // Each NbtBinaryWriter needs to have its own instance of the buffer. + readonly byte[] buffer = new byte[BufferSize]; + + // Swap is only needed if endianness of the runtime differs from desired NBT stream + readonly bool swapNeeded; + + + public NBTWriter( Stream input, bool bigEndian) + { + if (input == null) throw new ArgumentNullException("input"); + if (!input.CanWrite) throw new ArgumentException("Given stream must be writable", "input"); + stream = input; + swapNeeded = (BitConverter.IsLittleEndian == bigEndian); + } + + + public void Write(byte value) + { + stream.WriteByte(value); + } + + + public void Write(TagType value) + { + stream.WriteByte((byte)value); + } + + + public void Write(short value) + { + unchecked + { + if (swapNeeded) + { + buffer[0] = (byte)(value >> 8); + buffer[1] = (byte)value; + } + else + { + buffer[0] = (byte)value; + buffer[1] = (byte)(value >> 8); + } + } + stream.Write(buffer, 0, 2); + } + + + public void Write(int value) + { + unchecked + { + if (swapNeeded) + { + buffer[0] = (byte)(value >> 24); + buffer[1] = (byte)(value >> 16); + buffer[2] = (byte)(value >> 8); + buffer[3] = (byte)value; + } + else + { + buffer[0] = (byte)value; + buffer[1] = (byte)(value >> 8); + buffer[2] = (byte)(value >> 16); + buffer[3] = (byte)(value >> 24); + } + } + stream.Write(buffer, 0, 4); + } + + + public void Write(long value) + { + unchecked + { + if (swapNeeded) + { + buffer[0] = (byte)(value >> 56); + buffer[1] = (byte)(value >> 48); + buffer[2] = (byte)(value >> 40); + buffer[3] = (byte)(value >> 32); + buffer[4] = (byte)(value >> 24); + buffer[5] = (byte)(value >> 16); + buffer[6] = (byte)(value >> 8); + buffer[7] = (byte)value; + } + else + { + buffer[0] = (byte)value; + buffer[1] = (byte)(value >> 8); + buffer[2] = (byte)(value >> 16); + buffer[3] = (byte)(value >> 24); + buffer[4] = (byte)(value >> 32); + buffer[5] = (byte)(value >> 40); + buffer[6] = (byte)(value >> 48); + buffer[7] = (byte)(value >> 56); + } + } + stream.Write(buffer, 0, 8); + } + + + public void Write(float value) + { + ulong tmpValue = *(uint*)&value; + unchecked + { + if (swapNeeded) + { + buffer[0] = (byte)(tmpValue >> 24); + buffer[1] = (byte)(tmpValue >> 16); + buffer[2] = (byte)(tmpValue >> 8); + buffer[3] = (byte)tmpValue; + } + else + { + buffer[0] = (byte)tmpValue; + buffer[1] = (byte)(tmpValue >> 8); + buffer[2] = (byte)(tmpValue >> 16); + buffer[3] = (byte)(tmpValue >> 24); + } + } + stream.Write(buffer, 0, 4); + } + + + public void Write(double value) + { + ulong tmpValue = *(ulong*)&value; + unchecked + { + if (swapNeeded) + { + buffer[0] = (byte)(tmpValue >> 56); + buffer[1] = (byte)(tmpValue >> 48); + buffer[2] = (byte)(tmpValue >> 40); + buffer[3] = (byte)(tmpValue >> 32); + buffer[4] = (byte)(tmpValue >> 24); + buffer[5] = (byte)(tmpValue >> 16); + buffer[6] = (byte)(tmpValue >> 8); + buffer[7] = (byte)tmpValue; + } + else + { + buffer[0] = (byte)tmpValue; + buffer[1] = (byte)(tmpValue >> 8); + buffer[2] = (byte)(tmpValue >> 16); + buffer[3] = (byte)(tmpValue >> 24); + buffer[4] = (byte)(tmpValue >> 32); + buffer[5] = (byte)(tmpValue >> 40); + buffer[6] = (byte)(tmpValue >> 48); + buffer[7] = (byte)(tmpValue >> 56); + } + } + stream.Write(buffer, 0, 8); + } + + + // Based on BinaryWriter.Write(String) + public void Write(string value) + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + + // Write out string length (as number of bytes) + int numBytes = Encoding.GetByteCount(value); + Write((short)numBytes); + + if (numBytes <= BufferSize) + { + // If the string fits entirely in the buffer, encode and write it as one + Encoding.GetBytes(value, 0, value.Length, buffer, 0); + stream.Write(buffer, 0, numBytes); + } + else + { + // Aggressively try to not allocate memory in this loop for runtime performance reasons. + // Use an Encoder to write out the string correctly (handling surrogates crossing buffer + // boundaries properly). + int charStart = 0; + int numLeft = value.Length; + while (numLeft > 0) + { + // Figure out how many chars to process this round. + int charCount = (numLeft > MaxBufferedStringLength) ? MaxBufferedStringLength : numLeft; + int byteLen; + fixed (char* pChars = value) + { + fixed (byte* pBytes = buffer) + { + byteLen = encoder.GetBytes(pChars + charStart, charCount, pBytes, BufferSize, + charCount == numLeft); + } + } + stream.Write(buffer, 0, byteLen); + charStart += charCount; + numLeft -= charCount; + } + } + } + + + public void Write(byte[] data, int offset, int count) + { + int written = 0; + while (written < count) + { + int toWrite = Math.Min(MaxWriteChunk, count - written); + stream.Write(data, offset + written, toWrite); + written += toWrite; + } + } + + // Aria : Added a NBT compatible shortcut method for writing a byte array with the length prefix + public void Write(byte[] bytes) + { + this.Write(bytes.Length); + this.Write(bytes, 0, bytes.Length); + } + } +} diff --git a/Serialization/SerializingHelper.cs b/Serialization/SerializingHelper.cs new file mode 100644 index 0000000..e3f053c --- /dev/null +++ b/Serialization/SerializingHelper.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LibZNI.Serialization +{ + public static class SerializingHelper + { + private static int SEGMENT_BITS = 0x7F; + private static int CONTINUE_BIT = 0x80; + /// + /// Adapted from code from wiki.vg + /// + /// + /// + public static void WriteVarInt(this BinaryWriter bw, int value) + { + while (true) + { + if ((value & ~SEGMENT_BITS) == 0) + { + bw.Write((byte)value); + return; + } + + byte b = (byte)((value & SEGMENT_BITS) | CONTINUE_BIT); + bw.Write(b); + + value >>>= 7; + } + } + + public static int ReadVarInt(this BinaryReader br) + { + int value = 0; + int position = 0; + byte curByte; + + while (true) + { + curByte = br.ReadByte(); + value |= (curByte & SEGMENT_BITS) << position; + if ((curByte & CONTINUE_BIT) == 0) break; + + position += 7; + + if (position >= 32) throw new VarIntSizeException("Too large"); + } + + return value; + } + + public static void WriteVarLong(this BinaryWriter bw, long value) + { + while (true) + { + if ((value & ~((long)SEGMENT_BITS)) == 0) + { + byte bx = (byte)value; + bw.Write(bx); + return; + } + byte b = (byte)((value & SEGMENT_BITS) | CONTINUE_BIT); + bw.Write(b); + value >>>= 7; + } + } + + public static long ReadVarLong(this BinaryReader br) + { + long value = 0; + int position = 0; + byte curByte; + while (true) + { + curByte = br.ReadByte(); + value |= (long)(curByte & SEGMENT_BITS) << position; + + if ((curByte & CONTINUE_BIT) == 0) break; + + position += 7; + + if (position >= 64) throw new VarLongSizeException("Too large"); + } + + return value; + } + + /// + /// Applies ZigZag Encoding to the integer + /// + /// + /// + public static int ZigZag(this int i) + { + return Math.Abs((i + i) + ((i < 0) ? 1 : 0)); + } + /// + /// Undoes the zigzag encoding on a integer + /// + /// + /// + public static int DeZigZag(this int i) + { + if ((i % 2) == 0) + { + // Even number. Divide by two + return (i / 2); + } + else + { + int x = i - 1; + x = -i; + return x; + } + } + + + /// + /// Applies ZigZag Encoding to the integer + /// + /// + /// + public static long ZigZag(this long i) + { + return Math.Abs((i + i) + ((i < 0L) ? 1L : 0L)); + } + /// + /// Undoes the zigzag encoding on a integer + /// + /// + /// + public static long DeZigZag(this long i) + { + if ((i % 2) == 0) + { + // Even number. Divide by two + return (i / 2L); + } + else + { + long x = i - 1L; + x = -i; + return x; + } + } + + + } + + public class VarIntSizeException : Exception + { + public VarIntSizeException(string Message) : base(Message) { } + } + public class VarLongSizeException : Exception + { + public VarLongSizeException(string Message) : base(Message) { } + } +} diff --git a/Serialization/TagIO.cs b/Serialization/TagIO.cs index ccd5c95..445a830 100644 --- a/Serialization/TagIO.cs +++ b/Serialization/TagIO.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -16,8 +17,9 @@ namespace LibZNI.Serialization { public static void WriteOnStream(Stream s, Tag x) { - BinaryWriter bw = new BinaryWriter(s); + NBTWriter bw = new NBTWriter(s, true); x.WriteTag(bw); + x.WriteData(bw); } public static Folder ReadFromStream(Stream s) @@ -26,8 +28,8 @@ namespace LibZNI.Serialization { Folder folder = new Folder(); - BinaryReader br = new BinaryReader(s); - TagType type = (TagType)br.ReadInt32(); + NBTReader br = new NBTReader(s,true); + TagType type = (TagType)br.ReadByte(); if (type == TagType.FOLDER) { // Read the file! @@ -41,15 +43,23 @@ namespace LibZNI.Serialization } } - public static void SaveToFile(string FileName, Tag x) + public static void SaveToFile(string FileName, Tag x, bool gz=false) { - FileStream fs = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); + if(File.Exists(FileName))File.Delete(FileName); + Stream fs = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); + if (gz){ + fs = new GZipStream(fs, CompressionLevel.SmallestSize); + } WriteOnStream(fs, x); fs.Close(); } - public static Folder ReadFromFile(string FileName) + public static Folder ReadFromFile(string FileName, bool gz = false) { - FileStream fs = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); + Stream fs = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite); + if (gz) + { + fs = new GZipStream(fs, CompressionMode.Decompress); + } Folder f = ReadFromStream(fs); fs.Close(); return f; diff --git a/Serialization/ZNIFile/BoolTag.cs b/Serialization/ZNIFile/BoolTag.cs index 5b94801..2c55e7f 100644 --- a/Serialization/ZNIFile/BoolTag.cs +++ b/Serialization/ZNIFile/BoolTag.cs @@ -35,12 +35,9 @@ namespace LibZNI.Serialization.ZNIFile return TagType.BOOL; } } - - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); - BoolVal = br.ReadBoolean(); - return true; + throw new NotImplementedException(); } public override void Rename(string old, string newName) @@ -48,27 +45,49 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new BoolTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); + Folder vFolder = new Folder(Name); + vFolder.Add(new ByteTag("val", (byte)(Value ? 1 : 0))); + vFolder.Add(new ByteTag("_virtcast_", (byte)Type)); + if(Parent != null) + { + if(Parent.Type == TagType.LIST) + { + vFolder.Add(new StringTag("name", Name)); + } + } + vFolder.WriteTag(bw); + vFolder.WriteData(bw); } - public override void WriteTag(BinaryWriter bw) + public override void WriteTag(NBTWriter bw) { - bw.Write(((int)Type)); - bw.Write(Name); - bw.Write(Value); } public override object Clone() { return new BoolTag(Name, Value); } + + public override void CastFrom(Folder F) + { + if (!F.HasNamedTag("name")) + Name = F.Name; + else Name = F["name"].StringValue; + + int ret = F["val"].IntValue; + if (ret == 1) BoolVal = true; + else BoolVal = false; + + + } + } } diff --git a/Serialization/ZNIFile/ByteArrayTag.cs b/Serialization/ZNIFile/ByteArrayTag.cs index a606ae9..15cce94 100644 --- a/Serialization/ZNIFile/ByteArrayTag.cs +++ b/Serialization/ZNIFile/ByteArrayTag.cs @@ -35,12 +35,12 @@ namespace LibZNI.Serialization.ZNIFile return TagType.BYTEARRAY; } } - - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); - int count = br.ReadInt32(); - BArrVal = br.ReadBytes(count); + if(!(Parent!= null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); + BArrVal = br.ReadBytes(br.ReadInt32()); + return true; } @@ -49,28 +49,35 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new ByteArrayTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); + + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); + bw.Write(Value); } - public override void WriteTag(BinaryWriter bw) + public override void WriteTag(NBTWriter bw) { - bw.Write(((int)Type)); - bw.Write(Name); - bw.Write(Value.Length); + bw.Write(Type); - bw.Write(Value); + } public override object Clone() { return new ByteArrayTag(Name, Value); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } + } } diff --git a/Serialization/ZNIFile/ByteTag.cs b/Serialization/ZNIFile/ByteTag.cs index c9224c4..1dfdde7 100644 --- a/Serialization/ZNIFile/ByteTag.cs +++ b/Serialization/ZNIFile/ByteTag.cs @@ -36,9 +36,11 @@ namespace LibZNI.Serialization.ZNIFile } } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); + + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); ByteVal = br.ReadByte(); return true; } @@ -48,27 +50,34 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new ByteTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); + bw.Write(Value); } - public override void WriteTag(BinaryWriter bw) + public override void WriteTag(NBTWriter bw) { - bw.Write(((int)Type)); - bw.Write(Name); + bw.Write(Type); - bw.Write(Value); } public override object Clone() { return new ByteTag(Name, Value); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } + } } diff --git a/Serialization/ZNIFile/DoubleTag.cs b/Serialization/ZNIFile/DoubleTag.cs index 46bd055..5464363 100644 --- a/Serialization/ZNIFile/DoubleTag.cs +++ b/Serialization/ZNIFile/DoubleTag.cs @@ -38,10 +38,10 @@ namespace LibZNI.Serialization.ZNIFile { return new DoubleTag(Name, Value); } - - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); DoubleVal = br.ReadDouble(); return true; } @@ -51,20 +51,27 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new DoubleTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) + { + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); + bw.Write(Value); + } + + public override void WriteTag(NBTWriter bw) + { + bw.Write(Type); + + } + + public override void CastFrom(Folder F) { throw new NotImplementedException(); } - - public override void WriteTag(BinaryWriter bw) - { - bw.Write(Name); - bw.Write(Value); - } } } diff --git a/Serialization/ZNIFile/FloatTag.cs b/Serialization/ZNIFile/FloatTag.cs index 5b037be..231bca1 100644 --- a/Serialization/ZNIFile/FloatTag.cs +++ b/Serialization/ZNIFile/FloatTag.cs @@ -35,10 +35,10 @@ namespace LibZNI.Serialization.ZNIFile return TagType.FLOAT; } } - - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); FloatVal = br.ReadSingle(); return true; } @@ -48,27 +48,32 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new FloatTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); + bw.Write(Value); } - public override void WriteTag(BinaryWriter bw) + public override void WriteTag(NBTWriter bw) { - bw.Write(((int)Type)); - bw.Write(Name); + bw.Write(Type); - bw.Write(Value); } public override object Clone() { return new FloatTag(Name, Value); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } } } diff --git a/Serialization/ZNIFile/Folder.cs b/Serialization/ZNIFile/Folder.cs index 8f72082..8616c37 100644 --- a/Serialization/ZNIFile/Folder.cs +++ b/Serialization/ZNIFile/Folder.cs @@ -140,27 +140,22 @@ namespace LibZNI.Serialization.ZNIFile } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - if(Parent != null) - { - SkipTag(br); - return false; - } - Name = br.ReadString(); // Per ZNIFile standards, each tag reads its own name! + // Aria: Removed a return on parent not being null because that is how the ZNI Parsing system works. + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); - while(true) + + while (true) { - TagType next = (TagType)br.ReadInt32(); + TagType next = br.ReadTagType(); Tag _next = null; switch (next) { case TagType.FOLDER: _next = new Folder(); break; - case TagType.BOOL: - _next = new BoolTag(); - break; case TagType.BYTE: _next = new ByteTag(); break; @@ -193,37 +188,80 @@ namespace LibZNI.Serialization.ZNIFile break; case TagType.END: return true; + + case TagType.SHORT: + _next = new ShortTag(); + break; } + _next.Parent = this; if (_next.ReadTag(br)) { + if (_next.Type == TagType.FOLDER) + { + Folder NextTag = _next as Folder; + if (NextTag.HasNamedTag("_virtcast_")) + { + ByteTag bt = NextTag["_virtcast_"] as ByteTag; + next = (TagType)bt.Value; + Tag temp = null; + switch (next) + { + case TagType.BOOL: + temp = new BoolTag(); + temp.CastFrom(NextTag); + break; + case TagType.ULONG: + temp = new uLongTag(); + temp.CastFrom(NextTag); + break; + case TagType.UUID: + temp = new UUIDTag(); + temp.CastFrom(NextTag); + break; + } + _next = temp; + } + + } Tags.Add(_next); } - _next.Parent = this; } + return true; + } + + public bool HasNamedTag(string Name) + { + foreach(Tag t in Tags) + { + if(t.Name == Name) return true; + } + return false; } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new Folder().ReadTag(br); } - public override void WriteData(BinaryWriter bw) - { - throw new NotImplementedException(); - } - public override void WriteTag(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - bw.Write(((int)Type)); // Write int (0), folder - bw.Write(Name); - + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); foreach (Tag t in Tags) { t.WriteTag(bw); + t.WriteData(bw); } - bw.Write(((int)TagType.END)); + bw.Write(TagType.END); + } + + public override void WriteTag(NBTWriter bw) + { + bw.Write(Type); // Write int (0), folder + } IEnumerator IEnumerable.GetEnumerator() @@ -246,5 +284,10 @@ namespace LibZNI.Serialization.ZNIFile Name = existing.Name; Tags = new Collection(Tags.ToArray()); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } } } diff --git a/Serialization/ZNIFile/Header.cs b/Serialization/ZNIFile/Header.cs deleted file mode 100644 index 683deaf..0000000 --- a/Serialization/ZNIFile/Header.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LibZNI.Serialization.ZNIFile -{ - public class Header : Serializable - { - public const string SIGNATURE = "ZNIFile"; - public Version VERSION = new Version(1,0,0,1,0,0); - - public override void load(Folder f) - { - - Folder x = f["Header"] as Folder; - if (x == null) return; - - if (x["Signature"].StringValue == SIGNATURE) - { - Version ver = new Version(); - ver.load(f); - if (VERSION.Compare(ver) == 0) - { - return; - } else throw new VersionNumberDifferentException(VERSION, ver); - - }else - { - throw new Exception("Header failed validation"); - } - } - - public override void save(Folder f) - { - Folder x = new Folder("Header"); - x.Add(new StringTag("Signature", SIGNATURE)); - VERSION.save(x); - - f.Add(x); - } - - public static Folder GetHeader() - { - Folder f = new Folder("temp"); // Initialize a temporary header - Header x = new Header(); - x.save(f); - return f["Header"] as Folder; - } - } -} diff --git a/Serialization/ZNIFile/IntArrayTag.cs b/Serialization/ZNIFile/IntArrayTag.cs index 8b49762..b925c25 100644 --- a/Serialization/ZNIFile/IntArrayTag.cs +++ b/Serialization/ZNIFile/IntArrayTag.cs @@ -36,16 +36,18 @@ namespace LibZNI.Serialization.ZNIFile } } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); + int count = br.ReadInt32(); + BArrVal = new int[count]; - for(int i = 0; i < count; i++) + for (int i = 0; i < count; i++) { BArrVal[i] = br.ReadInt32(); } - return true; } @@ -54,31 +56,38 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new IntArrayTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); - } - public override void WriteTag(BinaryWriter bw) - { - bw.Write(((int)Type)); - bw.Write(Name); + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); bw.Write(Value.Length); - foreach(int i in Value) + foreach (int i in Value) { bw.Write(i); } } + public override void WriteTag(NBTWriter bw) + { + bw.Write(Type); + + } + public override object Clone() { return new IntArrayTag(Name, Value); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } } } diff --git a/Serialization/ZNIFile/IntTag.cs b/Serialization/ZNIFile/IntTag.cs index f87083b..861efbb 100644 --- a/Serialization/ZNIFile/IntTag.cs +++ b/Serialization/ZNIFile/IntTag.cs @@ -36,28 +36,31 @@ namespace LibZNI.Serialization.ZNIFile } } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); + IntVal = br.ReadInt32(); return true; } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new IntTag().ReadTag(br); } - public override void WriteTag(BinaryWriter bw) + public override void WriteTag(NBTWriter bw) { - bw.Write(((int)Type)); - bw.Write(Name); - bw.Write(Value); + bw.Write(Type); + } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); + bw.Write(Value); } public override void Rename(string old, string newName) { @@ -68,5 +71,10 @@ namespace LibZNI.Serialization.ZNIFile { return new IntTag(Name, Value); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } } } diff --git a/Serialization/ZNIFile/ListTag.cs b/Serialization/ZNIFile/ListTag.cs index 881f9ff..238cf89 100644 --- a/Serialization/ZNIFile/ListTag.cs +++ b/Serialization/ZNIFile/ListTag.cs @@ -5,12 +5,13 @@ using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using static System.Net.Mime.MediaTypeNames; namespace LibZNI.Serialization.ZNIFile { public class ListTag : Tag, IList, IList { - private TagType _subtype; + private TagType _subtype = TagType.INVALID; private List _tags; public List Value { @@ -105,15 +106,19 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - _subtype = (TagType)br.ReadInt32(); - Name = br.ReadString(); - while (true) + //_subtype = (TagType)br.ReadInt32(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); + _subtype = br.ReadTagType(); + int count = br.ReadInt32(); + TagType next = _subtype; + for (int i = 0; i < count; i++) { - TagType next = (TagType)br.ReadInt32(); Tag _next = null; - switch(next) + // read sub-tags + switch (next) { case TagType.FOLDER: _next = new Folder(); @@ -151,17 +156,45 @@ namespace LibZNI.Serialization.ZNIFile case TagType.LONGARRAY: _next = new LongArrayTag(); break; - case TagType.END: - return true; - } - - if (_next.ReadTag(br)) - { - _tags.Add(_next); + case TagType.SHORT: + _next = new ShortTag(); + break; } _next.Parent = this; - + if (_next.ReadTag(br)) + { + if (_next.Type == TagType.FOLDER) + { + Folder nxt = _next as Folder; + if (nxt.HasNamedTag("_virtcast_")) + { + TagType tag = (TagType)nxt["_virtcast_"].ByteValue; + Tag temp = null; + switch (tag) + { + case TagType.BOOL: + temp = new BoolTag(); + temp.CastFrom(nxt); + break; + case TagType.ULONG: + temp = new uLongTag(); + temp.CastFrom(nxt); + break; + case TagType.UUID: + temp = new UUIDTag(); + temp.CastFrom(nxt); + break; + + } + _next = temp; + } + } + _tags.Add(_next); + } + + } + return true; } public override void Rename(string old, string newName) @@ -169,28 +202,31 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new ListTag(_subtype).ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); + + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); + bw.Write(_subtype); + bw.Write(_tags.Count); + + foreach (Tag x in _tags) + { + x.WriteData(bw); + } } - public override void WriteTag(BinaryWriter bw) + public override void WriteTag(NBTWriter bw) { - bw.Write(((int)Type)); - bw.Write(((int)_subtype)); - bw.Write(Name); - - foreach(Tag x in _tags) - { - x.WriteTag(bw); - } + bw.Write(Type); - bw.Write(((int)TagType.END)); + + //bw.Write(((int)TagType.END)); } public int Add(object value) @@ -290,5 +326,10 @@ namespace LibZNI.Serialization.ZNIFile { return _tags.GetEnumerator(); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } } } diff --git a/Serialization/ZNIFile/LongArrayTag.cs b/Serialization/ZNIFile/LongArrayTag.cs index 471951a..21593a5 100644 --- a/Serialization/ZNIFile/LongArrayTag.cs +++ b/Serialization/ZNIFile/LongArrayTag.cs @@ -36,10 +36,11 @@ namespace LibZNI.Serialization.ZNIFile } } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); - int count = br.ReadInt32(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); + int count = br.ReadVarInt(); BArrVal = new long[count]; for(int i = 0; i < count; i++) { @@ -54,31 +55,36 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new LongArrayTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); - } - - public override void WriteTag(BinaryWriter bw) - { - bw.Write(((int)Type)); - bw.Write(Name); + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); bw.Write(Value.Length); - foreach(int i in Value) + foreach (long i in Value) { bw.Write(i); } } + public override void WriteTag(NBTWriter bw) + { + bw.Write(Type); + } + public override object Clone() { return new LongArrayTag(Name, Value); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } } } diff --git a/Serialization/ZNIFile/LongTag.cs b/Serialization/ZNIFile/LongTag.cs index b2ce767..abf4c5b 100644 --- a/Serialization/ZNIFile/LongTag.cs +++ b/Serialization/ZNIFile/LongTag.cs @@ -36,9 +36,10 @@ namespace LibZNI.Serialization.ZNIFile } } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); LongVal = br.ReadInt64(); return true; } @@ -48,27 +49,32 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new LongTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); - } - - public override void WriteTag(BinaryWriter bw) - { - bw.Write(((int)Type)); - bw.Write(Name); + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); bw.Write(Value); } + public override void WriteTag(NBTWriter bw) + { + bw.Write(Type); + } + public override object Clone() { return new LongTag(Name, Value); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } } } diff --git a/Serialization/ZNIFile/ShortTag.cs b/Serialization/ZNIFile/ShortTag.cs index 7bc47a9..130b772 100644 --- a/Serialization/ZNIFile/ShortTag.cs +++ b/Serialization/ZNIFile/ShortTag.cs @@ -36,9 +36,10 @@ namespace LibZNI.Serialization.ZNIFile } } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); FloatVal = br.ReadInt16(); return true; } @@ -48,27 +49,32 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new ShortTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); - } - - public override void WriteTag(BinaryWriter bw) - { - bw.Write(((int)Type)); - bw.Write(Name); + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); bw.Write(Value); } + public override void WriteTag(NBTWriter bw) + { + bw.Write(Type); + } + public override object Clone() { return new ShortTag(Name, Value); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } } } diff --git a/Serialization/ZNIFile/StringTag.cs b/Serialization/ZNIFile/StringTag.cs index 3ddbbb7..02c014e 100644 --- a/Serialization/ZNIFile/StringTag.cs +++ b/Serialization/ZNIFile/StringTag.cs @@ -37,9 +37,10 @@ namespace LibZNI.Serialization.ZNIFile StrVal = Val; } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + Name = br.ReadString(); StrVal = br.ReadString(); return true; } @@ -49,27 +50,32 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { - _ = br.ReadString(); - _ = br.ReadString(); + _ = new StringTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); + if (!(Parent != null && Parent.Type == TagType.LIST)) + bw.Write(Name); + + bw.Write(StrVal); } - public override void WriteTag(BinaryWriter bw) + public override void WriteTag(NBTWriter bw) { - bw.Write(((int)Type)); - bw.Write(Name); - bw.Write(Value); + bw.Write(Type); } public override object Clone() { return new StringTag(Name, Value); } + + public override void CastFrom(Folder F) + { + throw new NotImplementedException(); + } } } diff --git a/Serialization/ZNIFile/Tag.cs b/Serialization/ZNIFile/Tag.cs index ac12c29..8d63ad1 100644 --- a/Serialization/ZNIFile/Tag.cs +++ b/Serialization/ZNIFile/Tag.cs @@ -53,10 +53,12 @@ namespace LibZNI.Serialization.ZNIFile } } - public abstract bool ReadTag(BinaryReader br); - public abstract void SkipTag(BinaryReader br); - public abstract void WriteTag(BinaryWriter bw); - public abstract void WriteData(BinaryWriter bw); + public abstract bool ReadTag(NBTReader br); + public abstract void SkipTag(NBTReader br); + public abstract void WriteTag(NBTWriter bw); + public abstract void WriteData(NBTWriter bw); + + public abstract void CastFrom(Folder F); private string Error = "Invalid tag type"; public virtual Tag this[int index] diff --git a/Serialization/ZNIFile/TagType.cs b/Serialization/ZNIFile/TagType.cs index 1282139..329fc6b 100644 --- a/Serialization/ZNIFile/TagType.cs +++ b/Serialization/ZNIFile/TagType.cs @@ -6,27 +6,28 @@ using System.Threading.Tasks; namespace LibZNI.Serialization.ZNIFile { - public enum TagType + // Aria: Changed to a type of byte which keeps it to only one byte when writing out in serializing + public enum TagType : byte { - END = 0, // Present at the end of a folder or list - BYTE = 1, - SHORT = 2, - INTEGER = 3, - LONG = 4, - FLOAT = 5, - DOUBLE = 6, - BYTEARRAY = 7, - STRING = 8, - LIST = 9, // List can be any valid Tag Type - FOLDER = 10, - INTARRAY = 11, - LONGARRAY = 12, - BOOL = 13, - ULONG=14, - UUID=15, + END = 0x00, // Present at the end of a folder + BYTE = 0x01, + SHORT = 0x02, + INTEGER = 0x03, + LONG = 0x04, + FLOAT = 0x05, + DOUBLE = 0x06, + BYTEARRAY = 0x07, + STRING = 0x08, + LIST = 0x09, // List can be any valid Tag Type + FOLDER = 0x0A, + INTARRAY = 0x0B, + LONGARRAY = 0x0C, + BOOL = 0x0D, + ULONG=0x0E, + UUID=0x0F, - INVALID=99 + INVALID=0xFF } } diff --git a/Serialization/ZNIFile/UUIDTag.cs b/Serialization/ZNIFile/UUIDTag.cs index 1c4fb0b..dd49079 100644 --- a/Serialization/ZNIFile/UUIDTag.cs +++ b/Serialization/ZNIFile/UUIDTag.cs @@ -48,11 +48,9 @@ namespace LibZNI.Serialization.ZNIFile } } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); - LongVal = Guid.Parse(br.ReadString()); - return true; + throw new Exception("Must be virtcasted!"); } public override void Rename(string old, string newName) @@ -60,27 +58,43 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new UUIDTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); + Folder vCast = new Folder(Name); + vCast.Add(new ByteTag("_virtcast_", (byte)Type)); + vCast.Add(new ByteArrayTag("val", Value.ToByteArray())); + if (Parent != null) + { + if (Parent.Type == TagType.LIST) + { + vCast.Add(new StringTag("name", Name)); + } + } + vCast.WriteTag(bw); + vCast.WriteData(bw); } - public override void WriteTag(BinaryWriter bw) + public override void WriteTag(NBTWriter bw) { - bw.Write(((int)Type)); - bw.Write(Name); - - bw.Write(Value.ToString()); } public override object Clone() { return new UUIDTag(Name, Value); } + + public override void CastFrom(Folder F) + { + if (!F.HasNamedTag("name")) + Name = F.Name; + else Name = F["name"].StringValue; + ByteArrayTag bat = F["val"] as ByteArrayTag; + LongVal = new Guid(bat.Value); + } } } diff --git a/Serialization/ZNIFile/ulongTag.cs b/Serialization/ZNIFile/ulongTag.cs index 771dd64..48df36d 100644 --- a/Serialization/ZNIFile/ulongTag.cs +++ b/Serialization/ZNIFile/ulongTag.cs @@ -36,11 +36,9 @@ namespace LibZNI.Serialization.ZNIFile } } - public override bool ReadTag(BinaryReader br) + public override bool ReadTag(NBTReader br) { - Name = br.ReadString(); - LongVal = br.ReadUInt64(); - return true; + throw new Exception("Not allowed"); // This type must be virtual casted } public override void Rename(string old, string newName) @@ -48,27 +46,43 @@ namespace LibZNI.Serialization.ZNIFile throw new NotImplementedException(); } - public override void SkipTag(BinaryReader br) + public override void SkipTag(NBTReader br) { _ = new uLongTag().ReadTag(br); } - public override void WriteData(BinaryWriter bw) + public override void WriteData(NBTWriter bw) { - throw new NotImplementedException(); + Folder vCast = new Folder(Name); + vCast.Add(new ByteTag("_virtcast_", (byte)Type)); + vCast.Add(new StringTag("val", Value.ToString())); + if (Parent != null) + { + if (Parent.Type == TagType.LIST) + { + vCast.Add(new StringTag("name", Name)); + } + } + vCast.WriteTag(bw); + vCast.WriteData(bw); } - public override void WriteTag(BinaryWriter bw) + public override void WriteTag(NBTWriter bw) { - bw.Write(((int)Type)); - bw.Write(Name); - bw.Write(Value); } public override object Clone() { return new uLongTag(Name, Value); } + + public override void CastFrom(Folder F) + { + if (!F.HasNamedTag("name")) + Name = F.Name; + else Name = F["name"].StringValue; + LongVal = ulong.Parse(F["val"].StringValue); + } } }