Files
AeroMc-Launcher/agent/src/de/aeromc/capes/Umbau.java
T
2026-10-03 14:20:36 +00:00

79 lines
4.1 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package de.aeromc.capes;
import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* Baut YggdrasilMinecraftSessionService beim Laden um: vor jedem "return" der
* Textur-Methode wird das Ergebnis an den Nachschlage-Dienst gereicht, der den
* AeroMC-Umhang einsetzt.
*
* authlib 5+ (Minecraft 1.20.2 … 26.x):
* MinecraftProfileTextures unpackTextures(Property)
* authlib 1–4 (Minecraft 1.8 … 1.20.1):
* Map<Type, MinecraftProfileTexture> getTextures(GameProfile, boolean)
*
* Eingefügt wird nur geradliniger Code ohne Sprünge – die vorhandenen
* Stack-Map-Frames bleiben gültig, es muss nichts neu berechnet werden.
*/
final class Umbau implements ClassFileTransformer {
static final String ZIEL = "com/mojang/authlib/yggdrasil/YggdrasilMinecraftSessionService";
@Override
public byte[] transform(ClassLoader loader, String name, Class<?> umdefiniert, ProtectionDomain pd, byte[] klasse) {
if (!ZIEL.equals(name) || umdefiniert != null) return null;
try {
ClassReader leser = new ClassReader(klasse);
ClassWriter schreiber = new ClassWriter(leser, ClassWriter.COMPUTE_MAXS);
final int[] umgebaut = {0};
leser.accept(new ClassVisitor(Opcodes.ASM9, schreiber) {
@Override
public MethodVisitor visitMethod(int zugriff, String mname, String desc, String sig, String[] ausn) {
MethodVisitor mv = super.visitMethod(zugriff, mname, desc, sig, ausn);
if ((zugriff & Opcodes.ACC_STATIC) != 0) return mv;
String rueckgabe = null;
if ("unpackTextures".equals(mname) && desc.startsWith("(Lcom/mojang/authlib/properties/Property;)L")) {
rueckgabe = desc.substring(desc.indexOf(")L") + 2, desc.length() - 1);
} else if ("getTextures".equals(mname) && desc.equals("(Lcom/mojang/authlib/GameProfile;Z)Ljava/util/Map;")) {
rueckgabe = "java/util/Map";
}
if (rueckgabe == null) return mv;
umgebaut[0]++;
final String typ = rueckgabe;
return new MethodVisitor(Opcodes.ASM9, mv) {
@Override
public void visitInsn(int op) {
if (op == Opcodes.ARETURN) {
// Stapel: [ergebnis] -> [dienst, ergebnis, argument] -> apply -> [neu]
super.visitVarInsn(Opcodes.ALOAD, 1);
super.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "getProperties", "()Ljava/util/Properties;", false);
super.visitLdcInsn(Agent.SCHLUESSEL);
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/util/Properties", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", false);
super.visitTypeInsn(Opcodes.CHECKCAST, "java/util/function/BiFunction");
super.visitInsn(Opcodes.DUP_X2);
super.visitInsn(Opcodes.POP);
super.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/function/BiFunction", "apply",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true);
super.visitTypeInsn(Opcodes.CHECKCAST, typ);
}
super.visitInsn(op);
}
};
}
}, 0);
if (umgebaut[0] == 0) return null;
System.out.println("[AeroMC] authlib fuer Umhaenge vorbereitet (" + umgebaut[0] + " Methode)");
return schreiber.toByteArray();
} catch (Throwable t) {
System.out.println("[AeroMC] authlib konnte nicht angepasst werden: " + t);
return null;
}
}
}