Skip to content

Commit

Permalink
commonSuperClass?
Browse files Browse the repository at this point in the history
  • Loading branch information
Ecdcaeb committed Aug 2, 2024
1 parent 3a10fdb commit ea93cb7
Show file tree
Hide file tree
Showing 4 changed files with 234 additions and 30 deletions.
19 changes: 19 additions & 0 deletions src/main/java/rml/layer/cleanroom/CleanroomLayer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package rml.layer.cleanroom;

import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.versioning.ArtifactVersion;
import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion;
import net.minecraftforge.fml.common.versioning.VersionParser;

/**
* @Project ResourceModLoader
* @Author Hileb
* @Date 2024/8/2 18:44
**/
public class CleanroomLayer {
public static final ArtifactVersion CURRENT_JAVA = new DefaultArtifactVersion(System.getenv().get("java.specification.version"));
public static final ArtifactVersion JAVA_8 = new DefaultArtifactVersion("1.8");
public static boolean isRunningOnCleanroom(){
return CURRENT_JAVA.compareTo(JAVA_8) > 0; // Only Cleanroom could run on higher java version.
}
}
129 changes: 129 additions & 0 deletions src/main/java/rml/layer/cleanroom/LaunchClassLoaderUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package rml.layer.cleanroom;

import it.unimi.dsi.fastutil.ints.Int2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntMaps;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import rml.jrx.reflection.jvm.FieldAccessor;
import rml.jrx.reflection.jvm.MethodAccessor;
import rml.jrx.reflection.jvm.ReflectionHelper;

import java.sql.Ref;
import java.util.Arrays;
import java.util.Map;

/**
* @Project ResourceModLoader
* @Author Hileb
* @Date 2024/8/2 18:49
**/
public class LaunchClassLoaderUtil {
public static final FieldAccessor<Map<String, Class<?>>, LaunchClassLoader> cachedClasses = ReflectionHelper.getFieldAccessor(LaunchClassLoader.class, "cachedClasses");
public static final MethodAccessor<String, LaunchClassLoader> transformName = ReflectionHelper.getMethodAccessor(LaunchClassLoader.class, "transformName", "transformName", String.class);
public static final MethodAccessor<String, LaunchClassLoader> untransformName = ReflectionHelper.getMethodAccessor(LaunchClassLoader.class, "untransformName", "untransformName", String.class);
public static final MethodAccessor<byte[], LaunchClassLoader> getClassBytes = ReflectionHelper.getMethodAccessor(LaunchClassLoader.class, "getClassBytes", "getClassBytes", String.class);
public static final MethodAccessor<byte[], LaunchClassLoader> runTransformers = ReflectionHelper.getMethodAccessor(LaunchClassLoader.class, "runTransformers", "runTransformers", String.class, String.class, byte[].class);


public static byte[] getClassBytes(String name){
LaunchClassLoader classLoader = Launch.classLoader;
String transformedName = transformName.invoke(classLoader, name);
String untransformedName = untransformName.invoke(classLoader, name);
return runTransformers.invoke(classLoader, untransformedName, transformedName, getClassBytes.invoke(classLoader, untransformedName));
}

public static class ClassUtil{
public static String getSuperClass(byte[] clazz){
Int2IntLinkedOpenHashMap _utfs = new Int2IntLinkedOpenHashMap();
Int2IntLinkedOpenHashMap _classes=new Int2IntLinkedOpenHashMap();
int constantsCount=readUnsignedShort(clazz,8);
int passcount=10;
for(int i=1;i<constantsCount;i++){
int size=0;
switch (clazz[passcount]){
case 9:
case 10:
case 11:
case 3:
case 4:
case 12:
case 18:
size = 5;
break;
case 5:
case 6:
size = 9;
break;
case 1://UTF8
int UTFSize = readUnsignedShort(clazz,passcount + 1);
size = 3 + UTFSize;
_utfs.put(i, passcount);
break;
case 15:
size = 4;
break;
case 7://class
size = 3;
int index = readUnsignedShort(clazz,passcount+1);
_classes.put(i, index);
break;
default:
size = 3;
break;
}
passcount += size;

}
passcount += 4;
passcount = readUnsignedShort(clazz,passcount);
passcount = _classes.get(passcount);
passcount = _utfs.get(passcount);
int UTFSize = readUnsignedShort(clazz,passcount + 1);
return readUTF8(clazz,passcount+3,UTFSize);
}
public static int readUnsignedShort(byte[] b, int index) {
return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
}
public static String readUTF8(byte[] b,int index,int length){
return new String(Arrays.copyOfRange(b, index, index+length));
}

public static int getClassModifier(byte[] clazz){
int constantsCount = readUnsignedShort(clazz,8);
int passcount = 10;
for(int i = 1; i < constantsCount; i++){
int size=0;
switch (clazz[passcount]){
case 9:
case 10:
case 11:
case 3:
case 4:
case 12:
case 18:
size = 5;
break;
case 5:
case 6:
size = 9;
break;
case 1:
int UTFSize=readUnsignedShort(clazz,passcount + 1);
size = 3 + UTFSize;
break;
case 15:
size = 4;
break;
default:
size = 3;
break;
}
passcount += size;
}
return readUnsignedShort(clazz, passcount);
}
}


}
38 changes: 16 additions & 22 deletions src/main/java/rml/loader/core/RMLFMLLoadingPlugin.java
Original file line number Diff line number Diff line change
@@ -1,39 +1,20 @@
package rml.loader.core;

import com.cleanroommc.groovyscript.GroovyScript;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import crafttweaker.mc1120.CraftTweaker;
import dev.latvian.kubejs.KubeJS;
import net.minecraftforge.common.config.Config;
import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;
import org.lwjgl.Sys;
import rml.jrx.utils.ClassHelper;
import rml.loader.ResourceModLoader;
import rml.jrx.announces.BeDiscovered;
import rml.jrx.announces.EarlyClass;
import rml.jrx.announces.PrivateAPI;
import rml.jrx.announces.PublicAPI;
import rml.loader.api.RMLBus;
import rml.loader.api.world.text.RMLTextEffects;
import rml.layer.compat.crt.RMLCrTLoader;
import rml.layer.compat.kubejs.RMKKubeJs;
import rml.loader.deserialize.MCDeserializers;
import rml.loader.deserialize.RMLDeserializer;
import rml.loader.deserialize.RMLLoaders;
import rml.loader.deserialize.RMLForgeEventHandler;
import rml.loader.deserialize.craft.recipe.SimpleAnvilRecipe;
import net.minecraft.launchwrapper.Launch;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.DummyModContainer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.LoadController;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.ModContainer;
import net.minecraftforge.fml.common.ModMetadata;
import net.minecraftforge.fml.common.event.FMLConstructionEvent;
import net.minecraftforge.fml.common.event.FMLLoadCompleteEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.relauncher.CoreModManager;
Expand All @@ -42,11 +23,24 @@
import net.minecraftforge.fml.relauncher.Side;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import rml.jrx.announces.EarlyClass;
import rml.jrx.announces.PrivateAPI;
import rml.jrx.announces.PublicAPI;
import rml.jrx.utils.ClassHelper;
import rml.layer.compat.crt.RMLCrTLoader;
import rml.layer.compat.kubejs.RMKKubeJs;
import rml.loader.ResourceModLoader;
import rml.loader.api.RMLBus;
import rml.loader.api.world.text.RMLTextEffects;
import rml.loader.deserialize.MCDeserializers;
import rml.loader.deserialize.RMLDeserializer;
import rml.loader.deserialize.RMLForgeEventHandler;
import rml.loader.deserialize.RMLLoaders;
import rml.loader.deserialize.craft.recipe.SimpleAnvilRecipe;

import javax.annotation.Nullable;
import java.io.File;
import java.util.Map;
import java.util.function.Consumer;

/**
* @Project ResourceModLoader
Expand Down
78 changes: 70 additions & 8 deletions src/main/java/rml/loader/core/RMLTransformer.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
package rml.loader.core;

import crafttweaker.mc1120.CraftTweaker;
import org.objectweb.asm.commons.Remapper;
import rml.jrx.announces.EarlyClass;
import rml.jrx.announces.PrivateAPI;
import rml.jrx.asm.MethodName;
import rml.jrx.utils.Tasks;
import net.minecraft.launchwrapper.IClassTransformer;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.discovery.ASMDataTable;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.*;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.JumpInsnNode;
import org.objectweb.asm.tree.LabelNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;
import org.objectweb.asm.tree.VarInsnNode;
import rml.jrx.announces.EarlyClass;
import rml.jrx.announces.PrivateAPI;
import rml.jrx.asm.MethodName;
import rml.jrx.utils.Tasks;
import rml.layer.cleanroom.LaunchClassLoaderUtil;

import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -79,7 +92,7 @@ public byte[] transform(String name, String transformedName, byte[] basicClass)
}
if (!isTarget) return basicClass;
else {
ClassWriter classWriter = new ClassWriter(classReader, flags);
ClassWriter classWriter = new LaunchClassWriter(classReader, flags);
cn.accept(classWriter);
return ASMUtil.push(transformedName, classWriter.toByteArray());
}
Expand All @@ -91,6 +104,55 @@ public byte[] transform(String name, String transformedName, byte[] basicClass)
}
return basicClass;
}
public static class LaunchClassWriter extends ClassWriter{

public LaunchClassWriter(ClassReader classReader, int flags) {
super(classReader, flags);
}

@Override
protected String getCommonSuperClass(String type1, String type2) {
return getCommonSuperClass0(type1, type2);
}

public static String getCommonSuperClass0(final String type1, final String type2) {
ClassLoader classLoader = LaunchClassLoader.class.getClassLoader();
Class<?> class1;
try {
class1 = Class.forName(type1.replace('/', '.'), false, classLoader);
} catch (ClassNotFoundException e) {
try {
class1 = Class.forName(type1.replace('/', '.'), false, Launch.classLoader);
} catch (ClassNotFoundException e1) {
throw new TypeNotPresentException(type1, e1);
}
}
Class<?> class2;
try {
class2 = Class.forName(type2.replace('/', '.'), false, classLoader);
} catch (ClassNotFoundException e) {
try {
class2 = Class.forName(type2.replace('/', '.'), false, Launch.classLoader);
} catch (ClassNotFoundException e2) {
throw new TypeNotPresentException(type2, e2);
}
}
if (class1.isAssignableFrom(class2)) {
return type1;
}
if (class2.isAssignableFrom(class1)) {
return type2;
}
if (class1.isInterface() || class2.isInterface()) {
return "java/lang/Object";
} else {
do {
class1 = class1.getSuperclass();
} while (!class1.isAssignableFrom(class2));
return class1.getName().replace('.', '/');
}
}
}

/**
* @Project ResourceModLoader
Expand Down Expand Up @@ -392,7 +454,7 @@ public static void initModTransformers(Object[] objects){
list.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "rml/layer/compat/crt/RMLCrTLoader", "inject", "(Lcrafttweaker/runtime/IScriptProvider;)Lcrafttweaker/runtime/IScriptProvider;", false));
list.add(new VarInsnNode(Opcodes.ASTORE, 1)); // provider
mn.instructions.insert(list);
return ClassWriter.COMPUTE_MAXS;
return ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES;
}
}
return -1;
Expand Down

0 comments on commit ea93cb7

Please sign in to comment.