Implement plugin patcher (#63)

This commit is contained in:
IzzelAliz 2020-10-20 13:19:38 +08:00
parent 99d3bce676
commit 2361c206e4
5 changed files with 89 additions and 0 deletions

View File

@ -4,6 +4,7 @@ import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import io.izzel.arclight.api.Unsafe;
import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger;
import io.izzel.arclight.common.mod.util.remapper.patcher.ArclightPluginPatcher;
import net.md_5.specialsource.InheritanceMap;
import net.md_5.specialsource.JarMapping;
import net.md_5.specialsource.provider.ClassLoaderProvider;
@ -56,6 +57,7 @@ public class ArclightRemapper {
this.transformerList.add(ArclightInterfaceInvokerGen.INSTANCE);
this.transformerList.add(ArclightRedirectAdapter.INSTANCE);
this.transformerList.add(ClassLoaderAdapter.INSTANCE);
ArclightPluginPatcher.load(this.transformerList);
}
public static ClassLoaderRemapper createClassLoaderRemapper(ClassLoader classLoader) {

View File

@ -5,4 +5,8 @@ import org.objectweb.asm.tree.ClassNode;
public interface PluginTransformer {
void handleClass(ClassNode node, ClassLoaderRemapper remapper);
default int priority() {
return 0;
}
}

View File

@ -0,0 +1,73 @@
package io.izzel.arclight.common.mod.util.remapper.patcher;
import io.izzel.arclight.common.mod.ArclightMod;
import io.izzel.arclight.common.mod.util.remapper.ClassLoaderRemapper;
import io.izzel.arclight.common.mod.util.remapper.PluginTransformer;
import org.bukkit.configuration.file.YamlConfiguration;
import org.objectweb.asm.tree.ClassNode;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class ArclightPluginPatcher implements PluginTransformer {
private final List<PluginTransformer> list;
public ArclightPluginPatcher(List<PluginTransformer> list) {
this.list = list;
}
@Override
public void handleClass(ClassNode node, ClassLoaderRemapper remapper) {
for (PluginTransformer transformer : list) {
transformer.handleClass(node, remapper);
}
}
public static void load(List<PluginTransformer> transformerList) {
File pluginFolder = new File("plugins");
if (pluginFolder.exists()) {
ArclightMod.LOGGER.info("patcher.loading");
ArrayList<PluginTransformer> list = new ArrayList<>();
for (File file : pluginFolder.listFiles()) {
if (file.isFile() && file.getName().endsWith(".jar")) {
loadFromJar(file.toPath()).ifPresent(list::add);
}
}
if (!list.isEmpty()) {
list.sort(Comparator.comparing(PluginTransformer::priority));
ArclightMod.LOGGER.info("patcher.loaded", list.size());
transformerList.add(new ArclightPluginPatcher(list));
}
}
}
private static Optional<PluginTransformer> loadFromJar(Path path) {
try {
FileSystem fileSystem = FileSystems.newFileSystem(path, ArclightPluginPatcher.class.getClassLoader());
Path pluginYml = fileSystem.getPath("plugin.yml");
if (Files.exists(pluginYml)) {
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(Files.newBufferedReader(pluginYml));
String name = configuration.getString("arclight.patcher");
if (name != null) {
URLClassLoader loader = new URLClassLoader(new URL[]{path.toUri().toURL()}, ArclightPluginPatcher.class.getClassLoader());
Class<?> clazz = Class.forName(name, false, loader);
PluginTransformer transformer = clazz.asSubclass(PluginTransformer.class).newInstance();
return Optional.of(transformer);
}
}
} catch (Exception e) {
ArclightMod.LOGGER.error("patcher.load-error", e);
}
return Optional.empty();
}
}

View File

@ -40,6 +40,11 @@ mixin-load {
optimization = "Arclight optimization mixin added."
}
mod-load = "Arclight Mod loaded."
patcher {
loading = "Loading plugin patchers ..."
loaded = "Loaded {} patchers"
load-error = "Error occurred while loading patcher"
}
registry {
forge-event = "Arclight events registered."
begin = "Regitring for Bukkit ..."

View File

@ -44,6 +44,11 @@ mixin-load {
optimization = "服务端优化 Mixin 配置已加载"
}
mod-load = "Arclight Mod 已加载"
patcher {
loading = "正在加载 Plugin Patcher ..."
loaded = "加载了 {} 个 Patcher"
load-error = "加载 Patcher 时发生错误"
}
registry {
forge-event = "Arclight 事件系统已注册"
begin = "正在向 Bukkit 注册 ..."