Less ugly client-side pipeline code injecting

This commit is contained in:
creeper123123321 2019-10-27 10:44:35 -03:00
parent 27ba08dc52
commit ff4c2d108e
6 changed files with 130 additions and 105 deletions

View File

@ -36,59 +36,50 @@ import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.util.PipelineUtil;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
public class VRDecodeHandler extends ByteToMessageDecoder {
private UserConnection user;
private ByteToMessageDecoder minecraftDecoder;
public static final String NAME = "viafabric_decoder_handler";
public VRDecodeHandler(UserConnection user, ByteToMessageDecoder minecraftDecoder) {
public VRDecodeHandler(UserConnection user) {
this.user = user;
this.minecraftDecoder = minecraftDecoder;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
// Based on ViaVersion Sponge encoder code
ByteBuf buf = msg.alloc().buffer().writeBytes(msg);
ByteBuf outBuf = msg.alloc().buffer().writeBytes(msg);
try {
// Increment sent
user.incrementSent();
if (user.isActive()) {
// Handle ID
int id = Type.VAR_INT.read(outBuf);
// Increment sent
user.incrementSent();
if (user.isActive()) {
// Handle ID
int id = Type.VAR_INT.read(buf);
if (id != PacketWrapper.PASSTHROUGH_ID) {
// Transform
ByteBuf newPacket = buf.alloc().buffer();
try {
PacketWrapper wrapper = new PacketWrapper(id, buf, user);
if (id != PacketWrapper.PASSTHROUGH_ID) {
// Transform
PacketWrapper wrapper = new PacketWrapper(id, outBuf, user);
ProtocolInfo protInfo = user.get(ProtocolInfo.class);
protInfo.getPipeline().transform(Direction.OUTGOING, protInfo.getState(), wrapper);
wrapper.writeToBuffer(newPacket);
buf.clear();
buf.writeBytes(newPacket);
} catch (Exception e) {
buf.release();
throw e;
} finally {
newPacket.release();
ByteBuf newPacket = msg.alloc().buffer();
try {
wrapper.writeToBuffer(newPacket);
outBuf.clear();
outBuf.writeBytes(newPacket);
} finally {
newPacket.release();
}
}
}
}
// call minecraft encoder
try {
out.addAll(PipelineUtil.callDecode(this.minecraftDecoder, ctx, buf));
} catch (InvocationTargetException e) {
e.printStackTrace();
if (e.getCause() instanceof Exception) {
throw (Exception) e.getCause();
}
// pass to minecraft encoder
out.add(outBuf.retain());
} finally {
outBuf.release();
}
buf.release();
}
@Override
@ -97,11 +88,6 @@ public class VRDecodeHandler extends ByteToMessageDecoder {
super.exceptionCaught(ctx, cause);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
ProtocolInfo info = user.get(ProtocolInfo.class);

View File

@ -26,7 +26,7 @@ package com.github.creeper123123321.viafabric.handler.clientside;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.EncoderException;
import io.netty.handler.codec.MessageToByteEncoder;
import us.myles.ViaVersion.api.PacketWrapper;
import us.myles.ViaVersion.api.data.UserConnection;
@ -36,69 +36,58 @@ import us.myles.ViaVersion.packets.Direction;
import us.myles.ViaVersion.protocols.base.ProtocolInfo;
import us.myles.ViaVersion.util.PipelineUtil;
import java.lang.reflect.InvocationTargetException;
public class VREncodeHandler extends MessageToByteEncoder {
private UserConnection user;
private MessageToByteEncoder minecraftEncoder;
public static String NAME = "viafabric_encoder_handler";
public VREncodeHandler(UserConnection user, MessageToByteEncoder minecraftEncoder) {
public VREncodeHandler(UserConnection user) {
this.user = user;
this.minecraftEncoder = minecraftEncoder;
}
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
// Based on Sponge ViaVersion decoder code
if (!(msg instanceof ByteBuf)) throw new EncoderException("Received msg isn't ByteBuf");
ByteBuf pre = out.alloc().buffer();
ByteBuf outBuffer = ctx.alloc().buffer().writeBytes((ByteBuf) msg);
// call minecraft encoder
try {
PipelineUtil.callEncode(this.minecraftEncoder, ctx, msg, pre);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof Exception) {
throw (Exception) e.getCause();
}
}
// use transformers
if (outBuffer.readableBytes() > 0) {
// Ignore if pending disconnect
if (user.isPendingDisconnect()) {
return;
}
// Increment received
boolean second = user.incrementReceived();
// Check PPS
if (second && user.handlePPS())
return;
// use transformers
if (pre.readableBytes() > 0) {
// Ignore if pending disconnect
if (user.isPendingDisconnect()) {
return;
}
// Increment received
boolean second = user.incrementReceived();
// Check PPS
if (second && user.handlePPS())
return;
if (user.isActive()) {
// Handle ID
int id = Type.VAR_INT.read(pre);
// Transform
ByteBuf newPacket = pre.alloc().buffer();
try {
if (user.isActive()) {
// Handle ID
int id = Type.VAR_INT.read(outBuffer);
// Transform
if (id != PacketWrapper.PASSTHROUGH_ID) {
PacketWrapper wrapper = new PacketWrapper(id, pre, user);
PacketWrapper wrapper = new PacketWrapper(id, outBuffer, user);
ProtocolInfo protInfo = user.get(ProtocolInfo.class);
protInfo.getPipeline().transform(Direction.INCOMING, protInfo.getState(), wrapper);
wrapper.writeToBuffer(newPacket);
pre.clear();
pre.writeBytes(newPacket);
}
} catch (Exception e) {
pre.release();
throw e;
} finally {
newPacket.release();
}
}
}
out.writeBytes(pre);
pre.release();
ByteBuf newPacket = outBuffer.alloc().buffer();
try {
wrapper.writeToBuffer(newPacket);
outBuffer.clear();
outBuffer.writeBytes(newPacket);
} finally {
newPacket.release();
}
}
}
out.writeBytes(outBuffer);
}
} finally {
outBuffer.release();
}
}
@Override
@ -106,9 +95,4 @@ public class VREncodeHandler extends MessageToByteEncoder {
if (PipelineUtil.containsCause(cause, CancelException.class)) return;
super.exceptionCaught(ctx, cause);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
super.write(ctx, msg, promise);
}
}

View File

@ -0,0 +1,57 @@
/*
* MIT License
*
* Copyright (c) 2018 creeper123123321 and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.github.creeper123123321.viafabric.mixin.client;
import com.github.creeper123123321.viafabric.handler.clientside.VRDecodeHandler;
import com.github.creeper123123321.viafabric.handler.clientside.VREncodeHandler;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import net.minecraft.network.ClientConnection;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ClientConnection.class)
public class MixinClientConnection {
@Redirect(method = "setMinCompressedSize", at = @At(
value = "INVOKE",
remap = false,
target = "Lio/netty/channel/ChannelPipeline;addBefore(Ljava/lang/String;Ljava/lang/String;Lio/netty/channel/ChannelHandler;)Lio/netty/channel/ChannelPipeline;"
))
private ChannelPipeline decodeEncodePlacement(ChannelPipeline instance, String base, String newHandler, ChannelHandler handler) {
// Fixes the handler order
switch (base) {
case "decoder": {
if (instance.get(VRDecodeHandler.class) != null) base = VRDecodeHandler.NAME;
break;
}
case "encoder": {
if (instance.get(VREncodeHandler.class) != null) base = VREncodeHandler.NAME;
break;
}
}
return instance.addBefore(base, newHandler, handler);
}
}

View File

@ -29,8 +29,6 @@ import com.github.creeper123123321.viafabric.handler.clientside.VREncodeHandler;
import com.github.creeper123123321.viafabric.platform.VRClientSideUserConnection;
import io.netty.channel.Channel;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -46,11 +44,8 @@ public class MixinClientConnectionChInit {
UserConnection user = new VRClientSideUserConnection(channel);
new ProtocolPipeline(user);
MessageToByteEncoder oldEncoder = (MessageToByteEncoder) channel.pipeline().get("encoder");
ByteToMessageDecoder oldDecoder = (ByteToMessageDecoder) channel.pipeline().get("decoder");
channel.pipeline().replace("encoder", "encoder", new VREncodeHandler(user, oldEncoder));
channel.pipeline().replace("decoder", "decoder", new VRDecodeHandler(user, oldDecoder));
channel.pipeline().addBefore("encoder", VREncodeHandler.NAME, new VREncodeHandler(user));
channel.pipeline().addBefore("decoder", VRDecodeHandler.NAME, new VRDecodeHandler(user));
}
}
}

View File

@ -24,6 +24,8 @@
package com.github.creeper123123321.viafabric.platform;
import com.github.creeper123123321.viafabric.handler.clientside.VRDecodeHandler;
import com.github.creeper123123321.viafabric.handler.clientside.VREncodeHandler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
@ -51,10 +53,10 @@ public class VRClientSideUserConnection extends UserConnection {
packet.release();
final Channel channel = this.getChannel();
if (currentThread) {
PipelineUtil.getPreviousContext("decoder", channel.pipeline()).fireChannelRead(copy);
PipelineUtil.getPreviousContext(VRDecodeHandler.NAME, channel.pipeline()).fireChannelRead(copy);
} else {
channel.eventLoop().submit(() -> {
PipelineUtil.getPreviousContext("decoder", channel.pipeline()).fireChannelRead(copy);
PipelineUtil.getPreviousContext(VRDecodeHandler.NAME, channel.pipeline()).fireChannelRead(copy);
});
}
}
@ -70,17 +72,17 @@ public class VRClientSideUserConnection extends UserConnection {
copy.writeBytes(packet);
packet.release();
final Channel channel = this.getChannel();
PipelineUtil.getPreviousContext("decoder", channel.pipeline()).fireChannelRead(copy);
PipelineUtil.getPreviousContext(VRDecodeHandler.NAME, channel.pipeline()).fireChannelRead(copy);
return channel.newSucceededFuture();
}
@Override
public void sendRawPacketToServer(ByteBuf packet, boolean currentThread) {
if (currentThread) {
getChannel().pipeline().context("encoder").writeAndFlush(packet);
getChannel().pipeline().context(VREncodeHandler.NAME).writeAndFlush(packet);
} else {
getChannel().eventLoop().submit(() -> {
getChannel().pipeline().context("encoder").writeAndFlush(packet);
getChannel().pipeline().context(VREncodeHandler.NAME).writeAndFlush(packet);
});
}
}

View File

@ -3,10 +3,11 @@
"compatibilityLevel": "JAVA_8",
"package": "com.github.creeper123123321.viafabric.mixin",
"mixins": [
"MixinServerNetworkIoChInit",
"MixinClientConnection"
"MixinClientConnection",
"MixinServerNetworkIoChInit"
],
"client": [
"client.MixinClientConnection",
"client.MixinClientConnectionChInit",
"client.MixinMultiplayerScreen"
],