From f4e8ad4920210d783cd29201ddec836b720f3ca1 Mon Sep 17 00:00:00 2001 From: Xanadu13 <104714710+iXanadu13@users.noreply.github.com> Date: Wed, 26 Jul 2023 17:25:06 +0800 Subject: [PATCH] update to v2.1.0 --- .../enderdragon/command/MainCommand.java | 392 ++++++++ .../enderdragon/command/TabCompleter.java | 81 ++ .../xanadu/enderdragon/config/Config.java | 122 +++ .../enderdragon/config/FileUpdater.java | 123 +++ .../pers/xanadu/enderdragon/config/Lang.java | 215 +++++ .../event/DragonDamageByPlayerEvent.java | 56 ++ .../event/PlayerExplodeDragonEvent.java | 38 + .../java/pers/xanadu/enderdragon/gui/GUI.java | 203 +++++ .../xanadu/enderdragon/gui/GUIHolder.java | 20 + .../pers/xanadu/enderdragon/gui/GUISlot.java | 43 + .../xanadu/enderdragon/gui/GUISlotType.java | 29 + .../xanadu/enderdragon/gui/GUIWrapper.java | 138 +++ .../xanadu/enderdragon/gui/holder/Menu.java | 12 + .../enderdragon/gui/holder/MenuEditor.java | 17 + .../enderdragon/gui/holder/RewardEditor.java | 11 + .../enderdragon/gui/slot/DragonSlot.java | 37 + .../enderdragon/gui/slot/EmptySlot.java | 20 + .../xanadu/enderdragon/gui/slot/ItemSlot.java | 34 + .../enderdragon/gui/slot/PageJumpSlot.java | 21 + .../xanadu/enderdragon/gui/slot/TipSlot.java | 64 ++ .../pers/xanadu/enderdragon/hook/Papi.java | 116 +++ .../listener/CreatureSpawnListener.java | 145 +++ .../listener/DragonAttackListener.java | 41 + .../listener/DragonBaseHurtListener.java | 33 + .../DragonDamageByPlayerListener.java | 60 ++ .../listener/DragonDeathListener.java | 163 ++++ .../listener/DragonExplosionHurtListener.java | 94 ++ .../listener/DragonHealListener.java | 26 + .../listener/EndGatewayListener.java | 21 + .../listener/InventoryListener.java | 123 +++ .../enderdragon/listener/PlayerListener.java | 19 + .../listener/PluginDisableListener.java | 16 + .../RespawnAnchorExplodeListener.java | 45 + .../mythiclib/PlayerAttackListener.java | 27 + .../enderdragon/manager/DamageManager.java | 25 + .../enderdragon/manager/DragonManager.java | 463 ++++++++++ .../enderdragon/manager/GlowManager.java | 76 ++ .../enderdragon/manager/GuiManager.java | 76 ++ .../enderdragon/manager/ItemManager.java | 426 +++++++++ .../enderdragon/manager/RewardManager.java | 117 +++ .../enderdragon/manager/TaskManager.java | 93 ++ .../enderdragon/manager/TimerManager.java | 75 ++ .../enderdragon/manager/WorldManager.java | 196 ++++ .../xanadu/enderdragon/metrics/Metrics.java | 849 ++++++++++++++++++ .../nms/BossBar/I_BossBarManager.java | 11 + .../nms/BossBar/v1_12_R1/BossBarManager.java | 105 +++ .../nms/BossBar/v1_13_R1/BossBarManager.java | 103 +++ .../nms/BossBar/v1_13_R2/BossBarManager.java | 103 +++ .../nms/NMSItem/I_NMSItemManager.java | 11 + .../v1_12_R1/CraftNBTTagConfigSerializer.java | 146 +++ .../nms/NMSItem/v1_12_R1/NMSItemManager.java | 35 + .../v1_13_R1/CraftNBTTagConfigSerializer.java | 151 ++++ .../nms/NMSItem/v1_13_R1/NMSItemManager.java | 37 + .../v1_13_R2_above/NMSItemManager.java | 30 + .../RespawnAnchor/I_RespawnAnchorManager.java | 7 + .../v1_16_R1/RespawnAnchorManager.java | 15 + .../v1_16_R2/RespawnAnchorManager.java | 15 + .../v1_16_R3/RespawnAnchorManager.java | 15 + .../v1_17_R1/RespawnAnchorManager.java | 15 + .../v1_18_above/RespawnAnchorManager.java | 10 + .../nms/WorldData/I_WorldDataManager.java | 7 + .../WorldData/v1_12_R1/WorldDataManager.java | 14 + .../WorldData/v1_13_R1/WorldDataManager.java | 14 + .../WorldData/v1_13_R2/WorldDataManager.java | 14 + .../WorldData/v1_14_R1/WorldDataManager.java | 14 + .../WorldData/v1_15_R1/WorldDataManager.java | 14 + .../WorldData/v1_16_R1/WorldDataManager.java | 14 + .../WorldData/v1_16_R2/WorldDataManager.java | 14 + .../WorldData/v1_16_R3/WorldDataManager.java | 14 + .../v1_17_above/WorldDataManager.java | 10 + .../xanadu/enderdragon/reward/Chance.java | 22 + .../xanadu/enderdragon/reward/DistType.java | 28 + .../xanadu/enderdragon/reward/Reward.java | 50 ++ .../xanadu/enderdragon/reward/RewardDist.java | 59 ++ .../enderdragon/reward/dist/Dist_All.java | 36 + .../enderdragon/reward/dist/Dist_Drop.java | 53 ++ .../enderdragon/reward/dist/Dist_Killer.java | 29 + .../enderdragon/reward/dist/Dist_Pack.java | 53 ++ .../enderdragon/reward/dist/Dist_Rank.java | 57 ++ .../reward/dist/Dist_Termwise.java | 39 + .../task/DragonRespawnRunnable.java | 40 + .../enderdragon/task/DragonRespawnTimer.java | 82 ++ .../pers/xanadu/enderdragon/task/Task.java | 70 ++ .../xanadu/enderdragon/task/TaskType.java | 26 + .../xanadu/enderdragon/task/type/Day.java | 24 + .../xanadu/enderdragon/task/type/Hour.java | 23 + .../xanadu/enderdragon/task/type/Minute.java | 26 + .../xanadu/enderdragon/task/type/Month.java | 24 + .../xanadu/enderdragon/task/type/Week.java | 25 + .../xanadu/enderdragon/task/type/Year.java | 23 + .../pers/xanadu/enderdragon/util/AExpJ.java | 63 ++ .../xanadu/enderdragon/util/AliasSample.java | 42 + .../xanadu/enderdragon/util/ColorUtil.java | 63 ++ .../xanadu/enderdragon/util/MathUtil.java | 101 +++ .../xanadu/enderdragon/util/MyDragon.java | 60 ++ .../xanadu/enderdragon/util/MyUpdater.java | 40 + .../pers/xanadu/enderdragon/util/NMSUtil.java | 444 +++++++++ .../pers/xanadu/enderdragon/util/Pair.java | 11 + .../pers/xanadu/enderdragon/util/Version.java | 83 ++ 99 files changed, 7635 insertions(+) create mode 100644 src/main/java/pers/xanadu/enderdragon/command/MainCommand.java create mode 100644 src/main/java/pers/xanadu/enderdragon/command/TabCompleter.java create mode 100644 src/main/java/pers/xanadu/enderdragon/config/Config.java create mode 100644 src/main/java/pers/xanadu/enderdragon/config/FileUpdater.java create mode 100644 src/main/java/pers/xanadu/enderdragon/config/Lang.java create mode 100644 src/main/java/pers/xanadu/enderdragon/event/DragonDamageByPlayerEvent.java create mode 100644 src/main/java/pers/xanadu/enderdragon/event/PlayerExplodeDragonEvent.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/GUI.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/GUIHolder.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/GUISlot.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/GUISlotType.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/GUIWrapper.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/holder/Menu.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/holder/MenuEditor.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/holder/RewardEditor.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/slot/DragonSlot.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/slot/EmptySlot.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/slot/ItemSlot.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/slot/PageJumpSlot.java create mode 100644 src/main/java/pers/xanadu/enderdragon/gui/slot/TipSlot.java create mode 100644 src/main/java/pers/xanadu/enderdragon/hook/Papi.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/CreatureSpawnListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/DragonAttackListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/DragonBaseHurtListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/DragonDamageByPlayerListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/DragonDeathListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/DragonExplosionHurtListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/DragonHealListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/EndGatewayListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/InventoryListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/PlayerListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/PluginDisableListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/RespawnAnchorExplodeListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/listener/mythiclib/PlayerAttackListener.java create mode 100644 src/main/java/pers/xanadu/enderdragon/manager/DamageManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/manager/DragonManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/manager/GlowManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/manager/GuiManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/manager/ItemManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/manager/RewardManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/manager/TaskManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/manager/TimerManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/manager/WorldManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/metrics/Metrics.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/BossBar/I_BossBarManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_12_R1/BossBarManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_13_R1/BossBarManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_13_R2/BossBarManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/NMSItem/I_NMSItemManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_12_R1/CraftNBTTagConfigSerializer.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_12_R1/NMSItemManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R1/CraftNBTTagConfigSerializer.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R1/NMSItemManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R2_above/NMSItemManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/I_RespawnAnchorManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R1/RespawnAnchorManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R2/RespawnAnchorManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R3/RespawnAnchorManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_17_R1/RespawnAnchorManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_18_above/RespawnAnchorManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/I_WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_12_R1/WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_13_R1/WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_13_R2/WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_14_R1/WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_15_R1/WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R1/WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R2/WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R3/WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_17_above/WorldDataManager.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/Chance.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/DistType.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/Reward.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/RewardDist.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_All.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Drop.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Killer.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Pack.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Rank.java create mode 100644 src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Termwise.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/DragonRespawnRunnable.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/DragonRespawnTimer.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/Task.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/TaskType.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/type/Day.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/type/Hour.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/type/Minute.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/type/Month.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/type/Week.java create mode 100644 src/main/java/pers/xanadu/enderdragon/task/type/Year.java create mode 100644 src/main/java/pers/xanadu/enderdragon/util/AExpJ.java create mode 100644 src/main/java/pers/xanadu/enderdragon/util/AliasSample.java create mode 100644 src/main/java/pers/xanadu/enderdragon/util/ColorUtil.java create mode 100644 src/main/java/pers/xanadu/enderdragon/util/MathUtil.java create mode 100644 src/main/java/pers/xanadu/enderdragon/util/MyDragon.java create mode 100644 src/main/java/pers/xanadu/enderdragon/util/MyUpdater.java create mode 100644 src/main/java/pers/xanadu/enderdragon/util/NMSUtil.java create mode 100644 src/main/java/pers/xanadu/enderdragon/util/Pair.java create mode 100644 src/main/java/pers/xanadu/enderdragon/util/Version.java diff --git a/src/main/java/pers/xanadu/enderdragon/command/MainCommand.java b/src/main/java/pers/xanadu/enderdragon/command/MainCommand.java new file mode 100644 index 0000000..5c953be --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/command/MainCommand.java @@ -0,0 +1,392 @@ +package pers.xanadu.enderdragon.command; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.config.Config; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.manager.DragonManager; +import pers.xanadu.enderdragon.manager.GuiManager; +import pers.xanadu.enderdragon.manager.RewardManager; +import pers.xanadu.enderdragon.EnderDragon; +import pers.xanadu.enderdragon.manager.TimerManager; +import pers.xanadu.enderdragon.reward.Chance; +import pers.xanadu.enderdragon.config.FileUpdater; +import pers.xanadu.enderdragon.task.DragonRespawnTimer; +import pers.xanadu.enderdragon.util.MyDragon; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.lang.reflect.Method; + +import static pers.xanadu.enderdragon.EnderDragon.*; + +public class MainCommand implements CommandExecutor { + private Class CraftItemStackClass; + private Class NBTTagCompoundClass; + private Class ItemStackClass_e; + private Method asNMSCopy; + private Method save; + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + if (args.length == 0) { + sendCommandTips(sender); + return false; + } + switch(args[0].toLowerCase()){ +// case "parse" : { +// if(!(sender instanceof Player)) { +// Lang.sendFeedback(sender,Lang.command_only_player); +// return false; +// } +// Player p = (Player) sender; +// if(sender.isOp()){ +//// List entities = p.getNearbyEntities(50,50,50); +//// entities.forEach(entity -> { +//// if(entity instanceof org.bukkit.entity.EnderDragon){ +//// ScoreboardManager sm = server.getScoreboardManager(); +//// CraftScoreboardManager csm = (CraftScoreboardManager) sm; +//// try { +//// Field field = csm.getClass().getDeclaredField("scoreboards"); +//// field.setAccessible(true); +//// Collection sbs = (Collection) field.get(csm); +//// sbs.forEach(sb->{ +//// Team team = sb.getEntryTeam(entity.getUniqueId().toString()); +//// if(team!=null) Bukkit.broadcastMessage(team.getName()); +//// }); +//// } catch (ReflectiveOperationException e) { +//// throw new RuntimeException(e); +//// } +//// } +////// if(entity instanceof org.bukkit.entity.EnderDragon){ +////// Bukkit.broadcastMessage(entity.getName());//1 Special Ender Dragon +////// } +////// if(entity instanceof ComplexEntityPart){ +////// Bukkit.broadcastMessage(entity.getName());//1 Special Ender Dragon +////// } +////// if(entity instanceof ComplexLivingEntity){ +////// Bukkit.broadcastMessage(entity.getName());//8 EnderDragon +////// } +//// }); +// } +// return true; +// } + case "reload" : { + if(!sender.hasPermission("ed.reload")){ + Lang.sendFeedback(sender,Lang.command_no_permission); + return false; + } + if(args.length == 1){ + closeAllInventory(); + reloadAll(); + Lang.sendFeedback(sender,Lang.command_reload_config); + return true; + } + break; + } + case "update" : { + if(!sender.hasPermission("ed.update")){ + Lang.sendFeedback(sender,Lang.command_no_permission); + return false; + } + if(args.length == 1){ + try { + FileUpdater.update(); + } catch (IOException e) { + throw new RuntimeException(e); + } + return true; + } + break; + } + case "respawn" : {//ed respawn [world_name] + if(!sender.hasPermission("ed.respawn")){ + Lang.sendFeedback(sender,Lang.command_no_permission); + return false; + } + if(args.length == 1){ + if(!(sender instanceof Player)){ + Lang.sendFeedback(sender,"§cConsole usage: /ed respawn "); + return false; + } + Player player = (Player) sender; + EnderDragon.getInstance().getDragonManager().initiateRespawn(player); + return true; + } + else if(args.length == 2){ + String world_name = args[1]; + EnderDragon.getInstance().getDragonManager().initiateRespawn(sender,world_name); + return true; + } + else { + int size = args.length; + StringBuilder builder = new StringBuilder(args[1]); + for(int i=2;i + if(args.length == 3 && args[1].equalsIgnoreCase("get")){ + String world_name = args[2]; + DragonRespawnTimer timer = TimerManager.getTimer(world_name); + String value = timer!=null?timer.toString():world_name+": null"; + Lang.sendFeedback(sender,value); + return true; + } + //ed respawn_cd set + else if(args.length == 4 && args[1].equalsIgnoreCase("set")){ + String world_name = args[2]; + World world = Bukkit.getWorld(world_name); + if(world == null){ + Lang.sendFeedback(sender,"§c"+DragonManager.DragonRespawnResult.world_not_found.getMessage()); + return false; + } + if(world.getEnvironment() != World.Environment.THE_END){ + Lang.sendFeedback(sender,"§c"+DragonManager.DragonRespawnResult.world_wrong_env.getMessage()); + return false; + } + int delay = Integer.parseInt(args[3]); + TimerManager.setTimer(world_name,new DragonRespawnTimer(world_name,delay)); + TimerManager.save(); + Lang.sendFeedback(sender,Lang.command_respawn_cd_set.replaceAll("\\{second}",args[3])); + return true; + } + //ed respawn_cd removeAll + else if(args.length == 2 && args[1].equalsIgnoreCase("removeAll")){ + TimerManager.removeAll(); + TimerManager.save(); + Lang.sendFeedback(sender,Lang.command_respawn_cd_removeAll); + return true; + } + //ed respawn_cd remove + else if(args.length == 3 && args[1].equalsIgnoreCase("remove")){ + String world_name = args[2]; + TimerManager.removeTimer(world_name); + TimerManager.save(); + Lang.sendFeedback(sender,Lang.command_respawn_cd_remove.replaceAll("\\{world}",world_name)); + return true; + } + //ed respawn_cd start + else if(args.length == 3 && args[1].equalsIgnoreCase("start")){ + String world_name = args[2]; + DragonRespawnTimer timer = TimerManager.getTimer(world_name); + if(timer == null){ + Lang.sendFeedback(sender,Lang.command_respawn_cd_start_none); + return false; + } + if(timer.isRunning()){ + Lang.sendFeedback(sender,Lang.command_respawn_cd_start_already_started); + return false; + } + TimerManager.startTimer(world_name); + Lang.sendFeedback(sender,Lang.command_respawn_cd_start_succeed); + return true; + } + break; + } + case "drop" : { + if(!(sender instanceof Player)) { + Lang.sendFeedback(sender,Lang.command_only_player); + return false; + } + Player p = (Player) sender; + switch (args[1].toLowerCase()){ + case "gui" : { + if(!sender.hasPermission("ed.drop.gui")){ + Lang.sendFeedback(sender,Lang.command_no_permission); + return false; + } + if(args.length == 2){ + GuiManager.openGui(p, Config.main_gui,false); + return true; + } + if(args.length == 3){ + String key = args[2]; + MyDragon dragon = DragonManager.mp.get(key); + if(dragon == null){ + Lang.sendFeedback(sender, Lang.dragon_not_found); + return false; + } + GuiManager.openGui(p,dragon.drop_gui,key,false); + return true; + } + break; + } + case "clear" : { + if(!sender.hasPermission("ed.drop.edit")){ + Lang.sendFeedback(sender,Lang.command_no_permission); + return false; + } + if(args.length == 3) { + String key = args[2]; + RewardManager.clearItem(key); + Lang.sendFeedback(sender,Lang.command_drop_item_clear); + return true; + } + break; + } + case "add" : { + if(!sender.hasPermission("ed.drop.edit")){ + Lang.sendFeedback(sender,Lang.command_no_permission); + return false; + } + if(args.length == 4) { + if(p.getInventory().getItemInMainHand().getType() == Material.AIR){ + Lang.sendFeedback(p, Lang.command_drop_item_add_empty); + return false; + } + String ChanceStr = args[3]; + String key = args[2]; + double chance = -1; + try { + chance = Double.parseDouble(ChanceStr); + } catch (NumberFormatException ex){ + Lang.sendFeedback(p,Lang.command_drop_item_add_invalid_chance + ChanceStr); + return false; + } + if(chance <= 0) { + Lang.sendFeedback(p,Lang.command_drop_item_add_invalid_chance + ChanceStr); + return false; + } + if(chance > 100) chance = 100; + ItemStack item = p.getItemInHand().clone(); + RewardManager.addItem(key,item,new Chance(chance,ChanceStr)); + Lang.sendFeedback(p,Lang.command_drop_item_add_succeed.replaceAll("\\{chance}",ChanceStr)); + return true; + } + break; + } + case "edit" : { + if(!sender.hasPermission("ed.drop.edit")){ + Lang.sendFeedback(sender,Lang.command_no_permission); + return false; + } + if(args.length == 2){ + GuiManager.openGui(p, Config.main_gui,true); + return true; + } + break; + } + case "remove" : { + if(!sender.hasPermission("ed.drop.edit")){ + Lang.sendFeedback(sender,Lang.command_no_permission); + return false; + } + if(args.length == 4) { + try{ + int idx = Integer.parseInt(args[3]); + boolean b = RewardManager.removeItem(args[2],idx); + if(b) Lang.sendFeedback(sender,Lang.command_drop_item_remove_succeed); + else Lang.sendFeedback(sender,Lang.command_drop_item_remove_fail); + return true; + }catch (NumberFormatException e){ + Lang.sendFeedback(sender,Lang.command_drop_item_remove_invalid_num+args[3]); + return false; + } + } + break; + } + default : break; + } + } + } + sendCommandTips(sender); + return false; + } + private static void sendCommandTips(CommandSender sender){ + sender.sendMessage(Lang.CommandTips1); + sender.sendMessage(Lang.CommandTips2); + sender.sendMessage(Lang.CommandTips3); + sender.sendMessage(Lang.CommandTips4); + } + +} + + +// long st=System.currentTimeMillis(),ed; +// for(int i=0;i<1;i++) { +// try { +// ItemStack item = p.getItemInHand(); +// Class CraftItemStackClass = Class.forName("org.bukkit.craftbukkit.v1_13_R1.inventory.CraftItemStack"); +// Object ci = CraftItemStackClass.cast(item); +// Method asNMSCopy = CraftItemStackClass.getDeclaredMethod("asNMSCopy", ItemStack.class); +// Object ei = asNMSCopy.invoke(ci, item); +// Class NBTTagCompoundClass = Class.forName("net.minecraft.server.v1_13_R1.NBTTagCompound"); +// Method save = ei.getClass().getDeclaredMethod("save", NBTTagCompoundClass); +// Object cpd = save.invoke(ei, NBTTagCompoundClass.newInstance()); +// String str = cpd.toString(); +// p.sendMessage(cpd.toString()); +// } catch (ReflectiveOperationException e) { +// e.printStackTrace(); +// } +// } +// ed=System.currentTimeMillis(); +// Bukkit.broadcastMessage("test #1: "+(ed-st)+"ms"); +// st=System.currentTimeMillis(); +// for(int i=0;i<1e5;i++) { +// ItemStack item = p.getItemInHand(); +// net.minecraft.server.v1_13_R1.ItemStack ni = CraftItemStack.asNMSCopy(item); +// NBTTagCompound cpd = ni.save(new NBTTagCompound()); +// String str = cpd.toString(); +// } +// ed=System.currentTimeMillis(); +// Bukkit.broadcastMessage("test #2: "+(ed-st)+"ms"); +// +// try { +// CraftItemStackClass=Class.forName("org.bukkit.craftbukkit.v1_13_R1.inventory.CraftItemStack"); +// asNMSCopy = CraftItemStackClass.getDeclaredMethod("asNMSCopy", ItemStack.class); +// NBTTagCompoundClass = Class.forName("net.minecraft.server.v1_13_R1.NBTTagCompound"); +// ItemStackClass_e = Class.forName("net.minecraft.server.v1_13_R1.ItemStack"); +// save = ItemStackClass_e.getDeclaredMethod("save", NBTTagCompoundClass); +// } catch (ReflectiveOperationException e) { +// e.printStackTrace(); +// } +// for(int i=0;i<1e5;i++) { +// try { +// ItemStack item = p.getItemInHand(); +// Object ci = CraftItemStackClass.cast(item); +// Object ei = asNMSCopy.invoke(ci, item); +// Object cpd = save.invoke(ei, NBTTagCompoundClass.newInstance()); +// String str = cpd.toString(); +// //p.sendMessage(cpd.toString()); +// } catch (ReflectiveOperationException e) { +// e.printStackTrace(); +// } +// } +// ed=System.currentTimeMillis(); +// Bukkit.broadcastMessage("test #3: "+(ed-st)+"ms"); + + +// st=System.currentTimeMillis(); +// +// for(int i=0;i<1;i++) { +// ItemStack item = p.getItemInHand(); +// String str = new NbtItemStack(item).getOrCreateTag().toString(); +// //Bukkit.broadcastMessage(str); +// p.sendMessage(str); +// } +// ed=System.currentTimeMillis(); +// Bukkit.broadcastMessage("test #3: "+(ed-st)+"ms"); + +// net.minecraft.server.v1_16_R3.ItemStack nmsItem = CraftItemStack.asNMSCopy(item); +// NBTTagCompound cpd = nmsItem.save(new NBTTagCompound()); + +// net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item); +// NBTTagCompound cpd = nmsItem.b(new NBTTagCompound()); +// p.sendMessage(cpd.toString()); \ No newline at end of file diff --git a/src/main/java/pers/xanadu/enderdragon/command/TabCompleter.java b/src/main/java/pers/xanadu/enderdragon/command/TabCompleter.java new file mode 100644 index 0000000..e389144 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/command/TabCompleter.java @@ -0,0 +1,81 @@ +package pers.xanadu.enderdragon.command; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import pers.xanadu.enderdragon.manager.DragonManager; +import pers.xanadu.enderdragon.manager.WorldManager; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class TabCompleter implements org.bukkit.command.TabCompleter { + + private static final List arguments_ed = Arrays.asList("drop", "reload", "respawn", "respawn_cd", "update"); + private static final List arguments_drop = Arrays.asList("add", "clear", "edit", "remove", "gui"); + private static final List arguments_respawn_cd = Arrays.asList("get","remove","removeAll","set","start"); + + @Override + public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { + + List result = new ArrayList<>(); + if (args.length == 1) { + for (String s : arguments_ed) { + if (s.toLowerCase().startsWith(args[0].toLowerCase())) { + result.add(s); + } + } + return result; + } + else if (args.length == 2){ + if(args[0].equalsIgnoreCase("drop")) { + for (String s : arguments_drop) { + if (s.toLowerCase().startsWith(args[1].toLowerCase())) { + result.add(s); + } + } + } + else if(args[0].equalsIgnoreCase("respawn")){ + for(String s : WorldManager.worlds){ + if (s.toLowerCase().startsWith(args[1].toLowerCase())) { + result.add(s); + } + } + } + else if(args[0].equalsIgnoreCase("respawn_cd")){ + for(String s : arguments_respawn_cd){ + if (s.toLowerCase().startsWith(args[1].toLowerCase())) { + result.add(s); + } + } + } + return result; + } + else if(args.length == 3){ + if("drop".equals(args[0])){ + String str = args[1].toLowerCase(); + if("add".equals(str) || "clear".equals(str) || "gui".equals(str) || "remove".equals(str)){ + for (String s : DragonManager.dragon_names) { + if (s.toLowerCase().startsWith(args[2].toLowerCase())) { + result.add(s); + } + } + } + } + else if("respawn_cd".equals(args[0])){ + String str = args[1].toLowerCase(); + if("get".equals(str) || "remove".equals(str) || "removeAll".equals(str) || "set".equals(str) || "start".equals(str)){ + for (String s : WorldManager.worlds) { + if (s.toLowerCase().startsWith(args[2].toLowerCase())) { + result.add(s); + } + } + } + } + return result; + } + return null; + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/config/Config.java b/src/main/java/pers/xanadu/enderdragon/config/Config.java new file mode 100644 index 0000000..287d6f6 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/config/Config.java @@ -0,0 +1,122 @@ +package pers.xanadu.enderdragon.config; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; + +import java.io.*; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.nio.file.Files; +import java.util.*; + +import static pers.xanadu.enderdragon.EnderDragon.plugin; +import static pers.xanadu.enderdragon.config.Lang.error; + +public class Config { + public static String version; + public static String lang; + public static boolean debug; + public static boolean advanced_setting_world_env_fix; + public static boolean advanced_setting_save_respawn_status; + public static boolean advanced_setting_glowing_fix; + public static String damage_visible_mode; + public static int damage_statistics_limit; + public static String special_dragon_jude_mode; + public static boolean auto_respawn_enable; + public static String auto_respawn_world_the_end_name; + public static String auto_respawn_respawn_time; + public static boolean auto_respawn_invulnerable; + public static boolean respawn_cd_enable; + public static boolean resist_player_respawn; + public static boolean resist_dragon_breath_gather; + public static boolean hook_plugins_MythicLib; + public static String main_gui; + public static String item_format_data; + public static List dragon_setting_file; + public static List blacklist_worlds; + public static void reload(FileConfiguration file){ + Field[] fields = Config.class.getFields(); + for(Field field : fields){ + Type type = field.getType(); + if(type.equals(java.lang.String.class)){ + try{ + field.set(null,""); + }catch (Exception ignored){} + } + else if(type.equals(java.util.List.class)){ + try{ + field.set(null,new ArrayList()); + }catch (Exception ignored){} + } + } + Iterator it = file.getKeys(true).iterator(); + while (it.hasNext()){ + String str = it.next(); + try{ + if(file.isConfigurationSection(str)) continue; + Config.class.getField(str.replace(".","_")).set(null, file.get(str)); + }catch (Exception e){ + error("Config loading error! Key: "+str); + } + } + switch (special_dragon_jude_mode.toLowerCase()){ + case "pc" : + case "weight" : break; + default: { + error("Wrong special_dragon_jude_mode type in config.yml! Only \"weight\" or \"pc\" is valid."); + } + } + } + + public static void saveResource(String source,String to,boolean replace){ + if (source == null || source.equals("")) return; + source = source.replace('\\', '/'); + InputStream in = plugin.getResource(source); + if (in == null) return; + File outFile = new File("plugins/EnderDragon", to); + int lastIndex = to.lastIndexOf('/'); + File outDir = new File("plugins/EnderDragon", to.substring(0, Math.max(lastIndex, 0))); + if (!outDir.exists()) { + outDir.mkdirs(); + } + try { + if (!outFile.exists() || replace) { + OutputStream out = new FileOutputStream(outFile); + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + out.close(); + in.close(); + } + } catch (IOException ignored) {} + } + public static void copyFile(String source, String dest,boolean replace) { + if (source == null || source.equals("")) return; + source = source.replace('\\', '/'); + File inFile = new File("plugins/EnderDragon", source); + File outFile = new File("plugins/EnderDragon", dest); + int lastIndex = dest.lastIndexOf('/'); + File outDir = new File("plugins/EnderDragon", dest.substring(0, Math.max(lastIndex, 0))); + if (!outDir.exists()) { + outDir.mkdirs(); + } + try { + if (!outFile.exists() || replace) { + InputStream in = new FileInputStream(inFile); + OutputStream out = new FileOutputStream(outFile); + byte[] buf = new byte[1024]; + int len; + while ((len = in.read(buf)) > 0) { + out.write(buf, 0, len); + } + out.close(); + in.close(); + } + } catch (IOException ignored) { + Lang.error("Failed to copy file: "+inFile.getPath()+" -> "+outFile.getPath()); + } + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/config/FileUpdater.java b/src/main/java/pers/xanadu/enderdragon/config/FileUpdater.java new file mode 100644 index 0000000..3f89f14 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/config/FileUpdater.java @@ -0,0 +1,123 @@ +package pers.xanadu.enderdragon.config; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import pers.xanadu.enderdragon.manager.DragonManager; +import pers.xanadu.enderdragon.EnderDragon; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.io.*; +import java.util.List; + +import static pers.xanadu.enderdragon.EnderDragon.*; + +public class FileUpdater { + public static void update() throws IOException { + FileConfiguration config_old = plugin.getConfig(); + if("2.0.4".equals(config_old.getString("version"))){ + Config.saveResource("config.yml","new/config.yml",true); + File config_new_F = new File(plugin.getDataFolder(),"new/config.yml"); + FileConfiguration config_new = YamlConfiguration.loadConfiguration(config_new_F); + config_new.set("lang",config_old.getString("lang")); + config_new.set("damage_visible_mode",config_old.getString("damage_visible_mode")); + String judge_mode = config_old.getString("special_dragon_jude_mode"); + if("edge".equals(judge_mode)) judge_mode = "weight";//"edge" is deprecated + config_new.set("special_dragon_jude_mode",judge_mode); + config_new.set("dragon_setting_file",config_old.getStringList("dragon_setting_file")); + config_new.set("auto_respawn.enable",config_old.getBoolean("auto_respawn.enable")); + config_new.set("auto_respawn.world_the_end_name",config_old.getString("auto_respawn.world_the_end_name")); + config_new.set("auto_respawn.respawn_time",config_old.getString("auto_respawn.respawn_time")); + config_new.set("auto_respawn.invulnerable",config_old.getBoolean("auto_respawn.invulnerable")); + config_new.set("resist_player_respawn",config_old.getBoolean("resist_player_respawn")); + config_new.set("resist_dragon_breath_gather",config_old.getBoolean("resist_dragon_breath_gather")); + config_new.set("main_gui",config_old.getString("main_gui")); + config_new.save(config_new_F); + } + else Lang.error("The version of config.yml is not supported!"); + File folder = new File(plugin.getDataFolder(),"setting"); + if(folder.exists()){ + File[] files = folder.listFiles(); + if(files != null){ + for(File file : files){ + FileConfiguration config = YamlConfiguration.loadConfiguration(file); + String ver = config.getString("version"); + if(!"2.0.1".equals(ver)) { + Lang.error("The version of setting/"+file.getName()+" is not supported!"); + continue; + } + String name = file.getName(); + Config.copyFile("setting/"+name,"new/setting/"+name,true); + } + File new_folder = new File(plugin.getDataFolder(),"new/setting/"); + files = new_folder.listFiles(); + if(files != null){ + for(File file : files){ + FileOutputStream out = new FileOutputStream(file,true); + out.write(("\n\n" + + "reward_dist:\n" + + " # enable: [all,drop,killer,pack,rank,termwise]\n" + + " # all: Give to all participants in dragon slaying.\n" + + " # drop: Dropped item, players can grab it casually.\n" + + " # killer: Only give to the final killer.\n" + + " # pack: Pack all items that trigger drop and distribute them to players weighted based on their damage percentage.\n" + + " # rank: Strictly based on player damage ranking, give the top few players with the highest damage.\n" + + " # termwise: Assign the items that trigger the drop ONE BY ONE to the player based on the weighted proportion of damage.\n" + + " type: killer\n" + + " drop:\n" + + " # Whether the dropped item glows.\n" + + " # Refer to the previous 'glow_color' for configuration method\n" + + " glow: green\n" + + " pack:\n" + + " # the number of player(s) can be selected at most\n" + + " max_num: 1\n" + + " rank:\n" + + " # Top few can receive rewards\n" + + " max_num: 1\n" + + "\n" + ).getBytes()); + out.close(); + FileConfiguration fc = YamlConfiguration.loadConfiguration(file); + fc.set("version","2.1.0"); + fc.set("move_speed_modify",null); + fc.save(file); + } + } + } + } + String lang_name = config_old.getString("lang","English") + ".yml"; + FileConfiguration lang_old = lang; + if("2.0.0".equals(lang_old.getString("version"))){ + Config.saveResource("lang/"+lang_name,"new/lang/"+lang_name,true); + File lang_new_F = new File(plugin.getDataFolder(),"new/lang/"+lang_name); + FileConfiguration lang_new = YamlConfiguration.loadConfiguration(lang_new_F); + lang_old.getKeys(true).forEach(key->{ + Object obj = lang_old.get(key); + if(obj instanceof String){ + lang_new.set(key,obj); + } + }); + lang_new.set("version","2.1.0"); + lang_new.save(lang_new_F); + } + else Lang.error("The version of "+lang_name+" is not supported!"); + FileConfiguration data_old = EnderDragon.data; + if("2.0.0".equals(data_old.getString("version"))){ + File new_folder = new File(plugin.getDataFolder(),"new/reward"); + for (MyDragon myDragon : DragonManager.dragons) { + String key = myDragon.unique_name; + List list = data.getStringList(key); + File new_data = new File(new_folder,key+".yml"); + FileConfiguration fc = YamlConfiguration.loadConfiguration(new_data); + fc.set("version","2.1.0"); + fc.set("list",list); + fc.save(new_data); + data_old.set(key,null); + } + data_old.set("version","2.1.0"); + data_old.save(new File(plugin.getDataFolder(),"new/data.yml")); + } + else Lang.error("The version of data.yml is not supported!"); + Lang.info("New config files are generated in plugins/EnderDragon/new."); + Lang.error("Attention: Please confirm the accuracy before using new config!"); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/config/Lang.java b/src/main/java/pers/xanadu/enderdragon/config/Lang.java new file mode 100644 index 0000000..b604c08 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/config/Lang.java @@ -0,0 +1,215 @@ +package pers.xanadu.enderdragon.config; + +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import pers.xanadu.enderdragon.util.ColorUtil; + +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static pers.xanadu.enderdragon.EnderDragon.*; +import static pers.xanadu.enderdragon.EnderDragon.server; + +public class Lang { + public static String version; + public static String plugin_prefix; + public static String plugin_wrong_file_version; + public static String plugin_read_file; + public static String plugin_item_read_error; + public static String plugin_checking_update; + public static String plugin_check_update_fail; + public static String plugin_out_of_date; + public static String plugin_up_to_date; + public static String plugin_disable; + public static String plugin_file_save_error; + public static String command_no_permission; + public static String command_reload_config; + public static String command_only_player; + public static String command_drop_item_add_empty; + public static String command_drop_item_add_invalid_chance; + public static String command_drop_item_add_succeed; + public static String command_drop_item_clear; + public static String command_drop_item_remove_invalid_num; + public static String command_drop_item_remove_fail; + public static String command_drop_item_remove_succeed; + public static String command_respawn_cd_disable; + public static String command_respawn_cd_remove; + public static String command_respawn_cd_removeAll; + public static String command_respawn_cd_retry; + public static String command_respawn_cd_set; + public static String command_respawn_cd_start_already_started; + public static String command_respawn_cd_start_none; + public static String command_respawn_cd_start_succeed; + + + + + public static String gui_default_title; + public static String gui_not_found; + public static String gui_item_lore; + public static String gui_item_cmd_lore; + + public static String dragon_damage_display; + public static String dragon_player_inv_full; + public static String dragon_no_killer; + public static String dragon_auto_respawn; + public static String dragon_not_found; + public static String dragon_damage_statistics_text; + public static List dragon_damage_statistics_hover_prefix; + public static String dragon_damage_statistics_hover_mt; + public static List dragon_damage_statistics_hover_suffix; + public static String dragon_damage_statistics_hover_exceeds_limit; + public static String world_env_fix_enable; + + + + public static String CommandTips1; + public static String CommandTips2; + public static String CommandTips3; + public static String CommandTips4; + public static void reload(FileConfiguration file){ + Field[] fields = Lang.class.getFields(); + for(Field field : fields){ + Type type = field.getType(); + if(type.equals(java.lang.String.class)){ + try{ + field.set(null,""); + }catch (Exception ignored){} + } + else if(type.equals(java.util.List.class)){ + try{ + field.set(null,new ArrayList()); + }catch (Exception ignored){} + } + } + Iterator it = file.getKeys(true).iterator(); + while (it.hasNext()){ + String str = it.next(); + try{ + if(file.isConfigurationSection(str)) continue; + if(file.isString(str)) Lang.class.getField(str.replace(".","_")).set(null, ColorUtil.transGradient(file.getString(str))); + else if(file.isList(str)){ + List list = file.getStringList(str); + list.forEach(s-> s = ColorUtil.transGradient(s)); + Lang.class.getField(str.replace(".","_")).set(null, list); + } + }catch (Exception e){ + error("Language loading error! Key: "+str); + } + } + CommandTips1 = ColorUtil.transGradient(lang.getString("CommandTips1","§e/ed reload §a- reload the config")); + CommandTips2 = ColorUtil.transGradient(lang.getString("CommandTips2","§e/ed respawn §a- respawn a dragon")); + CommandTips3 = ColorUtil.transGradient(lang.getString("CommandTips3","§e/ed drop gui §a- view the drop_item")); + CommandTips4 = ColorUtil.transGradient(lang.getString("CommandTips4","§e/ed drop add §a- add drop_item to one dragon")); + } + public static void sendMessage(String str) { + if(str == null) { + Bukkit.getConsoleSender().sendMessage(Lang.plugin_prefix + "null"); + return; + } + if(str.contains("\\n")){ + String[] strings = str.split("\\\\n"); + for(String s : strings){ + sendMessage(s); + } + } + else Bukkit.getConsoleSender().sendMessage(Lang.plugin_prefix + str); + } + public static void info(String str){ + if(str == null) { + Bukkit.getConsoleSender().sendMessage("§a[EnderDragon] " + "null"); + return; + } + if(str.contains("\\n")){ + String[] strings = str.split("\\\\n"); + for(String s : strings){ + info(s); + } + } + else Bukkit.getConsoleSender().sendMessage("§a[EnderDragon] "+str); + } + public static void warn(String str){ + if(str == null) { + Bukkit.getConsoleSender().sendMessage("§e[EnderDragon] " + "null"); + return; + } + if(str.contains("\\n")){ + String[] strings = str.split("\\\\n"); + for(String s : strings){ + warn(s); + } + } + else Bukkit.getConsoleSender().sendMessage("§e[EnderDragon] "+str); + } + public static void error(String str){ + if(str == null) { + Bukkit.getConsoleSender().sendMessage("§c[EnderDragon] " + "null"); + return; + } + if(str.contains("\\n")){ + String[] strings = str.split("\\\\n"); + for(String s : strings){ + error(s); + } + } + else Bukkit.getConsoleSender().sendMessage("§c[EnderDragon] "+str); + } + public static void debug(String str){ + if(Config.debug) Bukkit.getLogger().info(str); + } + public static void sendFeedback(CommandSender sender,String str){ + if(str == null) { + sender.sendMessage(Lang.plugin_prefix + "null"); + return; + } + if(str.contains("\\n")){ + String[] strings = str.split("\\\\n"); + for(String s : strings){ + sender.sendMessage(Lang.plugin_prefix + s); + } + } + else sender.sendMessage(Lang.plugin_prefix + str); + } + public static void broadcastMSG(String str){ + if(str == null) { + Bukkit.broadcastMessage(Lang.plugin_prefix + "null"); + return; + } + if(str.contains("\\n")){ + String[] strings = str.split("\\\\n"); + for(String s : strings){ + broadcastMSG(s); + } + } + else Bukkit.broadcastMessage(Lang.plugin_prefix + str); + } + public static void broadcastMSG(List list){ + if(list == null) return; + for(String str : list){ + Bukkit.broadcastMessage(Lang.plugin_prefix + str); + } + } + public static void runCommands(List list, Player p){ + if(list == null) return; + for (String cmd : list) { + if(cmd.equals("")) continue; + if(!cmd.contains("%player%")) server.dispatchCommand(server.getConsoleSender(),cmd); + else{ + if(p != null) server.dispatchCommand(server.getConsoleSender(),cmd.replaceAll("%player%",p.getName())); + } + } + } + public static void runCommands(List list){ + if(list == null) return; + for(String cmd : list){ + if(cmd.equals("")) continue; + server.dispatchCommand(server.getConsoleSender(),cmd); + } + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/event/DragonDamageByPlayerEvent.java b/src/main/java/pers/xanadu/enderdragon/event/DragonDamageByPlayerEvent.java new file mode 100644 index 0000000..9d53ec3 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/event/DragonDamageByPlayerEvent.java @@ -0,0 +1,56 @@ +package pers.xanadu.enderdragon.event; + +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityDamageByEntityEvent; + +public final class DragonDamageByPlayerEvent extends EntityDamageByEntityEvent { + private static final HandlerList handlers = new HandlerList(); + private boolean cancel = false; + private final Player damager; + private final EnderDragon dragon; + private final DamageCause cause; + private final double finalDamage; + + public DragonDamageByPlayerEvent(final Player damager, final EnderDragon dragon, final DamageCause cause, final double finalDamage) { + super(damager, dragon, cause, finalDamage); + this.damager = damager; + this.dragon = dragon; + this.cause = cause; + this.finalDamage = finalDamage; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public void setCancelled(final boolean cancel) { + this.cancel = cancel; + } + + public boolean isCancelled() { + return cancel; + } + + public Player getDamager() { + return damager; + } + + public EnderDragon getDragon() { + return dragon; + } + + public DamageCause getDamagerCause() { + return cause; + } + @Override + public double getDamage() { + return finalDamage; + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/event/PlayerExplodeDragonEvent.java b/src/main/java/pers/xanadu/enderdragon/event/PlayerExplodeDragonEvent.java new file mode 100644 index 0000000..39bdaeb --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/event/PlayerExplodeDragonEvent.java @@ -0,0 +1,38 @@ +package pers.xanadu.enderdragon.event; + +import org.bukkit.Location; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; + +public final class PlayerExplodeDragonEvent { + long _time; + Player _player; + EnderDragon _dragon; + Location _loc; + public PlayerExplodeDragonEvent(long time,Player player,EnderDragon dragon,Location loc){ + _time = time; + _player = player; + _dragon = dragon; + _loc = loc; + } + public long getTime(){ + return _time; + } + public Player getPlayer(){ + return _player; + } + public EnderDragon getEnderDragon(){ + return _dragon; + } + public Location getLocation(){ + return _loc; + } +// private static final class MyComparator implements Comparator{ +// @Override +// public int compare(final PlayerExplodeDragonEvent e1,final PlayerExplodeDragonEvent e2){ +// if(e2._time>e1._time) return 1; +// else if(e2._time==e1._time) return 0; +// return -1; +// } +// } +} diff --git a/src/main/java/pers/xanadu/enderdragon/gui/GUI.java b/src/main/java/pers/xanadu/enderdragon/gui/GUI.java new file mode 100644 index 0000000..7e5906a --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/gui/GUI.java @@ -0,0 +1,203 @@ +package pers.xanadu.enderdragon.gui; + +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.gui.slot.DragonSlot; +import pers.xanadu.enderdragon.manager.DragonManager; +import pers.xanadu.enderdragon.manager.ItemManager; +import pers.xanadu.enderdragon.gui.slot.EmptySlot; +import pers.xanadu.enderdragon.gui.slot.ItemSlot; +import pers.xanadu.enderdragon.reward.Reward; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +public class GUI { + protected String title; + protected int maxPage; + protected int page; + protected int size; + protected ArrayList pagedItems; + protected ArrayList pagedData; + protected List slots; + protected Inventory inv; + protected HashSet dynamics; + + protected GUI(String str,int size,int maxPage){ + this.slots = new ArrayList<>(); + this.pagedItems = new ArrayList<>(); + this.pagedData = new ArrayList<>(); + this.dynamics = new HashSet<>(); + this.title = str; + this.size = size; + this.maxPage = maxPage; + this.page = 0; + } + public GUISlot getSlot(int index){ + GUISlot slot = this.slots.get(index); + if(slot == null) return new EmptySlot(); + return slot; + } + public void setPage(int a) { + this.page = a; + for(int i=0;i= this.pagedItems.size()) { + this.pagedItems.add(new ItemStack[this.size]); + } + for(int j = 0 ; j < this.slots.size() ; j++){ + GUISlot slot = this.slots.get(j); + if (slot instanceof ItemSlot) { + ItemStack itemStack = this.pagedItems.get(i)[j]; + if (itemStack == null) { + this.pagedItems.get(i)[j] = item; + return; + } + } + } + } + } + protected void addDragon(ItemStack item,String unique_name) { + for(int i = 0 ; i < this.maxPage ; i++){ + if (i >= this.pagedItems.size()) { + this.pagedItems.add(new ItemStack[this.size]); + this.pagedData.add(new String[this.size]); + } + for(int j = 0 ; j < this.slots.size() ; j++){ + if (this.slots.get(j) instanceof DragonSlot) { + ItemStack itemStack = this.pagedItems.get(i)[j]; + if (itemStack == null) { + //itemStack = item;(可以吗?) + this.pagedItems.get(i)[j] = item; + this.pagedData.get(i)[j] = unique_name; + return; + } + } + } + } + } + public String getData(int page,int index){ + return this.pagedData.get(page)[index]; + } + public int getSize() { + return this.size; + } + public int getPage(){ + return this.page; + } + public void prev() { + if (this.page > 0) { + this.setPage(this.page - 1); + } + } + + public void addPage() { + if (this.pagedItems.size() >= this.maxPage) { + return; + } + this.pagedItems.add(new ItemStack[this.size]); + } + + public void next() { + if (this.page < this.pagedItems.size() - 1) { + this.setPage(this.page + 1); + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/gui/GUIHolder.java b/src/main/java/pers/xanadu/enderdragon/gui/GUIHolder.java new file mode 100644 index 0000000..353bfe8 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/gui/GUIHolder.java @@ -0,0 +1,20 @@ +package pers.xanadu.enderdragon.gui; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +public abstract class GUIHolder implements InventoryHolder { + private final GUI gui; + + public Inventory getInventory() { + return this.gui.getInventory(); + } + + public GUI getGUI() { + return this.gui; + } + + public GUIHolder(GUI gui) { + this.gui = gui; + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/gui/GUISlot.java b/src/main/java/pers/xanadu/enderdragon/gui/GUISlot.java new file mode 100644 index 0000000..a72d09a --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/gui/GUISlot.java @@ -0,0 +1,43 @@ +package pers.xanadu.enderdragon.gui; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.gui.slot.*; + +public abstract class GUISlot { + private final GUISlotType guiSlotType; + protected DataType data_type; + public abstract ItemStack getItem(); + public abstract ItemStack getItemOnDisable(); + protected GUISlot(GUISlotType type){ + this.guiSlotType = type; + } + public final GUISlotType getType(){ + return this.guiSlotType; + } + public static GUISlot parse(ConfigurationSection section){ + if(section == null) return new EmptySlot(); + GUISlotType guiSlotType = GUISlotType.getByName(section.getString("type")); + switch (guiSlotType) { + case ITEM_SLOT : { + return new ItemSlot(section); + } + case DRAGON_SLOT : { + return new DragonSlot(section); + } + case PAGE_PREV : + case PAGE_NEXT : + case PAGE_TIP : + case TIP : { + return new TipSlot(guiSlotType, section); + } + case PAGE_JUMP : { + return new PageJumpSlot(section); + } + } + return new EmptySlot(); + } + protected enum DataType{ + DEFAULT,NBT,ADVANCED + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/gui/GUISlotType.java b/src/main/java/pers/xanadu/enderdragon/gui/GUISlotType.java new file mode 100644 index 0000000..b71bd9a --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/gui/GUISlotType.java @@ -0,0 +1,29 @@ +package pers.xanadu.enderdragon.gui; + +import java.util.Map; +import java.util.TreeMap; + +public enum GUISlotType { + TIP, + PAGE_TIP, + PAGE_PREV, + PAGE_NEXT, + PAGE_JUMP, + EMPTY, + ITEM_SLOT, + DRAGON_SLOT; + private static final Map mp = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + public static GUISlotType getByName(String str){ + if(str == null) return EMPTY; + return mp.getOrDefault(str.replaceAll("_",""),EMPTY); + } + static{ + GUISlotType[] values = values(); + for (GUISlotType guiSlotType : values) { + String name = guiSlotType.name(); + String target = "_"; + String replacement = ""; + mp.put(name.replaceAll(target, replacement), guiSlotType); + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/gui/GUIWrapper.java b/src/main/java/pers/xanadu/enderdragon/gui/GUIWrapper.java new file mode 100644 index 0000000..f55a518 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/gui/GUIWrapper.java @@ -0,0 +1,138 @@ +package pers.xanadu.enderdragon.gui; + +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.gui.holder.MenuEditor; +import pers.xanadu.enderdragon.gui.holder.Menu; +import pers.xanadu.enderdragon.gui.holder.RewardEditor; +import pers.xanadu.enderdragon.gui.slot.EmptySlot; + +import java.util.HashMap; +import java.util.List; + +public class GUIWrapper extends GUI{ + private final String name; + private final String key; + private int type; + private int[] item_idx; + private int item_size; + + public String getName() { + return this.name; + } + public GUIWrapper(GUIWrapper a, String key, boolean editor){ + super(a.title, a.size, a.maxPage); + if(editor) this.inv = Bukkit.createInventory(new MenuEditor(this,key), this.size, this.title); + else this.inv = Bukkit.createInventory(new Menu(this), this.size, this.title); + this.slots.addAll(a.slots); + this.dynamics.addAll(a.dynamics); + this.name = a.name; + this.key = key; + this.type = a.type; + this.item_idx = a.item_idx; + this.item_size = a.item_size; + this.init(); + this.resetPagedItem(type,key,editor); + this.setPage(0); + } + public GUIWrapper(GUIWrapper a, ItemStack item) { + super(a.title, a.size, a.maxPage); + this.inv = Bukkit.createInventory(new RewardEditor(this), this.size, this.title); + this.slots.addAll(a.slots); + this.dynamics.addAll(a.dynamics); + this.name = a.name; + this.key = null; + this.type = a.type; + this.item_idx = a.item_idx; + this.item_size = a.item_size; + this.init(); + this.resetPagedItem(item); + this.setPage(0); + } + @Deprecated + public GUIWrapper(GUIWrapper a, String key) { + super(a.title, a.size, a.maxPage); + this.inv = Bukkit.createInventory(new Menu(this), this.size, this.title); + this.slots.addAll(a.slots); + this.dynamics.addAll(a.dynamics); + this.name = a.name; + this.key = key; + this.type = a.type; + this.item_idx = a.item_idx; + this.item_size = a.item_size; + this.init(); + this.resetPagedItem(type,key,false); + this.setPage(0); + } + public GUIWrapper(ConfigurationSection config) { + super(config.getString("Title", Lang.gui_default_title).replaceAll("&", "§"), calcline(config.getStringList("Slots").size()) * 9, config.getInt("Page", 1000)); + this.type = 0; + this.name = config.getName(); + this.key = null; + this.inv = Bukkit.createInventory(new Menu(this), this.size, this.title); + for(int i = 0 ; i < this.size ; i++){ + slots.add(new EmptySlot()); + } + ConfigurationSection section = config.getConfigurationSection("Items"); + HashMap hash = new HashMap<>(); + if (section == null) return; + for (String s : section.getKeys(false)) { + GUISlot slot = GUISlot.parse(section.getConfigurationSection(s)); + hash.put(s.charAt(0), slot); + } + int n2 = 0; + List stringList = config.getStringList("Slots"); + for (String line : stringList) { + int i; + for (i = 0; i < line.length() && i < 9; ++i) { + char value = line.charAt(i); + this.slots.set(n2++, (hash.getOrDefault(value, new EmptySlot()))); + } + while(i ++ < 9){ + this.slots.set(n2++, new EmptySlot()); + } + } + boolean b = false; + for(int i = 0 ; i < slots.size(); i++){ + GUISlotType type = this.slots.get(i).getType(); + if(type == GUISlotType.PAGE_PREV || type == GUISlotType.PAGE_NEXT || type == GUISlotType.PAGE_TIP){ + this.dynamics.add(i); + } + else if(type == GUISlotType.ITEM_SLOT){ + this.type = 1; + } + else if(type == GUISlotType.DRAGON_SLOT){ + this.type = 2; + } + else if (type == GUISlotType.PAGE_JUMP) { + b = true; + } + } + this.item_idx = new int[size]; + int cur = -1; + for(int i=0;i()); + int times = data.getInt("times"); + Lang.runCommands(myDragon.spawn_cmd); + for(String str : myDragon.spawn_broadcast_msg){ + Lang.broadcastMSG(str.replaceAll("%times%",String.valueOf(times))); + } + dragon.setCustomName(myDragon.display_name); + setAttribute(dragon, Attribute.GENERIC_MAX_HEALTH, myDragon.max_health); + dragon.setHealth(myDragon.spawn_health); + + //modifyAttribute(dragon, Attribute.GENERIC_MOVEMENT_SPEED, myDragon.move_speed_modify);// + + modifyAttribute(dragon, Attribute.GENERIC_ARMOR, myDragon.armor_modify); + + modifyAttribute(dragon, Attribute.GENERIC_ARMOR_TOUGHNESS, myDragon.armor_toughness_modify); + String color = myDragon.glow_color.toUpperCase(); + if(!color.equals("NONE")) setGlowingColor(dragon,getGlowColor(color)); + else dragon.setGlowing(false); + String bossBar_color = myDragon.bossbar_color.toUpperCase(); + String bossBar_style = myDragon.bossbar_style.toUpperCase(); + + if(Version.mcMainVersion >= 14){ + BossBar bossBar = dragon.getBossBar(); + if(bossBar != null){ + bossBar.setColor(BarColor.valueOf(bossBar_color)); + bossBar.setStyle(BarStyle.valueOf(bossBar_style)); + } + } + else if(Version.mcMainVersion >= 12){ + getInstance().getBossBarManager().setBossBar(dragon.getWorld(),myDragon.display_name,bossBar_color,bossBar_style); + } + //dragon.getMetadata(); + + } + @EventHandler(priority = EventPriority.HIGHEST) + public void OnCrystalPlaced(final PlayerInteractEvent e){ + if(!Config.resist_player_respawn) return; + if(e.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if(e.getMaterial() != Material.END_CRYSTAL) return; + if(e.getClickedBlock() == null) return; + Material blockType = e.getClickedBlock().getType(); + if(blockType != Material.OBSIDIAN && blockType != Material.BEDROCK) return; + World world = e.getPlayer().getWorld(); + if(world.getEnvironment() != World.Environment.THE_END) return; + Block block = e.getClickedBlock(); + int d0 = block.getX(); + int d1 = block.getY() + 1; + int d2 = block.getZ(); + if(world.getBlockAt(d0, d1, d2).getType() != Material.AIR) return; + Location cen = block.getLocation().clone().add(0.5,1,0.5); + Collection list = world.getNearbyEntities(cen,0.5,1,0.5); + if(!list.isEmpty()) return; + e.setCancelled(true); + EnderCrystal crystal = (EnderCrystal) world.spawnEntity(cen,EntityType.ENDER_CRYSTAL); + crystal.setShowingBottom(false); + } + @EventHandler(priority = EventPriority.HIGH) + public void OnEffectCloudSpawn(final EntitySpawnEvent e){ + if(!(e.getEntity() instanceof AreaEffectCloud)) return; + AreaEffectCloud effectCloud = (AreaEffectCloud) e.getEntity(); + if(effectCloud.getSource() == null) return; + if(!(effectCloud.getSource() instanceof EnderDragon)) return; + EnderDragon dragon = (EnderDragon) effectCloud.getSource(); + String unique_name = getSpecialKey(dragon); + if(unique_name == null) return; + MyDragon myDragon = mp.get(unique_name); + if(myDragon == null) return; + effectCloud.setRadius((float) myDragon.effect_cloud_original_radius); + effectCloud.setRadiusPerTick((float) myDragon.effect_cloud_expand_speed/20f); + effectCloud.setDuration(myDragon.effect_cloud_duration * 20); + if(myDragon.effect_cloud_color_R != -1){ + effectCloud.setParticle(Particle.SPELL_MOB); + effectCloud.setColor(Color.fromRGB(myDragon.effect_cloud_color_R,myDragon.effect_cloud_color_G,myDragon.effect_cloud_color_B)); + } + effectCloud.clearCustomEffects(); + for(PotionEffect effect : myDragon.effect_cloud_potion){ + effectCloud.addCustomEffect(effect,true); + } + } + @EventHandler(priority = EventPriority.LOW) + public void OnDragonBreathGather(final PlayerInteractEvent e){ + if(!Config.resist_dragon_breath_gather) return; + if(e.getMaterial() != Material.GLASS_BOTTLE) return; + if(e.getAction() != Action.RIGHT_CLICK_BLOCK && e.getAction() != Action.RIGHT_CLICK_AIR) return; + World world = e.getPlayer().getWorld(); + if(world.getEnvironment() != World.Environment.THE_END) return; + Player p = e.getPlayer(); + Location cen = p.getLocation().clone().add(0d,0.9d,0d); + Collection list = world.getNearbyEntities(cen,2.3d,2.9d,2.3d); + for(Entity entity : list){ + if(entity instanceof AreaEffectCloud) { + AreaEffectCloud effectCloud = (AreaEffectCloud) entity; + if(effectCloud.getSource() instanceof EnderDragon){ + e.setCancelled(true); + break; + } + } + } + } + + +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/DragonAttackListener.java b/src/main/java/pers/xanadu/enderdragon/listener/DragonAttackListener.java new file mode 100644 index 0000000..07a3a38 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/DragonAttackListener.java @@ -0,0 +1,41 @@ +package pers.xanadu.enderdragon.listener; + +import org.bukkit.entity.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.potion.PotionEffect; +import pers.xanadu.enderdragon.manager.DragonManager; +import pers.xanadu.enderdragon.util.MyDragon; + +public class DragonAttackListener implements Listener { + @EventHandler(priority = EventPriority.LOW) + public void OnDragonAttack(final EntityDamageByEntityEvent e){ + Entity victim = e.getEntity(); + Entity attack = e.getDamager(); + if(!(attack instanceof EnderDragon)) return; + EnderDragon dragon = (EnderDragon) attack; + String unique_name = DragonManager.getSpecialKey(dragon); + if(unique_name == null) return; + MyDragon myDragon = DragonManager.mp.get(unique_name); + if(myDragon == null) return; + e.setDamage(Math.max(0.1, e.getDamage() + myDragon.attack_damage_modify)); + if(victim instanceof Player){ + Player player = (Player) victim; + for(PotionEffect effect : myDragon.attack_potion_effect){ + player.addPotionEffect(effect); + } + if(!myDragon.suck_blood_enable) return; + double suck = e.getFinalDamage() * myDragon.suck_blood_rate + myDragon.suck_blood_base_amount; + dragon.setHealth(Math.min(dragon.getHealth()+suck,dragon.getMaxHealth())); + } + else{ + if(!myDragon.suck_blood_enable) return; + if(myDragon.suck_blood_only_player) return; + double suck = e.getFinalDamage() * myDragon.suck_blood_rate + myDragon.suck_blood_base_amount; + dragon.setHealth(Math.min(dragon.getHealth()+suck,dragon.getMaxHealth())); + } + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/DragonBaseHurtListener.java b/src/main/java/pers/xanadu/enderdragon/listener/DragonBaseHurtListener.java new file mode 100644 index 0000000..50e7289 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/DragonBaseHurtListener.java @@ -0,0 +1,33 @@ +package pers.xanadu.enderdragon.listener; + +import org.bukkit.entity.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import pers.xanadu.enderdragon.event.DragonDamageByPlayerEvent; + +import static pers.xanadu.enderdragon.EnderDragon.pm; + +public class DragonBaseHurtListener implements Listener { + @EventHandler(priority = EventPriority.HIGHEST) + public void BaseAttackToDragon(EntityDamageByEntityEvent e){ + if(e.isCancelled()) return; + if(e.getDamage() <= 0.0) return; + Entity victim = e.getEntity(); + Entity entity = e.getDamager(); + if(victim instanceof EnderDragon){ + EnderDragon dragon = (EnderDragon) victim; + if(entity instanceof Player){ + Player player = (Player) entity; + pm.callEvent(new DragonDamageByPlayerEvent(player,dragon,e.getCause(),e.getFinalDamage())); + } + else if(entity instanceof Projectile){ + Projectile projectile = (Projectile) entity; + if(!(projectile.getShooter() instanceof Player)) return; + Player damager = (Player) projectile.getShooter(); + pm.callEvent(new DragonDamageByPlayerEvent(damager,dragon,e.getCause(),e.getFinalDamage())); + } + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/DragonDamageByPlayerListener.java b/src/main/java/pers/xanadu/enderdragon/listener/DragonDamageByPlayerListener.java new file mode 100644 index 0000000..c84fe1b --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/DragonDamageByPlayerListener.java @@ -0,0 +1,60 @@ +package pers.xanadu.enderdragon.listener; + +import net.md_5.bungee.api.ChatMessageType; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import pers.xanadu.enderdragon.config.Config; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.event.DragonDamageByPlayerEvent; +import pers.xanadu.enderdragon.manager.DamageManager; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class DragonDamageByPlayerListener implements Listener { + + @EventHandler(priority = EventPriority.HIGHEST) + public void OnDragonDamageByPlayer(final DragonDamageByPlayerEvent e){ + Player p = e.getDamager(); + EnderDragon dragon = e.getDragon(); + double health = dragon.getHealth(); + double damage = Math.min(e.getFinalDamage(),health); + if(damage > 0.0d){ + UUID dragon_uid = dragon.getUniqueId(); + ConcurrentHashMap mp = DamageManager.data.computeIfAbsent(dragon_uid, k->new ConcurrentHashMap<>()); + mp.compute(p.getName(),(k,v)->v==null?damage:v+damage); + } + //Bukkit.broadcastMessage(RewardManager.data.get(dragon.getUniqueId()).get(p.getUniqueId())+""); + double max_health = dragon.getMaxHealth(); + double remain_health = Math.max(health-e.getFinalDamage(),0.0); + String str = Lang.dragon_damage_display.replaceAll("%damage%", format(damage)).replaceAll("%remain_health%",format(remain_health)).replaceAll("%max_health%",format(max_health)); + switch (Config.damage_visible_mode.toLowerCase()){ + case "actionbar" : { + p.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(str)); + break; + } + case "chatbox" : { + Lang.sendFeedback(p,str); + break; + } + case "subtitle" : { + p.sendTitle("",str,5,40,5); + break; + } + default : { + + } + + } + } + + private String format(double d0){ + return String.format("%.2f",d0); + } + +} + diff --git a/src/main/java/pers/xanadu/enderdragon/listener/DragonDeathListener.java b/src/main/java/pers/xanadu/enderdragon/listener/DragonDeathListener.java new file mode 100644 index 0000000..43cad70 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/DragonDeathListener.java @@ -0,0 +1,163 @@ +package pers.xanadu.enderdragon.listener; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.scheduler.BukkitRunnable; +import pers.xanadu.enderdragon.config.Config; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.manager.DamageManager; +import pers.xanadu.enderdragon.manager.DragonManager; +import pers.xanadu.enderdragon.manager.TimerManager; +import pers.xanadu.enderdragon.util.MyDragon; +import pers.xanadu.enderdragon.util.Pair; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +import static pers.xanadu.enderdragon.EnderDragon.*; + +public class DragonDeathListener implements Listener { + @EventHandler + public void OnDragonDeath(final EntityDeathEvent e){ + if(!(e.getEntity() instanceof EnderDragon)) return; + EnderDragon dragon = (EnderDragon) e.getEntity(); + String unique_name = DragonManager.getSpecialKey(dragon); + if(unique_name == null) return; + MyDragon myDragon = DragonManager.mp.get(unique_name); + if(myDragon == null) return; + int times = data.getInt("times"); + data.set("times",times+1); + try{ + data.save(dataF); + }catch (IOException ex){ + Lang.error(Lang.plugin_file_save_error.replaceAll("\\{file_name}",dataF.getName())); + } + e.setDroppedExp(myDragon.exp_drop); + if(myDragon.dragon_egg_spawn_chance > ThreadLocalRandom.current().nextDouble(100)){ + new BukkitRunnable() { + @Override + public void run() { + Block block = e.getEntity().getWorld().getBlockAt(myDragon.dragon_egg_spawn_x, myDragon.dragon_egg_spawn_y, myDragon.dragon_egg_spawn_z); + block.setType(Material.DRAGON_EGG); + } + }.runTaskLater(plugin, myDragon.dragon_egg_spawn_delay); + } + Player p = e.getEntity().getKiller(); + myDragon.reward_dist.handle_dist(myDragon,dragon,p); + { + List processed = new ArrayList<>(); + if(p != null){ + for(String str : myDragon.death_broadcast_msg){ + processed.add(str.replaceAll("%times%",String.valueOf(times)).replaceAll("%player%",p.getDisplayName())); + } + } + else{ + StringBuilder names = new StringBuilder(); + List entities = dragon.getNearbyEntities(5,5,5); + for (Entity entity : entities) { + if (entity instanceof Player) { + names.append(((Player) entity).getDisplayName()).append(","); + } + } + String name = names.toString(); + if(name.equals("")) name = Lang.dragon_no_killer; + if(name.endsWith(",")) name = name.substring(0,name.length()-1); + for(String str : myDragon.death_broadcast_msg){ + processed.add(str.replaceAll("%times%",String.valueOf(times)).replaceAll("%player%", name)); + } + } + handleBroadcast(processed,myDragon,dragon); + } + DamageManager.data.remove(dragon.getUniqueId()); + Lang.runCommands(myDragon.death_cmd,p); + if(p != null){ + for(String str : myDragon.msg_to_killer){ + Lang.sendFeedback(p,str.replaceAll("%times%",String.valueOf(times))); + } + } + TimerManager.startTimer(dragon.getWorld().getName()); + } + public static void handleBroadcast(final List list,final MyDragon myDragon,final EnderDragon dragon){ + boolean find = false; + for(String str : list){ + if(str.contains("{damage_statistics}")){ + find = true; + break; + } + } + if(!find) Lang.broadcastMSG(list); + else{ + final TextComponent hover = getHover(myDragon,dragon); + for(String str : list){ + final String[] splits = str.split("\\{damage_statistics}"); + final ComponentBuilder builder = new ComponentBuilder(Lang.plugin_prefix); + int size = splits.length; + for(int i=0;ip.spigot().sendMessage(builder.create())); + } + } + } + public static TextComponent getHover(final MyDragon myDragon,final EnderDragon dragon) { + final TextComponent text = new TextComponent(Lang.dragon_damage_statistics_text); + List> list = DamageManager.getDamageList(dragon.getUniqueId()); + list.sort(DamageManager::sortByDamage); + double sum = 0d; + for(Pair pair : list){ + sum += pair.second; + } + StringBuilder builder = new StringBuilder(); + for(String raw : Lang.dragon_damage_statistics_hover_prefix){ + builder.append(raw + .replaceAll("%dragon_display_name%",myDragon.display_name) + .replaceAll("%damage_sum%",String.format("%.2f",sum)) + ).append("\n"); + } + int i = 0; + for(Pair pair : list){ + String raw = Lang.dragon_damage_statistics_hover_mt; + if(i < Config.damage_statistics_limit){ + double damage = pair.second; + double percent = damage/sum*100; + builder.append(raw + .replaceAll("%rank%", String.valueOf(++i)) + .replaceAll("%player%", pair.first) + .replaceAll("%damage%",String.format("%.2f",damage)) + .replaceAll("%percent%",String.format("%.2f%%",percent)) + ).append("\n"); + } + } + if(list.size()-i>0){ + String raw = Lang.dragon_damage_statistics_hover_exceeds_limit; + builder.append(raw + .replaceAll("%exceeds_number%", String.valueOf(list.size()-i)) + ).append("\n"); + } + for(String raw : Lang.dragon_damage_statistics_hover_suffix){ + builder.append(raw + .replaceAll("%dragon_display_name%",myDragon.display_name) + .replaceAll("%damage_sum%",String.format("%.2f",sum)) + ); + } + BaseComponent[] cmp = new ComponentBuilder(builder.toString()).create(); + text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,cmp)); + return text; + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/DragonExplosionHurtListener.java b/src/main/java/pers/xanadu/enderdragon/listener/DragonExplosionHurtListener.java new file mode 100644 index 0000000..3dfd332 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/DragonExplosionHurtListener.java @@ -0,0 +1,94 @@ +package pers.xanadu.enderdragon.listener; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByBlockEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerBedEnterEvent; +import pers.xanadu.enderdragon.event.DragonDamageByPlayerEvent; +import pers.xanadu.enderdragon.event.PlayerExplodeDragonEvent; + +import java.util.Collection; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import static pers.xanadu.enderdragon.EnderDragon.pm; +import static pers.xanadu.enderdragon.manager.WorldManager.getExplosionDragon; + +public class DragonExplosionHurtListener implements Listener { + + private static final ConcurrentHashMap mp = new ConcurrentHashMap<>(); + + @EventHandler(priority = EventPriority.HIGHEST) + public void OnDragonDamageByTNT(final EntityDamageByEntityEvent e){ + if(e.isCancelled()) return; + if(e.getDamage() <= 0.0) return; + Entity victim = e.getEntity(); + Entity entity = e.getDamager(); + if(victim instanceof EnderDragon){ + EnderDragon dragon = (EnderDragon) victim; + if(entity instanceof TNTPrimed){ + TNTPrimed tnt = (TNTPrimed) entity; + if(!(tnt.getSource() instanceof Player)) return; + Player damager = (Player) tnt.getSource(); + pers.xanadu.enderdragon.EnderDragon.pm.callEvent(new DragonDamageByPlayerEvent(damager,dragon,e.getCause(),e.getFinalDamage())); + } + } + } + + /** + * 用tnt隔着方块炸龙也能触发 + */ + @EventHandler(priority = EventPriority.HIGHEST) + public void OnDragonDamageByExplode(final EntityDamageByBlockEvent e){ + long time = pers.xanadu.enderdragon.EnderDragon.getInstance().getWorldDataManager().getGameTime(e.getEntity().getWorld()); + EntityDamageEvent.DamageCause cause = e.getCause(); + if(e.getCause() != EntityDamageEvent.DamageCause.BLOCK_EXPLOSION) return; + Entity entity = e.getEntity(); + if(entity instanceof EnderDragon){ + //Bukkit.broadcastMessage(e.getFinalDamage()+"awa"); + EnderDragon dragon = (EnderDragon) entity; + for(UUID uuid : mp.keySet()){ + PlayerExplodeDragonEvent ped = mp.get(uuid); + if(ped == null) continue; + if(ped.getTime() != time) continue; + if(ped.getEnderDragon().getUniqueId() != dragon.getUniqueId()) continue; + //mp.remove(uuid); + pm.callEvent(new DragonDamageByPlayerEvent(ped.getPlayer(),dragon,cause,e.getFinalDamage())); + //Bukkit.broadcastMessage(ped._loc.toString()); + //Bukkit.broadcastMessage("final: "+e.getFinalDamage()); + break; + } + } + } + @EventHandler(priority = EventPriority.HIGH) + public void OnPlayerClickBed(final PlayerBedEnterEvent e){ + Player p = e.getPlayer(); + if(p.getWorld().getEnvironment() != World.Environment.THE_END) return; + long time = pers.xanadu.enderdragon.EnderDragon.getInstance().getWorldDataManager().getGameTime(e.getPlayer().getWorld()); + Location bed_loc = e.getBed().getLocation(); + Collection entities = getExplosionDragon(5f,bed_loc); + for(EnderDragon dragon : entities){ + UUID uuid = p.getUniqueId(); + mp.put(uuid,new PlayerExplodeDragonEvent(time,p,dragon,bed_loc)); + break; + } + } + + + public static void clearUID(final UUID uuid){ + mp.remove(uuid); + } + public static void addUID(final UUID uuid,final PlayerExplodeDragonEvent ped){ + mp.put(uuid,ped); + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/DragonHealListener.java b/src/main/java/pers/xanadu/enderdragon/listener/DragonHealListener.java new file mode 100644 index 0000000..60351d4 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/DragonHealListener.java @@ -0,0 +1,26 @@ +package pers.xanadu.enderdragon.listener; + +import org.bukkit.entity.EnderDragon; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityRegainHealthEvent; +import pers.xanadu.enderdragon.util.MyDragon; + +import static pers.xanadu.enderdragon.manager.DragonManager.getSpecialKey; +import static pers.xanadu.enderdragon.manager.DragonManager.mp; + +public class DragonHealListener implements Listener { + @EventHandler(priority = EventPriority.HIGH) + public void OnDragonHeal(final EntityRegainHealthEvent e){ + if(!(e.getEntity() instanceof EnderDragon)) return; + EnderDragon dragon = (EnderDragon) e.getEntity(); + if(!e.getRegainReason().equals(EntityRegainHealthEvent.RegainReason.ENDER_CRYSTAL)) return; + String unique_name = getSpecialKey(dragon); + if(unique_name == null) return; + MyDragon myDragon = mp.get(unique_name); + if(myDragon == null) return; + e.setAmount(myDragon.crystal_heal_speed / 2d); + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/EndGatewayListener.java b/src/main/java/pers/xanadu/enderdragon/listener/EndGatewayListener.java new file mode 100644 index 0000000..e3bbbce --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/EndGatewayListener.java @@ -0,0 +1,21 @@ +package pers.xanadu.enderdragon.listener; + +import org.bukkit.entity.Item; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerDropItemEvent; + +public class EndGatewayListener implements Listener { +// @EventHandler +// public void OnEndGateWaySpawn(final PortalCreateEvent e){ +// Bukkit.broadcastMessage("123"); +// List list = e.getBlocks(); +// list.forEach(block -> Bukkit.broadcastMessage(block.toString())); +// } +// @EventHandler +// public void OnEndGateWaySpawn2(final EntityCreatePortalEvent e){ +// Bukkit.broadcastMessage("12345"); +// +// } +} + diff --git a/src/main/java/pers/xanadu/enderdragon/listener/InventoryListener.java b/src/main/java/pers/xanadu/enderdragon/listener/InventoryListener.java new file mode 100644 index 0000000..d968e65 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/InventoryListener.java @@ -0,0 +1,123 @@ +package pers.xanadu.enderdragon.listener; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.PlayerInventory; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.gui.*; +import pers.xanadu.enderdragon.gui.holder.Menu; +import pers.xanadu.enderdragon.gui.holder.MenuEditor; +import pers.xanadu.enderdragon.gui.slot.PageJumpSlot; +import pers.xanadu.enderdragon.manager.DragonManager; +import pers.xanadu.enderdragon.manager.GuiManager; +import pers.xanadu.enderdragon.manager.RewardManager; +import pers.xanadu.enderdragon.util.MyDragon; + +public class InventoryListener implements Listener { + @EventHandler(priority = EventPriority.LOWEST) + public void OnInventoryClick(InventoryClickEvent e){ + InventoryHolder holder = e.getInventory().getHolder(); + if(!(holder instanceof GUIHolder)) return; + GUIHolder guiHolder = (GUIHolder) holder; + if(!(guiHolder.getGUI() instanceof GUIWrapper)) return; + e.setCancelled(true); + GUIWrapper guiWrapper = (GUIWrapper) guiHolder.getGUI(); + if(e.getClickedInventory() instanceof PlayerInventory){ + return; + } + if(e.getRawSlot() >= 54 || e.getRawSlot() < 0){ //点击箱子以外界面会返回-999 + return; + } + Player p = (Player) e.getWhoClicked(); + GUISlot slot = guiWrapper.getSlot(e.getRawSlot()); + GUISlotType type = slot.getType(); + if(type == GUISlotType.EMPTY || type == GUISlotType.TIP || type == GUISlotType.PAGE_TIP){ + return; + } + if(type == GUISlotType.PAGE_PREV){ + guiWrapper.prev(); + p.updateInventory(); + return; + } + if(type == GUISlotType.PAGE_NEXT){ + guiWrapper.next(); + p.updateInventory(); + return; + } + + if(holder instanceof Menu){ + if(e.getClick() != ClickType.LEFT && e.getClick() != ClickType.RIGHT){ + return; + } + if(type == GUISlotType.ITEM_SLOT){ + return; + } + if(type == GUISlotType.PAGE_JUMP){ + String name = ((PageJumpSlot)slot).getGuiName(); + GuiManager.openGui(p,name,false); + return; + } + if(type == GUISlotType.DRAGON_SLOT){ + String unique_name = guiWrapper.getData(guiWrapper.getPage(),e.getRawSlot()); + MyDragon dragon = DragonManager.mp.get(unique_name); + if(dragon == null){ + Lang.sendFeedback(p,Lang.gui_not_found); + return; + } + GuiManager.openGui(p,dragon.drop_gui,dragon.unique_name,false); + return; + } + } + else if(holder instanceof MenuEditor){ + MenuEditor menuEditor = (MenuEditor) holder; + if(e.getClick() != ClickType.LEFT && e.getClick() != ClickType.RIGHT && e.getClick() != ClickType.SHIFT_RIGHT){ + return; + } + if(type == GUISlotType.ITEM_SLOT){ + if(e.getClick() != ClickType.SHIFT_RIGHT) return; + int idx = guiWrapper.getPage()*guiWrapper.getItemSize()+guiWrapper.getItemSlotIdx(e.getRawSlot()); + //Bukkit.broadcastMessage(idx+""); + boolean b = RewardManager.removeItem(menuEditor.getDragon_key(),idx); + if(b) { + p.sendMessage(Lang.command_drop_item_remove_succeed); + guiWrapper.updateItemChanges(true); + } + else p.sendMessage(Lang.command_drop_item_remove_fail); + return; + } + if(type == GUISlotType.PAGE_JUMP){ + String name = ((PageJumpSlot)slot).getGuiName(); + GuiManager.openGui(p,name,true); + return; + } + if(type == GUISlotType.DRAGON_SLOT){ + String unique_name = guiWrapper.getData(guiWrapper.getPage(),e.getRawSlot()); + MyDragon dragon = DragonManager.mp.get(unique_name); + if(dragon == null){ + Lang.sendFeedback(p,Lang.gui_not_found); + return; + } + GuiManager.openGui(p,dragon.drop_gui,dragon.unique_name,true); + return; + } + } + + } + @EventHandler(priority = EventPriority.LOWEST) + public void OnInventoryDrag(InventoryDragEvent e){ + InventoryHolder holder = e.getInventory().getHolder(); + if(!(holder instanceof GUIHolder)) return; + if(holder instanceof Menu){ + GUIHolder guiHolder = (GUIHolder) holder; + if(!(guiHolder.getGUI() instanceof GUIWrapper)) return; + e.setCancelled(true); + } + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/PlayerListener.java b/src/main/java/pers/xanadu/enderdragon/listener/PlayerListener.java new file mode 100644 index 0000000..aed1730 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/PlayerListener.java @@ -0,0 +1,19 @@ +package pers.xanadu.enderdragon.listener; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import pers.xanadu.enderdragon.manager.GlowManager; + +public class PlayerListener implements Listener { + @EventHandler + public void onPlayerJoin(final PlayerJoinEvent e){ + GlowManager.setScoreBoard(e.getPlayer()); + + } + @EventHandler + public void onPlayerQuit(final PlayerQuitEvent e){ + DragonExplosionHurtListener.clearUID(e.getPlayer().getUniqueId()); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/PluginDisableListener.java b/src/main/java/pers/xanadu/enderdragon/listener/PluginDisableListener.java new file mode 100644 index 0000000..9f55f79 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/PluginDisableListener.java @@ -0,0 +1,16 @@ +package pers.xanadu.enderdragon.listener; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.server.PluginDisableEvent; + +import static pers.xanadu.enderdragon.EnderDragon.*; + +public class PluginDisableListener implements Listener { + @EventHandler + public void OnPluginDisable(PluginDisableEvent e){ + if(e.getPlugin().equals(plugin)){ + disableAll(); + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/RespawnAnchorExplodeListener.java b/src/main/java/pers/xanadu/enderdragon/listener/RespawnAnchorExplodeListener.java new file mode 100644 index 0000000..167e5d7 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/RespawnAnchorExplodeListener.java @@ -0,0 +1,45 @@ +package pers.xanadu.enderdragon.listener; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.data.type.RespawnAnchor; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import pers.xanadu.enderdragon.event.PlayerExplodeDragonEvent; + +import java.util.Collection; +import java.util.UUID; + +import static pers.xanadu.enderdragon.manager.WorldManager.getExplosionDragon; + +public class RespawnAnchorExplodeListener implements Listener { + @EventHandler(priority = EventPriority.HIGH) + public void OnRespawnAnchorExplode(final PlayerInteractEvent e){ + if(e.getAction() != Action.RIGHT_CLICK_BLOCK) return; + Block block = e.getClickedBlock(); + if(block == null || block.getType() != Material.RESPAWN_ANCHOR) return; + RespawnAnchor anchor = (RespawnAnchor) block.getBlockData(); + Player p = e.getPlayer(); + Material offHand = p.getInventory().getItemInOffHand().getType(); + if(e.getHand()== EquipmentSlot.HAND && e.getMaterial()!=Material.GLOWSTONE && offHand==Material.GLOWSTONE) return; + if(e.getMaterial()==Material.GLOWSTONE && anchor.getCharges()<4) return; + if(anchor.getCharges()==0) return; + if(pers.xanadu.enderdragon.EnderDragon.getInstance().getRespawnAnchorManager().isRespawnAnchorWorks(p.getWorld())) return; + if(p.isSneaking() && (p.getItemInHand().getType()!=Material.AIR || offHand!=Material.AIR)) return; + long time = pers.xanadu.enderdragon.EnderDragon.getInstance().getWorldDataManager().getGameTime(e.getPlayer().getWorld()); + Location loc = block.getLocation(); + Collection entities = getExplosionDragon(5f,loc); + for(EnderDragon dragon : entities){ + UUID uuid = p.getUniqueId(); + DragonExplosionHurtListener.addUID(uuid,new PlayerExplodeDragonEvent(time,p,dragon,loc)); + break; + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/listener/mythiclib/PlayerAttackListener.java b/src/main/java/pers/xanadu/enderdragon/listener/mythiclib/PlayerAttackListener.java new file mode 100644 index 0000000..c8f9da7 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/listener/mythiclib/PlayerAttackListener.java @@ -0,0 +1,27 @@ +package pers.xanadu.enderdragon.listener.mythiclib; + +import io.lumine.mythic.lib.api.event.PlayerAttackEvent; +import io.lumine.mythic.lib.damage.DamageMetadata; +import org.bukkit.entity.EnderDragon; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import pers.xanadu.enderdragon.event.DragonDamageByPlayerEvent; + +import static pers.xanadu.enderdragon.EnderDragon.pm; + +public class PlayerAttackListener implements Listener { + @EventHandler(priority = EventPriority.HIGH) + public void onPlayerAttack(PlayerAttackEvent e){ + if(e.isCancelled()) return; + if(!(e.getEntity() instanceof org.bukkit.entity.EnderDragon)) return; + EnderDragon dragon = (EnderDragon) e.getEntity(); + DamageMetadata damage = e.getDamage(); + double final_damage = damage.getDamage(); + if(final_damage > 0.0d){ + DragonDamageByPlayerEvent event = new DragonDamageByPlayerEvent(e.getAttacker().getPlayer(),dragon, e.toBukkit().getCause(), final_damage); + pm.callEvent(event); + } + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/manager/DamageManager.java b/src/main/java/pers/xanadu/enderdragon/manager/DamageManager.java new file mode 100644 index 0000000..0c2e265 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/manager/DamageManager.java @@ -0,0 +1,25 @@ +package pers.xanadu.enderdragon.manager; + +import pers.xanadu.enderdragon.util.Pair; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class DamageManager { + public static final ConcurrentHashMap> data = new ConcurrentHashMap<>(); + public static List> getDamageList(UUID uuid){ + ConcurrentHashMap mp = data.get(uuid); + List> list = new ArrayList<>(); + if(mp == null) return list; + mp.forEach((k,v)->list.add(new Pair<>(k,v))); + return list; + } + public static int sortByDamage(Pair p1, Pair p2){ + if(p2.second>p1.second) return 1; + if(p2.second.equals(p1.second)) return 0; + return -1; + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/manager/DragonManager.java b/src/main/java/pers/xanadu/enderdragon/manager/DragonManager.java new file mode 100644 index 0000000..bb19858 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/manager/DragonManager.java @@ -0,0 +1,463 @@ +package pers.xanadu.enderdragon.manager; + +import org.bukkit.*; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.boss.DragonBattle; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.*; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scoreboard.Team; +import pers.xanadu.enderdragon.config.Config; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.reward.RewardDist; +import pers.xanadu.enderdragon.util.MyDragon; +import pers.xanadu.enderdragon.util.Version; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +import static pers.xanadu.enderdragon.EnderDragon.*; + +public class DragonManager { + public static ArrayList dragons = new ArrayList<>(); + public static HashMap mp = new HashMap<>(); + public static List dragon_names = new ArrayList<>(); + private static int sum = 0; + private static final int[][] nxt = {{3,0},{0,3},{-3,0},{0,-3}}; + private Method DragonBattle_e; + private Method getX; + private Method getY; + private Method getZ; + + public static void reload(){ + new BukkitRunnable(){ + @Override + public void run(){ + dragons.clear(); + mp.clear(); + dragon_names.clear(); + sum = 0; + if(Config.dragon_setting_file == null){ + Lang.error("\"dragon_setting_file\" in config.yml is empty!"); + Lang.warn("Plugin will use the default config..."); + Config.dragon_setting_file = new ArrayList<>(); + Config.dragon_setting_file.add("default:5"); + Config.dragon_setting_file.add("special:5"); + } + for(String str : Config.dragon_setting_file){ + String[] s = str.split(":"); + if(s.length != 2){ + Lang.error("\"dragon_setting_file\" in config.yml error! Key: " + str); + continue; + } + String path = "setting/" + s[0] + ".yml"; + int edge = -1; + try { + edge = Integer.parseInt(s[1]); + } catch (NumberFormatException ignored){} + if(edge < 0) { + Lang.error("\"dragon_setting_file\" in config.yml error! Key: " + str); + continue; + } + File file = new File(plugin.getDataFolder(),path); + if(!file.exists()) { + try{ + plugin.saveResource("setting/"+file.getName(),false); + file = new File(plugin.getDataFolder(),path); + }catch (Exception ignored){ + Lang.error("Not Found setting/" + s[0] + ".yml ,skipped it."); + continue; + } + } + FileConfiguration fc = YamlConfiguration.loadConfiguration(file); + readSettingFile(fc,edge); + } + dragons.sort((o1, o2) -> o2.priority - o1.priority); + RewardManager.reload(); + } + }.runTaskAsynchronously(plugin); + + } + public static MyDragon judge(){ + if(Config.special_dragon_jude_mode.equalsIgnoreCase("weight")){ + int cnt = 0, random = ThreadLocalRandom.current().nextInt(0, sum); + for(MyDragon cur : dragons){ + if(cnt <= random && cnt + cur.edge > random){ + return cur; + } + cnt += cur.edge; + } + } + else if(Config.special_dragon_jude_mode.equalsIgnoreCase("pc")){ + Iterator it = dragons.iterator(); + MyDragon cur = null; + while (it.hasNext()){ + cur = it.next(); + boolean judge = cur.spawn_chance > ThreadLocalRandom.current().nextDouble(100); + if(judge) return cur; + } + return cur; + } + else if(Config.special_dragon_jude_mode.equalsIgnoreCase("edge")){ + int cnt = 0, random = ThreadLocalRandom.current().nextInt(0, sum); + for(MyDragon cur : dragons){ + if(cnt <= random && cnt + cur.edge > random){ + return cur; + } + cnt += cur.edge; + } + Lang.error("\"edge\" in \"special_dragon_jude_mode\" of config.yml is deprecated!Please use \"weight\" instead."); + } + return null; + } + public static void setSpecialKey(Entity e, String key){ + e.addScoreboardTag(key); + } + public static String getSpecialKey(Entity e){ + for(MyDragon a : dragons){ + if(e.getScoreboardTags().contains(a.unique_name)) return a.unique_name; + } + return null; + } + public static void readSettingFile(FileConfiguration f,int edge){ + MyDragon myDragon = new MyDragon(); + myDragon.unique_name = f.getString("unique_name","default"); + if(mp.containsKey(myDragon.unique_name)){ + Lang.error("The unique_name conflict! Key: "+myDragon.unique_name); + return; + } + myDragon.icon = ItemManager.readFromBukkit(f,"icon"); + myDragon.display_name = f.getString("display_name","Special Dragon"); + myDragon.drop_gui = f.getString("drop_gui"); + myDragon.edge = edge; + myDragon.priority = f.getInt("priority",1); + myDragon.spawn_chance = f.getDouble("spawn_chance",0); + myDragon.max_health = f.getInt("max_health",200); + myDragon.spawn_health = f.getInt("spawn_health",200); + myDragon.exp_drop = f.getInt("exp_drop",500); + myDragon.dragon_egg_spawn_delay = f.getInt("dragon_egg_spawn.delay",410); + myDragon.dragon_egg_spawn_x = f.getInt("dragon_egg_spawn.x",0); + myDragon.dragon_egg_spawn_y = f.getInt("dragon_egg_spawn.y",70); + myDragon.dragon_egg_spawn_z = f.getInt("dragon_egg_spawn.z",0); + myDragon.dragon_egg_spawn_chance = f.getDouble("dragon_egg_spawn.chance",0); + myDragon.attack_damage_modify = f.getDouble("attack_damage_modify",0); + //myDragon.move_speed_modify = f.getDouble("move_speed_modify",0); + myDragon.armor_modify = f.getDouble("armor_modify",0); + myDragon.armor_toughness_modify = f.getDouble("armor_toughness_modify",0); + myDragon.crystal_heal_speed = f.getDouble("crystal_heal_speed",2.0); + myDragon.suck_blood_enable = f.getBoolean("suck_blood.enable",true); + myDragon.suck_blood_rate = f.getDouble("suck_blood.rate",50) / 100d; + myDragon.suck_blood_base_amount = f.getDouble("suck_blood.base_amount",1); + myDragon.suck_blood_only_player = f.getBoolean("suck_blood.only_player",true); + List stringList = f.getStringList("attack_potion_effect"); + List potions = new ArrayList<>(); + for(String string : stringList){ + String[] s = string.split(" "); + if(s.length != 3) continue; + PotionEffectType type = PotionEffectType.getByName(s[0].toUpperCase()); + if(type == null){ + Lang.error("Unknown potion type: " + s[0]); + continue; + } + int duration = -1; + try { + duration = Integer.parseInt(s[1]); + } catch (NumberFormatException ex){ + Lang.error("Wrong number format: " + s[1]); + } + if(duration == -1) continue; + int level = -1; + try { + level = Integer.parseInt(s[2]); + } catch (NumberFormatException ex){ + Lang.error("Wrong number format: " + s[2]); + } + if(level == -1) continue; + PotionEffect potionEffect = new PotionEffect(type,duration*20,level-1); + potions.add(potionEffect); + } + myDragon.attack_potion_effect = potions; + myDragon.spawn_cmd = f.getStringList("spawn_cmd"); + myDragon.death_cmd = f.getStringList("death_cmd"); + myDragon.spawn_broadcast_msg = f.getStringList("spawn_broadcast_msg"); + myDragon.death_broadcast_msg = f.getStringList("death_broadcast_msg"); + myDragon.msg_to_killer = f.getStringList("msg_to_killer"); + myDragon.glow_color = f.getString("glow_color","random"); + myDragon.bossbar_color = f.getString("bossbar.color","WHITE"); + myDragon.bossbar_style = f.getString("bossbar.style","SOLID"); + myDragon.effect_cloud_original_radius = f.getDouble("effect_cloud.original_radius",3); + myDragon.effect_cloud_expand_speed = f.getDouble("effect_cloud.expand_speed",0.1333333); + myDragon.effect_cloud_duration = f.getInt("effect_cloud.duration",60); + String effect_cloud_color = f.getString("effect_cloud.color","none"); + String[] s0 = effect_cloud_color.split(":"); + if(s0.length != 3) myDragon.effect_cloud_color_R = -1; + else{ + try{ + myDragon.effect_cloud_color_R = Integer.parseInt(s0[0]); + myDragon.effect_cloud_color_G = Integer.parseInt(s0[1]); + myDragon.effect_cloud_color_B = Integer.parseInt(s0[2]); + } + catch (NumberFormatException e){ + Lang.error("Wrong effect_cloud_color format!"); + myDragon.effect_cloud_color_R = -1; + } + } + List stringList2 = f.getStringList("effect_cloud.potion"); + List effectCloudPotions = new ArrayList<>(); + for(String string : stringList2){ + String[] s = string.split(" "); + if(s.length != 3) continue; + PotionEffectType type = PotionEffectType.getByName(s[0].toUpperCase()); + if(type == null){ + Lang.error("Unknown potion type: " + s[0]); + continue; + } + int duration = -1; + try { + duration = Integer.parseInt(s[1]); + } catch (NumberFormatException ex){ + Lang.error("Wrong number format: " + s[1]); + } + if(duration == -1) continue; + int level = -1; + try { + level = Integer.parseInt(s[2]); + } catch (NumberFormatException ex){ + Lang.error("Wrong number format: " + s[2]); + } + if(level == -1) continue; + PotionEffect potionEffect = new PotionEffect(type,duration*20,level-1); + effectCloudPotions.add(potionEffect); + } + myDragon.effect_cloud_potion = effectCloudPotions; + myDragon.reward_dist = RewardDist.parse(f.getConfigurationSection("reward_dist")); + dragons.add(myDragon); + mp.put(myDragon.unique_name,myDragon); + dragon_names.add(myDragon.unique_name); + sum += edge; + } + public static void disable(){ + dragons.clear(); + mp.clear(); + dragon_names.clear(); + } + + public static void setAttribute(EnderDragon dragon, Attribute attribute, double amount){ + AttributeInstance instance = dragon.getAttribute(attribute); + assert instance != null; + instance.setBaseValue(amount); + } + public static void modifyAttribute(EnderDragon dragon, Attribute attribute, double amount){ + AttributeInstance instance = dragon.getAttribute(attribute); + assert instance != null; + instance.addModifier(new AttributeModifier("EnderDragon",amount,AttributeModifier.Operation.ADD_NUMBER)); + } + + public void initiateRespawn(Player p){ + DragonRespawnResult res = initiateRespawn(p.getWorld()); + if(res == DragonRespawnResult.success) Lang.broadcastMSG(Lang.dragon_auto_respawn); + else Lang.sendFeedback(p,"§c"+res.getMessage()); + } + public void initiateRespawn(CommandSender sender, String world_name){ + DragonRespawnResult res = initiateRespawn(Bukkit.getWorld(world_name)); + if(res == DragonRespawnResult.success) Lang.broadcastMSG(Lang.dragon_auto_respawn); + else Lang.sendFeedback(sender,"§c"+res.getMessage()); + } + public void initiateRespawn(String world_name){ + DragonRespawnResult res = initiateRespawn(Bukkit.getWorld(world_name)); + if(res == DragonRespawnResult.success) Lang.broadcastMSG(Lang.dragon_auto_respawn); + else Lang.error(res.getMessage()); + } + public boolean canRespawn(String world_name){ + return canRespawn(Bukkit.getWorld(world_name)); + } + public boolean canRespawn(World world){ + if(world == null) return false; + if(world.getEnvironment() != World.Environment.THE_END) return false; + if(Version.mcMainVersion >= 16){//executes 1e5 times within 27ms + DragonBattle battle = world.getEnderDragonBattle(); + if(battle == null) return false; + if(battle.getEnderDragon() != null) return false; + if(battle.getRespawnPhase() != DragonBattle.RespawnPhase.NONE) return false; + Location cen = battle.getEndPortalLocation(); + if(cen == null) { + battle.initiateRespawn(); + cen = battle.getEndPortalLocation(); + if(cen == null){ + return false; + } + } + return true; + } + try {//executes 1e5 times within 76ms + Object battle = getInstance().getNMSManager().getEnderDragonBattle(world); + if(battle == null) return false; + Field k = battle.getClass().getDeclaredField("k"); + k.setAccessible(true); + Object isAlive = k.get(battle); + if(!((boolean) isAlive)) return false; + Field p = battle.getClass().getDeclaredField("p"); + p.setAccessible(true); + Object phase = p.get(battle); + if(phase != null) return false; + Field field = battle.getClass().getDeclaredField("o"); + field.setAccessible(true); + Object BlockPosition = field.get(battle); + if(BlockPosition == null){ + if (this.DragonBattle_e == null) this.DragonBattle_e = battle.getClass().getMethod("e"); + this.DragonBattle_e.invoke(battle); + BlockPosition = field.get(battle); + if(BlockPosition == null) return false; + } + return true; + } catch (ReflectiveOperationException e) { + return false; + } + } + public boolean isRespawnRunning(World world){ + if(world == null) return false; + if(world.getEnvironment() != World.Environment.THE_END) return false; + if(Version.mcMainVersion >= 16){ + DragonBattle battle = world.getEnderDragonBattle(); + assert battle != null; + return battle.getRespawnPhase() != DragonBattle.RespawnPhase.NONE; + } + try { + Object battle = getInstance().getNMSManager().getEnderDragonBattle(world); + assert battle != null; + Field p = battle.getClass().getDeclaredField("p"); + p.setAccessible(true); + Object phase = p.get(battle); + return phase != null; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + return false; + } + } + public void refresh_respawn(World world){ + if(world == null) return; + if(world.getEnvironment() != World.Environment.THE_END) return; + if(Version.mcMainVersion >= 16){ + DragonBattle battle = world.getEnderDragonBattle(); + assert battle != null; + battle.initiateRespawn(); + return; + } + try { + Object battle = getInstance().getNMSManager().getEnderDragonBattle(world); + assert battle != null; + if (this.DragonBattle_e == null) this.DragonBattle_e = battle.getClass().getMethod("e"); + this.DragonBattle_e.invoke(battle); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + } + private DragonRespawnResult initiateRespawn(World world){ + if(world == null) return DragonRespawnResult.world_not_found; + if(world.getEnvironment() != World.Environment.THE_END) return DragonRespawnResult.world_wrong_env; + if(Version.mcMainVersion >= 16){ + DragonBattle battle = world.getEnderDragonBattle(); + assert battle != null; + if(battle.getEnderDragon() != null) return DragonRespawnResult.dragon_has_existed; + if(battle.getRespawnPhase() != DragonBattle.RespawnPhase.NONE) return DragonRespawnResult.respawn_has_started; + Location cen = battle.getEndPortalLocation(); + if(cen == null) { + battle.initiateRespawn(); + cen = battle.getEndPortalLocation(); + if(cen == null){ + return DragonRespawnResult.world_unloaded;//也可尝试chunk.load() + } + } + placeEndCrystals(world,cen); + battle.initiateRespawn(); + return DragonRespawnResult.success; + } + try { + Object battle = getInstance().getNMSManager().getEnderDragonBattle(world); + assert battle != null; + Field k = battle.getClass().getDeclaredField("k"); + k.setAccessible(true); + Object isAlive = k.get(battle); + if(!((boolean) isAlive)) return DragonRespawnResult.dragon_has_existed; + Field p = battle.getClass().getDeclaredField("p"); + p.setAccessible(true); + Object phase = p.get(battle); + if(phase != null) return DragonRespawnResult.respawn_has_started; + Field field = battle.getClass().getDeclaredField("o"); + field.setAccessible(true); + Object BlockPosition = field.get(battle); + if(BlockPosition == null){ + if (this.DragonBattle_e == null) this.DragonBattle_e = battle.getClass().getMethod("e"); + this.DragonBattle_e.invoke(battle); + BlockPosition = field.get(battle); + if(BlockPosition == null) return DragonRespawnResult.world_unloaded; + } + if(this.getX == null) this.getX = BlockPosition.getClass().getMethod("getX"); + if(this.getY == null) this.getY = BlockPosition.getClass().getMethod("getY"); + if(this.getZ == null) this.getZ = BlockPosition.getClass().getMethod("getZ"); + Location loc = new Location(world,(int)getX.invoke(BlockPosition),(int)this.getY.invoke(BlockPosition),(int)this.getZ.invoke(BlockPosition)); + placeEndCrystals(world, loc); + if (this.DragonBattle_e == null) this.DragonBattle_e = battle.getClass().getMethod("e"); + this.DragonBattle_e.invoke(battle); + return DragonRespawnResult.success; + } catch (ReflectiveOperationException e) { + return DragonRespawnResult.version_not_support; + } + + } + private void placeEndCrystals(World world, Location cen){ + cen.add(0.5,1,0.5); + for(int i = 0; i < 4; i++){ + EnderCrystal crystal = (EnderCrystal) world.spawnEntity(cen.clone().add(nxt[i][0],0,nxt[i][1]), EntityType.ENDER_CRYSTAL); + if(Config.auto_respawn_invulnerable) crystal.setInvulnerable(true); + crystal.setShowingBottom(false); + } + } + public enum DragonRespawnResult{ + success, + world_not_found, + world_unloaded, + world_wrong_env, + respawn_has_started, + dragon_has_existed, + version_not_support; + public String getMessage(){ + switch (this){ + case success: return "Success"; + case world_not_found: return "Can't find this world!"; + case world_unloaded: return "The world_the_end is unloaded."; + case world_wrong_env: return "Respawn only can be called in the End."; + case respawn_has_started: return "The respawning has already started."; + case dragon_has_existed: return "There is already a dragon here."; + case version_not_support: return "Your server version (" + Version.getVersion() + ") is not supported!"; + default: return "Unknown error!"; + } + } + } + +} + +// try { +// Object WorldServer = getInstance().getNMSManager().getWorldServer(world); +// Field Z = WorldServer.getClass().getDeclaredField("Z"); +// Z.setAccessible(true); +// Object edb = Z.get(WorldServer); +// Class edb_clazz = Class.forName("net.minecraft.world.level.dimension.end.EnderDragonBattle"); +// Method a = edb_clazz.getMethod("a"); +// a.invoke(edb); +// Field y = edb_clazz.getDeclaredField("y"); +// y.setAccessible(true); +// Object bp = y.get(edb); +// if(bp == null) Bukkit.broadcastMessage("123"); +// }catch (ReflectiveOperationException e){ +// e.printStackTrace(); +// } \ No newline at end of file diff --git a/src/main/java/pers/xanadu/enderdragon/manager/GlowManager.java b/src/main/java/pers/xanadu/enderdragon/manager/GlowManager.java new file mode 100644 index 0000000..81b377e --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/manager/GlowManager.java @@ -0,0 +1,76 @@ +package pers.xanadu.enderdragon.manager; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; +import pers.xanadu.enderdragon.util.Version; + +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; + +public class GlowManager { + public static Set handled = new HashSet<>(); + public static void reload(){ + handled.clear(); + } + public static void setScoreBoard(Player p){ + Scoreboard board = p.getScoreboard(); + if(handled.contains(board)) return; + ChatColor[] colors = ChatColor.values(); + for(ChatColor color : colors){ + String name = "ed-"+color.name(); + if(board.getTeam(name)==null) board.registerNewTeam(name); + Team team = board.getTeam(name); + assert team != null; + if(Version.mcMainVersion >= 13) team.setColor(color); + else team.setPrefix(color.toString()); + } + handled.add(board); + } + public static void addUUID(String uuid,String color){ + Set teams = new HashSet<>(); + Bukkit.getOnlinePlayers().forEach(player -> { + GlowManager.setScoreBoard(player); + Team team = player.getScoreboard().getTeam("ed-"+color.toUpperCase()); + teams.add(team); + }); + teams.forEach(team->{ + team.addEntry(uuid); + }); + } + public static void setGlowingColor(Entity entity, ChatColor color){ + Set teams = new HashSet<>(); + Bukkit.getOnlinePlayers().forEach(player -> { + GlowManager.setScoreBoard(player); + Team team = player.getScoreboard().getTeam("ed-"+color.name()); + teams.add(team); + }); + teams.forEach(team->{ + team.addEntry(entity.getUniqueId().toString()); + entity.setGlowing(true); + }); + } + public static ChatColor getGlowColor(String str){ + ChatColor chatColor; + if(str.equals("RANDOM")) chatColor = randomColor(); + else chatColor = ChatColor.valueOf(str); + return chatColor; + } + public static ChatColor getGlowColor(GlowColor glowColor){ + if(glowColor == GlowColor.NONE) return null; + if(glowColor == GlowColor.RANDOM) return randomColor(); + return ChatColor.valueOf(glowColor.name()); + } + public static ChatColor randomColor(){ + return ChatColor.values()[ThreadLocalRandom.current().nextInt(16)]; + } + public enum GlowColor{ + AQUA,BLACK,BLUE,DARK_AQUA,DARK_BLUE,DARK_GRAY,DARK_GREEN,DARK_PURPLE,DARK_RED,GOLD,GRAY,GREEN,LIGHT_PURPLE,RED,WHITE,YELLOW, + NONE,RANDOM + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/manager/GuiManager.java b/src/main/java/pers/xanadu/enderdragon/manager/GuiManager.java new file mode 100644 index 0000000..1c8f50e --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/manager/GuiManager.java @@ -0,0 +1,76 @@ +package pers.xanadu.enderdragon.manager; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.gui.GUIWrapper; + +import java.io.File; +import java.util.HashMap; +import java.util.Iterator; + +import static pers.xanadu.enderdragon.EnderDragon.plugin; + +public class GuiManager { + private static HashMap f = new HashMap<>(); + public static void loadGui(){ + new BukkitRunnable(){ + @Override + public void run(){ + File folder = new File(plugin.getDataFolder(),"gui"); + if(!folder.exists()) return; + File[] files = folder.listFiles(); + if(files == null) return; + for(File file : files){ + if(!file.getName().endsWith(".yml")) continue; + Lang.info(Lang.plugin_read_file + file.getName()); + FileConfiguration fileConfiguration = YamlConfiguration.loadConfiguration(file); + Iterator it = fileConfiguration.getKeys(false).iterator(); + while (it.hasNext()){ + String name = (String) it.next(); + ConfigurationSection section = fileConfiguration.getConfigurationSection(name); + GUIWrapper guiWrapper = new GUIWrapper(section); + f.put(name, guiWrapper); + } + } + } + }.runTaskAsynchronously(plugin); + } + public static void disable(){ + f.clear(); + } + public static void openGui(Player player, String name, boolean editor) { + if (!f.containsKey(name)) { + Lang.sendFeedback(player,Lang.gui_not_found); + return; + } + player.openInventory(new GUIWrapper(f.get(name),name,editor).current()); + } + public static void openGui(Player player,String style,String key, boolean editor){ + if (!f.containsKey(style)) { + Lang.sendFeedback(player,Lang.gui_not_found); + return; + } + player.openInventory(new GUIWrapper(f.get(style),key,editor).current()); + } + + @Deprecated + public static void openGui(Player player, String name) { + if (!f.containsKey(name)) { + Lang.sendFeedback(player,Lang.gui_not_found); + return; + } + player.openInventory(new GUIWrapper(f.get(name),name,false).current()); + } + @Deprecated + public static void openGui(Player player,String style,String key){ + if (!f.containsKey(style)) { + Lang.sendFeedback(player,Lang.gui_not_found); + return; + } + player.openInventory(new GUIWrapper(f.get(style),key,false).current()); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/manager/ItemManager.java b/src/main/java/pers/xanadu/enderdragon/manager/ItemManager.java new file mode 100644 index 0000000..6a14f76 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/manager/ItemManager.java @@ -0,0 +1,426 @@ +package pers.xanadu.enderdragon.manager; + +import org.bukkit.Material; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.Repairable; +import org.bukkit.persistence.PersistentDataContainer; +import pers.xanadu.enderdragon.EnderDragon; +import pers.xanadu.enderdragon.config.Config; +import pers.xanadu.enderdragon.reward.Reward; +import pers.xanadu.enderdragon.reward.Chance; +import pers.xanadu.enderdragon.util.Version; + +import java.util.*; + +public class ItemManager { + public static String write(Reward reward){ + Chance chance = reward.getChance(); + return write(reward.getItem(),chance.getValue(),chance.getStr(),reward.getName()); + } + public static String write(ItemStack item,double value,String str,String name){ + YamlConfiguration yaml = new YamlConfiguration(); + if(name == null){ + ItemMeta meta = item.getItemMeta(); + if(meta != null) { + String displayName = meta.getDisplayName(); + if("".equals(displayName) || displayName == null){ + name = item.getType().name().toLowerCase() + "(" + TaskManager.getCurrentTimeWithSpecialFormat() + ")"; + } + else name = meta.getDisplayName(); + } + else name = item.getType().name().toLowerCase() + "(" + TaskManager.getCurrentTimeWithSpecialFormat() + ")"; + } + ConfigurationSection section = yaml.createSection(name); + switch(Config.item_format_data){ + case "nbt" : { + section.set("data_type","nbt"); + section.set("data",EnderDragon.getInstance().getNMSManager().getNBT(item)); + break; + } + case "advanced" : { + section.set("data_type","advanced"); + ConfigurationSection section_data = section.createSection("data"); + //type + String type = item.getType().name(); + section_data.set("type",type); + if("AIR".equals(type)) break; + //amount + int amount = item.getAmount(); + section_data.set("amount",amount); + //damage + int damage = item.getDurability(); + if(damage != 0) section_data.set("damage",damage); + ItemMeta meta = item.getItemMeta(); + if(meta == null) break; + //DisplayName + String display_name = meta.getDisplayName(); + if(!"".equals(display_name)) section_data.set("display_name",display_name); + //LocalizedName + if(meta.hasLocalizedName()){ + section_data.set("localized_name",meta.getLocalizedName()); + } + //lore + List lores = meta.getLore(); + if(lores != null) section_data.set("lore",lores); + //Enchantments + if(meta.hasEnchants()){ + ConfigurationSection enchants = section_data.createSection("enchants"); + Map mp = meta.getEnchants(); + mp.forEach((enchantment,level) -> enchants.set(enchantment.getName(),level)); + } + if(Version.mcMainVersion>=14 || "v1_13_R2".equals(Version.getVersion())){ + //AttributeModifiers + if(meta.hasAttributeModifiers()){ + ConfigurationSection attributes = section_data.createSection("AttributeModifiers"); + meta.getAttributeModifiers().forEach((attribute,modifier)->{ + attributes.set(attribute.name(),modifier); + }); + } + } + if(Version.mcMainVersion>=14){ + //CustomModelData + if(meta.hasCustomModelData()) { + section_data.set("CustomModelData",meta.getCustomModelData());//int + } + //PersistentDataContainer + PersistentDataContainer dataContainer = meta.getPersistentDataContainer(); + if(!dataContainer.isEmpty()){ + ConfigurationSection dataContainer_section = section_data.createSection("PersistentDataContainer"); + String cpd = EnderDragon.getInstance().getNMSManager().PDCtoString(dataContainer); + dataContainer_section.set("data_type","nbt"); + dataContainer_section.set("data",cpd); + } + } + //RepairCost + if(meta instanceof Repairable){ + Repairable repairable = (Repairable) meta; + section_data.set("RepairCost",repairable.getRepairCost()); + } + //ItemFlags + Set flags = meta.getItemFlags(); + if(!flags.isEmpty()){ + List list = new ArrayList<>(); + flags.forEach(flag ->{ + list.add(flag.name()); + }); + section_data.set("ItemFlags",list); + } + //Unbreakable + section_data.set("unbreakable",meta.isUnbreakable()); + //internal + Object cpd = EnderDragon.getInstance().getNMSManager().getCPD(item); + Map mp = EnderDragon.getInstance().getNMSManager().cpdToMap(cpd); + if(mp.containsKey("tag")){ + cpd = mp.get("tag"); + mp = EnderDragon.getInstance().getNMSManager().cpdToMap(cpd); + mp.remove("Damage"); + if(mp.containsKey("display")){ + Object display = mp.get("display"); + Map display_mp = EnderDragon.getInstance().getNMSManager().cpdToMap(display); + display_mp.remove("Name"); + display_mp.remove("LocName"); + display_mp.remove("Lore"); + Object new_display = EnderDragon.getInstance().getNMSManager().getNBTTagCompound(display_mp); + mp.put("display",new_display); + } + //mp.remove("display");//Name, LocName, Lore, color + mp.remove("Enchantments"); + mp.remove("AttributeModifiers"); + mp.remove("CustomModelData"); + mp.remove("PublicBukkitValues");//PersistentDataContainer + mp.remove("RepairCost"); + mp.remove("HideFlags");//ItemFlags + mp.remove("Unbreakable"); + //CanDestroy, CanPlaceOn + Object new_cpd = EnderDragon.getInstance().getNMSManager().getNBTTagCompound(mp); + ConfigurationSection internal = section_data.createSection("internal"); + internal.set("data_type","nbt"); + internal.set("data",new_cpd.toString()); + } +// Map mp = EnderDragon.getInstance().getNMSManager().getUnhandledTags(meta); +// if(mp != null){ +// ConfigurationSection internal = section_data.createSection("internal"); +// saveUnhandledTags(internal,mp); +// } + + break; + } + default : { + section.set("data_type","default"); + section.set("data", item); + } + } + section.set("drop_chance.value",value); + section.set("drop_chance.format",str); + return yaml.saveToString(); + } + public static Reward readAsReward(ConfigurationSection section){ + Set strings = section.getKeys(false); + String name = strings.iterator().next(); + ConfigurationSection section0 = section.getConfigurationSection(name); + if(section0 == null) return null; + String data_type = section0.getString("data_type"); + //data_type may be null + ItemStack item; + if("nbt".equals(data_type)) item = readFromNBT(section0,"data"); + else if("advanced".equals(data_type)) item = readFromAdvData(section0, "data"); + else item = readFromBukkit(section0,"data"); + double d0 = section0.getDouble("drop_chance.value"); + String str = section0.getString("drop_chance.format"); + return new Reward(item,new Chance(d0, str)); + } + public static ItemStack readFromAdvData(ConfigurationSection section, String path){ + ConfigurationSection data = section.getConfigurationSection(path); + if(data == null) return new ItemStack(Material.AIR); + String type = data.getString("type"); + if(type == null || "AIR".equals(type)) return new ItemStack(Material.AIR); + int amount = data.getInt("amount"); + Material material = Material.getMaterial(type); + if(material == null) return new ItemStack(Material.AIR); + ItemStack item = new ItemStack(material,amount); + //internal + if(data.contains("internal")){ + ConfigurationSection internal_section = data.getConfigurationSection("internal"); + if(internal_section!=null){ + if("nbt".equals(internal_section.getString("data_type"))){ + String nbt = internal_section.getString("data"); + Object cpd = EnderDragon.getInstance().getNMSManager().getCPD(nbt); + Map mp_tag = new HashMap<>(); + mp_tag.put("tag",cpd); + Object full_cpd = EnderDragon.getInstance().getNMSManager().getNBTTagCompound(mp_tag); + item = EnderDragon.getInstance().getNMSManager().mergeItemCPD(item,full_cpd); + } +// else{ +// Map mp = getUnhandledTags(internal_section); +// EnderDragon.getInstance().getNMSManager().setUnhandledTags(meta,mp); +// } +// Map mp = new HashMap<>(); +// internal_section.getKeys(false).forEach(key->{ +// Object obj = internal_section.get(key);//obj instanceof String +// Object nbt_base = EnderDragon.getInstance().getNMSItemManager().readAsNBTBase((String) obj); +// mp.put(key,nbt_base); +// }); +// Map mp = getUnhandledTags(internal_section); +// NBTTagCompound cpd = getNBTTagCompound(mp); +// net.minecraft.world.item.ItemStack ei = CraftItemStack.asNMSCopy(item); +// ei.c(cpd); +// item = CraftItemStack.asBukkitCopy(ei); + //EnderDragon.getInstance().getNMSManager().setUnhandledTags(meta,mp); + } + } + //damage + if(data.contains("damage")){ + int damage = data.getInt("damage"); + item.setDurability((short) damage); + } + ItemMeta meta = item.getItemMeta(); + if(meta == null) return item; + //DisplayName + String display_name = data.getString("display_name"); + if(display_name != null) meta.setDisplayName(display_name); + //LocalizedName + if(data.contains("localized_name")){ + String LocalizedName = data.getString("localized_name"); + if(LocalizedName != null) meta.setLocalizedName(LocalizedName); + } + //lore + if(data.contains("lore")){ + List lores = data.getStringList("lore"); + if(!lores.isEmpty()) meta.setLore(lores); + } + //Enchantments + if(data.contains("enchants")){ + ConfigurationSection enchants = data.getConfigurationSection("enchants"); + if(enchants != null){ + //Map mp = new HashMap<>(); + enchants.getKeys(false).forEach(key->{ + Enchantment enchantment = Enchantment.getByName(key); + int level = enchants.getInt(key); + if(enchantment != null && level>0){ + meta.addEnchant(enchantment,level,true); + } + }); + } + } + //CustomModelData + if(data.contains("CustomModelData")){ + int CustomModelData = data.getInt("CustomModelData"); + meta.setCustomModelData(CustomModelData); + } + //AttributeModifiers + if(data.contains("AttributeModifiers")){ + ConfigurationSection attributes = data.getConfigurationSection("AttributeModifiers"); + if(attributes != null){ + attributes.getKeys(false).forEach(name->{ + Attribute attribute = Attribute.valueOf(name); + AttributeModifier modifier = (AttributeModifier) attributes.get(name); + if(modifier != null){ + meta.addAttributeModifier(attribute,modifier); + } + }); + } + } + //RepairCost + if(data.contains("RepairCost")){ + int cost = data.getInt("RepairCost"); + if(meta instanceof Repairable){ + ((Repairable)meta).setRepairCost(cost); + } + } + //ItemFlags + if(data.contains("ItemFlags")){ + List names = data.getStringList("ItemFlags"); + names.forEach(name->meta.addItemFlags(ItemFlag.valueOf(name))); + } + //Unbreakable + if(data.contains("unbreakable") && data.getBoolean("unbreakable")) meta.setUnbreakable(true); + //PersistentDataContainer + if(data.contains("PersistentDataContainer")){ + ConfigurationSection dataContainer_section = data.getConfigurationSection("PersistentDataContainer"); + if(dataContainer_section != null){ + if("nbt".equals(dataContainer_section.getString("data_type"))){ + String nbt = dataContainer_section.getString("data"); + Object cpd = EnderDragon.getInstance().getNMSManager().getCPD(nbt); + PersistentDataContainer container = meta.getPersistentDataContainer(); + EnderDragon.getInstance().getNMSManager().setPersistentDataContainer(container, cpd); + } + } + } + item.setItemMeta(meta); + return item; + } + public static ItemStack readFromNBT(ConfigurationSection section, String path){ + String nbt = section.getString(path); + if (nbt == null) return new ItemStack(Material.AIR); + return EnderDragon.getInstance().getNMSItemManager().readAsItem(nbt); + } + public static ItemStack readFromBukkit(ConfigurationSection section, String path){ + String nbt = section.getString(path); + if (nbt == null) return new ItemStack(Material.AIR); + return section.getItemStack(path); + } + public static ItemStack readFromString(String str){ + YamlConfiguration yml = new YamlConfiguration(); + yml.set("test",str); + return yml.getItemStack("test"); + } + public static void addLoreFront(ItemStack item, String lore){ + ItemMeta meta = item.getItemMeta(); + if(meta != null) { + List lores = meta.getLore(); + if (lores != null) { + lores.add(0,lore); + meta.setLore(lores); + } + else { + meta.setLore(Collections.singletonList(lore)); + } + item.setItemMeta(meta); + } + } + public static void addLoreBack(ItemStack item, String lore){ + ItemMeta meta = item.getItemMeta(); + if(meta != null) { + List lores = meta.getLore(); + if (lores != null) { + lores.add(lore); + meta.setLore(lores); + } + else { + meta.setLore(Collections.singletonList(lore)); + } + item.setItemMeta(meta); + } + } + public static boolean isEmpty(ItemStack item){ + if(item == null) return true; + if(item.getType() == Material.AIR) return true; + return false; + } + private static void saveUnhandledTags(ConfigurationSection section, Map mp){ + mp.forEach((k,v)->{ + //Bukkit.broadcastMessage(k+": "+v.getClass().toString()); + if(v instanceof Map){ + saveUnhandledTags(section.createSection(k), (Map) v); + } + else section.set(k,v.toString()); + }); + } +/** + private static void saveUnhandledTags(ConfigurationSection section, Map mp){ + mp.forEach((k,v)->{ + Object obj = v; + //Bukkit.broadcastMessage(obj.getClass().toString()); + try{ + obj = EnderDragon.getInstance().getNMSItemManager().parseNBT(v); + }catch (Throwable ignored){ + + } + if(obj instanceof Map){ + saveUnhandledTags(section.createSection(k), (Map) obj); + } + else section.set(k,obj); + }); + }**/ + private static Map getUnhandledTags(ConfigurationSection section){ + Map res = new HashMap<>(); + section.getKeys(false).forEach(key->{ + Object obj = section.get(key); + if(obj instanceof ConfigurationSection){ + ConfigurationSection subSection = section.getConfigurationSection(key); + if(subSection != null){ + obj = getUnhandledTags(subSection); +// Object mp = getUnhandledTags(subSection); +// Bukkit.getLogger().info(mp.getClass().toString()); +// try{ +// obj = EnderDragon.getInstance().getNMSItemManager().getNBTBase(mp); +// }catch (Throwable throwable){ +// +// } + } + } + else obj = EnderDragon.getInstance().getNMSManager().getCPD((String) obj); + //else obj = EnderDragon.getInstance().getNMSItemManager().readAsNBTBase((String) obj); + res.put(key,obj); + }); + return res; + } + +// private static Object dfs(ConfigurationSection section){ +// section.getKeys(false).forEach(key->{ +// Object obj = section.get(key); +// if(obj instanceof ConfigurationSection){ +// ConfigurationSection subSection = section.getConfigurationSection(key); +// if(subSection != null) obj = dfs(subSection); +// } +// else obj = EnderDragon.getInstance().getNMSItemManager().readAsNBTBase((String) obj); +// +// }); +// return +// } + +// //internal +// Map mp = EnderDragon.getInstance().getNMSManager().getUnhandledTags(meta); +// if(mp != null){ +// ConfigurationSection internal = section_data.createSection("internal"); +// mp.forEach((k,v)->{ +// Object obj = EnderDragon.getInstance().getNMSItemManager().parseNBT(v); +// +// if(obj instanceof Map) obj = obj.toString(); +// else if(obj instanceof List) obj = obj.toString(); +// +// internal.set(k,obj); +// }); +// } + + + + +} diff --git a/src/main/java/pers/xanadu/enderdragon/manager/RewardManager.java b/src/main/java/pers/xanadu/enderdragon/manager/RewardManager.java new file mode 100644 index 0000000..681c354 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/manager/RewardManager.java @@ -0,0 +1,117 @@ +package pers.xanadu.enderdragon.manager; + +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.reward.Reward; +import pers.xanadu.enderdragon.reward.Chance; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import static pers.xanadu.enderdragon.EnderDragon.*; + +public class RewardManager { + + public static void reload(){ + for(MyDragon dragon : DragonManager.dragons){ + dragon.datum.clear(); + File file = getRewardFile(dragon.unique_name); + if(file == null) return; + FileConfiguration data = YamlConfiguration.loadConfiguration(file); + String path = "list"; + List list = data.getStringList(path); + // if list == null ? + for(String str : list){ + YamlConfiguration yml = new YamlConfiguration(); + try{ + yml.loadFromString(str); + Reward reward = ItemManager.readAsReward(yml); + dragon.datum.add(reward); + }catch (InvalidConfigurationException e){ + Lang.error(Lang.plugin_item_read_error + str); + } + } + } + } + public static void addItem(String key,Reward reward){ + addItem(key,reward.getItem(),reward.getChance()); + } + public static void addItem(String key, ItemStack item, Chance chance){ + MyDragon dragon = DragonManager.mp.get(key); + if(dragon == null) return; + File file = getRewardFile(dragon.unique_name); + if(file == null) return; + FileConfiguration data = YamlConfiguration.loadConfiguration(file); + String path = "list"; + List list = data.getStringList(path); + Reward reward = new Reward(item,chance); + list.add(reward.toString()); + data.set(path,list); + try { + data.save(file); + } catch (IOException e) { + throw new RuntimeException(e); + } + dragon.datum.add(reward); + } + public static void clearItem(String key){ + MyDragon dragon = DragonManager.mp.get(key); + if(dragon == null) return; + File file = getRewardFile(dragon.unique_name); + if(file == null) return; + FileConfiguration data = YamlConfiguration.loadConfiguration(file); + String path = "list"; + data.set(path,""); + try { + data.save(file); + } catch (IOException e) { + throw new RuntimeException(e); + } + dragon.datum.clear(); + } + public static boolean removeItem(String key,int idx){ + MyDragon dragon = DragonManager.mp.get(key); + if(dragon == null) return false; + File file = getRewardFile(dragon.unique_name); + if(file == null) return false; + FileConfiguration data = YamlConfiguration.loadConfiguration(file); + String path = "list"; + List list = data.getStringList(path); + try{ + list.remove(idx); + data.set(path,list); + data.save(file); + dragon.datum.remove(idx); + return true; + }catch (IndexOutOfBoundsException e){ + Lang.error("Index out of bound!"); + }catch (IOException e) { + throw new RuntimeException(e); + } + return false; + } + private static File getRewardFile(String key){ + String file_path = "reward/" + key + ".yml"; + File file = new File(plugin.getDataFolder(),file_path); + if(!file.exists()) { + try{ + YamlConfiguration yml = new YamlConfiguration(); + yml.set("version","2.1.0"); + yml.set("list",""); + yml.save(file); + }catch (IOException e){ + Lang.error("Not Found "+file_path+" ,skipped it."); + return null; + } + } + return new File(plugin.getDataFolder(),file_path); + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/manager/TaskManager.java b/src/main/java/pers/xanadu/enderdragon/manager/TaskManager.java new file mode 100644 index 0000000..9277d56 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/manager/TaskManager.java @@ -0,0 +1,93 @@ +package pers.xanadu.enderdragon.manager; + +import pers.xanadu.enderdragon.config.Config; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.task.type.*; +import pers.xanadu.enderdragon.task.Task; +import pers.xanadu.enderdragon.task.TaskType; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Date; + +import static pers.xanadu.enderdragon.EnderDragon.*; + +public class TaskManager { + private static final DateTimeFormatter RoundTimeFormat_hm = DateTimeFormatter.ofPattern("HH:mm"); + private static final DateTimeFormatter RoundTimeFormat_all = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + public static String path = "auto_respawn.next_respawn_time"; + public static Task task = null; + public static Task parse(String string){ + String[] str = string.split(":",2); + TaskType taskType = TaskType.getByName(str[0]); + switch (taskType){ + case minute : { + return new Minute(TaskType.minute,str[1]); + } + case hour : { + return new Hour(TaskType.hour,str[1]); + } + case day : { + return new Day(TaskType.day,str[1]); + } + case week : { + return new Week(TaskType.week,str[1]); + } + case month : { + return new Month(TaskType.month,str[1]); + } + case year : { + return new Year(TaskType.year,str[1]); + } + default : { + return null; + } + } + } + public static void reload(){ + task = parse(Config.auto_respawn_respawn_time); + } + public static LocalTime getRoundTime(String str){ + try { + return LocalTime.parse(str, RoundTimeFormat_hm); + }catch (DateTimeParseException e){ + Lang.error("\"respawn_time\" in config.yml error!The format of time should be HH:mm."); + } + return null; + } + public static String getRoundTimeStr(LocalDateTime time){ + return time.format(RoundTimeFormat_all); + } + public static LocalDateTime getLocalDateTime(String str){ + if(isValidTime(str)) return LocalDateTime.parse(str, RoundTimeFormat_all); + return null; + } + public static boolean isValidTime(String str){ + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + try{ + df.parse(str); + } catch (ParseException e) { + Lang.error("\"next_respawn_time\" in data.yml error!The format of time should be HH:mm."); + return false; + } + return true; + } + public static void saveFile(LocalDateTime nextTime){ + data.set(TaskManager.path,getRoundTimeStr(nextTime)); + try{ + data.save(dataF); + }catch (IOException ex){ + Lang.error(Lang.plugin_file_save_error.replaceAll("\\{file_name}",dataF.getName())); + } + } + public static String getCurrentTimeWithSpecialFormat(){ + SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH∶mm∶ss");//这里的∶是特殊字符 + return df.format(new Date()); + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/manager/TimerManager.java b/src/main/java/pers/xanadu/enderdragon/manager/TimerManager.java new file mode 100644 index 0000000..92e512d --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/manager/TimerManager.java @@ -0,0 +1,75 @@ +package pers.xanadu.enderdragon.manager; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.task.DragonRespawnTimer; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; + +import static pers.xanadu.enderdragon.EnderDragon.plugin; + +public class TimerManager { + private static final HashMap mp = new HashMap<>(); + public static void enable(){ + File file = new File(plugin.getDataFolder(),"respawn_cd.yml"); + if(file.exists()){ + FileConfiguration fc = YamlConfiguration.loadConfiguration(file); + ConfigurationSection section = fc.getConfigurationSection("respawn_cd"); + if(section == null) return; + section.getKeys(false).forEach(name->{ + int set_time = section.getInt(name+".setTime"); + int rest_time = section.getInt(name+".remainTime"); + if(set_time>0){ + boolean run = section.getBoolean(name+".isRunning"); + DragonRespawnTimer timer = new DragonRespawnTimer(name,set_time,rest_time); + if(run) timer.run(); + TimerManager.mp.put(name,timer); + } + }); + } + } + public static void save(){ + YamlConfiguration yml = new YamlConfiguration(); + mp.forEach((k,v)->{ + ConfigurationSection section = yml.createSection("respawn_cd."+k); + if(v.getRestTime()>0){ + //section.set("world_name",k); + section.set("setTime",v.getSetTime()); + section.set("remainTime",v.getRestTime()); + section.set("isRunning",v.isRunning()); + } + }); + try{ + yml.save(new File(plugin.getDataFolder(),"respawn_cd.yml")); + }catch (IOException e){ + Lang.error("Failed to save respawn_cd.yml!"); + } + } + public static void startTimer(String world_name){ + DragonRespawnTimer timer = mp.get(world_name); + if(timer != null){ + timer.run(); + } + } + public static void setTimer(String world_name, DragonRespawnTimer timer){ + DragonRespawnTimer timer_old = mp.get(world_name); + if(timer_old != null) timer_old.del(); + mp.put(world_name,timer); + } + public static DragonRespawnTimer getTimer(String world_name){ + return mp.get(world_name); + } + public static void removeTimer(String world_name){ + DragonRespawnTimer timer_old = mp.get(world_name); + if(timer_old != null) timer_old.del(); + mp.remove(world_name); + } + public static void removeAll(){ + mp.values().forEach(DragonRespawnTimer::del); + mp.clear(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/manager/WorldManager.java b/src/main/java/pers/xanadu/enderdragon/manager/WorldManager.java new file mode 100644 index 0000000..d8fde3f --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/manager/WorldManager.java @@ -0,0 +1,196 @@ +package pers.xanadu.enderdragon.manager; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Entity; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.util.Version; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import static java.lang.Math.sqrt; +import static pers.xanadu.enderdragon.EnderDragon.getInstance; +import static pers.xanadu.enderdragon.util.MathUtil.*; + +public class WorldManager { + public static final List worlds = new ArrayList<>(); + private Field dimension; + private Field world_provider; + private Method getDimensionID; + + public static void reload(){ + worlds.clear(); + Bukkit.getWorlds().forEach(world -> worlds.add(world.getName())); + } + + public static Collection getExplosionDragon(float power, Location loc){ + World world = loc.getWorld(); + if(world == null) return Collections.EMPTY_LIST; + return getExplosionDragon(loc.getWorld(),power,loc.getX()+0.5d,loc.getY()+0.5d,loc.getZ()+0.5d); + } + public static Collection getExplosionDragon(World world,float power,double x,double y,double z){ + float f = power * 2.0F; + int x1 = floor(x - (double)f - 1.0); + int x2 = floor(x + (double)f + 1.0); + int y1 = floor(y - (double)f - 1.0); + int y2 = floor(y + (double)f + 1.0); + int z1 = floor(z - (double)f - 1.0); + int z2 = floor(z + (double)f + 1.0); +// Collection list = world.getNearbyEntities(new BoundingBox(x1, y1, z1, x2, y2, z2)); + Location cen = new Location(world,(x1+x2)/2d,(y1+y2)/2d,(z1+z2)/2d); + double rx = (x2-x1)/2d; + double ry = (y2-y1)/2d; + double rz = (z2-z1)/2d; + Collection list = world.getNearbyEntities(cen,rx,ry,rz); + List res = new ArrayList<>(); + for (Entity entity : list) { + if(entity instanceof EnderDragon){ + double d0 = sqrt(c(entity,x, y, z)) / f; + if (d0 <= 1.0) { + Location loc = entity.getLocation(); + double dx = loc.getX() - x; + double dy = loc.getY() + 6.8d - y; + double dz = loc.getZ() - z; + double d1 = sqrt(dx * dx + dy * dy + dz * dz); + if (d1 != 0.0) { + res.add((EnderDragon) entity); + } + } + } + } + return res; + } +// public static float a(Vector endPos, Entity entity) { +// BoundingBox bb = entity.getBoundingBox(); +// double d0 = 1.0 / ((bb.getMaxX() - bb.getMinX()) * 2.0 + 1.0); +// double d1 = 1.0 / ((bb.getMaxY() - bb.getMinY()) * 2.0 + 1.0); +// double d2 = 1.0 / ((bb.getMaxZ() - bb.getMinZ()) * 2.0 + 1.0); +// double d3 = (1.0 - Math.floor(1.0 / d0) * d0) / 2.0; +// double d4 = (1.0 - Math.floor(1.0 / d2) * d2) / 2.0; +// if (d0 >= 0.0 && d1 >= 0.0 && d2 >= 0.0) { +// int i = 0; +// int j = 0; +// +// for(float f = 0.0F; f <= 1.0F; f = (float)((double)f + d0)) { +// for(float f1 = 0.0F; f1 <= 1.0F; f1 = (float)((double)f1 + d1)) { +// for(float f2 = 0.0F; f2 <= 1.0F; f2 = (float)((double)f2 + d2)) { +// double d5 = d(f, bb.getMinX(), bb.getMaxX()); +// double d6 = d(f1, bb.getMinY(), bb.getMaxY()); +// double d7 = d(f2, bb.getMinZ(), bb.getMaxZ()); +// //Vec3D vec3d1 = new Vec3D(d5 + d3, d6, d7 + d4); +// Location start = new Location(entity.getWorld(),d5 + d3, d6, d7 + d4); +// Vector dir = new Vector(endPos.getX()-start.getX(),endPos.getY()-start.getY(),endPos.getZ()-start.getZ()); +// double maxDistance = dir.length(); +// RayTraceResult result = entity.getWorld().rayTraceBlocks(start,dir,maxDistance, FluidCollisionMode.NEVER,false); +// if(result == null) ++i; +//// if (entity.getWorld().rayTrace(new RayTrace(vec3d1, endPos, RayTrace.BlockCollisionOption.OUTLINE, RayTrace.FluidCollisionOption.NONE, entity)).getType() == MovingObjectPosition.EnumMovingObjectType.MISS) { +//// ++i; +//// } +// ++j; +// } +// } +// } +// return (float)i / (float)j; +// } else { +// return 0.0F; +// } +// } + + public void fixWorldEnvironment(){ + Bukkit.getWorlds().forEach(world -> { + try{ + if(isTheEnd(world)) getInstance().getNMSManager().setEnvironment(world, World.Environment.THE_END); + }catch(ReflectiveOperationException e){ + e.printStackTrace(); + } + }); + } + private boolean isTheEnd(World world) throws ReflectiveOperationException { + String version = Version.getVersion(); + switch (version) { + case "v1_12_R1" : + case "v1_13_R1" : { + Object world_server = getInstance().getNMSManager().getWorldServer(world); + if(dimension == null) dimension = world_server.getClass().getDeclaredField("dimension"); + int dimen = (int) dimension.get(world_server); + return dimen == 1; + } + case "v1_13_R2" : { + Object world_server = getInstance().getNMSManager().getWorldServer(world); + if(dimension == null) dimension = world_server.getClass().getField("dimension"); + Object DimensionManager = dimension.get(world_server); + if(getDimensionID == null) getDimensionID = DimensionManager.getClass().getMethod("getDimensionID"); + int dimen = (int) getDimensionID.invoke(DimensionManager); + return dimen == 1; + } + case "v1_14_R1" : + case "v1_15_R1" : { + Object world_server = getInstance().getNMSManager().getWorldServer(world); + if(world_provider == null) world_provider = world_server.getClass().getField("worldProvider"); + Object worldProvider = world_provider.get(world_server); + if(dimension == null) dimension = getInstance().getNMSManager().getWorldProviderClass().getDeclaredField("f"); + dimension.setAccessible(true); + Object DimensionManager = dimension.get(worldProvider); + if(getDimensionID == null) getDimensionID = DimensionManager.getClass().getMethod("getDimensionID"); + int dimen = (int) getDimensionID.invoke(DimensionManager); + return dimen == 1; + } + case "v1_16_R1" : + case "v1_16_R2" : + case "v1_16_R3" : + case "v1_17_R1" : { + Object world_server = getInstance().getNMSManager().getWorldServer(world); + if(getDimensionID == null) getDimensionID = getInstance().getNMSManager().getWorldClass().getMethod("getDimensionKey"); + Object world_type = getDimensionID.invoke(world_server); + return world_type.toString().contains("minecraft:the_end"); + } + default : { + if(Version.mcMainVersion < 12){ + Lang.warn("Your server version (" + version + ") is not supported!"); + return false; + } + Object world_server = getInstance().getNMSManager().getWorldServer(world); + if(getDimensionID == null) getDimensionID = world_server.getClass().getMethod("getTypeKey"); + Object world_type = getDimensionID.invoke(world_server); + return world_type.toString().contains("minecraft:the_end"); + } + } + /* + try{ + //>=1.18 建议使用WorldServer::getTypeKey + Object world_server = getInstance().getNMSManager().getWorldServer(world); + Class World_Class = Class.forName("net.minecraft.server."+ Version.getVersion()+".World");//<=1.16.5 + Object world_type = World_Class.getDeclaredMethod("getDimensionKey").invoke(world_server);//<=1.17.1 + + String string_type = world_type.toString(); + Bukkit.broadcastMessage(string_type); + + Class ResourceKey_Class = Class.forName("net.minecraft.server."+Version.getVersion()+".ResourceKey"); + Object ResourceKey = ResourceKey_Class.cast(world_type); + Object MinecraftKey = ResourceKey_Class.getDeclaredMethod("a").invoke(ResourceKey); + Class MinecraftKey_Class = Class.forName("net.minecraft.server."+Version.getVersion()+".MinecraftKey"); + String string_type2 = (String) MinecraftKey_Class.getDeclaredMethod("getKey").invoke(MinecraftKey); + Bukkit.broadcastMessage(string_type2); + + + + +// Object world_c = getCraftWorld(world); +// Object envi = CraftWorldClass.getDeclaredMethod("getEnvironment").invoke(world_c); +// World.Environment environment = (World.Environment) envi; +// Bukkit.broadcastMessage(environment.toString()); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + */ + } + +} + diff --git a/src/main/java/pers/xanadu/enderdragon/metrics/Metrics.java b/src/main/java/pers/xanadu/enderdragon/metrics/Metrics.java new file mode 100644 index 0000000..7964196 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/metrics/Metrics.java @@ -0,0 +1,849 @@ +package pers.xanadu.enderdragon.metrics; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.Method; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.zip.GZIPOutputStream; +import javax.net.ssl.HttpsURLConnection; +import org.bukkit.Bukkit; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.java.JavaPlugin; + +public class Metrics { + + private final Plugin plugin; + + private final MetricsBase metricsBase; + + /** + * Creates a new Metrics instance. + * + * @param plugin Your plugin instance. + * @param serviceId The id of the service. It can be found at What is my plugin id? + */ + public Metrics(JavaPlugin plugin, int serviceId) { + this.plugin = plugin; + // Get the config file + File bStatsFolder = new File(plugin.getDataFolder().getParentFile(), "bStats"); + File configFile = new File(bStatsFolder, "config.yml"); + YamlConfiguration config = YamlConfiguration.loadConfiguration(configFile); + if (!config.isSet("serverUuid")) { + config.addDefault("enabled", true); + config.addDefault("serverUuid", UUID.randomUUID().toString()); + config.addDefault("logFailedRequests", false); + config.addDefault("logSentData", false); + config.addDefault("logResponseStatusText", false); + // Inform the server owners about bStats + config + .options() + .header( + "bStats (https://bStats.org) collects some basic information for plugin authors, like how\n" + + "many people use their plugin and their total player count. It's recommended to keep bStats\n" + + "enabled, but if you're not comfortable with this, you can turn this setting off. There is no\n" + + "performance penalty associated with having metrics enabled, and data sent to bStats is fully\n" + + "anonymous.") + .copyDefaults(true); + try { + config.save(configFile); + } catch (IOException ignored) { + } + } + // Load the data + boolean enabled = config.getBoolean("enabled", true); + String serverUUID = config.getString("serverUuid"); + boolean logErrors = config.getBoolean("logFailedRequests", false); + boolean logSentData = config.getBoolean("logSentData", false); + boolean logResponseStatusText = config.getBoolean("logResponseStatusText", false); + metricsBase = + new MetricsBase( + "bukkit", + serverUUID, + serviceId, + enabled, + this::appendPlatformData, + this::appendServiceData, + submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask), + plugin::isEnabled, + (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error), + (message) -> this.plugin.getLogger().log(Level.INFO, message), + logErrors, + logSentData, + logResponseStatusText); + } + + /** + * Adds a custom chart. + * + * @param chart The chart to add. + */ + public void addCustomChart(CustomChart chart) { + metricsBase.addCustomChart(chart); + } + + private void appendPlatformData(JsonObjectBuilder builder) { + builder.appendField("playerAmount", getPlayerAmount()); + builder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0); + builder.appendField("bukkitVersion", Bukkit.getVersion()); + builder.appendField("bukkitName", Bukkit.getName()); + builder.appendField("javaVersion", System.getProperty("java.version")); + builder.appendField("osName", System.getProperty("os.name")); + builder.appendField("osArch", System.getProperty("os.arch")); + builder.appendField("osVersion", System.getProperty("os.version")); + builder.appendField("coreCount", Runtime.getRuntime().availableProcessors()); + } + + private void appendServiceData(JsonObjectBuilder builder) { + builder.appendField("pluginVersion", plugin.getDescription().getVersion()); + } + + private int getPlayerAmount() { + try { + // Around MC 1.8 the return type was changed from an array to a collection, + // This fixes java.lang.NoSuchMethodError: + // org.bukkit.Bukkit.getOnlinePlayers()Ljava/util/Collection; + Method onlinePlayersMethod = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"); + return onlinePlayersMethod.getReturnType().equals(Collection.class) + ? ((Collection) onlinePlayersMethod.invoke(Bukkit.getServer())).size() + : ((Player[]) onlinePlayersMethod.invoke(Bukkit.getServer())).length; + } catch (Exception e) { + // Just use the new method if the reflection failed + return Bukkit.getOnlinePlayers().size(); + } + } + + public static class MetricsBase { + + /** The version of the Metrics class. */ + public static final String METRICS_VERSION = "3.0.0"; + + private static final ScheduledExecutorService scheduler = + Executors.newScheduledThreadPool(1, task -> new Thread(task, "bStats-Metrics")); + + private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s"; + + private final String platform; + + private final String serverUuid; + + private final int serviceId; + + private final Consumer appendPlatformDataConsumer; + + private final Consumer appendServiceDataConsumer; + + private final Consumer submitTaskConsumer; + + private final Supplier checkServiceEnabledSupplier; + + private final BiConsumer errorLogger; + + private final Consumer infoLogger; + + private final boolean logErrors; + + private final boolean logSentData; + + private final boolean logResponseStatusText; + + private final Set customCharts = new HashSet<>(); + + private final boolean enabled; + + /** + * Creates a new MetricsBase class instance. + * + * @param platform The platform of the service. + * @param serviceId The id of the service. + * @param serverUuid The server uuid. + * @param enabled Whether or not data sending is enabled. + * @param appendPlatformDataConsumer A consumer that receives a {@code JsonObjectBuilder} and + * appends all platform-specific data. + * @param appendServiceDataConsumer A consumer that receives a {@code JsonObjectBuilder} and + * appends all service-specific data. + * @param submitTaskConsumer A consumer that takes a runnable with the submit task. This can be + * used to delegate the data collection to a another thread to prevent errors caused by + * concurrency. Can be {@code null}. + * @param checkServiceEnabledSupplier A supplier to check if the service is still enabled. + * @param errorLogger A consumer that accepts log message and an error. + * @param infoLogger A consumer that accepts info log messages. + * @param logErrors Whether or not errors should be logged. + * @param logSentData Whether or not the sent data should be logged. + * @param logResponseStatusText Whether or not the response status text should be logged. + */ + public MetricsBase( + String platform, + String serverUuid, + int serviceId, + boolean enabled, + Consumer appendPlatformDataConsumer, + Consumer appendServiceDataConsumer, + Consumer submitTaskConsumer, + Supplier checkServiceEnabledSupplier, + BiConsumer errorLogger, + Consumer infoLogger, + boolean logErrors, + boolean logSentData, + boolean logResponseStatusText) { + this.platform = platform; + this.serverUuid = serverUuid; + this.serviceId = serviceId; + this.enabled = enabled; + this.appendPlatformDataConsumer = appendPlatformDataConsumer; + this.appendServiceDataConsumer = appendServiceDataConsumer; + this.submitTaskConsumer = submitTaskConsumer; + this.checkServiceEnabledSupplier = checkServiceEnabledSupplier; + this.errorLogger = errorLogger; + this.infoLogger = infoLogger; + this.logErrors = logErrors; + this.logSentData = logSentData; + this.logResponseStatusText = logResponseStatusText; + checkRelocation(); + if (enabled) { + // WARNING: Removing the option to opt-out will get your plugin banned from bStats + startSubmitting(); + } + } + + public void addCustomChart(CustomChart chart) { + this.customCharts.add(chart); + } + + private void startSubmitting() { + final Runnable submitTask = + () -> { + if (!enabled || !checkServiceEnabledSupplier.get()) { + // Submitting data or service is disabled + scheduler.shutdown(); + return; + } + if (submitTaskConsumer != null) { + submitTaskConsumer.accept(this::submitData); + } else { + this.submitData(); + } + }; + // Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution + // of requests on the + // bStats backend. To circumvent this problem, we introduce some randomness into the initial + // and second delay. + // WARNING: You must not modify and part of this Metrics class, including the submit delay or + // frequency! + // WARNING: Modifying this code will get your plugin banned on bStats. Just don't do it! + long initialDelay = (long) (1000 * 60 * (3 + Math.random() * 3)); + long secondDelay = (long) (1000 * 60 * (Math.random() * 30)); + scheduler.schedule(submitTask, initialDelay, TimeUnit.MILLISECONDS); + scheduler.scheduleAtFixedRate( + submitTask, initialDelay + secondDelay, 1000 * 60 * 30, TimeUnit.MILLISECONDS); + } + + private void submitData() { + final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder(); + appendPlatformDataConsumer.accept(baseJsonBuilder); + final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder(); + appendServiceDataConsumer.accept(serviceJsonBuilder); + JsonObjectBuilder.JsonObject[] chartData = + customCharts.stream() + .map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors)) + .filter(Objects::nonNull) + .toArray(JsonObjectBuilder.JsonObject[]::new); + serviceJsonBuilder.appendField("id", serviceId); + serviceJsonBuilder.appendField("customCharts", chartData); + baseJsonBuilder.appendField("service", serviceJsonBuilder.build()); + baseJsonBuilder.appendField("serverUUID", serverUuid); + baseJsonBuilder.appendField("metricsVersion", METRICS_VERSION); + JsonObjectBuilder.JsonObject data = baseJsonBuilder.build(); + scheduler.execute( + () -> { + try { + // Send the data + sendData(data); + } catch (Exception e) { + // Something went wrong! :( + if (logErrors) { + errorLogger.accept("Could not submit bStats metrics data", e); + } + } + }); + } + + private void sendData(JsonObjectBuilder.JsonObject data) throws Exception { + if (logSentData) { + infoLogger.accept("Sent bStats metrics data: " + data.toString()); + } + String url = String.format(REPORT_URL, platform); + HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection(); + // Compress the data to save bandwidth + byte[] compressedData = compress(data.toString()); + connection.setRequestMethod("POST"); + connection.addRequestProperty("Accept", "application/json"); + connection.addRequestProperty("Connection", "close"); + connection.addRequestProperty("Content-Encoding", "gzip"); + connection.addRequestProperty("Content-Length", String.valueOf(compressedData.length)); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("User-Agent", "Metrics-Service/1"); + connection.setDoOutput(true); + try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) { + outputStream.write(compressedData); + } + StringBuilder builder = new StringBuilder(); + try (BufferedReader bufferedReader = + new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + String line; + while ((line = bufferedReader.readLine()) != null) { + builder.append(line); + } + } + if (logResponseStatusText) { + infoLogger.accept("Sent data to bStats and received response: " + builder); + } + } + + /** Checks that the class was properly relocated. */ + private void checkRelocation() { + // You can use the property to disable the check in your test environment + if (System.getProperty("bstats.relocatecheck") == null + || !System.getProperty("bstats.relocatecheck").equals("false")) { + // Maven's Relocate is clever and changes strings, too. So we have to use this little + // "trick" ... :D + final String defaultPackage = + new String(new byte[] {'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's'}); + final String examplePackage = + new String(new byte[] {'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e'}); + // We want to make sure no one just copy & pastes the example and uses the wrong package + // names + if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage) + || MetricsBase.class.getPackage().getName().startsWith(examplePackage)) { + throw new IllegalStateException("bStats Metrics class has not been relocated correctly!"); + } + } + } + + /** + * Gzips the given string. + * + * @param str The string to gzip. + * @return The gzipped string. + */ + private static byte[] compress(final String str) throws IOException { + if (str == null) { + return null; + } + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) { + gzip.write(str.getBytes(StandardCharsets.UTF_8)); + } + return outputStream.toByteArray(); + } + } + + public static class DrilldownPie extends CustomChart { + + private final Callable>> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public DrilldownPie(String chartId, Callable>> callable) { + super(chartId); + this.callable = callable; + } + + @Override + public JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map> map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean reallyAllSkipped = true; + for (Map.Entry> entryValues : map.entrySet()) { + JsonObjectBuilder valueBuilder = new JsonObjectBuilder(); + boolean allSkipped = true; + for (Map.Entry valueEntry : map.get(entryValues.getKey()).entrySet()) { + valueBuilder.appendField(valueEntry.getKey(), valueEntry.getValue()); + allSkipped = false; + } + if (!allSkipped) { + reallyAllSkipped = false; + valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build()); + } + } + if (reallyAllSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class AdvancedPie extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public AdvancedPie(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) { + // Skip this invalid + continue; + } + allSkipped = false; + valuesBuilder.appendField(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class MultiLineChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public MultiLineChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue() == 0) { + // Skip this invalid + continue; + } + allSkipped = false; + valuesBuilder.appendField(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class SimpleBarChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SimpleBarChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + for (Map.Entry entry : map.entrySet()) { + valuesBuilder.appendField(entry.getKey(), new int[] {entry.getValue()}); + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public abstract static class CustomChart { + + private final String chartId; + + protected CustomChart(String chartId) { + if (chartId == null) { + throw new IllegalArgumentException("chartId must not be null"); + } + this.chartId = chartId; + } + + public JsonObjectBuilder.JsonObject getRequestJsonObject( + BiConsumer errorLogger, boolean logErrors) { + JsonObjectBuilder builder = new JsonObjectBuilder(); + builder.appendField("chartId", chartId); + try { + JsonObjectBuilder.JsonObject data = getChartData(); + if (data == null) { + // If the data is null we don't send the chart. + return null; + } + builder.appendField("data", data); + } catch (Throwable t) { + if (logErrors) { + errorLogger.accept("Failed to get data for custom chart with id " + chartId, t); + } + return null; + } + return builder.build(); + } + + protected abstract JsonObjectBuilder.JsonObject getChartData() throws Exception; + } + + public static class SimplePie extends CustomChart { + + private final Callable callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SimplePie(String chartId, Callable callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + String value = callable.call(); + if (value == null || value.isEmpty()) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("value", value).build(); + } + } + + public static class AdvancedBarChart extends CustomChart { + + private final Callable> callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public AdvancedBarChart(String chartId, Callable> callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + JsonObjectBuilder valuesBuilder = new JsonObjectBuilder(); + Map map = callable.call(); + if (map == null || map.isEmpty()) { + // Null = skip the chart + return null; + } + boolean allSkipped = true; + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue().length == 0) { + // Skip this invalid + continue; + } + allSkipped = false; + valuesBuilder.appendField(entry.getKey(), entry.getValue()); + } + if (allSkipped) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build(); + } + } + + public static class SingleLineChart extends CustomChart { + + private final Callable callable; + + /** + * Class constructor. + * + * @param chartId The id of the chart. + * @param callable The callable which is used to request the chart data. + */ + public SingleLineChart(String chartId, Callable callable) { + super(chartId); + this.callable = callable; + } + + @Override + protected JsonObjectBuilder.JsonObject getChartData() throws Exception { + int value = callable.call(); + if (value == 0) { + // Null = skip the chart + return null; + } + return new JsonObjectBuilder().appendField("value", value).build(); + } + } + + /** + * An extremely simple JSON builder. + * + *

While this class is neither feature-rich nor the most performant one, it's sufficient enough + * for its use-case. + */ + public static class JsonObjectBuilder { + + private StringBuilder builder = new StringBuilder(); + + private boolean hasAtLeastOneField = false; + + public JsonObjectBuilder() { + builder.append("{"); + } + + /** + * Appends a null field to the JSON. + * + * @param key The key of the field. + * @return A reference to this object. + */ + public JsonObjectBuilder appendNull(String key) { + appendFieldUnescaped(key, "null"); + return this; + } + + /** + * Appends a string field to the JSON. + * + * @param key The key of the field. + * @param value The value of the field. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, String value) { + if (value == null) { + throw new IllegalArgumentException("JSON value must not be null"); + } + appendFieldUnescaped(key, "\"" + escape(value) + "\""); + return this; + } + + /** + * Appends an integer field to the JSON. + * + * @param key The key of the field. + * @param value The value of the field. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, int value) { + appendFieldUnescaped(key, String.valueOf(value)); + return this; + } + + /** + * Appends an object to the JSON. + * + * @param key The key of the field. + * @param object The object. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, JsonObject object) { + if (object == null) { + throw new IllegalArgumentException("JSON object must not be null"); + } + appendFieldUnescaped(key, object.toString()); + return this; + } + + /** + * Appends a string array to the JSON. + * + * @param key The key of the field. + * @param values The string array. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, String[] values) { + if (values == null) { + throw new IllegalArgumentException("JSON values must not be null"); + } + String escapedValues = + Arrays.stream(values) + .map(value -> "\"" + escape(value) + "\"") + .collect(Collectors.joining(",")); + appendFieldUnescaped(key, "[" + escapedValues + "]"); + return this; + } + + /** + * Appends an integer array to the JSON. + * + * @param key The key of the field. + * @param values The integer array. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, int[] values) { + if (values == null) { + throw new IllegalArgumentException("JSON values must not be null"); + } + String escapedValues = + Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(",")); + appendFieldUnescaped(key, "[" + escapedValues + "]"); + return this; + } + + /** + * Appends an object array to the JSON. + * + * @param key The key of the field. + * @param values The integer array. + * @return A reference to this object. + */ + public JsonObjectBuilder appendField(String key, JsonObject[] values) { + if (values == null) { + throw new IllegalArgumentException("JSON values must not be null"); + } + String escapedValues = + Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(",")); + appendFieldUnescaped(key, "[" + escapedValues + "]"); + return this; + } + + /** + * Appends a field to the object. + * + * @param key The key of the field. + * @param escapedValue The escaped value of the field. + */ + private void appendFieldUnescaped(String key, String escapedValue) { + if (builder == null) { + throw new IllegalStateException("JSON has already been built"); + } + if (key == null) { + throw new IllegalArgumentException("JSON key must not be null"); + } + if (hasAtLeastOneField) { + builder.append(","); + } + builder.append("\"").append(escape(key)).append("\":").append(escapedValue); + hasAtLeastOneField = true; + } + + /** + * Builds the JSON string and invalidates this builder. + * + * @return The built JSON string. + */ + public JsonObject build() { + if (builder == null) { + throw new IllegalStateException("JSON has already been built"); + } + JsonObject object = new JsonObject(builder.append("}").toString()); + builder = null; + return object; + } + + /** + * Escapes the given string like stated in https://www.ietf.org/rfc/rfc4627.txt. + * + *

This method escapes only the necessary characters '"', '\'. and '\u0000' - '\u001F'. + * Compact escapes are not used (e.g., '\n' is escaped as "\u000a" and not as "\n"). + * + * @param value The value to escape. + * @return The escaped value. + */ + private static String escape(String value) { + final StringBuilder builder = new StringBuilder(); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + if (c == '"') { + builder.append("\\\""); + } else if (c == '\\') { + builder.append("\\\\"); + } else if (c <= '\u000F') { + builder.append("\\u000").append(Integer.toHexString(c)); + } else if (c <= '\u001F') { + builder.append("\\u00").append(Integer.toHexString(c)); + } else { + builder.append(c); + } + } + return builder.toString(); + } + + /** + * A super simple representation of a JSON object. + * + *

This class only exists to make methods of the {@link JsonObjectBuilder} type-safe and not + * allow a raw string inputs for methods like {@link JsonObjectBuilder#appendField(String, + * JsonObject)}. + */ + public static class JsonObject { + + private final String value; + + private JsonObject(String value) { + this.value = value; + } + + @Override + public String toString() { + return value; + } + } + } +} \ No newline at end of file diff --git a/src/main/java/pers/xanadu/enderdragon/nms/BossBar/I_BossBarManager.java b/src/main/java/pers/xanadu/enderdragon/nms/BossBar/I_BossBarManager.java new file mode 100644 index 0000000..7968aee --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/BossBar/I_BossBarManager.java @@ -0,0 +1,11 @@ +package pers.xanadu.enderdragon.nms.BossBar; + +import org.bukkit.World; + +import java.util.List; + +public interface I_BossBarManager { + void saveBossBarData(List worlds); + void loadBossBarData(List worlds); + void setBossBar(World world,String title,String color,String style); +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_12_R1/BossBarManager.java b/src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_12_R1/BossBarManager.java new file mode 100644 index 0000000..157f1cd --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_12_R1/BossBarManager.java @@ -0,0 +1,105 @@ +package pers.xanadu.enderdragon.nms.BossBar.v1_12_R1; + +import net.minecraft.server.v1_12_R1.BossBattle; +import net.minecraft.server.v1_12_R1.BossBattleServer; +import org.bukkit.World; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.craftbukkit.v1_12_R1.util.CraftChatMessage; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.nms.BossBar.I_BossBarManager; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.List; + +import static pers.xanadu.enderdragon.EnderDragon.getInstance; +import static pers.xanadu.enderdragon.EnderDragon.plugin; + +public class BossBarManager implements I_BossBarManager { + private Field BossBattleServer = null; + public void saveBossBarData(List worlds){ + File file = new File(plugin.getDataFolder(),"world_data.yml"); + YamlConfiguration yml = new YamlConfiguration(); + worlds.forEach(world -> { + try{ + Object edb = getInstance().getNMSManager().getEnderDragonBattle(world); + if(BossBattleServer == null) BossBattleServer = edb.getClass().getDeclaredField("c"); + BossBattleServer.setAccessible(true); + BossBattleServer bbs = (BossBattleServer) BossBattleServer.get(edb); + String path = world.getName()+"."; + yml.set(path+"title",bbs.title.getText()); + yml.set(path+"color",bbs.color.name()); + yml.set(path+"style",bbs.style.name()); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + }); + try{ + yml.save(file); + Lang.info("BossBar data has been saved!"); + }catch (IOException e){ + Lang.error("Failed to save world_data!"); + } + } + public void loadBossBarData(List worlds){ + File file = new File(plugin.getDataFolder(),"world_data.yml"); + if(!file.exists()) return; + Lang.info("Enabling BossBar fix..."); + YamlConfiguration yml = new YamlConfiguration(); + try{ + yml.load(file); + }catch (InvalidConfigurationException | IOException e) { + Lang.error("Failed to load world_data!"); + return; + } + worlds.forEach(world -> { + try{ + Object edb = getInstance().getNMSManager().getEnderDragonBattle(world); + if(BossBattleServer == null) BossBattleServer = edb.getClass().getDeclaredField("c"); + BossBattleServer.setAccessible(true); + BossBattleServer bbs = (BossBattleServer) BossBattleServer.get(edb); + String path = world.getName()+"."; + bbs.title = CraftChatMessage.fromString(yml.getString(path+"title"), true)[0]; + bbs.color = BossBattle.BarColor.valueOf(yml.getString(path+"color")); + bbs.style = BossBattle.BarStyle.valueOf(yml.getString(path+"style")); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + }); + } + public void setBossBar(World world,String title,String color,String style){ + BossBattleServer bbs = new BossBattleServer( + CraftChatMessage.fromString(title, true)[0], + convertColor(color), + convertStyle(style) + ); + bbs.setCreateFog(true); + bbs.setDarkenSky(true); + bbs.setPlayMusic(true); + try{ + Object edb = getInstance().getNMSManager().getEnderDragonBattle(world); + if(BossBattleServer == null) BossBattleServer = edb.getClass().getDeclaredField("c"); + BossBattleServer.setAccessible(true); + BossBattleServer.set(edb,bbs); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + } + private BossBattle.BarColor convertColor(String color) { + return BossBattle.BarColor.valueOf(color); + } + private BossBattle.BarStyle convertStyle(String style) { + switch (style) { + case "SOLID": + default: return net.minecraft.server.v1_12_R1.BossBattle.BarStyle.PROGRESS; + case "SEGMENTED_6": return net.minecraft.server.v1_12_R1.BossBattle.BarStyle.NOTCHED_6; + case "SEGMENTED_10": return net.minecraft.server.v1_12_R1.BossBattle.BarStyle.NOTCHED_10; + case "SEGMENTED_12": return net.minecraft.server.v1_12_R1.BossBattle.BarStyle.NOTCHED_12; + case "SEGMENTED_20": return net.minecraft.server.v1_12_R1.BossBattle.BarStyle.NOTCHED_20; + } + } + + +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_13_R1/BossBarManager.java b/src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_13_R1/BossBarManager.java new file mode 100644 index 0000000..4879e0b --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_13_R1/BossBarManager.java @@ -0,0 +1,103 @@ +package pers.xanadu.enderdragon.nms.BossBar.v1_13_R1; + +import net.minecraft.server.v1_13_R1.BossBattle; +import net.minecraft.server.v1_13_R1.BossBattleServer; +import org.bukkit.World; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.craftbukkit.v1_13_R1.util.CraftChatMessage; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.nms.BossBar.I_BossBarManager; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.List; + +import static pers.xanadu.enderdragon.EnderDragon.getInstance; +import static pers.xanadu.enderdragon.EnderDragon.plugin; + +public class BossBarManager implements I_BossBarManager { + private Field BossBattleServer = null; + public void saveBossBarData(List worlds){ + File file = new File(plugin.getDataFolder(),"world_data.yml"); + YamlConfiguration yml = new YamlConfiguration(); + worlds.forEach(world -> { + try{ + Object edb = getInstance().getNMSManager().getEnderDragonBattle(world); + if(BossBattleServer == null) BossBattleServer = edb.getClass().getDeclaredField("c"); + BossBattleServer.setAccessible(true); + BossBattleServer bbs = (BossBattleServer) BossBattleServer.get(edb); + String path = world.getName()+"."; + yml.set(path+"title",bbs.title.getText()); + yml.set(path+"color",bbs.color.name()); + yml.set(path+"style",bbs.style.name()); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + }); + try{ + yml.save(file); + Lang.info("BossBar data has been saved!"); + }catch (IOException e){ + Lang.error("Failed to save world_data!"); + } + } + public void loadBossBarData(List worlds){ + File file = new File(plugin.getDataFolder(),"world_data.yml"); + if(!file.exists()) return; + Lang.info("Enabling BossBar fix..."); + YamlConfiguration yml = new YamlConfiguration(); + try{ + yml.load(file); + }catch (InvalidConfigurationException | IOException e) { + Lang.error("Failed to load world_data!"); + return; + } + worlds.forEach(world -> { + try{ + Object edb = getInstance().getNMSManager().getEnderDragonBattle(world); + if(BossBattleServer == null) BossBattleServer = edb.getClass().getDeclaredField("c"); + BossBattleServer.setAccessible(true); + BossBattleServer bbs = (BossBattleServer) BossBattleServer.get(edb); + String path = world.getName()+"."; + bbs.title = CraftChatMessage.fromString(yml.getString(path+"title"), true)[0]; + bbs.color = BossBattle.BarColor.valueOf(yml.getString(path+"color")); + bbs.style = BossBattle.BarStyle.valueOf(yml.getString(path+"style")); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + }); + } + public void setBossBar(World world,String title,String color,String style){ + BossBattleServer bbs = new BossBattleServer( + CraftChatMessage.fromString(title, true)[0], + convertColor(color), + convertStyle(style) + ); + bbs.setCreateFog(true); + bbs.setDarkenSky(true); + bbs.setPlayMusic(true); + try{ + Object edb = getInstance().getNMSManager().getEnderDragonBattle(world); + if(BossBattleServer == null) BossBattleServer = edb.getClass().getDeclaredField("c"); + BossBattleServer.setAccessible(true); + BossBattleServer.set(edb,bbs); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + } + private BossBattle.BarColor convertColor(String color) { + return BossBattle.BarColor.valueOf(color); + } + private BossBattle.BarStyle convertStyle(String style) { + switch (style) { + case "SOLID": + default: return net.minecraft.server.v1_13_R1.BossBattle.BarStyle.PROGRESS; + case "SEGMENTED_6": return net.minecraft.server.v1_13_R1.BossBattle.BarStyle.NOTCHED_6; + case "SEGMENTED_10": return net.minecraft.server.v1_13_R1.BossBattle.BarStyle.NOTCHED_10; + case "SEGMENTED_12": return net.minecraft.server.v1_13_R1.BossBattle.BarStyle.NOTCHED_12; + case "SEGMENTED_20": return net.minecraft.server.v1_13_R1.BossBattle.BarStyle.NOTCHED_20; + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_13_R2/BossBarManager.java b/src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_13_R2/BossBarManager.java new file mode 100644 index 0000000..247e125 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/BossBar/v1_13_R2/BossBarManager.java @@ -0,0 +1,103 @@ +package pers.xanadu.enderdragon.nms.BossBar.v1_13_R2; + +import net.minecraft.server.v1_13_R2.BossBattle; +import net.minecraft.server.v1_13_R2.BossBattleServer; +import org.bukkit.World; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.craftbukkit.v1_13_R2.util.CraftChatMessage; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.nms.BossBar.I_BossBarManager; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.List; + +import static pers.xanadu.enderdragon.EnderDragon.getInstance; +import static pers.xanadu.enderdragon.EnderDragon.plugin; + +public class BossBarManager implements I_BossBarManager { + private Field BossBattleServer = null; + public void saveBossBarData(List worlds){ + File file = new File(plugin.getDataFolder(),"world_data.yml"); + YamlConfiguration yml = new YamlConfiguration(); + worlds.forEach(world -> { + try{ + Object edb = getInstance().getNMSManager().getEnderDragonBattle(world); + if(BossBattleServer == null) BossBattleServer = edb.getClass().getDeclaredField("bossBattle"); + BossBattleServer.setAccessible(true); + BossBattleServer bbs = (BossBattleServer) BossBattleServer.get(edb); + String path = world.getName()+"."; + yml.set(path+"title",bbs.title.getText()); + yml.set(path+"color",bbs.color.name()); + yml.set(path+"style",bbs.style.name()); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + }); + try{ + yml.save(file); + Lang.info("BossBar data has been saved!"); + }catch (IOException e){ + Lang.error("Failed to save world_data!"); + } + } + public void loadBossBarData(List worlds){ + File file = new File(plugin.getDataFolder(),"world_data.yml"); + if(!file.exists()) return; + Lang.info("Enabling BossBar fix..."); + YamlConfiguration yml = new YamlConfiguration(); + try{ + yml.load(file); + }catch (InvalidConfigurationException | IOException e) { + Lang.error("Failed to load world_data!"); + return; + } + worlds.forEach(world -> { + try{ + Object edb = getInstance().getNMSManager().getEnderDragonBattle(world); + if(BossBattleServer == null) BossBattleServer = edb.getClass().getDeclaredField("bossBattle"); + BossBattleServer.setAccessible(true); + BossBattleServer bbs = (BossBattleServer) BossBattleServer.get(edb); + String path = world.getName()+"."; + bbs.title = CraftChatMessage.fromString(yml.getString(path+"title"), true)[0]; + bbs.color = BossBattle.BarColor.valueOf(yml.getString(path+"color")); + bbs.style = BossBattle.BarStyle.valueOf(yml.getString(path+"style")); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + }); + } + public void setBossBar(World world,String title,String color,String style){ + BossBattleServer bbs = new BossBattleServer( + CraftChatMessage.fromString(title, true)[0], + convertColor(color), + convertStyle(style) + ); + bbs.setCreateFog(true); + bbs.setDarkenSky(true); + bbs.setPlayMusic(true); + try{ + Object edb = getInstance().getNMSManager().getEnderDragonBattle(world); + if(BossBattleServer == null) BossBattleServer = edb.getClass().getField("bossBattle"); + BossBattleServer.setAccessible(true); + BossBattleServer.set(edb,bbs); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + } + private BossBattle.BarColor convertColor(String color) { + return BossBattle.BarColor.valueOf(color); + } + private BossBattle.BarStyle convertStyle(String style) { + switch (style) { + case "SOLID": + default: return net.minecraft.server.v1_13_R2.BossBattle.BarStyle.PROGRESS; + case "SEGMENTED_6": return net.minecraft.server.v1_13_R2.BossBattle.BarStyle.NOTCHED_6; + case "SEGMENTED_10": return net.minecraft.server.v1_13_R2.BossBattle.BarStyle.NOTCHED_10; + case "SEGMENTED_12": return net.minecraft.server.v1_13_R2.BossBattle.BarStyle.NOTCHED_12; + case "SEGMENTED_20": return net.minecraft.server.v1_13_R2.BossBattle.BarStyle.NOTCHED_20; + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/I_NMSItemManager.java b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/I_NMSItemManager.java new file mode 100644 index 0000000..d1704c4 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/I_NMSItemManager.java @@ -0,0 +1,11 @@ +package pers.xanadu.enderdragon.nms.NMSItem; + +import org.bukkit.inventory.ItemStack; + +public interface I_NMSItemManager { + ItemStack readAsItem(String nbt); + ItemStack cpdToItem(Object cpd); + Object parseNBT(Object nbt_base); + Object readAsNBTBase(String raw); + Object getNBTBase(Object obj); +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_12_R1/CraftNBTTagConfigSerializer.java b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_12_R1/CraftNBTTagConfigSerializer.java new file mode 100644 index 0000000..ce86e30 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_12_R1/CraftNBTTagConfigSerializer.java @@ -0,0 +1,146 @@ +package pers.xanadu.enderdragon.nms.NMSItem.v1_12_R1; + +import net.minecraft.server.v1_12_R1.*; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.*; +import java.util.regex.Pattern; + +public class CraftNBTTagConfigSerializer { + private static final Pattern ARRAY = Pattern.compile("^\\[.*]"); + private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", 2); + private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", 2); + private static final Pattern byte_format = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)b", 2); + private static final Pattern short_format = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)s", 2); + private static final Pattern integer_format = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)"); + private static final Pattern long_format = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)l", 2); + private static final Pattern float_format = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?f", 2); + private static final Pattern double_format = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", 2); + private static final Pattern double_format2 = Pattern.compile("[-+]?(?:[0-9]+[.]|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?", 2); + + + public CraftNBTTagConfigSerializer() { + } + + public static Object serialize(NBTBase base) { + if (base instanceof NBTTagCompound) { + Map innerMap = new HashMap(); + + for (String key : ((NBTTagCompound) base).c()) { + innerMap.put(key, serialize(((NBTTagCompound) base).get(key))); + } + + return innerMap; + } + if (base instanceof NBTTagString) { + return ((NBTTagString) base).c_(); + } + else { + return base instanceof NBTTagInt ? base + "i" : base.toString(); + } + + } + + public static NBTBase deserialize(Object object) { + if (object instanceof Map) { + NBTTagCompound compound = new NBTTagCompound(); + for (Object obj : ((Map) object).entrySet()) { + Map.Entry entry = (Map.Entry) obj; + compound.set(entry.getKey(), deserialize(entry.getValue())); + } + return compound; + } else if (!(object instanceof List)) { + if (object instanceof String) { + String string = (String)object; + if (ARRAY.matcher(string).matches()) { + try { + Constructor constructor = MojangsonParser.class.getDeclaredConstructor(String.class); + MojangsonParser parser = constructor.newInstance(string); + Method parseArray = MojangsonParser.class.getDeclaredMethod("k"); + parseArray.setAccessible(true); + return (NBTBase) parseArray.invoke(parser); + } catch (Throwable e) { + throw new RuntimeException("Could not deserialize found list ", e); + } + } else if (INTEGER.matcher(string).matches()) { + return new NBTTagInt(Integer.parseInt(string.substring(0, string.length() - 1))); + } else if (DOUBLE.matcher(string).matches()) { + return new NBTTagDouble(Double.parseDouble(string.substring(0, string.length() - 1))); + } else { + try{ + Constructor constructor = MojangsonParser.class.getDeclaredConstructor(String.class); + MojangsonParser parser = constructor.newInstance(""); + Method parseLiteral = MojangsonParser.class.getDeclaredMethod("c", String.class); + parseLiteral.setAccessible(true); + NBTBase nbtBase = (NBTBase) parseLiteral.invoke(parser,string); + if (nbtBase instanceof NBTTagInt) { + return new NBTTagString(nbtBase.toString()); + } else { + return (nbtBase instanceof NBTTagDouble ? new NBTTagString(String.valueOf(((NBTTagDouble)nbtBase).asDouble())) : nbtBase); + } + }catch (ReflectiveOperationException e){ + throw new RuntimeException("Could not deserialize NBTBase"); + } + + } + } else { + throw new RuntimeException("Could not deserialize NBTBase"); + } + } else { + List list = (List)object; + if (list.isEmpty()) { + return new NBTTagList(); + } + else { + NBTTagList tagList = new NBTTagList(); + for (Object tag : list) { + tagList.add(deserialize(tag)); + } + return tagList; + } + } + } + public static NBTBase v1_12_R1_c(String raw) { + try { + if (float_format.matcher(raw).matches()) { + return new NBTTagFloat(Float.parseFloat(raw.substring(0, raw.length() - 1))); + } + + if (byte_format.matcher(raw).matches()) { + return new NBTTagByte(Byte.parseByte(raw.substring(0, raw.length() - 1))); + } + + if (long_format.matcher(raw).matches()) { + return new NBTTagLong(Long.parseLong(raw.substring(0, raw.length() - 1))); + } + + if (short_format.matcher(raw).matches()) { + return new NBTTagShort(Short.parseShort(raw.substring(0, raw.length() - 1))); + } + + if (integer_format.matcher(raw).matches()) { + return new NBTTagInt(Integer.parseInt(raw)); + } + + if (double_format.matcher(raw).matches()) { + return new NBTTagDouble(Double.parseDouble(raw.substring(0, raw.length() - 1))); + } + + if (double_format2.matcher(raw).matches()) { + return new NBTTagDouble(Double.parseDouble(raw)); + } + + if ("true".equalsIgnoreCase(raw)) { + return new NBTTagByte((byte)1); + } + + if ("false".equalsIgnoreCase(raw)) { + return new NBTTagByte((byte)0); + } + } catch (NumberFormatException e) { + e.printStackTrace(); + } + return new NBTTagString(raw); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_12_R1/NMSItemManager.java b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_12_R1/NMSItemManager.java new file mode 100644 index 0000000..7eaffea --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_12_R1/NMSItemManager.java @@ -0,0 +1,35 @@ +package pers.xanadu.enderdragon.nms.NMSItem.v1_12_R1; + +import net.minecraft.server.v1_12_R1.*; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_12_R1.inventory.CraftItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.nms.NMSItem.I_NMSItemManager; + +public class NMSItemManager implements I_NMSItemManager { + + public org.bukkit.inventory.ItemStack readAsItem(String nbt){ + try { + NBTTagCompound cpd = MojangsonParser.parse(nbt); + ItemStack ei = new ItemStack(cpd); + return CraftItemStack.asBukkitCopy(ei); + } catch (MojangsonParseException e) { + Lang.error("Wrong item nbt format:"+nbt); + return new org.bukkit.inventory.ItemStack(Material.AIR); + } + } + public org.bukkit.inventory.ItemStack cpdToItem(Object cpd){ + ItemStack ei = new ItemStack((NBTTagCompound) cpd); + return CraftItemStack.asBukkitCopy(ei); + } + public Object parseNBT(Object nbt_base){ + return CraftNBTTagConfigSerializer.serialize((NBTBase) nbt_base); + } + public Object readAsNBTBase(String raw){ + return CraftNBTTagConfigSerializer.v1_12_R1_c(raw); + } + public Object getNBTBase(Object obj){ + return CraftNBTTagConfigSerializer.deserialize(obj); + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R1/CraftNBTTagConfigSerializer.java b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R1/CraftNBTTagConfigSerializer.java new file mode 100644 index 0000000..d0b6947 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R1/CraftNBTTagConfigSerializer.java @@ -0,0 +1,151 @@ +package pers.xanadu.enderdragon.nms.NMSItem.v1_13_R1; + +import com.mojang.brigadier.StringReader; +import net.minecraft.server.v1_13_R1.*; + +import java.lang.reflect.Method; +import java.util.*; +import java.util.regex.Pattern; + +public class CraftNBTTagConfigSerializer { + private static final Pattern ARRAY = Pattern.compile("^\\[.*]"); + private static final Pattern INTEGER = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)?i", 2); + private static final Pattern DOUBLE = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", 2); + public static final MojangsonParser MOJANGSON_PARSER = new MojangsonParser(new StringReader("")); + private static final Pattern byte_format = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)b", 2); + private static final Pattern short_format = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)s", 2); + private static final Pattern integer_format = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)"); + private static final Pattern long_format = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)l", 2); + private static final Pattern float_format = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?f", 2); + private static final Pattern double_format = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", 2); + private static final Pattern double_format_2 = Pattern.compile("[-+]?(?:[0-9]+[.]|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?", 2); + + public CraftNBTTagConfigSerializer() { + } + + public static Object serialize(NBTBase base) { + if (base instanceof NBTTagCompound) { + Map innerMap = new HashMap(); + Iterator var3 = ((NBTTagCompound)base).getKeys().iterator(); + + while(var3.hasNext()) { + String key = (String)var3.next(); + innerMap.put(key, serialize(((NBTTagCompound)base).get(key))); + } + + return innerMap; + } else if (!(base instanceof NBTTagList)) { + if (base instanceof NBTTagString) { + return base.b_(); + } else { + return base instanceof NBTTagInt ? base + "i" : base.toString(); + } + } else { + List baseList = new ArrayList(); + + for(int i = 0; i < ((NBTList)base).size(); ++i) { + baseList.add(serialize(((NBTList)base).get(i))); + } + + return baseList; + } + } + + public static NBTBase v1_13_R1_b(String str) { + try { + if (float_format.matcher(str).matches()) { + return new NBTTagFloat(Float.parseFloat(str.substring(0, str.length() - 1))); + } + + if (byte_format.matcher(str).matches()) { + return new NBTTagByte(Byte.parseByte(str.substring(0, str.length() - 1))); + } + + if (long_format.matcher(str).matches()) { + return new NBTTagLong(Long.parseLong(str.substring(0, str.length() - 1))); + } + + if (short_format.matcher(str).matches()) { + return new NBTTagShort(Short.parseShort(str.substring(0, str.length() - 1))); + } + + if (integer_format.matcher(str).matches()) { + return new NBTTagInt(Integer.parseInt(str)); + } + + if (double_format.matcher(str).matches()) { + return new NBTTagDouble(Double.parseDouble(str.substring(0, str.length() - 1))); + } + + if (double_format_2.matcher(str).matches()) { + return new NBTTagDouble(Double.parseDouble(str)); + } + + if ("true".equalsIgnoreCase(str)) { + return new NBTTagByte((byte)1); + } + + if ("false".equalsIgnoreCase(str)) { + return new NBTTagByte((byte)0); + } + } catch (NumberFormatException e) { + e.printStackTrace(); + } + return new NBTTagString(str); + } + + public static NBTBase deserialize(Object object) { + if (object instanceof Map) { + NBTTagCompound compound = new NBTTagCompound(); + for (Object obj : ((Map) object).entrySet()) { + Map.Entry entry = (Map.Entry) obj; + compound.set(entry.getKey(), deserialize(entry.getValue())); + } + return compound; + } else if (!(object instanceof List)) { + if (object instanceof String) { + String string = (String)object; + if (ARRAY.matcher(string).matches()) { + try { + Method parseArray = MojangsonParser.class.getDeclaredMethod("h"); + parseArray.setAccessible(true); + MojangsonParser parser = new MojangsonParser(new StringReader(string)); + return (NBTBase) parseArray.invoke(parser); + } catch (Throwable e) { + throw new RuntimeException("Could not deserialize found list ", e); + } + } else if (INTEGER.matcher(string).matches()) { + return new NBTTagInt(Integer.parseInt(string.substring(0, string.length() - 1))); + } else if (DOUBLE.matcher(string).matches()) { + return new NBTTagDouble(Double.parseDouble(string.substring(0, string.length() - 1))); + } else { + try{ + Method parseLiteral = MojangsonParser.class.getDeclaredMethod("b", String.class); + parseLiteral.setAccessible(true); + NBTBase nbtBase = (NBTBase) parseLiteral.invoke(MOJANGSON_PARSER,string); + if (nbtBase instanceof NBTTagInt) { + return new NBTTagString(nbtBase.b_()); + } else { + return (nbtBase instanceof NBTTagDouble ? new NBTTagString(String.valueOf(((NBTTagDouble)nbtBase).asDouble())) : nbtBase); + } + }catch (ReflectiveOperationException e){ + throw new RuntimeException("Could not deserialize NBTBase"); + } + } + } else { + throw new RuntimeException("Could not deserialize NBTBase"); + } + } else { + List list = (List)object; + if (list.isEmpty()) { + return new NBTTagList(); + } else { + NBTTagList tagList = new NBTTagList(); + for (Object tag : list) { + tagList.add(deserialize(tag)); + } + return tagList; + } + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R1/NMSItemManager.java b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R1/NMSItemManager.java new file mode 100644 index 0000000..1642a4e --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R1/NMSItemManager.java @@ -0,0 +1,37 @@ +package pers.xanadu.enderdragon.nms.NMSItem.v1_13_R1; + +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import net.minecraft.server.v1_13_R1.ItemStack; +import net.minecraft.server.v1_13_R1.MojangsonParser; +import net.minecraft.server.v1_13_R1.NBTBase; +import net.minecraft.server.v1_13_R1.NBTTagCompound; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_13_R1.inventory.CraftItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.nms.NMSItem.I_NMSItemManager; + +public class NMSItemManager implements I_NMSItemManager { + public org.bukkit.inventory.ItemStack readAsItem(String nbt){ + try { + NBTTagCompound cpd = MojangsonParser.parse(nbt); + ItemStack ei = ItemStack.a(cpd); + return CraftItemStack.asBukkitCopy(ei); + } catch (CommandSyntaxException e) { + Lang.error("Wrong item nbt format:"+nbt); + return new org.bukkit.inventory.ItemStack(Material.AIR); + } + } + public org.bukkit.inventory.ItemStack cpdToItem(Object cpd){ + ItemStack ei = ItemStack.a((NBTTagCompound) cpd); + return CraftItemStack.asBukkitCopy(ei); + } + public Object parseNBT(Object nbt_base){ + return CraftNBTTagConfigSerializer.serialize((NBTBase) nbt_base); + } + public Object readAsNBTBase(String raw){ + return CraftNBTTagConfigSerializer.v1_13_R1_b(raw); + } + public Object getNBTBase(Object obj){ + return CraftNBTTagConfigSerializer.deserialize(obj); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R2_above/NMSItemManager.java b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R2_above/NMSItemManager.java new file mode 100644 index 0000000..90e1b63 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/NMSItem/v1_13_R2_above/NMSItemManager.java @@ -0,0 +1,30 @@ +package pers.xanadu.enderdragon.nms.NMSItem.v1_13_R2_above; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.EnderDragon; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.nms.NMSItem.I_NMSItemManager; + +public class NMSItemManager implements I_NMSItemManager { + public ItemStack readAsItem(String nbt){ + try { + return EnderDragon.getInstance().getNMSManager().getItemStack(nbt); + } catch (Throwable e) { + Lang.error("Wrong item nbt format:"+nbt); + return new org.bukkit.inventory.ItemStack(Material.AIR); + } + } + public ItemStack cpdToItem(Object cpd){ + return EnderDragon.getInstance().getNMSManager().getItemStack(cpd); + } + public Object parseNBT(Object nbt_base){ + return EnderDragon.getInstance().getNMSManager().serializeNBTBase(nbt_base); + } + public Object readAsNBTBase(String raw){ + return EnderDragon.getInstance().getNMSManager().StringParseLiteral(raw); + } + public Object getNBTBase(Object obj){ + return EnderDragon.getInstance().getNMSManager().deserializeObject(obj); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/I_RespawnAnchorManager.java b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/I_RespawnAnchorManager.java new file mode 100644 index 0000000..98ec9f9 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/I_RespawnAnchorManager.java @@ -0,0 +1,7 @@ +package pers.xanadu.enderdragon.nms.RespawnAnchor; + +import org.bukkit.World; + +public interface I_RespawnAnchorManager { + boolean isRespawnAnchorWorks(World world); +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R1/RespawnAnchorManager.java b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R1/RespawnAnchorManager.java new file mode 100644 index 0000000..214724f --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R1/RespawnAnchorManager.java @@ -0,0 +1,15 @@ +package pers.xanadu.enderdragon.nms.RespawnAnchor.v1_16_R1; + +import net.minecraft.server.v1_16_R1.DimensionManager; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_16_R1.CraftWorld; +import pers.xanadu.enderdragon.nms.RespawnAnchor.I_RespawnAnchorManager; + +public class RespawnAnchorManager implements I_RespawnAnchorManager { + public boolean isRespawnAnchorWorks(World world){ + CraftWorld cw = (CraftWorld) world; + net.minecraft.server.v1_16_R1.World ew = cw.getHandle(); + DimensionManager dm = ew.getDimensionManager(); + return dm.isRespawnAnchorWorks(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R2/RespawnAnchorManager.java b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R2/RespawnAnchorManager.java new file mode 100644 index 0000000..3493704 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R2/RespawnAnchorManager.java @@ -0,0 +1,15 @@ +package pers.xanadu.enderdragon.nms.RespawnAnchor.v1_16_R2; + +import net.minecraft.server.v1_16_R2.DimensionManager; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_16_R2.CraftWorld; +import pers.xanadu.enderdragon.nms.RespawnAnchor.I_RespawnAnchorManager; + +public class RespawnAnchorManager implements I_RespawnAnchorManager { + public boolean isRespawnAnchorWorks(World world){ + CraftWorld cw = (CraftWorld) world; + net.minecraft.server.v1_16_R2.World ew = cw.getHandle(); + DimensionManager dm = ew.getDimensionManager(); + return dm.isRespawnAnchorWorks(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R3/RespawnAnchorManager.java b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R3/RespawnAnchorManager.java new file mode 100644 index 0000000..8956c12 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_16_R3/RespawnAnchorManager.java @@ -0,0 +1,15 @@ +package pers.xanadu.enderdragon.nms.RespawnAnchor.v1_16_R3; + +import net.minecraft.server.v1_16_R3.DimensionManager; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_16_R3.CraftWorld; +import pers.xanadu.enderdragon.nms.RespawnAnchor.I_RespawnAnchorManager; + +public class RespawnAnchorManager implements I_RespawnAnchorManager { + public boolean isRespawnAnchorWorks(World world){ + CraftWorld cw = (CraftWorld) world; + net.minecraft.server.v1_16_R3.World ew = cw.getHandle(); + DimensionManager dm = ew.getDimensionManager(); + return dm.isRespawnAnchorWorks(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_17_R1/RespawnAnchorManager.java b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_17_R1/RespawnAnchorManager.java new file mode 100644 index 0000000..04f8c40 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_17_R1/RespawnAnchorManager.java @@ -0,0 +1,15 @@ +package pers.xanadu.enderdragon.nms.RespawnAnchor.v1_17_R1; + +import net.minecraft.world.level.dimension.DimensionManager; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_17_R1.CraftWorld; +import pers.xanadu.enderdragon.nms.RespawnAnchor.I_RespawnAnchorManager; + +public class RespawnAnchorManager implements I_RespawnAnchorManager { + public boolean isRespawnAnchorWorks(World world){ + CraftWorld cw = (CraftWorld) world; + net.minecraft.world.level.World ew = cw.getHandle(); + DimensionManager dm = ew.getDimensionManager(); + return dm.isRespawnAnchorWorks(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_18_above/RespawnAnchorManager.java b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_18_above/RespawnAnchorManager.java new file mode 100644 index 0000000..3ef57e2 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/RespawnAnchor/v1_18_above/RespawnAnchorManager.java @@ -0,0 +1,10 @@ +package pers.xanadu.enderdragon.nms.RespawnAnchor.v1_18_above; + +import org.bukkit.World; +import pers.xanadu.enderdragon.nms.RespawnAnchor.I_RespawnAnchorManager; + +public class RespawnAnchorManager implements I_RespawnAnchorManager { + public boolean isRespawnAnchorWorks(World world){ + return world.isRespawnAnchorWorks(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/I_WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/I_WorldDataManager.java new file mode 100644 index 0000000..187b97a --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/I_WorldDataManager.java @@ -0,0 +1,7 @@ +package pers.xanadu.enderdragon.nms.WorldData; + +import org.bukkit.World; + +public interface I_WorldDataManager { + long getGameTime(World world); +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_12_R1/WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_12_R1/WorldDataManager.java new file mode 100644 index 0000000..67f1795 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_12_R1/WorldDataManager.java @@ -0,0 +1,14 @@ +package pers.xanadu.enderdragon.nms.WorldData.v1_12_R1; + +import net.minecraft.server.v1_12_R1.WorldServer; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_12_R1.CraftWorld; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +public class WorldDataManager implements I_WorldDataManager { + public long getGameTime(World world){ + CraftWorld cw = (CraftWorld) world; + WorldServer ws = cw.getHandle(); + return ws.getTime(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_13_R1/WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_13_R1/WorldDataManager.java new file mode 100644 index 0000000..8b41385 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_13_R1/WorldDataManager.java @@ -0,0 +1,14 @@ +package pers.xanadu.enderdragon.nms.WorldData.v1_13_R1; + +import net.minecraft.server.v1_13_R1.WorldServer; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_13_R1.CraftWorld; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +public class WorldDataManager implements I_WorldDataManager { + public long getGameTime(World world){ + CraftWorld cw = (CraftWorld) world; + WorldServer ws = cw.getHandle(); + return ws.getTime(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_13_R2/WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_13_R2/WorldDataManager.java new file mode 100644 index 0000000..e76ef5c --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_13_R2/WorldDataManager.java @@ -0,0 +1,14 @@ +package pers.xanadu.enderdragon.nms.WorldData.v1_13_R2; + +import net.minecraft.server.v1_13_R2.WorldServer; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_13_R2.CraftWorld; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +public class WorldDataManager implements I_WorldDataManager { + public long getGameTime(World world){ + CraftWorld cw = (CraftWorld) world; + WorldServer ws = cw.getHandle(); + return ws.getTime(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_14_R1/WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_14_R1/WorldDataManager.java new file mode 100644 index 0000000..b0fd469 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_14_R1/WorldDataManager.java @@ -0,0 +1,14 @@ +package pers.xanadu.enderdragon.nms.WorldData.v1_14_R1; + +import net.minecraft.server.v1_14_R1.WorldServer; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_14_R1.CraftWorld; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +public class WorldDataManager implements I_WorldDataManager { + public long getGameTime(World world){ + CraftWorld cw = (CraftWorld) world; + WorldServer ws = cw.getHandle(); + return ws.getTime(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_15_R1/WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_15_R1/WorldDataManager.java new file mode 100644 index 0000000..f2e35f9 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_15_R1/WorldDataManager.java @@ -0,0 +1,14 @@ +package pers.xanadu.enderdragon.nms.WorldData.v1_15_R1; + +import net.minecraft.server.v1_15_R1.WorldServer; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_15_R1.CraftWorld; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +public class WorldDataManager implements I_WorldDataManager { + public long getGameTime(World world){ + CraftWorld cw = (CraftWorld) world; + WorldServer ws = cw.getHandle(); + return ws.getTime(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R1/WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R1/WorldDataManager.java new file mode 100644 index 0000000..235f80a --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R1/WorldDataManager.java @@ -0,0 +1,14 @@ +package pers.xanadu.enderdragon.nms.WorldData.v1_16_R1; + +import net.minecraft.server.v1_16_R1.WorldServer; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_16_R1.CraftWorld; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +public class WorldDataManager implements I_WorldDataManager { + public long getGameTime(World world){ + CraftWorld cw = (CraftWorld) world; + WorldServer ws = cw.getHandle(); + return ws.getTime(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R2/WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R2/WorldDataManager.java new file mode 100644 index 0000000..1fc537c --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R2/WorldDataManager.java @@ -0,0 +1,14 @@ +package pers.xanadu.enderdragon.nms.WorldData.v1_16_R2; + +import net.minecraft.server.v1_16_R2.WorldServer; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_16_R2.CraftWorld; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +public class WorldDataManager implements I_WorldDataManager { + public long getGameTime(World world){ + CraftWorld cw = (CraftWorld) world; + WorldServer ws = cw.getHandle(); + return ws.getTime(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R3/WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R3/WorldDataManager.java new file mode 100644 index 0000000..0a4b223 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_16_R3/WorldDataManager.java @@ -0,0 +1,14 @@ +package pers.xanadu.enderdragon.nms.WorldData.v1_16_R3; + +import net.minecraft.server.v1_16_R3.WorldServer; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_16_R3.CraftWorld; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +public class WorldDataManager implements I_WorldDataManager { + public long getGameTime(World world){ + CraftWorld cw = (CraftWorld) world; + WorldServer ws = cw.getHandle(); + return ws.getTime(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_17_above/WorldDataManager.java b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_17_above/WorldDataManager.java new file mode 100644 index 0000000..fcd0f86 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/nms/WorldData/v1_17_above/WorldDataManager.java @@ -0,0 +1,10 @@ +package pers.xanadu.enderdragon.nms.WorldData.v1_17_above; + +import org.bukkit.World; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +public class WorldDataManager implements I_WorldDataManager { + public long getGameTime(World world){ + return world.getGameTime(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/reward/Chance.java b/src/main/java/pers/xanadu/enderdragon/reward/Chance.java new file mode 100644 index 0000000..e9a8ccb --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/Chance.java @@ -0,0 +1,22 @@ +package pers.xanadu.enderdragon.reward; + + +public class Chance { + private double value; + private String str; + public Chance(Chance chance){ + str = chance.str; + value = chance.value; + } + public Chance(double d0,String str){ + this.str = str; + this.value = d0; + } + public double getValue(){ + return value; + } + public String getStr(){ + return str; + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/reward/DistType.java b/src/main/java/pers/xanadu/enderdragon/reward/DistType.java new file mode 100644 index 0000000..f8d72a8 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/DistType.java @@ -0,0 +1,28 @@ +package pers.xanadu.enderdragon.reward; + +import java.util.Map; +import java.util.TreeMap; + +public enum DistType { + killer, + drop,//glow? + all, + rank,//num + pack,//num + termwise, + unknown; + + private static final Map mp = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + public static DistType getByName(String str){ + //if(str == null) return drop; + return mp.getOrDefault(str,unknown); + } + static { + DistType[] values = DistType.values(); + for (DistType type : values) { + String name = type.name(); + mp.put(name, type); + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/reward/Reward.java b/src/main/java/pers/xanadu/enderdragon/reward/Reward.java new file mode 100644 index 0000000..6bc6cf6 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/Reward.java @@ -0,0 +1,50 @@ +package pers.xanadu.enderdragon.reward; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.manager.ItemManager; + + +public class Reward extends ItemStack { + protected String name; + protected Chance chance; + private ItemStack item; + + @Override + public String toString(){ + return ItemManager.write(this); + } + + public String getName() { + return this.name; + } +// +// @Override +// public int hashCode() { +// return this.name.hashCode(); +// } + + public ItemStack getItem() { + if(item == null) return new ItemStack(Material.AIR); + return item.clone(); + } + public Chance getChance(){ + return this.chance; + } + + + + protected Reward(ItemStack item,String chance) { + this.item = item; + + } + public Reward(ItemStack item, Chance chance){ + this.item = item; + this.chance = chance; + } + public Reward(ItemStack item){ + this.item = item; + this.chance = null; + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/reward/RewardDist.java b/src/main/java/pers/xanadu/enderdragon/reward/RewardDist.java new file mode 100644 index 0000000..2b41a98 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/RewardDist.java @@ -0,0 +1,59 @@ +package pers.xanadu.enderdragon.reward; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.reward.dist.*; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +public abstract class RewardDist { + public static RewardDist parse(ConfigurationSection section){ + if(section == null) return new Dist_Drop(); + String type_name = section.getString("type"); + DistType type = DistType.getByName(type_name); + switch (type){ + case all : { + return new Dist_All(); + } + case drop : { + return new Dist_Drop(section.getConfigurationSection("drop")); + } + case killer : { + return new Dist_Killer(); + } + case pack : { + return new Dist_Pack(section.getConfigurationSection("pack")); + } + case rank : { + return new Dist_Rank(section.getConfigurationSection("rank")); + } + case termwise : { + return new Dist_Termwise(); + } + default : { + Lang.error("Unknown reward_dist type: "+type_name); + return new Dist_Drop(); + } + } + } + public List getDropReward(MyDragon myDragon){ + List list = new ArrayList<>(); + for(Reward reward : myDragon.datum){ + double chance = reward.getChance().getValue(); + if(chance > ThreadLocalRandom.current().nextDouble(100)){ + list.add(reward.getItem()); + } + } + return list; + } + public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){ + + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_All.java b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_All.java new file mode 100644 index 0000000..47abdd3 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_All.java @@ -0,0 +1,36 @@ +package pers.xanadu.enderdragon.reward.dist; + +import org.bukkit.Bukkit; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.manager.DamageManager; +import pers.xanadu.enderdragon.reward.RewardDist; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class Dist_All extends RewardDist { + @Override + public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){ + ConcurrentHashMap damage_data = DamageManager.data.get(dragon.getUniqueId()); + if(damage_data == null) return; + List items = getDropReward(myDragon); + if(items.isEmpty()) return; + Bukkit.getOnlinePlayers().forEach(p->{ + if(damage_data.containsKey(p.getName())){ + boolean full = false; + for(ItemStack item : items){ + if(full || p.getInventory().firstEmpty() == -1){ + p.getWorld().dropItem(p.getLocation(),item); + full = true; + } + else p.getInventory().addItem(item); + } + if(full) Lang.sendFeedback(p, Lang.dragon_player_inv_full); + } + }); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Drop.java b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Drop.java new file mode 100644 index 0000000..8cb1ce3 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Drop.java @@ -0,0 +1,53 @@ +package pers.xanadu.enderdragon.reward.dist; + +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; +import pers.xanadu.enderdragon.manager.GlowManager; +import pers.xanadu.enderdragon.reward.RewardDist; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +import static pers.xanadu.enderdragon.manager.GlowManager.setGlowingColor; + +public class Dist_Drop extends RewardDist { + private final GlowManager.GlowColor color; + public Dist_Drop(ConfigurationSection section){ + if(section == null) color = GlowManager.GlowColor.NONE; + else { + String color = section.getString("glow","NONE").toUpperCase(); + this.color = GlowManager.GlowColor.valueOf(color); + } + } + public Dist_Drop(){ + color = GlowManager.GlowColor.NONE; + } + @Override + public void handle_dist(final MyDragon myDragon, final EnderDragon dragon, final Player killer){ + List items = getDropReward(myDragon); + if(items.isEmpty()) return; + World world = dragon.getWorld(); + Location loc = dragon.getLocation(); + items.forEach(item->{ + Item entity_item = world.dropItemNaturally(loc,item); + ChatColor color = getGlowColor(); + if(color!=null) setGlowingColor(entity_item,color); + double x = ThreadLocalRandom.current().nextDouble(0.25); + double y = ThreadLocalRandom.current().nextDouble(0.25); + double z = ThreadLocalRandom.current().nextDouble(0.25); + entity_item.setVelocity(new Vector(x,y,z)); + }); + } + + public ChatColor getGlowColor(){ + return GlowManager.getGlowColor(color); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Killer.java b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Killer.java new file mode 100644 index 0000000..f442e38 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Killer.java @@ -0,0 +1,29 @@ +package pers.xanadu.enderdragon.reward.dist; + +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.reward.RewardDist; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.util.List; + +public class Dist_Killer extends RewardDist { + @Override + public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player p){ + List items = getDropReward(myDragon); + if(items.isEmpty()) return; + if(p != null){ + boolean full = false; + for(ItemStack item : items){ + if(full || p.getInventory().firstEmpty() == -1){ + p.getWorld().dropItem(p.getLocation(),item); + full = true; + } + else p.getInventory().addItem(item); + } + if(full) Lang.sendFeedback(p, Lang.dragon_player_inv_full); + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Pack.java b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Pack.java new file mode 100644 index 0000000..a443c3f --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Pack.java @@ -0,0 +1,53 @@ +package pers.xanadu.enderdragon.reward.dist; + +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.manager.DamageManager; +import pers.xanadu.enderdragon.reward.RewardDist; +import pers.xanadu.enderdragon.util.AExpJ; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class Dist_Pack extends RewardDist { + private final int max_num; + public Dist_Pack(ConfigurationSection section){ + if(section == null) max_num = 1; + else max_num = section.getInt("max_num",1); + } + + @Override + public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){ + ConcurrentHashMap damage_data = DamageManager.data.get(dragon.getUniqueId()); + if(damage_data == null) return; + List items = getDropReward(myDragon); + if(items.isEmpty()) return; + int m = Math.min(max_num,damage_data.size()); + if(m<=0) return; + List receivers = AExpJ.sample(damage_data,m); + receivers.forEach(receiver->{ + Player p = Bukkit.getPlayer(receiver); + if(p != null){ + boolean full = false; + for(ItemStack item : items){ + if(full || p.getInventory().firstEmpty() == -1){ + p.getWorld().dropItem(p.getLocation(),item); + full = true; + } + else p.getInventory().addItem(item); + } + if(full) Lang.sendFeedback(p, Lang.dragon_player_inv_full); + } + }); + } + + public int getMax_num(){ + return max_num; + } +} + diff --git a/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Rank.java b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Rank.java new file mode 100644 index 0000000..d17fb95 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Rank.java @@ -0,0 +1,57 @@ +package pers.xanadu.enderdragon.reward.dist; + +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.manager.DamageManager; +import pers.xanadu.enderdragon.reward.RewardDist; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +public class Dist_Rank extends RewardDist { + private final int max_num; + public Dist_Rank(ConfigurationSection section){ + if(section == null) max_num = 1; + else max_num = section.getInt("max_num",1); + } + public int getMax_num(){ + return max_num; + } + @Override + public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){ + ConcurrentHashMap damage_data = DamageManager.data.get(dragon.getUniqueId()); + if(damage_data == null) return; + List items = getDropReward(myDragon); + if(items.isEmpty()) return; + int m = Math.min(max_num,damage_data.size()); + if(m<=0) return; + List> list = damage_data.entrySet().stream().sorted(Dist_Rank::sortByDamage).collect(Collectors.toList()); + for(int i=0;i int sortByDamage(Map.Entry e1,Map.Entry e2){ + if(e2.getValue()>e1.getValue()) return 1; + if(e2.getValue().equals(e1.getValue())) return 0; + return -1; + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Termwise.java b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Termwise.java new file mode 100644 index 0000000..65bdc1d --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/reward/dist/Dist_Termwise.java @@ -0,0 +1,39 @@ +package pers.xanadu.enderdragon.reward.dist; + +import org.bukkit.Bukkit; +import org.bukkit.entity.EnderDragon; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.manager.DamageManager; +import pers.xanadu.enderdragon.reward.RewardDist; +import pers.xanadu.enderdragon.util.AliasSample; +import pers.xanadu.enderdragon.util.MyDragon; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +public class Dist_Termwise extends RewardDist { + @Override + public void handle_dist(final MyDragon myDragon,final EnderDragon dragon,final Player killer){ + ConcurrentHashMap damage_data = DamageManager.data.get(dragon.getUniqueId()); + if(damage_data == null) return; + List items = getDropReward(myDragon); + if(items.isEmpty()) return; + AliasSample alias = new AliasSample(new ArrayList<>(damage_data.values())); + List list = new ArrayList<>(damage_data.keySet()); + items.forEach(item->{ + int idx = alias.next(); + String receiver = list.get(idx); + Player p = Bukkit.getPlayer(receiver); + if(p != null){ + if(p.getInventory().firstEmpty() == -1){ + p.getWorld().dropItem(p.getLocation(),item); + Lang.sendFeedback(p, Lang.dragon_player_inv_full); + } + else p.getInventory().addItem(item); + } + }); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/DragonRespawnRunnable.java b/src/main/java/pers/xanadu/enderdragon/task/DragonRespawnRunnable.java new file mode 100644 index 0000000..6f42d2e --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/DragonRespawnRunnable.java @@ -0,0 +1,40 @@ +package pers.xanadu.enderdragon.task; + +import org.bukkit.scheduler.BukkitRunnable; +import pers.xanadu.enderdragon.config.Config; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.manager.TaskManager; +import pers.xanadu.enderdragon.EnderDragon; + +import static pers.xanadu.enderdragon.EnderDragon.plugin; + +public class DragonRespawnRunnable extends BukkitRunnable { + private static DragonRespawnRunnable runnable = null; + @Override + public void run(){ + if(TaskManager.task == null) { + this.cancel(); + runnable = null; + Lang.error("The config of auto-respawn errors!Task has been disabled..."); + return; + } + if(TaskManager.task.isTimeUp()){ + new BukkitRunnable(){ + @Override + public void run(){ + EnderDragon.getInstance().getDragonManager().initiateRespawn(Config.auto_respawn_world_the_end_name); + } + }.runTask(plugin); + TaskManager.task.updateTime(); + } + } + public static void reload(){ + if(runnable != null){ + runnable.cancel(); + runnable = null; + } + runnable = new DragonRespawnRunnable(); + runnable.runTaskTimerAsynchronously(plugin,0,200L); + Lang.info("The task has started to run..."); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/DragonRespawnTimer.java b/src/main/java/pers/xanadu/enderdragon/task/DragonRespawnTimer.java new file mode 100644 index 0000000..ade7165 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/DragonRespawnTimer.java @@ -0,0 +1,82 @@ +package pers.xanadu.enderdragon.task; + +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitRunnable; +import pers.xanadu.enderdragon.EnderDragon; +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.util.MathUtil; + +import static pers.xanadu.enderdragon.EnderDragon.plugin; + +public class DragonRespawnTimer { + private final String world_name; + private final int delay; + private BukkitRunnable runnable; + private int remainSecond; + private boolean isRunning; + public DragonRespawnTimer(String WorldName,int second){ + this(WorldName,second,second); + } + public DragonRespawnTimer(String WorldName,int second,int rest_second){ + this.world_name = WorldName; + this.delay = second; + this.remainSecond = rest_second; + this.isRunning = false; + resetRunnable(); + } + public void run(){ + if(!isRunning) runnable.runTaskTimerAsynchronously(plugin,0L,20L); + isRunning = true; + } + public void update(){ + remainSecond = delay; + runnable.cancel(); + isRunning = false; + resetRunnable(); + } + public void del(){ + if(isRunning) runnable.cancel(); + } + public String getWorld_name(){ + return this.world_name; + } + public int getSetTime(){ + return this.delay; + } + public int getRestTime(){ + return this.remainSecond; + } + public boolean isRunning(){ + return isRunning; + } + public double getProgress(){ + return 1d*remainSecond/delay; + } + @Override + public String toString(){ + return "(" + world_name + ") " + + "remain:" + MathUtil.formatDuration(remainSecond) + + ", set:" + MathUtil.formatDuration(delay); + } + private void resetRunnable(){ + this.runnable = new BukkitRunnable() { + @Override + public void run() { + remainSecond--; + if(remainSecond <= 0){ + Bukkit.getScheduler().runTask(plugin,() -> { + if(EnderDragon.getInstance().getDragonManager().canRespawn(world_name)){ + EnderDragon.getInstance().getDragonManager().initiateRespawn(world_name); + update(); + } + else { + remainSecond = delay; + Lang.error(Lang.command_respawn_cd_retry); + } + }); + } + } + }; + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/Task.java b/src/main/java/pers/xanadu/enderdragon/task/Task.java new file mode 100644 index 0000000..a0e41c0 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/Task.java @@ -0,0 +1,70 @@ +package pers.xanadu.enderdragon.task; + +import pers.xanadu.enderdragon.EnderDragon; +import pers.xanadu.enderdragon.manager.TaskManager; + +import java.time.LocalDateTime; +import java.time.LocalTime; + +public abstract class Task { + protected int period; + protected int day; + private final TaskType type; + public abstract LocalDateTime getNextTime(LocalDateTime cur); + public abstract void updateTime(); + protected LocalDateTime nextTime; + protected Task(TaskType type,String str){ + this.type = type; + switch (type){ + case minute : + case hour : { + this.period = Integer.parseInt(str); + break; + } + case day : { + this.period = Integer.parseInt(str.split(",")[0]); + break; + } + case week : + case month : + case year : { + this.day = Integer.parseInt(str.split(",")[0]); + break; + } + } + if(EnderDragon.data.getString(TaskManager.path) == null){ + switch (type){ + case minute : + case hour : { + this.nextTime = this.getNextTime(LocalDateTime.now().withSecond(0)); + break; + } + case day : + case week : + case month : + case year : { + calcNextTime(str); + break; + } + } + TaskManager.saveFile(nextTime); + } + else this.nextTime = TaskManager.getLocalDateTime(EnderDragon.data.getString(TaskManager.path)); + } + private void calcNextTime(String str){ + LocalTime time = TaskManager.getRoundTime(str.split(",")[1]); + if(time != null) this.nextTime = this.getNextTime(LocalDateTime.now().withSecond(0).with(time)); + else this.nextTime = this.getNextTime(LocalDateTime.now().withSecond(0)); + } + public boolean isTimeUp(){ + LocalDateTime now = LocalDateTime.now(); + if(now.isEqual(nextTime) || now.isAfter(nextTime)){ + return true; + } + return false; + } + public TaskType getType(){ + return this.type; + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/TaskType.java b/src/main/java/pers/xanadu/enderdragon/task/TaskType.java new file mode 100644 index 0000000..0a30096 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/TaskType.java @@ -0,0 +1,26 @@ +package pers.xanadu.enderdragon.task; + +import java.util.Map; +import java.util.TreeMap; + +public enum TaskType { + minute, + hour, + day, + week, + month, + year, + unknown; + private static final Map mp = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + public static TaskType getByName(String str){ + if(str == null) return unknown; + return mp.getOrDefault(str,unknown); + } + static{ + TaskType[] values = values(); + for (TaskType taskType : values) { + String name = taskType.name(); + mp.put(name, taskType); + } + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/type/Day.java b/src/main/java/pers/xanadu/enderdragon/task/type/Day.java new file mode 100644 index 0000000..473c003 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/type/Day.java @@ -0,0 +1,24 @@ +package pers.xanadu.enderdragon.task.type; + +import pers.xanadu.enderdragon.task.Task; +import pers.xanadu.enderdragon.task.TaskType; + +import java.time.LocalDateTime; + +import static pers.xanadu.enderdragon.manager.TaskManager.saveFile; + +public class Day extends Task { + + @Override + public LocalDateTime getNextTime(LocalDateTime cur) { + return cur.plusDays(period); + } + @Override + public void updateTime(){ + this.nextTime = LocalDateTime.now().withSecond(0).plusDays(period); + saveFile(nextTime); + } + public Day(TaskType type, String str){ + super(type,str); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/type/Hour.java b/src/main/java/pers/xanadu/enderdragon/task/type/Hour.java new file mode 100644 index 0000000..d76ce6f --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/type/Hour.java @@ -0,0 +1,23 @@ +package pers.xanadu.enderdragon.task.type; + +import pers.xanadu.enderdragon.task.Task; +import pers.xanadu.enderdragon.task.TaskType; + +import java.time.LocalDateTime; + +import static pers.xanadu.enderdragon.manager.TaskManager.saveFile; + +public class Hour extends Task { + @Override + public LocalDateTime getNextTime(LocalDateTime cur) { + return cur.plusHours(period); + } + @Override + public void updateTime(){ + this.nextTime = LocalDateTime.now().withSecond(0).plusHours(period); + saveFile(nextTime); + } + public Hour(TaskType type, String str){ + super(type,str); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/type/Minute.java b/src/main/java/pers/xanadu/enderdragon/task/type/Minute.java new file mode 100644 index 0000000..07dd2dd --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/type/Minute.java @@ -0,0 +1,26 @@ +package pers.xanadu.enderdragon.task.type; + +import pers.xanadu.enderdragon.task.Task; +import pers.xanadu.enderdragon.task.TaskType; + +import java.time.LocalDateTime; + +import static pers.xanadu.enderdragon.manager.TaskManager.saveFile; + +public class Minute extends Task { + + @Override + public LocalDateTime getNextTime(LocalDateTime cur) { + return cur.plusMinutes(period); + } + @Override + public void updateTime(){ + this.nextTime = LocalDateTime.now().withSecond(0).plusMinutes(period); + saveFile(nextTime); + } + + public Minute(TaskType type, String str){ + super(type,str); + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/type/Month.java b/src/main/java/pers/xanadu/enderdragon/task/type/Month.java new file mode 100644 index 0000000..e25eaa9 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/type/Month.java @@ -0,0 +1,24 @@ +package pers.xanadu.enderdragon.task.type; + +import pers.xanadu.enderdragon.task.Task; +import pers.xanadu.enderdragon.task.TaskType; + +import java.time.LocalDateTime; + +import static pers.xanadu.enderdragon.manager.TaskManager.saveFile; + +public class Month extends Task { + @Override + public LocalDateTime getNextTime(LocalDateTime cur) { + return cur.plusMonths(1).withDayOfMonth(day); + } + @Override + public void updateTime(){ + this.nextTime = LocalDateTime.now().withSecond(0).plusMonths(1).withDayOfMonth(day); + saveFile(nextTime); + } + public Month(TaskType type, String str){ + super(type,str); + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/type/Week.java b/src/main/java/pers/xanadu/enderdragon/task/type/Week.java new file mode 100644 index 0000000..6da40a7 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/type/Week.java @@ -0,0 +1,25 @@ +package pers.xanadu.enderdragon.task.type; + +import pers.xanadu.enderdragon.task.Task; +import pers.xanadu.enderdragon.task.TaskType; + +import java.time.DayOfWeek; +import java.time.LocalDateTime; + +import static pers.xanadu.enderdragon.manager.TaskManager.saveFile; + +public class Week extends Task { + + @Override + public LocalDateTime getNextTime(LocalDateTime cur) { + return cur.with(DayOfWeek.of(day)).plusDays(7); + } + @Override + public void updateTime(){ + this.nextTime = LocalDateTime.now().withSecond(0).plusDays(7); + saveFile(nextTime); + } + public Week(TaskType type, String str){ + super(type,str); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/task/type/Year.java b/src/main/java/pers/xanadu/enderdragon/task/type/Year.java new file mode 100644 index 0000000..ac98589 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/task/type/Year.java @@ -0,0 +1,23 @@ +package pers.xanadu.enderdragon.task.type; + +import pers.xanadu.enderdragon.task.Task; +import pers.xanadu.enderdragon.task.TaskType; + +import java.time.LocalDateTime; + +import static pers.xanadu.enderdragon.manager.TaskManager.saveFile; + +public class Year extends Task { + @Override + public LocalDateTime getNextTime(LocalDateTime cur) { + return cur.plusYears(1).withDayOfMonth(day); + } + @Override + public void updateTime(){ + this.nextTime = LocalDateTime.now().withSecond(0).plusYears(1); + saveFile(nextTime); + } + public Year(TaskType type, String str){ + super(type,str); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/util/AExpJ.java b/src/main/java/pers/xanadu/enderdragon/util/AExpJ.java new file mode 100644 index 0000000..b84b3f4 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/util/AExpJ.java @@ -0,0 +1,63 @@ +package pers.xanadu.enderdragon.util; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadLocalRandom; + +public final class AExpJ { + public static List sample(ConcurrentHashMap mp,int m){ + List> list = new ArrayList<>(); + mp.forEach((k,v)->list.add(new Pair<>(k,v))); + return sample(list,m); + } + public static List sample(List> samples, int m) { + PriorityQueue> heap = new PriorityQueue<>(Comparator.comparingDouble(p -> p.second)); + double Xw = 0.0; + double Tw = 0.0; + double w_acc = 0.0; + for (Pair sample : samples) { + if (heap.size() < m) { + double wi = sample.second; + double ui = ThreadLocalRandom.current().nextDouble(); + double ki = Math.pow(ui, 1 / wi); + heap.offer(new Pair<>(sample.first, ki)); + continue; + } + if (w_acc == 0) { + if (heap.isEmpty()) break; + Tw = heap.peek().second; + double r = ThreadLocalRandom.current().nextDouble(); + Xw = Math.log(r) / Math.log(Tw); + } + double wi = sample.second; + if (w_acc + wi < Xw) { + w_acc += wi; + continue; + } + else w_acc = 0; + double tw = Math.pow(Tw, wi); + double r2 = ThreadLocalRandom.current().nextDouble() * (1 - tw) + tw; + double ki = Math.pow(r2, 1 / wi); + heap.poll(); + heap.offer(new Pair<>(sample.first, ki)); + } + List res = new ArrayList<>(); + for (Pair pair : heap) { + res.add(pair.first); + } + return res; + } + +// public static void main(String[] args) { +// List> samples = new ArrayList<>(); +// samples.add(new Pair<>("item1", 0.8)); +// samples.add(new Pair<>("item2", 0.4)); +// samples.add(new Pair<>("item3", 0.2)); +// Map mp = new HashMap<>(); +// for(int i=0;i<1e5;i++){ +// List result = sample(samples, 1); +// mp.compute(result.get(0), (k, v)->v==null?1:v+1); +// } +// System.out.println(mp); +// } +} diff --git a/src/main/java/pers/xanadu/enderdragon/util/AliasSample.java b/src/main/java/pers/xanadu/enderdragon/util/AliasSample.java new file mode 100644 index 0000000..6a8a4f4 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/util/AliasSample.java @@ -0,0 +1,42 @@ +package pers.xanadu.enderdragon.util; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +public final class AliasSample { + private final int[] alias; + private final double[] probability; + public AliasSample(List probabilities) { + if (probabilities == null) throw new NullPointerException(); + if (probabilities.size() == 0) + throw new IllegalArgumentException("Probability vector can't be empty."); + this.probability = new double[probabilities.size()]; + this.alias = new int[probabilities.size()]; + final double average = 1.0 / probabilities.size(); + probabilities = new ArrayList<>(probabilities);//make a copy of list, avoid modifying the param + Deque small = new ArrayDeque<>(); + Deque large = new ArrayDeque<>(); + for (int i = 0; i < probabilities.size(); ++i) { + if (probabilities.get(i) >= average) large.add(i); + else small.add(i); + } + while (!small.isEmpty() && !large.isEmpty()) { + int less = small.removeLast(); + int more = large.removeLast(); + probability[less] = probabilities.get(less) * probabilities.size(); + alias[less] = more; + probabilities.set(more, (probabilities.get(more) + probabilities.get(less)) - average); + if (probabilities.get(more) >= 1.0 / probabilities.size()) large.add(more); + else small.add(more); + } + while (!small.isEmpty()) probability[small.removeLast()] = 1.0; + while (!large.isEmpty()) probability[large.removeLast()] = 1.0; + } + + public int next() { + int column = ThreadLocalRandom.current().nextInt(probability.length); + boolean coinToss = ThreadLocalRandom.current().nextDouble() < probability[column]; + return coinToss ? column : alias[column]; + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/util/ColorUtil.java b/src/main/java/pers/xanadu/enderdragon/util/ColorUtil.java new file mode 100644 index 0000000..b26b3f2 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/util/ColorUtil.java @@ -0,0 +1,63 @@ +package pers.xanadu.enderdragon.util; + +import net.md_5.bungee.api.ChatColor; + +import java.awt.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static pers.xanadu.enderdragon.util.Version.mcMainVersion; + +public class ColorUtil { + + public static Pattern hex_code = Pattern.compile("&#([0-9A-Fa-f]{6})"); + public static Pattern gradient = Pattern.compile("&\\[#([0-9a-fA-F]{6})-#([0-9a-fA-F]{6})(.+)]"); + public static String translateHexCodes (String str) { + if(mcMainVersion < 16) return str; + Matcher matcher = hex_code.matcher(str); + StringBuffer buffer = new StringBuffer(); + while(matcher.find()) { + matcher.appendReplacement(buffer, ChatColor.of("#" + matcher.group(1)).toString()); + } + return ChatColor.translateAlternateColorCodes('&', matcher.appendTail(buffer).toString()); + } + public static String transGradient(String str) { + if(mcMainVersion < 16) return str; + if (str.contains("&[#")&&str.contains("]")) { + Matcher matcher = gradient.matcher(str); + StringBuffer buffer = new StringBuffer(); + while (matcher.find()) { + String text = matcher.group(3); + int[] colors = gradient(matcher.group(1),matcher.group(2),text.length()); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + Color c = new Color(colors[i]); + builder.append(ChatColor.of(c)).append(text.charAt(i)); + } + matcher.appendReplacement(buffer, builder.toString()); + } + matcher.appendTail(buffer); + return buffer.toString(); + } + return translateHexCodes(str); + } + private static int[] gradient(String start,String end,int length){ + int[] color = new int[length]; + int[] rgb1 = MathUtil.hexToInt(start); + int[] rgb2 = MathUtil.hexToInt(end); + if(length==0){return color;} + if(length==1){ + for(int j=0;j<3;j++){ + color[0] = color[0]*256+rgb1[j]; + } + return color; + } + for(int i=0;i0){ + duration.append(days).append("d"); + f = true; + } + if(f||hours>0){ + duration.append(hours).append("h"); + f = true; + } + if(f||minutes>0){ + duration.append(minutes).append("m"); + } + duration.append(remainingSeconds).append("s"); + return duration.toString(); + } + public static int[] getDate(int seconds){ + if (seconds < 0) throw new IllegalArgumentException("Duration must be a positive number."); + int days = seconds / (24 * 3600); + int hours = (seconds % (24 * 3600)) / 3600; + int minutes = ((seconds % (24 * 3600)) % 3600) / 60; + int remainingSeconds = ((seconds % (24 * 3600)) % 3600) % 60; + return new int[]{days,hours,minutes,remainingSeconds}; + } + @Deprecated + public static K getByWeight(ConcurrentHashMap mp){ + double sum = mp.values().stream().mapToDouble(Double::doubleValue).sum(); + double rand = ThreadLocalRandom.current().nextDouble(sum); + final AtomicReference cur = new AtomicReference<>(0d); + final AtomicReference res = new AtomicReference<>(); + mp.forEach((k,v)->{ + Double value = cur.get(); + if(value<=rand && value+v>rand) { + res.set(k); + return; + } + cur.updateAndGet(v1 -> v1 + v); + }); + return res.get(); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/util/MyDragon.java b/src/main/java/pers/xanadu/enderdragon/util/MyDragon.java new file mode 100644 index 0000000..d17cd2e --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/util/MyDragon.java @@ -0,0 +1,60 @@ +package pers.xanadu.enderdragon.util; + +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import pers.xanadu.enderdragon.reward.Reward; +import pers.xanadu.enderdragon.reward.RewardDist; + +import java.util.ArrayList; +import java.util.List; + +public class MyDragon implements Comparable{ + public ItemStack icon; + public String unique_name; + public String display_name; + public String drop_gui; + public int edge; + public int priority; + public double spawn_chance; + public int max_health; + public int spawn_health; + public int exp_drop; + public int dragon_egg_spawn_delay; + public int dragon_egg_spawn_x; + public int dragon_egg_spawn_y; + public int dragon_egg_spawn_z; + public double dragon_egg_spawn_chance; + public double attack_damage_modify; + //public double move_speed_modify; + public double armor_modify; + public double armor_toughness_modify; + public double crystal_heal_speed; + public boolean suck_blood_enable; + public double suck_blood_rate; + public double suck_blood_base_amount; + public boolean suck_blood_only_player; + public List attack_potion_effect; + public List spawn_cmd; + public List death_cmd; + public List spawn_broadcast_msg; + public List death_broadcast_msg; + public List msg_to_killer; + public String glow_color; + public String bossbar_color; + public String bossbar_style; + public double effect_cloud_original_radius; + public double effect_cloud_expand_speed; + public int effect_cloud_duration; + public int effect_cloud_color_R; + public int effect_cloud_color_G; + public int effect_cloud_color_B; + public List effect_cloud_potion; + public List datum = new ArrayList<>(); + public RewardDist reward_dist; + + @Override + public int compareTo(MyDragon o) { + return o.priority - this.priority;//降序 + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/util/MyUpdater.java b/src/main/java/pers/xanadu/enderdragon/util/MyUpdater.java new file mode 100644 index 0000000..addd1e0 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/util/MyUpdater.java @@ -0,0 +1,40 @@ +package pers.xanadu.enderdragon.util; + +import org.bukkit.scheduler.BukkitRunnable; +import pers.xanadu.enderdragon.EnderDragon; +import pers.xanadu.enderdragon.config.Lang; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; + +public class MyUpdater { + public static void checkUpdate(){ + Lang.info(Lang.plugin_checking_update); + new BukkitRunnable(){ + @Override + public void run(){ + try { + URLConnection conn = new URL("https://api.github.com/repos/iXanadu13/EnderDragon/releases/latest").openConnection(); + conn.setConnectTimeout(20000); + conn.setReadTimeout(60000); + InputStream is = conn.getInputStream(); + String line = new BufferedReader(new InputStreamReader(is)).readLine(); + is.close(); + String newVer = line.substring(line.indexOf("\"tag_name\"") + 13, line.indexOf("\"target_commitish\"") - 2); + String localVer = EnderDragon.plugin.getDescription().getVersion(); + if (!localVer.equals(newVer)) { + Lang.warn(Lang.plugin_out_of_date.replace("{0}",localVer).replace("{1}",newVer)); + } + else{ + Lang.info(Lang.plugin_up_to_date.replace("{1}",newVer)); + } + } catch (Exception e) { + Lang.warn(Lang.plugin_check_update_fail); + } + } + }.runTaskAsynchronously(EnderDragon.plugin); + } +} diff --git a/src/main/java/pers/xanadu/enderdragon/util/NMSUtil.java b/src/main/java/pers/xanadu/enderdragon/util/NMSUtil.java new file mode 100644 index 0000000..f83fe5b --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/util/NMSUtil.java @@ -0,0 +1,444 @@ +package pers.xanadu.enderdragon.util; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataContainer; +import pers.xanadu.enderdragon.EnderDragon; +import pers.xanadu.enderdragon.config.Lang; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Map; + +import static pers.xanadu.enderdragon.EnderDragon.getInstance; + +public class NMSUtil { + private String getEDB_base; + private Method getNMSWord; + private Method asNMSCopy; + private Method copyNMSStack; + private Method asBukkitCopy; + private Method asCraftMirror; + private Method asCraftCopy; + private Method NMSItemStack_save; + private Method NMSItemStack_setTag; + private Method cpdToEi; + private Method stringToCPD; + private Method stringToNBTBase; + private Method serializeNBTBase; + private Method deserializeObject; + private Method PDCtoCPD; + private Method PersistentDataContainer_putAll; + private Method NBTTagCompound_set; + + private Field unhandledTags; + private Field internalTag; + private Field MOJANGSON_PARSER; + private Field world_c_environment; + private Field NBTTagCompound_map; + private Class WorldClass; + private Class CraftWorldClass; + private Class WorldProviderClass; + private Class WorldProviderTheEndClass; + private Class CraftItemStackClass; + private Class CraftMetaItemClass; + private Class NMSItemStackClass; + private Class CraftEntityClass; + private Class NBTTagCompoundClass; + private Class NBTBaseClass; + private Class MojangsonParserClass; + private Class CraftNBTTagConfigSerializerClass; + private Class CraftPersistentDataContainerClass; + + public void init(){ + String version = Version.getVersion(); + try{ + this.CraftWorldClass = Class.forName("org.bukkit.craftbukkit." + version + ".CraftWorld"); + this.WorldClass = CraftWorldClass.getDeclaredMethod("getHandle").getReturnType().getSuperclass(); + this.world_c_environment = CraftWorldClass.getDeclaredField("environment"); + this.world_c_environment.setAccessible(true); + if(Version.mcMainVersion>=12 && Version.mcMainVersion<16){ + this.WorldProviderClass = Class.forName("net.minecraft.server."+version+".WorldProvider"); + this.WorldProviderTheEndClass = Class.forName("net.minecraft.server."+version+".WorldProviderTheEnd"); + } + this.CraftItemStackClass = Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack"); + this.CraftMetaItemClass = Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftMetaItem"); + this.unhandledTags = CraftMetaItemClass.getDeclaredField("unhandledTags"); + unhandledTags.setAccessible(true); + this.internalTag = CraftMetaItemClass.getDeclaredField("internalTag"); + internalTag.setAccessible(true); + this.NMSItemStackClass = CraftItemStackClass.getDeclaredField("handle").getType(); + this.CraftEntityClass = Class.forName("org.bukkit.craftbukkit."+version+".entity.CraftEntity"); + init_NBTTagCompoundClass(); + init_NBTBaseClass(); + init_NBTTagCompound_map(); + this.NBTTagCompound_set = NBTTagCompoundClass.getMethod(getMethodName(ReflectiveMethod.NBTTagCompound_set),String.class,NBTBaseClass); + this.asNMSCopy = CraftItemStackClass.getMethod("asNMSCopy",ItemStack.class); + this.copyNMSStack = CraftItemStackClass.getMethod("copyNMSStack",NMSItemStackClass,int.class); + this.asBukkitCopy = CraftItemStackClass.getMethod("asBukkitCopy",NMSItemStackClass); + this.asCraftMirror = CraftItemStackClass.getMethod("asCraftMirror",NMSItemStackClass); + this.asCraftCopy = CraftItemStackClass.getMethod("asCraftCopy",ItemStack.class); + this.NMSItemStack_save = NMSItemStackClass.getMethod(getMethodName(ReflectiveMethod.NMSItemStack_save),NBTTagCompoundClass); + this.NMSItemStack_setTag = NMSItemStackClass.getMethod(getMethodName(ReflectiveMethod.NMSItemStack_setTag),NBTTagCompoundClass); + if(Version.mcMainVersion>=13) this.cpdToEi = NMSItemStackClass.getMethod("a",NBTTagCompoundClass); + + if(Version.mcMainVersion<=16) this.MojangsonParserClass = Class.forName("net.minecraft.server."+version+".MojangsonParser"); + else this.MojangsonParserClass = Class.forName("net.minecraft.nbt.MojangsonParser"); + this.stringToCPD = MojangsonParserClass.getMethod(getMethodName(ReflectiveMethod.MojangsonParser_parse),String.class); + this.stringToNBTBase = MojangsonParserClass.getDeclaredMethod(getMethodName(ReflectiveMethod.MojangsonParser_parseLiteral),String.class); + stringToNBTBase.setAccessible(true); + + if(Version.mcMainVersion>13 || "v1_13_R2".equals(Version.getVersion())){ + this.CraftNBTTagConfigSerializerClass = Class.forName("org.bukkit.craftbukkit." + version + ".util.CraftNBTTagConfigSerializer"); + this.serializeNBTBase = CraftNBTTagConfigSerializerClass.getMethods()[0]; + this.deserializeObject = CraftNBTTagConfigSerializerClass.getMethod("deserialize",Object.class); + this.MOJANGSON_PARSER = CraftNBTTagConfigSerializerClass.getDeclaredField("MOJANGSON_PARSER"); + MOJANGSON_PARSER.setAccessible(true); + } + if(Version.mcMainVersion>=14){ + this.CraftPersistentDataContainerClass = Class.forName("org.bukkit.craftbukkit." + version + ".persistence.CraftPersistentDataContainer"); + this.PDCtoCPD = CraftPersistentDataContainerClass.getDeclaredMethod("toTagCompound"); + this.PersistentDataContainer_putAll = CraftPersistentDataContainerClass.getDeclaredMethod("putAll",NBTTagCompoundClass); + } + + + + }catch(ReflectiveOperationException e){ + e.printStackTrace(); + } + switch (version) { + case "v1_12_R1" : { + getEDB_base = "t"; + break; + } + case "v1_13_R1" : + case "v1_13_R2" : { + getEDB_base = "r"; + break; + } + case "v1_14_R1" : { + getEDB_base = "q"; + break; + } + case "v1_15_R1" : { + getEDB_base = "o"; + break; + } + default : getEDB_base = null; + } + } +// public Object getMetaCPD(ItemMeta meta){ +// try{ +// Object craft_meta = CraftMetaItemClass.cast(meta); +// Object internalTag = this.internalTag.get(craft_meta); +// return internalTag; +// }catch (ReflectiveOperationException e){ +// e.printStackTrace(); +// return null; +// } +// } + + /** + * 只保留物品type和amount + * nbt深合并需要遍历每一层 + */ + @Deprecated + public ItemStack mergeItemCPD(ItemStack item,Object cpd){ + Map self = cpdToMap(getCPD(item)); + Map rhs = cpdToMap(cpd); + self.putAll(rhs); + Object new_cpd = getNBTTagCompound(self); + return EnderDragon.getInstance().getNMSItemManager().cpdToItem(new_cpd); + } + public Map cpdToMap(Object cpd){ + try{ + return (Map) NBTTagCompound_map.get(cpd); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + public Object getNBTTagCompound(Map mp){ + try{ + Object cpd = NBTTagCompoundClass.newInstance(); + mp.forEach((key,value)->{ + Object res; + if(value instanceof Map){ + res = getNBTTagCompound((Map) value); + } + else res = value; + try{ + NBTTagCompound_set.invoke(cpd,key,res); + }catch (ReflectiveOperationException e){ + throw new RuntimeException("Reflective error!"); + } + }); + return cpd; + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + public Object StringParseLiteral(String str){ + try{ + return stringToNBTBase.invoke(MOJANGSON_PARSER.get(null),str); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + public void setPersistentDataContainer(PersistentDataContainer dataContainer,Object cpd){ + try{ + Object PDC = CraftPersistentDataContainerClass.cast(dataContainer); + PersistentDataContainer_putAll.invoke(PDC,cpd); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + } + public String PDCtoString(PersistentDataContainer dataContainer){ + try{ + Object PDC = CraftPersistentDataContainerClass.cast(dataContainer); + return PDCtoCPD.invoke(PDC).toString(); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + + public Object deserializeObject(Object object){ + try{ + return deserializeObject.invoke(null,object); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + public Object serializeNBTBase(Object nbt_base){ + try{ + return serializeNBTBase.invoke(null, nbt_base); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + public void setUnhandledTags(ItemMeta meta, Map unhandledTags){ + try{ + Object craft_meta = CraftMetaItemClass.cast(meta); + this.unhandledTags.set(craft_meta, unhandledTags); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + } + public Map getUnhandledTags(ItemMeta meta){ + try{ + Object craft_meta = CraftMetaItemClass.cast(meta); + Object unhandledTags = this.unhandledTags.get(craft_meta); + return (Map) unhandledTags; + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + public ItemStack applyItemTag(ItemStack item,Object cpd){ + try{ + Object ei = asNMSCopy.invoke(null,item); + NMSItemStack_setTag.invoke(ei,cpd); + return (ItemStack) asBukkitCopy.invoke(null,ei); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return new ItemStack(Material.AIR); + } + } + public String getNBT(ItemStack item){ + try{ + Object ci = CraftItemStackClass.isInstance(item)?CraftItemStackClass.cast(item):asCraftCopy.invoke(null,item); + Object ei = asNMSCopy.invoke(null, ci); + Object cpd = NMSItemStack_save.invoke(ei, NBTTagCompoundClass.newInstance()); + return cpd.toString(); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return "{id:\"minecraft:air\"}"; + } + } + public Object getCPD(ItemStack item){ + try{ + Object ci = CraftItemStackClass.isInstance(item)?CraftItemStackClass.cast(item):asCraftCopy.invoke(null,item); + Object ei = asNMSCopy.invoke(null, ci); + return NMSItemStack_save.invoke(ei, NBTTagCompoundClass.newInstance()); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + public Object getCPD(String nbt){ + try{ + return stringToCPD.invoke(null,nbt); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + /** + * 仅1.13+可用 + */ + public ItemStack getItemStack(Object cpd){ + try{ + Object ei = cpdToEi.invoke(null,cpd); + Object ci = asBukkitCopy.invoke(null,ei); + return (ItemStack) ci; + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + /** + * 仅1.13+可用 + */ + public ItemStack getItemStack(String nbt){ + try{ + Object cpd = stringToCPD.invoke(null,nbt); + Object ei = cpdToEi.invoke(null,cpd); + Object ci = asBukkitCopy.invoke(null,ei); + return (ItemStack) ci; + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + return null; + } + } + public void setEnvironment(World world,World.Environment env){ + Object world_c = getCraftWorld(world); + try{ + //Object old_env = world_c_environment.get(world_c); + world_c_environment.set(world_c,env); + }catch (ReflectiveOperationException e){ + e.printStackTrace(); + } + } + public Object getEnderDragonBattle(World world){ + String version = Version.getVersion(); + if (Version.mcMainVersion>=12 && Version.mcMainVersion<16) { + try { + Object worldServer = getInstance().getNMSManager().getWorldServer(world); + assert worldServer != null; + Field field = worldServer.getClass().getField("worldProvider"); + Object worldProvider = field.get(worldServer); + Object WorldProviderTheEnd = WorldProviderTheEndClass.cast(worldProvider); + String method_name = getInstance().getNMSManager().getEDB_base; + if(method_name == null) return null; + Method method = WorldProviderTheEnd.getClass().getDeclaredMethod(method_name); + return method.invoke(WorldProviderTheEnd); + } catch (ReflectiveOperationException e) { + Lang.warn("Your server version (" + version + ") is not supported!"); + e.printStackTrace(); + } + } + Lang.warn("Your server version (" + version + ") is not supported!"); + return null; + } + public Object getWorldServer(World ThisWorld) { + try { + Object castClass = getCraftWorld(ThisWorld); + return this.CraftWorldClass.getDeclaredMethod("getHandle").invoke(castClass); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + return null; + } + public Object getCraftWorld(World ThisWorld) { + if (this.CraftWorldClass.isInstance(ThisWorld)) return this.CraftWorldClass.cast(ThisWorld); + return null; + } + public Object getWorld_e(World world){ + try { + Object world_c = getCraftWorld(world); + if(this.getNMSWord == null){ + this.getNMSWord = this.CraftWorldClass.getDeclaredMethod("getHandle"); + } + return this.getNMSWord.invoke(world_c); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + return null; + } + public Class getNBTBaseClass(){ + return this.NBTBaseClass; + } + public Class getNBTTagCompoundClass(){ + return this.NBTTagCompoundClass; + } + public Class getWorldClass(){ + return this.WorldClass; + } + public Class getWorldProviderClass(){ + return this.WorldProviderClass; + } + private String getMethodName(ReflectiveMethod method){ + switch (method){ + case NMSItemStack_save: { + if(Version.mcMainVersion<=17) return "save"; + return "b"; + } + case NMSItemStack_setTag: { + if(Version.mcMainVersion<=17) return "setTag"; + return "c"; + } + case MojangsonParser_parse: { + if(Version.mcMainVersion<=17) return "parse"; + return "a"; + } + case MojangsonParser_parseLiteral: { + if(Version.mcMainVersion==12) return "c"; + else if("v1_13_R1".equals(Version.getVersion())) return "b"; + else if(Version.mcMainVersion<=17) return "parseLiteral"; + else return "b"; + } + case NBTTagCompound_set: { + if(Version.mcMainVersion<=17) return "set"; + return "a"; + } + default: return "unreachable"; + } + } + private void init_NBTTagCompoundClass(){ + try{ + Class CraftMetaBlockStateClass = Class.forName("org.bukkit.craftbukkit."+Version.getVersion()+".inventory.CraftMetaBlockState"); + Field field = CraftMetaBlockStateClass.getDeclaredField("blockEntityTag"); + this.NBTTagCompoundClass = field.getType(); + return; + }catch (ReflectiveOperationException ignored){} + + Method[] methods = CraftEntityClass.getDeclaredMethods(); + for (Method method : methods) { + if ("save".equals(method.getName())) this.NBTTagCompoundClass = method.getReturnType(); + } + } + private void init_NBTTagCompound_map(){ + Field[] fields = NBTTagCompoundClass.getDeclaredFields(); + for(Field field : fields){ + if(field.getType() == this.unhandledTags.getType()){ + this.NBTTagCompound_map = field; + break; + } + } + this.NBTTagCompound_map.setAccessible(true); + } + private void init_NBTBaseClass(){ + try{ + //在mohist端使用getPackage()喜提null + this.NBTBaseClass = Class.forName(this.NBTTagCompoundClass.getName().replace(".NBTTagCompound",".NBTBase")); + }catch (ClassNotFoundException e){ + e.printStackTrace(); + } + } + private static enum ReflectiveMethod { + NMSItemStack_save, + NMSItemStack_setTag, + MojangsonParser_parse, + MojangsonParser_parseLiteral, + NBTTagCompound_set + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/util/Pair.java b/src/main/java/pers/xanadu/enderdragon/util/Pair.java new file mode 100644 index 0000000..e3fea87 --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/util/Pair.java @@ -0,0 +1,11 @@ +package pers.xanadu.enderdragon.util; + +public class Pair { + public P1 first; + public P2 second; + public Pair(P1 first, P2 second) { + this.first = first; + this.second = second; + } + +} diff --git a/src/main/java/pers/xanadu/enderdragon/util/Version.java b/src/main/java/pers/xanadu/enderdragon/util/Version.java new file mode 100644 index 0000000..b01ee1d --- /dev/null +++ b/src/main/java/pers/xanadu/enderdragon/util/Version.java @@ -0,0 +1,83 @@ +package pers.xanadu.enderdragon.util; + +import pers.xanadu.enderdragon.config.Lang; +import pers.xanadu.enderdragon.nms.BossBar.I_BossBarManager; +import pers.xanadu.enderdragon.nms.NMSItem.I_NMSItemManager; +import pers.xanadu.enderdragon.nms.RespawnAnchor.I_RespawnAnchorManager; +import pers.xanadu.enderdragon.nms.WorldData.I_WorldDataManager; + +import static org.bukkit.Bukkit.getServer; + +public class Version { + public static int mcMainVersion; + public static int mcPatchVersion; + private static String version = "no version found"; + private static boolean isMohist = false; + public static void init(){ + try { + version = getServer().getClass().getPackage().getName().split("\\.")[3]; + String[] mc_version = getServer().getBukkitVersion().split("-")[0].split("\\."); + mcMainVersion = Integer.parseInt(mc_version[1]); + if(mc_version.length<=2) mcPatchVersion = 0; + else mcPatchVersion = Integer.parseInt(mc_version[2]); + } catch (Throwable throwable) { + throwable.printStackTrace(); + Lang.warn("Failed to get nms-version!"); + } + Lang.info("Found version: " + version); + try{ + Class.forName("net.minecraftforge.server.ServerMain"); + isMohist = true; + }catch(ReflectiveOperationException ignored){} + + } + public static I_NMSItemManager getNMSItemManager(){ + switch (version){ + case "v1_12_R1" : return new pers.xanadu.enderdragon.nms.NMSItem.v1_12_R1.NMSItemManager(); + case "v1_13_R1" : return new pers.xanadu.enderdragon.nms.NMSItem.v1_13_R1.NMSItemManager(); + default: return new pers.xanadu.enderdragon.nms.NMSItem.v1_13_R2_above.NMSItemManager(); + } + } + public static I_BossBarManager getBossBarManager(){ + switch(version){ + case "v1_12_R1" : return new pers.xanadu.enderdragon.nms.BossBar.v1_12_R1.BossBarManager(); + case "v1_13_R1" : return new pers.xanadu.enderdragon.nms.BossBar.v1_13_R1.BossBarManager(); + case "v1_13_R2" : return new pers.xanadu.enderdragon.nms.BossBar.v1_13_R2.BossBarManager(); + default: return null; + } + } + public static I_WorldDataManager getWorldDataManager(){ + switch (version){ + case "v1_12_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_12_R1.WorldDataManager(); + case "v1_13_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_13_R1.WorldDataManager(); + case "v1_13_R2" : return new pers.xanadu.enderdragon.nms.WorldData.v1_13_R2.WorldDataManager(); + case "v1_14_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_14_R1.WorldDataManager(); + case "v1_15_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_15_R1.WorldDataManager(); + case "v1_16_R1" : return new pers.xanadu.enderdragon.nms.WorldData.v1_16_R1.WorldDataManager(); + case "v1_16_R2" : return new pers.xanadu.enderdragon.nms.WorldData.v1_16_R2.WorldDataManager(); + case "v1_16_R3" : return new pers.xanadu.enderdragon.nms.WorldData.v1_16_R3.WorldDataManager(); + default : return new pers.xanadu.enderdragon.nms.WorldData.v1_17_above.WorldDataManager(); + } + } + public static I_RespawnAnchorManager getRespawnAnchorManager(){ + switch (version){ + case "v1_12_R1" : + case "v1_13_R1" : + case "v1_14_R1" : + case "v1_13_R2" : + case "v1_15_R1" : return null; + case "v1_16_R1" : return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_16_R1.RespawnAnchorManager(); + case "v1_16_R2" : return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_16_R2.RespawnAnchorManager(); + case "v1_16_R3" : return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_16_R3.RespawnAnchorManager(); + case "v1_17_R1" : return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_17_R1.RespawnAnchorManager(); + default: return new pers.xanadu.enderdragon.nms.RespawnAnchor.v1_18_above.RespawnAnchorManager(); + } + } + public static String getVersion() { + return version; + } + public static boolean isMohist(){ + return isMohist; + } + +}