AsmClassTransformer
This commit is contained in:
@@ -66,6 +66,21 @@ public class TConfigInjector {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void reloadConfig(Plugin plugin, Object object) {
|
||||
try {
|
||||
Config config = object.getClass().getAnnotation(Config.class);
|
||||
Validate.notNull(config);
|
||||
File file = new File(plugin.getDataFolder(), config.name());
|
||||
Map<String, Object> map = ConfigUtils.confToMap(ConfigUtils.loadYaml(plugin, file));
|
||||
Object obj = ConfigUtils.mapToObj(map, object);
|
||||
if (!config.readOnly()) saveConfig(plugin, obj);
|
||||
} catch (NullPointerException e) {
|
||||
TLocale.Logger.warn("CONFIG.LOAD-FAIL-NO-ANNOTATION", plugin.toString(), object.getClass().getSimpleName());
|
||||
} catch (Exception e) {
|
||||
TLocale.Logger.warn("CONFIG.LOAD-FAIL", plugin.toString(), object.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
public static Object unserialize(Plugin plugin, Class<?> clazz) {
|
||||
try {
|
||||
Config config = clazz.getAnnotation(Config.class);
|
||||
|
||||
@@ -72,11 +72,7 @@ public class TDependencyInjector {
|
||||
obj,
|
||||
object -> {
|
||||
try {
|
||||
Object newObj = TConfigInjector.loadConfig(plugin, object.getClass());
|
||||
for (Field f : newObj.getClass().getDeclaredFields()) {
|
||||
f.setAccessible(true);
|
||||
f.set(obj, f.get(newObj));
|
||||
}
|
||||
TConfigInjector.reloadConfig(plugin, object);
|
||||
TLocale.Logger.info("CONFIG.RELOAD-SUCCESS", plugin.toString(), config.name());
|
||||
} catch (Exception ignored) {
|
||||
TLocale.Logger.warn("CONFIG.RELOAD-FAIL", plugin.toString(), config.name());
|
||||
|
||||
50
src/main/java/com/ilummc/tlib/nms/ActionBar.java
Normal file
50
src/main/java/com/ilummc/tlib/nms/ActionBar.java
Normal file
@@ -0,0 +1,50 @@
|
||||
package com.ilummc.tlib.nms;
|
||||
|
||||
import com.ilummc.tlib.util.asm.AsmClassTransformer;
|
||||
import me.skymc.taboolib.TabooLib;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public abstract class ActionBar {
|
||||
|
||||
private static ActionBar instance;
|
||||
|
||||
static {
|
||||
if (TabooLib.getVerint() > 11100) {
|
||||
instance = (ActionBar) AsmClassTransformer.builder().from(Impl_1_12.class).fromVersion("v1_12_R1")
|
||||
.toVersion(Bukkit.getServer().getClass().getName().split("\\.")[3]).build().transform();
|
||||
} else {
|
||||
instance = (ActionBar) AsmClassTransformer.builder().from(Impl_1_8.class).fromVersion("v1_8_R3")
|
||||
.toVersion(Bukkit.getServer().getClass().getName().split("\\.")[3]).build().transform();
|
||||
}
|
||||
System.out.println(instance.getClass());
|
||||
}
|
||||
|
||||
public static void sendActionBar(Player player, String text) {
|
||||
instance.send(player, text);
|
||||
}
|
||||
|
||||
public abstract void send(Player player, String text);
|
||||
|
||||
public static class Impl_1_8 extends ActionBar {
|
||||
|
||||
@Override
|
||||
public void send(Player player, String text) {
|
||||
net.minecraft.server.v1_8_R3.ChatComponentText component = new net.minecraft.server.v1_8_R3.ChatComponentText(text);
|
||||
net.minecraft.server.v1_8_R3.PacketPlayOutChat packet = new net.minecraft.server.v1_8_R3.PacketPlayOutChat(component, (byte) 2);
|
||||
((org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Impl_1_12 extends ActionBar {
|
||||
|
||||
@Override
|
||||
public void send(Player player, String text) {
|
||||
net.minecraft.server.v1_12_R1.ChatComponentText component = new net.minecraft.server.v1_12_R1.ChatComponentText(text);
|
||||
net.minecraft.server.v1_12_R1.PacketPlayOutChat packet = new net.minecraft.server.v1_12_R1.PacketPlayOutChat(component,
|
||||
net.minecraft.server.v1_12_R1.ChatMessageType.a((byte) 2));
|
||||
((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,8 @@ public class TLocaleLoader {
|
||||
TLocaleInstance localeInstance = new TLocaleInstance(plugin);
|
||||
localeInstance.load(configuration);
|
||||
map.put(plugin.getName(), localeInstance);
|
||||
TLib.getTLib().getLogger().info(Strings.replaceWithOrder(TLib.getTLib().getInternalLang().getString("SUCCESS-LOADING-LANG"),
|
||||
plugin.getName(), lang, String.valueOf(localeInstance.size())));
|
||||
}
|
||||
File finalFile = file;
|
||||
String finalLang = lang;
|
||||
@@ -84,7 +86,6 @@ public class TLocaleLoader {
|
||||
TLib.getTLib().getLogger().info(Strings.replaceWithOrder(TLib.getTLib().getInternalLang().getString("SUCCESS-LOADING-LANG"),
|
||||
plugin.getName(), finalLang, String.valueOf(localeInstance.size())));
|
||||
});
|
||||
TLib.getTLib().getLogger().info(Strings.replaceWithOrder(TLib.getTLib().getInternalLang().getString("SUCCESS-LOADING-LANG"), plugin.getName(), lang));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
TLib.getTLib().getLogger().error(Strings.replaceWithOrder(TLib.getTLib().getInternalLang().getString("ERROR-LOADING-LANG"),
|
||||
|
||||
13
src/main/java/com/ilummc/tlib/util/asm/AsmClassLoader.java
Normal file
13
src/main/java/com/ilummc/tlib/util/asm/AsmClassLoader.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.ilummc.tlib.util.asm;
|
||||
|
||||
public class AsmClassLoader extends ClassLoader {
|
||||
|
||||
public AsmClassLoader() {
|
||||
super(AsmClassLoader.class.getClassLoader());
|
||||
}
|
||||
|
||||
public Class<?> createNewClass(String name, byte[] arr) {
|
||||
return defineClass(name, arr, 0, arr.length, AsmClassLoader.class.getProtectionDomain());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,153 @@
|
||||
package com.ilummc.tlib.util.asm;
|
||||
|
||||
public class AsmClassTransformer {
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Map;
|
||||
|
||||
public class AsmClassTransformer extends ClassVisitor implements Opcodes {
|
||||
|
||||
private final Class<?> from;
|
||||
|
||||
private final String fromVer, toVer;
|
||||
|
||||
private final ClassWriter writer;
|
||||
|
||||
private String newClassName, prevName;
|
||||
|
||||
private AsmClassTransformer(Class<?> from, String fromVer, String toVer, ClassWriter classWriter) {
|
||||
super(Opcodes.ASM6, classWriter);
|
||||
writer = classWriter;
|
||||
this.from = from;
|
||||
this.fromVer = fromVer;
|
||||
this.toVer = toVer;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder().toVersion(Bukkit.getServer().getClass().getName().split("\\.")[3]);
|
||||
}
|
||||
|
||||
public Object transform() {
|
||||
try {
|
||||
ClassReader classReader = new ClassReader(from.getResourceAsStream("/" + from.getName().replace('.', '/') + ".class"));
|
||||
newClassName = from.getName() + "_TabooLibRemap_" + this.hashCode() + "_" + toVer;
|
||||
prevName = from.getName().replace('.', '/');
|
||||
classReader.accept(this, ClassReader.SKIP_DEBUG);
|
||||
Class<?> clazz = new AsmClassLoader().createNewClass(newClassName, writer.toByteArray());
|
||||
Field field = from.getClassLoader().getClass().getDeclaredField("classes");
|
||||
field.setAccessible(true);
|
||||
((Map<String, Class<?>>) field.get(from.getClassLoader())).put(newClassName, clazz);
|
||||
Constructor<?> constructor = clazz.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance();
|
||||
} catch (IOException | NoSuchFieldException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
||||
super.visit(version, access, newClassName.replace('.', '/'), replace(signature),
|
||||
prevName, replace(interfaces));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
|
||||
MethodVisitor visitor = super.visitMethod(access, name, replace(descriptor), replace(signature), replace(exceptions));
|
||||
return new AsmMethodTransformer(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
|
||||
return super.visitField(access, name, replace(descriptor), replace(signature), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInnerClass(String name, String outerName, String innerName, int access) {
|
||||
super.visitInnerClass(replace(name), outerName, replace(name).substring(outerName.length() + 1), access);
|
||||
}
|
||||
|
||||
private String replace(String text) {
|
||||
if (text != null)
|
||||
return text.replace("net/minecraft/server/" + fromVer, "net/minecraft/server/" + toVer)
|
||||
.replace("org/bukkit/craftbukkit/" + fromVer, "org/bukkit/craftbukkit/" + toVer)
|
||||
.replace(prevName, newClassName.replace('.', '/'));
|
||||
else return null;
|
||||
}
|
||||
|
||||
private String[] replace(String[] text) {
|
||||
if (text != null) {
|
||||
for (int i = 0; i < text.length; i++) {
|
||||
text[i] = replace(text[i]);
|
||||
}
|
||||
return text;
|
||||
} else return null;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private Class<?> from;
|
||||
|
||||
private String fromVersion, toVersion;
|
||||
|
||||
public Builder from(Class<?> clazz) {
|
||||
this.from = clazz;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fromVersion(String ver) {
|
||||
fromVersion = ver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder toVersion(String ver) {
|
||||
toVersion = ver;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AsmClassTransformer build() {
|
||||
return new AsmClassTransformer(from, fromVersion, toVersion, new ClassWriter(ClassWriter.COMPUTE_MAXS));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class AsmMethodTransformer extends MethodVisitor {
|
||||
|
||||
AsmMethodTransformer(MethodVisitor visitor) {
|
||||
super(Opcodes.ASM6, visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
|
||||
super.visitMethodInsn(opcode, replace(owner), name, replace(descriptor), isInterface);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLdcInsn(Object value) {
|
||||
if (value instanceof String)
|
||||
super.visitLdcInsn(replace((String) value));
|
||||
else super.visitLdcInsn(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTypeInsn(int opcode, String type) {
|
||||
super.visitTypeInsn(opcode, replace(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
|
||||
super.visitFieldInsn(opcode, replace(owner), name, replace(descriptor));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
|
||||
super.visitLocalVariable(name, replace(descriptor), replace(signature), start, end, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user