Add Bulk Chunks, need to do full packet reading as a fallback though

This commit is contained in:
Myles 2016-09-25 19:34:24 +01:00
parent d3f5ebdba7
commit 30d477c6d2
6 changed files with 132 additions and 63 deletions

View File

@ -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<Object> transformMapChunkBulk(Object packet, ClientChunks clientChunks) {
List<Object> 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;
}
}

View File

@ -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) {

View File

@ -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");
}

View File

@ -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

View File

@ -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<Object> transformMapChunkBulk(Object packet, ClientChunks clientChunks) {
return Arrays.asList(packet);
}
public boolean isEnabled() {
return false;
}
}

View File

@ -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<Long> loadedChunks = Sets.newConcurrentHashSet();
private final Set<Long> 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<Object> transformMapChunkBulk(Object packet) {
List<Object> 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);
}
}