TabooLib v4.25
+ 新增 TConfiguration 工具,与 TConfigWatcher 联动创建能够自动重载的配置文件。(尚未测试) + 新增 TFunction 注解,自动执行载入与卸载方法。(变懒第一步,放弃注册步骤) + 调整 TLogger 工具,允许以自定义名称创建,并支持在 BungeeCord 下使用。 + 调整 TListener 与 Instantiable 注解,不会再重复读取插件类了。 + 调整 ReflectionUtils 工具,对部分语法进行了修改。 + 调整 TabooLib 类下的 isSpigot 与 getVersion 算法。 + 重做 AnvilContainerAPI 工具,现在可以正常使用了。(丢人玩意儿终于重写了) + InstanceHandler 类更名为 InstantiableLoader + MsgUtils 类被赋予尊贵的 @Deprecated
This commit is contained in:
@@ -1,78 +1,29 @@
|
||||
package me.skymc.taboolib.anvil;
|
||||
|
||||
import me.skymc.taboolib.nms.NMSUtils;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author sky
|
||||
* @Author sky
|
||||
* @Since 2018-09-08 15:47
|
||||
*/
|
||||
public class AnvilContainer {
|
||||
public class AnvilContainer extends net.minecraft.server.v1_12_R1.ContainerAnvil {
|
||||
|
||||
// private static IAnvilContainer instance;
|
||||
public AnvilContainer(net.minecraft.server.v1_12_R1.EntityHuman player) {
|
||||
super(player.inventory, player.world, new net.minecraft.server.v1_12_R1.BlockPosition(0, 0, 0), player);
|
||||
}
|
||||
|
||||
private static Class<?> ChatMessage = NMSUtils.getNMSClass("ChatMessage");
|
||||
private static Class<?> PacketPlayOutOpenWindow = NMSUtils.getNMSClass("PacketPlayOutOpenWindow");
|
||||
private static Class<?> IChatBaseComponent = NMSUtils.getNMSClass("IChatBaseComponent");
|
||||
private static Class<?> Packet = NMSUtils.getNMSClass("Packet");
|
||||
|
||||
// public static IAnvilContainer getInstance() {
|
||||
// return instance;
|
||||
// }
|
||||
//
|
||||
// static {
|
||||
// /*
|
||||
// * 玩不懂玩不懂... 似乎不会更改父类的包名?
|
||||
// */
|
||||
// instance = (IAnvilContainer) AsmClassTransformer.builder()
|
||||
// .from(AnvilContainerImpl.class)
|
||||
// .fromVersion("v1_12_R1")
|
||||
// .toVersion(Bukkit.getServer().getClass().getName().split("\\.")[3])
|
||||
// .build()
|
||||
// .transform();
|
||||
// }
|
||||
@Override
|
||||
public boolean a(net.minecraft.server.v1_12_R1.EntityHuman player) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void openAnvil(Player p) {
|
||||
try {
|
||||
Object player = p.getClass().getMethod("getHandle").invoke(p);
|
||||
int c = (int) player.getClass().getMethod("nextContainerCounter").invoke(player);
|
||||
Object chatMessage = ChatMessage.getConstructor(String.class, Object[].class).newInstance("Repairing", new Object[0]);
|
||||
Object packetPlayOutOpenWindow = PacketPlayOutOpenWindow.getConstructor(Integer.TYPE, String.class, IChatBaseComponent, Integer.TYPE).newInstance(c, "minecraft:anvil", chatMessage, 0);
|
||||
Object playerConnection = player.getClass().getDeclaredField("playerConnection").get(player);
|
||||
playerConnection.getClass().getMethod("sendPacket", Packet).invoke(playerConnection, packetPlayOutOpenWindow);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
net.minecraft.server.v1_12_R1.EntityPlayer player = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer) p).getHandle();
|
||||
AnvilContainer container = new AnvilContainer(player);
|
||||
int c = player.nextContainerCounter();
|
||||
player.playerConnection.sendPacket(new net.minecraft.server.v1_12_R1.PacketPlayOutOpenWindow(c, "minecraft:anvil", new net.minecraft.server.v1_12_R1.ChatMessage("Repairing"), 0));
|
||||
player.activeContainer = container;
|
||||
player.activeContainer.windowId = c;
|
||||
player.activeContainer.addSlotListener(player);
|
||||
}
|
||||
}
|
||||
|
||||
//interface IAnvilContainer {
|
||||
//
|
||||
// /**
|
||||
// * 打开铁砧界面
|
||||
// *
|
||||
// * @param player 玩家
|
||||
// */
|
||||
// void openAnvil(Player player);
|
||||
//}
|
||||
//
|
||||
//class AnvilContainerImpl extends net.minecraft.server.v1_12_R1.ContainerAnvil implements IAnvilContainer {
|
||||
//
|
||||
// public AnvilContainerImpl(net.minecraft.server.v1_12_R1.EntityHuman player) {
|
||||
// super(player.inventory, player.world, new net.minecraft.server.v1_12_R1.BlockPosition(0, 0, 0), player);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void openAnvil(Player p) {
|
||||
// net.minecraft.server.v1_12_R1.EntityPlayer player = ((org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer) p).getHandle();
|
||||
// AnvilContainerImpl container = new AnvilContainerImpl(player);
|
||||
// int c = player.nextContainerCounter();
|
||||
// player.playerConnection.sendPacket(new net.minecraft.server.v1_12_R1.PacketPlayOutOpenWindow(c, "minecraft:anvil", new net.minecraft.server.v1_12_R1.ChatMessage("Repairing"), 0));
|
||||
// player.activeContainer = container;
|
||||
// player.activeContainer.windowId = c;
|
||||
// player.activeContainer.addSlotListener(player);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public boolean a(net.minecraft.server.v1_12_R1.EntityHuman player) {
|
||||
// return true;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
@@ -1,105 +1,42 @@
|
||||
package me.skymc.taboolib.anvil;
|
||||
|
||||
import com.ilummc.tlib.resources.TLocale;
|
||||
import com.ilummc.tlib.util.asm.AsmClassLoader;
|
||||
import me.skymc.taboolib.TabooLib;
|
||||
import me.skymc.taboolib.listener.TListener;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author sky
|
||||
*/
|
||||
@TListener
|
||||
public class AnvilContainerAPI implements Listener {
|
||||
|
||||
public static List<String> list = new ArrayList<>();
|
||||
public static ItemStack item = new ItemStack(Material.NAME_TAG);
|
||||
public static HashMap<String, String> isOpen = new HashMap<>();
|
||||
public static AnvilContainerAPIEvent event;
|
||||
private static Class<?> impl;
|
||||
|
||||
public static void send(Player p, String type, String str, List<String> lorelist) {
|
||||
isOpen.put(p.getName(), type);
|
||||
|
||||
AnvilContainer.openAnvil(p);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
|
||||
list.clear();
|
||||
if (lorelist == null) {
|
||||
list.addAll(TLocale.asStringList("ANVIL-CONTAINER.LORE-NORMAL"));
|
||||
} else {
|
||||
list = lorelist;
|
||||
}
|
||||
|
||||
meta.setLore(list);
|
||||
meta.setDisplayName(str);
|
||||
item.setItemMeta(meta);
|
||||
|
||||
p.getOpenInventory().getTopInventory().setItem(0, item);
|
||||
p.playSound(p.getLocation(), Sound.BLOCK_ANVIL_PLACE, 1, 1);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void close(InventoryCloseEvent e) {
|
||||
if (isOpen.containsKey(e.getPlayer().getName())) {
|
||||
isOpen.remove(e.getPlayer().getName());
|
||||
if (e.getInventory().getType() == InventoryType.ANVIL) {
|
||||
e.getInventory().clear();
|
||||
}
|
||||
public AnvilContainerAPI() {
|
||||
try {
|
||||
impl = AsmClassLoader.createNewClass("me.skymc.taboolib.anvil.AnvilContainer", AnvilContainerAsm.create(TabooLib.getVersion()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void click(InventoryClickEvent e) {
|
||||
if (!isOpen.containsKey(e.getWhoClicked().getName())) {
|
||||
return;
|
||||
}
|
||||
if (e.getInventory().getType() != InventoryType.ANVIL) {
|
||||
return;
|
||||
}
|
||||
e.setCancelled(true);
|
||||
|
||||
int slot = e.getRawSlot();
|
||||
if (slot != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
Inventory inv = e.getInventory();
|
||||
if (inv.getItem(2) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (inv.getItem(2).getItemMeta().hasDisplayName()) {
|
||||
event = new AnvilContainerAPIEvent(e, isOpen.get(e.getWhoClicked().getName()), inv.getItem(2).getItemMeta().getDisplayName());
|
||||
e.getWhoClicked().closeInventory();
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
public static void openAnvil(Player player) {
|
||||
try {
|
||||
impl.getMethod("openAnvil", Player.class).invoke(impl, player);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void example(PlayerCommandPreprocessEvent e) {
|
||||
if ("/anvilexample".equals(e.getMessage())) {
|
||||
if (e.getPlayer().hasPermission("taboolib.admin")) {
|
||||
e.setCancelled(true);
|
||||
AnvilContainerAPI.send(e.getPlayer(), "EXAMPLE", TLocale.asString("ANVIL-CONTAINER.NAME-EXAMPLE"), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void example2(AnvilContainerAPIEvent e) {
|
||||
if ("EXAMPLE".equals(e.type)) {
|
||||
e.event.getWhoClicked().sendMessage(e.string);
|
||||
if (e.getMessage().equalsIgnoreCase("/anvilExample") && e.getPlayer().hasPermission("taboolib.admin")) {
|
||||
e.setCancelled(true);
|
||||
openAnvil(e.getPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package me.skymc.taboolib.anvil;
|
||||
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
|
||||
public class AnvilContainerAPIEvent extends Event {
|
||||
|
||||
public static final HandlerList handlers = new HandlerList();
|
||||
public InventoryClickEvent event;
|
||||
public String string;
|
||||
public String type;
|
||||
|
||||
public AnvilContainerAPIEvent(InventoryClickEvent e, String t, String s) {
|
||||
event = e;
|
||||
string = s;
|
||||
type = t;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
||||
145
src/main/java/me/skymc/taboolib/anvil/AnvilContainerAsm.java
Normal file
145
src/main/java/me/skymc/taboolib/anvil/AnvilContainerAsm.java
Normal file
@@ -0,0 +1,145 @@
|
||||
package me.skymc.taboolib.anvil;
|
||||
|
||||
import org.objectweb.asm.*;
|
||||
|
||||
/**
|
||||
* @author sky
|
||||
*/
|
||||
public class AnvilContainerAsm {
|
||||
|
||||
public static byte[] create(String version) {
|
||||
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
FieldVisitor fv;
|
||||
MethodVisitor mv;
|
||||
AnnotationVisitor av0;
|
||||
|
||||
cw.visit(Opcodes.V1_8, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, "me/skymc/taboolib/anvil/AnvilContainer", null, "net/minecraft/server/" + version + "/ContainerAnvil", null);
|
||||
|
||||
cw.visitSource("AnvilContainer.java", null);
|
||||
|
||||
{
|
||||
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "(Lnet/minecraft/server/" + version + "/EntityHuman;)V", null, null);
|
||||
mv.visitCode();
|
||||
Label l0 = new Label();
|
||||
mv.visitLabel(l0);
|
||||
mv.visitLineNumber(12, l0);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityHuman", "inventory", "Lnet/minecraft/server/" + version + "/PlayerInventory;");
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityHuman", "world", "Lnet/minecraft/server/" + version + "/World;");
|
||||
mv.visitTypeInsn(Opcodes.NEW, "net/minecraft/server/" + version + "/BlockPosition");
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "net/minecraft/server/" + version + "/BlockPosition", "<init>", "(III)V", false);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "net/minecraft/server/" + version + "/ContainerAnvil", "<init>", "(Lnet/minecraft/server/" + version + "/PlayerInventory;Lnet/minecraft/server/" + version + "/World;Lnet/minecraft/server/" + version + "/BlockPosition;Lnet/minecraft/server/" + version + "/EntityHuman;)V", false);
|
||||
Label l1 = new Label();
|
||||
mv.visitLabel(l1);
|
||||
mv.visitLineNumber(13, l1);
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
Label l2 = new Label();
|
||||
mv.visitLabel(l2);
|
||||
mv.visitLocalVariable("this", "Lme/skymc/taboolib/anvil/AnvilContainer;", null, l0, l2, 0);
|
||||
mv.visitLocalVariable("player", "Lnet/minecraft/server/" + version + "/EntityHuman;", null, l0, l2, 1);
|
||||
mv.visitMaxs(8, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{
|
||||
mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "a", "(Lnet/minecraft/server/" + version + "/EntityHuman;)Z", null, null);
|
||||
mv.visitCode();
|
||||
Label l0 = new Label();
|
||||
mv.visitLabel(l0);
|
||||
mv.visitLineNumber(17, l0);
|
||||
mv.visitInsn(Opcodes.ICONST_1);
|
||||
mv.visitInsn(Opcodes.IRETURN);
|
||||
Label l1 = new Label();
|
||||
mv.visitLabel(l1);
|
||||
mv.visitLocalVariable("this", "Lme/skymc/taboolib/anvil/AnvilContainer;", null, l0, l1, 0);
|
||||
mv.visitLocalVariable("player", "Lnet/minecraft/server/" + version + "/EntityHuman;", null, l0, l1, 1);
|
||||
mv.visitMaxs(1, 2);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{
|
||||
mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "openAnvil", "(Lorg/bukkit/entity/Player;)V", null, null);
|
||||
mv.visitCode();
|
||||
Label l0 = new Label();
|
||||
mv.visitLabel(l0);
|
||||
mv.visitLineNumber(21, l0);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 0);
|
||||
mv.visitTypeInsn(Opcodes.CHECKCAST, "org/bukkit/craftbukkit/" + version + "/entity/CraftPlayer");
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "org/bukkit/craftbukkit/" + version + "/entity/CraftPlayer", "getHandle", "()Lnet/minecraft/server/" + version + "/EntityPlayer;", false);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, 1);
|
||||
Label l1 = new Label();
|
||||
mv.visitLabel(l1);
|
||||
mv.visitLineNumber(22, l1);
|
||||
mv.visitTypeInsn(Opcodes.NEW, "me/skymc/taboolib/anvil/AnvilContainer");
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "me/skymc/taboolib/anvil/AnvilContainer", "<init>", "(Lnet/minecraft/server/" + version + "/EntityHuman;)V", false);
|
||||
mv.visitVarInsn(Opcodes.ASTORE, 2);
|
||||
Label l2 = new Label();
|
||||
mv.visitLabel(l2);
|
||||
mv.visitLineNumber(23, l2);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "net/minecraft/server/" + version + "/EntityPlayer", "nextContainerCounter", "()I", false);
|
||||
mv.visitVarInsn(Opcodes.ISTORE, 3);
|
||||
Label l3 = new Label();
|
||||
mv.visitLabel(l3);
|
||||
mv.visitLineNumber(24, l3);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityPlayer", "playerConnection", "Lnet/minecraft/server/" + version + "/PlayerConnection;");
|
||||
mv.visitTypeInsn(Opcodes.NEW, "net/minecraft/server/" + version + "/PacketPlayOutOpenWindow");
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitVarInsn(Opcodes.ILOAD, 3);
|
||||
mv.visitLdcInsn("minecraft:anvil");
|
||||
mv.visitTypeInsn(Opcodes.NEW, "net/minecraft/server/" + version + "/ChatMessage");
|
||||
mv.visitInsn(Opcodes.DUP);
|
||||
mv.visitLdcInsn("Repairing");
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "net/minecraft/server/" + version + "/ChatMessage", "<init>", "(Ljava/lang/String;[Ljava/lang/Object;)V", false);
|
||||
mv.visitInsn(Opcodes.ICONST_0);
|
||||
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "net/minecraft/server/" + version + "/PacketPlayOutOpenWindow", "<init>", "(ILjava/lang/String;Lnet/minecraft/server/" + version + "/IChatBaseComponent;I)V", false);
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "net/minecraft/server/" + version + "/PlayerConnection", "sendPacket", "(Lnet/minecraft/server/" + version + "/Packet;)V", false);
|
||||
Label l4 = new Label();
|
||||
mv.visitLabel(l4);
|
||||
mv.visitLineNumber(25, l4);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 2);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, "net/minecraft/server/" + version + "/EntityPlayer", "activeContainer", "Lnet/minecraft/server/" + version + "/Container;");
|
||||
Label l5 = new Label();
|
||||
mv.visitLabel(l5);
|
||||
mv.visitLineNumber(26, l5);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityPlayer", "activeContainer", "Lnet/minecraft/server/" + version + "/Container;");
|
||||
mv.visitVarInsn(Opcodes.ILOAD, 3);
|
||||
mv.visitFieldInsn(Opcodes.PUTFIELD, "net/minecraft/server/" + version + "/Container", "windowId", "I");
|
||||
Label l6 = new Label();
|
||||
mv.visitLabel(l6);
|
||||
mv.visitLineNumber(27, l6);
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitFieldInsn(Opcodes.GETFIELD, "net/minecraft/server/" + version + "/EntityPlayer", "activeContainer", "Lnet/minecraft/server/" + version + "/Container;");
|
||||
mv.visitVarInsn(Opcodes.ALOAD, 1);
|
||||
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "net/minecraft/server/" + version + "/Container", "addSlotListener", "(Lnet/minecraft/server/" + version + "/ICrafting;)V", false);
|
||||
Label l7 = new Label();
|
||||
mv.visitLabel(l7);
|
||||
mv.visitLineNumber(28, l7);
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
Label l8 = new Label();
|
||||
mv.visitLabel(l8);
|
||||
mv.visitLocalVariable("p", "Lorg/bukkit/entity/Player;", null, l0, l8, 0);
|
||||
mv.visitLocalVariable("player", "Lnet/minecraft/server/" + version + "/EntityPlayer;", null, l1, l8, 1);
|
||||
mv.visitLocalVariable("container", "Lme/skymc/taboolib/anvil/AnvilContainer;", null, l2, l8, 2);
|
||||
mv.visitLocalVariable("c", "I", null, l3, l8, 3);
|
||||
mv.visitMaxs(9, 4);
|
||||
mv.visitEnd();
|
||||
}
|
||||
cw.visitEnd();
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user