From b208f77d9ddf5ac3e35e409eef6be58843e6d20c Mon Sep 17 00:00:00 2001 From: pjscruggs Date: Tue, 27 Oct 2026 00:08:52 -0500 Subject: [PATCH 1/5] fix(compression): consume unrecognized handshake frames once --- .../common/connection/MultiChannelingStreamingCompression.java | 1 + 1 file changed, 1 insertion(+) diff --git a/common/src/main/java/com/ishland/raknetify/common/connection/MultiChannelingStreamingCompression.java b/common/src/main/java/com/ishland/raknetify/common/connection/MultiChannelingStreamingCompression.java index b30ae01..6c50642 100644 --- a/common/src/main/java/com/ishland/raknetify/common/connection/MultiChannelingStreamingCompression.java +++ b/common/src/main/java/com/ishland/raknetify/common/connection/MultiChannelingStreamingCompression.java @@ -138,6 +138,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception compressedFrameData.release(); if (payload != null) payload.release(); } + return; } else if (compressedFrameData.getPacketId() == compressedPacketId && compressedFrameData.getReliability().isReliable && compressedFrameData.getReliability().isOrdered && !compressedFrameData.getReliability().isSequenced && inflaters[compressedFrameData.getOrderChannel()] != null) { final int orderChannel = compressedFrameData.getOrderChannel(); final Inflater inflater = inflaters[orderChannel]; From f838fa0bb255e42a7f08f140c0abce64a64e6995 Mon Sep 17 00:00:00 2001 From: pjscruggs Date: Tue, 27 Oct 2026 00:28:19 -0500 Subject: [PATCH 2/5] build: update the toolchain for Minecraft 26 --- build.gradle | 5 +++-- gradle/wrapper/gradle-wrapper.properties | 2 +- velocity/build.gradle | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 7f19926..33e9137 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { - id 'fabric-loom' version '1.13-SNAPSHOT' apply false + id 'fabric-loom' version '1.17.21' apply false id 'com.gradleup.shadow' version '9.2.1' apply false - id 'dev.yumi.gradle.licenser' version '2.1.1' apply false + id 'dev.yumi.gradle.licenser' version '4.0.0' apply false id 'com.modrinth.minotaur' version '2.+' apply false id 'io.github.themrmilchmann.curseforge-publish' version '0.8.0' apply false } @@ -20,6 +20,7 @@ subprojects { version = project.mod_version + "." + getVersionSuffix() license { + include '**/*.java' rule(rootProject.file('HEADER.txt')) } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7b0b78c..52ad5e7 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/velocity/build.gradle b/velocity/build.gradle index d705ccb..e70e945 100644 --- a/velocity/build.gradle +++ b/velocity/build.gradle @@ -24,9 +24,9 @@ repositories { url 'https://repo.papermc.io/repository/maven-public/' } ivy { - url 'https://api.papermc.io/v2/projects/' + url 'https://fill-data.papermc.io/v1/objects/af292ea5c9c330fc3b367e48c7d1d448b1b3216f597798bfbef662d002b1343b/' patternLayout { - artifact "[organization]/versions/[module]/builds/[revision]/downloads/[organization]-[module]-[revision](.[ext])" + artifact "[organization]-[module]-[revision](.[ext])" } metadataSources { it.artifact() From 2350810ea2eda14b5066fdf27267394f63d5cd2e Mon Sep 17 00:00:00 2001 From: pjscruggs Date: Tue, 27 Oct 2026 00:28:50 -0500 Subject: [PATCH 3/5] fix(fabric): adapt encryption and protocol transition hooks --- .../connection/RakNetNetworkTransitionUtil.java | 10 ++++++++-- .../fabric/common/util/MultiVersionUtil.java | 12 ++++++++++++ .../fabric/mixin/RaknetifyFabricMixinPlugin.java | 2 ++ .../fabric/mixin/access/IClientConnection.java | 3 --- .../common/encryption/MixinClientConnection.java | 6 ++---- .../krypton/MixinServerLoginNetworkHandler.java | 3 ++- 6 files changed, 26 insertions(+), 10 deletions(-) diff --git a/fabric/src/main/java/com/ishland/raknetify/fabric/common/connection/RakNetNetworkTransitionUtil.java b/fabric/src/main/java/com/ishland/raknetify/fabric/common/connection/RakNetNetworkTransitionUtil.java index c43ac42..47bb967 100644 --- a/fabric/src/main/java/com/ishland/raknetify/fabric/common/connection/RakNetNetworkTransitionUtil.java +++ b/fabric/src/main/java/com/ishland/raknetify/fabric/common/connection/RakNetNetworkTransitionUtil.java @@ -30,9 +30,15 @@ public class RakNetNetworkTransitionUtil { static Object handleTransition(Object msg) { if (msg instanceof NetworkStateTransitions.DecoderTransitioner transitioner) { - return transitioner.andThen(context -> RakNetFabricConnectionUtil.onPipelineReorder(context.pipeline())); + return (NetworkStateTransitions.DecoderTransitioner) context -> { + transitioner.run(context); + RakNetFabricConnectionUtil.onPipelineReorder(context.pipeline()); + }; } else if (msg instanceof NetworkStateTransitions.EncoderTransitioner transitioner) { - return transitioner.andThen(context -> RakNetFabricConnectionUtil.onPipelineReorder(context.pipeline())); + return (NetworkStateTransitions.EncoderTransitioner) context -> { + transitioner.run(context); + RakNetFabricConnectionUtil.onPipelineReorder(context.pipeline()); + }; } return msg; } diff --git a/fabric/src/main/java/com/ishland/raknetify/fabric/common/util/MultiVersionUtil.java b/fabric/src/main/java/com/ishland/raknetify/fabric/common/util/MultiVersionUtil.java index 553ef0e..bb57ffc 100644 --- a/fabric/src/main/java/com/ishland/raknetify/fabric/common/util/MultiVersionUtil.java +++ b/fabric/src/main/java/com/ishland/raknetify/fabric/common/util/MultiVersionUtil.java @@ -62,6 +62,7 @@ public class MultiVersionUtil { public static final VarHandle ServerPlayNetworkHandler$connection; public static final VarHandle ClientPlayNetworkHandler$connection; + private static final VarHandle ClientConnection$encrypted; public static final VarHandle ServerPlayerEntity$pingMillis1_20_1; public static final Class clazzNetworkStatePacketHandler; public static final VarHandle NetworkStatePacketHandler$backingHandler1_20_2; @@ -77,6 +78,11 @@ public class MultiVersionUtil { try { final MappingResolver resolver = FabricLoader.getInstance().getMappingResolver(); + final Field encrypted = getOrNull(() -> ClientConnection.class.getDeclaredField( + resolver.mapFieldName(INTERMEDIARY, "net.minecraft.class_2535", "field_11647", "Z")), NoSuchFieldException.class); + ClientConnection$encrypted = encrypted == null ? null : MethodHandles + .privateLookupIn(ClientConnection.class, MethodHandles.lookup()).unreflectVarHandle(encrypted); + { final List connFields = tryLocateFields(ServerPlayNetworkHandler.class, ClientConnection.class, false); if (connFields.size() != 1) { @@ -254,6 +260,12 @@ private static List tryLocateFields(Class clazz, Class fieldType, b public static void init() { } + public static void setEncrypted(ClientConnection connection, boolean encrypted) { + if (ClientConnection$encrypted != null) { + ClientConnection$encrypted.set(connection, encrypted); + } + } + public static Class tryLocateClass(String name) { try { return Class.forName(name); diff --git a/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/RaknetifyFabricMixinPlugin.java b/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/RaknetifyFabricMixinPlugin.java index 50b5194..22f1924 100644 --- a/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/RaknetifyFabricMixinPlugin.java +++ b/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/RaknetifyFabricMixinPlugin.java @@ -103,6 +103,8 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { return !AFTER_1_20_1; if (mixinClassName.equals("com.ishland.raknetify.fabric.mixin.access.INetworkState1_20_4")) return !AFTER_1_20_4; + if (mixinClassName.equals("com.ishland.raknetify.fabric.mixin.access.INetworkStateInternalPacketHandler")) + return !AFTER_1_20_4; return true; } diff --git a/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/access/IClientConnection.java b/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/access/IClientConnection.java index 05253d9..01fff8a 100644 --- a/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/access/IClientConnection.java +++ b/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/access/IClientConnection.java @@ -35,7 +35,4 @@ public interface IClientConnection { @Accessor Channel getChannel(); - @Accessor - void setEncrypted(boolean encrypted); - } diff --git a/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/common/encryption/MixinClientConnection.java b/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/common/encryption/MixinClientConnection.java index 1ce35aa..255ac12 100644 --- a/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/common/encryption/MixinClientConnection.java +++ b/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/common/encryption/MixinClientConnection.java @@ -26,6 +26,7 @@ import com.ishland.raknetify.common.connection.MultiChannelingStreamingCompression; import com.ishland.raknetify.common.connection.MultiChannellingEncryption; +import com.ishland.raknetify.fabric.common.util.MultiVersionUtil; import io.netty.channel.Channel; import net.minecraft.network.ClientConnection; import net.minecraft.network.encryption.PacketDecryptor; @@ -44,9 +45,6 @@ @Mixin(ClientConnection.class) public class MixinClientConnection { - @Shadow - private boolean encrypted; - @Shadow private Channel channel; @@ -54,7 +52,7 @@ public class MixinClientConnection { public void beforeSetupEncryption(Cipher decryptionCipher, Cipher encryptionCipher, CallbackInfo ci) { if (this.channel.config() instanceof RakNet.Config) { ci.cancel(); - this.encrypted = true; + MultiVersionUtil.setEncrypted((ClientConnection) (Object) this, true); try { this.channel.pipeline().remove("decrypt"); this.channel.pipeline().remove("encrypt"); diff --git a/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/compat/krypton/MixinServerLoginNetworkHandler.java b/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/compat/krypton/MixinServerLoginNetworkHandler.java index 29d07b5..ce9a80f 100644 --- a/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/compat/krypton/MixinServerLoginNetworkHandler.java +++ b/fabric/src/main/java/com/ishland/raknetify/fabric/mixin/compat/krypton/MixinServerLoginNetworkHandler.java @@ -25,6 +25,7 @@ package com.ishland.raknetify.fabric.mixin.compat.krypton; import com.ishland.raknetify.fabric.mixin.access.IClientConnection; +import com.ishland.raknetify.fabric.common.util.MultiVersionUtil; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import net.minecraft.network.ClientConnection; @@ -76,7 +77,7 @@ private void afterSetupEncryption(LoginKeyC2SPacket packet, CallbackInfo ci) thr Cipher cipher = NetworkEncryptionUtils.cipherFromKey(2, secretKey); Cipher cipher2 = NetworkEncryptionUtils.cipherFromKey(1, secretKey); - ((IClientConnection) this.connection).setEncrypted(false); + MultiVersionUtil.setEncrypted(this.connection, false); this.connection.setupEncryption(cipher, cipher2); } } From 887507708a16884712e9228c526de02e29845e86 Mon Sep 17 00:00:00 2001 From: pjscruggs Date: Tue, 27 Oct 2026 00:32:14 -0500 Subject: [PATCH 4/5] feat(fabric): add deobfuscated Minecraft 26 artifacts --- .github/workflows/build.yml | 4 +- .github/workflows/checkMappings.yml | 2 +- Jenkinsfile | 2 +- build.gradle | 11 ++ fabric-26/build.gradle | 1 + fabric/build.gradle | 157 +++++++++++++----- .../common/connection/RakNetMultiChannel.java | 45 +++-- fabric/src/main/resources/fabric.mod.json | 5 +- genMappings.sh | 12 +- gradle.properties | 4 +- settings.gradle | 1 + 11 files changed, 184 insertions(+), 60 deletions(-) create mode 100644 fabric-26/build.gradle diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7257cbd..cd777fa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: matrix: # Use these Java versions java: [ - 21, # Current Java LTS & minimum supported by Minecraft + 25, # Required by Minecraft 26.x ] # and run on both Linux and Windows os: [ubuntu-24.04] @@ -51,7 +51,7 @@ jobs: GITHUB_EVENT_RAW_PATH: ${{ github.event_path }} continue-on-error: true - name: capture build artifacts - if: ${{ runner.os == 'Linux' && matrix.java == '21' }} # Only upload artifacts built from latest java on one OS + if: ${{ runner.os == 'Linux' && matrix.java == '25' }} # Only upload artifacts built from latest java on one OS uses: actions/upload-artifact@v4 with: name: Artifacts diff --git a/.github/workflows/checkMappings.yml b/.github/workflows/checkMappings.yml index c0350d6..bb4026d 100644 --- a/.github/workflows/checkMappings.yml +++ b/.github/workflows/checkMappings.yml @@ -7,7 +7,7 @@ jobs: matrix: # Use these Java versions java: [ - 21, # Current Java LTS & minimum supported by Minecraft + 25, # Required by Minecraft 26.x ] # and run on both Linux and Windows os: [ubuntu-24.04] diff --git a/Jenkinsfile b/Jenkinsfile index 5e65562..a2829fa 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,7 +9,7 @@ pipeline { } stage('Build') { tools { - jdk "OpenJDK 21" + jdk "OpenJDK 25" } steps { withMaven( diff --git a/build.gradle b/build.gradle index 33e9137..f5fe607 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,10 @@ plugins { id 'io.github.themrmilchmann.curseforge-publish' version '0.8.0' apply false } +ext.remapJarTaskType = net.fabricmc.loom.task.RemapJarTask +ext.curseforgeAlpha = io.github.themrmilchmann.gradle.publish.curseforge.ReleaseType.ALPHA +ext.curseforgeMarkdown = io.github.themrmilchmann.gradle.publish.curseforge.ChangelogFormat.MARKDOWN + subprojects { apply plugin: 'java' apply plugin: 'java-library' @@ -18,6 +22,7 @@ subprojects { } version = project.mod_version + "." + getVersionSuffix() + if (project.name == 'fabric-26') version += '.mc26' license { include '**/*.java' @@ -63,6 +68,12 @@ subprojects { versionType = "alpha" // This is the default -- can also be `beta` or `alpha` // uploadFile = remapShadowJar // With Loom, this MUST be set to `remapJar` instead of `jar`! gameVersions = ["1.18", "1.18.1", "1.18.2", "1.19", "1.19.1", "1.19.2", "1.19.3", "1.19.4", "1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4", "1.20.5", "1.20.6", "1.21", "1.21.1", "1.21.2", "1.21.3", "1.21.4", "1.21.5", "1.21.6", "1.21.7", "1.21.8", "1.21.9", "1.21.10", "1.21.11"] + def modernVersions = ['26.1', '26.1.1', '26.1.2', '26.2', '26.3'] + if (project.name == 'fabric-26') { + gameVersions = modernVersions + } else if (project.name != 'fabric') { + gameVersions.addAll(modernVersions) + } // loaders = ["fabric"] changelog = com.ishland.buildscript.ParseGItHubActionChangelog.getChangelog() } diff --git a/fabric-26/build.gradle b/fabric-26/build.gradle new file mode 100644 index 0000000..a1f38cd --- /dev/null +++ b/fabric-26/build.gradle @@ -0,0 +1 @@ +apply from: rootProject.file('fabric/build.gradle') diff --git a/fabric/build.gradle b/fabric/build.gradle index 5bac328..e801cf9 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -5,8 +5,20 @@ apply plugin: 'com.gradleup.shadow' apply plugin: 'com.modrinth.minotaur' apply plugin: 'io.github.themrmilchmann.curseforge-publish' +def modernMinecraft = project.name == 'fabric-26' +def fabricSources = rootProject.file('fabric/src/main') +if (modernMinecraft) { + ext.minecraft_version = project.modern_minecraft_version + ext.yarn_mappings = project.modern_yarn_mappings +} + +sourceSets.main { + java.setSrcDirs([new File(fabricSources, 'java')]) + resources.setSrcDirs([new File(fabricSources, 'resources')]) +} + base { - archivesName = project.archives_base_name + "-fabric" + archivesName = project.archives_base_name + (modernMinecraft ? "-fabric-26" : "-fabric") } group = project.maven_group + ".fabric" @@ -14,10 +26,23 @@ configurations { shadowInclude } +repositories { + maven { url 'https://repo.codemc.io/repository/relativitymc/' } +} + +def packetMappingFiles = files() +if (modernMinecraft) { + ['26.1', '26.1.1', '26.1.2', '26.2'].each { + def mapping = configurations.detachedConfiguration(dependencies.create("org.relativitymc:intermediary:${it}:v2")) + mapping.transitive = false + packetMappingFiles.from(mapping) + } +} + dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + mappings "${modernMinecraft ? 'org.relativitymc:modern-yarn' : 'net.fabricmc:yarn'}:${project.yarn_mappings}:v2" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" shadowInclude implementation(project(":common")) @@ -28,12 +53,51 @@ dependencies { processResources { inputs.property "version", project.version + inputs.property "minecraft", modernMinecraft ? '>=26.1 <26.4' : '>=1.18 <26' + inputs.property "java", modernMinecraft ? '>=25' : '>=17' + inputs.property "loader", modernMinecraft ? '>=0.19.5' : '>=0.15.2' filesMatching("fabric.mod.json") { - expand "version": project.version + expand "version": project.version, + "minecraft": inputs.properties.minecraft, + "java": inputs.properties.java, + "loader": inputs.properties.loader + } +} + +def packetNames = tasks.register('generatePacketNames') { + def packetSource = new File(fabricSources, 'java/com/ishland/raknetify/fabric/common/connection/RakNetMultiChannel.java') + def output = layout.buildDirectory.file('generated/packetNames/raknetify-packet-names.properties') + inputs.file(packetSource) + inputs.file(provider { loom.mappingConfiguration.tinyMappings.toFile() }) + inputs.files(packetMappingFiles) + outputs.file(output) + doLast { + def classes = (packetSource.text =~ 'net/minecraft/class_[0-9_]+(?:\\$class_[0-9_]+)*').collect().toSet() + def names = new TreeMap>() + def mappingFiles = [loom.mappingConfiguration.tinyMappings.toFile()] + packetMappingFiles.each { + mappingFiles.addAll(zipTree(it).matching { include 'mappings/mappings.tiny' }.files) + } + mappingFiles.each { mappingFile -> + mappingFile.eachLine('UTF-8') { line -> + def fields = line.split('\t') + if (fields[0] == 'c' && classes.contains(fields[2])) { + def key = fields[2].replace('/', '.') + if (!names.containsKey(key)) names[key] = new TreeSet() + names[key].add(fields[1].replace('/', '.')) + } + } + } + output.get().asFile.with { parentFile.mkdirs() } + output.get().asFile.setText(names.collect { key, value -> "$key=${value.join(',')}\n" }.join(), 'UTF-8') } } +processResources { + from(packetNames) +} + tasks.withType(JavaCompile).configureEach { // Minecraft 1.18 (1.18-pre2) upwards uses Java 17. it.options.release = 17 @@ -47,7 +111,11 @@ java { } loom { - accessWidenerPath = file("src/main/resources/raknetify-fabric.accesswidener") + if (modernMinecraft) { + intermediaryUrl = 'https://repo.codemc.io/repository/relativitymc/org/relativitymc/intermediary/%1$s/intermediary-%1$s-v2.jar' + useIntermediateMappings = true + } + accessWidenerPath = new File(fabricSources, 'resources/raknetify-fabric.accesswidener') runs { server { vmArgs "-Draknetify.debug=true", "-Dio.netty.leakDetection.level=advanced" @@ -82,7 +150,7 @@ shadowJar { } //noinspection UnnecessaryQualifiedReference -task("remapShadowJar", type: net.fabricmc.loom.task.RemapJarTask, dependsOn: shadowJar) { +task("remapShadowJar", type: rootProject.remapJarTaskType, dependsOn: shadowJar) { input = shadowJar.archiveFile archiveFileName = shadowJar.archiveFileName.get().replaceAll("-dev\\.jar\$", ".jar") addNestedDependencies = true @@ -120,40 +188,49 @@ curseforge { register("main") { projectId = "631457" - gameVersion("minecraft-1-18", "1-18") - gameVersion("minecraft-1-18", "1-18-1") - gameVersion("minecraft-1-18", "1-18-2") - gameVersion("minecraft-1-19", "1-19") - gameVersion("minecraft-1-19", "1-19-1") - gameVersion("minecraft-1-19", "1-19-2") - gameVersion("minecraft-1-19", "1-19-3") - gameVersion("minecraft-1-19", "1-19-4") - gameVersion("minecraft-1-20", "1-20") - gameVersion("minecraft-1-20", "1-20-1") - gameVersion("minecraft-1-20", "1-20-2") - gameVersion("minecraft-1-20", "1-20-3") - gameVersion("minecraft-1-20", "1-20-4") - gameVersion("minecraft-1-20", "1-20-5") - gameVersion("minecraft-1-20", "1-20-6") - gameVersion("minecraft-1-21", "1-21") - gameVersion("minecraft-1-21", "1-21-1") - gameVersion("minecraft-1-21", "1-21-2") - gameVersion("minecraft-1-21", "1-21-3") - gameVersion("minecraft-1-21", "1-21-4") - gameVersion("minecraft-1-21", "1-21-5") - gameVersion("minecraft-1-21", "1-21-6") - gameVersion("minecraft-1-21", "1-21-7") - gameVersion("minecraft-1-21", "1-21-8") - gameVersion("minecraft-1-21", "1-21-9") - gameVersion("minecraft-1-21", "1-21-10") - gameVersion("minecraft-1-21", "1-21-11") + if (modernMinecraft) { + gameVersion("minecraft-26-1", "26-1") + gameVersion("minecraft-26-1", "26-1-1") + gameVersion("minecraft-26-1", "26-1-2") + gameVersion("minecraft-26-2", "26-2") + gameVersion("minecraft-26-3", "26-3") + gameVersion("java", "java-25") + } else { + gameVersion("minecraft-1-18", "1-18") + gameVersion("minecraft-1-18", "1-18-1") + gameVersion("minecraft-1-18", "1-18-2") + gameVersion("minecraft-1-19", "1-19") + gameVersion("minecraft-1-19", "1-19-1") + gameVersion("minecraft-1-19", "1-19-2") + gameVersion("minecraft-1-19", "1-19-3") + gameVersion("minecraft-1-19", "1-19-4") + gameVersion("minecraft-1-20", "1-20") + gameVersion("minecraft-1-20", "1-20-1") + gameVersion("minecraft-1-20", "1-20-2") + gameVersion("minecraft-1-20", "1-20-3") + gameVersion("minecraft-1-20", "1-20-4") + gameVersion("minecraft-1-20", "1-20-5") + gameVersion("minecraft-1-20", "1-20-6") + gameVersion("minecraft-1-21", "1-21") + gameVersion("minecraft-1-21", "1-21-1") + gameVersion("minecraft-1-21", "1-21-2") + gameVersion("minecraft-1-21", "1-21-3") + gameVersion("minecraft-1-21", "1-21-4") + gameVersion("minecraft-1-21", "1-21-5") + gameVersion("minecraft-1-21", "1-21-6") + gameVersion("minecraft-1-21", "1-21-7") + gameVersion("minecraft-1-21", "1-21-8") + gameVersion("minecraft-1-21", "1-21-9") + gameVersion("minecraft-1-21", "1-21-10") + gameVersion("minecraft-1-21", "1-21-11") + gameVersion("java", "java-22") + gameVersion("java", "java-21") + gameVersion("java", "java-20") + gameVersion("java", "java-19") + gameVersion("java", "java-18") + gameVersion("java", "java-17") + } gameVersion("modloader", "fabric") - gameVersion("java", "java-22") - gameVersion("java", "java-21") - gameVersion("java", "java-20") - gameVersion("java", "java-19") - gameVersion("java", "java-18") - gameVersion("java", "java-17") gameVersion("environment", "server") gameVersion("environment", "client") @@ -161,10 +238,10 @@ curseforge { from(remapShadowJar) displayName = project.version + " devbuild" - releaseType = io.github.themrmilchmann.gradle.publish.curseforge.ReleaseType.ALPHA + releaseType = rootProject.curseforgeAlpha changelog { - format = io.github.themrmilchmann.gradle.publish.curseforge.ChangelogFormat.MARKDOWN + format = rootProject.curseforgeMarkdown from(com.ishland.buildscript.ParseGItHubActionChangelog.getChangelog()) } } diff --git a/fabric/src/main/java/com/ishland/raknetify/fabric/common/connection/RakNetMultiChannel.java b/fabric/src/main/java/com/ishland/raknetify/fabric/common/connection/RakNetMultiChannel.java index 89f04a0..ec956ce 100644 --- a/fabric/src/main/java/com/ishland/raknetify/fabric/common/connection/RakNetMultiChannel.java +++ b/fabric/src/main/java/com/ishland/raknetify/fabric/common/connection/RakNetMultiChannel.java @@ -29,7 +29,10 @@ import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.MappingResolver; +import java.io.IOException; +import java.io.InputStream; import java.util.HashSet; +import java.util.Properties; import java.util.Set; public class RakNetMultiChannel { @@ -37,21 +40,34 @@ public class RakNetMultiChannel { private RakNetMultiChannel() { } + private static final Properties packetNames = loadPacketNames(); + + private static Properties loadPacketNames() { + final Properties names = new Properties(); + try (InputStream input = RakNetMultiChannel.class.getResourceAsStream("/raknetify-packet-names.properties")) { + if (input != null) names.load(input); + } catch (IOException e) { + throw new IllegalStateException("Failed to load packet names", e); + } + return names; + } + private static Set> createClassSet(String[] classNames) { final MappingResolver mappingResolver = FabricLoader.getInstance().getMappingResolver(); final boolean isIntermediaryNamespace = mappingResolver.getCurrentRuntimeNamespace().equals("intermediary"); final HashSet> classHashSet = new HashSet<>(); for (String className : classNames) { - final String intermediary = mappingResolver.mapClassName("intermediary", className.replace('/', '.')); - if (!isIntermediaryNamespace && intermediary.equals(className)) - //noinspection RedundantStringFormatCall - System.err.println("Raknetify: Warning: Failed to remap %s for raknet multi-channel".formatted(intermediary)); - try { - classHashSet.add(Class.forName(intermediary, false, RakNetMultiChannel.class.getClassLoader())); - } catch (ClassNotFoundException e) { - if (Boolean.getBoolean("raknetify.printNotFoundClasses")) { - //noinspection RedundantStringFormatCall - System.out.println("Raknetify: Warning: %s not found for raknet multi-channel".formatted(intermediary)); + final String sourceName = className.replace('/', '.'); + final String mappedName = mappingResolver.mapClassName("intermediary", sourceName); + final String names = mappedName.equals(sourceName) && !isIntermediaryNamespace + ? packetNames.getProperty(sourceName, mappedName) : mappedName; + for (String name : names.split(",")) { + try { + classHashSet.add(Class.forName(name, false, RakNetMultiChannel.class.getClassLoader())); + } catch (ClassNotFoundException e) { + if (Boolean.getBoolean("raknetify.printNotFoundClasses")) { + System.out.println("Raknetify: Warning: %s not found for raknet multi-channel".formatted(name)); + } } } } @@ -89,6 +105,9 @@ private static Set> createClassSet(String[] classNames) { // Primarily used for interactions independent to world private static final Set> channel1 = createClassSet(new String[]{ + "net/minecraft/class_1_71", // LowDiskSpaceWarningS2CPacket + "net/minecraft/class_1_130", // SetGameRuleC2SPacket + "net/minecraft/class_1_132", // GameRuleValuesS2CPacket "net/minecraft/class_2629", // BossBarS2C "net/minecraft/class_5888", // ClearTitleS2C "net/minecraft/class_5903", // SubtitleS2C @@ -181,6 +200,9 @@ private static Set> createClassSet(String[] classNames) { // Entities related stuff private static final Set> channel2 = createClassSet(new String[]{ + "net/minecraft/class_1_126", // AttackC2SPacket + "net/minecraft/class_1_1438", // HandSwingC2SPacket + "net/minecraft/class_1_1444", // SwingAnimationS2CPacket "net/minecraft/class_5890", // EndCombatS2C "net/minecraft/class_5891", // EnterCombatS2C "net/minecraft/class_2716", // EntitiesDestroyS2C @@ -250,6 +272,7 @@ private static Set> createClassSet(String[] classNames) { // Primarily used for interactions dependent to world private static final Set> channel3 = createClassSet(new String[]{ + "net/minecraft/class_1_133", // SpectateEntityC2SPacket "net/minecraft/class_2884", // SpectatorTeleportC2S "net/minecraft/class_2793", // TeleportConfirmC2S @@ -320,6 +343,7 @@ private static Set> createClassSet(String[] classNames) { // Primarily for packets not very critical to interactions private static final Set> channel4 = createClassSet(new String[]{ + "net/minecraft/class_1_1290", // PostEffectsS2CPacket "net/minecraft/class_2683", // MapUpdateS2C "net/minecraft/class_2660", // PlaySoundIdS2C "net/minecraft/class_2765", // PlaySoundFromEntityS2C @@ -332,6 +356,7 @@ private static Set> createClassSet(String[] classNames) { // Used for worlds private static final Set> channel7 = createClassSet(new String[]{ + "net/minecraft/class_1_1680", // AddTransientBlockS2CPacket "net/minecraft/class_5194", // JigsawGeneratingC2S "net/minecraft/class_2693", // SignEditorOpenS2C "net/minecraft/class_2877", // UpdateSignC2S diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 8e00798..d386fb6 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -30,8 +30,9 @@ ], "depends": { - "fabricloader": ">=0.15.2", - "java": ">=17" + "fabricloader": "${loader}", + "minecraft": "${minecraft}", + "java": "${java}" }, "suggests": { } diff --git a/genMappings.sh b/genMappings.sh index fa7d619..6b270bb 100755 --- a/genMappings.sh +++ b/genMappings.sh @@ -1,11 +1,11 @@ #!/bin/bash -loader_version=0.18.4 +loader_version=0.20.1 installer_version=1.1.1 #declare -a vers if [[ -z "$@" ]]; then - vers="1.17 1.17.1 1.18.1 1.18.2 1.19 1.19.2 1.19.3 1.19.4 23w13a_or_b 1.20.1 1.20.2 1.20.4 1.20.6 1.21.1 1.21.3 1.21.4 1.21.5 1.21.6 1.21.8 1.21.10 1.21.11" + vers="1.18.1 1.18.2 1.19 1.19.2 1.19.3 1.19.4 23w13a_or_b 1.20.1 1.20.2 1.20.4 1.20.6 1.21.1 1.21.3 1.21.4 1.21.5 1.21.6 1.21.8 1.21.10 1.21.11 26.1 26.1.1 26.1.2 26.2 26.3" else vers=$@ fi @@ -18,7 +18,6 @@ mkdir run-mappingsGen || true cd run-mappingsGen || exit 1 rm -r mods mkdir mods -cp ../fabric/build/libs/raknetify-*-all.jar mods/ rm channelMappings.json || true if [[ -z "${MAPPINGS_GEN_FRESH}" ]]; then cp ../common/src/main/resources/raknetify-channel-mappings.json channelMappings.json @@ -26,6 +25,13 @@ fi for version in $vers do + rm -f mods/raknetify-*-all.jar + if [[ "$version" == 26.* ]]; then + cp ../fabric-26/build/libs/raknetify-*-all.jar mods/ || exit 1 + else + cp ../fabric/build/libs/raknetify-*-all.jar mods/ || exit 1 + fi + if [ -e fabric-server-mc"$version".jar ]; then echo "Using existing fabric-server-mc$version.jar" else diff --git a/gradle.properties b/gradle.properties index 5ad7b7d..2844389 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,9 @@ gradle-curseforge-publish.interop.neogradle=false # Also don't forget to gen mappings in genMappings.sh minecraft_version=1.21.11 yarn_mappings=1.21.11+build.1 -loader_version=0.17.2 +modern_minecraft_version=26.3 +modern_yarn_mappings=26.3+build.1 +loader_version=0.19.5 # Mod Properties mod_version = 0.1.0+alpha.5 diff --git a/settings.gradle b/settings.gradle index fb9b7ca..47cc500 100644 --- a/settings.gradle +++ b/settings.gradle @@ -20,6 +20,7 @@ includeBuild('netty-raknet') { } include "fabric" +include "fabric-26" include "velocity" include "bungee" include "common" From 76d2cafdcd2c01c6ed813ed66af8fd62aba63230 Mon Sep 17 00:00:00 2001 From: pjscruggs Date: Tue, 27 Oct 2026 00:35:53 -0500 Subject: [PATCH 5/5] fix(proxy): add and regenerate Minecraft 26 channel mappings --- .../resources/raknetify-channel-mappings.json | 651 ++++++++++++++++++ .../raknetify/fabric/RaknetifyFabric.java | 5 + 2 files changed, 656 insertions(+) diff --git a/common/src/main/resources/raknetify-channel-mappings.json b/common/src/main/resources/raknetify-channel-mappings.json index 704573e..0e13b59 100644 --- a/common/src/main/resources/raknetify-channel-mappings.json +++ b/common/src/main/resources/raknetify-channel-mappings.json @@ -3612,6 +3612,657 @@ "65": 1 } }, + "775": { + "s2c": { + "0": -2147483648, + "1": 2, + "2": 2, + "3": -1, + "4": 7, + "5": 7, + "6": 7, + "7": 7, + "8": 7, + "9": 1, + "10": 1, + "11": 7, + "12": 7, + "13": 7, + "14": 1, + "15": 1, + "16": 1, + "17": 3, + "18": 3, + "19": 3, + "20": 3, + "21": 1, + "22": 1, + "23": 1, + "24": 3, + "25": 2, + "26": 7, + "27": 7, + "28": 2, + "29": 2, + "30": 1, + "31": 1, + "32": -1, + "33": 1, + "34": 2, + "35": 2, + "36": 2, + "37": 7, + "38": 2, + "39": 1, + "40": 7, + "41": 3, + "42": 2, + "43": 3, + "44": -1, + "45": 7, + "46": 7, + "47": 4, + "48": 7, + "49": 2, + "50": 1, + "51": 4, + "52": 3, + "53": 2, + "54": 2, + "55": 2, + "56": 2, + "57": 2, + "58": 3, + "59": 3, + "60": 7, + "61": -1, + "62": -1, + "63": 3, + "64": 2, + "65": 1, + "66": 2, + "67": 2, + "68": 1, + "69": 1, + "70": 1, + "71": 1, + "72": 1, + "73": 2, + "74": 3, + "75": 3, + "76": 3, + "77": 2, + "78": 2, + "79": 1, + "80": -1, + "81": -1, + "82": 3, + "83": 2, + "84": 7, + "85": -1, + "86": 1, + "87": 1, + "88": 3, + "89": 3, + "90": 3, + "91": 3, + "92": 3, + "93": 2, + "94": 7, + "95": 7, + "96": 3, + "97": 2, + "98": 1, + "99": 2, + "100": 2, + "101": 2, + "102": 2, + "103": 1, + "104": 1, + "105": 3, + "106": 1, + "107": 2, + "108": 3, + "109": 1, + "110": 1, + "111": 7, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 4, + "117": 4, + "118": 0, + "119": 4, + "120": 1, + "121": 1, + "122": 1, + "123": 3, + "124": 2, + "125": 2, + "126": 7, + "127": 3, + "128": 3, + "129": 0, + "130": 1, + "131": 2, + "132": 2, + "133": 1, + "134": 1, + "135": 2, + "136": -1, + "137": -1, + "138": 1, + "139": 1, + "140": 1 + }, + "c2s": { + "0": 3, + "1": 2, + "2": 3, + "3": 3, + "4": 1, + "5": 2, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 7, + "12": 3, + "13": 2, + "14": 1, + "15": 1, + "16": 0, + "17": 1, + "18": 1, + "19": 3, + "20": 3, + "21": 1, + "22": 3, + "23": 1, + "24": 3, + "25": 3, + "26": 2, + "27": 7, + "28": -1, + "29": 1, + "30": 2, + "31": 2, + "32": 2, + "33": 2, + "34": 2, + "35": 2, + "36": 1, + "37": 1, + "38": -1, + "39": 3, + "40": 3, + "41": 1, + "42": 1, + "43": 1, + "44": 7, + "45": -1, + "46": 3, + "47": 3, + "48": 3, + "49": -1, + "50": -1, + "51": 3, + "52": 3, + "53": 3, + "54": 3, + "55": 3, + "56": 3, + "57": 1, + "58": 3, + "59": 3, + "60": 3, + "61": 7, + "62": 3, + "63": 2, + "64": 3, + "65": 3, + "66": 2, + "67": 2, + "68": 1 + } + }, + "776": { + "s2c": { + "0": -2147483648, + "1": 2, + "2": 2, + "3": -1, + "4": 7, + "5": 7, + "6": 7, + "7": 7, + "8": 7, + "9": 1, + "10": 1, + "11": 7, + "12": 7, + "13": 7, + "14": 1, + "15": 1, + "16": 1, + "17": 3, + "18": 3, + "19": 3, + "20": 3, + "21": 1, + "22": 1, + "23": 1, + "24": 3, + "25": 2, + "26": 7, + "27": 7, + "28": 2, + "29": 2, + "30": 1, + "31": 1, + "32": -1, + "33": 1, + "34": 2, + "35": 2, + "36": 2, + "37": 7, + "38": 2, + "39": 1, + "40": 7, + "41": 3, + "42": 2, + "43": 3, + "44": -1, + "45": 7, + "46": 7, + "47": 4, + "48": 7, + "49": 2, + "50": 1, + "51": 4, + "52": 3, + "53": 2, + "54": 2, + "55": 2, + "56": 2, + "57": 2, + "58": 3, + "59": 3, + "60": 7, + "61": -1, + "62": -1, + "63": 3, + "64": 2, + "65": 1, + "66": 2, + "67": 2, + "68": 1, + "69": 1, + "70": 1, + "71": 1, + "72": 1, + "73": 2, + "74": 3, + "75": 3, + "76": 3, + "77": 2, + "78": 2, + "79": 1, + "80": -1, + "81": -1, + "82": 3, + "83": 2, + "84": 7, + "85": -1, + "86": 1, + "87": 1, + "88": 3, + "89": 3, + "90": 3, + "91": 3, + "92": 3, + "93": 2, + "94": 7, + "95": 7, + "96": 3, + "97": 2, + "98": 1, + "99": 2, + "100": 2, + "101": 2, + "102": 2, + "103": 1, + "104": 1, + "105": 3, + "106": 1, + "107": 2, + "108": 3, + "109": 1, + "110": 1, + "111": 7, + "112": 1, + "113": 1, + "114": 1, + "115": 1, + "116": 4, + "117": 4, + "118": 0, + "119": 4, + "120": 1, + "121": 1, + "122": 1, + "123": 3, + "124": 2, + "125": 2, + "126": 7, + "127": 3, + "128": 3, + "129": 0, + "130": 1, + "131": 2, + "132": 2, + "133": 1, + "134": 1, + "135": 2, + "136": -1, + "137": -1, + "138": 1, + "139": 1, + "140": 1 + }, + "c2s": { + "0": 3, + "1": 2, + "2": 3, + "3": 3, + "4": 1, + "5": 2, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 7, + "12": 3, + "13": 2, + "14": 1, + "15": 1, + "16": 0, + "17": 1, + "18": 1, + "19": 3, + "20": 3, + "21": 1, + "22": 3, + "23": 1, + "24": 3, + "25": 3, + "26": 2, + "27": 7, + "28": -1, + "29": 1, + "30": 2, + "31": 2, + "32": 2, + "33": 2, + "34": 2, + "35": 2, + "36": 1, + "37": 1, + "38": -1, + "39": 3, + "40": 3, + "41": 1, + "42": 1, + "43": 1, + "44": 7, + "45": -1, + "46": 3, + "47": 3, + "48": 3, + "49": -1, + "50": -1, + "51": 3, + "52": 3, + "53": 3, + "54": 3, + "55": 3, + "56": 3, + "57": 1, + "58": 3, + "59": 3, + "60": 3, + "61": 7, + "62": 3, + "63": 2, + "64": 3, + "65": 3, + "66": 2, + "67": 2, + "68": 1 + } + }, + "777": { + "s2c": { + "0": -2147483648, + "1": 2, + "2": 2, + "3": -1, + "4": 7, + "5": 7, + "6": 7, + "7": 7, + "8": 7, + "9": 1, + "10": 1, + "11": 7, + "12": 7, + "13": 7, + "14": 1, + "15": 1, + "16": 1, + "17": 3, + "18": 3, + "19": 3, + "20": 3, + "21": 1, + "22": 1, + "23": 1, + "24": 3, + "25": 2, + "26": 7, + "27": 7, + "28": 2, + "29": 2, + "30": 1, + "31": 1, + "32": -1, + "33": 1, + "34": 2, + "35": 2, + "36": 2, + "37": 7, + "38": 7, + "39": 2, + "40": 1, + "41": 7, + "42": 3, + "43": 2, + "44": 3, + "45": -1, + "46": 7, + "47": 7, + "48": 4, + "49": 7, + "50": 2, + "51": 1, + "52": 4, + "53": 3, + "54": 2, + "55": 2, + "56": 2, + "57": 2, + "58": 2, + "59": 3, + "60": 3, + "61": 7, + "62": -1, + "63": -1, + "64": 3, + "65": 2, + "66": 1, + "67": 2, + "68": 2, + "69": 1, + "70": 1, + "71": 1, + "72": 1, + "73": 1, + "74": 2, + "75": 3, + "76": 3, + "77": 3, + "78": 2, + "79": 2, + "80": 1, + "81": -1, + "82": -1, + "83": 4, + "84": 3, + "85": 2, + "86": 7, + "87": -1, + "88": 1, + "89": 1, + "90": 3, + "91": 3, + "92": 3, + "93": 3, + "94": 3, + "95": 2, + "96": 7, + "97": 7, + "98": 3, + "99": 2, + "100": 1, + "101": 2, + "102": 2, + "103": 2, + "104": 2, + "105": 1, + "106": 1, + "107": 3, + "108": 1, + "109": 2, + "110": 3, + "111": 1, + "112": 1, + "113": 7, + "114": 1, + "115": 1, + "116": 1, + "117": 1, + "118": 4, + "119": 4, + "120": 0, + "121": 4, + "122": 1, + "123": 2, + "124": 1, + "125": 1, + "126": 3, + "127": 2, + "128": 2, + "129": 7, + "130": 3, + "131": 3, + "132": 0, + "133": 1, + "134": 2, + "135": 2, + "136": 1, + "137": 1, + "138": 2, + "139": -1, + "140": -1, + "141": 1, + "142": 1, + "143": 1 + }, + "c2s": { + "0": 3, + "1": 2, + "2": 3, + "3": 3, + "4": 1, + "5": 2, + "6": 1, + "7": 1, + "8": 1, + "9": 1, + "10": 1, + "11": 7, + "12": 3, + "13": 2, + "14": 1, + "15": 1, + "16": 0, + "17": 1, + "18": 1, + "19": 3, + "20": 3, + "21": 1, + "22": 3, + "23": 1, + "24": 3, + "25": 3, + "26": 2, + "27": 7, + "28": -1, + "29": 1, + "30": 2, + "31": 2, + "32": 2, + "33": 2, + "34": 2, + "35": 2, + "36": 1, + "37": 1, + "38": -1, + "39": 3, + "40": 3, + "41": 1, + "42": 1, + "43": 1, + "44": 7, + "45": -1, + "46": 2, + "47": 3, + "48": 3, + "49": 3, + "50": -1, + "51": -1, + "52": 3, + "53": 3, + "54": 3, + "55": 3, + "56": 3, + "57": 3, + "58": 1, + "59": 3, + "60": 3, + "61": 3, + "62": 7, + "63": 3, + "64": 3, + "65": 3, + "66": 2, + "67": 2, + "68": 1 + } + }, "1073741953": { "s2c": { "0": -2147483648, diff --git a/fabric/src/main/java/com/ishland/raknetify/fabric/RaknetifyFabric.java b/fabric/src/main/java/com/ishland/raknetify/fabric/RaknetifyFabric.java index 53c3e53..9753b64 100644 --- a/fabric/src/main/java/com/ishland/raknetify/fabric/RaknetifyFabric.java +++ b/fabric/src/main/java/com/ishland/raknetify/fabric/RaknetifyFabric.java @@ -226,6 +226,11 @@ record FieldNodeClazzPair(FieldNode fieldNode, Class clazz) { .setPrettyPrinting() .create(); ProtocolMultiChannelMappings mappings = new ProtocolMultiChannelMappings(); + // Preserve proxy mappings for versions no longer supported by Fabric. + for (int protocol : new int[]{755, 756}) { + final ProtocolMultiChannelMappings.VersionMapping retained = ProtocolMultiChannelMappings.INSTANCE.mappings.get(protocol); + if (retained != null) mappings.mappings.put(protocol, retained); + } Path path = Path.of("channelMappings.json"); try { mappings = gson.fromJson(Files.readString(path), ProtocolMultiChannelMappings.class);