diff --git a/README.md b/README.md index ced0a38..3b6ed98 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,9 @@ - **支持跨服** - **gui显示自己的权限包** - **语言支持整理** +- **支持自定义哪个玩家的头颅** +- **支持物品发光(附魔效果)** +- **玩家进入游戏时赋予权限更早** - 手动删除过期的或无效数据 - 取消前置插件 diff --git a/config/packages.yml b/config/packages.yml index 6f7b47d..82d53fa 100644 --- a/config/packages.yml +++ b/config/packages.yml @@ -12,8 +12,17 @@ packages: # Permission package display name. displayName: '&4Test Package' # 显示的物品类型. + # 可以使用id, 但不可与type同时使用. + # 可以定义物品的种类, 特殊的如头颅可以指定哪个玩家的头颅. # Show the type of item. + # You can use 'id', but you can't use 'type' at the same time. + # You can define the type of item, such as skull can set which player's head. + #id: 397 + #type: SKULL_ITEM:5 + #type: SKULL_ITEM:MHF_Present1 type: NETHER_STAR + # 是否有附魔发光的特效 + glowing: false # 标签. # Lores. lores: diff --git a/pom.xml b/pom.xml index e79b2ac..7f68fe8 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 gg.frog.mc permissionstime - 0.1.1-SNAPSHOT + 0.1.2-SNAPSHOT jar PermissionsTime 支持跨服的权限限时插件 @@ -38,7 +38,7 @@ org.bukkit bukkit - 1.12-pre6-SNAPSHOT + 1.8-R0.1-SNAPSHOT jar compile diff --git a/src/main/gg/frog/mc/permissionstime/config/PackagesCfg.java b/src/main/gg/frog/mc/permissionstime/config/PackagesCfg.java index 456e4eb..f36e79c 100644 --- a/src/main/gg/frog/mc/permissionstime/config/PackagesCfg.java +++ b/src/main/gg/frog/mc/permissionstime/config/PackagesCfg.java @@ -19,6 +19,7 @@ import gg.frog.mc.permissionstime.PluginMain; import gg.frog.mc.permissionstime.model.cfg.PermissionPackageBean; import gg.frog.mc.permissionstime.utils.StrUtil; import gg.frog.mc.permissionstime.utils.config.PluginConfig; +import gg.frog.mc.permissionstime.utils.nms.ItemUtil; public class PackagesCfg extends PluginConfig { @@ -66,35 +67,42 @@ public class PackagesCfg extends PluginConfig { if (ppb != null) { Material type = null; int exid = 0; + String skullOwner = null; if (ppb.getType() != null) { String[] args = ppb.getType().split(":"); - try { - switch (args.length) { - case 2: - exid = Integer.parseInt(args[1]); - case 1: - type = Material.getMaterial(args[0].toUpperCase(Locale.ENGLISH)); + type = Material.getMaterial(args[0].toUpperCase(Locale.ENGLISH)); + if (args.length == 2) { + try { + exid = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + if (Material.SKULL_ITEM.equals(type)) { + exid = 3; + skullOwner = args[1]; + } else { + e.printStackTrace(); + } } - } catch (NumberFormatException e) { - e.printStackTrace(); } } else if (ppb.getId() != null) { String[] args = ppb.getId().split(":"); - try { - switch (args.length) { - case 2: - exid = Integer.parseInt(args[1]); - case 1: - int id = Integer.parseInt(args[0]); - type = Material.getMaterial(id); + int id = Integer.parseInt(args[0]); + type = Material.getMaterial(id); + if (args.length == 2) { + try { + exid = Integer.parseInt(args[1]); + } catch (NumberFormatException e) { + if (Material.SKULL_ITEM.equals(type)) { + exid = 3; + skullOwner = args[1]; + } else { + e.printStackTrace(); + } } - } catch (NumberFormatException e) { - e.printStackTrace(); } } if (type != null) { - ItemStack items = new ItemStack(type, 1, (short) 0, (byte) exid); - ItemMeta meta = items.getItemMeta(); + ItemStack item = new ItemStack(type, 1, (short) 0, (byte) exid); + ItemMeta meta = item.getItemMeta(); meta.setDisplayName(StrUtil.messageFormat(ppb.getDisplayName() + "&r(" + name + ")")); List lores = new ArrayList(); for (String lore : ppb.getLores()) { @@ -102,8 +110,14 @@ public class PackagesCfg extends PluginConfig { } lores.add(""); meta.setLore(lores); - items.setItemMeta(meta); - return items; + item.setItemMeta(meta); + if (ppb.getGlowing() && !meta.hasEnchants()) { + item = ItemUtil.addEnchantLight(item); + } + if (skullOwner != null) { + item = ItemUtil.addSkullOwner(item, skullOwner); + } + return item; } } return null; diff --git a/src/main/gg/frog/mc/permissionstime/database/SqlManager.java b/src/main/gg/frog/mc/permissionstime/database/SqlManager.java index 9eb5380..640c7be 100644 --- a/src/main/gg/frog/mc/permissionstime/database/SqlManager.java +++ b/src/main/gg/frog/mc/permissionstime/database/SqlManager.java @@ -8,7 +8,6 @@ import gg.frog.mc.permissionstime.config.PluginCfg; import gg.frog.mc.permissionstime.database.impl.MySQLPlayerDataDao; import gg.frog.mc.permissionstime.database.impl.SqlitePlayerDataDao; import gg.frog.mc.permissionstime.model.db.PlayerDataBean; -import gg.frog.mc.permissionstime.utils.StrUtil; import lib.PatPeter.SQLibrary.Database; import lib.PatPeter.SQLibrary.MySQL; import lib.PatPeter.SQLibrary.SQLite; diff --git a/src/main/gg/frog/mc/permissionstime/listener/MainListener.java b/src/main/gg/frog/mc/permissionstime/listener/MainListener.java index 18d13f4..fe63a04 100644 --- a/src/main/gg/frog/mc/permissionstime/listener/MainListener.java +++ b/src/main/gg/frog/mc/permissionstime/listener/MainListener.java @@ -3,10 +3,11 @@ package gg.frog.mc.permissionstime.listener; import java.util.List; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; import gg.frog.mc.permissionstime.PluginMain; @@ -24,28 +25,17 @@ public class MainListener implements Listener { this.pm = pm; } - /** - * 一个监听器例子 - * - * @param e - */ - @EventHandler - public void onJoin(PlayerJoinEvent event) { - new Thread(new Runnable() { - @Override - public void run() { - try { - List pdbList = pm.getSqlManager().getTime(event.getPlayer().getUniqueId().toString()); - PermissionPackageBean.reloadPlayerPermissions(event.getPlayer(), pdbList, pm); - } catch (Exception e) { - e.printStackTrace(); - event.getPlayer().sendMessage(StrUtil.messageFormat(PluginCfg.PLUGIN_PREFIX + LangCfg.MSG_FAIL_SET_PERMISSION)); - } - } - }).start(); + @EventHandler(priority = EventPriority.LOWEST) + public void onJoin(PlayerLoginEvent event) { + try { + List pdbList = pm.getSqlManager().getTime(event.getPlayer().getUniqueId().toString()); + PermissionPackageBean.reloadPlayerPermissions(event.getPlayer(), pdbList, pm, false); + } catch (Exception e) { + e.printStackTrace(); + event.getPlayer().sendMessage(StrUtil.messageFormat(PluginCfg.PLUGIN_PREFIX + LangCfg.MSG_FAIL_SET_PERMISSION)); + } } - @EventHandler public void onQuit(PlayerQuitEvent event) { new Thread(new Runnable() { @Override @@ -59,7 +49,6 @@ public class MainListener implements Listener { }).start(); } - @EventHandler public void onKick(PlayerKickEvent event) { new Thread(new Runnable() { @Override diff --git a/src/main/gg/frog/mc/permissionstime/model/cfg/PermissionPackageBean.java b/src/main/gg/frog/mc/permissionstime/model/cfg/PermissionPackageBean.java index e431711..9054d49 100644 --- a/src/main/gg/frog/mc/permissionstime/model/cfg/PermissionPackageBean.java +++ b/src/main/gg/frog/mc/permissionstime/model/cfg/PermissionPackageBean.java @@ -14,8 +14,11 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.scheduler.BukkitTask; import gg.frog.mc.permissionstime.PluginMain; +import gg.frog.mc.permissionstime.config.LangCfg; import gg.frog.mc.permissionstime.config.PackagesCfg; +import gg.frog.mc.permissionstime.config.PluginCfg; import gg.frog.mc.permissionstime.model.db.PlayerDataBean; +import gg.frog.mc.permissionstime.utils.StrUtil; import gg.frog.mc.permissionstime.utils.config.IConfigBean; import net.milkbowl.vault.permission.Permission; @@ -30,8 +33,9 @@ public class PermissionPackageBean implements IConfigBean { private String displayName = null; private String id; private String type; + private Boolean glowing; private List lores = new ArrayList<>(); - private Boolean global = null; + private Boolean global; private List permissions = new ArrayList<>(); private List groups = new ArrayList<>(); private static Map taskMap = new ConcurrentHashMap<>(); @@ -60,6 +64,14 @@ public class PermissionPackageBean implements IConfigBean { this.type = type; } + public Boolean getGlowing() { + return glowing; + } + + public void setGlowing(Boolean glowing) { + this.glowing = glowing; + } + public List getLores() { return lores; } @@ -98,6 +110,7 @@ public class PermissionPackageBean implements IConfigBean { config.set("displayName", displayName); config.set("id", id); config.set("type", type); + config.set("glowing", glowing); config.set("lores", lores); config.set("global", global); config.set("permissions", permissions); @@ -116,6 +129,7 @@ public class PermissionPackageBean implements IConfigBean { if (id == null && type == null) { type = "NETHER_STAR"; } + glowing = config.getBoolean("glowing"); lores = config.getStringList("lores"); global = config.getBoolean("global"); permissions = config.getStringList("permissions"); @@ -124,7 +138,7 @@ public class PermissionPackageBean implements IConfigBean { @Override public String toString() { - return "PermissionPackageBean [displayName=" + displayName + ", id=" + id + ", type=" + type + ", lores=" + lores + ", global=" + global + ", permissions=" + permissions + ", groups=" + groups + "]"; + return "PermissionPackageBean [displayName=" + displayName + ", id=" + id + ", type=" + type + ", glowing=" + glowing + ", lores=" + lores + ", global=" + global + ", permissions=" + permissions + ", groups=" + groups + "]"; } private void givePlayer(OfflinePlayer player, Server server, Permission permission) { @@ -196,6 +210,10 @@ public class PermissionPackageBean implements IConfigBean { } public static void reloadPlayerPermissions(OfflinePlayer player, List pdbList, PluginMain plugin) { + reloadPlayerPermissions(player, pdbList, plugin, true); + } + + public static void reloadPlayerPermissions(OfflinePlayer player, List pdbList, PluginMain plugin, boolean async) { long delay = -1; long now = new Date().getTime(); PermissionPackageBean addPpb = new PermissionPackageBean(); @@ -219,13 +237,23 @@ public class PermissionPackageBean implements IConfigBean { subPpb.getGroups().removeAll(p.getGroups()); } } - plugin.getServer().getScheduler().runTask(plugin, new Runnable() { - @Override - public void run() { - subPpb.clearPlayer(player, plugin.getServer(), plugin.getPermission()); - addPpb.givePlayer(player, plugin.getServer(), plugin.getPermission()); - } - }); + if (async) { + plugin.getServer().getScheduler().runTask(plugin, new Runnable() { + @Override + public void run() { + try { + subPpb.clearPlayer(player, plugin.getServer(), plugin.getPermission()); + addPpb.givePlayer(player, plugin.getServer(), plugin.getPermission()); + } catch (Exception e) { + e.printStackTrace(); + player.getPlayer().sendMessage(StrUtil.messageFormat(PluginCfg.PLUGIN_PREFIX + LangCfg.MSG_FAIL_SET_PERMISSION)); + } + } + }); + } else { + subPpb.clearPlayer(player, plugin.getServer(), plugin.getPermission()); + addPpb.givePlayer(player, plugin.getServer(), plugin.getPermission()); + } BukkitTask task = taskMap.get(player.getUniqueId().toString()); if (task != null) { plugin.getServer().getScheduler().cancelTask(task.getTaskId()); diff --git a/src/main/gg/frog/mc/permissionstime/utils/config/PluginConfig.java b/src/main/gg/frog/mc/permissionstime/utils/config/PluginConfig.java index 89b1463..54ae939 100644 --- a/src/main/gg/frog/mc/permissionstime/utils/config/PluginConfig.java +++ b/src/main/gg/frog/mc/permissionstime/utils/config/PluginConfig.java @@ -18,6 +18,8 @@ import org.bukkit.configuration.file.YamlConfiguration; import com.google.common.base.Charsets; import gg.frog.mc.permissionstime.PluginMain; +import gg.frog.mc.permissionstime.config.PluginCfg; +import gg.frog.mc.permissionstime.utils.StrUtil; /** * 配置操作 @@ -105,7 +107,7 @@ public abstract class PluginConfig { try { getConfig().save(configFile); } catch (IOException ex) { - PluginMain.LOG.log(Level.SEVERE, "Could not save config to " + configFile, ex); + PluginMain.LOG.log(Level.SEVERE, StrUtil.messageFormat(PluginCfg.PLUGIN_PREFIX + "Could not save config to " + configFile), ex); } } @@ -114,7 +116,7 @@ public abstract class PluginConfig { getConfig().save(configFile); reloadConfig(); } catch (IOException ex) { - PluginMain.LOG.log(Level.SEVERE, "Could not save config to " + configFile, ex); + PluginMain.LOG.log(Level.SEVERE, StrUtil.messageFormat(PluginCfg.PLUGIN_PREFIX + "Could not save config to " + configFile), ex); } } diff --git a/src/main/gg/frog/mc/permissionstime/utils/nms/ItemUtil.java b/src/main/gg/frog/mc/permissionstime/utils/nms/ItemUtil.java new file mode 100644 index 0000000..4875cf7 --- /dev/null +++ b/src/main/gg/frog/mc/permissionstime/utils/nms/ItemUtil.java @@ -0,0 +1,124 @@ +package gg.frog.mc.permissionstime.utils.nms; + +import java.lang.reflect.Method; + +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; + +import gg.frog.mc.permissionstime.PluginMain; +import gg.frog.mc.permissionstime.config.PluginCfg; +import gg.frog.mc.permissionstime.utils.StrUtil; + +public class ItemUtil { + + private static Class nbtBaseClass; + private static Class nbtTagCompoundClass; + private static Class nbtTagStringClass; + private static Class nbtTagIntClass; +// private static Class nbtTagShortClass; +// private static Class nbtTagListClass; + private static Class nmsItemstackClass; + private static Method asNmsCopyMethod; + private static Method asCraftMirrorMethod; + private static Method hasTagMethod; + private static Method getTagMethod; + private static Method setTagMethod; + private static Method nbtSetMethod; +// private static Method nbtListAddSetMethod; + private static boolean setupOk; + + static { + try { + nmsItemstackClass = NMSUtil.getNmsClass("ItemStack");// add + nbtBaseClass = NMSUtil.getNmsClass("NBTBase");// dy + nbtTagStringClass = NMSUtil.getNmsClass("NBTTagString");// dx + nbtTagIntClass = NMSUtil.getNmsClass("NBTTagInt");// dp + nbtTagCompoundClass = NMSUtil.getNmsClass("NBTTagCompound");// dh +// nbtTagShortClass = NMSUtil.getNmsClass("NBTTagShort"); +// nbtTagListClass = NMSUtil.getNmsClass("NBTTagList"); + asNmsCopyMethod = NMSUtil.getObcClass("inventory.CraftItemStack").getMethod("asNMSCopy", new Class[] { ItemStack.class }); + asCraftMirrorMethod = NMSUtil.getObcClass("inventory.CraftItemStack").getMethod("asCraftMirror", new Class[] { nmsItemstackClass }); + hasTagMethod = nmsItemstackClass.getMethod("hasTag", new Class[0]);// p + getTagMethod = nmsItemstackClass.getMethod("getTag", new Class[0]);// q + setTagMethod = nmsItemstackClass.getMethod("setTag", new Class[] { nbtTagCompoundClass });// d + nbtSetMethod = nbtTagCompoundClass.getMethod("set", new Class[] { String.class, nbtBaseClass });// a +// nbtListAddSetMethod = nbtTagListClass.getMethod("add", new Class[] { nbtBaseClass }); + setupOk = true; + } catch (Exception e) { + e.printStackTrace(); +// try { +// nmsItemstackClass = Class.forName("add"); +// nbtBaseClass = Class.forName("dy"); +// nbtTagStringClass = Class.forName("dx"); +// nbtTagIntClass = Class.forName("dp"); +// nbtTagCompoundClass = Class.forName("dh"); +// asNmsCopyMethod = NMSUtil.getObcClass("inventory.CraftItemStack").getMethod("asNMSCopy", new Class[] { ItemStack.class }); +// asCraftMirrorMethod = NMSUtil.getObcClass("inventory.CraftItemStack").getMethod("asCraftMirror", new Class[] { nmsItemstackClass }); +// hasTagMethod = nmsItemstackClass.getMethod("func_77942_o", new Class[0]); +// getTagMethod = nmsItemstackClass.getMethod("func_77978_p", new Class[0]); +// setTagMethod = nmsItemstackClass.getMethod("func_77982_d", new Class[] { nbtTagCompoundClass }); +// nbtSetMethod = nbtTagCompoundClass.getMethod("func_74782_a", new Class[] { String.class, nbtBaseClass }); +// setupOk = true; +// } catch (Exception ex) { +// ex.printStackTrace(); +// PluginMain.LOG.warning(StrUtil.messageFormat(PluginCfg.PLUGIN_PREFIX + "ItemUtil setup fail. Some functions are unavailable.")); +// } + PluginMain.LOG.warning(StrUtil.messageFormat(PluginCfg.PLUGIN_PREFIX + "ItemUtil setup fail. Some functions are unavailable.")); + } + } + + public static ItemStack addEnchantLight(ItemStack item) { + item.addUnsafeEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 0); + if (!NMSUtil.getServerVersion().startsWith("v1_7_") && setupOk) { + try { + Object nmsItemstack = asNmsCopyMethod.invoke(null, new Object[] { item }); + if (nmsItemstack == null) { + return item; + } + Object nbtCompound = null; + if (((Boolean) hasTagMethod.invoke(nmsItemstack, new Object[0])).booleanValue()) { + nbtCompound = getTagMethod.invoke(nmsItemstack, new Object[0]); + } else { + nbtCompound = nbtTagCompoundClass.newInstance(); + setTagMethod.invoke(nmsItemstack, new Object[] { nbtCompound }); + } + if (nbtCompound == null) { + return item; + } + Object nbtHideFlags = nbtTagIntClass.getConstructor(int.class).newInstance(1); + nbtSetMethod.invoke(nbtCompound, new Object[] { "HideFlags", nbtHideFlags }); + return (ItemStack) asCraftMirrorMethod.invoke(null, new Object[] { nmsItemstack }); + } catch (Exception e) { + e.printStackTrace(); + } + } + return item; + } + + public static ItemStack addSkullOwner(ItemStack item, String name) { + if (setupOk) { + try { + Object nmsItemstack = asNmsCopyMethod.invoke(null, new Object[] { item }); + if (nmsItemstack == null) { + return item; + } + Object nbtCompound = null; + if (((Boolean) hasTagMethod.invoke(nmsItemstack, new Object[0])).booleanValue()) { + nbtCompound = getTagMethod.invoke(nmsItemstack, new Object[0]); + } else { + nbtCompound = nbtTagCompoundClass.newInstance(); + setTagMethod.invoke(nmsItemstack, new Object[] { nbtCompound }); + } + if (nbtCompound == null) { + return item; + } + Object nbtString = nbtTagStringClass.getConstructor(String.class).newInstance(name); + nbtSetMethod.invoke(nbtCompound, new Object[] { "SkullOwner", nbtString }); + return (ItemStack) asCraftMirrorMethod.invoke(null, new Object[] { nmsItemstack }); + } catch (Exception e) { + e.printStackTrace(); + } + } + return item; + } +} diff --git a/src/main/gg/frog/mc/permissionstime/utils/nms/NMSUtil.java b/src/main/gg/frog/mc/permissionstime/utils/nms/NMSUtil.java new file mode 100644 index 0000000..acf354c --- /dev/null +++ b/src/main/gg/frog/mc/permissionstime/utils/nms/NMSUtil.java @@ -0,0 +1,26 @@ +package gg.frog.mc.permissionstime.utils.nms; + +import org.bukkit.Bukkit; + +public class NMSUtil { + + private static String serverVersion; + + static { + String packageName = Bukkit.getServer().getClass().getPackage().getName(); + serverVersion = packageName.substring(packageName.lastIndexOf('.') + 1); + } + + public static String getServerVersion() { + return serverVersion; + } + + public static Class getNmsClass(String name) throws ClassNotFoundException { + return Class.forName("net.minecraft.server." + getServerVersion() + "." + name); + } + + public static Class getObcClass(String name) throws ClassNotFoundException { + return Class.forName("org.bukkit.craftbukkit." + getServerVersion() + "." + name); + } + +} diff --git a/src/resources/packages.yml b/src/resources/packages.yml index 6f7b47d..82d53fa 100644 --- a/src/resources/packages.yml +++ b/src/resources/packages.yml @@ -12,8 +12,17 @@ packages: # Permission package display name. displayName: '&4Test Package' # 显示的物品类型. + # 可以使用id, 但不可与type同时使用. + # 可以定义物品的种类, 特殊的如头颅可以指定哪个玩家的头颅. # Show the type of item. + # You can use 'id', but you can't use 'type' at the same time. + # You can define the type of item, such as skull can set which player's head. + #id: 397 + #type: SKULL_ITEM:5 + #type: SKULL_ITEM:MHF_Present1 type: NETHER_STAR + # 是否有附魔发光的特效 + glowing: false # 标签. # Lores. lores: