Skip to content

Commit 757e142

Browse files
committed
Support NBT files with roots of any tag type
1 parent 3990f30 commit 757e142

File tree

2 files changed

+55
-65
lines changed

2 files changed

+55
-65
lines changed

fNbt/NbtFile.cs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public sealed class NbtFile {
2525
/// <summary> Root tag of this file. Must be a named CompoundTag. Defaults to an empty-named tag. </summary>
2626
/// <exception cref="ArgumentException"> If given tag is unnamed. </exception>
2727
[NotNull]
28-
public NbtCompound RootTag {
28+
public NbtTag RootTag {
2929
get { return rootTag; }
3030
set {
3131
if (value == null) throw new ArgumentNullException("value");
@@ -34,8 +34,10 @@ public NbtCompound RootTag {
3434
}
3535
}
3636

37+
public T GetRootTag<T>() where T : NbtTag => RootTag as T;
38+
3739
[NotNull]
38-
NbtCompound rootTag;
40+
NbtTag rootTag;
3941

4042
/// <summary> Whether new NbtFiles should default to big-endian encoding (default: true). </summary>
4143
public static bool BigEndianByDefault { get; set; }
@@ -94,7 +96,7 @@ public NbtFile() {
9496
/// <summary> Creates a new NBT file with the given root tag. </summary>
9597
/// <param name="rootTag"> Compound tag to set as the root tag. May be <c>null</c>. </param>
9698
/// <exception cref="ArgumentException"> If given <paramref name="rootTag"/> is unnamed. </exception>
97-
public NbtFile([NotNull] NbtCompound rootTag)
99+
public NbtFile([NotNull] NbtTag rootTag)
98100
: this() {
99101
if (rootTag == null) throw new ArgumentNullException("rootTag");
100102
RootTag = rootTag;
@@ -317,7 +319,18 @@ static NbtCompression DetectCompression([NotNull] Stream stream) {
317319
case -1:
318320
throw new EndOfStreamException();
319321

320-
case (byte)NbtTagType.Compound: // 0x0A
322+
case (byte)NbtTagType.Byte:
323+
case (byte)NbtTagType.Short:
324+
case (byte)NbtTagType.Int:
325+
case (byte)NbtTagType.Long:
326+
case (byte)NbtTagType.Float:
327+
case (byte)NbtTagType.Double:
328+
case (byte)NbtTagType.String:
329+
case (byte)NbtTagType.ByteArray:
330+
case (byte)NbtTagType.IntArray:
331+
case (byte)NbtTagType.LongArray:
332+
case (byte)NbtTagType.Compound:
333+
case (byte)NbtTagType.List:
321334
compression = NbtCompression.None;
322335
break;
323336

@@ -345,16 +358,14 @@ void LoadFromStreamInternal([NotNull] Stream stream, [CanBeNull] TagSelector tag
345358
if (firstByte < 0) {
346359
throw new EndOfStreamException();
347360
}
348-
if (firstByte != (int)NbtTagType.Compound) {
349-
throw new NbtFormatException("Given NBT stream does not start with a TAG_Compound");
350-
}
351361
var reader = new NbtBinaryReader(stream, BigEndian) {
352362
Selector = tagSelector
353363
};
354364

355-
var rootCompound = new NbtCompound(reader.ReadString());
356-
rootCompound.ReadTag(reader);
357-
RootTag = rootCompound;
365+
var rootValue = NbtCompound.CreateTag((NbtTagType)firstByte);
366+
rootValue.Name = reader.ReadString();
367+
rootValue.ReadTag(reader);
368+
RootTag = rootValue;
358369
}
359370

360371
#endregion

fNbt/Tags/NbtCompound.cs

Lines changed: 34 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,37 @@ public IEnumerable<NbtTag> Tags {
292292

293293
#region Reading / Writing
294294

295+
internal static NbtTag CreateTag(NbtTagType type) {
296+
switch (type) {
297+
case NbtTagType.Byte:
298+
return new NbtByte();
299+
case NbtTagType.Short:
300+
return new NbtShort();
301+
case NbtTagType.Int:
302+
return new NbtInt();
303+
case NbtTagType.Long:
304+
return new NbtLong();
305+
case NbtTagType.Float:
306+
return new NbtFloat();
307+
case NbtTagType.Double:
308+
return new NbtDouble();
309+
case NbtTagType.ByteArray:
310+
return new NbtByteArray();
311+
case NbtTagType.String:
312+
return new NbtString();
313+
case NbtTagType.List:
314+
return new NbtList();
315+
case NbtTagType.Compound:
316+
return new NbtCompound();
317+
case NbtTagType.IntArray:
318+
return new NbtIntArray();
319+
case NbtTagType.LongArray:
320+
return new NbtLongArray();
321+
default:
322+
throw new NbtFormatException("Unsupported tag type found: " + type);
323+
}
324+
}
325+
295326
internal override bool ReadTag(NbtBinaryReader readStream) {
296327
if (Parent != null && readStream.Selector != null && !readStream.Selector(this)) {
297328
SkipTag(readStream);
@@ -300,62 +331,10 @@ internal override bool ReadTag(NbtBinaryReader readStream) {
300331

301332
while (true) {
302333
NbtTagType nextTag = readStream.ReadTagType();
303-
NbtTag newTag;
304-
switch (nextTag) {
305-
case NbtTagType.End:
306-
return true;
307-
308-
case NbtTagType.Byte:
309-
newTag = new NbtByte();
310-
break;
311-
312-
case NbtTagType.Short:
313-
newTag = new NbtShort();
314-
break;
315-
316-
case NbtTagType.Int:
317-
newTag = new NbtInt();
318-
break;
319-
320-
case NbtTagType.Long:
321-
newTag = new NbtLong();
322-
break;
323-
324-
case NbtTagType.Float:
325-
newTag = new NbtFloat();
326-
break;
327-
328-
case NbtTagType.Double:
329-
newTag = new NbtDouble();
330-
break;
331-
332-
case NbtTagType.ByteArray:
333-
newTag = new NbtByteArray();
334-
break;
335-
336-
case NbtTagType.String:
337-
newTag = new NbtString();
338-
break;
339-
340-
case NbtTagType.List:
341-
newTag = new NbtList();
342-
break;
343-
344-
case NbtTagType.Compound:
345-
newTag = new NbtCompound();
346-
break;
347-
348-
case NbtTagType.IntArray:
349-
newTag = new NbtIntArray();
350-
break;
351-
352-
case NbtTagType.LongArray:
353-
newTag = new NbtLongArray();
354-
break;
334+
if (nextTag == NbtTagType.End)
335+
return true;
355336

356-
default:
357-
throw new NbtFormatException("Unsupported tag type found in NBT_Compound: " + nextTag);
358-
}
337+
NbtTag newTag = CreateTag(nextTag);
359338
newTag.Parent = this;
360339
newTag.Name = readStream.ReadString();
361340
if (newTag.ReadTag(readStream)) {

0 commit comments

Comments
 (0)