diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaBulkChunkTranslator.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaBulkChunkTranslator.java new file mode 100644 index 000000000..66b6ab226 --- /dev/null +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaBulkChunkTranslator.java @@ -0,0 +1,80 @@ +package us.myles.ViaVersion.bukkit; + +import com.google.common.collect.Lists; +import us.myles.ViaVersion.ViaVersionPlugin; +import us.myles.ViaVersion.api.Via; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks; +import us.myles.ViaVersion.util.ReflectionUtil; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.logging.Level; + +public class BukkitViaBulkChunkTranslator extends BulkChunkTranslatorProvider { + // Reflection + private static ReflectionUtil.ClassReflection mapChunkBulkRef; + private static ReflectionUtil.ClassReflection mapChunkRef; + private static Method obfuscateRef; + + static { + try { + // TODO: Abstract this ? + mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk")); + mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk")); + if (((ViaVersionPlugin) Via.getPlatform()).isSpigot()) { + obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, ReflectionUtil.nms("World")); + } + } catch (Exception e) { + Via.getPlatform().getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e); + } + } + + @Override + public List transformMapChunkBulk(Object packet, ClientChunks clientChunks) { + List list = Lists.newArrayList(); + try { + int[] xcoords = mapChunkBulkRef.getFieldValue("a", packet, int[].class); + int[] zcoords = mapChunkBulkRef.getFieldValue("b", packet, int[].class); + Object[] chunkMaps = mapChunkBulkRef.getFieldValue("c", packet, Object[].class); + + if (Via.getConfig().isAntiXRay() && ((ViaVersionPlugin) Via.getPlatform()).isSpigot()) { //Spigot anti-xray patch + try { + Object world = mapChunkBulkRef.getFieldValue("world", packet, Object.class); + + for (int i = 0; i < xcoords.length; ++i) { + Object spigotConfig = ReflectionUtil.getPublic(world, "spigotConfig", Object.class); + Object antiXrayInstance = ReflectionUtil.getPublic(spigotConfig, "antiXrayInstance", Object.class); + + Object b = ReflectionUtil.get(chunkMaps[i], "b", Object.class); + Object a = ReflectionUtil.get(chunkMaps[i], "a", Object.class); + + obfuscateRef.invoke(antiXrayInstance, xcoords[i], zcoords[i], b, a, world); + } + } catch (Exception e) { + // not spigot, or it failed. + } + } + for (int i = 0; i < chunkMaps.length; i++) { + int x = xcoords[i]; + int z = zcoords[i]; + Object chunkMap = chunkMaps[i]; + Object chunkPacket = mapChunkRef.newInstance(); + mapChunkRef.setFieldValue("a", chunkPacket, x); + mapChunkRef.setFieldValue("b", chunkPacket, z); + mapChunkRef.setFieldValue("c", chunkPacket, chunkMap); + mapChunkRef.setFieldValue("d", chunkPacket, true); // Chunk bulk chunks are always ground-up + clientChunks.getBulkChunks().add(ClientChunks.toLong(x, z)); // Store for later + list.add(chunkPacket); + } + } catch (Exception e) { + Via.getPlatform().getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e); + } + return list; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaLoader.java b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaLoader.java index 48e76ed00..9c6e7bf7b 100644 --- a/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaLoader.java +++ b/bukkit/src/main/java/us/myles/ViaVersion/bukkit/BukkitViaLoader.java @@ -14,7 +14,9 @@ import us.myles.ViaVersion.listeners.UpdateListener; import us.myles.ViaVersion.listeners.protocol1_9to1_8.*; import us.myles.ViaVersion.protocols.base.ProtocolInfo; import us.myles.ViaVersion.protocols.protocol1_9to1_8.ViaIdleThread; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.HandItemProvider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; import java.util.UUID; import java.util.concurrent.Callable; @@ -56,6 +58,8 @@ public class BukkitViaLoader implements ViaPlatformLoader { } /* Providers */ + Via.getManager().getProviders().use(BulkChunkTranslatorProvider.class, new BukkitViaBulkChunkTranslator()); + Via.getManager().getProviders().use(MovementTransmitterProvider.class, new BukkitViaMovementTransmitter()); Via.getManager().getProviders().use(HandItemProvider.class, new HandItemProvider() { @Override public Item getHandItem(final UserConnection info) { diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java index 3a14a4340..8926966ff 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/Protocol1_9TO1_8.java @@ -15,6 +15,7 @@ import us.myles.ViaVersion.api.type.Type; import us.myles.ViaVersion.api.type.types.version.Metadata1_8Type; import us.myles.ViaVersion.api.type.types.version.MetadataList1_8Type; import us.myles.ViaVersion.protocols.protocol1_9to1_8.packets.*; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.HandItemProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider; import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.*; @@ -81,6 +82,7 @@ public class Protocol1_9TO1_8 extends Protocol { @Override protected void register(ViaProviders providers) { providers.register(HandItemProvider.class, new HandItemProvider()); + providers.register(BulkChunkTranslatorProvider.class, new BulkChunkTranslatorProvider()); providers.require(MovementTransmitterProvider.class); if (Via.getConfig().isStimulatePlayerTick()) { Via.getPlatform().runRepeatingSync(new ViaIdleThread(), 1L); @@ -89,6 +91,8 @@ public class Protocol1_9TO1_8 extends Protocol { @Override public boolean isFiltered(Class packetClass) { + if (!Via.getManager().getProviders().get(BulkChunkTranslatorProvider.class).isEnabled()) + return false; return packetClass.getName().endsWith("PacketPlayOutMapChunkBulk"); } diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java index 45c6d8117..8139ce841 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/packets/WorldPackets.java @@ -125,6 +125,30 @@ public class WorldPackets { } }); + // Bulk Chunk Packet + protocol.registerOutgoing(State.PLAY, 0x26, -1, new PacketRemapper() { + @Override + public void registerMap() { + handler(new PacketHandler() { + @Override + public void handle(PacketWrapper wrapper) throws Exception { +// ClientChunks clientChunks = wrapper.user().get(ClientChunks.class); +// Chunk1_9to1_8 chunk = (Chunk1_9to1_8) wrapper.passthrough(new ChunkType(clientChunks)); +// if (chunk.isUnloadPacket()) +// wrapper.setId(0x1D); +// +// // eat any other data (Usually happens with unload packets) +// wrapper.read(Type.REMAINING_BYTES); + // TODO: Implement Bulk Chunks + // Boolean + // Column Count + + wrapper.cancel(); + } + }); + } + }); + // Update Block Entity Packet protocol.registerOutgoing(State.PLAY, 0x35, 0x09, new PacketRemapper() { @Override diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/BulkChunkTranslatorProvider.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/BulkChunkTranslatorProvider.java new file mode 100644 index 000000000..c84698fdb --- /dev/null +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/providers/BulkChunkTranslatorProvider.java @@ -0,0 +1,17 @@ +package us.myles.ViaVersion.protocols.protocol1_9to1_8.providers; + +import us.myles.ViaVersion.api.platform.providers.Provider; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.storage.ClientChunks; + +import java.util.Arrays; +import java.util.List; + +public class BulkChunkTranslatorProvider implements Provider { + public List transformMapChunkBulk(Object packet, ClientChunks clientChunks) { + return Arrays.asList(packet); + } + + public boolean isEnabled() { + return false; + } +} diff --git a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java index 8573aa70b..67c7fe36d 100644 --- a/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java +++ b/common/src/main/java/us/myles/ViaVersion/protocols/protocol1_9to1_8/storage/ClientChunks.java @@ -1,40 +1,18 @@ package us.myles.ViaVersion.protocols.protocol1_9to1_8.storage; -import com.google.common.collect.Lists; import com.google.common.collect.Sets; import lombok.Getter; import us.myles.ViaVersion.api.Via; -import us.myles.ViaVersion.api.ViaVersion; import us.myles.ViaVersion.api.data.StoredObject; import us.myles.ViaVersion.api.data.UserConnection; -import us.myles.ViaVersion.util.ReflectionUtil; +import us.myles.ViaVersion.protocols.protocol1_9to1_8.providers.BulkChunkTranslatorProvider; -import java.lang.reflect.Method; import java.util.List; import java.util.Set; -import java.util.logging.Level; @Getter public class ClientChunks extends StoredObject { - // Reflection - private static ReflectionUtil.ClassReflection mapChunkBulkRef; - private static ReflectionUtil.ClassReflection mapChunkRef; - private static Method obfuscateRef; - private static Class worldRef; - static { - try { - // TODO: Abstract this ? - mapChunkBulkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunkBulk")); - mapChunkRef = new ReflectionUtil.ClassReflection(ReflectionUtil.nms("PacketPlayOutMapChunk")); - if (ViaVersion.getInstance().isSpigot()) { - obfuscateRef = Class.forName("org.spigotmc.AntiXray").getMethod("obfuscate", int.class, int.class, int.class, byte[].class, ReflectionUtil.nms("World")); - worldRef = ReflectionUtil.nms("World"); - } - } catch (Exception e) { - Via.getPlatform().getLogger().log(Level.WARNING, "Failed to initialise chunks reflection", e); - } - } private final Set loadedChunks = Sets.newConcurrentHashSet(); private final Set bulkChunks = Sets.newConcurrentHashSet(); @@ -43,49 +21,11 @@ public class ClientChunks extends StoredObject { super(user); } - private static long toLong(int msw, int lsw) { + public static long toLong(int msw, int lsw) { return ((long) msw << 32) + lsw - -2147483648L; } public List transformMapChunkBulk(Object packet) { - List list = Lists.newArrayList(); - try { - int[] xcoords = mapChunkBulkRef.getFieldValue("a", packet, int[].class); - int[] zcoords = mapChunkBulkRef.getFieldValue("b", packet, int[].class); - Object[] chunkMaps = mapChunkBulkRef.getFieldValue("c", packet, Object[].class); - - if (Via.getConfig().isAntiXRay() && Via.getInstance().isSpigot()) { //Spigot anti-xray patch - try { - Object world = mapChunkBulkRef.getFieldValue("world", packet, Object.class); - - for (int i = 0; i < xcoords.length; ++i) { - Object spigotConfig = ReflectionUtil.getPublic(world, "spigotConfig", Object.class); - Object antiXrayInstance = ReflectionUtil.getPublic(spigotConfig, "antiXrayInstance", Object.class); - - Object b = ReflectionUtil.get(chunkMaps[i], "b", Object.class); - Object a = ReflectionUtil.get(chunkMaps[i], "a", Object.class); - - obfuscateRef.invoke(antiXrayInstance, xcoords[i], zcoords[i], b, a, world); - } - } catch (Exception e) { - // not spigot, or it failed. - } - } - for (int i = 0; i < chunkMaps.length; i++) { - int x = xcoords[i]; - int z = zcoords[i]; - Object chunkMap = chunkMaps[i]; - Object chunkPacket = mapChunkRef.newInstance(); - mapChunkRef.setFieldValue("a", chunkPacket, x); - mapChunkRef.setFieldValue("b", chunkPacket, z); - mapChunkRef.setFieldValue("c", chunkPacket, chunkMap); - mapChunkRef.setFieldValue("d", chunkPacket, true); // Chunk bulk chunks are always ground-up - bulkChunks.add(toLong(x, z)); // Store for later - list.add(chunkPacket); - } - } catch (Exception e) { - Via.getPlatform().getLogger().log(Level.WARNING, "Failed to transform chunks bulk", e); - } - return list; + return Via.getManager().getProviders().get(BulkChunkTranslatorProvider.class).transformMapChunkBulk(packet, this); } }