mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-06 12:37:28 -04:00
142 lines
4.1 KiB
C#
142 lines
4.1 KiB
C#
// ClassicalSharp copyright 2014-2016 UnknownShadow200 | Licensed under MIT
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Text;
|
|
|
|
namespace ClassicalSharp.Map {
|
|
|
|
public struct NbtTag {
|
|
public string Name;
|
|
public object Value;
|
|
public NbtTagType TagId;
|
|
}
|
|
|
|
public class NbtList {
|
|
public NbtTagType ChildTagId;
|
|
public object[] ChildrenValues;
|
|
}
|
|
|
|
public enum NbtTagType : byte {
|
|
End, Int8, Int16, Int32, Int64,
|
|
Real32, Real64, Int8Array, String,
|
|
List, Compound, Int32Array,
|
|
Invalid = 255,
|
|
}
|
|
|
|
public sealed class NbtFile {
|
|
|
|
readonly BinaryReader reader;
|
|
readonly BinaryWriter writer;
|
|
|
|
public NbtFile( BinaryReader reader ) {
|
|
this.reader = reader;
|
|
}
|
|
|
|
public NbtFile( BinaryWriter writer ) {
|
|
this.writer = writer;
|
|
}
|
|
|
|
|
|
public void Write( NbtTagType v ) { writer.Write( (byte)v ); }
|
|
|
|
public void WriteInt64( long v ) { writer.Write( IPAddress.HostToNetworkOrder( v ) ); }
|
|
|
|
public void WriteInt32( int v ) { writer.Write( IPAddress.HostToNetworkOrder( v ) ); }
|
|
|
|
public void WriteInt16( short v ) { writer.Write( IPAddress.HostToNetworkOrder( v ) ); }
|
|
|
|
public void WriteInt8( sbyte v ) { writer.Write( (byte)v ); }
|
|
|
|
public void WriteUInt8( int v ) { writer.Write( (byte)v ); }
|
|
|
|
public void WriteUInt8( byte v ) { writer.Write( v ); }
|
|
|
|
public void WriteBytes( byte[] v ) { writer.Write( v ); }
|
|
|
|
public void WriteBytes( byte[] v, int index, int count ) { writer.Write( v, index, count ); }
|
|
|
|
public void Write( string value ) {
|
|
ushort len = (ushort)value.Length;
|
|
byte[] data = Encoding.UTF8.GetBytes( value );
|
|
WriteInt16( (short)len );
|
|
writer.Write( data );
|
|
}
|
|
|
|
public void WriteCpeExtCompound( string name, int version ) {
|
|
Write( NbtTagType.Compound ); Write( name );
|
|
|
|
Write( NbtTagType.Int32 );
|
|
Write( "ExtensionVersion" ); WriteInt32( version );
|
|
}
|
|
|
|
|
|
public long ReadInt64() { return IPAddress.HostToNetworkOrder( reader.ReadInt64() ); }
|
|
|
|
public int ReadInt32() { return IPAddress.HostToNetworkOrder( reader.ReadInt32() ); }
|
|
|
|
public short ReadInt16() { return IPAddress.HostToNetworkOrder( reader.ReadInt16() ); }
|
|
|
|
public string ReadString() {
|
|
int len = (ushort)ReadInt16();
|
|
byte[] data = reader.ReadBytes( len );
|
|
return Encoding.UTF8.GetString( data );
|
|
}
|
|
|
|
public unsafe NbtTag ReadTag( byte typeId, bool readTagName ) {
|
|
NbtTag tag = default( NbtTag );
|
|
if( typeId == 0 ) {
|
|
tag.TagId = NbtTagType.Invalid; return tag;
|
|
}
|
|
|
|
tag.Name = readTagName ? ReadString() : null;
|
|
tag.TagId = (NbtTagType)typeId;
|
|
switch( (NbtTagType)typeId ) {
|
|
case NbtTagType.Int8:
|
|
tag.Value = reader.ReadByte(); break;
|
|
case NbtTagType.Int16:
|
|
tag.Value = ReadInt16(); break;
|
|
case NbtTagType.Int32:
|
|
tag.Value = ReadInt32(); break;
|
|
case NbtTagType.Int64:
|
|
tag.Value = ReadInt64(); break;
|
|
case NbtTagType.Real32:
|
|
int temp32 = ReadInt32();
|
|
tag.Value = *((float*)&temp32); break;
|
|
case NbtTagType.Real64:
|
|
long temp64 = ReadInt64();
|
|
tag.Value = *((double*)&temp64); break;
|
|
case NbtTagType.Int8Array:
|
|
tag.Value = reader.ReadBytes( ReadInt32() ); break;
|
|
case NbtTagType.String:
|
|
tag.Value = ReadString(); break;
|
|
|
|
case NbtTagType.List:
|
|
NbtList list = new NbtList();
|
|
list.ChildTagId = (NbtTagType)reader.ReadByte();
|
|
list.ChildrenValues = new object[ReadInt32()];
|
|
for( int i = 0; i < list.ChildrenValues.Length; i++ )
|
|
list.ChildrenValues[i] = ReadTag( (byte)list.ChildTagId, false ).Value;
|
|
tag.Value = list; break;
|
|
|
|
case NbtTagType.Compound:
|
|
Dictionary<string, NbtTag> children = new Dictionary<string, NbtTag>();
|
|
NbtTag child;
|
|
while( (child = ReadTag( reader.ReadByte(), true )).TagId != NbtTagType.Invalid )
|
|
children[child.Name] = child;
|
|
tag.Value = children; break;
|
|
|
|
case NbtTagType.Int32Array:
|
|
int[] array = new int[ReadInt32()];
|
|
for( int i = 0; i < array.Length; i++ )
|
|
array[i] = ReadInt32();
|
|
tag.Value = array; break;
|
|
|
|
default:
|
|
throw new InvalidDataException( "Unrecognised tag id: " + typeId );
|
|
}
|
|
return tag;
|
|
}
|
|
}
|
|
} |