diff --git a/pom.xml b/pom.xml index e0c8a00..f7bdbff 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.loohp Limbo - 0.3.3-ALPHA + 0.3.4-ALPHA src diff --git a/src/com/loohp/limbo/Server/Packets/PacketPlayOutMapChunk.java b/src/com/loohp/limbo/Server/Packets/PacketPlayOutMapChunk.java index 4aadf0a..dbee890 100644 --- a/src/com/loohp/limbo/Server/Packets/PacketPlayOutMapChunk.java +++ b/src/com/loohp/limbo/Server/Packets/PacketPlayOutMapChunk.java @@ -3,9 +3,13 @@ package com.loohp.limbo.Server.Packets; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.util.ArrayList; +import java.util.BitSet; import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; -import com.loohp.limbo.Utils.ChunkDataUtils; +import com.loohp.limbo.Utils.BitsUtils; import com.loohp.limbo.Utils.DataTypeIO; import com.loohp.limbo.World.Environment; import com.loohp.limbo.World.GeneratedBlockDataMappings; @@ -105,8 +109,9 @@ public class PacketPlayOutMapChunk extends PacketOut { int newBits = 32 - Integer.numberOfLeadingZeros(section.getPalette().size() - 1); newBits = Math.max(newBits, 4); - + //Limbo.getInstance().getConsole().sendMessage(i + " " + newBits); if (newBits <= 8) { + /* if (newBits == 4) { dataOut.writeByte(4); } else { @@ -114,25 +119,79 @@ public class PacketPlayOutMapChunk extends PacketOut { ChunkDataUtils.adjustBlockStateBits(newBits, section, chunk.getDataVersion()); dataOut.writeByte(8); } + */ + dataOut.writeByte(newBits); DataTypeIO.writeVarInt(dataOut, section.getPalette().size()); //Limbo.getInstance().getConsole().sendMessage(section.getPalette().size()); Iterator itr1 = section.getPalette().iterator(); //Limbo.getInstance().getConsole().sendMessage("Nonnull -> " + i + " " + newBits); - counter = 0; while (itr1.hasNext()) { CompoundTag tag = itr1.next(); DataTypeIO.writeVarInt(dataOut, GeneratedBlockDataMappings.getGlobalPaletteIDFromState(tag)); //Limbo.getInstance().getConsole().sendMessage(tag + " -> " + GeneratedDataUtils.getGlobalPaletteIDFromState(tag)); } + + BitSet bits = BitSet.valueOf(section.getBlockStates()); + int shift = 64 % newBits; + int longsNeeded = (int) Math.ceil(4096 / (double) (64 / newBits)); + for (int u = 64; u <= bits.length(); u += 64) { + bits = BitsUtils.shiftAfter(bits, u - shift, shift); + } + + long[] formattedLongs = bits.toLongArray(); + //Limbo.getInstance().getConsole().sendMessage(longsNeeded + ""); + + DataTypeIO.writeVarInt(dataOut, longsNeeded); + for (int u = 0; u < longsNeeded; u++) { + if (u < formattedLongs.length) { + dataOut.writeLong(formattedLongs[u]); + } else { + dataOut.writeLong(0); + } + //Limbo.getInstance().getConsole().sendMessage(Arrays.toString(section.getBlockStates())); + } } else { - dataOut.writeByte(14); - } - - DataTypeIO.writeVarInt(dataOut, section.getBlockStates().length); - for (int u = 0; u < section.getBlockStates().length; u++) { - dataOut.writeLong(section.getBlockStates()[u]); - //Limbo.getInstance().getConsole().sendMessage(Arrays.toString(section.getBlockStates())); + try { + dataOut.writeByte(15); + section.getBlockStates(); + int longsNeeded = 1024; + List list = new LinkedList<>(); + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + list.add(GeneratedBlockDataMappings.getGlobalPaletteIDFromState(section.getBlockStateAt(x, y, z))); + } + } + } + List globalLongs = new ArrayList<>(); + long currentLong = 0; + int pos = 0; + int u = 0; + while (pos < longsNeeded) { + if (u == 3) { + globalLongs.add(currentLong); + currentLong = 0; + u = 0; + pos++; + } else { + u++; + } + int id = list.isEmpty() ? 0 : list.remove(0); + currentLong = currentLong << 15; + currentLong |= (long) id; + } + DataTypeIO.writeVarInt(dataOut, longsNeeded); + for (int j = 0; j < longsNeeded; j++) { + if (j < globalLongs.size()) { + dataOut.writeLong(globalLongs.get(j)); + } else { + dataOut.writeLong(0); + } + } + } catch (Exception e) { + e.printStackTrace(); + } } } } diff --git a/src/com/loohp/limbo/Utils/BitsUtils.java b/src/com/loohp/limbo/Utils/BitsUtils.java new file mode 100644 index 0000000..b1291e5 --- /dev/null +++ b/src/com/loohp/limbo/Utils/BitsUtils.java @@ -0,0 +1,31 @@ +package com.loohp.limbo.Utils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.List; + +public class BitsUtils { + + public static BitSet shiftAfter(BitSet bitset, int from, int shift) { + BitSet subset = bitset.get(from, bitset.length()); + for (int i = 0; i < subset.length(); i++) { + bitset.set(from + shift + i, subset.get(i)); + } + if (shift > 0) { + for (int i = 0; i < shift; i++) { + bitset.set(from + i, false); + } + } + return bitset; + } + + public static String toLongString(BitSet bitset) { + List list = new ArrayList<>(); + for (long l : bitset.toLongArray()) { + list.add(Long.toBinaryString(l)); + } + return Arrays.toString(list.toArray()); + } + +} diff --git a/src/com/loohp/limbo/World/Schematic.java b/src/com/loohp/limbo/World/Schematic.java index f0c7908..17e1d1f 100644 --- a/src/com/loohp/limbo/World/Schematic.java +++ b/src/com/loohp/limbo/World/Schematic.java @@ -16,8 +16,8 @@ public class Schematic { public static World toWorld(String name, Environment environment, CompoundTag nbt) { short width = nbt.getShort("Width"); short length = nbt.getShort("Length"); - short height = nbt.getShort("Height"); - byte[] blocks = nbt.getByteArray("BlockData"); + //short height = nbt.getShort("Height"); + byte[] blockdata = nbt.getByteArray("BlockData"); CompoundTag palette = nbt.getCompoundTag("Palette"); ListTag blockEntities = nbt.getListTag("BlockEntities").asTypedList(CompoundTag.class); Map mapping = new HashMap<>(); @@ -26,29 +26,50 @@ public class Schematic { } World world = new World(name, width, length, environment); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - for (int z = 0; z < length; z++) { - int blockIndex = x + z * width + y * width * length; - world.setBlock(x, y, z, mapping.get(blocks[blockIndex] < 0 ? blocks[blockIndex] + 256 : blocks[blockIndex])); - Chunk chunk = world.getChunkAtWorldPos(x, z); - - Iterator itr = blockEntities.iterator(); - while (itr.hasNext()) { - CompoundTag tag = itr.next(); - int[] pos = tag.getIntArray("Pos"); - - if (pos[0] == x && pos[1] == y && pos[2] == z) { - ListTag newTag = chunk.getTileEntities(); - newTag.add(SchematicConvertionUtils.toTileEntityTag(tag)); - chunk.setTileEntities(newTag); - itr.remove(); - break; - } - } + + int index = 0; + int i = 0; + int value = 0; + int varint_length = 0; + while (i < blockdata.length) { + value = 0; + varint_length = 0; + + while (true) { + value |= (blockdata[i] & 127) << (varint_length++ * 7); + if (varint_length > 5) { + throw new RuntimeException("VarInt too big (probably corrupted data)"); + } + if ((blockdata[i] & 128) != 128) { + i++; + break; + } + i++; + } + // index = (y * length + z) * width + x + int y = index / (width * length); + int z = (index % (width * length)) / width; + int x = (index % (width * length)) % width; + world.setBlock(x, y, z, mapping.get(value)); + + Chunk chunk = world.getChunkAtWorldPos(x, z); + + Iterator itr = blockEntities.iterator(); + while (itr.hasNext()) { + CompoundTag tag = itr.next(); + int[] pos = tag.getIntArray("Pos"); + + if (pos[0] == x && pos[1] == y && pos[2] == z) { + ListTag newTag = chunk.getTileEntities(); + newTag.add(SchematicConvertionUtils.toTileEntityTag(tag)); + chunk.setTileEntities(newTag); + itr.remove(); + break; } } - } + + index++; + } for (Chunk[] chunkarray : world.getChunks()) { for (Chunk chunk : chunkarray) {