diff --git a/modules/API/pom.xml b/modules/API/pom.xml index ecf00464..9ce87178 100644 --- a/modules/API/pom.xml +++ b/modules/API/pom.xml @@ -3,7 +3,7 @@ 4.0.0 ProtocolLib-API ProtocolLib-API - 4.3.0-SNAPSHOT + ${minorVersion} Provides read/write access to the Minecraft protocol. http://www.spigotmc.org/resources/protocollib.1997/ @@ -20,6 +20,7 @@ UTF-8 ${project.version} + 1.12-pre2-SNAPSHOT @@ -191,62 +192,4 @@ 1 - - - - - org.spigotmc - spigot-api - ${spigotVersion} - provided - - - org.spigotmc - spigot - ${spigotVersion} - provided - - - cglib - cglib-nodep - 2.2.2 - compile - - - com.comphenix.executors - BukkitExecutors - 1.1-SNAPSHOT - compile - - - junit - junit - 4.10 - test - - - org.mockito - mockito-all - 1.8.4 - test - - - org.powermock - powermock-module-junit4 - 1.5 - test - - - org.powermock - powermock-api-mockito - 1.5 - test - - \ No newline at end of file diff --git a/modules/API/src/main/java/com/comphenix/protocol/injector/netty/NettyByteBufAdapter.java b/modules/API/src/main/java/com/comphenix/protocol/injector/netty/NettyByteBufAdapter.java index 7df96bcf..e6fa4707 100644 --- a/modules/API/src/main/java/com/comphenix/protocol/injector/netty/NettyByteBufAdapter.java +++ b/modules/API/src/main/java/com/comphenix/protocol/injector/netty/NettyByteBufAdapter.java @@ -45,6 +45,7 @@ import com.google.common.io.ByteStreams; * all indexing in the byte buffer. * @author Kristian */ +@SuppressWarnings("unused") public class NettyByteBufAdapter extends AbstractByteBuf { private DataInputStream input; private DataOutputStream output; diff --git a/modules/ProtocolLib/pom.xml b/modules/ProtocolLib/pom.xml index 45c51ab0..ac224fec 100644 --- a/modules/ProtocolLib/pom.xml +++ b/modules/ProtocolLib/pom.xml @@ -3,7 +3,7 @@ 4.0.0 ProtocolLib ProtocolLib - 4.3.0-SNAPSHOT + ${minorVersion} Provides read/write access to the Minecraft protocol. http://www.spigotmc.org/resources/protocollib.1997/ @@ -63,6 +63,7 @@ org.spigotmc:spigot org.spigotmc:spigot-api junit:junit + io.netty:* @@ -230,38 +231,10 @@ com.comphenix.protocol ProtocolLib-API ${project.version} - - - - org.spigotmc - spigot-api - ${spigotVersion} - provided - - - org.spigotmc - spigot - ${spigotVersion} - provided - - - cglib - cglib-nodep - 2.2.2 - compile - - - com.comphenix.executors - BukkitExecutors - 1.1-SNAPSHOT compile + + junit junit diff --git a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ChannelInjector.java b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ChannelInjector.java index 8b66efb9..1160ffdc 100644 --- a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ChannelInjector.java +++ b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ChannelInjector.java @@ -66,6 +66,7 @@ import io.netty.channel.ChannelPromise; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.MessageToByteEncoder; +import io.netty.util.AttributeKey; import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.internal.TypeParameterMatcher; @@ -89,6 +90,10 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector { private static Class PACKET_LOGIN_CLIENT = null; private static FieldAccessor LOGIN_GAME_PROFILE = null; + // Versioning + private static Class PACKET_SET_PROTOCOL = null; + private static AttributeKey PROTOCOL_KEY = AttributeKey.valueOf("PROTOCOL"); + // Saved accessors private static MethodAccessor DECODE_BUFFER; private static MethodAccessor ENCODE_BUFFER; @@ -97,9 +102,6 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector { // For retrieving the protocol private static FieldAccessor PROTOCOL_ACCESSOR; - // For retrieving the protocol version - private static MethodAccessor PROTOCOL_VERSION; - // The factory that created this injector private InjectionFactory factory; @@ -184,19 +186,8 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector { */ @Override public int getProtocolVersion() { - MethodAccessor accessor = PROTOCOL_VERSION; - if (accessor == null) { - try { - accessor = Accessors.getMethodAccessor(networkManager.getClass(), "getVersion"); - } catch (Throwable ex) { - } - } - - if (accessor != null) { - return (Integer) accessor.invoke(networkManager); - } else { - return MinecraftProtocolVersion.getCurrentVersion(); - } + Integer value = originalChannel.attr(PROTOCOL_KEY).get(); + return value != null ? value : MinecraftProtocolVersion.getCurrentVersion(); } @Override @@ -279,6 +270,7 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector { originalChannel.pipeline().addBefore("protocol_lib_decoder", "protocol_lib_finish", finishHandler); originalChannel.pipeline().addAfter("encoder", "protocol_lib_encoder", protocolEncoder); + try { // Intercept all write methods channelField.setValue(new ChannelProxy(originalChannel, MinecraftReflection.getPacketClass()) { // Compatibility with Spigot 1.8 @@ -370,6 +362,9 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector { return event != null ? event : BYPASSED_PACKET; } }); + } catch (Throwable ex) { + throw new RuntimeException("Failed to overwrite channel field", ex); + } injected = true; return true; @@ -602,6 +597,26 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector { // Save the channel injector factory.cacheInjector(profile.getName(), this); } + + if (PACKET_SET_PROTOCOL == null) { + try { + PACKET_SET_PROTOCOL = PacketType.Handshake.Client.SET_PROTOCOL.getPacketClass(); + } catch (Throwable ex) { + ex.printStackTrace(); // TODO debug + PACKET_SET_PROTOCOL = getClass(); // If we can't find it don't worry about it + } + } + + if (PACKET_SET_PROTOCOL.equals(packetClass)) { + FuzzyReflection fuzzy = FuzzyReflection.fromObject(packet); + try { + int protocol = (int) fuzzy.invokeMethod(packet, "getProtocol", int.class); + System.out.println("Determined protocol " + protocol); + originalChannel.attr(PROTOCOL_KEY).set(protocol); + } catch (Throwable ex) { + ex.printStackTrace(); // TODO debug + } + } } @Override diff --git a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ChannelProxy.java b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ChannelProxy.java index bb8453f5..3afe0c27 100644 --- a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ChannelProxy.java +++ b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ChannelProxy.java @@ -16,19 +16,6 @@ */ package com.comphenix.protocol.injector.netty; -import io.netty.buffer.ByteBufAllocator; -import io.netty.channel.Channel; -import io.netty.channel.ChannelConfig; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelId; -import io.netty.channel.ChannelMetadata; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelProgressivePromise; -import io.netty.channel.ChannelPromise; -import io.netty.channel.EventLoop; -import io.netty.util.Attribute; -import io.netty.util.AttributeKey; - import java.lang.reflect.Field; import java.net.SocketAddress; import java.util.Map; @@ -38,6 +25,18 @@ import com.comphenix.protocol.reflect.accessors.Accessors; import com.comphenix.protocol.reflect.accessors.FieldAccessor; import com.google.common.collect.Maps; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.Channel; +import io.netty.channel.ChannelConfig; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelMetadata; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelProgressivePromise; +import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoop; +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; + public abstract class ChannelProxy implements Channel { // Mark that a certain object does not contain a message field private static final FieldAccessor MARK_NO_MESSAGE = new FieldAccessor() { @@ -333,6 +332,7 @@ public abstract class ChannelProxy implements Channel { return delegate.compareTo(o); } + /* Added in Netty 4.1, seem to be unused public long bytesBeforeUnwritable() { return delegate.bytesBeforeUnwritable(); } @@ -348,4 +348,5 @@ public abstract class ChannelProxy implements Channel { public boolean hasAttr(AttributeKey key) { return delegate.hasAttr(key); } + */ } diff --git a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/EventLoopProxy.java b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/EventLoopProxy.java index fe1aa7bf..7e2eed59 100644 --- a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/EventLoopProxy.java +++ b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/EventLoopProxy.java @@ -257,7 +257,9 @@ abstract class EventLoopProxy implements EventLoop { return getDelegate().shutdownNow(); } + /* public ChannelFuture register(ChannelPromise promise) { return getDelegate().register(promise); } + */ } diff --git a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/PipelineProxy.java b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/PipelineProxy.java index 4dbbc48f..fdb86b2a 100644 --- a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/PipelineProxy.java +++ b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/PipelineProxy.java @@ -16,21 +16,20 @@ */ package com.comphenix.protocol.injector.netty; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.ChannelProgressivePromise; -import io.netty.channel.ChannelPromise; -import io.netty.util.concurrent.EventExecutorGroup; - import java.net.SocketAddress; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelPromise; +import io.netty.util.concurrent.EventExecutorGroup; + /** * A pipeline proxy. * @author Kristian @@ -370,6 +369,7 @@ public class PipelineProxy implements ChannelPipeline { return pipeline.writeAndFlush(arg0); } + /* Added in Netty 4.1, seem to be unused public ChannelFuture newFailedFuture(Throwable ex) { return pipeline.newFailedFuture(ex); } @@ -389,4 +389,5 @@ public class PipelineProxy implements ChannelPipeline { public ChannelPromise voidPromise() { return pipeline.voidPromise(); } + */ } diff --git a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ProtocolInjector.java b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ProtocolInjector.java index ea75052b..3c1c6984 100644 --- a/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ProtocolInjector.java +++ b/modules/ProtocolLib/src/main/java/com/comphenix/protocol/injector/netty/ProtocolInjector.java @@ -48,6 +48,7 @@ import com.comphenix.protocol.injector.spigot.AbstractPlayerHandler; import com.comphenix.protocol.reflect.FuzzyReflection; import com.comphenix.protocol.reflect.VolatileField; import com.comphenix.protocol.utility.MinecraftReflection; +import com.comphenix.protocol.utility.MinecraftVersion; import com.google.common.collect.Lists; import io.netty.channel.Channel; @@ -142,10 +143,15 @@ public class ProtocolInjector implements ChannelListener { @Override protected void initChannel(final Channel channel) throws Exception { try { - // TODO I don't like this synchronized (networkManagers) { - channel.eventLoop().submit(() -> - injectionFactory.fromChannel(channel, ProtocolInjector.this, playerFactory).inject()); + // For some reason it needs to be delayed on 1.12, but the delay breaks 1.11 and below + // TODO I see this more as a temporary hotfix than a permanent solution + if (MinecraftVersion.getCurrentVersion().getMinor() >= 12) { + channel.eventLoop().submit(() -> + injectionFactory.fromChannel(channel, ProtocolInjector.this, playerFactory).inject()); + } else { + injectionFactory.fromChannel(channel, ProtocolInjector.this, playerFactory).inject(); + } } } catch (Exception e) { reporter.reportDetailed(ProtocolInjector.this, Report.newBuilder(REPORT_CANNOT_INJECT_INCOMING_CHANNEL).messageParam(channel).error(e)); diff --git a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java index 57f0c7cb..a015cd13 100644 --- a/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java +++ b/modules/ProtocolLib/src/test/java/com/comphenix/protocol/BukkitInitialization.java @@ -63,7 +63,7 @@ public class BukkitInitialization { packaged = true; MinecraftReflection.setMinecraftPackage(Constants.NMS, Constants.OBC); - MinecraftVersion.setCurrentVersion(MinecraftVersion.FROSTBURN_UPDATE); + MinecraftVersion.setCurrentVersion(MinecraftVersion.COLOR_UPDATE); } } } diff --git a/pom.xml b/pom.xml index 54f58ff5..be76b6ba 100644 --- a/pom.xml +++ b/pom.xml @@ -8,6 +8,7 @@ UTF-8 + 4.3.0-SNAPSHOT 1.12-pre2-SNAPSHOT @@ -42,6 +43,40 @@ https://hub.spigotmc.org/nexus/content/groups/public/ + + + + + io.netty + netty-all + 4.0.23.Final + provided + + + org.spigotmc + spigot-api + ${spigotVersion} + provided + + + org.spigotmc + spigot + ${spigotVersion} + provided + + + cglib + cglib-nodep + 2.2.2 + compile + + + com.comphenix.executors + BukkitExecutors + 1.1-SNAPSHOT + compile + + clean package install