void WriteBlocks( NbtFile nbt, byte[] blocks ) { const int chunkSize = 64 * 1024 * 32; nbt.Write( NbtTagType.Int8Array ); nbt.Write( "Blocks" ); nbt.WriteInt32( blocks.Length ); for( int i = 0; i < blocks.Length; i += chunkSize ) { int count = Math.Min( chunkSize, blocks.Length - i ); nbt.WriteBytes( blocks, i, count ); } }
void WriteBlockData( NbtFile nbt, byte[] blocks ) { const int chunkSize = 64 * 1024; byte[] chunk = new byte[chunkSize]; nbt.Write( NbtTagType.Int8Array ); nbt.Write( "Data" ); nbt.WriteInt32( blocks.Length ); for( int i = 0; i < blocks.Length; i += chunkSize ) { // All 0 so we can skip this. int count = Math.Min( chunkSize, blocks.Length - i ); nbt.WriteBytes( chunk, 0, count ); } }
public byte[] Load( Stream stream, Game game, out int width, out int height, out int length ) { GZipHeaderReader gsHeader = new GZipHeaderReader(); while( !gsHeader.ReadHeader( stream ) ) { } using( DeflateStream gs = new DeflateStream( stream, CompressionMode.Decompress ) ) { reader = new BinaryReader( gs ); if( reader.ReadByte() != (byte)NbtTagType.Compound ) throw new InvalidDataException( "Nbt file must start with Tag_Compound" ); this.game = game; map = game.World; file = new NbtFile( reader ); NbtTag root = file.ReadTag( (byte)NbtTagType.Compound, true ); NbtCompound children = (NbtCompound)root.Value; if( children.ContainsKey( "Metadata" ) ) ParseMetadata( children ); NbtCompound spawn = (NbtCompound)children["Spawn"].Value; LocalPlayer p = game.LocalPlayer; p.Spawn.X = (short)spawn["X"].Value; p.Spawn.Y = (short)spawn["Y"].Value; p.Spawn.Z = (short)spawn["Z"].Value; if( spawn.ContainsKey( "H" ) ) p.SpawnYaw = (float)Utils.PackedToDegrees( (byte)spawn["H"].Value ); if( spawn.ContainsKey( "P" ) ) p.SpawnPitch = (float)Utils.PackedToDegrees( (byte)spawn["P"].Value ); map.Uuid = new Guid( (byte[])children["UUID"].Value ); width = (short)children["X"].Value; height = (short)children["Y"].Value; length = (short)children["Z"].Value; // Older versions incorrectly multiplied spawn coords by * 32, so we check for that. if( p.Spawn.X < 0 || p.Spawn.X >= width || p.Spawn.Y < 0 || p.Spawn.Y >= height || p.Spawn.Z < 0 || p.Spawn.Z >= length ) { p.Spawn.X /= 32; p.Spawn.Y /= 32; p.Spawn.Z /= 32; } return (byte[])children["BlockArray"].Value; } }
public void Save(Stream stream, Game game) { using (GZipStream wrapper = new GZipStream(stream, CompressionMode.Compress)) { BinaryWriter writer = new BinaryWriter(wrapper); NbtFile nbt = new NbtFile(writer); World map = game.World; nbt.Write(NbtTagType.Compound); nbt.Write("Schematic"); nbt.Write(NbtTagType.String); nbt.Write("Materials"); nbt.Write("Classic"); nbt.Write(NbtTagType.Int16); nbt.Write("Width"); nbt.WriteInt16((short)map.Width); nbt.Write(NbtTagType.Int16); nbt.Write("Height"); nbt.WriteInt16((short)map.Height); nbt.Write(NbtTagType.Int16); nbt.Write("Length"); nbt.WriteInt16((short)map.Length); #if USE16_BIT WriteBlocks(nbt, Utils.UInt16sToUInt8s(map.blocks)); #else WriteBlocks(nbt, map.blocks); #endif WriteBlockData(nbt, map.blocks.Length); nbt.Write(NbtTagType.List); nbt.Write("Entities"); nbt.Write(NbtTagType.Compound); nbt.WriteInt32(0); nbt.Write(NbtTagType.List); nbt.Write("TileEntities"); nbt.Write(NbtTagType.Compound); nbt.WriteInt32(0); nbt.Write(NbtTagType.End); } }
public bool LoadChunk(ref Chunk chunk, string path) { try { using (FileStream fs = File.OpenRead(path)) { GZipHeaderReader gsheader = new GZipHeaderReader(); while (!gsheader.ReadHeader(fs)) { } using (DeflateStream gs = new DeflateStream(fs, CompressionMode.Decompress)) { BinaryReader reader = new BinaryReader(gs); if (reader.ReadByte() != (byte)NbtTagType.Compound) { throw new InvalidDataException("Nbt file must start with Tag_Compound"); } NbtFile file = new NbtFile(reader); NbtTag root = file.ReadTag((byte)NbtTagType.Compound, true); NbtCompound children = (NbtCompound)root.Value; if (children.ContainsKey("Level")) { NbtCompound levelChildren = (NbtCompound)children["Level"].Value; chunk.blocks = (byte[])levelChildren["Blocks"].Value; int size = 16 * 128 * 16; int halfSize = size / 2; byte[] data = (byte[])levelChildren["Data"].Value; chunk.metadata = new NibbleSlice(data, 0, halfSize); chunk.populated = ((byte)levelChildren["TerrainPopulated"].Value != 0); return(true); } } } } catch (Exception ex) { ErrorHandler.LogError("loading chunk", ex); game.Chat.Add("Failed to load chunk."); return(false); } return(false); }
public void Save( Stream stream, Game game ) { using( GZipStream wrapper = new GZipStream( stream, CompressionMode.Compress ) ) { writer = new BinaryWriter( wrapper ); nbt = new NbtFile( writer ); this.game = game; map = game.World; nbt.Write( NbtTagType.Compound ); nbt.Write( "ClassicWorld" ); nbt.Write( NbtTagType.Int8 ); nbt.Write( "FormatVersion" ); nbt.WriteInt8( 1 ); nbt.Write( NbtTagType.Int8Array ); nbt.Write( "UUID" ); nbt.WriteInt32( 16 ); nbt.WriteBytes( map.Uuid.ToByteArray() ); nbt.Write( NbtTagType.Int16 ); nbt.Write( "X" ); nbt.WriteInt16( (short)map.Width ); nbt.Write( NbtTagType.Int16 ); nbt.Write( "Y" ); nbt.WriteInt16( (short)map.Height ); nbt.Write( NbtTagType.Int16 ); nbt.Write( "Z" ); nbt.WriteInt16( (short)map.Length ); WriteSpawnCompoundTag(); nbt.Write( NbtTagType.Int8Array ); nbt.Write( "BlockArray" ); nbt.WriteInt32( map.blocks.Length ); nbt.WriteBytes( map.blocks ); WriteMetadata(); nbt.Write( NbtTagType.End ); } }
public void Save(Stream stream, Game game) { using (GZipStream wrapper = new GZipStream(stream, CompressionMode.Compress)) { writer = new BinaryWriter(wrapper); nbt = new NbtFile(writer); this.game = game; map = game.World; nbt.Write(NbtTagType.Compound); nbt.Write("ClassicWorld"); nbt.Write(NbtTagType.Int8); nbt.Write("FormatVersion"); nbt.WriteUInt8(1); nbt.Write(NbtTagType.Int8Array); nbt.Write("UUID"); nbt.WriteInt32(16); nbt.WriteBytes(map.Uuid.ToByteArray()); nbt.Write(NbtTagType.Int16); nbt.Write("X"); nbt.WriteInt16((short)map.Width); nbt.Write(NbtTagType.Int16); nbt.Write("Y"); nbt.WriteInt16((short)map.Height); nbt.Write(NbtTagType.Int16); nbt.Write("Z"); nbt.WriteInt16((short)map.Length); WriteSpawnCompoundTag(); nbt.Write(NbtTagType.Int8Array); nbt.Write("BlockArray"); nbt.WriteInt32(map.blocks1.Length); nbt.WriteBytes(map.blocks1); WriteMetadata(); nbt.Write(NbtTagType.End); } }
public void Save( Stream stream, Game game ) { using( GZipStream wrapper = new GZipStream( stream, CompressionMode.Compress ) ) { BinaryWriter writer = new BinaryWriter( wrapper ); NbtFile nbt = new NbtFile( writer ); World map = game.World; nbt.Write( NbtTagType.Compound ); nbt.Write( "Schematic" ); nbt.Write( NbtTagType.String ); nbt.Write( "Materials" ); nbt.Write( "Classic" ); nbt.Write( NbtTagType.Int16 ); nbt.Write( "Width" ); nbt.WriteInt16( (short)map.Width ); nbt.Write( NbtTagType.Int16 ); nbt.Write( "Height" ); nbt.WriteInt16( (short)map.Height ); nbt.Write( NbtTagType.Int16 ); nbt.Write( "Length" ); nbt.WriteInt16( (short)map.Length ); WriteBlocks( nbt, map.blocks ); WriteBlockData( nbt, map.blocks ); nbt.Write( NbtTagType.List ); nbt.Write( "Entities" ); nbt.Write( NbtTagType.Compound ); nbt.WriteInt32( 0 ); nbt.Write( NbtTagType.List ); nbt.Write( "TileEntities" ); nbt.Write( NbtTagType.Compound ); nbt.WriteInt32( 0 ); nbt.Write( NbtTagType.End ); } }