From 7a0e44b88c06ea70bdb8f16621b8ee4ad16ac9f6 Mon Sep 17 00:00:00 2001 From: Gardel Date: Mon, 1 Sep 2025 02:06:58 +0800 Subject: [PATCH] feat: 1.21 port --- build.gradle | 13 ++-- common/build.gradle | 2 +- .../InjectYggdrasilAuthenticationService.java | 29 ++------- ...njectYggdrasilMinecraftSessionService.java | 62 +++++++++---------- common/src/main/resources/skinfix.mixins.json | 7 +-- fabric/build.gradle | 4 +- fabric/src/main/resources/fabric.mod.json | 6 +- forge/gradle.properties | 1 - .../skinfix/forge/SkinFixModForge.java | 12 ---- forge/src/main/resources/pack.mcmeta | 6 -- gradle.properties | 6 +- {forge => neoforge}/build.gradle | 27 ++++---- neoforge/gradle.properties | 1 + .../skinfix/neoforge/SkinFixModNeoForge.java | 12 ++++ .../resources/META-INF/neoforge.mods.toml | 14 +++-- settings.gradle | 2 +- 16 files changed, 92 insertions(+), 112 deletions(-) delete mode 100644 forge/gradle.properties delete mode 100644 forge/src/main/java/net/magicterra/skinfix/forge/SkinFixModForge.java delete mode 100644 forge/src/main/resources/pack.mcmeta rename {forge => neoforge}/build.gradle (71%) create mode 100644 neoforge/gradle.properties create mode 100644 neoforge/src/main/java/net/magicterra/skinfix/neoforge/SkinFixModNeoForge.java rename forge/src/main/resources/META-INF/mods.toml => neoforge/src/main/resources/META-INF/neoforge.mods.toml (70%) diff --git a/build.gradle b/build.gradle index 9c034dc..38b60dc 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ plugins { id 'dev.architectury.loom' version '1.11-SNAPSHOT' apply false id 'architectury-plugin' version '3.4-SNAPSHOT' - id 'com.github.johnrengelman.shadow' version '8.1.1' apply false + id 'com.gradleup.shadow' version '8.3.6' apply false } architectury { @@ -31,6 +31,10 @@ subprojects { // for more information about repositories. } + loom { + silentMojangMappingsLicense() + } + dependencies { minecraft "net.minecraft:minecraft:$rootProject.minecraft_version" mappings loom.officialMojangMappings() @@ -42,12 +46,12 @@ subprojects { // If you remove this line, sources will not be generated. withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } tasks.withType(JavaCompile).configureEach { - it.options.release = 17 + it.options.release = 21 } // Configure Maven publishing. @@ -65,6 +69,7 @@ subprojects { // Notice: This block does NOT have the same function as the block in the top level. // The repositories here will be used for publishing your artifact, not for // retrieving dependencies. + mavenLocal() } } } diff --git a/common/build.gradle b/common/build.gradle index 9ef60cb..a1b0cac 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -7,5 +7,5 @@ dependencies { // which get remapped to the correct annotations on each platform. // Do NOT use other classes from Fabric Loader. modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" - compileOnly("com.mojang:authlib:4.0.43") + compileOnly("com.mojang:authlib:6.0.54") } diff --git a/common/src/main/java/net/magicterra/skinfix/inject/InjectYggdrasilAuthenticationService.java b/common/src/main/java/net/magicterra/skinfix/inject/InjectYggdrasilAuthenticationService.java index 4f9bdf6..bac918d 100644 --- a/common/src/main/java/net/magicterra/skinfix/inject/InjectYggdrasilAuthenticationService.java +++ b/common/src/main/java/net/magicterra/skinfix/inject/InjectYggdrasilAuthenticationService.java @@ -3,16 +3,13 @@ package net.magicterra.skinfix.inject; import com.mojang.authlib.Environment; import com.mojang.authlib.EnvironmentParser; import com.mojang.authlib.GameProfileRepository; -import com.mojang.authlib.HttpAuthenticationService; -import com.mojang.authlib.exceptions.AuthenticationException; import com.mojang.authlib.minecraft.MinecraftSessionService; -import com.mojang.authlib.minecraft.UserApiService; +import com.mojang.authlib.minecraft.client.MinecraftClient; import com.mojang.authlib.yggdrasil.ServicesKeySet; import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; import com.mojang.authlib.yggdrasil.YggdrasilEnvironment; import com.mojang.authlib.yggdrasil.YggdrasilGameProfileRepository; import com.mojang.authlib.yggdrasil.YggdrasilServicesKeyInfo; -import com.mojang.authlib.yggdrasil.YggdrasilUserApiService; import java.net.Proxy; import java.net.URL; @@ -37,13 +34,14 @@ public class InjectYggdrasilAuthenticationService extends YggdrasilAuthenticatio super(proxy, environment); this.environment = environment; - final URL publicKeySetUrl = HttpAuthenticationService.constantURL("https://mc.gardel.top/minecraftservices/publickeys"); - this.servicesKeySet = YggdrasilServicesKeyInfo.get(publicKeySetUrl, this); + final MinecraftClient client = MinecraftClient.unauthenticated(proxy); + final URL publicKeySetUrl = constantURL("https://mc.gardel.top/minecraftservices/publickeys"); + this.servicesKeySet = YggdrasilServicesKeyInfo.get(publicKeySetUrl, client); } @Override public MinecraftSessionService createMinecraftSessionService() { - return new InjectYggdrasilMinecraftSessionService(this, environment); + return new InjectYggdrasilMinecraftSessionService(servicesKeySet, getProxy(), environment); } @Override @@ -53,21 +51,6 @@ public class InjectYggdrasilAuthenticationService extends YggdrasilAuthenticatio @Override public GameProfileRepository createProfileRepository() { - return new YggdrasilGameProfileRepository(this, Environment.create( - environment.getAuthHost(), - "https://mc.gardel.top/api", - environment.getSessionHost(), - environment.getServicesHost(), - environment.getName())); - } - - @Override - public UserApiService createUserApiService(String accessToken) throws AuthenticationException { - return new YggdrasilUserApiService(accessToken, getProxy(), Environment.create( - environment.getAuthHost(), - environment.getAccountsHost(), - environment.getSessionHost(), - "https://mc.gardel.top/minecraftservices", - environment.getName())); + return new YggdrasilGameProfileRepository(getProxy(), new Environment(environment.sessionHost(), "https://mc.gardel.top/minecraftservices", environment.name())); } } diff --git a/common/src/main/java/net/magicterra/skinfix/inject/InjectYggdrasilMinecraftSessionService.java b/common/src/main/java/net/magicterra/skinfix/inject/InjectYggdrasilMinecraftSessionService.java index 97a7ced..3eb67dc 100644 --- a/common/src/main/java/net/magicterra/skinfix/inject/InjectYggdrasilMinecraftSessionService.java +++ b/common/src/main/java/net/magicterra/skinfix/inject/InjectYggdrasilMinecraftSessionService.java @@ -1,22 +1,20 @@ package net.magicterra.skinfix.inject; -import com.google.common.collect.Iterables; import com.google.gson.Gson; import com.google.gson.JsonParseException; import com.mojang.authlib.Environment; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.minecraft.InsecurePublicKeyException; +import com.mojang.authlib.SignatureState; import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import com.mojang.authlib.minecraft.MinecraftProfileTextures; import com.mojang.authlib.properties.Property; import com.mojang.authlib.yggdrasil.ServicesKeySet; import com.mojang.authlib.yggdrasil.ServicesKeyType; -import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; import com.mojang.authlib.yggdrasil.response.MinecraftTexturesPayload; import java.lang.reflect.Field; +import java.net.Proxy; import java.nio.charset.StandardCharsets; import java.util.Base64; -import java.util.HashMap; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,12 +26,15 @@ import org.slf4j.LoggerFactory; * @since 2025-04-26 22:11 */ public class InjectYggdrasilMinecraftSessionService extends YggdrasilMinecraftSessionService { - private static final Logger LOGGER = LoggerFactory.getLogger(InjectYggdrasilMinecraftSessionService.class); + private static final Logger LOGGER = LoggerFactory.getLogger(YggdrasilMinecraftSessionService.class); private final Gson gson; - protected InjectYggdrasilMinecraftSessionService(YggdrasilAuthenticationService service, Environment env) { - super(service, env); + private final ServicesKeySet servicesKeySet; + + protected InjectYggdrasilMinecraftSessionService(ServicesKeySet servicesKeySet, Proxy proxy, Environment env) { + super(servicesKeySet, proxy, env); + this.servicesKeySet = servicesKeySet; try { Field field = YggdrasilMinecraftSessionService.class.getDeclaredField("gson"); field.setAccessible(true); @@ -44,52 +45,47 @@ public class InjectYggdrasilMinecraftSessionService extends YggdrasilMinecraftSe } @Override - public Map getTextures(GameProfile profile, boolean requireSecure) throws InsecurePublicKeyException { - final Property textureProperty = Iterables.getFirst(profile.getProperties().get("textures"), null); - - if (textureProperty == null) { - return new HashMap<>(); - } - - final String value = requireSecure ? getSecurePropertyValue(textureProperty) : textureProperty.getValue(); + public MinecraftProfileTextures unpackTextures(Property packedTextures) { + final String value = packedTextures.value(); + final SignatureState signatureState = getPropertySignatureState(packedTextures); final MinecraftTexturesPayload result; try { final String json = new String(Base64.getDecoder().decode(value), StandardCharsets.UTF_8); result = gson.fromJson(json, MinecraftTexturesPayload.class); - } catch (final JsonParseException e) { + } catch (final JsonParseException | IllegalArgumentException e) { LOGGER.error("Could not decode textures payload", e); - return new HashMap<>(); + return MinecraftProfileTextures.EMPTY; } - if (result == null || result.getTextures() == null) { - return new HashMap<>(); + if (result == null || result.textures() == null || result.textures().isEmpty()) { + return MinecraftProfileTextures.EMPTY; } - for (final Map.Entry entry : result.getTextures().entrySet()) { + final Map textures = result.textures(); + for (final Map.Entry entry : textures.entrySet()) { final String url = entry.getValue().getUrl(); if (!InjectTextureUrlChecker.isAllowedTextureDomain(url)) { LOGGER.error("Textures payload contains blocked domain: {}", url); - return new HashMap<>(); + return MinecraftProfileTextures.EMPTY; } } - return result.getTextures(); + return new MinecraftProfileTextures( + textures.get(MinecraftProfileTexture.Type.SKIN), + textures.get(MinecraftProfileTexture.Type.CAPE), + textures.get(MinecraftProfileTexture.Type.ELYTRA), + signatureState + ); } - @Override - public String getSecurePropertyValue(final Property property) throws InsecurePublicKeyException { + private SignatureState getPropertySignatureState(final Property property) { if (!property.hasSignature()) { - LOGGER.error("Signature is missing from Property {}", property.getName()); - throw new InsecurePublicKeyException.MissingException(); + return SignatureState.UNSIGNED; } - - final ServicesKeySet servicesKeySet = getAuthenticationService().getServicesKeySet(); if (servicesKeySet.keys(ServicesKeyType.PROFILE_PROPERTY).stream().noneMatch(key -> key.validateProperty(property))) { - LOGGER.error("Property {} has been tampered with (signature invalid)", property.getName()); - throw new InsecurePublicKeyException.InvalidException("Property has been tampered with (signature invalid)"); + return SignatureState.INVALID; } - - return property.getValue(); + return SignatureState.SIGNED; } } diff --git a/common/src/main/resources/skinfix.mixins.json b/common/src/main/resources/skinfix.mixins.json index 222326b..9fa395c 100644 --- a/common/src/main/resources/skinfix.mixins.json +++ b/common/src/main/resources/skinfix.mixins.json @@ -1,14 +1,13 @@ { "required": true, "package": "net.magicterra.skinfix.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "minVersion": "0.8", "client": [ - "MinecraftMixin" - ], - "mixins": [ + "MinecraftMixin", "ProfilePublicKeyDataMixin" ], + "mixins": [], "injectors": { "defaultRequire": 1 } diff --git a/fabric/build.gradle b/fabric/build.gradle index 23c5f76..62aea1f 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'com.github.johnrengelman.shadow' + id 'com.gradleup.shadow' } architectury { @@ -46,5 +46,5 @@ shadowJar { } remapJar { - input.set shadowJar.archiveFile + inputFile.set shadowJar.archiveFile } diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index 74944d0..41d6484 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -25,9 +25,9 @@ "skinfix.mixins.json" ], "depends": { - "fabricloader": ">=0.17.2", - "minecraft": "~1.20.1", - "java": ">=17" + "fabricloader": ">=0.17", + "minecraft": ">=1.21", + "java": ">=21" }, "suggests": { "another-mod": "*" diff --git a/forge/gradle.properties b/forge/gradle.properties deleted file mode 100644 index 8242585..0000000 --- a/forge/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -loom.platform=forge diff --git a/forge/src/main/java/net/magicterra/skinfix/forge/SkinFixModForge.java b/forge/src/main/java/net/magicterra/skinfix/forge/SkinFixModForge.java deleted file mode 100644 index 8673c3e..0000000 --- a/forge/src/main/java/net/magicterra/skinfix/forge/SkinFixModForge.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.magicterra.skinfix.forge; - -import net.magicterra.skinfix.SkinFixMod; -import net.minecraftforge.fml.common.Mod; - -@Mod(SkinFixMod.MOD_ID) -public final class SkinFixModForge { - public SkinFixModForge() { - // Run our common setup. - SkinFixMod.init(); - } -} diff --git a/forge/src/main/resources/pack.mcmeta b/forge/src/main/resources/pack.mcmeta deleted file mode 100644 index cd937d8..0000000 --- a/forge/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,6 +0,0 @@ -{ - "pack": { - "description": "skinfix resources", - "pack_format": 15 - } -} diff --git a/gradle.properties b/gradle.properties index 468efc0..ef16720 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,9 +5,9 @@ org.gradle.parallel=true mod_version=1.0-SNAPSHOT maven_group=net.magicterra archives_name=skinfix -enabled_platforms=fabric,forge +enabled_platforms=fabric,neoforge # Minecraft properties -minecraft_version=1.20.1 +minecraft_version=1.21 # Dependencies fabric_loader_version=0.17.2 -forge_version=1.20.1-47.4.6 +neoforge_version=21.0.167 diff --git a/forge/build.gradle b/neoforge/build.gradle similarity index 71% rename from forge/build.gradle rename to neoforge/build.gradle index 7f1ea34..fc901bf 100644 --- a/forge/build.gradle +++ b/neoforge/build.gradle @@ -1,16 +1,10 @@ plugins { - id 'com.github.johnrengelman.shadow' -} - -loom { - forge { - mixinConfig "skinfix.mixins.json" - } + id 'com.gradleup.shadow' } architectury { platformSetupLoomIde() - forge() + neoForge() } configurations { @@ -20,7 +14,7 @@ configurations { } compileClasspath.extendsFrom common runtimeClasspath.extendsFrom common - developmentForge.extendsFrom common + developmentNeoForge.extendsFrom common // Files in this configuration will be bundled into your mod using the Shadow plugin. // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files. @@ -30,18 +24,25 @@ configurations { } } +repositories { + maven { + name = 'NeoForged' + url = 'https://maven.neoforged.net/releases' + } +} + dependencies { - forge "net.minecraftforge:forge:$rootProject.forge_version" + neoForge "net.neoforged:neoforge:$rootProject.neoforge_version" common(project(path: ':common', configuration: 'namedElements')) { transitive false } - shadowBundle project(path: ':common', configuration: 'transformProductionForge') + shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge') } processResources { inputs.property 'version', project.version - filesMatching('META-INF/mods.toml') { + filesMatching('META-INF/neoforge.mods.toml') { expand version: project.version } } @@ -52,5 +53,5 @@ shadowJar { } remapJar { - input.set shadowJar.archiveFile + inputFile.set shadowJar.archiveFile } diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties new file mode 100644 index 0000000..7da18ea --- /dev/null +++ b/neoforge/gradle.properties @@ -0,0 +1 @@ +loom.platform=neoforge diff --git a/neoforge/src/main/java/net/magicterra/skinfix/neoforge/SkinFixModNeoForge.java b/neoforge/src/main/java/net/magicterra/skinfix/neoforge/SkinFixModNeoForge.java new file mode 100644 index 0000000..5631e8d --- /dev/null +++ b/neoforge/src/main/java/net/magicterra/skinfix/neoforge/SkinFixModNeoForge.java @@ -0,0 +1,12 @@ +package net.magicterra.skinfix.neoforge; + +import net.magicterra.skinfix.SkinFixMod; +import net.neoforged.fml.common.Mod; + +@Mod(SkinFixMod.MOD_ID) +public final class SkinFixModNeoForge { + public SkinFixModNeoForge() { + // Run our common setup. + SkinFixMod.init(); + } +} diff --git a/forge/src/main/resources/META-INF/mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml similarity index 70% rename from forge/src/main/resources/META-INF/mods.toml rename to neoforge/src/main/resources/META-INF/neoforge.mods.toml index cc2e4c9..b6a1b89 100644 --- a/forge/src/main/resources/META-INF/mods.toml +++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -1,5 +1,5 @@ modLoader = "javafml" -loaderVersion = "[47,)" +loaderVersion = "[1,)" #issueTrackerURL = "" license = "MIT" @@ -14,16 +14,18 @@ Fix Minecraft does not load skin png not prefix with minecraft.net logoFile="assets/skinfix/icon.png" [[dependencies.skinfix]] -modId = "forge" -mandatory = true -versionRange = "[47,)" +modId = "neoforge" +type="required" +versionRange = "[21.0.0-beta,)" ordering = "NONE" side = "BOTH" [[dependencies.skinfix]] modId = "minecraft" -mandatory = true -versionRange = "[1.20.1,)" +type="required" +versionRange = "[1.21,1.21.5)" ordering = "NONE" side = "BOTH" +[[mixins]] +config="skinfix.mixins.json" diff --git a/settings.gradle b/settings.gradle index d5d91cf..b76fefa 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,4 +11,4 @@ rootProject.name = 'skinfix' include 'common' include 'fabric' -include 'forge' +include 'neoforge'