mirror of
https://github.com/ViaVersion/ViaFabric.git
synced 2024-12-21 16:17:37 +01:00
update 1.17 snapshot, cleanup VersionProvider
This commit is contained in:
parent
4bbd683382
commit
105e64b11a
14
.github/workflows/build.yml
vendored
14
.github/workflows/build.yml
vendored
@ -10,14 +10,11 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout repository
|
||||
uses: actions/checkout@v2
|
||||
- name: setup jdk 11
|
||||
uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Cache
|
||||
uses: actions/cache@v2
|
||||
java-version: 16
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.gradle/
|
||||
key: ${{ runner.os }}-via-cache
|
||||
@ -25,8 +22,7 @@ jobs:
|
||||
env:
|
||||
CURSEFORGE_API_KEY: ${{ secrets.CREEPER_CF }}
|
||||
run: ./gradlew
|
||||
- name: capture build artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Artifacts
|
||||
path: build/libs/
|
||||
|
11
build.gradle
11
build.gradle
@ -1,8 +1,10 @@
|
||||
import org.apache.tools.ant.filters.ReplaceTokens
|
||||
|
||||
// Stolen https://github.com/FabricMC/fabric/blob/1.17/build.gradle
|
||||
plugins {
|
||||
id "java"
|
||||
id "maven-publish"
|
||||
id "fabric-loom" version "0.7-SNAPSHOT" apply false
|
||||
id "fabric-loom" version "0.8-SNAPSHOT" apply false
|
||||
id "org.ajoberstar.grgit" version "3.1.1"
|
||||
id "com.matthewprenger.cursegradle" version "1.4.0"
|
||||
}
|
||||
@ -11,8 +13,8 @@ def ENV = System.getenv()
|
||||
def vvVer = "4.0.0-21w19a"
|
||||
|
||||
description = "Client-side and server-side ViaVersion implementation for Fabric"
|
||||
version = "0.4.0" + "+" + ENV.GITHUB_RUN_NUMBER + "-" + getBranch()
|
||||
logger.lifecycle("Building ViaFabric: " + version)
|
||||
version = "0.4.0+" + ENV.GITHUB_RUN_NUMBER + "-" + getBranch()
|
||||
logger.lifecycle("Building ViaFabric: $version")
|
||||
|
||||
def getBranch() {
|
||||
def ENV = System.getenv()
|
||||
@ -85,7 +87,7 @@ allprojects {
|
||||
|
||||
processResources {
|
||||
filesMatching("fabric.mod.json") {
|
||||
filter(org.apache.tools.ant.filters.ReplaceTokens, tokens: [
|
||||
filter(ReplaceTokens, tokens: [
|
||||
version : rootProject.version,
|
||||
description: rootProject.description
|
||||
])
|
||||
@ -196,7 +198,6 @@ dependencies {
|
||||
include("org.yaml:snakeyaml:1.28")
|
||||
|
||||
subprojects.each {
|
||||
//implementation project(path: ":${it.name}", configuration: "dev")
|
||||
include project("${it.name}:")
|
||||
}
|
||||
}
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
@ -0,0 +1,174 @@
|
||||
package com.viaversion.fabric.common.provider;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import com.viaversion.fabric.common.config.VFConfig;
|
||||
import com.viaversion.fabric.common.util.ProtocolUtils;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.protocols.base.BaseProtocol1_16;
|
||||
import com.viaversion.viaversion.protocols.base.BaseProtocol1_7;
|
||||
import com.viaversion.viaversion.protocols.base.BaseVersionProvider;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public abstract class VFVersionProvider extends BaseVersionProvider {
|
||||
private int[] multiconnectSupportedVersions = null;
|
||||
|
||||
{
|
||||
try {
|
||||
if (FabricLoader.getInstance().isModLoaded("multiconnect")) {
|
||||
Class<?> mcApiClass = Class.forName("net.earthcomputer.multiconnect.api.MultiConnectAPI");
|
||||
Class<?> iProtocolClass = Class.forName("net.earthcomputer.multiconnect.api.IProtocol");
|
||||
Object mcApiInstance = mcApiClass.getMethod("instance").invoke(null);
|
||||
List<?> protocols = (List<?>) mcApiClass.getMethod("getSupportedProtocols").invoke(mcApiInstance);
|
||||
Method getValue = iProtocolClass.getMethod("getValue");
|
||||
Method isMulticonnectBeta;
|
||||
try {
|
||||
isMulticonnectBeta = iProtocolClass.getMethod("isMulticonnectBeta");
|
||||
} catch (NoSuchMethodException e) {
|
||||
isMulticonnectBeta = null;
|
||||
}
|
||||
Set<Integer> vers = new TreeSet<>();
|
||||
for (Object protocol : protocols) {
|
||||
// Do not use versions with beta multiconnect support, which may have stability issues
|
||||
if (isMulticonnectBeta == null || !(Boolean) isMulticonnectBeta.invoke(protocol)) {
|
||||
vers.add((Integer) getValue.invoke(protocol));
|
||||
}
|
||||
}
|
||||
multiconnectSupportedVersions = vers.stream().mapToInt(Integer::intValue).toArray();
|
||||
getLogger().info("ViaFabric will integrate with multiconnect");
|
||||
}
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException
|
||||
| ClassCastException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClosestServerProtocol(UserConnection connection) throws Exception {
|
||||
if (connection.isClientSide()) {
|
||||
ProtocolInfo info = Objects.requireNonNull(connection.getProtocolInfo());
|
||||
|
||||
if (!getConfig().isClientSideEnabled()) {
|
||||
return info.getProtocolVersion();
|
||||
}
|
||||
|
||||
int serverVer = getConfig().getClientSideVersion();
|
||||
SocketAddress addr = connection.getChannel().remoteAddress();
|
||||
|
||||
if (addr instanceof InetSocketAddress) {
|
||||
int addrVersion = new VFAddressParser().parse(((InetSocketAddress) addr).getHostName()).protocol;
|
||||
if (addrVersion != 0) serverVer = addrVersion;
|
||||
|
||||
try {
|
||||
if (serverVer == -2) {
|
||||
// Hope protocol was autodetected
|
||||
ProtocolVersion autoVer =
|
||||
detectVersion((InetSocketAddress) addr).getNow(null);
|
||||
if (autoVer != null) {
|
||||
serverVer = autoVer.getVersion();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
getLogger().warning("Couldn't auto detect: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean blocked = checkAddressBlocked(addr);
|
||||
boolean supported = ProtocolUtils.isSupported(serverVer, info.getProtocolVersion());
|
||||
|
||||
handleMulticonnectPing(connection, info, blocked, serverVer);
|
||||
|
||||
if (blocked || !supported) serverVer = info.getProtocolVersion();
|
||||
|
||||
return serverVer;
|
||||
}
|
||||
return super.getClosestServerProtocol(connection);
|
||||
}
|
||||
|
||||
private boolean checkAddressBlocked(SocketAddress addr) {
|
||||
return addr instanceof InetSocketAddress && (isDisabled(((InetSocketAddress) addr).getHostString())
|
||||
|| ((((InetSocketAddress) addr).getAddress() != null) &&
|
||||
(isDisabled(((InetSocketAddress) addr).getAddress().getHostAddress())
|
||||
|| isDisabled(((InetSocketAddress) addr).getAddress().getHostName()))));
|
||||
}
|
||||
|
||||
private void handleMulticonnectPing(UserConnection connection, ProtocolInfo info, boolean blocked, int serverVer) throws Exception {
|
||||
if (info.getState() == State.STATUS
|
||||
&& info.getProtocolVersion() == -1
|
||||
&& connection.getChannel().pipeline().get(ClientConnection.class).getPacketListener()
|
||||
.getClass().getName().startsWith("net.earthcomputer.multiconnect")
|
||||
&& (blocked || ProtocolUtils.isSupported(serverVer, getVersionForMulticonnect(serverVer)))) { // Intercept the connection
|
||||
int multiconnectSuggestion = blocked ? -1 : getVersionForMulticonnect(serverVer);
|
||||
getLogger().info("Sending " + ProtocolVersion.getProtocol(multiconnectSuggestion) + " for multiconnect version detector");
|
||||
PacketWrapper newAnswer = PacketWrapper.create(0x00, null, connection);
|
||||
newAnswer.write(Type.STRING, "{\"version\":{\"name\":\"viafabric integration\",\"protocol\":" + multiconnectSuggestion + "}}");
|
||||
newAnswer.send(info.getPipeline().contains(BaseProtocol1_16.class) ? BaseProtocol1_16.class : BaseProtocol1_7.class, true, true);
|
||||
throw CancelException.generate();
|
||||
}
|
||||
}
|
||||
|
||||
private int getVersionForMulticonnect(int clientSideVersion) {
|
||||
// https://github.com/ViaVersion/ViaVersion/blob/master/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityVersionProvider.java
|
||||
int[] compatibleProtocols = multiconnectSupportedVersions;
|
||||
|
||||
if (Arrays.binarySearch(compatibleProtocols, clientSideVersion) >= 0) {
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
if (clientSideVersion < compatibleProtocols[0]) {
|
||||
return compatibleProtocols[0];
|
||||
}
|
||||
|
||||
// TODO: This needs a better fix, i.e checking ProtocolRegistry to see if it would work.
|
||||
for (int i = compatibleProtocols.length - 1; i >= 0; i--) {
|
||||
int protocol = compatibleProtocols[i];
|
||||
if (clientSideVersion > protocol && ProtocolVersion.isRegistered(protocol)) {
|
||||
return protocol;
|
||||
}
|
||||
}
|
||||
|
||||
getLogger().severe("multiconnect integration: Panic, no protocol id found for " + clientSideVersion);
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
private boolean isDisabled(String addr) {
|
||||
String[] parts = addr.split("\\.");
|
||||
boolean isNumericIp = parts.length == 4 && Arrays.stream(parts).map(Ints::tryParse).allMatch(Objects::nonNull);
|
||||
return IntStream.range(0, parts.length).anyMatch(i -> {
|
||||
String query;
|
||||
if (isNumericIp) {
|
||||
query = String.join(".", Arrays.stream(parts, 0, i + 1)
|
||||
.toArray(String[]::new)) + ((i != 3) ? ".*" : "");
|
||||
} else {
|
||||
query = ((i != 0) ? "*." : "") + String.join(".", Arrays.stream(parts, i, parts.length)
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
if (getConfig().isForcedDisable(query)) {
|
||||
getLogger().info(addr + " is force-disabled. (Matches " + query + ")");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract Logger getLogger();
|
||||
|
||||
protected abstract VFConfig getConfig();
|
||||
|
||||
protected abstract CompletableFuture<ProtocolVersion> detectVersion(InetSocketAddress address);
|
||||
}
|
@ -1,166 +1,28 @@
|
||||
package com.viaversion.fabric.mc114.providers;
|
||||
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import com.viaversion.fabric.common.config.VFConfig;
|
||||
import com.viaversion.fabric.common.provider.VFVersionProvider;
|
||||
import com.viaversion.fabric.mc114.ViaFabric;
|
||||
import com.viaversion.fabric.mc114.service.ProtocolAutoDetector;
|
||||
import com.viaversion.fabric.common.util.ProtocolUtils;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.protocols.base.*;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class VRVersionProvider extends BaseVersionProvider {
|
||||
private int[] multiconnectSupportedVersions = null;
|
||||
|
||||
{
|
||||
try {
|
||||
if (FabricLoader.getInstance().isModLoaded("multiconnect")) {
|
||||
Class<?> mcApiClass = Class.forName("net.earthcomputer.multiconnect.api.MultiConnectAPI");
|
||||
Class<?> iProtocolClass = Class.forName("net.earthcomputer.multiconnect.api.IProtocol");
|
||||
Object mcApiInstance = mcApiClass.getMethod("instance").invoke(null);
|
||||
List<?> protocols = (List<?>) mcApiClass.getMethod("getSupportedProtocols").invoke(mcApiInstance);
|
||||
Method getValue = iProtocolClass.getMethod("getValue");
|
||||
Method isMulticonnectBeta;
|
||||
try {
|
||||
isMulticonnectBeta = iProtocolClass.getMethod("isMulticonnectBeta");
|
||||
} catch (NoSuchMethodException e) {
|
||||
isMulticonnectBeta = null;
|
||||
}
|
||||
Set<Integer> vers = new TreeSet<>();
|
||||
for (Object protocol : protocols) {
|
||||
// Do not use versions with beta multiconnect support, which may have stability issues
|
||||
if (isMulticonnectBeta == null || !(Boolean) isMulticonnectBeta.invoke(protocol)) {
|
||||
vers.add((Integer) getValue.invoke(protocol));
|
||||
}
|
||||
}
|
||||
multiconnectSupportedVersions = vers.stream().mapToInt(Integer::intValue).toArray();
|
||||
ViaFabric.JLOGGER.info("ViaFabric will integrate with multiconnect");
|
||||
}
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException
|
||||
| ClassCastException ignored) {
|
||||
}
|
||||
public class VRVersionProvider extends VFVersionProvider {
|
||||
@Override
|
||||
protected Logger getLogger() {
|
||||
return ViaFabric.JLOGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClosestServerProtocol(UserConnection connection) throws Exception {
|
||||
if (connection.isClientSide()) {
|
||||
ProtocolInfo info = Objects.requireNonNull(connection.getProtocolInfo());
|
||||
|
||||
if (!ViaFabric.config.isClientSideEnabled()) {
|
||||
return info.getProtocolVersion();
|
||||
}
|
||||
|
||||
int serverVer = ViaFabric.config.getClientSideVersion();
|
||||
SocketAddress addr = connection.getChannel().remoteAddress();
|
||||
|
||||
if (addr instanceof InetSocketAddress) {
|
||||
int addrVersion = new VFAddressParser().parse(((InetSocketAddress) addr).getHostName()).protocol;
|
||||
if (addrVersion != 0) serverVer = addrVersion;
|
||||
|
||||
try {
|
||||
if (serverVer == -2) {
|
||||
// Hope protocol was autodetected
|
||||
ProtocolVersion autoVer =
|
||||
ProtocolAutoDetector.detectVersion((InetSocketAddress) addr).getNow(null);
|
||||
if (autoVer != null) {
|
||||
serverVer = autoVer.getVersion();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ViaFabric.JLOGGER.warning("Couldn't auto detect: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean blocked = checkAddressBlocked(addr);
|
||||
boolean supported = ProtocolUtils.isSupported(serverVer, info.getProtocolVersion());
|
||||
|
||||
handleMulticonnectPing(connection, info, blocked, serverVer);
|
||||
|
||||
if (blocked || !supported) serverVer = info.getProtocolVersion();
|
||||
|
||||
return serverVer;
|
||||
}
|
||||
return super.getClosestServerProtocol(connection);
|
||||
protected VFConfig getConfig() {
|
||||
return ViaFabric.config;
|
||||
}
|
||||
|
||||
private boolean checkAddressBlocked(SocketAddress addr) {
|
||||
return addr instanceof InetSocketAddress && (isDisabled(((InetSocketAddress) addr).getHostString())
|
||||
|| ((((InetSocketAddress) addr).getAddress() != null) &&
|
||||
(isDisabled(((InetSocketAddress) addr).getAddress().getHostAddress())
|
||||
|| isDisabled(((InetSocketAddress) addr).getAddress().getHostName()))));
|
||||
}
|
||||
|
||||
private void handleMulticonnectPing(UserConnection connection, ProtocolInfo info, boolean blocked, int serverVer) throws Exception {
|
||||
if (info.getState() == State.STATUS
|
||||
&& info.getProtocolVersion() == -1
|
||||
&& connection.getChannel().pipeline().get(ClientConnection.class).getPacketListener()
|
||||
.getClass().getName().startsWith("net.earthcomputer.multiconnect")
|
||||
&& (blocked || ProtocolUtils.isSupported(serverVer, getVersionForMulticonnect(serverVer)))) { // Intercept the connection
|
||||
int multiconnectSuggestion = blocked ? -1 : getVersionForMulticonnect(serverVer);
|
||||
ViaFabric.JLOGGER.info("Sending " + ProtocolVersion.getProtocol(multiconnectSuggestion) + " for multiconnect version detector");
|
||||
PacketWrapper newAnswer = PacketWrapper.create(0x00, null, connection);
|
||||
newAnswer.write(Type.STRING, "{\"version\":{\"name\":\"viafabric integration\",\"protocol\":" + multiconnectSuggestion + "}}");
|
||||
newAnswer.send(info.getPipeline().contains(BaseProtocol1_16.class) ? BaseProtocol1_16.class : BaseProtocol1_7.class, true, true);
|
||||
throw CancelException.generate();
|
||||
}
|
||||
}
|
||||
|
||||
private int getVersionForMulticonnect(int clientSideVersion) {
|
||||
// https://github.com/ViaVersion/ViaVersion/blob/master/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityVersionProvider.java
|
||||
int[] compatibleProtocols = multiconnectSupportedVersions;
|
||||
|
||||
if (Arrays.binarySearch(compatibleProtocols, clientSideVersion) >= 0) {
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
if (clientSideVersion < compatibleProtocols[0]) {
|
||||
return compatibleProtocols[0];
|
||||
}
|
||||
|
||||
// TODO: This needs a better fix, i.e checking ProtocolRegistry to see if it would work.
|
||||
for (int i = compatibleProtocols.length - 1; i >= 0; i--) {
|
||||
int protocol = compatibleProtocols[i];
|
||||
if (clientSideVersion > protocol && ProtocolVersion.isRegistered(protocol)) {
|
||||
return protocol;
|
||||
}
|
||||
}
|
||||
|
||||
ViaFabric.JLOGGER.severe("multiconnect integration: Panic, no protocol id found for " + clientSideVersion);
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
private boolean isDisabled(String addr) {
|
||||
String[] parts = addr.split("\\.");
|
||||
boolean isNumericIp = parts.length == 4 && Arrays.stream(parts).map(Ints::tryParse).allMatch(Objects::nonNull);
|
||||
return IntStream.range(0, parts.length).anyMatch(i -> {
|
||||
String query;
|
||||
if (isNumericIp) {
|
||||
query = String.join(".", Arrays.stream(parts, 0, i + 1)
|
||||
.toArray(String[]::new)) + ((i != 3) ? ".*" : "");
|
||||
} else {
|
||||
query = ((i != 0) ? "*." : "") + String.join(".", Arrays.stream(parts, i, parts.length)
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
if (ViaFabric.config.isForcedDisable(query)) {
|
||||
ViaFabric.JLOGGER.info(addr + " is force-disabled. (Matches " + query + ")");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@Override
|
||||
protected CompletableFuture<ProtocolVersion> detectVersion(InetSocketAddress address) {
|
||||
return ProtocolAutoDetector.detectVersion(address);
|
||||
}
|
||||
}
|
||||
|
@ -1,168 +1,29 @@
|
||||
package com.viaversion.fabric.mc115.providers;
|
||||
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import com.viaversion.fabric.common.util.ProtocolUtils;
|
||||
import com.viaversion.fabric.common.config.VFConfig;
|
||||
import com.viaversion.fabric.common.provider.VFVersionProvider;
|
||||
import com.viaversion.fabric.mc115.ViaFabric;
|
||||
import com.viaversion.fabric.mc115.service.ProtocolAutoDetector;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.protocols.base.BaseProtocol1_16;
|
||||
import com.viaversion.viaversion.protocols.base.BaseProtocol1_7;
|
||||
import com.viaversion.viaversion.protocols.base.BaseVersionProvider;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class VRVersionProvider extends BaseVersionProvider {
|
||||
private int[] multiconnectSupportedVersions = null;
|
||||
public class VRVersionProvider extends VFVersionProvider {
|
||||
|
||||
{
|
||||
try {
|
||||
if (FabricLoader.getInstance().isModLoaded("multiconnect")) {
|
||||
Class<?> mcApiClass = Class.forName("net.earthcomputer.multiconnect.api.MultiConnectAPI");
|
||||
Class<?> iProtocolClass = Class.forName("net.earthcomputer.multiconnect.api.IProtocol");
|
||||
Object mcApiInstance = mcApiClass.getMethod("instance").invoke(null);
|
||||
List<?> protocols = (List<?>) mcApiClass.getMethod("getSupportedProtocols").invoke(mcApiInstance);
|
||||
Method getValue = iProtocolClass.getMethod("getValue");
|
||||
Method isMulticonnectBeta;
|
||||
try {
|
||||
isMulticonnectBeta = iProtocolClass.getMethod("isMulticonnectBeta");
|
||||
} catch (NoSuchMethodException e) {
|
||||
isMulticonnectBeta = null;
|
||||
}
|
||||
Set<Integer> vers = new TreeSet<>();
|
||||
for (Object protocol : protocols) {
|
||||
// Do not use versions with beta multiconnect support, which may have stability issues
|
||||
if (isMulticonnectBeta == null || !(Boolean) isMulticonnectBeta.invoke(protocol)) {
|
||||
vers.add((Integer) getValue.invoke(protocol));
|
||||
}
|
||||
}
|
||||
multiconnectSupportedVersions = vers.stream().mapToInt(Integer::intValue).toArray();
|
||||
ViaFabric.JLOGGER.info("ViaFabric will integrate with multiconnect");
|
||||
}
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException
|
||||
| ClassCastException ignored) {
|
||||
}
|
||||
@Override
|
||||
protected Logger getLogger() {
|
||||
return ViaFabric.JLOGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClosestServerProtocol(UserConnection connection) throws Exception {
|
||||
if (connection.isClientSide()) {
|
||||
ProtocolInfo info = Objects.requireNonNull(connection.getProtocolInfo());
|
||||
|
||||
if (!ViaFabric.config.isClientSideEnabled()) {
|
||||
return info.getProtocolVersion();
|
||||
}
|
||||
|
||||
int serverVer = ViaFabric.config.getClientSideVersion();
|
||||
SocketAddress addr = connection.getChannel().remoteAddress();
|
||||
|
||||
if (addr instanceof InetSocketAddress) {
|
||||
int addrVersion = new VFAddressParser().parse(((InetSocketAddress) addr).getHostName()).protocol;
|
||||
if (addrVersion != 0) serverVer = addrVersion;
|
||||
|
||||
try {
|
||||
if (serverVer == -2) {
|
||||
// Hope protocol was autodetected
|
||||
ProtocolVersion autoVer =
|
||||
ProtocolAutoDetector.detectVersion((InetSocketAddress) addr).getNow(null);
|
||||
if (autoVer != null) {
|
||||
serverVer = autoVer.getVersion();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ViaFabric.JLOGGER.warning("Couldn't auto detect: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean blocked = checkAddressBlocked(addr);
|
||||
boolean supported = ProtocolUtils.isSupported(serverVer, info.getProtocolVersion());
|
||||
|
||||
handleMulticonnectPing(connection, info, blocked, serverVer);
|
||||
|
||||
if (blocked || !supported) serverVer = info.getProtocolVersion();
|
||||
|
||||
return serverVer;
|
||||
}
|
||||
return super.getClosestServerProtocol(connection);
|
||||
protected VFConfig getConfig() {
|
||||
return ViaFabric.config;
|
||||
}
|
||||
|
||||
private boolean checkAddressBlocked(SocketAddress addr) {
|
||||
return addr instanceof InetSocketAddress && (isDisabled(((InetSocketAddress) addr).getHostString())
|
||||
|| ((((InetSocketAddress) addr).getAddress() != null) &&
|
||||
(isDisabled(((InetSocketAddress) addr).getAddress().getHostAddress())
|
||||
|| isDisabled(((InetSocketAddress) addr).getAddress().getHostName()))));
|
||||
@Override
|
||||
protected CompletableFuture<ProtocolVersion> detectVersion(InetSocketAddress address) {
|
||||
return ProtocolAutoDetector.detectVersion(address);
|
||||
}
|
||||
|
||||
private void handleMulticonnectPing(UserConnection connection, ProtocolInfo info, boolean blocked, int serverVer) throws Exception {
|
||||
if (info.getState() == State.STATUS
|
||||
&& info.getProtocolVersion() == -1
|
||||
&& connection.getChannel().pipeline().get(ClientConnection.class).getPacketListener()
|
||||
.getClass().getName().startsWith("net.earthcomputer.multiconnect")
|
||||
&& (blocked || ProtocolUtils.isSupported(serverVer, getVersionForMulticonnect(serverVer)))) { // Intercept the connection
|
||||
int multiconnectSuggestion = blocked ? -1 : getVersionForMulticonnect(serverVer);
|
||||
ViaFabric.JLOGGER.info("Sending " + ProtocolVersion.getProtocol(multiconnectSuggestion) + " for multiconnect version detector");
|
||||
PacketWrapper newAnswer = PacketWrapper.create(0x00, null, connection);
|
||||
newAnswer.write(Type.STRING, "{\"version\":{\"name\":\"viafabric integration\",\"protocol\":" + multiconnectSuggestion + "}}");
|
||||
newAnswer.send(info.getPipeline().contains(BaseProtocol1_16.class) ? BaseProtocol1_16.class : BaseProtocol1_7.class, true, true);
|
||||
throw CancelException.generate();
|
||||
}
|
||||
}
|
||||
|
||||
private int getVersionForMulticonnect(int clientSideVersion) {
|
||||
// https://github.com/ViaVersion/ViaVersion/blob/master/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityVersionProvider.java
|
||||
int[] compatibleProtocols = multiconnectSupportedVersions;
|
||||
|
||||
if (Arrays.binarySearch(compatibleProtocols, clientSideVersion) >= 0) {
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
if (clientSideVersion < compatibleProtocols[0]) {
|
||||
return compatibleProtocols[0];
|
||||
}
|
||||
|
||||
// TODO: This needs a better fix, i.e checking ProtocolRegistry to see if it would work.
|
||||
for (int i = compatibleProtocols.length - 1; i >= 0; i--) {
|
||||
int protocol = compatibleProtocols[i];
|
||||
if (clientSideVersion > protocol && ProtocolVersion.isRegistered(protocol)) {
|
||||
return protocol;
|
||||
}
|
||||
}
|
||||
|
||||
ViaFabric.JLOGGER.severe("multiconnect integration: Panic, no protocol id found for " + clientSideVersion);
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
private boolean isDisabled(String addr) {
|
||||
String[] parts = addr.split("\\.");
|
||||
boolean isNumericIp = parts.length == 4 && Arrays.stream(parts).map(Ints::tryParse).allMatch(Objects::nonNull);
|
||||
return IntStream.range(0, parts.length).anyMatch(i -> {
|
||||
String query;
|
||||
if (isNumericIp) {
|
||||
query = String.join(".", Arrays.stream(parts, 0, i + 1)
|
||||
.toArray(String[]::new)) + ((i != 3) ? ".*" : "");
|
||||
} else {
|
||||
query = ((i != 0) ? "*." : "") + String.join(".", Arrays.stream(parts, i, parts.length)
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
if (ViaFabric.config.isForcedDisable(query)) {
|
||||
ViaFabric.JLOGGER.info(addr + " is force-disabled. (Matches " + query + ")");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,166 +1,29 @@
|
||||
package com.viaversion.fabric.mc116.providers;
|
||||
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import com.viaversion.fabric.common.config.VFConfig;
|
||||
import com.viaversion.fabric.common.provider.VFVersionProvider;
|
||||
import com.viaversion.fabric.mc116.ViaFabric;
|
||||
import com.viaversion.fabric.mc116.service.ProtocolAutoDetector;
|
||||
import com.viaversion.fabric.common.util.ProtocolUtils;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.protocols.base.*;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class VRVersionProvider extends BaseVersionProvider {
|
||||
private int[] multiconnectSupportedVersions = null;
|
||||
public class VRVersionProvider extends VFVersionProvider {
|
||||
|
||||
{
|
||||
try {
|
||||
if (FabricLoader.getInstance().isModLoaded("multiconnect")) {
|
||||
Class<?> mcApiClass = Class.forName("net.earthcomputer.multiconnect.api.MultiConnectAPI");
|
||||
Class<?> iProtocolClass = Class.forName("net.earthcomputer.multiconnect.api.IProtocol");
|
||||
Object mcApiInstance = mcApiClass.getMethod("instance").invoke(null);
|
||||
List<?> protocols = (List<?>) mcApiClass.getMethod("getSupportedProtocols").invoke(mcApiInstance);
|
||||
Method getValue = iProtocolClass.getMethod("getValue");
|
||||
Method isMulticonnectBeta;
|
||||
try {
|
||||
isMulticonnectBeta = iProtocolClass.getMethod("isMulticonnectBeta");
|
||||
} catch (NoSuchMethodException e) {
|
||||
isMulticonnectBeta = null;
|
||||
}
|
||||
Set<Integer> vers = new TreeSet<>();
|
||||
for (Object protocol : protocols) {
|
||||
// Do not use versions with beta multiconnect support, which may have stability issues
|
||||
if (isMulticonnectBeta == null || !(Boolean) isMulticonnectBeta.invoke(protocol)) {
|
||||
vers.add((Integer) getValue.invoke(protocol));
|
||||
}
|
||||
}
|
||||
multiconnectSupportedVersions = vers.stream().mapToInt(Integer::intValue).toArray();
|
||||
ViaFabric.JLOGGER.info("ViaFabric will integrate with multiconnect");
|
||||
}
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException
|
||||
| ClassCastException ignored) {
|
||||
}
|
||||
@Override
|
||||
protected Logger getLogger() {
|
||||
return ViaFabric.JLOGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClosestServerProtocol(UserConnection connection) throws Exception {
|
||||
if (connection.isClientSide()) {
|
||||
ProtocolInfo info = Objects.requireNonNull(connection.getProtocolInfo());
|
||||
|
||||
if (!ViaFabric.config.isClientSideEnabled()) {
|
||||
return info.getProtocolVersion();
|
||||
}
|
||||
|
||||
int serverVer = ViaFabric.config.getClientSideVersion();
|
||||
SocketAddress addr = connection.getChannel().remoteAddress();
|
||||
|
||||
if (addr instanceof InetSocketAddress) {
|
||||
int addrVersion = new VFAddressParser().parse(((InetSocketAddress) addr).getHostName()).protocol;
|
||||
if (addrVersion != 0) serverVer = addrVersion;
|
||||
|
||||
try {
|
||||
if (serverVer == -2) {
|
||||
// Hope protocol was autodetected
|
||||
ProtocolVersion autoVer =
|
||||
ProtocolAutoDetector.detectVersion((InetSocketAddress) addr).getNow(null);
|
||||
if (autoVer != null) {
|
||||
serverVer = autoVer.getVersion();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ViaFabric.JLOGGER.warning("Couldn't auto detect: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean blocked = checkAddressBlocked(addr);
|
||||
boolean supported = ProtocolUtils.isSupported(serverVer, info.getProtocolVersion());
|
||||
|
||||
handleMulticonnectPing(connection, info, blocked, serverVer);
|
||||
|
||||
if (blocked || !supported) serverVer = info.getProtocolVersion();
|
||||
|
||||
return serverVer;
|
||||
}
|
||||
return super.getClosestServerProtocol(connection);
|
||||
protected VFConfig getConfig() {
|
||||
return ViaFabric.config;
|
||||
}
|
||||
|
||||
private boolean checkAddressBlocked(SocketAddress addr) {
|
||||
return addr instanceof InetSocketAddress && (isDisabled(((InetSocketAddress) addr).getHostString())
|
||||
|| ((((InetSocketAddress) addr).getAddress() != null) &&
|
||||
(isDisabled(((InetSocketAddress) addr).getAddress().getHostAddress())
|
||||
|| isDisabled(((InetSocketAddress) addr).getAddress().getHostName()))));
|
||||
@Override
|
||||
protected CompletableFuture<ProtocolVersion> detectVersion(InetSocketAddress address) {
|
||||
return ProtocolAutoDetector.detectVersion(address);
|
||||
}
|
||||
|
||||
private void handleMulticonnectPing(UserConnection connection, ProtocolInfo info, boolean blocked, int serverVer) throws Exception {
|
||||
if (info.getState() == State.STATUS
|
||||
&& info.getProtocolVersion() == -1
|
||||
&& connection.getChannel().pipeline().get(ClientConnection.class).getPacketListener()
|
||||
.getClass().getName().startsWith("net.earthcomputer.multiconnect")
|
||||
&& (blocked || ProtocolUtils.isSupported(serverVer, getVersionForMulticonnect(serverVer)))) { // Intercept the connection
|
||||
int multiconnectSuggestion = blocked ? -1 : getVersionForMulticonnect(serverVer);
|
||||
ViaFabric.JLOGGER.info("Sending " + ProtocolVersion.getProtocol(multiconnectSuggestion) + " for multiconnect version detector");
|
||||
PacketWrapper newAnswer = PacketWrapper.create(0x00, null, connection);
|
||||
newAnswer.write(Type.STRING, "{\"version\":{\"name\":\"viafabric integration\",\"protocol\":" + multiconnectSuggestion + "}}");
|
||||
newAnswer.send(info.getPipeline().contains(BaseProtocol1_16.class) ? BaseProtocol1_16.class : BaseProtocol1_7.class, true, true);
|
||||
throw CancelException.generate();
|
||||
}
|
||||
}
|
||||
|
||||
private int getVersionForMulticonnect(int clientSideVersion) {
|
||||
// https://github.com/ViaVersion/ViaVersion/blob/master/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityVersionProvider.java
|
||||
int[] compatibleProtocols = multiconnectSupportedVersions;
|
||||
|
||||
if (Arrays.binarySearch(compatibleProtocols, clientSideVersion) >= 0) {
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
if (clientSideVersion < compatibleProtocols[0]) {
|
||||
return compatibleProtocols[0];
|
||||
}
|
||||
|
||||
// TODO: This needs a better fix, i.e checking ProtocolRegistry to see if it would work.
|
||||
for (int i = compatibleProtocols.length - 1; i >= 0; i--) {
|
||||
int protocol = compatibleProtocols[i];
|
||||
if (clientSideVersion > protocol && ProtocolVersion.isRegistered(protocol)) {
|
||||
return protocol;
|
||||
}
|
||||
}
|
||||
|
||||
ViaFabric.JLOGGER.severe("multiconnect integration: Panic, no protocol id found for " + clientSideVersion);
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
private boolean isDisabled(String addr) {
|
||||
String[] parts = addr.split("\\.");
|
||||
boolean isNumericIp = parts.length == 4 && Arrays.stream(parts).map(Ints::tryParse).allMatch(Objects::nonNull);
|
||||
return IntStream.range(0, parts.length).anyMatch(i -> {
|
||||
String query;
|
||||
if (isNumericIp) {
|
||||
query = String.join(".", Arrays.stream(parts, 0, i + 1)
|
||||
.toArray(String[]::new)) + ((i != 3) ? ".*" : "");
|
||||
} else {
|
||||
query = ((i != 0) ? "*." : "") + String.join(".", Arrays.stream(parts, i, parts.length)
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
if (ViaFabric.config.isForcedDisable(query)) {
|
||||
ViaFabric.JLOGGER.info(addr + " is force-disabled. (Matches " + query + ")");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
version = rootProject.version
|
||||
|
||||
dependencies {
|
||||
minecraft("com.mojang:minecraft:21w15a")
|
||||
mappings("net.fabricmc:yarn:21w15a+build.16:v2")
|
||||
minecraft("com.mojang:minecraft:21w19a")
|
||||
mappings("net.fabricmc:yarn:21w19a+build.9:v2")
|
||||
|
||||
modImplementation("net.fabricmc.fabric-api:fabric-api:0.33.0+1.17")
|
||||
modImplementation("net.fabricmc.fabric-api:fabric-api:0.34.4+1.17")
|
||||
modImplementation("com.terraformersmc:modmenu:1.16.9")
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
package com.viaversion.fabric.mc117.mixin.address.client;
|
||||
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import net.minecraft.client.network.Address;
|
||||
import net.minecraft.client.network.AllowedAddressResolver;
|
||||
import net.minecraft.client.network.RedirectResolver;
|
||||
import net.minecraft.client.network.ServerAddress;
|
||||
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.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(AllowedAddressResolver.class)
|
||||
public abstract class MixinAllowedAddressResolver {
|
||||
@Shadow
|
||||
@Final
|
||||
private RedirectResolver redirectResolver;
|
||||
|
||||
@Shadow
|
||||
protected abstract Optional<Address> getAllowedAddress(ServerAddress address);
|
||||
|
||||
@Inject(method = "resolve", at = @At(value = "HEAD"), cancellable = true)
|
||||
private void resolveVF(ServerAddress address, CallbackInfoReturnable<Optional<Address>> cir) throws UnknownHostException {
|
||||
VFAddressParser viaAddr = new VFAddressParser().parse(address.getAddress());
|
||||
if (viaAddr.viaSuffix == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerAddress realAddress = new ServerAddress(viaAddr.realAddress, address.getPort());
|
||||
|
||||
cir.setReturnValue(getAllowedAddress(realAddress)
|
||||
.map(it -> redirectResolver.lookupRedirect(realAddress)
|
||||
.flatMap(this::getAllowedAddress)
|
||||
.orElse(it))
|
||||
.map(it -> {
|
||||
try {
|
||||
return Address.create(new InetSocketAddress(InetAddress.getByAddress(
|
||||
it.getHostName() + "." + viaAddr.viaSuffix,
|
||||
it.getInetSocketAddress().getAddress().getAddress()), it.getPort()
|
||||
));
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
package com.viaversion.fabric.mc117.mixin.address.client;
|
||||
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
@Mixin(targets = "net/minecraft/client/gui/screen/ConnectScreen$1", priority = 2000)
|
||||
public class MixinConnectScreenThread {
|
||||
@Redirect(method = "run()V", at = @At(value = "INVOKE",
|
||||
target = "Ljava/net/InetAddress;getByName(Ljava/lang/String;)Ljava/net/InetAddress;"))
|
||||
private InetAddress resolveViaFabricAddr(String address) throws UnknownHostException {
|
||||
VFAddressParser viaAddr = new VFAddressParser().parse(address);
|
||||
if (viaAddr.viaSuffix == null) {
|
||||
return InetAddress.getByName(address);
|
||||
}
|
||||
|
||||
InetAddress resolved = InetAddress.getByName(viaAddr.realAddress);
|
||||
return InetAddress.getByAddress(resolved.getHostName() + "." + viaAddr.viaSuffix, resolved.getAddress());
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
package com.viaversion.fabric.mc117.mixin.address.client;
|
||||
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import net.minecraft.client.network.ServerAddress;
|
||||
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.Redirect;
|
||||
|
||||
@Mixin(ServerAddress.class)
|
||||
public abstract class MixinServerAddress {
|
||||
@Shadow
|
||||
private static HostAndPort resolveServer(HostAndPort address) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@Redirect(method = "parse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ServerAddress;resolveServer(Lcom/google/common/net/HostAndPort;)Lcom/google/common/net/HostAndPort;"))
|
||||
private static HostAndPort modifySrvAddr(HostAndPort address) {
|
||||
VFAddressParser viaAddr = new VFAddressParser().parse(address.getHost());
|
||||
if (viaAddr.viaSuffix == null) {
|
||||
return resolveServer(address);
|
||||
}
|
||||
|
||||
HostAndPort resolved = resolveServer(HostAndPort.fromParts(viaAddr.realAddress, address.getPort()));
|
||||
return HostAndPort.fromParts(
|
||||
resolved.getHost().replaceAll("\\.$", "") + "." + viaAddr.viaSuffix, resolved.getPort());
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package com.viaversion.fabric.mc117.mixin.address.client;
|
||||
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import net.minecraft.client.network.MultiplayerServerListPinger;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
@Mixin(MultiplayerServerListPinger.class)
|
||||
public class MixinServerPinger {
|
||||
@Redirect(method = "add", at = @At(value = "INVOKE",
|
||||
target = "Ljava/net/InetAddress;getByName(Ljava/lang/String;)Ljava/net/InetAddress;"))
|
||||
private InetAddress resolveViaFabricAddr(String address) throws UnknownHostException {
|
||||
VFAddressParser viaAddr = new VFAddressParser().parse(address);
|
||||
if (viaAddr.viaSuffix == null) {
|
||||
return InetAddress.getByName(address);
|
||||
}
|
||||
|
||||
InetAddress resolved = InetAddress.getByName(viaAddr.realAddress);
|
||||
return InetAddress.getByAddress(resolved.getHostName() + "." + viaAddr.viaSuffix, resolved.getAddress());
|
||||
}
|
||||
}
|
@ -1,166 +1,28 @@
|
||||
package com.viaversion.fabric.mc117.providers;
|
||||
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import com.viaversion.fabric.common.config.VFConfig;
|
||||
import com.viaversion.fabric.common.provider.VFVersionProvider;
|
||||
import com.viaversion.fabric.mc117.ViaFabric;
|
||||
import com.viaversion.fabric.mc117.service.ProtocolAutoDetector;
|
||||
import com.viaversion.fabric.common.util.ProtocolUtils;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.protocols.base.*;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class VRVersionProvider extends BaseVersionProvider {
|
||||
private int[] multiconnectSupportedVersions = null;
|
||||
|
||||
{
|
||||
try {
|
||||
if (FabricLoader.getInstance().isModLoaded("multiconnect")) {
|
||||
Class<?> mcApiClass = Class.forName("net.earthcomputer.multiconnect.api.MultiConnectAPI");
|
||||
Class<?> iProtocolClass = Class.forName("net.earthcomputer.multiconnect.api.IProtocol");
|
||||
Object mcApiInstance = mcApiClass.getMethod("instance").invoke(null);
|
||||
List<?> protocols = (List<?>) mcApiClass.getMethod("getSupportedProtocols").invoke(mcApiInstance);
|
||||
Method getValue = iProtocolClass.getMethod("getValue");
|
||||
Method isMulticonnectBeta;
|
||||
try {
|
||||
isMulticonnectBeta = iProtocolClass.getMethod("isMulticonnectBeta");
|
||||
} catch (NoSuchMethodException e) {
|
||||
isMulticonnectBeta = null;
|
||||
}
|
||||
Set<Integer> vers = new TreeSet<>();
|
||||
for (Object protocol : protocols) {
|
||||
// Do not use versions with beta multiconnect support, which may have stability issues
|
||||
if (isMulticonnectBeta == null || !(Boolean) isMulticonnectBeta.invoke(protocol)) {
|
||||
vers.add((Integer) getValue.invoke(protocol));
|
||||
}
|
||||
}
|
||||
multiconnectSupportedVersions = vers.stream().mapToInt(Integer::intValue).toArray();
|
||||
ViaFabric.JLOGGER.info("ViaFabric will integrate with multiconnect");
|
||||
}
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException
|
||||
| ClassCastException ignored) {
|
||||
}
|
||||
public class VRVersionProvider extends VFVersionProvider {
|
||||
@Override
|
||||
protected Logger getLogger() {
|
||||
return ViaFabric.JLOGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClosestServerProtocol(UserConnection connection) throws Exception {
|
||||
if (connection.isClientSide()) {
|
||||
ProtocolInfo info = Objects.requireNonNull(connection.getProtocolInfo());
|
||||
|
||||
if (!ViaFabric.config.isClientSideEnabled()) {
|
||||
return info.getProtocolVersion();
|
||||
}
|
||||
|
||||
int serverVer = ViaFabric.config.getClientSideVersion();
|
||||
SocketAddress addr = connection.getChannel().remoteAddress();
|
||||
|
||||
if (addr instanceof InetSocketAddress) {
|
||||
int addrVersion = new VFAddressParser().parse(((InetSocketAddress) addr).getHostName()).protocol;
|
||||
if (addrVersion != 0) serverVer = addrVersion;
|
||||
|
||||
try {
|
||||
if (serverVer == -2) {
|
||||
// Hope protocol was autodetected
|
||||
ProtocolVersion autoVer =
|
||||
ProtocolAutoDetector.detectVersion((InetSocketAddress) addr).getNow(null);
|
||||
if (autoVer != null) {
|
||||
serverVer = autoVer.getVersion();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ViaFabric.JLOGGER.warning("Couldn't auto detect: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean blocked = checkAddressBlocked(addr);
|
||||
boolean supported = ProtocolUtils.isSupported(serverVer, info.getProtocolVersion());
|
||||
|
||||
handleMulticonnectPing(connection, info, blocked, serverVer);
|
||||
|
||||
if (blocked || !supported) serverVer = info.getProtocolVersion();
|
||||
|
||||
return serverVer;
|
||||
}
|
||||
return super.getClosestServerProtocol(connection);
|
||||
protected VFConfig getConfig() {
|
||||
return ViaFabric.config;
|
||||
}
|
||||
|
||||
private boolean checkAddressBlocked(SocketAddress addr) {
|
||||
return addr instanceof InetSocketAddress && (isDisabled(((InetSocketAddress) addr).getHostString())
|
||||
|| ((((InetSocketAddress) addr).getAddress() != null) &&
|
||||
(isDisabled(((InetSocketAddress) addr).getAddress().getHostAddress())
|
||||
|| isDisabled(((InetSocketAddress) addr).getAddress().getHostName()))));
|
||||
}
|
||||
|
||||
private void handleMulticonnectPing(UserConnection connection, ProtocolInfo info, boolean blocked, int serverVer) throws Exception {
|
||||
if (info.getState() == State.STATUS
|
||||
&& info.getProtocolVersion() == -1
|
||||
&& connection.getChannel().pipeline().get(ClientConnection.class).getPacketListener()
|
||||
.getClass().getName().startsWith("net.earthcomputer.multiconnect")
|
||||
&& (blocked || ProtocolUtils.isSupported(serverVer, getVersionForMulticonnect(serverVer)))) { // Intercept the connection
|
||||
int multiconnectSuggestion = blocked ? -1 : getVersionForMulticonnect(serverVer);
|
||||
ViaFabric.JLOGGER.info("Sending " + ProtocolVersion.getProtocol(multiconnectSuggestion) + " for multiconnect version detector");
|
||||
PacketWrapper newAnswer = PacketWrapper.create(0x00, null, connection);
|
||||
newAnswer.write(Type.STRING, "{\"version\":{\"name\":\"viafabric integration\",\"protocol\":" + multiconnectSuggestion + "}}");
|
||||
newAnswer.send(info.getPipeline().contains(BaseProtocol1_16.class) ? BaseProtocol1_16.class : BaseProtocol1_7.class, true, true);
|
||||
throw CancelException.generate();
|
||||
}
|
||||
}
|
||||
|
||||
private int getVersionForMulticonnect(int clientSideVersion) {
|
||||
// https://github.com/ViaVersion/ViaVersion/blob/master/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityVersionProvider.java
|
||||
int[] compatibleProtocols = multiconnectSupportedVersions;
|
||||
|
||||
if (Arrays.binarySearch(compatibleProtocols, clientSideVersion) >= 0) {
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
if (clientSideVersion < compatibleProtocols[0]) {
|
||||
return compatibleProtocols[0];
|
||||
}
|
||||
|
||||
// TODO: This needs a better fix, i.e checking ProtocolRegistry to see if it would work.
|
||||
for (int i = compatibleProtocols.length - 1; i >= 0; i--) {
|
||||
int protocol = compatibleProtocols[i];
|
||||
if (clientSideVersion > protocol && ProtocolVersion.isRegistered(protocol)) {
|
||||
return protocol;
|
||||
}
|
||||
}
|
||||
|
||||
ViaFabric.JLOGGER.severe("multiconnect integration: Panic, no protocol id found for " + clientSideVersion);
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
private boolean isDisabled(String addr) {
|
||||
String[] parts = addr.split("\\.");
|
||||
boolean isNumericIp = parts.length == 4 && Arrays.stream(parts).map(Ints::tryParse).allMatch(Objects::nonNull);
|
||||
return IntStream.range(0, parts.length).anyMatch(i -> {
|
||||
String query;
|
||||
if (isNumericIp) {
|
||||
query = String.join(".", Arrays.stream(parts, 0, i + 1)
|
||||
.toArray(String[]::new)) + ((i != 3) ? ".*" : "");
|
||||
} else {
|
||||
query = ((i != 0) ? "*." : "") + String.join(".", Arrays.stream(parts, i, parts.length)
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
if (ViaFabric.config.isForcedDisable(query)) {
|
||||
ViaFabric.JLOGGER.info(addr + " is force-disabled. (Matches " + query + ")");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
@Override
|
||||
protected CompletableFuture<ProtocolVersion> detectVersion(InetSocketAddress address) {
|
||||
return ProtocolAutoDetector.detectVersion(address);
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@
|
||||
},
|
||||
"depends": {
|
||||
"fabric-resource-loader-v0": "*",
|
||||
"minecraft": ">1.16.50",
|
||||
"minecraft": "1.17.x",
|
||||
"viafabric": "*"
|
||||
},
|
||||
"recommends": {
|
||||
|
@ -1,13 +1,11 @@
|
||||
{
|
||||
"required": true,
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"package": "com.viaversion.fabric.mc117.mixin.address",
|
||||
"mixins": [
|
||||
],
|
||||
"client": [
|
||||
"client.MixinConnectScreenThread",
|
||||
"client.MixinServerAddress",
|
||||
"client.MixinServerPinger"
|
||||
"client.MixinAllowedAddressResolver"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"required": true,
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"package": "com.viaversion.fabric.mc117.mixin.debug",
|
||||
"mixins": [
|
||||
],
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"required": true,
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"package": "com.viaversion.fabric.mc117.mixin.gui",
|
||||
"mixins": [
|
||||
],
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"required": true,
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"package": "com.viaversion.fabric.mc117.mixin.pipeline",
|
||||
"mixins": [
|
||||
"MixinClientConnection",
|
||||
|
@ -1,166 +1,28 @@
|
||||
package com.viaversion.fabric.mc18.providers;
|
||||
|
||||
import com.viaversion.fabric.common.config.VFConfig;
|
||||
import com.viaversion.fabric.common.provider.VFVersionProvider;
|
||||
import com.viaversion.fabric.mc18.ViaFabric;
|
||||
import com.viaversion.fabric.common.VFAddressParser;
|
||||
import com.viaversion.fabric.mc18.service.ProtocolAutoDetector;
|
||||
import com.viaversion.fabric.common.util.ProtocolUtils;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.network.ClientConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.protocols.base.*;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class VRVersionProvider extends BaseVersionProvider {
|
||||
private int[] multiconnectSupportedVersions = null;
|
||||
|
||||
{
|
||||
try {
|
||||
if (FabricLoader.getInstance().isModLoaded("multiconnect")) {
|
||||
Class<?> mcApiClass = Class.forName("net.earthcomputer.multiconnect.api.MultiConnectAPI");
|
||||
Class<?> iProtocolClass = Class.forName("net.earthcomputer.multiconnect.api.IProtocol");
|
||||
Object mcApiInstance = mcApiClass.getMethod("instance").invoke(null);
|
||||
List<?> protocols = (List<?>) mcApiClass.getMethod("getSupportedProtocols").invoke(mcApiInstance);
|
||||
Method getValue = iProtocolClass.getMethod("getValue");
|
||||
Method isMulticonnectBeta;
|
||||
try {
|
||||
isMulticonnectBeta = iProtocolClass.getMethod("isMulticonnectBeta");
|
||||
} catch (NoSuchMethodException e) {
|
||||
isMulticonnectBeta = null;
|
||||
}
|
||||
Set<Integer> vers = new TreeSet<>();
|
||||
for (Object protocol : protocols) {
|
||||
// Do not use versions with beta multiconnect support, which may have stability issues
|
||||
if (isMulticonnectBeta == null || !(Boolean) isMulticonnectBeta.invoke(protocol)) {
|
||||
vers.add((Integer) getValue.invoke(protocol));
|
||||
}
|
||||
}
|
||||
multiconnectSupportedVersions = vers.stream().mapToInt(Integer::intValue).toArray();
|
||||
ViaFabric.JLOGGER.info("ViaFabric will integrate with multiconnect");
|
||||
}
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InvocationTargetException | NoSuchMethodException
|
||||
| ClassCastException ignored) {
|
||||
}
|
||||
public class VRVersionProvider extends VFVersionProvider {
|
||||
@Override
|
||||
protected Logger getLogger() {
|
||||
return ViaFabric.JLOGGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClosestServerProtocol(UserConnection connection) throws Exception {
|
||||
if (connection.isClientSide()) {
|
||||
ProtocolInfo info = Objects.requireNonNull(connection.getProtocolInfo());
|
||||
|
||||
if (!ViaFabric.config.isClientSideEnabled()) {
|
||||
return info.getProtocolVersion();
|
||||
}
|
||||
|
||||
int serverVer = ViaFabric.config.getClientSideVersion();
|
||||
SocketAddress addr = connection.getChannel().remoteAddress();
|
||||
|
||||
if (addr instanceof InetSocketAddress) {
|
||||
int addrVersion = new VFAddressParser().parse(((InetSocketAddress) addr).getHostName()).protocol;
|
||||
if (addrVersion != 0) serverVer = addrVersion;
|
||||
|
||||
try {
|
||||
if (serverVer == -2) {
|
||||
// Hope protocol was autodetected
|
||||
ProtocolVersion autoVer =
|
||||
ProtocolAutoDetector.detectVersion((InetSocketAddress) addr).getNow(null);
|
||||
if (autoVer != null) {
|
||||
serverVer = autoVer.getVersion();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
ViaFabric.JLOGGER.warning("Couldn't auto detect: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
boolean blocked = checkAddressBlocked(addr);
|
||||
boolean supported = ProtocolUtils.isSupported(serverVer, info.getProtocolVersion());
|
||||
|
||||
handleMulticonnectPing(connection, info, blocked, serverVer);
|
||||
|
||||
if (blocked || !supported) serverVer = info.getProtocolVersion();
|
||||
|
||||
return serverVer;
|
||||
}
|
||||
return super.getClosestServerProtocol(connection);
|
||||
protected VFConfig getConfig() {
|
||||
return ViaFabric.config;
|
||||
}
|
||||
|
||||
private boolean checkAddressBlocked(SocketAddress addr) {
|
||||
return addr instanceof InetSocketAddress && (isDisabled(((InetSocketAddress) addr).getHostString())
|
||||
|| ((((InetSocketAddress) addr).getAddress() != null) &&
|
||||
(isDisabled(((InetSocketAddress) addr).getAddress().getHostAddress())
|
||||
|| isDisabled(((InetSocketAddress) addr).getAddress().getHostName()))));
|
||||
@Override
|
||||
protected CompletableFuture<ProtocolVersion> detectVersion(InetSocketAddress address) {
|
||||
return ProtocolAutoDetector.detectVersion(address);
|
||||
}
|
||||
|
||||
private void handleMulticonnectPing(UserConnection connection, ProtocolInfo info, boolean blocked, int serverVer) throws Exception {
|
||||
if (info.getState() == State.STATUS
|
||||
&& info.getProtocolVersion() == -1
|
||||
&& connection.getChannel().pipeline().get(ClientConnection.class).getPacketListener()
|
||||
.getClass().getName().startsWith("net.earthcomputer.multiconnect")
|
||||
&& (blocked || ProtocolUtils.isSupported(serverVer, getVersionForMulticonnect(serverVer)))) { // Intercept the connection
|
||||
int multiconnectSuggestion = blocked ? -1 : getVersionForMulticonnect(serverVer);
|
||||
ViaFabric.JLOGGER.info("Sending " + ProtocolVersion.getProtocol(multiconnectSuggestion) + " for multiconnect version detector");
|
||||
PacketWrapper newAnswer = PacketWrapper.create(0x00, null, connection);
|
||||
newAnswer.write(Type.STRING, "{\"version\":{\"name\":\"viafabric integration\",\"protocol\":" + multiconnectSuggestion + "}}");
|
||||
newAnswer.send(info.getPipeline().contains(BaseProtocol1_16.class) ? BaseProtocol1_16.class : BaseProtocol1_7.class, true, true);
|
||||
throw CancelException.generate();
|
||||
}
|
||||
}
|
||||
|
||||
private int getVersionForMulticonnect(int clientSideVersion) {
|
||||
// https://github.com/ViaVersion/ViaVersion/blob/master/velocity/src/main/java/us/myles/ViaVersion/velocity/providers/VelocityVersionProvider.java
|
||||
int[] compatibleProtocols = multiconnectSupportedVersions;
|
||||
|
||||
if (Arrays.binarySearch(compatibleProtocols, clientSideVersion) >= 0) {
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
if (clientSideVersion < compatibleProtocols[0]) {
|
||||
return compatibleProtocols[0];
|
||||
}
|
||||
|
||||
// TODO: This needs a better fix, i.e checking ProtocolRegistry to see if it would work.
|
||||
for (int i = compatibleProtocols.length - 1; i >= 0; i--) {
|
||||
int protocol = compatibleProtocols[i];
|
||||
if (clientSideVersion > protocol && ProtocolVersion.isRegistered(protocol)) {
|
||||
return protocol;
|
||||
}
|
||||
}
|
||||
|
||||
ViaFabric.JLOGGER.severe("multiconnect integration: Panic, no protocol id found for " + clientSideVersion);
|
||||
return clientSideVersion;
|
||||
}
|
||||
|
||||
private boolean isDisabled(String addr) {
|
||||
String[] parts = addr.split("\\.");
|
||||
boolean isNumericIp = parts.length == 4 && Arrays.stream(parts).map(Ints::tryParse).allMatch(Objects::nonNull);
|
||||
return IntStream.range(0, parts.length).anyMatch(i -> {
|
||||
String query;
|
||||
if (isNumericIp) {
|
||||
query = String.join(".", Arrays.stream(parts, 0, i + 1)
|
||||
.toArray(String[]::new)) + ((i != 3) ? ".*" : "");
|
||||
} else {
|
||||
query = ((i != 0) ? "*." : "") + String.join(".", Arrays.stream(parts, i, parts.length)
|
||||
.toArray(String[]::new));
|
||||
}
|
||||
if (ViaFabric.config.isForcedDisable(query)) {
|
||||
ViaFabric.JLOGGER.info(addr + " is force-disabled. (Matches " + query + ")");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user