diff --git a/build.gradle b/build.gradle index 6dab00b..8f6ee30 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ plugins { } group = 'me.xpyex.plugin.invactions.bukkit' -version = '1.1.6' +version = '1.1.7' repositories { mavenCentral() @@ -19,7 +19,7 @@ repositories { dependencies { compileOnly fileTree(dir:'libs' ,include:['*.jar']) - compileOnly 'org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT' + compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT' compileOnly 'org.jetbrains:annotations:23.1.0' } diff --git a/src/main/java/me/xpyex/plugin/invactions/bukkit/InvActions.java b/src/main/java/me/xpyex/plugin/invactions/bukkit/InvActions.java index 465aa65..c54f933 100644 --- a/src/main/java/me/xpyex/plugin/invactions/bukkit/InvActions.java +++ b/src/main/java/me/xpyex/plugin/invactions/bukkit/InvActions.java @@ -5,6 +5,7 @@ import java.util.UUID; import me.xpyex.plugin.invactions.bukkit.command.HandleCmd; import me.xpyex.plugin.invactions.bukkit.listener.AutoFarmer; +import me.xpyex.plugin.invactions.bukkit.listener.AutoTool; import me.xpyex.plugin.invactions.bukkit.listener.CraftDrop; import me.xpyex.plugin.invactions.bukkit.listener.HandleEvent; import me.xpyex.plugin.invactions.bukkit.listener.InventoryF; @@ -22,6 +23,7 @@ import me.xpyex.plugin.xplib.bukkit.util.version.VersionUtil; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; @@ -29,79 +31,22 @@ public final class InvActions extends JavaPlugin { private static final String XPLIB_VER = "1.0.8"; - public static final String[] LIGHTS = {"LANTERN", "TORCH", "GLOW", "SHROOMLIGHT", "FrogLight", "END_ROD", "CampFire", "LAVA"}; + public static final String[] LIGHTS = {"LANTERN", "TORCH", "GLOW", "ShroomLight", "FrogLight", "END_ROD", "CampFire", "LAVA"}; private static InvActions INSTANCE; private static final HashMap PLAYER_DYNAMIC_LIGHT = new HashMap<>(); @Override public void onEnable() { INSTANCE = this; - if (!getServer().getPluginManager().isPluginEnabled("XPLib")) { - getLogger().severe("本插件需要XPLib作为前置..."); - getLogger().severe("请在下载后,再加载本插件"); - getLogger().severe("GitHub: https://github.com/0XPYEX0/XPLib/releases"); - getLogger().severe("Gitee(国内): https://gitee.com/XPYEX/XPLib/releases"); - getServer().getPluginManager().disablePlugin(getInstance()); - return; - } - - if (VersionUtil.getMainVersion() < 9) { - getLogger().severe("本插件需要Minecraft至少为1.9才可运行"); - getLogger().severe("很遗憾,您的服务器不满足此条件..."); - getServer().getPluginManager().disablePlugin(getInstance()); - return; - } - - if (!VersionUtil.requireXPLib(new Version(XPLIB_VER))) { - getLogger().severe("请更新您服务器内的XPLib!"); - getLogger().severe("当前XPLib无法支持本插件"); - getLogger().severe("需要: " + XPLIB_VER + " , 当前: " + VersionUtil.getXPLibVersion().getVersion()); - getLogger().severe("GitHub: https://github.com/0XPYEX0/XPLib/releases"); - getLogger().severe("Gitee(国内): https://gitee.com/XPYEX/XPLib/releases"); + if (!initCheck()) { getServer().getPluginManager().disablePlugin(getInstance()); return; } - { - ConfigUtil.saveConfig(getInstance(), "config", GsonUtil.parseStr(SettingsUtil.DEFAULT_SERVER_SETTINGS), false); - JsonObject o = GsonUtil.copy(SettingsUtil.DEFAULT_SERVER_SETTINGS); - JsonObject config = ConfigUtil.getConfig(getInstance()); - for (String key : GsonUtil.getKeysOfJsonObject(config)) { - o.add(key, config.get(key)); - } - ConfigUtil.saveConfig(getInstance(), "config", GsonUtil.parseStr(o), true); - } //更新服务端config.json - - { - getServer().getScheduler().runTaskAsynchronously(getInstance(), () -> { - getServer().getOnlinePlayers().forEach((player -> { - ConfigUtil.saveConfig(InvActions.getInstance(), "players/" + player.getUniqueId(), GsonUtil.parseStr(SettingsUtil.DEFAULT_SETTINGS), false); - //如果文件还不存在,则新建一份 - JsonObject before = ConfigUtil.getConfig(InvActions.getInstance(), "players/" + player.getUniqueId()); - JsonObject out = GsonUtil.copy(SettingsUtil.DEFAULT_SETTINGS); - for (String setting : GsonUtil.getKeysOfJsonObject(SettingsUtil.DEFAULT_SETTINGS)) { - if (before.has(setting)) { - out.add(setting, before.get(setting)); - } - } //更新设定,应对热拔插 - ConfigUtil.saveConfig(InvActions.getInstance(), "players/" + player.getUniqueId(), GsonUtil.parseStr(out), true); - })); - }); - } //更新玩家们的设定 + updateServerConfig(); + getServer().getScheduler().runTaskAsynchronously(getInstance(), this::updatePlayersConfig); - getServer().getPluginManager().registerEvents(new AutoFarmer(), getInstance()); - getServer().getPluginManager().registerEvents(new CraftDrop(), getInstance()); - getServer().getPluginManager().registerEvents(new HandleEvent(), getInstance()); - getServer().getPluginManager().registerEvents(new QuickDrop(), getInstance()); - getServer().getPluginManager().registerEvents(new QuickMove(), getInstance()); - getServer().getPluginManager().registerEvents(new ReplaceBroken(), getInstance()); - try { - @SuppressWarnings("unused") - ClickType swapOffhand = ClickType.SWAP_OFFHAND; //不是每个版本都有这个 - getServer().getPluginManager().registerEvents(new InventoryF(), getInstance()); - } catch (Throwable ignored) { - getLogger().warning("您的服务器不支持在玩家背包内按F整理,该功能已被禁用"); - } + registerListener(); getLogger().info("已注册监听器"); getCommand("InvActions").setExecutor(new HandleCmd()); @@ -176,4 +121,80 @@ public static InvActions getInstance() { return INSTANCE; // } + + public boolean initCheck() { + if (!getServer().getPluginManager().isPluginEnabled("XPLib")) { + getLogger().severe("本插件需要XPLib作为前置..."); + getLogger().severe("请在下载后,再加载本插件"); + getLogger().severe("GitHub: https://github.com/0XPYEX0/XPLib/releases"); + getLogger().severe("Gitee(国内): https://gitee.com/XPYEX/XPLib/releases"); + return false; + } + + if (VersionUtil.getMainVersion() < 9) { + getLogger().severe("本插件需要Minecraft至少为1.9才可运行"); + getLogger().severe("很遗憾,您的服务器不满足此条件..."); + return false; + } + + if (!VersionUtil.requireXPLib(new Version(XPLIB_VER))) { + getLogger().severe("请更新您服务器内的XPLib!"); + getLogger().severe("当前XPLib无法支持本插件"); + getLogger().severe("需要: " + XPLIB_VER + " , 当前: " + VersionUtil.getXPLibVersion().getVersion()); + getLogger().severe("GitHub: https://github.com/0XPYEX0/XPLib/releases"); + getLogger().severe("Gitee(国内): https://gitee.com/XPYEX/XPLib/releases"); + getServer().getPluginManager().disablePlugin(getInstance()); + return false; + } + + return true; + } + + public void updateServerConfig() { + ConfigUtil.saveConfig(getInstance(), "config", GsonUtil.parseStr(SettingsUtil.DEFAULT_SERVER_SETTINGS), false); + JsonObject o = GsonUtil.copy(SettingsUtil.DEFAULT_SERVER_SETTINGS); + JsonObject config = ConfigUtil.getConfig(getInstance()); + for (String key : GsonUtil.getKeysOfJsonObject(config)) { + o.add(key, config.get(key)); + } + ConfigUtil.saveConfig(getInstance(), "config", GsonUtil.parseStr(o), true); + } //更新服务端config.json + + public void updatePlayersConfig() { + getServer().getOnlinePlayers().forEach((player -> { + ConfigUtil.saveConfig(InvActions.getInstance(), "players/" + player.getUniqueId(), GsonUtil.parseStr(SettingsUtil.DEFAULT_SETTINGS), false); + //如果文件还不存在,则新建一份 + JsonObject before = ConfigUtil.getConfig(InvActions.getInstance(), "players/" + player.getUniqueId()); + JsonObject out = GsonUtil.copy(SettingsUtil.DEFAULT_SETTINGS); + for (String setting : GsonUtil.getKeysOfJsonObject(SettingsUtil.DEFAULT_SETTINGS)) { + if (before.has(setting)) { + out.add(setting, before.get(setting)); + } + } //更新设定,应对热拔插 + ConfigUtil.saveConfig(InvActions.getInstance(), "players/" + player.getUniqueId(), GsonUtil.parseStr(out), true); + })); + } + + public void registerListener() { + getServer().getPluginManager().registerEvents(new AutoFarmer(), getInstance()); + getServer().getPluginManager().registerEvents(new CraftDrop(), getInstance()); + getServer().getPluginManager().registerEvents(new HandleEvent(), getInstance()); + getServer().getPluginManager().registerEvents(new QuickDrop(), getInstance()); + getServer().getPluginManager().registerEvents(new QuickMove(), getInstance()); + getServer().getPluginManager().registerEvents(new ReplaceBroken(), getInstance()); + try { + @SuppressWarnings("unused") + ClickType swapOffhand = ClickType.SWAP_OFFHAND; //1.16+ + getServer().getPluginManager().registerEvents(new InventoryF(), getInstance()); + } catch (Throwable ignored) { + getLogger().warning("您的服务器不支持在玩家背包内按F整理,该功能已被禁用"); + } + + try { + Block.class.getMethod("getBreakSpeed", Player.class); //1.17+ + getServer().getPluginManager().registerEvents(new AutoTool(), getInstance()); + } catch (NoSuchMethodError | NoSuchMethodException ignored) { + getLogger().warning("您的服务器不支持自动切换玩家工具,该功能已禁用"); + } + } } diff --git a/src/main/java/me/xpyex/plugin/invactions/bukkit/command/HandleCmd.java b/src/main/java/me/xpyex/plugin/invactions/bukkit/command/HandleCmd.java index b6d4ca5..20110a0 100644 --- a/src/main/java/me/xpyex/plugin/invactions/bukkit/command/HandleCmd.java +++ b/src/main/java/me/xpyex/plugin/invactions/bukkit/command/HandleCmd.java @@ -60,7 +60,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command } if (sender instanceof Player) { ConfigUtil.saveConfig(InvActions.getInstance(), "players/" + ((Player) sender).getUniqueId(), GsonUtil.parseStr(SettingsUtil.DEFAULT_SETTINGS), false); - InvSetter setter = new InvSetter("InvActions-设定-" + sender.getName(), "#########", "#1234567#", "#8 A#", "#########"); + InvSetter setter = new InvSetter("InvActions-设定-" + sender.getName(), "#########", "#1234567#", "#89 A#", "#########"); setter.setSign("#", ItemUtil.getItemStack(Material.BLACK_STAINED_GLASS_PANE, " ")); setter.setSign(" ", Material.AIR); @@ -200,13 +200,21 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command SettingsUtil.turnSetting(player, "DynamicLight"); })) , 1) + .setSign("9", new UnmodifiableButton(menu, (player -> SettingsUtil.getMenuShow(player, "AutoTool"))) + .addMode(-1, ItemUtil.getItemStack(Material.RED_WOOL, "&a自动更换工具", "&f当尝试破坏方块", "&f或尝试耕地时", "&f自动从背包内换出适合的工具", "", "&f当前状态: &4服务端禁用")) + .addMode(0, ItemUtil.getItemStack(Material.RED_WOOL, "&a自动更换工具", "&f当尝试破坏方块", "&f或尝试耕地时", "&f自动从背包内换出适合的工具", "", "&f当前状态: &c禁用")) + .addMode(1, ItemUtil.getItemStack(Material.LIME_WOOL, "&a自动更换工具", "&f当尝试破坏方块", "&f或尝试耕地时", "&f自动从背包内换出适合的工具", "", "&f当前状态: &a启用")) + .setClickEffect((player, clickType, itemStack) -> { + SettingsUtil.turnSetting(player, "AutoTool"); + }) + , 1) .setSign("A", new UnmodifiableButton(menu, (player -> { return player.hasPermission("InvActions.admin") ? 1 : 0; })) .addMode(1, ItemUtil.getItemStack(Material.ORANGE_WOOL, "&6重载所有配置文件", "&f包括服务端和玩家")) .addMode(0, new ItemStack(Material.AIR)) .setClickEffect(((player, clickType, itemStack) -> { - if (itemStack.getAmount() == 0) { + if (itemStack.getAmount() == 0) { //玩家没权限的时候 return; } Bukkit.getScheduler().runTask(InvActions.getInstance(), () -> { diff --git a/src/main/java/me/xpyex/plugin/invactions/bukkit/enums/ItemType.java b/src/main/java/me/xpyex/plugin/invactions/bukkit/enums/ItemType.java index 31a68c4..e9fbcbb 100644 --- a/src/main/java/me/xpyex/plugin/invactions/bukkit/enums/ItemType.java +++ b/src/main/java/me/xpyex/plugin/invactions/bukkit/enums/ItemType.java @@ -40,4 +40,11 @@ public static boolean isAir(Material material) { return material == Material.AIR; } } + + public enum ToolType { + AXE, + PICKAXE, + SHOVEL, + HOE + } } diff --git a/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/AutoTool.java b/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/AutoTool.java new file mode 100644 index 0000000..5d74e98 --- /dev/null +++ b/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/AutoTool.java @@ -0,0 +1,56 @@ +package me.xpyex.plugin.invactions.bukkit.listener; + +import java.util.HashMap; +import java.util.TreeMap; +import me.xpyex.plugin.invactions.bukkit.enums.ItemType; +import me.xpyex.plugin.invactions.bukkit.util.InvUtil; +import me.xpyex.plugin.invactions.bukkit.util.SettingsUtil; +import me.xpyex.plugin.xplib.bukkit.util.inventory.ItemUtil; +import me.xpyex.plugin.xplib.bukkit.util.strings.StrUtil; +import org.bukkit.Material; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +public class AutoTool implements Listener { + private static final HashMap TOOLS = new HashMap<>(); + static { + TOOLS.put(ItemType.ToolType.AXE, new ItemStack(Material.DIAMOND_AXE)); + TOOLS.put(ItemType.ToolType.PICKAXE, new ItemStack(Material.DIAMOND_PICKAXE)); + TOOLS.put(ItemType.ToolType.SHOVEL, new ItemStack(Material.DIAMOND_SHOVEL)); + TOOLS.put(ItemType.ToolType.HOE, new ItemStack(Material.DIAMOND_HOE)); //割稻草块 + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + if (!SettingsUtil.getServerSetting("AutoTool")) return; + + if (!SettingsUtil.getSetting(event.getPlayer(), "AutoTool")) return; + + if (event.getClickedBlock() != null) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + if (ItemUtil.typeIsOr(event.getClickedBlock(), Material.GRASS_BLOCK, Material.DIRT, Material.COARSE_DIRT)) { + if (StrUtil.containsIgnoreCaseOr(event.getPlayer().getInventory().getItemInMainHand().getType().toString(), "_SHOVEL", "_HOE")) + return; //玩家已经拿着对应道具了,就不要换 + InvUtil.swapSlotToMainHand(event.getPlayer(), InvUtil.getFastestToolSlot(event.getPlayer(), event.getClickedBlock(), ItemType.ToolType.HOE)); + } + } + if (event.getAction() == Action.LEFT_CLICK_BLOCK) { + ItemStack before = new ItemStack(event.getPlayer().getInventory().getItemInMainHand()); //保存主手 + TreeMap timeCost = new TreeMap<>(); + for (ItemType.ToolType toolType : TOOLS.keySet()) { + ItemStack item = TOOLS.get(toolType); + event.getPlayer().getInventory().setItemInMainHand(item); //手中设为模板 + timeCost.put(event.getClickedBlock().getBreakSpeed(event.getPlayer()), toolType); //计算并排序 + } + event.getPlayer().getInventory().setItemInMainHand(before); //恢复手中道具 + if (timeCost.size() <= 1) { //时间都一样,或者根本没算成,无需更换道具 + return; + } + InvUtil.swapSlotToMainHand(event.getPlayer(), InvUtil.getFastestToolSlot(event.getPlayer(), event.getClickedBlock(), timeCost.get(timeCost.lastKey()))); //更换这个类别中最快速度的工具 + } + } + } +} diff --git a/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/HandleEvent.java b/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/HandleEvent.java index 8f338ea..c9713a4 100644 --- a/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/HandleEvent.java +++ b/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/HandleEvent.java @@ -65,7 +65,7 @@ public void onPressFWithoutInv(PlayerSwapHandItemsEvent event) { event.getPlayer().playSound(event.getPlayer().getLocation(), Sound.UI_BUTTON_CLICK, 1f, 1f); return; } - if (!SettingsUtil.getSetting(event.getPlayer(), "DefaultF") && !event.getPlayer().isSneaking()) { + if (!SettingsUtil.getSetting(event.getPlayer(), "DefaultF") && !(event.getPlayer().isSneaking() && event.getPlayer().getLocation().getPitch() == 90)) { return; } event.setCancelled(true); diff --git a/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/InventoryF.java b/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/InventoryF.java index 96c7e2e..ca4aef0 100644 --- a/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/InventoryF.java +++ b/src/main/java/me/xpyex/plugin/invactions/bukkit/listener/InventoryF.java @@ -16,7 +16,7 @@ public void onPressFWithInv(InventoryClickEvent event) { if (event.getClickedInventory() == null) { return; } - if (event.getClick() == ClickType.SWAP_OFFHAND) { //不知道哪个版本加上的 + if (event.getClick() == ClickType.SWAP_OFFHAND) { if (event.getClickedInventory() == event.getWhoClicked().getInventory() || InvUtil.isNotMenu(event.getClickedInventory())) { //仅允许整理自己的背包,或是方块的界面,不允许整理菜单 event.setCancelled(true); SortUtil.sortInv(event.getClickedInventory()); diff --git a/src/main/java/me/xpyex/plugin/invactions/bukkit/util/InvUtil.java b/src/main/java/me/xpyex/plugin/invactions/bukkit/util/InvUtil.java index 8701e23..2197be1 100644 --- a/src/main/java/me/xpyex/plugin/invactions/bukkit/util/InvUtil.java +++ b/src/main/java/me/xpyex/plugin/invactions/bukkit/util/InvUtil.java @@ -1,11 +1,18 @@ package me.xpyex.plugin.invactions.bukkit.util; import com.google.gson.JsonPrimitive; +import java.util.Optional; import me.xpyex.plugin.invactions.bukkit.InvActions; +import me.xpyex.plugin.invactions.bukkit.enums.ItemType; +import me.xpyex.plugin.xplib.bukkit.api.Pair; +import me.xpyex.plugin.xplib.bukkit.util.Util; import me.xpyex.plugin.xplib.bukkit.util.config.ConfigUtil; import me.xpyex.plugin.xplib.bukkit.util.strings.MsgUtil; +import org.bukkit.Material; +import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; public class InvUtil { public static boolean isNotMenu(Inventory inv) { @@ -20,4 +27,40 @@ public static boolean isNotMenu(Inventory inv) { } return className.startsWith("org.bukkit."); } + + public static void swapSlotToMainHand(Player player, int slot) { + Util.checkNull("Player为空,请联系开发者修复", player); + + if (player.getInventory().getHeldItemSlot() == slot) { + return; + } + + ItemStack copiedTool = new ItemStack(player.getInventory().getItemInMainHand()); + ItemStack copiedSlot = new ItemStack(Optional.ofNullable(player.getInventory().getItem(slot)).orElse(new ItemStack(Material.AIR))); + player.getInventory().setItem(slot, copiedTool); + player.getInventory().setItemInMainHand(copiedSlot); + MsgUtil.sendActionBar(player, "&a已自动切换为合适的工具. " + SettingsUtil.SETTING_HELP); + } + + public static int getFastestToolSlot(Player player, Block block, ItemType.ToolType type) { + if (player.getInventory().getItemInMainHand().getType().toString().contains("_" + type)) return player.getInventory().getHeldItemSlot(); + Pair fastest = new Pair<>(0f, -1); //速度, Slot + ItemStack before = new ItemStack(player.getInventory().getItemInMainHand()); + int slot; + for (slot = 0; slot < player.getInventory().getStorageContents().length; slot++) { + ItemStack content = player.getInventory().getStorageContents()[slot]; + if (content == null) continue; + + if (content.getType().toString().contains("_" + type)) { + player.getInventory().setItemInMainHand(content); + float breakSpeed = block.getBreakSpeed(player); + if (fastest.getKey() < breakSpeed) { + fastest = new Pair<>(breakSpeed, slot); + } + } + } + player.getInventory().setItemInMainHand(before); + return fastest.getValue() == -1 ? player.getInventory().getHeldItemSlot() : fastest.getValue(); + } + } diff --git a/src/main/java/me/xpyex/plugin/invactions/bukkit/util/SettingsUtil.java b/src/main/java/me/xpyex/plugin/invactions/bukkit/util/SettingsUtil.java index a412c4d..7d39f31 100644 --- a/src/main/java/me/xpyex/plugin/invactions/bukkit/util/SettingsUtil.java +++ b/src/main/java/me/xpyex/plugin/invactions/bukkit/util/SettingsUtil.java @@ -15,6 +15,7 @@ public class SettingsUtil { static { DEFAULT_SETTINGS.addProperty("AutoFarmer", true); + DEFAULT_SETTINGS.addProperty("AutoTool", true); DEFAULT_SETTINGS.addProperty("CraftDrop", true); DEFAULT_SETTINGS.addProperty("DefaultF", false); DEFAULT_SETTINGS.addProperty("QuickDrop", false); @@ -53,4 +54,10 @@ public static void turnSeverSetting(String setting) { o.addProperty(setting, futureMode); ConfigUtil.saveConfig(InvActions.getInstance(), "config", GsonUtil.parseStr(o), true); } + + public static int getMenuShow(Player player, String setting) { + if (!getServerSetting(setting)) return -1; + + return getSetting(player, setting) ? 1 : 0; + } }