feat: 1.21 port
This commit is contained in:
13
build.gradle
13
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<MinecraftProfileTexture.Type, MinecraftProfileTexture> 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<MinecraftProfileTexture.Type, MinecraftProfileTexture> entry : result.getTextures().entrySet()) {
|
||||
final Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> textures = result.textures();
|
||||
for (final Map.Entry<MinecraftProfileTexture.Type, MinecraftProfileTexture> 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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": "*"
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
loom.platform=forge
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "skinfix resources",
|
||||
"pack_format": 15
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
1
neoforge/gradle.properties
Normal file
1
neoforge/gradle.properties
Normal file
@@ -0,0 +1 @@
|
||||
loom.platform=neoforge
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -11,4 +11,4 @@ rootProject.name = 'skinfix'
|
||||
|
||||
include 'common'
|
||||
include 'fabric'
|
||||
include 'forge'
|
||||
include 'neoforge'
|
||||
|
||||
Reference in New Issue
Block a user