public override byte[] GetBytes(Stream instream) { if (_cache != null) { instream.Write(_cache); return(_cache); } using (var stream = new MemoryStream()) { stream.WriteByte(8); // version int numberOfStores = 1; stream.WriteByte((byte)numberOfStores); // storage size List <uint> palette = new List <uint>(10); byte[] indexes = new byte[_blocks.Length]; for (int i = 0; i < numberOfStores; i++) { palette.Clear(); stream.WriteByte((8 << 1) | 1); // version int index = 0; uint prevHash = uint.MaxValue; for (int b = 0; b < _blocks.Length; b++) { byte bid = (byte)_blocks[b]; byte data = _metadata[b]; uint hash = BlockFactory.GetRuntimeId(bid, data); if (hash != prevHash) { index = palette.IndexOf(hash); if (index == -1) { palette.Add(hash); } index = palette.IndexOf(hash); } indexes[b] = (byte)index; prevHash = hash; } stream.Write(indexes, 0, indexes.Length); VarInt.WriteSInt32(stream, palette.Count); // count foreach (var val in palette) { VarInt.WriteSInt32(stream, (int)val); } } var bytes = stream.ToArray(); instream.Write(bytes); _cache = bytes; } return(_cache); }
public override void WriteTo(BinaryWriter reader) { Stream stream = reader.BaseStream; VarInt.WriteSInt32(stream, Value.X); VarInt.WriteSInt32(stream, Value.Y); VarInt.WriteSInt32(stream, Value.Z); }
public byte[] GetBytes() { if (_cache != null) { return(_cache); } using (MemoryStream stream = MiNetServer.MemoryStreamManager.GetStream()) { NbtBinaryWriter writer = new NbtBinaryWriter(stream, true); int topEmpty = 16; for (int ci = 15; ci >= 0; ci--) { if (chunks[ci].IsAllAir()) { topEmpty = ci; } else { break; } } writer.Write((byte)topEmpty); int sent = 0; for (int ci = 0; ci < topEmpty; ci++) { writer.Write((byte)0); writer.Write(chunks[ci].GetBytes()); sent++; } //Log.Debug($"Saved sending {16 - sent} chunks"); //RecalcHeight(); byte[] ba = new byte[512]; Buffer.BlockCopy(height, 0, ba, 0, 512); writer.Write(ba); //Log.Debug($"Heights:\n{Package.HexDump(ba)}"); //BiomeUtils utils = new BiomeUtils(); //utils.PrecomputeBiomeColors(); //InterpolateBiomes(); writer.Write(biomeId); //for (int i = 0; i < biomeId.Length; i++) //{ // //var biome = biomeId[i]; // int color = biomeColor[i]; // writer.Write((int) (color & 0x00ffffff) /*| biome << 24*/); //} //short extraSize = 0; //writer.Write(extraSize); // No extra data // Count = SignedVarInt (zigzag) // Each entry // - Hash SignedVarint x << 12, z << 8, y // - Block data short writer.Write((byte)0); // Border blocks - nope VarInt.WriteSInt32(stream, 0); // Block extradata count //VarInt.WriteSInt32(stream, 2); //VarInt.WriteSInt32(stream, 1 << 12 | 1 << 8 | 4); //writer.Write((byte)31); //writer.Write((byte)0); if (BlockEntities.Count == 0) { //NbtFile file = new NbtFile(new NbtCompound(string.Empty)) {BigEndian = false, UseVarInt = true}; //file.SaveToStream(writer.BaseStream, NbtCompression.None); } else { foreach (NbtCompound blockEntity in BlockEntities.Values.ToArray()) { NbtFile file = new NbtFile(blockEntity) { BigEndian = false, UseVarInt = true }; file.SaveToStream(writer.BaseStream, NbtCompression.None); } } _cache = stream.ToArray(); } return(_cache); }
private bool WriteStore(MemoryStream stream, short[] blocks, byte[] loggedBlocks, bool forceWrite, List <int> palette) { if (palette.Count == 0) { return(false); } // log2(number of entries) => bits needed to store them int bitsPerBlock = (int)Math.Ceiling(Math.Log(palette.Count, 2)); switch (bitsPerBlock) { case 0: if (!forceWrite && palette.Contains(0)) { return(false); } bitsPerBlock = 1; break; case 1: case 2: case 3: case 4: case 5: case 6: //Paletted1 = 1, // 32 blocks per word //Paletted2 = 2, // 16 blocks per word //Paletted3 = 3, // 10 blocks and 2 bits of padding per word //Paletted4 = 4, // 8 blocks per word //Paletted5 = 5, // 6 blocks and 2 bits of padding per word //Paletted6 = 6, // 5 blocks and 2 bits of padding per word break; case 7: case 8: //Paletted8 = 8, // 4 blocks per word bitsPerBlock = 8; break; case int i when i > 8: //Paletted16 = 16, // 2 blocks per word bitsPerBlock = 16; break; default: break; } stream.WriteByte((byte)((bitsPerBlock << 1) | 1)); // version int blocksPerWord = (int)Math.Floor(32f / bitsPerBlock); // Floor to remove padding bits int wordsPerChunk = (int)Math.Ceiling(4096f / blocksPerWord); byte t = 0; uint[] indexes = new uint[wordsPerChunk]; int position = 0; for (int w = 0; w < wordsPerChunk; w++) { uint word = 0; for (int block = 0; block < blocksPerWord; block++) { if (position >= 4096) { continue; } uint state; if (blocks != null) { state = (uint)blocks[position]; } else { state = (uint)loggedBlocks[position]; } word |= state << (bitsPerBlock * block); position++; } indexes[w] = word; } byte[] ba = new byte[indexes.Length * 4]; Buffer.BlockCopy(indexes, 0, ba, 0, indexes.Length * 4); stream.Write(ba, 0, ba.Length); VarInt.WriteSInt32(stream, palette.Count); // count foreach (var val in palette) { VarInt.WriteSInt32(stream, val); } return(true); }
public void WriteSignedVarInt(int value) { VarInt.WriteSInt32(_buffer, value); }
private static bool WriteStore(MemoryStream stream, short[] blocks, NibbleArray metadata, bool forceWrite) { var palette = new Dictionary <uint, byte>(); uint prevHash = uint.MaxValue; for (int i = 0; i < 4096; i++) { uint hash = (uint)blocks[i] << 4 | metadata[i]; // 1.7 if (hash == prevHash) { continue; } prevHash = hash; palette[hash] = 0; } // log2(number of entries) => bits needed to store them int bitsPerBlock = (int)Math.Ceiling(Math.Log(palette.Count, 2)); switch (bitsPerBlock) { case 0: if (!forceWrite && palette.ContainsKey(0)) { return(false); } bitsPerBlock = 1; break; case 1: case 2: case 3: case 4: case 5: case 6: //Paletted1 = 1, // 32 blocks per word //Paletted2 = 2, // 16 blocks per word //Paletted3 = 3, // 10 blocks and 2 bits of padding per word //Paletted4 = 4, // 8 blocks per word //Paletted5 = 5, // 6 blocks and 2 bits of padding per word //Paletted6 = 6, // 5 blocks and 2 bits of padding per word break; case 7: case 8: //Paletted8 = 8, // 4 blocks per word bitsPerBlock = 8; break; case int i when i > 8: //Paletted16 = 16, // 2 blocks per word bitsPerBlock = 16; break; default: break; } stream.WriteByte((byte)((bitsPerBlock << 1) | 1)); // version int blocksPerWord = (int)Math.Floor(32f / bitsPerBlock); // Floor to remove padding bits int wordsPerChunk = (int)Math.Ceiling(4096f / blocksPerWord); byte t = 0; foreach (var b in palette.ToArray()) { palette[b.Key] = t++; } uint[] indexes = new uint[wordsPerChunk]; int position = 0; for (int w = 0; w < wordsPerChunk; w++) { uint word = 0; for (int block = 0; block < blocksPerWord; block++) { if (position >= 4096) { continue; } uint state = palette[(uint)blocks[position] << 4 | metadata[position]]; word |= state << (bitsPerBlock * block); //string bin = Convert.ToString(word, 2); //bin = new string('0', 32 - bin.Length) + bin; //Console.WriteLine($"{bin}"); position++; } indexes[w] = word; } byte[] ba = new byte[indexes.Length * 4]; Buffer.BlockCopy(indexes, 0, ba, 0, indexes.Length * 4); stream.Write(ba, 0, ba.Length); int[] legacyToRuntimeId = BlockFactory.LegacyToRuntimeId; VarInt.WriteSInt32(stream, palette.Count); // count foreach (var val in palette) { VarInt.WriteSInt32(stream, legacyToRuntimeId[val.Key]); } return(true); }
public override void WriteTo(BinaryWriter stream) { VarInt.WriteSInt32(stream.BaseStream, Value); }