This release concentrates on cleaning up the code by removing unused or rarely used features, solving boxing issues, removing some hacks, generally reworking the API and increasing the testing coverage. Some minor code changes may be required due to the level of breaking change this release introduces.
A fair chunk of both the library code and test code are now generated via T4 templates.
- With the base
Tag
class no longer offering aValue
property,GetValue
andSetValue
methods are available. However, note that these methods will box value types - The
TagWriter
class can now be used to directly write NBT data to a stream without having to first create concreteTag
classes (e.g. similar to usingXmlWriter
overXmlDocument
) - The base
Tag
class now implementsIEquatable<Tag>
(boxing) - Each concrete tag class now implements
IEquatable<>
(non-boxing) - Added indexers to
TagCompound
- Added
TagCompound.Count
- Added Benchmarks project testing the different serialization methods. Unsurprisingly, XML is many times slower than binary, and writing NBT documents without constructing
Tag
objects is faster than creating and then saving aNbtDocument
- Added new
TagDictionary.AddRange
overloads - All library code is now covered by tests
- All tags created internally by the library use
TagFactory
and avoid all of the boxing issues present in previous versions XmlTagReader
crashed if empty byte or int array values were present- Calling
XmlTagReader.IsNbtDocument
would returntrue
if atype
attribute was found, regardless of if the value wasTagCompound
or not TagDictionary.Add(name, object)
didn't supportTagDictionary
orTagCollection
valuesTagCollection.Add(object)
now correctly supportsTagDictionary
andTagCollection
valuesTagCollection.Add
will now correctly throw exceptions if named tags are added- Resolved an infinite loop reading empty
TagCompound
orTagList
data stored in XML files
- Tag names should now be empty when not set rather than
null
TagReader.ReadCollection
andReadDictionary
renamed toReadList
andReadCompound
to match their NBT types.TagFactory.Create
methods have had their parameters shuffled so thatname
comes first, mirroringTagDictionary
and otherTagFactory
methodsTagCollection
contents will automatically set theListType
based on the first value added when no explicit type is definedTagDictionary.Add
methods now return the appropriate concreteTag
instance for the value's data typeTagCompound.GetBoolValue
renamed toGetBooleanValue
TagCompound.Query
should no longer throw exceptions when a match cannot be found, but instead returnsnull
- Removed the
WriteTagOptions
andReadTagOptions
enumerations, plus removed any overloaded method supplying these options. Each reader and writer now maintains its own state to know when it should or should not be doing things without having to be told - Removed the
ITag
interface as it was a pointless level of abstraction and there is already an abstractTag
class - Similarly,
ITagReader
andITagWriter
have also been removed - Removed the default constructors from tag readers and writers
- Removed the default
Tag.Value
implementation. EachTag
implementation has a strongly typedValue
property without boxing. - Removed all events from the
Tag
object as they added overhead without being used in most use cases - Removed the
TagException
class as it was unused - Removed the
TagEventArgs
class as it was unused - Removed
Tag.ToString(string)
overloads - Removed
Tag.CanRemove
andTag.Remove()
, as they are too situational Tag
properties are no longervirtual
- Removed the
CompressionOptions
enum and related support fromNbtDocument
. When saving to a file, XML will be uncompressed, binary will be gzipped. When saving to aStream
, you can pass in your ownGZipStream
,DeflateStream
or equivalent - All
TagCollection.Add
method overloads that accepted aname
argument have been removed - Removed secondary data type helpers from
TagCollection
- Removed
TagCompound.GetEnumValue
- Added new constructor to
XmlTagWriter
allowing you to specify aXmlWriter
. Useful for when callingWrite*
methods directly, without first usingWriteDocument
- Added new constructor to
XmlTagReader
allowing you to specify aXmlReader
. Useful for when callingRead*
methods directly, without first usingReadDocument
- XML documents that either didn't include any whitespace between elements or that used self closing tags weren't loaded correctly
This major update includes breaking changes, mostly around the ITagReader
and ITagWriter
interfaces and implementing classes. The NbtDocument
class has been updated so that methods such as Load
and Save
now can accept a Stream
rather than always being forced to use a file.
I've also changed the license to the GNU Lesser General Public License, version 2.1. Originally I said it was licensed under Creative Commons Share Alike to match the original code this library was derived from, but it was actually LGPL all along.
- Added overloads accepting
Stream
arguments toLoadDocument
,Load
,Save
,IsNbtDocument
andGetDocumentFormat
methods - When saving a document, you can now specify
Auto
for compression which essentially lets the serializer choose the compression (on for binary, off for XML)
- The
ITagWriter
andITagReader
interfaces have also been intensively refactored to use separate enums for options and compression (seeNbtOptions
in the Removed section), and to use a sourceStream
rather than a filename, and to remove some very silly API designs - The
Custom
value for theNbtFormat
enum has been renamed toInvalid
reflecting the fact that custom support is no longer supported natively - Added (hopefully) correct detection of gzip or deflate streams, removing the awful practice of relying on exceptions to drop between the formats
- All interfaces, classes and enums which strictly deal with serialization or de-serialization have been moved to the
Serialization
namespace - Methods which would previously accept null input, or missing files such as
IsNbtDocument
,GetDocumentName
andGetDocument
format now throw the appropriateArgumentNullException
orFileNotFoundException
exceptions
- Removed the
NbtOptions
enum, replacing it withCompressionOption
,WriteTagOption
andReadTagOption
which appropriate options. TheSingleUse
flag has been fully removed as it was a hack for XML support - Removed the
ITagEditor
interface, theTagEditorAttribute
class and all defined instances ofTagEditor
. The editor support doesn't really belong in the core library, but rather by the separate GUI library. - Removed the
TagReader
andTagWriter
classes as they were fairly pointless - Removed the
ReaderType
andWriterType
properties fromNbtDocument
along with constructors that accepted types,NbtFormat
values, or file names. - Removed the static
NbtDocument.DefaultFormat
property - Removed the static
IsDeflateDocument
,IsGzipDocument
,IsXmlDocument
andIsRawDocument
methods fromNbtDocument
- they never should have been public in the first place, and have been replaced with proper stream detection NbtDocument
no longer supports custom serialization options
- The
ITagWriter
interface is now correctly public
- Reformatted using C# 6 syntax, and minor corrections to avoid double casts
- Added culture info to date conversions
- Added
ToString
overrides toTagCollection
andTagDictionary
- Saving an empty byte array didn't store the zero length size correctly, causing a crash when trying to reload the document. Documents affected by this bug are essentially corrupt and can't be loaded.
- Removed
EnumExtensions
class and replaced allHasFlag
calls with bitwise statements
- Added missing
GetByteValue
toTagCompound
NbtDocument.GetDocumentName
now automatically returnsfalse
if the format of the document is not XML or binary.- Removed exception when lists have a type of 0, as although it makes sense as it's essentially an invalid tag, some Minecraft tags are using zero type lists.
- Added tests for
Tag.ToValueString
ICollectionTag
now explicitly inherits fromITag
so you don't have to cast back to the former if you only have a reference to the latter.- Added new
TagEventArgs
helper class
TagIntArray.ToValueString
andTagByteArray.ToValueString
now return appropriate values instead of the .NET type name for their respective arrays.
- Added
AddRange
method toTagDictionary
- Added
AddRange
andAdd(bool)
methods toTagCollection
- Added tests for
TagDictionary
,TagCollection
andTagEnd
, and added some other tests for classes without full coverage [still more to go] - Added new
NbtOptions.HeaderOnly
flag, allowing the name of a tag to be read without loading the full body
Tag.Value
is now virtual- Setting the value of the
TagEnd
class now has no effect, and retrieving the value always returnsnull
- Calling
NbtDocument.GetDocumentName
no longer loads the entire NBT document to return a single string value TagDictionary.Add(Guid)
andTagCollection.Add(Guid)
now returnITag
instead ofvoid
- Removed
AddIfNotDefault
methods fromTagDictionary
BinaryTagReader.Load
always passed in default options rather than whatever the caller had specified
- Changed
TagEditor
attributes on tag classes to remove fixed version information
- Code refactoring according to Resharper suggestions
- Fixed corrupt document tree and crash when loading XML document with self closing tags
- Added a number of
TagCollection.Add
overloads without thename
parameter to make it somewhat easier to populate lists via code. - Added a few more tests
- Fixed problems trying to load invalid documents with the
NbtDocument
class and having them misidentified as "custom" documents. - Fixed an infinite loop when loading an XML file containing a list tag with no children
- Change history not available in this document