Minecraft 1.18

This commit is contained in:
LOOHP 2021-12-01 00:55:27 +00:00
parent 2909c77d62
commit 14a1f50abf
12 changed files with 13469 additions and 357 deletions

View File

@ -5,7 +5,7 @@
<groupId>com.loohp</groupId>
<artifactId>Limbo</artifactId>
<name>Limbo</name>
<version>0.6.4-ALPHA</version>
<version>0.6.5-ALPHA</version>
<description>Standalone Limbo Minecraft Server.</description>
<url>https://github.com/LOOHP/Limbo</url>
@ -117,7 +117,7 @@
</executions>
</plugin>
</plugins>
<finalName>${project.artifactId}-${project.version}-1.17.1</finalName>
<finalName>${project.artifactId}-${project.version}-1.18</finalName>
</build>
<profiles>

View File

@ -106,8 +106,8 @@ public class Limbo {
//===========================
public final String serverImplementationVersion = "1.17.1";
public final int serverImplmentationProtocol = 756;
public final String serverImplementationVersion = "1.18";
public final int serverImplmentationProtocol = 757;
public final String limboImplementationVersion;
private AtomicBoolean isRunning;

View File

@ -15,8 +15,7 @@ import com.loohp.limbo.entity.Entity;
import com.loohp.limbo.location.Location;
import com.loohp.limbo.server.packets.PacketPlayOutEntityDestroy;
import com.loohp.limbo.server.packets.PacketPlayOutEntityMetadata;
import com.loohp.limbo.server.packets.PacketPlayOutLightUpdate;
import com.loohp.limbo.server.packets.PacketPlayOutMapChunk;
import com.loohp.limbo.server.packets.ClientboundLevelChunkWithLightPacket;
import com.loohp.limbo.server.packets.PacketPlayOutSpawnEntity;
import com.loohp.limbo.server.packets.PacketPlayOutSpawnEntityLiving;
import com.loohp.limbo.server.packets.PacketPlayOutUnloadChunk;
@ -112,9 +111,6 @@ public class PlayerInteractManager {
for (Chunk chunk : chunksInRange) {
if (!chunks.containsKey(chunk)) {
int[] chunkPos = world.getChunkXZ(chunk);
PacketPlayOutMapChunk packet0 = new PacketPlayOutMapChunk(chunkPos[0], chunkPos[1], chunk, world.getEnvironment());
player.clientConnection.sendPacket(packet0);
List<Byte[]> blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos[0], chunkPos[1]);
if (blockChunk == null) {
blockChunk = new ArrayList<>();
@ -126,7 +122,7 @@ public class PlayerInteractManager {
if (skyChunk == null) {
skyChunk = new ArrayList<>();
}
PacketPlayOutLightUpdate chunkdata = new PacketPlayOutLightUpdate(chunkPos[0], chunkPos[1], true, skyChunk, blockChunk);
ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos[0], chunkPos[1], chunk, world.getEnvironment(), true, skyChunk, blockChunk);
player.clientConnection.sendPacket(chunkdata);
}
}

View File

@ -0,0 +1,84 @@
package com.loohp.limbo.registry;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.loohp.limbo.Limbo;
import com.loohp.limbo.utils.NamespacedKey;
public class Registry {
public static final BlockEntityRegistry BLOCK_ENTITY_TYPE;
static {
String name = "registries.json";
File file = new File(Limbo.getInstance().getInternalDataFolder(), name);
if (!file.exists()) {
try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream(name)) {
Files.copy(in, file.toPath());
} catch (IOException e) {
e.printStackTrace();
}
}
Map<NamespacedKey, Integer> blockEntityType = new HashMap<>();
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
JSONObject json = (JSONObject) new JSONParser().parse(reader);
JSONObject blockEntityJson = (JSONObject) ((JSONObject) json.get("minecraft:block_entity_type")).get("entries");
for (Object obj : blockEntityJson.keySet()) {
String key = obj.toString();
int id = (int) (long) ((JSONObject) blockEntityJson.get(key)).get("protocol_id");
blockEntityType.put(new NamespacedKey(key), id);
}
} catch (IOException | ParseException e) {
e.printStackTrace();
}
BLOCK_ENTITY_TYPE = new BlockEntityRegistry(blockEntityType);
}
public static class BlockEntityRegistry {
private Map<NamespacedKey, Integer> blockEntityType;
private BlockEntityRegistry(Map<NamespacedKey, Integer> blockEntityType) {
this.blockEntityType = blockEntityType;
}
public int getId(NamespacedKey key) {
Integer exact = blockEntityType.get(key);
if (exact != null) {
return exact;
}
List<String> toTest = new LinkedList<>();
toTest.add(key.getKey());
if (key.getKey().contains("head")) {
toTest.add("skull");
}
for (Entry<NamespacedKey, Integer> entry : blockEntityType.entrySet()) {
NamespacedKey namespacedKey = entry.getKey();
for (String each : toTest) {
if (namespacedKey.getNamespace().equals(key.getNamespace()) && (each.contains(namespacedKey.getKey()) || namespacedKey.getKey().contains(each))) {
return entry.getValue();
}
}
}
return -1;
}
}
}

View File

@ -374,7 +374,7 @@ public class ClientConnection extends Thread {
worldSpawn = joinEvent.getSpawnLocation();
World world = worldSpawn.getWorld();
PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, properties.getDefaultGamemode(), Limbo.getInstance().getWorlds(), Limbo.getInstance().getDimensionRegistry().getCodec(), world, 0, (byte) properties.getMaxPlayers(), 8, properties.isReducedDebugInfo(), true, false, true);
PacketPlayOutLogin join = new PacketPlayOutLogin(player.getEntityId(), false, properties.getDefaultGamemode(), Limbo.getInstance().getWorlds(), Limbo.getInstance().getDimensionRegistry().getCodec(), world, 0, (byte) properties.getMaxPlayers(), 8, 8, properties.isReducedDebugInfo(), true, false, true);
sendPacket(join);
Limbo.getInstance().getUnsafe().setPlayerGameModeSilently(player, properties.getDefaultGamemode());

View File

@ -0,0 +1,304 @@
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.registry.Registry;
import com.loohp.limbo.utils.BitsUtils;
import com.loohp.limbo.utils.DataTypeIO;
import com.loohp.limbo.utils.NamespacedKey;
import com.loohp.limbo.world.Environment;
import com.loohp.limbo.world.GeneratedBlockDataMappings;
import net.querz.mca.Chunk;
import net.querz.mca.Section;
import net.querz.nbt.tag.CompoundTag;
import net.querz.nbt.tag.ListTag;
public class ClientboundLevelChunkWithLightPacket extends PacketOut {
private int chunkX;
private int chunkZ;
private Chunk chunk;
private Environment environment;
private boolean trustEdges;
private long[] skyLightBitMasks;
private long[] blockLightBitMasks;
private long[] skyLightBitMasksEmpty;
private long[] blockLightBitMasksEmpty;
private List<Byte[]> skylightArrays;
private List<Byte[]> blocklightArrays;
public ClientboundLevelChunkWithLightPacket(int chunkX, int chunkZ, Chunk chunk, Environment environment, boolean trustEdges, List<Byte[]> skylightArrays, List<Byte[]> blocklightArrays) {
this.chunkX = chunkX;
this.chunkZ = chunkZ;
this.chunk = chunk;
this.environment = environment;
this.chunkX = chunkX;
this.chunkZ = chunkZ;
this.trustEdges = trustEdges;
this.skylightArrays = skylightArrays;
this.blocklightArrays = blocklightArrays;
BitSet skyLightBitSet = new BitSet();
BitSet skyLightBitSetInverse = new BitSet();
for (int i = Math.min(17, skylightArrays.size() - 1); i >= 0; i--) {
skyLightBitSet.set(i, skylightArrays.get(i) != null);
skyLightBitSetInverse.set(i, skylightArrays.get(i) == null);
}
skyLightBitMasks = skyLightBitSet.toLongArray();
skyLightBitMasksEmpty = skyLightBitSetInverse.toLongArray();
BitSet blockLightBitSet = new BitSet();
BitSet blockLightBitSetInverse = new BitSet();
for (int i = Math.min(17, blocklightArrays.size() - 1); i >= 0; i--) {
blockLightBitSet.set(i, blocklightArrays.get(i) != null);
blockLightBitSetInverse.set(i, blocklightArrays.get(i) == null);
}
blockLightBitMasks = blockLightBitSet.toLongArray();
blockLightBitMasksEmpty = blockLightBitSetInverse.toLongArray();
}
public Chunk getChunk() {
return chunk;
}
public int getChunkX() {
return chunkX;
}
public int getChunkZ() {
return chunkZ;
}
public Environment getEnvironment() {
return environment;
}
public boolean isTrustEdges() {
return trustEdges;
}
public long[] getSkyLightBitMasks() {
return skyLightBitMasks;
}
public long[] getBlockLightBitMasks() {
return blockLightBitMasks;
}
public List<Byte[]> getSkylightArrays() {
return skylightArrays;
}
public List<Byte[]> getBlocklightArrays() {
return blocklightArrays;
}
@Override
public byte[] serializePacket() throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DataOutputStream output = new DataOutputStream(buffer);
output.writeByte(Packet.getPlayOut().get(getClass()));
output.writeInt(chunkX);
output.writeInt(chunkZ);
DataTypeIO.writeCompoundTag(output, chunk.getHeightMaps());
ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(dataBuffer);
for (int i = 0; i < 16; i++) {
Section section = chunk.getSection(i);
if (section != null) {
int counter = 0;
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = 0; y < 16; y++) {
CompoundTag tag = section.getBlockStateAt(x, y, z);
if (tag != null && !tag.getString("Name").equals("minecraft:air")) {
counter++;
}
}
}
}
dataOut.writeShort(counter);
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 {
newBits = 8;
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<CompoundTag> itr1 = section.getPalette().iterator();
//Limbo.getInstance().getConsole().sendMessage("Nonnull -> " + i + " " + newBits);
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 {
try {
dataOut.writeByte(15);
section.getBlockStates();
int longsNeeded = 1024;
List<Integer> 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<Long> 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();
}
}
} else {
dataOut.writeShort(0);
dataOut.writeByte(0);
DataTypeIO.writeVarInt(dataOut, 0);
DataTypeIO.writeVarInt(dataOut, 0);
}
int biome;
if (environment.equals(Environment.END)) {
biome = 9; //the_end
} else if (environment.equals(Environment.NETHER)) {
biome = 8; //nether_waste
} else if (environment.equals(Environment.NORMAL)) {
biome = 1; //plains
} else {
biome = 1; //plains
}
dataOut.writeByte(0);
DataTypeIO.writeVarInt(dataOut, biome);
DataTypeIO.writeVarInt(dataOut, 0);
}
byte[] data = dataBuffer.toByteArray();
DataTypeIO.writeVarInt(output, data.length);
output.write(data);
ListTag<CompoundTag> tileEntities = chunk.getTileEntities();
DataTypeIO.writeVarInt(output, tileEntities.size());
for (CompoundTag each : tileEntities) {
int x = each.getInt("x") % 16;
int y = each.getInt("y");
int z = each.getInt("z") % 16;
output.writeByte((x << 4) | z);
output.writeShort(y);
Integer id = Registry.BLOCK_ENTITY_TYPE.getId(new NamespacedKey(chunk.getBlockStateAt(x, y, z).getString("Name")));
System.out.println(chunk.getBlockStateAt(x, y, z).toString());
System.out.println(each.toString());
DataTypeIO.writeVarInt(output, id == null ? -1 : id);
DataTypeIO.writeCompoundTag(output, each);
}
output.writeBoolean(trustEdges);
DataTypeIO.writeVarInt(output, skyLightBitMasks.length);
for (long l : skyLightBitMasks) {
output.writeLong(l);
}
DataTypeIO.writeVarInt(output, blockLightBitMasks.length);
for (long l : blockLightBitMasks) {
output.writeLong(l);
}
DataTypeIO.writeVarInt(output, skyLightBitMasksEmpty.length);
for (long l : skyLightBitMasksEmpty) {
output.writeLong(l);
}
DataTypeIO.writeVarInt(output, blockLightBitMasksEmpty.length);
for (long l : blockLightBitMasksEmpty) {
output.writeLong(l);
}
DataTypeIO.writeVarInt(output, skylightArrays.stream().mapToInt(each -> each == null ? 0 : 1).sum());
for (int i = skylightArrays.size() - 1; i >= 0; i--) {
Byte[] array = skylightArrays.get(i);
if (array != null) {
DataTypeIO.writeVarInt(output, 2048);
//System.out.println(Arrays.toString(ArrayUtils.toPrimitive(array)));
for (int u = 0; u < array.length; u++) {
output.writeByte(array[u]);
}
}
}
DataTypeIO.writeVarInt(output, blocklightArrays.stream().mapToInt(each -> each == null ? 0 : 1).sum());
for (int i = blocklightArrays.size() - 1; i >= 0; i--) {
Byte[] array = blocklightArrays.get(i);
if (array != null) {
DataTypeIO.writeVarInt(output, 2048);
//System.out.println(Arrays.toString(ArrayUtils.toPrimitive(array)));
for (int u = 0; u < array.length; u++) {
output.writeByte(array[u]);
}
}
}
return buffer.toByteArray();
}
}

View File

@ -1,130 +0,0 @@
package com.loohp.limbo.server.packets;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.BitSet;
import java.util.List;
import com.loohp.limbo.utils.DataTypeIO;
public class PacketPlayOutLightUpdate extends PacketOut {
private int chunkX;
private int chunkZ;
private boolean trustEdges;
private long[] skyLightBitMasks;
private long[] blockLightBitMasks;
private long[] skyLightBitMasksEmpty;
private long[] blockLightBitMasksEmpty;
private List<Byte[]> skylightArrays;
private List<Byte[]> blocklightArrays;
public PacketPlayOutLightUpdate(int chunkX, int chunkZ, boolean trustEdges, List<Byte[]> skylightArrays, List<Byte[]> blocklightArrays) {
this.chunkX = chunkX;
this.chunkZ = chunkZ;
this.trustEdges = trustEdges;
this.skylightArrays = skylightArrays;
this.blocklightArrays = blocklightArrays;
BitSet skyLightBitSet = new BitSet();
BitSet skyLightBitSetInverse = new BitSet();
for (int i = Math.min(17, skylightArrays.size() - 1); i >= 0; i--) {
skyLightBitSet.set(i, skylightArrays.get(i) != null);
skyLightBitSetInverse.set(i, skylightArrays.get(i) == null);
}
skyLightBitMasks = skyLightBitSet.toLongArray();
skyLightBitMasksEmpty = skyLightBitSetInverse.toLongArray();
BitSet blockLightBitSet = new BitSet();
BitSet blockLightBitSetInverse = new BitSet();
for (int i = Math.min(17, blocklightArrays.size() - 1); i >= 0; i--) {
blockLightBitSet.set(i, blocklightArrays.get(i) != null);
blockLightBitSetInverse.set(i, blocklightArrays.get(i) == null);
}
blockLightBitMasks = blockLightBitSet.toLongArray();
blockLightBitMasksEmpty = blockLightBitSetInverse.toLongArray();
}
public int getChunkX() {
return chunkX;
}
public int getChunkZ() {
return chunkZ;
}
public boolean isTrustEdges() {
return trustEdges;
}
public long[] getSkyLightBitMasks() {
return skyLightBitMasks;
}
public long[] getBlockLightBitMasks() {
return blockLightBitMasks;
}
public List<Byte[]> getSkylightArrays() {
return skylightArrays;
}
public List<Byte[]> getBlocklightArrays() {
return blocklightArrays;
}
@Override
public byte[] serializePacket() throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DataOutputStream output = new DataOutputStream(buffer);
output.writeByte(Packet.getPlayOut().get(getClass()));
DataTypeIO.writeVarInt(output, chunkX);
DataTypeIO.writeVarInt(output, chunkZ);
output.writeBoolean(trustEdges);
DataTypeIO.writeVarInt(output, skyLightBitMasks.length);
for (long l : skyLightBitMasks) {
output.writeLong(l);
}
DataTypeIO.writeVarInt(output, blockLightBitMasks.length);
for (long l : blockLightBitMasks) {
output.writeLong(l);
}
DataTypeIO.writeVarInt(output, skyLightBitMasksEmpty.length);
for (long l : skyLightBitMasksEmpty) {
output.writeLong(l);
}
DataTypeIO.writeVarInt(output, blockLightBitMasksEmpty.length);
for (long l : blockLightBitMasksEmpty) {
output.writeLong(l);
}
DataTypeIO.writeVarInt(output, skylightArrays.stream().mapToInt(each -> each == null ? 0 : 1).sum());
for (int i = skylightArrays.size() - 1; i >= 0; i--) {
Byte[] array = skylightArrays.get(i);
if (array != null) {
DataTypeIO.writeVarInt(output, 2048);
//System.out.println(Arrays.toString(ArrayUtils.toPrimitive(array)));
for (int u = 0; u < array.length; u++) {
output.writeByte(array[u]);
}
}
}
DataTypeIO.writeVarInt(output, blocklightArrays.stream().mapToInt(each -> each == null ? 0 : 1).sum());
for (int i = blocklightArrays.size() - 1; i >= 0; i--) {
Byte[] array = blocklightArrays.get(i);
if (array != null) {
DataTypeIO.writeVarInt(output, 2048);
//System.out.println(Arrays.toString(ArrayUtils.toPrimitive(array)));
for (int u = 0; u < array.length; u++) {
output.writeByte(array[u]);
}
}
}
return buffer.toByteArray();
}
}

View File

@ -27,12 +27,13 @@ public class PacketPlayOutLogin extends PacketOut {
private long hashedSeed;
private byte maxPlayers;
private int viewDistance;
private int simulationDistance;
private boolean reducedDebugInfo;
private boolean enableRespawnScreen;
private boolean isDebug;
private boolean isFlat;
public PacketPlayOutLogin(int entityId, boolean isHardcore, GameMode gamemode, List<World> worlds, CompoundTag dimensionCodec, World world, long hashedSeed, byte maxPlayers, int viewDistance, boolean reducedDebugInfo, boolean enableRespawnScreen, boolean isDebug, boolean isFlat) {
public PacketPlayOutLogin(int entityId, boolean isHardcore, GameMode gamemode, List<World> worlds, CompoundTag dimensionCodec, World world, long hashedSeed, byte maxPlayers, int viewDistance, int simulationDistance, boolean reducedDebugInfo, boolean enableRespawnScreen, boolean isDebug, boolean isFlat) {
this.entityId = entityId;
this.isHardcore = isHardcore;
this.gamemode = gamemode;
@ -43,6 +44,7 @@ public class PacketPlayOutLogin extends PacketOut {
this.hashedSeed = hashedSeed;
this.maxPlayers = maxPlayers;
this.viewDistance = viewDistance;
this.simulationDistance = simulationDistance;
this.reducedDebugInfo = reducedDebugInfo;
this.enableRespawnScreen = enableRespawnScreen;
this.isDebug = isDebug;
@ -88,6 +90,10 @@ public class PacketPlayOutLogin extends PacketOut {
public int getViewDistance() {
return viewDistance;
}
public int getSimulationDistance() {
return simulationDistance;
}
public boolean isReducedDebugInfo() {
return reducedDebugInfo;
@ -133,6 +139,7 @@ public class PacketPlayOutLogin extends PacketOut {
output.writeLong(hashedSeed);
DataTypeIO.writeVarInt(output, maxPlayers);
DataTypeIO.writeVarInt(output, viewDistance);
DataTypeIO.writeVarInt(output, simulationDistance);
output.writeBoolean(reducedDebugInfo);
output.writeBoolean(enableRespawnScreen);
output.writeBoolean(isDebug);

View File

@ -1,212 +0,0 @@
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.BitsUtils;
import com.loohp.limbo.utils.DataTypeIO;
import com.loohp.limbo.world.Environment;
import com.loohp.limbo.world.GeneratedBlockDataMappings;
import net.querz.mca.Chunk;
import net.querz.mca.Section;
import net.querz.nbt.tag.CompoundTag;
import net.querz.nbt.tag.ListTag;
public class PacketPlayOutMapChunk extends PacketOut {
private int chunkX;
private int chunkZ;
private Chunk chunk;
private Environment environment;
public PacketPlayOutMapChunk(int chunkX, int chunkZ, Chunk chunk, Environment environment) {
this.chunkX = chunkX;
this.chunkZ = chunkZ;
this.chunk = chunk;
this.environment = environment;
}
@Deprecated
public PacketPlayOutMapChunk(int chunkX, int chunkZ, Chunk chunk) {
this(chunkZ, chunkZ, chunk, Environment.NORMAL);
}
public Chunk getChunk() {
return chunk;
}
public int getChunkX() {
return chunkX;
}
public int getChunkZ() {
return chunkZ;
}
public Environment getEnvironment() {
return environment;
}
@Override
public byte[] serializePacket() throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
DataOutputStream output = new DataOutputStream(buffer);
output.writeByte(Packet.getPlayOut().get(getClass()));
output.writeInt(chunkX);
output.writeInt(chunkZ);
BitSet chunkPresent = new BitSet();
for (int i = 0; i < 16; i++) {
Section section = chunk.getSection(i);
chunkPresent.set(i, section != null);
}
long[] bitmasks = chunkPresent.toLongArray();
DataTypeIO.writeVarInt(output, bitmasks.length);
for (long l : bitmasks) {
output.writeLong(l);
}
DataTypeIO.writeCompoundTag(output, chunk.getHeightMaps());
DataTypeIO.writeVarInt(output, 1024);
int biome;
if (environment.equals(Environment.END)) {
biome = 9; //the_end
} else if (environment.equals(Environment.NETHER)) {
biome = 8; //nether_waste
} else if (environment.equals(Environment.NORMAL)) {
biome = 1; //plains
} else {
biome = 1; //plains
}
for (int i = 0; i < 1024; i++) {
DataTypeIO.writeVarInt(output, biome);
}
ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(dataBuffer);
for (int i = 0; i < 16; i++) {
Section section = chunk.getSection(i);
if (section != null) {
int counter = 0;
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = 0; y < 16; y++) {
CompoundTag tag = section.getBlockStateAt(x, y, z);
if (tag != null && !tag.getString("Name").equals("minecraft:air")) {
counter++;
}
}
}
}
dataOut.writeShort(counter);
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 {
newBits = 8;
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<CompoundTag> itr1 = section.getPalette().iterator();
//Limbo.getInstance().getConsole().sendMessage("Nonnull -> " + i + " " + newBits);
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 {
try {
dataOut.writeByte(15);
section.getBlockStates();
int longsNeeded = 1024;
List<Integer> 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<Long> 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();
}
}
}
}
byte[] data = dataBuffer.toByteArray();
DataTypeIO.writeVarInt(output, data.length);
output.write(data);
ListTag<CompoundTag> tileEntities = chunk.getTileEntities();
DataTypeIO.writeVarInt(output, tileEntities.size());
for (CompoundTag each : tileEntities) {
DataTypeIO.writeCompoundTag(output, each);
}
return buffer.toByteArray();
}
}

View File

@ -28,9 +28,8 @@
"PacketPlayOutSpawnPosition": "0x4B",
"PacketPlayOutChat": "0x0F",
"PacketPlayOutPlayerAbilities": "0x32",
"PacketPlayOutMapChunk": "0x22",
"ClientboundLevelChunkWithLightPacket": "0x22",
"PacketPlayOutUnloadChunk": "0x1D",
"PacketPlayOutLightUpdate": "0x25",
"PacketPlayOutKeepAlive": "0x21",
"PacketPlayOutPlayerInfo": "0x36",
"PacketPlayOutUpdateViewPosition": "0x49",
@ -45,7 +44,7 @@
"PacketPlayOutSpawnEntity": "0x00",
"PacketPlayOutSpawnEntityLiving": "0x02",
"PacketPlayOutHeldItemChange": "0x48",
"PacketPlayOutPlayerListHeaderFooter": "0x5E",
"PacketPlayOutPlayerListHeaderFooter": "0x5F",
"PacketPlayOutResourcePackSend": "0x3C"
},
"StatusIn": {

File diff suppressed because it is too large Load Diff