Remapper does not need a plugin now.
This commit is contained in:
parent
ac871c63d3
commit
9d1be58b04
@ -6,7 +6,6 @@ import io.izzel.arclight.api.EnumHelper;
|
|||||||
import io.izzel.arclight.api.Unsafe;
|
import io.izzel.arclight.api.Unsafe;
|
||||||
import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger;
|
import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger;
|
||||||
import io.izzel.arclight.common.mod.util.log.ArclightLazyLogManager;
|
import io.izzel.arclight.common.mod.util.log.ArclightLazyLogManager;
|
||||||
import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper;
|
|
||||||
import io.izzel.arclight.common.util.EnumTypeFactory;
|
import io.izzel.arclight.common.util.EnumTypeFactory;
|
||||||
import io.izzel.arclight.i18n.ArclightConfig;
|
import io.izzel.arclight.i18n.ArclightConfig;
|
||||||
import io.izzel.arclight.i18n.ArclightLocale;
|
import io.izzel.arclight.i18n.ArclightLocale;
|
||||||
@ -14,7 +13,6 @@ import net.minecraftforge.server.ServerMain;
|
|||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.jar.Attributes;
|
import java.util.jar.Attributes;
|
||||||
import java.util.jar.Manifest;
|
import java.util.jar.Manifest;
|
||||||
|
|
||||||
@ -38,8 +36,6 @@ public abstract class ArclightMain {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
printLogo();
|
printLogo();
|
||||||
ArclightI18nLogger.getLogger("Arclight").info("loading-mapping");
|
|
||||||
Objects.requireNonNull(ArclightRemapper.INSTANCE);
|
|
||||||
this.beforeStart();
|
this.beforeStart();
|
||||||
this.dirtyHacks();
|
this.dirtyHacks();
|
||||||
ServerMain.main(args);
|
ServerMain.main(args);
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import com.google.common.io.ByteStreams;
|
|||||||
import io.izzel.arclight.common.asm.SwitchTableFixer;
|
import io.izzel.arclight.common.asm.SwitchTableFixer;
|
||||||
import io.izzel.arclight.common.bridge.bukkit.JavaPluginLoaderBridge;
|
import io.izzel.arclight.common.bridge.bukkit.JavaPluginLoaderBridge;
|
||||||
import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper;
|
import io.izzel.arclight.common.mod.util.remapper.ArclightRemapper;
|
||||||
import io.izzel.arclight.common.mod.util.remapper.PluginRemapper;
|
import io.izzel.arclight.common.mod.util.remapper.ClassLoaderRemapper;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
import org.bukkit.plugin.java.JavaPluginLoader;
|
||||||
@ -36,7 +36,7 @@ public class PluginClassLoaderMixin extends URLClassLoader {
|
|||||||
@Shadow @Final private URL url;
|
@Shadow @Final private URL url;
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
private PluginRemapper remapper;
|
private ClassLoaderRemapper remapper;
|
||||||
|
|
||||||
public PluginClassLoaderMixin(URL[] urls) {
|
public PluginClassLoaderMixin(URL[] urls) {
|
||||||
super(urls);
|
super(urls);
|
||||||
@ -74,7 +74,7 @@ public class PluginClassLoaderMixin extends URLClassLoader {
|
|||||||
classBytes = SwitchTableFixer.INSTANCE.processClass(classBytes);
|
classBytes = SwitchTableFixer.INSTANCE.processClass(classBytes);
|
||||||
classBytes = Bukkit.getUnsafe().processClass(description, path, classBytes);
|
classBytes = Bukkit.getUnsafe().processClass(description, path, classBytes);
|
||||||
if (remapper == null) {
|
if (remapper == null) {
|
||||||
remapper = ArclightRemapper.INSTANCE.createPluginRemapper(this.loader, this);
|
remapper = ArclightRemapper.INSTANCE.createClassLoaderRemapper(this);
|
||||||
}
|
}
|
||||||
classBytes = remapper.remapClass(classBytes);
|
classBytes = remapper.remapClass(classBytes);
|
||||||
|
|
||||||
|
|||||||
@ -16,14 +16,20 @@ import java.util.HashSet;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class ArclightInterfaceInvokerGen {
|
public class ArclightInterfaceInvokerGen implements PluginTransformer {
|
||||||
|
|
||||||
|
public static final ArclightInterfaceInvokerGen INSTANCE = new ArclightInterfaceInvokerGen();
|
||||||
private static final String PREFIX = "net/minecraft/";
|
private static final String PREFIX = "net/minecraft/";
|
||||||
|
|
||||||
public static void generate(ClassNode classNode, ClassRepo classRepo, PluginRemapper remapper, InheritanceProvider inheritanceProvider) {
|
@Override
|
||||||
|
public void handleClass(ClassNode node, ClassLoaderRemapper remapper) {
|
||||||
|
generate(node, remapper, GlobalClassRepo.inheritanceProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void generate(ClassNode classNode, ClassLoaderRemapper remapper, InheritanceProvider inheritanceProvider) {
|
||||||
if (shouldGenerate(classNode.name, inheritanceProvider)) {
|
if (shouldGenerate(classNode.name, inheritanceProvider)) {
|
||||||
HashSet<Map.Entry<String, String>> set = new HashSet<>();
|
HashSet<Map.Entry<String, String>> set = new HashSet<>();
|
||||||
interfaceMethods(classNode.name, set, classRepo);
|
interfaceMethods(classNode.name, set, GlobalClassRepo.INSTANCE);
|
||||||
for (Map.Entry<String, String> entry : set) {
|
for (Map.Entry<String, String> entry : set) {
|
||||||
String name = entry.getKey();
|
String name = entry.getKey();
|
||||||
String desc = entry.getValue();
|
String desc = entry.getValue();
|
||||||
@ -47,7 +53,7 @@ public class ArclightInterfaceInvokerGen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MethodNode generateSynthetic(String name, String desc, MethodInsnNode node, PluginRemapper remapper) {
|
private static MethodNode generateSynthetic(String name, String desc, MethodInsnNode node, ClassLoaderRemapper remapper) {
|
||||||
name = remapper.mapType(name);
|
name = remapper.mapType(name);
|
||||||
MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, name, desc, null, null);
|
MethodNode methodNode = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, name, desc, null, null);
|
||||||
methodNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
methodNode.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0));
|
||||||
|
|||||||
@ -17,10 +17,11 @@ import java.util.ListIterator;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ArclightRedirectAdapter {
|
public class ArclightRedirectAdapter implements PluginTransformer {
|
||||||
|
|
||||||
private static String REPLACED_NAME = Type.getInternalName(ArclightReflectionHandler.class);
|
public static final ArclightRedirectAdapter INSTANCE = new ArclightRedirectAdapter();
|
||||||
private static Map<MethodInsnNode, MethodInsnNode> methodRedirects = ImmutableMap
|
private static final String REPLACED_NAME = Type.getInternalName(ArclightReflectionHandler.class);
|
||||||
|
private static final Map<MethodInsnNode, MethodInsnNode> METHOD_REDIRECTS = ImmutableMap
|
||||||
.<MethodInsnNode, MethodInsnNode>builder()
|
.<MethodInsnNode, MethodInsnNode>builder()
|
||||||
.put(
|
.put(
|
||||||
method(Opcodes.INVOKEVIRTUAL, Field.class, "getName"),
|
method(Opcodes.INVOKEVIRTUAL, Field.class, "getName"),
|
||||||
@ -104,14 +105,19 @@ public class ArclightRedirectAdapter {
|
|||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static void redirect(ClassNode classNode, String generatedOwner) {
|
@Override
|
||||||
|
public void handleClass(ClassNode node, ClassLoaderRemapper remapper) {
|
||||||
|
redirect(node, remapper.getGeneratedHandler());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void redirect(ClassNode classNode, String generatedOwner) {
|
||||||
for (MethodNode methodNode : classNode.methods) {
|
for (MethodNode methodNode : classNode.methods) {
|
||||||
ListIterator<AbstractInsnNode> iterator = methodNode.instructions.iterator();
|
ListIterator<AbstractInsnNode> iterator = methodNode.instructions.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
AbstractInsnNode insnNode = iterator.next();
|
AbstractInsnNode insnNode = iterator.next();
|
||||||
if (insnNode instanceof MethodInsnNode) {
|
if (insnNode instanceof MethodInsnNode) {
|
||||||
MethodInsnNode from = (MethodInsnNode) insnNode;
|
MethodInsnNode from = (MethodInsnNode) insnNode;
|
||||||
for (Map.Entry<MethodInsnNode, MethodInsnNode> entry : methodRedirects.entrySet()) {
|
for (Map.Entry<MethodInsnNode, MethodInsnNode> entry : METHOD_REDIRECTS.entrySet()) {
|
||||||
MethodInsnNode key = entry.getKey();
|
MethodInsnNode key = entry.getKey();
|
||||||
if (
|
if (
|
||||||
key.getOpcode() == from.getOpcode() &&
|
key.getOpcode() == from.getOpcode() &&
|
||||||
@ -151,5 +157,4 @@ public class ArclightRedirectAdapter {
|
|||||||
String desc = Type.getMethodDescriptor(method);
|
String desc = Type.getMethodDescriptor(method);
|
||||||
return new MethodInsnNode(opcode, owner, name, desc);
|
return new MethodInsnNode(opcode, owner, name, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,21 +3,23 @@ package io.izzel.arclight.common.mod.util.remapper;
|
|||||||
import com.google.common.collect.BiMap;
|
import com.google.common.collect.BiMap;
|
||||||
import com.google.common.collect.HashBiMap;
|
import com.google.common.collect.HashBiMap;
|
||||||
import io.izzel.arclight.api.Unsafe;
|
import io.izzel.arclight.api.Unsafe;
|
||||||
|
import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger;
|
||||||
import net.md_5.specialsource.InheritanceMap;
|
import net.md_5.specialsource.InheritanceMap;
|
||||||
import net.md_5.specialsource.JarMapping;
|
import net.md_5.specialsource.JarMapping;
|
||||||
import net.md_5.specialsource.provider.ClassLoaderProvider;
|
import net.md_5.specialsource.provider.ClassLoaderProvider;
|
||||||
import net.md_5.specialsource.provider.JointProvider;
|
import net.md_5.specialsource.provider.JointProvider;
|
||||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.URLClassLoader;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class ArclightRemapper {
|
public class ArclightRemapper {
|
||||||
|
|
||||||
public static final ArclightRemapper INSTANCE;
|
public static final ArclightRemapper INSTANCE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
ArclightI18nLogger.getLogger("Arclight").info("loading-mapping");
|
||||||
try {
|
try {
|
||||||
INSTANCE = new ArclightRemapper();
|
INSTANCE = new ArclightRemapper();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -28,6 +30,7 @@ public class ArclightRemapper {
|
|||||||
private final JarMapping toNmsMapping;
|
private final JarMapping toNmsMapping;
|
||||||
private final JarMapping toBukkitMapping;
|
private final JarMapping toBukkitMapping;
|
||||||
public final InheritanceMap inheritanceMap;
|
public final InheritanceMap inheritanceMap;
|
||||||
|
private final List<PluginTransformer> transformerList = new ArrayList<>();
|
||||||
|
|
||||||
public ArclightRemapper() throws Exception {
|
public ArclightRemapper() throws Exception {
|
||||||
this.toNmsMapping = new JarMapping();
|
this.toNmsMapping = new JarMapping();
|
||||||
@ -50,10 +53,16 @@ public class ArclightRemapper {
|
|||||||
inheritanceProvider.add(new ClassLoaderProvider(ClassLoader.getSystemClassLoader()));
|
inheritanceProvider.add(new ClassLoaderProvider(ClassLoader.getSystemClassLoader()));
|
||||||
this.toNmsMapping.setFallbackInheritanceProvider(inheritanceProvider);
|
this.toNmsMapping.setFallbackInheritanceProvider(inheritanceProvider);
|
||||||
this.toBukkitMapping.setFallbackInheritanceProvider(inheritanceProvider);
|
this.toBukkitMapping.setFallbackInheritanceProvider(inheritanceProvider);
|
||||||
|
this.transformerList.add(ArclightInterfaceInvokerGen.INSTANCE);
|
||||||
|
this.transformerList.add(ArclightRedirectAdapter.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PluginRemapper createPluginRemapper(JavaPluginLoader loader, URLClassLoader plugin) {
|
public ClassLoaderRemapper createClassLoaderRemapper(ClassLoader classLoader) {
|
||||||
return new PluginRemapper(copyOf(toNmsMapping), copyOf(toBukkitMapping), loader, plugin);
|
return new ClassLoaderRemapper(copyOf(toNmsMapping), copyOf(toBukkitMapping), classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PluginTransformer> getTransformerList() {
|
||||||
|
return transformerList;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long pkgOffset, clOffset, mdOffset, fdOffset, mapOffset;
|
private static long pkgOffset, clOffset, mdOffset, fdOffset, mapOffset;
|
||||||
|
|||||||
@ -4,15 +4,14 @@ import com.google.common.base.Preconditions;
|
|||||||
import com.google.common.collect.BiMap;
|
import com.google.common.collect.BiMap;
|
||||||
import com.google.common.collect.HashBiMap;
|
import com.google.common.collect.HashBiMap;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import io.izzel.arclight.common.mod.util.remapper.generated.ArclightReflectionHandler;
|
|
||||||
import io.izzel.arclight.api.Unsafe;
|
import io.izzel.arclight.api.Unsafe;
|
||||||
|
import io.izzel.arclight.common.mod.util.remapper.generated.ArclightReflectionHandler;
|
||||||
import net.md_5.specialsource.JarMapping;
|
import net.md_5.specialsource.JarMapping;
|
||||||
import net.md_5.specialsource.JarRemapper;
|
import net.md_5.specialsource.JarRemapper;
|
||||||
import net.md_5.specialsource.RemappingClassAdapter;
|
import net.md_5.specialsource.RemappingClassAdapter;
|
||||||
import net.md_5.specialsource.repo.ClassRepo;
|
import net.md_5.specialsource.repo.ClassRepo;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.ClassWriter;
|
import org.objectweb.asm.ClassWriter;
|
||||||
@ -27,7 +26,6 @@ import org.spongepowered.asm.service.MixinService;
|
|||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -36,33 +34,30 @@ import java.util.Objects;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public class PluginRemapper extends JarRemapper {
|
public class ClassLoaderRemapper extends JarRemapper {
|
||||||
|
|
||||||
private static final Logger LOGGER = LogManager.getLogger("Arclight");
|
private static final Logger LOGGER = LogManager.getLogger("Arclight");
|
||||||
private static final String PREFIX = "net/minecraft/";
|
private static final String PREFIX = "net/minecraft/";
|
||||||
|
|
||||||
private final PluginInheritanceProvider inheritanceProvider;
|
|
||||||
private final ClassRepo classRepo;
|
|
||||||
private final JarMapping toBukkitMapping;
|
private final JarMapping toBukkitMapping;
|
||||||
private final JarRemapper toBukkitRemapper;
|
private final JarRemapper toBukkitRemapper;
|
||||||
private final URLClassLoader plugin;
|
private final ClassLoader classLoader;
|
||||||
private final String generatedHandler;
|
private final String generatedHandler;
|
||||||
|
|
||||||
public PluginRemapper(JarMapping jarMapping, JarMapping toBukkitMapping, JavaPluginLoader loader, URLClassLoader plugin) {
|
public ClassLoaderRemapper(JarMapping jarMapping, JarMapping toBukkitMapping, ClassLoader classLoader) {
|
||||||
super(jarMapping);
|
super(jarMapping);
|
||||||
this.toBukkitMapping = toBukkitMapping;
|
this.toBukkitMapping = toBukkitMapping;
|
||||||
this.plugin = plugin;
|
this.classLoader = classLoader;
|
||||||
this.classRepo = SharedClassRepo.get(loader, plugin);
|
|
||||||
this.inheritanceProvider = new PluginInheritanceProvider(this.classRepo);
|
|
||||||
this.jarMapping.setInheritanceMap(ArclightRemapper.INSTANCE.inheritanceMap);
|
this.jarMapping.setInheritanceMap(ArclightRemapper.INSTANCE.inheritanceMap);
|
||||||
this.jarMapping.setFallbackInheritanceProvider(this.inheritanceProvider);
|
this.jarMapping.setFallbackInheritanceProvider(GlobalClassRepo.inheritanceProvider());
|
||||||
this.toBukkitMapping.setFallbackInheritanceProvider(this.inheritanceProvider);
|
this.toBukkitMapping.setFallbackInheritanceProvider(GlobalClassRepo.inheritanceProvider());
|
||||||
this.toBukkitRemapper = new JarRemapper(this.toBukkitMapping);
|
this.toBukkitRemapper = new JarRemapper(this.toBukkitMapping);
|
||||||
this.generatedHandler = generateReflectionHandler();
|
this.generatedHandler = generateReflectionHandler();
|
||||||
|
GlobalClassRepo.INSTANCE.addRepo(new ClassLoaderRepo(this.classLoader));
|
||||||
}
|
}
|
||||||
|
|
||||||
public URLClassLoader getPluginClassLoader() {
|
public ClassLoader getClassLoader() {
|
||||||
return plugin;
|
return classLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JarMapping toBukkitMapping() {
|
public JarMapping toBukkitMapping() {
|
||||||
@ -77,8 +72,8 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
return toBukkitRemapper;
|
return toBukkitRemapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ClassRepo getClassRepo() {
|
public String getGeneratedHandler() {
|
||||||
return classRepo;
|
return generatedHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BiMap: srg -> bukkit
|
// BiMap: srg -> bukkit
|
||||||
@ -204,7 +199,7 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
private boolean shouldRemap(String internalName) {
|
private boolean shouldRemap(String internalName) {
|
||||||
Boolean b = cacheRemap.get(internalName);
|
Boolean b = cacheRemap.get(internalName);
|
||||||
if (b != null) return b;
|
if (b != null) return b;
|
||||||
for (String s : inheritanceProvider.getAll(internalName)) {
|
for (String s : GlobalClassRepo.inheritanceProvider().getAll(internalName)) {
|
||||||
if (s.startsWith(PREFIX)) {
|
if (s.startsWith(PREFIX)) {
|
||||||
cacheRemap.put(internalName, true);
|
cacheRemap.put(internalName, true);
|
||||||
return true;
|
return true;
|
||||||
@ -230,7 +225,7 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
if (ArclightRemapper.INSTANCE.inheritanceMap.hasParents(owner)) {
|
if (ArclightRemapper.INSTANCE.inheritanceMap.hasParents(owner)) {
|
||||||
parents = ArclightRemapper.INSTANCE.inheritanceMap.getParents(owner);
|
parents = ArclightRemapper.INSTANCE.inheritanceMap.getParents(owner);
|
||||||
} else {
|
} else {
|
||||||
parents = this.inheritanceProvider.getParents(owner);
|
parents = GlobalClassRepo.inheritanceProvider().getParents(owner);
|
||||||
ArclightRemapper.INSTANCE.inheritanceMap.setParents(owner, parents);
|
ArclightRemapper.INSTANCE.inheritanceMap.setParents(owner, parents);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +244,7 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte[] remapClass(byte[] arr) {
|
public byte[] remapClass(byte[] arr) {
|
||||||
return remapClassFile(arr, classRepo);
|
return remapClassFile(arr, GlobalClassRepo.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -262,8 +257,9 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
RemappingClassAdapter mapper = new RemappingClassAdapter(node, this, repo);
|
RemappingClassAdapter mapper = new RemappingClassAdapter(node, this, repo);
|
||||||
reader.accept(mapper, ClassReader.SKIP_FRAMES);
|
reader.accept(mapper, ClassReader.SKIP_FRAMES);
|
||||||
|
|
||||||
ArclightRedirectAdapter.redirect(node, generatedHandler);
|
for (PluginTransformer transformer : ArclightRemapper.INSTANCE.getTransformerList()) {
|
||||||
ArclightInterfaceInvokerGen.generate(node, this.classRepo, this, this.inheritanceProvider);
|
transformer.handleClass(node, this);
|
||||||
|
}
|
||||||
|
|
||||||
// 有的插件的编译器奇奇怪怪的,所以在这里要重新计算 frame
|
// 有的插件的编译器奇奇怪怪的,所以在这里要重新计算 frame
|
||||||
ClassWriter wr = new PluginClassWriter(ClassWriter.COMPUTE_FRAMES);
|
ClassWriter wr = new PluginClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||||
@ -272,14 +268,14 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
return wr.toByteArray();
|
return wr.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AtomicInteger atomicInteger = new AtomicInteger();
|
private static final AtomicInteger COUNTER = new AtomicInteger();
|
||||||
|
|
||||||
private String generateReflectionHandler() {
|
private String generateReflectionHandler() {
|
||||||
try {
|
try {
|
||||||
ClassNode node = MixinService.getService().getBytecodeProvider().getClassNode(Type.getInternalName(ArclightReflectionHandler.class));
|
ClassNode node = MixinService.getService().getBytecodeProvider().getClassNode(Type.getInternalName(ArclightReflectionHandler.class));
|
||||||
Preconditions.checkNotNull(node, "node");
|
Preconditions.checkNotNull(node, "node");
|
||||||
ClassWriter writer = new ClassWriter(0);
|
ClassWriter writer = new ClassWriter(0);
|
||||||
String name = Type.getInternalName(ArclightReflectionHandler.class) + "_" + atomicInteger.getAndIncrement();
|
String name = Type.getInternalName(ArclightReflectionHandler.class) + "_" + COUNTER.getAndIncrement();
|
||||||
ClassVisitor visitor = new ClassRemapper(writer, new NameRemapper(name));
|
ClassVisitor visitor = new ClassRemapper(writer, new NameRemapper(name));
|
||||||
node.accept(visitor);
|
node.accept(visitor);
|
||||||
byte[] bytes = writer.toByteArray();
|
byte[] bytes = writer.toByteArray();
|
||||||
@ -296,7 +292,7 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
|
|
||||||
private static class NameRemapper extends Remapper {
|
private static class NameRemapper extends Remapper {
|
||||||
|
|
||||||
private static String origin = Type.getInternalName(ArclightReflectionHandler.class);
|
private static final String ORIGIN = Type.getInternalName(ArclightReflectionHandler.class);
|
||||||
|
|
||||||
private final String internal;
|
private final String internal;
|
||||||
|
|
||||||
@ -306,14 +302,14 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String mapType(String internalName) {
|
public String mapType(String internalName) {
|
||||||
if (internalName.equals(origin)) {
|
if (internalName.equals(ORIGIN)) {
|
||||||
return internal;
|
return internal;
|
||||||
}
|
}
|
||||||
return super.mapType(internalName);
|
return super.mapType(internalName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PluginClassWriter extends ClassWriter {
|
private static class PluginClassWriter extends ClassWriter {
|
||||||
|
|
||||||
public PluginClassWriter(int flags) {
|
public PluginClassWriter(int flags) {
|
||||||
super(flags);
|
super(flags);
|
||||||
@ -321,11 +317,11 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getCommonSuperClass(String type1, String type2) {
|
protected String getCommonSuperClass(String type1, String type2) {
|
||||||
Collection<String> parents = inheritanceProvider.getAll(type2);
|
Collection<String> parents = GlobalClassRepo.inheritanceProvider().getAll(type2);
|
||||||
if (parents.contains(type1)) {
|
if (parents.contains(type1)) {
|
||||||
return type1;
|
return type1;
|
||||||
}
|
}
|
||||||
if (inheritanceProvider.getAll(type1).contains(type2)) {
|
if (GlobalClassRepo.inheritanceProvider().getAll(type1).contains(type2)) {
|
||||||
return type2;
|
return type2;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
@ -335,7 +331,7 @@ public class PluginRemapper extends JarRemapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getSuper(final String typeName) {
|
private String getSuper(final String typeName) {
|
||||||
ClassNode node = classRepo.findClass(typeName);
|
ClassNode node = GlobalClassRepo.INSTANCE.findClass(typeName);
|
||||||
if (node == null) return "java/lang/Object";
|
if (node == null) return "java/lang/Object";
|
||||||
return node.superName;
|
return node.superName;
|
||||||
}
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package io.izzel.arclight.common.mod.util.remapper;
|
||||||
|
|
||||||
|
import net.md_5.specialsource.repo.ClassRepo;
|
||||||
|
import org.objectweb.asm.ClassReader;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
|
||||||
|
public class ClassLoaderRepo implements ClassRepo {
|
||||||
|
|
||||||
|
private final ClassLoader classLoader;
|
||||||
|
|
||||||
|
public ClassLoaderRepo(ClassLoader classLoader) {
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassNode findClass(String internalName) {
|
||||||
|
URL url = classLoader.getResource(internalName + ".class");
|
||||||
|
if (url == null) return null;
|
||||||
|
try {
|
||||||
|
URLConnection connection = url.openConnection();
|
||||||
|
try (InputStream inputStream = connection.getInputStream()) {
|
||||||
|
ClassReader reader = new ClassReader(inputStream);
|
||||||
|
ClassNode classNode = new ClassNode();
|
||||||
|
reader.accept(classNode, ClassReader.SKIP_CODE);
|
||||||
|
return classNode;
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
package io.izzel.arclight.common.mod.util.remapper;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import net.md_5.specialsource.repo.ClassRepo;
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
import org.spongepowered.asm.service.MixinService;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class GlobalClassRepo implements ClassRepo {
|
||||||
|
|
||||||
|
public static final GlobalClassRepo INSTANCE = new GlobalClassRepo();
|
||||||
|
private static final PluginInheritanceProvider PROVIDER = new PluginInheritanceProvider(INSTANCE);
|
||||||
|
|
||||||
|
private final LoadingCache<String, ClassNode> cache = CacheBuilder.newBuilder().maximumSize(65536).build(CacheLoader.from(this::findParallel));
|
||||||
|
private final Set<ClassRepo> repos = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||||
|
|
||||||
|
private GlobalClassRepo() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassNode findClass(String internalName) {
|
||||||
|
try {
|
||||||
|
return cache.get(internalName);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClassNode findParallel(String internalName) {
|
||||||
|
return this.repos.parallelStream()
|
||||||
|
.map(it -> it.findClass(internalName))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.findAny()
|
||||||
|
.orElseGet(() -> this.findMinecraft(internalName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClassNode findMinecraft(String internalName) {
|
||||||
|
try {
|
||||||
|
return MixinService.getService().getBytecodeProvider().getClassNode(internalName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(internalName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRepo(ClassRepo repo) {
|
||||||
|
this.repos.add(repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRepo(ClassRepo repo) {
|
||||||
|
this.repos.remove(repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PluginInheritanceProvider inheritanceProvider() {
|
||||||
|
return PROVIDER;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,34 +0,0 @@
|
|||||||
package io.izzel.arclight.common.mod.util.remapper;
|
|
||||||
|
|
||||||
import io.izzel.arclight.common.bridge.bukkit.JavaPluginLoaderBridge;
|
|
||||||
import net.md_5.specialsource.repo.ClassRepo;
|
|
||||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
|
||||||
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
|
|
||||||
public class PluginClassRepo implements ClassRepo {
|
|
||||||
|
|
||||||
private final SharedClassRepo shared;
|
|
||||||
private JavaPluginLoaderBridge loader;
|
|
||||||
private URLClassLoader plugin;
|
|
||||||
|
|
||||||
protected PluginClassRepo(SharedClassRepo shared, JavaPluginLoader loader, URLClassLoader plugin) {
|
|
||||||
this.shared = shared;
|
|
||||||
this.loader = (JavaPluginLoaderBridge) (Object) loader;
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClassNode findClass(String internalName) {
|
|
||||||
if (plugin == null) return shared.findClass(internalName);
|
|
||||||
if (loader.bridge$getLoaders().contains(plugin)) {
|
|
||||||
plugin = null;
|
|
||||||
}
|
|
||||||
ClassNode node = shared.findClass(internalName);
|
|
||||||
if (node == null && plugin != null) {
|
|
||||||
return shared.findIn(plugin, internalName + ".class");
|
|
||||||
}
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -12,7 +12,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
|
|
||||||
public class PluginInheritanceProvider implements InheritanceProvider {
|
public class PluginInheritanceProvider implements InheritanceProvider {
|
||||||
|
|
||||||
private static Map<String, Collection<String>> sharedInheritanceMap = new ConcurrentHashMap<>();
|
private static final Map<String, Collection<String>> SHARED_INHERITANCE_MAP = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private final ClassRepo classRepo;
|
private final ClassRepo classRepo;
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ public class PluginInheritanceProvider implements InheritanceProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Collection<String> getAll(String className) {
|
public Collection<String> getAll(String className) {
|
||||||
Collection<String> collection = sharedInheritanceMap.get(className);
|
Collection<String> collection = SHARED_INHERITANCE_MAP.get(className);
|
||||||
if (collection != null) return collection;
|
if (collection != null) return collection;
|
||||||
|
|
||||||
ClassNode node = classRepo.findClass(className);
|
ClassNode node = classRepo.findClass(className);
|
||||||
@ -48,7 +48,7 @@ public class PluginInheritanceProvider implements InheritanceProvider {
|
|||||||
parents.add("java/lang/Object");
|
parents.add("java/lang/Object");
|
||||||
}
|
}
|
||||||
|
|
||||||
sharedInheritanceMap.put(className, parents);
|
SHARED_INHERITANCE_MAP.put(className, parents);
|
||||||
return parents;
|
return parents;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,8 @@
|
|||||||
|
package io.izzel.arclight.common.mod.util.remapper;
|
||||||
|
|
||||||
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
|
|
||||||
|
public interface PluginTransformer {
|
||||||
|
|
||||||
|
void handleClass(ClassNode node, ClassLoaderRemapper remapper);
|
||||||
|
}
|
||||||
@ -1,93 +0,0 @@
|
|||||||
package io.izzel.arclight.common.mod.util.remapper;
|
|
||||||
|
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import io.izzel.arclight.common.bridge.bukkit.JavaPluginLoaderBridge;
|
|
||||||
import net.md_5.specialsource.repo.ClassRepo;
|
|
||||||
import org.bukkit.plugin.java.JavaPluginLoader;
|
|
||||||
import org.objectweb.asm.ClassReader;
|
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
|
||||||
import org.spongepowered.asm.service.MixinService;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.net.URLClassLoader;
|
|
||||||
import java.net.URLConnection;
|
|
||||||
|
|
||||||
public class SharedClassRepo implements ClassRepo {
|
|
||||||
|
|
||||||
private static SharedClassRepo classRepo;
|
|
||||||
|
|
||||||
protected final JavaPluginLoaderBridge loader;
|
|
||||||
private final Cache<String, ClassNode> cache = CacheBuilder.newBuilder().maximumSize(65536).build();
|
|
||||||
|
|
||||||
protected SharedClassRepo(JavaPluginLoader loader) {
|
|
||||||
this.loader = ((JavaPluginLoaderBridge) (Object) loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ClassNode findClass(String internalName) {
|
|
||||||
ClassNode ret = cache.getIfPresent(internalName);
|
|
||||||
if (ret != null) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
ret = MixinService.getService().getBytecodeProvider().getClassNode(internalName);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
if (ret == null) {
|
|
||||||
ret = findPlugins(internalName + ".class");
|
|
||||||
}
|
|
||||||
if (ret != null) {
|
|
||||||
cache.put(internalName, ret);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ClassNode findPlugins(String name) {
|
|
||||||
for (URLClassLoader classLoader : loader.bridge$getLoaders()) {
|
|
||||||
ClassNode node = findIn(classLoader, name);
|
|
||||||
if (node != null) return node;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ClassNode findIn(URLClassLoader classLoader, String name) {
|
|
||||||
URL url = HelperClassLoader.find(classLoader, name);
|
|
||||||
if (url == null) return null;
|
|
||||||
try {
|
|
||||||
URLConnection connection = url.openConnection();
|
|
||||||
try (InputStream inputStream = connection.getInputStream()) {
|
|
||||||
ClassReader reader = new ClassReader(inputStream);
|
|
||||||
ClassNode classNode = new ClassNode();
|
|
||||||
reader.accept(classNode, ClassReader.SKIP_CODE);
|
|
||||||
return classNode;
|
|
||||||
}
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ClassRepo get(JavaPluginLoader loader, URLClassLoader plugin) {
|
|
||||||
if (classRepo == null) {
|
|
||||||
synchronized (SharedClassRepo.class) {
|
|
||||||
if (classRepo == null) {
|
|
||||||
classRepo = new SharedClassRepo(loader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new PluginClassRepo(classRepo, loader, plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class HelperClassLoader extends URLClassLoader {
|
|
||||||
|
|
||||||
public HelperClassLoader(URL[] urls) {
|
|
||||||
super(urls);
|
|
||||||
}
|
|
||||||
|
|
||||||
static URL find(URLClassLoader classLoader, String resource) {
|
|
||||||
return classLoader.findResource(resource); // search local
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
package io.izzel.arclight.common.mod.util.remapper.generated;
|
package io.izzel.arclight.common.mod.util.remapper.generated;
|
||||||
|
|
||||||
|
import io.izzel.arclight.common.mod.util.remapper.ClassLoaderRemapper;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import io.izzel.arclight.common.mod.util.remapper.PluginRemapper;
|
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
@ -14,11 +14,11 @@ public class ArclightReflectionHandler {
|
|||||||
|
|
||||||
private static final String PREFIX = "net.minecraft.";
|
private static final String PREFIX = "net.minecraft.";
|
||||||
|
|
||||||
public static PluginRemapper remapper;
|
public static ClassLoaderRemapper remapper;
|
||||||
|
|
||||||
// bukkit -> srg
|
// bukkit -> srg
|
||||||
public static Class<?> redirectForName(String cl) throws ClassNotFoundException {
|
public static Class<?> redirectForName(String cl) throws ClassNotFoundException {
|
||||||
return redirectForName(cl, true, remapper.getPluginClassLoader());
|
return redirectForName(cl, true, remapper.getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
// bukkit -> srg
|
// bukkit -> srg
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import java.nio.file.attribute.BasicFileAttributes
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group 'io.izzel.arclight'
|
group 'io.izzel.arclight'
|
||||||
version '1.0.2'
|
version '1.0.3-SNAPSHOT'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
agpVersion = '1.7'
|
agpVersion = '1.7'
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user