update readme, parse .viafabric before autodetect, close #89 by stealing viaversion-velocity code

This commit is contained in:
creeper123123321 2021-01-11 12:02:03 -03:00
parent 98d9052aaf
commit db57b474d9
8 changed files with 142 additions and 51 deletions

View File

@ -21,17 +21,19 @@ or registry synchronization (fabric-registry-sync mod).
| Dependency | Download |
| ----------------------------------------- | ------------------------------------------------------------------------------------------ |
| (Bundled 3.2.0 release) ViaVersion 3.2.0+ | https://ci.viaversion.com/job/ViaVersion/ or https://ci.viaversion.com/job/ViaVersion-DEV/ |
| (Bundled 3.2.1 release) ViaVersion 3.2.1+ | https://ci.viaversion.com/job/ViaVersion/ or https://ci.viaversion.com/job/ViaVersion-DEV/ |
| (Bundled) Cotton Client Commands | https://www.curseforge.com/minecraft/mc-mods/cotton-client-commands |
| (Optional) Fabric Command API v1/v0 | https://www.curseforge.com/minecraft/mc-mods/fabric-api |
| (Optional) Fabric Lifecycle Events v1/v0 | https://www.curseforge.com/minecraft/mc-mods/fabric-api |
| Fabric Resource Loader v0 | https://www.curseforge.com/minecraft/mc-mods/fabric-api |
**1.8.9 Dependencies:**
| Dependency | Download |
| ----------------------------------------- | ------------------------------------------------------------------------------------------ |
| (Bundled 3.2.0 release) ViaVersion 3.2.0+ | https://ci.viaversion.com/job/ViaVersion/ or https://ci.viaversion.com/job/ViaVersion-DEV/ |
| (Bundled 3.2.1 release) ViaVersion 3.2.1+ | https://ci.viaversion.com/job/ViaVersion/ or https://ci.viaversion.com/job/ViaVersion-DEV/ |
| (Optional) Fabric Commands v0 | https://www.curseforge.com/minecraft/mc-mods/legacy-fabric-api |
| (Optional) Fabric Lifecycle Events v1 | https://www.curseforge.com/minecraft/mc-mods/legacy-fabric-api |
| Fabric Resource Loader v0 | https://www.curseforge.com/minecraft/mc-mods/legacy-fabric-api |
@ -102,6 +104,12 @@ Adding [ViaBackwards](https://viaversion.com/backwards) (and optionally [ViaRewi
- [ViaVersion](https://viaversion.com): ViaVersion can run as a plugin for BungeeCord, CraftBukkit, SpongeCommon and Velocity servers.
**Cool things to try:**
- [Geyser](https://geysermc.org/): Plugins, Fabric mod and a standalone proxy for Bedrock edition translation.
- [PolyMc](https://github.com/TheEpicBlock/PolyMc): Fabric mods which translates modded items and blocks, allowing
vanilla to connect using resource packs.
**How can I disable client-side ViaFabric?:**
- You can disable it in the menu or by setting global protocol version to -1 (this will keep per-server translations still enabled)

View File

@ -25,7 +25,39 @@
package com.github.creeper123123321.viafabric.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.handler.codec.MessageToMessageDecoder;
import us.myles.ViaVersion.util.PipelineUtil;
import java.lang.reflect.InvocationTargetException;
public class CommonTransformer {
public static final String HANDLER_DECODER_NAME = "via-decoder";
public static final String HANDLER_ENCODER_NAME = "via-encoder";
public static void decompress(ChannelHandlerContext ctx, ByteBuf buf) throws InvocationTargetException {
ChannelHandler handler = ctx.pipeline().get("decompress");
ByteBuf decompressed = handler instanceof MessageToMessageDecoder
? (ByteBuf) PipelineUtil.callDecode((MessageToMessageDecoder<?>) handler, ctx, buf).get(0)
: (ByteBuf) PipelineUtil.callDecode((ByteToMessageDecoder) handler, ctx, buf).get(0);
try {
buf.clear().writeBytes(decompressed);
} finally {
decompressed.release();
}
}
public static void compress(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
ByteBuf compressed = ctx.alloc().buffer();
try {
PipelineUtil.callEncode((MessageToByteEncoder<?>) ctx.pipeline().get("compress"), ctx, buf, compressed);
buf.clear().writeBytes(compressed);
} finally {
compressed.release();
}
}
}

View File

@ -34,11 +34,14 @@ import us.myles.ViaVersion.exception.CancelCodecException;
import us.myles.ViaVersion.exception.CancelDecoderException;
import us.myles.ViaVersion.util.PipelineUtil;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
@ChannelHandler.Sharable
public class FabricDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
private final UserConnection info;
private boolean handledCompression;
private boolean skipDoubleTransform;
public FabricDecodeHandler(UserConnection info) {
this.info = info;
@ -48,8 +51,15 @@ public class FabricDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
return info;
}
// https://github.com/ViaVersion/ViaVersion/blob/master/velocity/src/main/java/us/myles/ViaVersion/velocity/handlers/VelocityDecodeHandler.java
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
if (skipDoubleTransform) {
skipDoubleTransform = false;
out.add(bytebuf.retain());
return;
}
if (!info.checkIncomingPacket()) throw CancelDecoderException.generate(null);
if (!info.shouldTransformPacket()) {
out.add(bytebuf.retain());
@ -58,13 +68,40 @@ public class FabricDecodeHandler extends MessageToMessageDecoder<ByteBuf> {
ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
try {
boolean needsCompress = handleCompressionOrder(ctx, transformedBuf);
info.transformIncoming(transformedBuf, CancelDecoderException::generate);
if (needsCompress) {
CommonTransformer.compress(ctx, transformedBuf);
skipDoubleTransform = true;
}
out.add(transformedBuf.retain());
} finally {
transformedBuf.release();
}
}
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf buf) throws InvocationTargetException {
if (handledCompression) return false;
int decoderIndex = ctx.pipeline().names().indexOf("decompress");
if (decoderIndex == -1) return false;
handledCompression = true;
if (decoderIndex > ctx.pipeline().names().indexOf("via-decoder")) {
// Need to decompress this packet due to bad order
CommonTransformer.decompress(ctx, buf);
ChannelHandler encoder = ctx.pipeline().get("via-encoder");
ChannelHandler decoder = ctx.pipeline().get("via-decoder");
ctx.pipeline().remove(encoder);
ctx.pipeline().remove(decoder);
ctx.pipeline().addAfter("compress", "via-encoder", encoder);
ctx.pipeline().addAfter("decompress", "via-decoder", decoder);
return true;
}
return false;
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (PipelineUtil.containsCause(cause, CancelCodecException.class)) return;

View File

@ -34,18 +34,20 @@ import us.myles.ViaVersion.exception.CancelCodecException;
import us.myles.ViaVersion.exception.CancelEncoderException;
import us.myles.ViaVersion.util.PipelineUtil;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
@ChannelHandler.Sharable
public class FabricEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
private final UserConnection info;
private boolean handledCompression;
public FabricEncodeHandler(UserConnection info) {
this.info = info;
}
@Override
protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, final List<Object> out) throws Exception {
protected void encode(final ChannelHandlerContext ctx, ByteBuf bytebuf, List<Object> out) throws Exception {
if (!info.checkOutgoingPacket()) throw CancelEncoderException.generate(null);
if (!info.shouldTransformPacket()) {
out.add(bytebuf.retain());
@ -54,13 +56,39 @@ public class FabricEncodeHandler extends MessageToMessageEncoder<ByteBuf> {
ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
try {
boolean needsCompress = handleCompressionOrder(ctx, transformedBuf);
info.transformOutgoing(transformedBuf, CancelEncoderException::generate);
if (needsCompress) {
CommonTransformer.compress(ctx, transformedBuf);
}
out.add(transformedBuf.retain());
} finally {
transformedBuf.release();
}
}
private boolean handleCompressionOrder(ChannelHandlerContext ctx, ByteBuf buf) throws InvocationTargetException {
if (handledCompression) return false;
int encoderIndex = ctx.pipeline().names().indexOf("compress");
if (encoderIndex == -1) return false;
handledCompression = true;
if (encoderIndex > ctx.pipeline().names().indexOf("via-encoder")) {
// Need to decompress this packet due to bad order
CommonTransformer.decompress(ctx, buf);
ChannelHandler encoder = ctx.pipeline().get("via-encoder");
ChannelHandler decoder = ctx.pipeline().get("via-decoder");
ctx.pipeline().remove(encoder);
ctx.pipeline().remove(decoder);
ctx.pipeline().addAfter("compress", "via-encoder", encoder);
ctx.pipeline().addAfter("decompress", "via-decoder", decoder);
return true;
}
return false;
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
if (PipelineUtil.containsCause(cause, CancelCodecException.class)) return;

View File

@ -35,7 +35,6 @@ import us.myles.ViaVersion.api.Pair;
import java.net.InetSocketAddress;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@ -48,23 +47,19 @@ public class ProtocolDetectionHandler extends ChannelDuplexHandler {
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
if (ctx.channel().remoteAddress() instanceof InetSocketAddress) {
try {
ScheduledFuture<?> timeoutRun = ctx.executor().schedule(() -> {
ViaFabric.JLOGGER.warning("Timeout for protocol auto-detection in "
+ ctx.channel().remoteAddress() + " server");
hold = false;
drainQueue(ctx);
ctx.pipeline().remove(this);
}, 10, TimeUnit.SECONDS);
ProtocolAutoDetector.SERVER_VER.get(((InetSocketAddress) ctx.channel().remoteAddress()))
.whenComplete((obj, ex) -> {
ctx.pipeline().remove(this);
timeoutRun.cancel(false);
});
// Let's cache it before we need it
} catch (ExecutionException e) {
ViaFabric.JLOGGER.warning("Protocol auto detector error: " + e);
}
ScheduledFuture<?> timeoutRun = ctx.executor().schedule(() -> {
ViaFabric.JLOGGER.warning("Timeout for protocol auto-detection in "
+ ctx.channel().remoteAddress() + " server");
hold = false;
drainQueue(ctx);
ctx.pipeline().remove(this);
}, 10, TimeUnit.SECONDS);
ProtocolAutoDetector.detectVersion(((InetSocketAddress) ctx.channel().remoteAddress()))
.whenComplete((obj, ex) -> {
ctx.pipeline().remove(this);
timeoutRun.cancel(false);
});
// Let's cache it before we need it
}
}

View File

@ -25,25 +25,19 @@
package com.github.creeper123123321.viafabric.mixin.pipeline;
import com.github.creeper123123321.viafabric.handler.CommonTransformer;
import com.github.creeper123123321.viafabric.handler.FabricDecodeHandler;
import com.github.creeper123123321.viafabric.handler.FabricEncodeHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import net.minecraft.network.ClientConnection;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientConnection.class)
public class MixinClientConnection {
@Shadow private Channel channel;
@Shadow
private Channel channel;
@Redirect(
method = "exceptionCaught",
@ -59,21 +53,4 @@ public class MixinClientConnection {
logger.debug(message, t);
}
}
@Inject(method = "setCompressionThreshold", at = @At(
value = "RETURN",
remap = false
))
private void fixCompressionOrder(int compressionThreshold, CallbackInfo ci) {
if (channel.pipeline().get(FabricEncodeHandler.class) == null) return;
if (channel.pipeline().names().indexOf("compress")
< channel.pipeline().names().indexOf(CommonTransformer.HANDLER_ENCODER_NAME)) {
return; // Order is correct or compression is disabled
}
// Fixes the handler order
FabricDecodeHandler decode = channel.pipeline().remove(FabricDecodeHandler.class);
FabricEncodeHandler encode = channel.pipeline().remove(FabricEncodeHandler.class);
channel.pipeline().addAfter("decompress", "via-decoder", decode);
channel.pipeline().addAfter("compress", "via-encoder", encode);
}
}

View File

@ -102,7 +102,7 @@ public class VRVersionProvider extends VersionProvider {
if (serverVer == -2) {
// Hope protocol was autodetected
ProtocolVersion autoVer =
ProtocolAutoDetector.SERVER_VER.get((InetSocketAddress) addr).getNow(null);
ProtocolAutoDetector.detectVersion((InetSocketAddress) addr).getNow(null);
if (autoVer != null) {
serverVer = autoVer.getId();
}

View File

@ -47,13 +47,17 @@ import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import us.myles.ViaVersion.api.protocol.ProtocolVersion;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
@Environment(EnvType.CLIENT)
public class ProtocolAutoDetector {
public static LoadingCache<InetSocketAddress, CompletableFuture<ProtocolVersion>> SERVER_VER = CacheBuilder.newBuilder()
private static LoadingCache<InetSocketAddress, CompletableFuture<ProtocolVersion>> SERVER_VER = CacheBuilder.newBuilder()
.expireAfterAccess(100, TimeUnit.SECONDS)
.build(CacheLoader.from((address) -> {
CompletableFuture<ProtocolVersion> future = new CompletableFuture<>();
@ -61,8 +65,6 @@ public class ProtocolAutoDetector {
try {
final ClientConnection clientConnection = new ClientConnection(NetworkSide.CLIENTBOUND);
ViaFabricAddress viaAddr = new ViaFabricAddress().parse(address.getHostString());
ChannelFuture ch = new Bootstrap()
.group(ClientConnection.CLIENT_IO_GROUP.get())
.channel(NioSocketChannel.class)
@ -121,7 +123,7 @@ public class ProtocolAutoDetector {
}
});
clientConnection.send(new HandshakeC2SPacket(viaAddr.realAddress,
clientConnection.send(new HandshakeC2SPacket(address.getHostString(),
address.getPort(), NetworkState.STATUS));
clientConnection.send(new QueryRequestC2SPacket());
});
@ -133,4 +135,16 @@ public class ProtocolAutoDetector {
return future;
}));
public static CompletableFuture<ProtocolVersion> detectVersion(InetSocketAddress address) {
try {
InetSocketAddress real = new InetSocketAddress(InetAddress.getByAddress
(new ViaFabricAddress().parse(address.getHostString()).realAddress,
address.getAddress().getAddress()), address.getPort());
return SERVER_VER.get(real);
} catch (UnknownHostException | ExecutionException e) {
ViaFabric.JLOGGER.log(Level.WARNING, "Protocol auto detector error: ", e);
return CompletableFuture.completedFuture(null);
}
}
}