mirror of
https://github.com/ViaVersion/ViaFabricPlus.git
synced 2024-11-21 11:46:49 +01:00
(WIP) ViaBedrock Implementation
This commit is contained in:
parent
e5aa52f10f
commit
42eb7e46e4
@ -1,5 +1,5 @@
|
||||
# ViaFabricPlus
|
||||
Clientside ViaVersion, ViaLegacy and ViaAprilFools implementation with clientside fixes for Fabric
|
||||
Clientside ViaVersion, ViaLegacy, ViaBedrock and ViaAprilFools implementation with clientside fixes for Fabric
|
||||
### This project has nothing to do with the original ViaFabric and is therefore also not compact
|
||||
|
||||
## Contact
|
||||
@ -13,6 +13,7 @@ If you just want to talk or need help with ViaFabricPlus feel free to join my
|
||||
- [x] ViaBackwards implementation
|
||||
- [x] ViaLegacy implementation
|
||||
- [x] ViaAprilFools implementation
|
||||
- [x] (Beta) ViaBedrock implementation
|
||||
- [x] BetaCraft implementation for MP Pass
|
||||
|
||||
## Clientside related Fixes
|
||||
@ -36,7 +37,7 @@ If you just want to talk or need help with ViaFabricPlus feel free to join my
|
||||
- [x] Fixed clientside packet handling (1.16.5 transactions, 1.19.0 tablist, ...)
|
||||
|
||||
## TODO
|
||||
- [ ] ViaBedrock implementation
|
||||
- [ ] Bedrock account auth for ViaBedrock
|
||||
- [ ] ClassiCube implementation for MP Pass
|
||||
- [ ] BetaCraft server list screen
|
||||
- [ ] More extensions for Classic Protocol Extensions protocol
|
||||
@ -64,6 +65,7 @@ as does [multiconnect](https://github.com/Earthcomputer/multiconnect) from Earth
|
||||
| Snake YAML | https://mvnrepository.com/artifact/org.yaml/snakeyaml/1.33 |
|
||||
| ViaLegacy | https://github.com/RaphiMC/ViaLegacy |
|
||||
| ViaAprilFools | https://github.com/RaphiMC/ViaAprilFools |
|
||||
| ViaBedrock | https://github.com/RaphiMC/ViaBedrock |
|
||||
| MC-Structs | https://github.com/Lenni0451/MCStructs |
|
||||
| Reflect | https://github.com/Lenni0451/Reflect |
|
||||
| ViaLoadingBase | https://github.com/FlorianMichael/ViaLoadingBase |
|
||||
|
11
build.gradle
11
build.gradle
@ -37,6 +37,10 @@ allprojects {
|
||||
name = "TerraformersMC"
|
||||
url = "https://maven.terraformersmc.com/releases"
|
||||
}
|
||||
maven {
|
||||
name = "OpenCollab Snapshots"
|
||||
url = "https://repo.opencollab.dev/maven-snapshots/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,9 +63,16 @@ dependencies {
|
||||
|
||||
libs "net.raphimc:ViaLegacy:${project.vialegacy_version}"
|
||||
libs "net.raphimc:ViaAprilFools:${project.viaaprilfools_version}"
|
||||
libs "net.raphimc:ViaBedrock:${project.viabedrock_version}"
|
||||
|
||||
libs "net.lenni0451.mcstructs:text:${project.mcstructs_text_version}"
|
||||
libs "net.lenni0451:Reflect:${project.reflect_version}"
|
||||
libs("org.cloudburstmc.netty:netty-transport-raknet:1.0.0.CR1-SNAPSHOT") {
|
||||
exclude group: "io.netty", module: "netty-common"
|
||||
exclude group: "io.netty", module: "netty-buffer"
|
||||
exclude group: "io.netty", module: "netty-codec"
|
||||
exclude group: "io.netty", module: "netty-transport"
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
@ -23,6 +23,7 @@ snake_yml_version=2.0
|
||||
# raphimc libs
|
||||
vialegacy_version=2.2.9-SNAPSHOT
|
||||
viaaprilfools_version=2.0.6
|
||||
viabedrock_version=0.0.1-SNAPSHOT
|
||||
|
||||
# lenni0451 libs
|
||||
mcstructs_text_version=2.2.0
|
||||
|
@ -30,6 +30,7 @@ import de.florianmichael.viafabricplus.definition.c0_30.command.ClassicProtocolC
|
||||
import de.florianmichael.viafabricplus.definition.v1_19_0.provider.CommandArgumentsProvider;
|
||||
import de.florianmichael.viafabricplus.definition.v1_8_x.ArmorPointsDefinition;
|
||||
import de.florianmichael.viafabricplus.platform.ViaAprilFoolsPlatformImpl;
|
||||
import de.florianmichael.viafabricplus.platform.ViaBedrockPlatformImpl;
|
||||
import de.florianmichael.viafabricplus.platform.ViaLegacyPlatformImpl;
|
||||
import de.florianmichael.viafabricplus.provider.*;
|
||||
import de.florianmichael.viafabricplus.settings.SettingGroup;
|
||||
@ -43,6 +44,8 @@ import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.raphimc.viaaprilfools.api.AprilFoolsProtocolVersion;
|
||||
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
|
||||
import net.raphimc.viabedrock.protocol.providers.NettyPipelineProvider;
|
||||
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
|
||||
import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicCustomCommandProvider;
|
||||
import net.raphimc.vialegacy.protocols.classic.protocola1_0_15toc0_28_30.providers.ClassicMPPassProvider;
|
||||
@ -52,6 +55,7 @@ import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.providers.
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_8to1_7_6_10.providers.GameProfileFetcher;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@ -80,12 +84,14 @@ public class ViaFabricPlus {
|
||||
protocolVersions.add(protocolVersions.indexOf(ProtocolVersion.v1_16) + 1, AprilFoolsProtocolVersion.s20w14infinite);
|
||||
protocolVersions.add(protocolVersions.indexOf(ProtocolVersion.v1_16_2) + 1, AprilFoolsProtocolVersion.sCombatTest8c);
|
||||
});
|
||||
private final SubPlatform SUB_PLATFORM_VIA_BEDROCK = new SubPlatform("ViaBedrock", () -> true, ViaBedrockPlatformImpl::new, protocolVersions -> protocolVersions.add(BedrockProtocolVersion.bedrockLatest));
|
||||
|
||||
public void preLoad() {
|
||||
CustomClassicProtocolExtensions.reflect();
|
||||
|
||||
ViaLoadingBase.ViaLoadingBaseBuilder builder = ViaLoadingBase.ViaLoadingBaseBuilder.create();
|
||||
|
||||
builder = builder.subPlatform(SUB_PLATFORM_VIA_BEDROCK, 0);
|
||||
builder = builder.subPlatform(SUB_PLATFORM_VIA_LEGACY);
|
||||
builder = builder.subPlatform(SUB_PLATFORM_VIA_APRIL_FOOLS);
|
||||
|
||||
@ -108,6 +114,7 @@ public class ViaFabricPlus {
|
||||
providers.use(GameProfileFetcher.class, new ViaFabricPlusGameProfileFetcher());
|
||||
providers.use(ClassicMPPassProvider.class, new ViaFabricPlusClassicMPPassProvider());
|
||||
providers.use(ClassicCustomCommandProvider.class, new ViaFabricPlusClassicCustomCommandProvider());
|
||||
providers.use(NettyPipelineProvider.class, new ViaFabricPlusNettyPipelineProvider());
|
||||
});
|
||||
builder = builder.onProtocolReload(protocolVersion -> {
|
||||
FabricLoader.getInstance().getEntrypoints("viafabricplus", ViaFabricPlusAddon.class).forEach(viaFabricPlusAddon -> viaFabricPlusAddon.onChangeVersion(protocolVersion));
|
||||
|
@ -17,7 +17,21 @@
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.injection.access;
|
||||
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public interface IClientConnection {
|
||||
|
||||
void viafabricplus_setupPreNettyEncryption();
|
||||
|
||||
void viafabricplus_captureAddress(final InetSocketAddress address);
|
||||
InetSocketAddress viafabricplus_capturedAddress();
|
||||
|
||||
void viafabricplus_enableZLibCompression();
|
||||
void viafabricplus_enableSnappyCompression();
|
||||
void viafabricplus_enableAesGcmEncryption(final SecretKey secretKey) throws InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException;
|
||||
}
|
||||
|
@ -18,35 +18,67 @@
|
||||
package de.florianmichael.viafabricplus.injection.mixin.base;
|
||||
|
||||
import de.florianmichael.viafabricplus.injection.access.IClientConnection;
|
||||
import de.florianmichael.viafabricplus.platform.PreNettyConstants;
|
||||
import de.florianmichael.viafabricplus.platform.pre_netty.PreNettyConstants;
|
||||
import de.florianmichael.viafabricplus.platform.raknet.BedrockRakNetConstants;
|
||||
import de.florianmichael.viafabricplus.platform.raknet.RakNetPingSessions;
|
||||
import de.florianmichael.vialoadingbase.ViaLoadingBase;
|
||||
import de.florianmichael.vialoadingbase.event.PipelineReorderEvent;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.bootstrap.AbstractBootstrap;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.epoll.EpollDatagramChannel;
|
||||
import io.netty.channel.epoll.EpollSocketChannel;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.encryption.PacketDecryptor;
|
||||
import net.minecraft.network.encryption.PacketEncryptor;
|
||||
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
|
||||
import net.raphimc.viabedrock.netty.AesGcmEncryption;
|
||||
import net.raphimc.viabedrock.netty.SnappyCompression;
|
||||
import net.raphimc.viabedrock.netty.ZLibCompression;
|
||||
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakChannelFactory;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
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;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
@Mixin(ClientConnection.class)
|
||||
public class MixinClientConnection implements IClientConnection {
|
||||
public abstract class MixinClientConnection extends SimpleChannelInboundHandler<Packet<?>> implements IClientConnection {
|
||||
|
||||
@Shadow private Channel channel;
|
||||
|
||||
@Shadow private boolean encrypted;
|
||||
|
||||
@Shadow public abstract void channelActive(ChannelHandlerContext context) throws Exception;
|
||||
|
||||
@Unique
|
||||
private Cipher viafabricplus_decryptionCipher;
|
||||
|
||||
@Unique
|
||||
private Cipher viafabricplus_encryptionCipher;
|
||||
|
||||
@Unique
|
||||
private boolean viafabricplus_compressionEnabled = false;
|
||||
|
||||
@Unique
|
||||
private InetSocketAddress viafabricplus_capturedAddress;
|
||||
|
||||
@Inject(method = "setCompressionThreshold", at = @At("RETURN"))
|
||||
private void reorderCompression(int compressionThreshold, boolean rejectBad, CallbackInfo ci) {
|
||||
channel.pipeline().fireUserEventTriggered(new PipelineReorderEvent());
|
||||
@ -61,10 +93,73 @@ public class MixinClientConnection implements IClientConnection {
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "connect", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Lazy;get()Ljava/lang/Object;"), locals = LocalCapture.CAPTURE_FAILHARD)
|
||||
private static void captureAddress(InetSocketAddress address, boolean useEpoll, CallbackInfoReturnable<ClientConnection> cir, final ClientConnection clientConnection) {
|
||||
((IClientConnection) clientConnection).viafabricplus_captureAddress(address);
|
||||
}
|
||||
|
||||
@Redirect(method = "connect", at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;channel(Ljava/lang/Class;)Lio/netty/bootstrap/AbstractBootstrap;"))
|
||||
private static AbstractBootstrap applyRakNetChannelFactory(Bootstrap instance, Class aClass) {
|
||||
if (ViaLoadingBase.getClassWrapper().getTargetVersion().isEqualTo(BedrockProtocolVersion.bedrockLatest)) {
|
||||
return instance.channelFactory(aClass == EpollSocketChannel.class ? RakChannelFactory.client(EpollDatagramChannel.class) : RakChannelFactory.client(NioDatagramChannel.class));
|
||||
}
|
||||
return instance.channel(aClass);
|
||||
}
|
||||
|
||||
@Redirect(method = "connect", at = @At(value = "INVOKE", target = "Lio/netty/bootstrap/Bootstrap;connect(Ljava/net/InetAddress;I)Lio/netty/channel/ChannelFuture;"))
|
||||
private static ChannelFuture applyRakNetPing(Bootstrap instance, InetAddress inetHost, int inetPort) {
|
||||
if (RakNetPingSessions.isPingSession(inetHost)) {
|
||||
return instance.bind(new InetSocketAddress(0)).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
|
||||
}
|
||||
return instance.connect(inetHost, inetPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
|
||||
super.channelRegistered(ctx);
|
||||
if (ViaLoadingBase.getClassWrapper().getTargetVersion().isEqualTo(BedrockProtocolVersion.bedrockLatest)) {
|
||||
channelActive(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void viafabricplus_setupPreNettyEncryption() {
|
||||
this.encrypted = true;
|
||||
this.channel.pipeline().addBefore(PreNettyConstants.HANDLER_DECODER_NAME, "decrypt", new PacketDecryptor(this.viafabricplus_decryptionCipher));
|
||||
this.channel.pipeline().addBefore(PreNettyConstants.HANDLER_ENCODER_NAME, "encrypt", new PacketEncryptor(this.viafabricplus_encryptionCipher));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void viafabricplus_captureAddress(InetSocketAddress address) {
|
||||
this.viafabricplus_capturedAddress = address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress viafabricplus_capturedAddress() {
|
||||
return this.viafabricplus_capturedAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void viafabricplus_enableZLibCompression() {
|
||||
if (this.viafabricplus_compressionEnabled) throw new IllegalStateException("Compression is already enabled");
|
||||
this.viafabricplus_compressionEnabled = true;
|
||||
|
||||
this.channel.pipeline().addBefore(BedrockRakNetConstants.BATCH_LENGTH_HANDLER_NAME, BedrockRakNetConstants.COMPRESSION_HANDLER_NAME, new ZLibCompression());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void viafabricplus_enableSnappyCompression() {
|
||||
if (this.viafabricplus_compressionEnabled) throw new IllegalStateException("Compression is already enabled");
|
||||
this.viafabricplus_compressionEnabled = true;
|
||||
|
||||
this.channel.pipeline().addBefore(BedrockRakNetConstants.BATCH_LENGTH_HANDLER_NAME, BedrockRakNetConstants.COMPRESSION_HANDLER_NAME, new SnappyCompression());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void viafabricplus_enableAesGcmEncryption(final SecretKey secretKey) throws InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
|
||||
if (this.encrypted) throw new IllegalStateException("Encryption is already enabled");
|
||||
this.encrypted = true;
|
||||
|
||||
this.channel.pipeline().addAfter(BedrockRakNetConstants.FRAME_ENCAPSULATION_HANDLER_NAME, BedrockRakNetConstants.ENCRYPTION_HANDLER_NAME, new AesGcmEncryption(secretKey));
|
||||
}
|
||||
}
|
||||
|
@ -17,29 +17,48 @@
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.injection.mixin.base;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.connection.UserConnectionImpl;
|
||||
import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
|
||||
import de.florianmichael.viafabricplus.ViaFabricPlus;
|
||||
import de.florianmichael.viafabricplus.platform.PreNettyConstants;
|
||||
import de.florianmichael.viafabricplus.platform.VFPPreNettyDecoder;
|
||||
import de.florianmichael.viafabricplus.platform.VFPPreNettyEncoder;
|
||||
import de.florianmichael.viafabricplus.injection.access.IClientConnection;
|
||||
import de.florianmichael.viafabricplus.platform.pre_netty.PreNettyConstants;
|
||||
import de.florianmichael.viafabricplus.platform.pre_netty.VFPPreNettyDecoder;
|
||||
import de.florianmichael.viafabricplus.platform.pre_netty.VFPPreNettyEncoder;
|
||||
import de.florianmichael.viafabricplus.platform.VFPVLBViaDecodeHandler;
|
||||
import de.florianmichael.viafabricplus.platform.raknet.*;
|
||||
import de.florianmichael.viafabricplus.platform.raknet.library_fix.FixedUnconnectedPingEncoder;
|
||||
import de.florianmichael.viafabricplus.platform.raknet.library_fix.FixedUnconnectedPongDecoder;
|
||||
import de.florianmichael.vialoadingbase.ViaLoadingBase;
|
||||
import de.florianmichael.vialoadingbase.netty.VLBViaEncodeHandler;
|
||||
import de.florianmichael.vialoadingbase.netty.NettyConstants;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelConfig;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
|
||||
import net.raphimc.viabedrock.netty.BatchLengthCodec;
|
||||
import net.raphimc.viabedrock.netty.PacketEncapsulationCodec;
|
||||
import net.raphimc.viabedrock.protocol.BedrockBaseProtocol;
|
||||
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
|
||||
import net.raphimc.vialegacy.protocols.release.protocol1_7_2_5to1_6_4.baseprotocols.PreNettyBaseProtocol;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakClientChannel;
|
||||
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
|
||||
import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPingEncoder;
|
||||
import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPongDecoder;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
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;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@Mixin(targets = "net.minecraft.network.ClientConnection$1")
|
||||
public class MixinClientConnection_1 {
|
||||
|
||||
@ -47,9 +66,22 @@ public class MixinClientConnection_1 {
|
||||
@Shadow
|
||||
ClientConnection field_11663;
|
||||
|
||||
@Redirect(method = "initChannel", at = @At(value = "INVOKE", target = "Lio/netty/channel/ChannelConfig;setOption(Lio/netty/channel/ChannelOption;Ljava/lang/Object;)Z"))
|
||||
public boolean applyRakNetOptions(ChannelConfig instance, ChannelOption<Object> tChannelOption, Object t) {
|
||||
if (ViaLoadingBase.getClassWrapper().getTargetVersion().isEqualTo(BedrockProtocolVersion.bedrockLatest)) {
|
||||
instance.setOption(RakChannelOption.RAK_PROTOCOL_VERSION, 11);
|
||||
instance.setOption(RakChannelOption.RAK_CONNECT_TIMEOUT, 4_000L);
|
||||
instance.setOption(RakChannelOption.RAK_SESSION_TIMEOUT, 30_000L);
|
||||
return instance.setOption(RakChannelOption.RAK_GUID, ThreadLocalRandom.current().nextLong());
|
||||
}
|
||||
return instance.setOption(tChannelOption, t);
|
||||
}
|
||||
|
||||
@Inject(method = "initChannel", at = @At("TAIL"))
|
||||
public void hackNettyPipeline(Channel channel, CallbackInfo ci) {
|
||||
if (channel instanceof SocketChannel) {
|
||||
final boolean isBedrock = ViaLoadingBase.getClassWrapper().getTargetVersion().isEqualTo(BedrockProtocolVersion.bedrockLatest);
|
||||
|
||||
if (channel instanceof SocketChannel || isBedrock) {
|
||||
final UserConnection user = new UserConnectionImpl(channel, true);
|
||||
channel.attr(ViaFabricPlus.LOCAL_VIA_CONNECTION).set(user);
|
||||
channel.attr(ViaFabricPlus.LOCAL_MINECRAFT_CONNECTION).set(field_11663);
|
||||
@ -59,12 +91,49 @@ public class MixinClientConnection_1 {
|
||||
channel.pipeline().addBefore("encoder", NettyConstants.HANDLER_ENCODER_NAME, new VLBViaEncodeHandler(user));
|
||||
channel.pipeline().addBefore("decoder", NettyConstants.HANDLER_DECODER_NAME, new VFPVLBViaDecodeHandler(user));
|
||||
|
||||
if (isBedrock) {
|
||||
user.getProtocolInfo().getPipeline().add(BedrockBaseProtocol.INSTANCE);
|
||||
|
||||
channel.pipeline().replace("splitter", BedrockRakNetConstants.BATCH_LENGTH_HANDLER_NAME, new BatchLengthCodec());
|
||||
|
||||
channel.pipeline().addBefore(BedrockRakNetConstants.BATCH_LENGTH_HANDLER_NAME, BedrockRakNetConstants.DISCONNECT_HANDLER_NAME, new DisconnectHandler());
|
||||
channel.pipeline().addAfter(BedrockRakNetConstants.DISCONNECT_HANDLER_NAME, BedrockRakNetConstants.FRAME_ENCAPSULATION_HANDLER_NAME, new RakMessageEncapsulationCodec());
|
||||
channel.pipeline().addAfter(BedrockRakNetConstants.BATCH_LENGTH_HANDLER_NAME, BedrockRakNetConstants.PACKET_ENCAPSULATION_HANDLER_NAME, new PacketEncapsulationCodec());
|
||||
|
||||
channel.pipeline().remove("prepender");
|
||||
channel.pipeline().remove("timeout");
|
||||
|
||||
final InetSocketAddress address = ((IClientConnection) field_11663).viafabricplus_capturedAddress();
|
||||
|
||||
// Pinging in RakNet is something different
|
||||
if (RakNetPingSessions.isPingSession(address.getAddress())) {
|
||||
RakNetPingSessions.pingSessions.remove(address.getAddress());
|
||||
Via.getPlatform().getLogger().info("ViaFabricPlus is capturing RakNet/Ping protocol");
|
||||
|
||||
{ // Temporary fix for the ping encoder
|
||||
final RakClientChannel rakChannel = (RakClientChannel) channel;
|
||||
|
||||
rakChannel.parent().pipeline().replace(UnconnectedPingEncoder.NAME, UnconnectedPingEncoder.NAME, new FixedUnconnectedPingEncoder(rakChannel));
|
||||
rakChannel.parent().pipeline().replace(UnconnectedPongDecoder.NAME, UnconnectedPongDecoder.NAME, new FixedUnconnectedPongDecoder(rakChannel));
|
||||
}
|
||||
|
||||
channel.pipeline().replace(BedrockRakNetConstants.FRAME_ENCAPSULATION_HANDLER_NAME, BedrockRakNetConstants.PING_ENCAPSULATION_HANDLER_NAME, new PingEncapsulationCodec(address));
|
||||
|
||||
channel.pipeline().remove(BedrockRakNetConstants.PACKET_ENCAPSULATION_HANDLER_NAME);
|
||||
channel.pipeline().remove(BedrockRakNetConstants.BATCH_LENGTH_HANDLER_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
if (ViaLoadingBase.getClassWrapper().getTargetVersion().isOlderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)) {
|
||||
user.getProtocolInfo().getPipeline().add(PreNettyBaseProtocol.INSTANCE);
|
||||
|
||||
channel.pipeline().addBefore("prepender", PreNettyConstants.HANDLER_ENCODER_NAME, new VFPPreNettyEncoder(user));
|
||||
channel.pipeline().addBefore("splitter", PreNettyConstants.HANDLER_DECODER_NAME, new VFPPreNettyDecoder(user));
|
||||
}
|
||||
|
||||
for (String name : channel.pipeline().names()) {
|
||||
System.out.println(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
|
||||
* Copyright (C) 2021-2023 FlorianMichael/MrLookAtMe (EnZaXD) and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.injection.mixin.base;
|
||||
|
||||
import de.florianmichael.viafabricplus.platform.raknet.RakNetPingSessions;
|
||||
import de.florianmichael.vialoadingbase.ViaLoadingBase;
|
||||
import net.minecraft.client.network.MultiplayerServerListPinger;
|
||||
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(MultiplayerServerListPinger.class)
|
||||
public class MixinMultiplayerServerListPinger {
|
||||
|
||||
@Redirect(method = "add", at = @At(value = "INVOKE", target = "Ljava/util/Optional;get()Ljava/lang/Object;"))
|
||||
public Object mapSocketAddress(Optional<InetSocketAddress> instance) {
|
||||
final InetSocketAddress address = instance.get();
|
||||
if (ViaLoadingBase.getClassWrapper().getTargetVersion().isEqualTo(BedrockProtocolVersion.bedrockLatest)) {
|
||||
RakNetPingSessions.storePingSession(address.getAddress());
|
||||
}
|
||||
return address;
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import de.florianmichael.vialoadingbase.ViaLoadingBase;
|
||||
import de.florianmichael.vialoadingbase.platform.ProtocolRange;
|
||||
import net.minecraft.client.network.AllowedAddressResolver;
|
||||
import net.minecraft.client.network.ServerAddress;
|
||||
import net.raphimc.viabedrock.api.BedrockProtocolVersion;
|
||||
import net.raphimc.vialegacy.api.LegacyProtocolVersion;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
@ -41,7 +42,7 @@ public class MixinServerAddress {
|
||||
|
||||
@Inject(method = "parse", at = @At("RETURN"), cancellable = true)
|
||||
private static void fixAddress(String address, CallbackInfoReturnable<ServerAddress> cir) {
|
||||
if (!cir.getReturnValue().equals(INVALID) && viafabricplus_srvRange.contains(ViaLoadingBase.getClassWrapper().getTargetVersion())) {
|
||||
if (!cir.getReturnValue().equals(INVALID) && (viafabricplus_srvRange.contains(ViaLoadingBase.getClassWrapper().getTargetVersion()) || ViaLoadingBase.getClassWrapper().getTargetVersion().isEqualTo(BedrockProtocolVersion.bedrockLatest))) {
|
||||
cir.setReturnValue(AllowedAddressResolver.DEFAULT.redirectResolver.lookupRedirect(cir.getReturnValue()).orElse(cir.getReturnValue()));
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ public class MixinConnectScreen_1 {
|
||||
}
|
||||
|
||||
final ClientConnection connection = field_2416.connection;
|
||||
if (connection == null) return;
|
||||
if (connection == null || connection.channel == null) return;
|
||||
final UserConnection userConnection = connection.channel.attr(ViaFabricPlus.LOCAL_VIA_CONNECTION).get();
|
||||
|
||||
if (userConnection == null) {
|
||||
|
@ -31,5 +31,4 @@ public abstract class MixinWorldPackets1_13 {
|
||||
private static void returnAirDefault(int oldId, CallbackInfoReturnable<Integer> cir) {
|
||||
cir.setReturnValue(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
|
||||
* Copyright (C) 2021-2023 FlorianMichael/MrLookAtMe (EnZaXD) and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.platform;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import de.florianmichael.vialoadingbase.util.JLoggerToLog4j;
|
||||
import net.raphimc.viabedrock.platform.ViaBedrockPlatform;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ViaBedrockPlatformImpl implements ViaBedrockPlatform {
|
||||
private static final Logger LOGGER = new JLoggerToLog4j(LogManager.getLogger("ViaBedrock"));
|
||||
|
||||
public ViaBedrockPlatformImpl() {
|
||||
this.init(this.getDataFolder());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Logger getLogger() {
|
||||
return LOGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDataFolder() {
|
||||
return Via.getPlatform().getDataFolder();
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.platform;
|
||||
package de.florianmichael.viafabricplus.platform.pre_netty;
|
||||
|
||||
public class PreNettyConstants {
|
||||
|
@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.platform;
|
||||
package de.florianmichael.viafabricplus.platform.pre_netty;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.platform;
|
||||
package de.florianmichael.viafabricplus.platform.pre_netty;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
|
||||
* Copyright (C) 2021-2023 FlorianMichael/MrLookAtMe (EnZaXD) and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.platform.raknet;
|
||||
|
||||
public class BedrockRakNetConstants {
|
||||
|
||||
public static final String DISCONNECT_HANDLER_NAME = "disconnect_handler";
|
||||
public static final String FRAME_ENCAPSULATION_HANDLER_NAME = "frame_encapsulation";
|
||||
public static final String PING_ENCAPSULATION_HANDLER_NAME = "ping_encapsulation";
|
||||
public static final String PACKET_ENCAPSULATION_HANDLER_NAME = "packet_encapsulation";
|
||||
public static final String BATCH_LENGTH_HANDLER_NAME = "batch_length";
|
||||
public static final String COMPRESSION_HANDLER_NAME = "compression";
|
||||
public static final String ENCRYPTION_HANDLER_NAME = "encryption";
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock
|
||||
* Copyright (C) 2023 RK_01/RaphiMC and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.platform.raknet;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
|
||||
public class DisconnectHandler extends ChannelOutboundHandlerAdapter {
|
||||
|
||||
private boolean calledDisconnect = false;
|
||||
|
||||
@Override
|
||||
public void close(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
|
||||
if (ctx.channel().isActive() && !this.calledDisconnect) {
|
||||
this.calledDisconnect = true;
|
||||
ctx.disconnect(promise); // Send disconnect notification to the server and close the channel
|
||||
} else {
|
||||
super.close(ctx, promise);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock
|
||||
* Copyright (C) 2023 RK_01/RaphiMC and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.platform.raknet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageCodec;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakConstants;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakPing;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakPong;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
public class PingEncapsulationCodec extends MessageToMessageCodec<RakPong, ByteBuf> {
|
||||
|
||||
private final InetSocketAddress remoteAddress;
|
||||
|
||||
public PingEncapsulationCodec(final InetSocketAddress remoteAddress) {
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||
final int packetId = in.readUnsignedByte();
|
||||
|
||||
if (packetId == RakConstants.ID_UNCONNECTED_PING) {
|
||||
out.add(new RakPing(in.readLong(), this.remoteAddress));
|
||||
} else {
|
||||
ctx.close();
|
||||
throw new IllegalStateException("Unexpected packet ID: " + packetId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, RakPong in, List<Object> out) {
|
||||
if (!this.remoteAddress.equals(in.getSender())) {
|
||||
ctx.close();
|
||||
throw new IllegalStateException("Received pong from unexpected address: " + in.getSender());
|
||||
}
|
||||
|
||||
final ByteBuf buf = ctx.alloc().buffer();
|
||||
buf.writeByte(RakConstants.ID_UNCONNECTED_PONG);
|
||||
buf.writeLong(in.getPingTime());
|
||||
buf.writeBytes(in.getPongData());
|
||||
out.add(buf);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock
|
||||
* Copyright (C) 2023 RK_01/RaphiMC and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.platform.raknet;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.CompositeByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageCodec;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakReliability;
|
||||
import org.cloudburstmc.netty.channel.raknet.packet.RakMessage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RakMessageEncapsulationCodec extends MessageToMessageCodec<RakMessage, ByteBuf> {
|
||||
|
||||
private static final int FRAME_ID = 0xFE;
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) {
|
||||
final CompositeByteBuf buf = ctx.alloc().compositeBuffer(2);
|
||||
try {
|
||||
buf.addComponent(true, ctx.alloc().ioBuffer(1).writeByte(FRAME_ID));
|
||||
buf.addComponent(true, msg.retainedSlice());
|
||||
out.add(buf.retain());
|
||||
} finally {
|
||||
buf.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, RakMessage msg, List<Object> out) {
|
||||
if (msg.channel() != 0 && msg.reliability() != RakReliability.RELIABLE_ORDERED) {
|
||||
return;
|
||||
}
|
||||
final ByteBuf in = msg.content();
|
||||
if (!in.isReadable()) {
|
||||
return;
|
||||
}
|
||||
final int id = in.readUnsignedByte();
|
||||
if (id != FRAME_ID) {
|
||||
throw new IllegalStateException("Invalid frame ID: " + id);
|
||||
}
|
||||
out.add(in.readRetainedSlice(in.readableBytes()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
|
||||
* Copyright (C) 2021-2023 FlorianMichael/MrLookAtMe (EnZaXD) and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.platform.raknet;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RakNetPingSessions {
|
||||
public final static List<InetAddress> pingSessions = new ArrayList<>();
|
||||
|
||||
public static void storePingSession(final InetAddress address) {
|
||||
pingSessions.add(address);
|
||||
}
|
||||
|
||||
public static boolean isPingSession(final InetAddress address) {
|
||||
return pingSessions.contains(address);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock
|
||||
* Copyright (C) 2023 RK_01/RaphiMC and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.florianmichael.viafabricplus.platform.raknet.library_fix;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakClientChannel;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakPing;
|
||||
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
|
||||
|
||||
import static org.cloudburstmc.netty.channel.raknet.RakConstants.ID_UNCONNECTED_PING;
|
||||
|
||||
// Temporary fix until the library fixes the issue
|
||||
public class FixedUnconnectedPingEncoder extends ChannelOutboundHandlerAdapter {
|
||||
|
||||
private final RakClientChannel rakClientChannel;
|
||||
|
||||
public FixedUnconnectedPingEncoder(final RakClientChannel rakClientChannel) {
|
||||
this.rakClientChannel = rakClientChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
|
||||
if (!(msg instanceof RakPing)) {
|
||||
ctx.write(msg, promise);
|
||||
return;
|
||||
}
|
||||
|
||||
RakPing ping = (RakPing) msg;
|
||||
ByteBuf magicBuf = this.rakClientChannel.config().getOption(RakChannelOption.RAK_UNCONNECTED_MAGIC);
|
||||
long guid = this.rakClientChannel.config().getOption(RakChannelOption.RAK_GUID);
|
||||
|
||||
ByteBuf pingBuffer = ctx.alloc().ioBuffer(magicBuf.readableBytes() + 17);
|
||||
pingBuffer.writeByte(ID_UNCONNECTED_PING);
|
||||
pingBuffer.writeLong(ping.getPingTime());
|
||||
pingBuffer.writeBytes(magicBuf, magicBuf.readerIndex(), magicBuf.readableBytes());
|
||||
pingBuffer.writeLong(guid);
|
||||
ctx.write(new DatagramPacket(pingBuffer, ping.getSender()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock
|
||||
* Copyright (C) 2023 RK_01/RaphiMC and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.florianmichael.viafabricplus.platform.raknet.library_fix;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakClientChannel;
|
||||
import org.cloudburstmc.netty.channel.raknet.RakPong;
|
||||
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
|
||||
import org.cloudburstmc.netty.handler.codec.raknet.AdvancedChannelInboundHandler;
|
||||
|
||||
import static org.cloudburstmc.netty.channel.raknet.RakConstants.ID_UNCONNECTED_PONG;
|
||||
|
||||
// Temporary fix until the library fixes the issue
|
||||
public class FixedUnconnectedPongDecoder extends AdvancedChannelInboundHandler<DatagramPacket> {
|
||||
|
||||
private final RakClientChannel rakClientChannel;
|
||||
|
||||
public FixedUnconnectedPongDecoder(final RakClientChannel rakClientChannel) {
|
||||
this.rakClientChannel = rakClientChannel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptInboundMessage(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
if (!super.acceptInboundMessage(ctx, msg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DatagramPacket packet = (DatagramPacket) msg;
|
||||
ByteBuf buf = packet.content();
|
||||
return buf.isReadable() && buf.getUnsignedByte(buf.readerIndex()) == ID_UNCONNECTED_PONG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) throws Exception {
|
||||
ByteBuf buf = packet.content();
|
||||
buf.readUnsignedByte(); // Packet ID
|
||||
|
||||
long pingTime = buf.readLong();
|
||||
long guid = buf.readLong();
|
||||
|
||||
ByteBuf magicBuf = this.rakClientChannel.config().getOption(RakChannelOption.RAK_UNCONNECTED_MAGIC);
|
||||
if (!buf.isReadable(magicBuf.readableBytes()) || !ByteBufUtil.equals(buf.readSlice(magicBuf.readableBytes()), magicBuf)) {
|
||||
// Magic does not match
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuf pongData = Unpooled.EMPTY_BUFFER;
|
||||
if (buf.isReadable(2)) { // Length
|
||||
pongData = buf.readRetainedSlice(buf.readUnsignedShort());
|
||||
}
|
||||
ctx.fireChannelRead(new RakPong(pingTime, guid, pongData, packet.sender()));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of ViaFabricPlus - https://github.com/FlorianMichael/ViaFabricPlus
|
||||
* Copyright (C) 2021-2023 FlorianMichael/MrLookAtMe (EnZaXD) and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package de.florianmichael.viafabricplus.provider;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import de.florianmichael.viafabricplus.ViaFabricPlus;
|
||||
import de.florianmichael.viafabricplus.injection.access.IClientConnection;
|
||||
import net.raphimc.viabedrock.protocol.providers.NettyPipelineProvider;
|
||||
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKey;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
public class ViaFabricPlusNettyPipelineProvider extends NettyPipelineProvider {
|
||||
|
||||
@Override
|
||||
public void enableCompression(UserConnection user, int threshold, int algorithm) {
|
||||
final IClientConnection currentConnection = (IClientConnection) user.getChannel().attr(ViaFabricPlus.LOCAL_MINECRAFT_CONNECTION).get();
|
||||
|
||||
try {
|
||||
switch (algorithm) {
|
||||
case 0 -> currentConnection.viafabricplus_enableZLibCompression();
|
||||
case 1 -> currentConnection.viafabricplus_enableSnappyCompression();
|
||||
|
||||
default -> throw new IllegalStateException("Invalid compression algorithm: " + algorithm);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enableEncryption(UserConnection user, SecretKey key) {
|
||||
final IClientConnection currentConnection = (IClientConnection) user.getChannel().attr(ViaFabricPlus.LOCAL_MINECRAFT_CONNECTION).get();
|
||||
|
||||
try {
|
||||
currentConnection.viafabricplus_enableAesGcmEncryption(key);
|
||||
} catch (InvalidAlgorithmParameterException | NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -5,11 +5,11 @@
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"client": [
|
||||
"base.MixinClientConnection",
|
||||
"base.MixinClientConnection_1",
|
||||
"base.MixinClientLoginNetworkHandler",
|
||||
"base.MixinMain",
|
||||
"base.MixinMinecraftClient",
|
||||
"base.MixinMultiplayerScreen",
|
||||
"base.MixinMultiplayerServerListPinger",
|
||||
"bridge.MixinConnectScreen",
|
||||
"bridge.MixinDebugHud",
|
||||
"bridge.MixinDownloadingTerrainScreen",
|
||||
@ -145,6 +145,8 @@
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"mixins": [
|
||||
"fixes.block.MixinAbstractBlock"
|
||||
"base.MixinClientConnection_1",
|
||||
"fixes.block.MixinAbstractBlock",
|
||||
"fixes.vialegacy.MixinBedrockProtocol"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user