Implement API
This commit is contained in:
parent
c7bb5dfbf7
commit
a4f015fce6
|
@ -61,8 +61,8 @@ dependencies {
|
|||
implementation 'net.md-5:bungeecord-chat:1.16-R0.4'
|
||||
implementation 'mysql:mysql-connector-java:5.1.49'
|
||||
implementation 'org.yaml:snakeyaml:1.27'
|
||||
implementation 'io.izzel:tools:1.1.+'
|
||||
implementation 'io.izzel.arclight:arclight-api:1.0.+'
|
||||
implementation "io.izzel:tools:$toolsVersion"
|
||||
implementation "io.izzel.arclight:arclight-api:$apiVersion"
|
||||
implementation project(':i18n-config')
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
package io.izzel.arclight.common.mixin.api;
|
||||
|
||||
import io.izzel.arclight.api.Arclight;
|
||||
import io.izzel.arclight.common.mod.util.PluginEventHandler;
|
||||
import net.minecraftforge.eventbus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Overwrite;
|
||||
|
||||
@Mixin(value = Arclight.class, remap = false)
|
||||
public class Arclight_ForgeEventMixin {
|
||||
|
||||
/**
|
||||
* @author IzzelAliz
|
||||
* @reason
|
||||
*/
|
||||
@Overwrite
|
||||
public static void registerForgeEvent(Plugin plugin, IEventBus bus, Object target) throws Throwable {
|
||||
if (bus instanceof EventBus) {
|
||||
PluginEventHandler.register(plugin, (EventBus) bus, target);
|
||||
} else {
|
||||
bus.register(target);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ public class ArclightConnector implements IMixinConnector {
|
|||
|
||||
public static final Logger LOGGER = ArclightI18nLogger.getLogger("Arclight");
|
||||
private static final List<String> FILTER_PACKAGE = Arrays.asList("com.google.common", "com.google.gson", "ninja.leaping.configurate",
|
||||
"io.izzel.arclight.api", "io.izzel.arclight.i18n");
|
||||
"io.izzel.arclight.i18n");
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
|
@ -26,6 +26,7 @@ public class ArclightConnector implements IMixinConnector {
|
|||
Mixins.addConfiguration("mixins.arclight.core.json");
|
||||
Mixins.addConfiguration("mixins.arclight.bukkit.json");
|
||||
Mixins.addConfiguration("mixins.arclight.forge.json");
|
||||
Mixins.addConfiguration("mixins.arclight.api.json");
|
||||
LOGGER.info("mixin-load.core");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.izzel.arclight.common.mod;
|
||||
|
||||
import io.izzel.arclight.api.ArclightVersion;
|
||||
import io.izzel.arclight.common.mod.server.ArclightPermissionHandler;
|
||||
import io.izzel.arclight.common.mod.server.event.ArclightEventDispatcherRegistry;
|
||||
import io.izzel.arclight.common.mod.util.log.ArclightI18nLogger;
|
||||
|
@ -18,6 +19,7 @@ public class ArclightMod {
|
|||
|
||||
public ArclightMod() {
|
||||
LOGGER.info("mod-load");
|
||||
ArclightVersion.setVersion(ArclightVersion.v1_16_4);
|
||||
ArclightEventDispatcherRegistry.registerAllEventDispatchers();
|
||||
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.DISPLAYTEST, () -> Pair.of(() -> FMLNetworkConstants.IGNORESERVERONLY, (a, b) -> true));
|
||||
PermissionAPI.setPermissionHandler(ArclightPermissionHandler.INSTANCE);
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
package io.izzel.arclight.common.mod.util;
|
||||
|
||||
import io.izzel.arclight.api.Unsafe;
|
||||
import io.izzel.arclight.common.mod.ArclightMod;
|
||||
import net.minecraftforge.eventbus.ASMEventHandler;
|
||||
import net.minecraftforge.eventbus.EventBus;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.eventbus.api.EventPriority;
|
||||
import net.minecraftforge.eventbus.api.IEventListener;
|
||||
import net.minecraftforge.eventbus.api.IGenericEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.objectweb.asm.ClassWriter;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Type;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
|
||||
public class PluginEventHandler extends ASMEventHandler {
|
||||
|
||||
private static final String HANDLER_DESC = Type.getInternalName(IEventListener.class);
|
||||
private static final String HANDLER_FUNC_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Event.class));
|
||||
private static final MethodHandle MH_GET_LISTENERS;
|
||||
private static final MethodHandle MH_ADD_LISTENERS;
|
||||
private static final MethodHandle MH_UNIQUE_NAME;
|
||||
|
||||
static {
|
||||
try {
|
||||
MH_GET_LISTENERS = Unsafe.lookup().findGetter(EventBus.class, "listeners", ConcurrentHashMap.class);
|
||||
MH_ADD_LISTENERS = Unsafe.lookup().findVirtual(EventBus.class, "addToListeners", MethodType.methodType(void.class,
|
||||
Object.class, Class.class, IEventListener.class, EventPriority.class));
|
||||
MH_UNIQUE_NAME = Unsafe.lookup().findVirtual(ASMEventHandler.class, "getUniqueName", MethodType.methodType(String.class, Method.class));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final Plugin plugin;
|
||||
|
||||
public PluginEventHandler(Plugin plugin, Object target, Method method, boolean isGeneric) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
|
||||
super(target, method, isGeneric);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void register(Plugin plugin, EventBus bus, Object target) throws Throwable {
|
||||
ConcurrentHashMap<Object, ?> listeners = (ConcurrentHashMap<Object, ?>) MH_GET_LISTENERS.invokeExact(bus);
|
||||
if (!listeners.containsKey(target)) {
|
||||
if (target.getClass() == Class.class) {
|
||||
registerClass((Class<?>) target, plugin, bus);
|
||||
} else {
|
||||
registerObject(target, plugin, bus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerClass(final Class<?> clazz, Plugin plugin, EventBus bus) {
|
||||
Arrays.stream(clazz.getMethods()).
|
||||
filter(m -> Modifier.isStatic(m.getModifiers())).
|
||||
filter(m -> m.isAnnotationPresent(SubscribeEvent.class)).
|
||||
forEach(m -> registerListener(clazz, m, m, plugin, bus));
|
||||
}
|
||||
|
||||
private static Optional<Method> getDeclMethod(final Class<?> clz, final Method in) {
|
||||
try {
|
||||
return Optional.of(clz.getDeclaredMethod(in.getName(), in.getParameterTypes()));
|
||||
} catch (NoSuchMethodException nse) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void registerObject(final Object obj, Plugin plugin, EventBus bus) {
|
||||
final HashSet<Class<?>> classes = new HashSet<>();
|
||||
typesFor(obj.getClass(), classes);
|
||||
Arrays.stream(obj.getClass().getMethods()).
|
||||
filter(m -> !Modifier.isStatic(m.getModifiers())).
|
||||
forEach(m -> classes.stream().
|
||||
map(c -> getDeclMethod(c, m)).
|
||||
filter(rm -> rm.isPresent() && rm.get().isAnnotationPresent(SubscribeEvent.class)).
|
||||
findFirst().
|
||||
ifPresent(rm -> registerListener(obj, m, rm.get(), plugin, bus)));
|
||||
}
|
||||
|
||||
private static void typesFor(final Class<?> clz, final Set<Class<?>> visited) {
|
||||
if (clz.getSuperclass() == null) return;
|
||||
typesFor(clz.getSuperclass(), visited);
|
||||
Arrays.stream(clz.getInterfaces()).forEach(i -> typesFor(i, visited));
|
||||
visited.add(clz);
|
||||
}
|
||||
|
||||
private static void registerListener(final Object target, final Method method, final Method real, Plugin plugin, EventBus bus) {
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
if (parameterTypes.length != 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"Method " + method + " has @SubscribeEvent annotation. " +
|
||||
"It has " + parameterTypes.length + " arguments, " +
|
||||
"but event handler methods require a single argument only."
|
||||
);
|
||||
}
|
||||
|
||||
Class<?> eventType = parameterTypes[0];
|
||||
|
||||
if (!Event.class.isAssignableFrom(eventType)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Method " + method + " has @SubscribeEvent annotation, " +
|
||||
"but takes an argument that is not an Event subtype : " + eventType);
|
||||
}
|
||||
|
||||
register(eventType, target, real, plugin, bus);
|
||||
}
|
||||
|
||||
private static void register(Class<?> eventType, Object target, Method method, Plugin plugin, EventBus bus) {
|
||||
try {
|
||||
ASMEventHandler asm = new PluginEventHandler(plugin, target, method, IGenericEvent.class.isAssignableFrom(eventType));
|
||||
MH_ADD_LISTENERS.invokeExact(bus, target, eventType, (IEventListener) asm, asm.getPriority());
|
||||
} catch (Throwable e) {
|
||||
ArclightMod.LOGGER.error("Error registering event handler: {} {}", eventType, method, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> createWrapper(Method callback) {
|
||||
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
MethodVisitor mv;
|
||||
|
||||
boolean isStatic = Modifier.isStatic(callback.getModifiers());
|
||||
String name;
|
||||
try {
|
||||
name = (String) MH_UNIQUE_NAME.invoke(this, callback);
|
||||
} catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
String desc = name.replace('.', '/');
|
||||
String instType = Type.getInternalName(callback.getDeclaringClass());
|
||||
String eventType = Type.getInternalName(callback.getParameterTypes()[0]);
|
||||
|
||||
cw.visit(V1_6, ACC_PUBLIC | ACC_SUPER, desc, null, "java/lang/Object", new String[]{HANDLER_DESC});
|
||||
|
||||
cw.visitSource(".dynamic", null);
|
||||
{
|
||||
if (!isStatic)
|
||||
cw.visitField(ACC_PUBLIC, "instance", "Ljava/lang/Object;", null, null).visitEnd();
|
||||
}
|
||||
{
|
||||
mv = cw.visitMethod(ACC_PUBLIC, "<init>", isStatic ? "()V" : "(Ljava/lang/Object;)V", null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
if (!isStatic) {
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitFieldInsn(PUTFIELD, desc, "instance", "Ljava/lang/Object;");
|
||||
}
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{
|
||||
mv = cw.visitMethod(ACC_PUBLIC, "invoke", HANDLER_FUNC_DESC, null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
if (!isStatic) {
|
||||
mv.visitFieldInsn(GETFIELD, desc, "instance", "Ljava/lang/Object;");
|
||||
mv.visitTypeInsn(CHECKCAST, instType);
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitTypeInsn(CHECKCAST, eventType);
|
||||
mv.visitMethodInsn(isStatic ? INVOKESTATIC : INVOKEVIRTUAL, instType, callback.getName(), Type.getMethodDescriptor(callback), false);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(2, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
cw.visitEnd();
|
||||
byte[] bytes = cw.toByteArray();
|
||||
return Unsafe.defineClass(name, bytes, 0, bytes.length, plugin.getClass().getClassLoader(), plugin.getClass().getProtectionDomain());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PL:" + plugin.getName() + " " + super.toString();
|
||||
}
|
||||
}
|
|
@ -436,7 +436,7 @@ public class ArclightRedirectAdapter implements PluginTransformer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object[] apply(ClassLoaderRemapper remapper, Method method, Object src, Object[] param) {
|
||||
public Object[] apply4(ClassLoaderRemapper remapper, Method method, Object src, Object[] param) {
|
||||
try {
|
||||
Method handleMethod = remapper.getGeneratedHandlerClass().getMethod(handlerName, handlerArgs);
|
||||
if (method.getParameterCount() > 0) {
|
||||
|
@ -467,7 +467,7 @@ public class ArclightRedirectAdapter implements PluginTransformer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object[] apply(ClassLoaderRemapper remapper, Method method, Object src, Object[] param) {
|
||||
public Object[] apply4(ClassLoaderRemapper remapper, Method method, Object src, Object[] param) {
|
||||
try {
|
||||
Method redirectMethod = remapper.getGeneratedHandlerClass().getMethod(handlerName, handlerArgs);
|
||||
return new Object[]{redirectMethod, null, Modifier.isStatic(method.getModifiers()) ? param : ArrayUtil.prepend(param, src)};
|
||||
|
@ -489,7 +489,7 @@ public class ArclightRedirectAdapter implements PluginTransformer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Object[] apply(ClassLoaderRemapper remapper, Method method, Object src, Object[] param) {
|
||||
public Object[] apply4(ClassLoaderRemapper remapper, Method method, Object src, Object[] param) {
|
||||
boolean bridgeStatic = Modifier.isStatic(targetMethod.getModifiers());
|
||||
if (bridgeStatic) {
|
||||
Object[] ret = bridge.apply(remapper, this.targetMethod, null, param);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package io.izzel.arclight.common.mod.util.remapper;
|
||||
|
||||
import io.izzel.arclight.api.PluginPatcher;
|
||||
import net.md_5.specialsource.repo.ClassRepo;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
|
@ -10,7 +11,7 @@ import java.net.URL;
|
|||
import java.net.URLClassLoader;
|
||||
import java.net.URLConnection;
|
||||
|
||||
public class ClassLoaderRepo implements ClassRepo {
|
||||
public class ClassLoaderRepo implements ClassRepo, PluginPatcher.ClassRepo {
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
|
@ -20,6 +21,11 @@ public class ClassLoaderRepo implements ClassRepo {
|
|||
|
||||
@Override
|
||||
public ClassNode findClass(String internalName) {
|
||||
return findClass(internalName, ClassReader.SKIP_CODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassNode findClass(String internalName, int parsingOptions) {
|
||||
URL url = classLoader instanceof URLClassLoader
|
||||
? ((URLClassLoader) classLoader).findResource(internalName + ".class") // search local
|
||||
: classLoader.getResource(internalName + ".class");
|
||||
|
@ -29,7 +35,7 @@ public class ClassLoaderRepo implements ClassRepo {
|
|||
try (InputStream inputStream = connection.getInputStream()) {
|
||||
ClassReader reader = new ClassReader(inputStream);
|
||||
ClassNode classNode = new ClassNode();
|
||||
reader.accept(classNode, ClassReader.SKIP_CODE);
|
||||
reader.accept(classNode, parsingOptions);
|
||||
return classNode;
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
|
|
|
@ -3,7 +3,9 @@ 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 io.izzel.arclight.api.PluginPatcher;
|
||||
import net.md_5.specialsource.repo.ClassRepo;
|
||||
import org.objectweb.asm.ClassReader;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.spongepowered.asm.service.MixinService;
|
||||
|
||||
|
@ -13,7 +15,7 @@ import java.util.Set;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class GlobalClassRepo implements ClassRepo {
|
||||
public class GlobalClassRepo implements ClassRepo, PluginPatcher.ClassRepo {
|
||||
|
||||
public static final GlobalClassRepo INSTANCE = new GlobalClassRepo();
|
||||
private static final PluginInheritanceProvider PROVIDER = new PluginInheritanceProvider(INSTANCE);
|
||||
|
@ -35,6 +37,21 @@ public class GlobalClassRepo implements ClassRepo {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassNode findClass(String internalName, int parsingOptions) {
|
||||
if (parsingOptions == ClassReader.SKIP_CODE) {
|
||||
return findClass(internalName);
|
||||
} else {
|
||||
return this.repos.parallelStream()
|
||||
.filter(PluginPatcher.ClassRepo.class::isInstance)
|
||||
.map(PluginPatcher.ClassRepo.class::cast)
|
||||
.map(it -> it.findClass(internalName, parsingOptions))
|
||||
.filter(Objects::nonNull)
|
||||
.findAny()
|
||||
.orElseGet(() -> this.findMinecraft(internalName));
|
||||
}
|
||||
}
|
||||
|
||||
private ClassNode findParallel(String internalName) {
|
||||
return this.repos.parallelStream()
|
||||
.map(it -> it.findClass(internalName))
|
||||
|
|
|
@ -1,35 +1,37 @@
|
|||
package io.izzel.arclight.common.mod.util.remapper.patcher;
|
||||
|
||||
import io.izzel.arclight.api.PluginPatcher;
|
||||
import io.izzel.arclight.common.mod.ArclightMod;
|
||||
import io.izzel.arclight.common.mod.util.remapper.ClassLoaderRemapper;
|
||||
import io.izzel.arclight.common.mod.util.remapper.GlobalClassRepo;
|
||||
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.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
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;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
public class ArclightPluginPatcher implements PluginTransformer {
|
||||
|
||||
private final List<PluginTransformer> list;
|
||||
private final List<PluginPatcher> list;
|
||||
|
||||
public ArclightPluginPatcher(List<PluginTransformer> list) {
|
||||
public ArclightPluginPatcher(List<PluginPatcher> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleClass(ClassNode node, ClassLoaderRemapper remapper) {
|
||||
for (PluginTransformer transformer : list) {
|
||||
transformer.handleClass(node, remapper);
|
||||
for (PluginPatcher patcher : list) {
|
||||
patcher.handleClass(node, GlobalClassRepo.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,32 +39,36 @@ public class ArclightPluginPatcher implements PluginTransformer {
|
|||
File pluginFolder = new File("plugins");
|
||||
if (pluginFolder.exists()) {
|
||||
ArclightMod.LOGGER.info("patcher.loading");
|
||||
ArrayList<PluginTransformer> list = new ArrayList<>();
|
||||
for (File file : pluginFolder.listFiles()) {
|
||||
ArrayList<PluginPatcher> list = new ArrayList<>();
|
||||
File[] files = pluginFolder.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isFile() && file.getName().endsWith(".jar")) {
|
||||
loadFromJar(file.toPath()).ifPresent(list::add);
|
||||
loadFromJar(file).ifPresent(list::add);
|
||||
}
|
||||
}
|
||||
if (!list.isEmpty()) {
|
||||
list.sort(Comparator.comparing(PluginTransformer::priority));
|
||||
list.sort(Comparator.comparing(PluginPatcher::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));
|
||||
private static Optional<PluginPatcher> loadFromJar(File file) {
|
||||
try (JarFile jarFile = new JarFile(file)) {
|
||||
JarEntry jarEntry = jarFile.getJarEntry("plugin.yml");
|
||||
if (jarEntry != null) {
|
||||
try (InputStream stream = jarFile.getInputStream(jarEntry)) {
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(new InputStreamReader(stream));
|
||||
String name = configuration.getString("arclight.patcher");
|
||||
if (name != null) {
|
||||
URLClassLoader loader = new URLClassLoader(new URL[]{path.toUri().toURL()}, ArclightPluginPatcher.class.getClassLoader());
|
||||
URLClassLoader loader = new URLClassLoader(new URL[]{file.toURI().toURL()}, ArclightPluginPatcher.class.getClassLoader());
|
||||
Class<?> clazz = Class.forName(name, false, loader);
|
||||
PluginTransformer transformer = clazz.asSubclass(PluginTransformer.class).newInstance();
|
||||
return Optional.of(transformer);
|
||||
PluginPatcher patcher = clazz.asSubclass(PluginPatcher.class).getConstructor().newInstance();
|
||||
return Optional.of(patcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
|
|
14
arclight-common/src/main/resources/mixins.arclight.api.json
Normal file
14
arclight-common/src/main/resources/mixins.arclight.api.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"required": true,
|
||||
"minVersion": "0.8",
|
||||
"package": "io.izzel.arclight.common.mixin.api",
|
||||
"target": "@env(DEFAULT)",
|
||||
"refmap": "mixins.arclight.refmap.json",
|
||||
"setSourceFile": true,
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
},
|
||||
"mixins": [
|
||||
"Arclight_ForgeEventMixin"
|
||||
]
|
||||
}
|
|
@ -97,8 +97,8 @@ dependencies {
|
|||
embed 'net.md-5:bungeecord-chat:1.16-R0.4@jar'
|
||||
embed "org.spigotmc:spigot-api:$minecraftVersion-R0.1-SNAPSHOT@jar"
|
||||
embed 'com.github.ArclightTeam:mixin-tools:1.0.0@jar'
|
||||
embed 'io.izzel:tools:1.1.+'
|
||||
embed 'io.izzel.arclight:arclight-api:1.0.+'
|
||||
embed "io.izzel:tools:$toolsVersion"
|
||||
embed "io.izzel.arclight:arclight-api:$apiVersion"
|
||||
annotationProcessor 'org.spongepowered:mixin:0.8.2:processor'
|
||||
annotationProcessor 'com.github.ArclightTeam:mixin-tools:1.0.0'
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ allprojects {
|
|||
agpVersion = '1.17'
|
||||
minecraftVersion = '1.16.5'
|
||||
forgeVersion = '36.1.24'
|
||||
apiVersion = '1.0.+'
|
||||
toolsVersion = '1.3.+'
|
||||
}
|
||||
|
||||
task cleanBuild {
|
||||
|
|
|
@ -13,6 +13,6 @@ repositories {
|
|||
|
||||
dependencies {
|
||||
compile 'com.google.code.gson:gson:2.8.0'
|
||||
compile 'io.izzel.arclight:arclight-api:1.0.+'
|
||||
compile "io.izzel.arclight:arclight-api:$apiVersion"
|
||||
compile project(':i18n-config')
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user