From ce698e209b61890d180114d2ff7142ada3976ccd Mon Sep 17 00:00:00 2001 From: AMinecraftDev Date: Wed, 31 May 2017 03:36:39 +0800 Subject: [PATCH] 3.0.0.0 - master branch + Initial Commit + Added Core module + Added FactionsM module + Added FactionsUUID module + Added FactionsOne module + Added PluginAPI module + Added resources to Core module --- .idea/.name | 1 + .idea/compiler.xml | 45 + ..._com_google_code_findbugs_jsr305_1_3_9.xml | 13 + ...Maven__com_google_code_gson_gson_2_2_4.xml | 13 + .../Maven__com_google_guava_guava_10_0_1.xml | 13 + ...oglecode_json_simple_json_simple_1_1_1.xml | 13 + ...en__com_massivecraft_FactionsOne_1_2_1.xml | 13 + ...sivecraft_FactionsUUID_1_6_9_5_U0_1_20.xml | 13 + ...craft_factions_Factions_2_9_1_SNAPSHOT.xml | 13 + ...massivecore_MassiveCore_2_9_1_SNAPSHOT.xml | 13 + .../Maven__com_sk89q_commandbook_2_3.xml | 13 + ...it_classloader_check_1_8_R0_1_SNAPSHOT.xml | 13 + ...en__com_sk89q_worldedit_6_0_0_SNAPSHOT.xml | 13 + ...n__com_sk89q_worldguard_6_0_0_SNAPSHOT.xml | 13 + .../Maven__com_spigotmc_spigot_1_11_2.xml | 13 + .../Maven__commons_lang_commons_lang_2_6.xml | 13 + .../Maven__de_schlichtherle_truezip_6_8_3.xml | 13 + ..._javax_persistence_persistence_api_1_0.xml | 13 + .idea/libraries/Maven__junit_junit_4_10.xml | 13 + ...Maven__net_milkbowl_vault_VaultAPI_1_6.xml | 13 + .../Maven__net_sf_opencsv_opencsv_2_0.xml | 13 + .../Maven__org_avaje_ebean_2_8_1.xml | 13 + ..._org_bukkit_bukkit_1_8_6_R0_1_SNAPSHOT.xml | 13 + .../Maven__org_hamcrest_hamcrest_core_1_1.xml | 13 + .../Maven__org_yaml_snakeyaml_1_14.xml | 13 + .idea/libraries/Maven__rhino_js_1_7R2.xml | 13 + .idea/misc.xml | 13 + .idea/modules.xml | 13 + .idea/uiDesigner.xml | 124 ++ .idea/vcs.xml | 6 + api-modules/FactionsM/FactionsM.iml | 36 + api-modules/FactionsM/pom.xml | 70 + .../innerapi/factions/FactionsM.java | 76 + api-modules/FactionsOne/FactionsOne.iml | 35 + api-modules/FactionsOne/pom.xml | 64 + .../innerapi/factions/FactionsOne.java | 78 + api-modules/FactionsUUID/FactionsUUID.iml | 35 + api-modules/FactionsUUID/pom.xml | 64 + .../FactionsUUID.java | 72 + api-modules/PluginAPI/PluginAPI.iml | 33 + api-modules/PluginAPI/pom.xml | 49 + .../custombosses/innerapi/FileUtils.java | 27 + .../custombosses/innerapi/FireworkUtils.java | 66 + .../custombosses/innerapi/NumberUtils.java | 53 + .../custombosses/innerapi/PotionUtils.java | 38 + .../custombosses/innerapi/RandomUtils.java | 24 + .../custombosses/innerapi/SoundUtils.java | 35 + .../innerapi/command/CommandUtils.java | 44 + .../innerapi/command/SubCommand.java | 24 + .../innerapi/command/SubCommandBuilder.java | 14 + .../command/builder/CommandRemover.java | 49 + .../command/builder/CommandService.java | 135 ++ .../command/builder/attributes/Alias.java | 15 + .../builder/attributes/Description.java | 15 + .../command/builder/attributes/Name.java | 15 + .../builder/attributes/NoPermission.java | 17 + .../builder/attributes/Permission.java | 15 + .../command/builder/attributes/Usage.java | 17 + .../innerapi/dependencies/FactionBuilder.java | 59 + .../innerapi/dependencies/VaultHelper.java | 76 + .../dependencies/WorldGuardHelper.java | 97 ++ .../innerapi/factory/CloneableFactory.java | 10 + .../innerapi/factory/Factory.java | 11 + .../innerapi/factory/FactoryBuilder.java | 11 + .../innerapi/factory/NbtFactory.java | 997 +++++++++++ .../innerapi/inventory/IInventoryBuilder.java | 26 + .../innerapi/inventory/InventoryBuilder.java | 106 ++ .../innerapi/inventory/InventoryFactory.java | 84 + .../innerapi/inventory/Panel.java | 333 ++++ .../innerapi/inventory/base/ClickAction.java | 21 + .../innerapi/inventory/base/PageAction.java | 15 + .../inventory/base/PanelCloseAction.java | 21 + .../innerapi/itemstack/ItemFactory.java | 94 ++ .../innerapi/itemstack/ItemStackUtils.java | 193 +++ .../itemstack/enchants/GlowEnchant.java | 22 + .../innerapi/message/DefaultFontInfo.java | 133 ++ .../innerapi/message/MessageUtils.java | 153 ++ .../innerapi/message/RomanNumber.java | 38 + .../innerapi/particles/ColoredParticle.java | 20 + .../innerapi/particles/ParticleEffect.java | 1499 +++++++++++++++++ .../innerapi/particles/ReflectionUtils.java | 607 +++++++ .../reflection/ActionBarReflection.java | 131 ++ .../innerapi/reflection/ChunkReflection.java | 86 + .../innerapi/reflection/ReflectionUtils.java | 40 + .../innerapi/serialization/BoostedGson.java | 35 + .../innerapi/serialization/Serialize.java | 40 + .../helpers/LocationAdapter.java | 28 + custombosses.iml | 32 + plugin-modules/Core/Core.iml | 37 + plugin-modules/Core/pom.xml | 95 ++ plugin-modules/Core/resources/autospawns.yml | 55 + plugin-modules/Core/resources/bosses.yml | 135 ++ plugin-modules/Core/resources/config.yml | 102 ++ plugin-modules/Core/resources/droptable.yml | 144 ++ plugin-modules/Core/resources/items.yml | 18 + plugin-modules/Core/resources/lang.yml | 1 + plugin-modules/Core/resources/plugin.yml | 4 + plugin-modules/Core/resources/skills.yml | 193 +++ .../custombosses/CustomBosses.java | 9 + .../custombosses/commands/BossHelpCmd.java | 23 + .../custombosses/commands/BossKillAllCmd.java | 9 + .../custombosses/commands/BossListCmd.java | 9 + .../custombosses/commands/BossReloadCmd.java | 9 + .../custombosses/commands/BossSpawnCmd.java | 9 + .../custombosses/commands/BossTimeCmd.java | 9 + .../custombosses/commands/base/BossCmd.java | 54 + .../custombosses/events/BossDamageEvent.java | 9 + .../custombosses/events/BossDeathEvent.java | 9 + .../custombosses/events/BossSkillEvent.java | 9 + .../custombosses/events/BossSpawnEvent.java | 9 + .../handlers/AutoSpawnHandler.java | 9 + .../custombosses/handlers/EntityHandler.java | 9 + .../custombosses/handlers/MinionHandler.java | 9 + .../custombosses/handlers/TauntHandler.java | 9 + .../managers/AutoSpawnManager.java | 9 + .../custombosses/managers/BossManager.java | 9 + .../custombosses/managers/ItemManager.java | 9 + .../custombosses/managers/MinionManager.java | 9 + .../custombosses/managers/SkillManager.java | 9 + .../custombosses/utils/Message.java | 201 +++ pom.xml | 46 + 121 files changed, 8026 insertions(+) create mode 100644 .idea/.name create mode 100644 .idea/compiler.xml create mode 100644 .idea/libraries/Maven__com_google_code_findbugs_jsr305_1_3_9.xml create mode 100644 .idea/libraries/Maven__com_google_code_gson_gson_2_2_4.xml create mode 100644 .idea/libraries/Maven__com_google_guava_guava_10_0_1.xml create mode 100644 .idea/libraries/Maven__com_googlecode_json_simple_json_simple_1_1_1.xml create mode 100644 .idea/libraries/Maven__com_massivecraft_FactionsOne_1_2_1.xml create mode 100644 .idea/libraries/Maven__com_massivecraft_FactionsUUID_1_6_9_5_U0_1_20.xml create mode 100644 .idea/libraries/Maven__com_massivecraft_factions_Factions_2_9_1_SNAPSHOT.xml create mode 100644 .idea/libraries/Maven__com_massivecraft_massivecore_MassiveCore_2_9_1_SNAPSHOT.xml create mode 100644 .idea/libraries/Maven__com_sk89q_commandbook_2_3.xml create mode 100644 .idea/libraries/Maven__com_sk89q_spigot_bukkit_classloader_check_1_8_R0_1_SNAPSHOT.xml create mode 100644 .idea/libraries/Maven__com_sk89q_worldedit_6_0_0_SNAPSHOT.xml create mode 100644 .idea/libraries/Maven__com_sk89q_worldguard_6_0_0_SNAPSHOT.xml create mode 100644 .idea/libraries/Maven__com_spigotmc_spigot_1_11_2.xml create mode 100644 .idea/libraries/Maven__commons_lang_commons_lang_2_6.xml create mode 100644 .idea/libraries/Maven__de_schlichtherle_truezip_6_8_3.xml create mode 100644 .idea/libraries/Maven__javax_persistence_persistence_api_1_0.xml create mode 100644 .idea/libraries/Maven__junit_junit_4_10.xml create mode 100644 .idea/libraries/Maven__net_milkbowl_vault_VaultAPI_1_6.xml create mode 100644 .idea/libraries/Maven__net_sf_opencsv_opencsv_2_0.xml create mode 100644 .idea/libraries/Maven__org_avaje_ebean_2_8_1.xml create mode 100644 .idea/libraries/Maven__org_bukkit_bukkit_1_8_6_R0_1_SNAPSHOT.xml create mode 100644 .idea/libraries/Maven__org_hamcrest_hamcrest_core_1_1.xml create mode 100644 .idea/libraries/Maven__org_yaml_snakeyaml_1_14.xml create mode 100644 .idea/libraries/Maven__rhino_js_1_7R2.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/uiDesigner.xml create mode 100644 .idea/vcs.xml create mode 100644 api-modules/FactionsM/FactionsM.iml create mode 100644 api-modules/FactionsM/pom.xml create mode 100644 api-modules/FactionsM/src/net/aminecraftdev/custombosses/innerapi/factions/FactionsM.java create mode 100644 api-modules/FactionsOne/FactionsOne.iml create mode 100644 api-modules/FactionsOne/pom.xml create mode 100644 api-modules/FactionsOne/src/net/aminecraftdev/custombosses/innerapi/factions/FactionsOne.java create mode 100644 api-modules/FactionsUUID/FactionsUUID.iml create mode 100644 api-modules/FactionsUUID/pom.xml create mode 100644 api-modules/FactionsUUID/src/net.aminecraftdev.custombosses.innerapi.factions/FactionsUUID.java create mode 100644 api-modules/PluginAPI/PluginAPI.iml create mode 100644 api-modules/PluginAPI/pom.xml create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/FileUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/FireworkUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/NumberUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/PotionUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/RandomUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/SoundUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/CommandUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/SubCommand.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/SubCommandBuilder.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/CommandRemover.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/CommandService.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Alias.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Description.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Name.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/NoPermission.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Permission.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Usage.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/FactionBuilder.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/VaultHelper.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/WorldGuardHelper.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/CloneableFactory.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/Factory.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/FactoryBuilder.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/NbtFactory.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/IInventoryBuilder.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/InventoryBuilder.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/InventoryFactory.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/Panel.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/ClickAction.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/PageAction.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/PanelCloseAction.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/ItemFactory.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/ItemStackUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/enchants/GlowEnchant.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/DefaultFontInfo.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/MessageUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/RomanNumber.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ColoredParticle.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ParticleEffect.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ReflectionUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ActionBarReflection.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ChunkReflection.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ReflectionUtils.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/BoostedGson.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/Serialize.java create mode 100644 api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/helpers/LocationAdapter.java create mode 100644 custombosses.iml create mode 100644 plugin-modules/Core/Core.iml create mode 100644 plugin-modules/Core/pom.xml create mode 100644 plugin-modules/Core/resources/autospawns.yml create mode 100644 plugin-modules/Core/resources/bosses.yml create mode 100644 plugin-modules/Core/resources/config.yml create mode 100644 plugin-modules/Core/resources/droptable.yml create mode 100644 plugin-modules/Core/resources/items.yml create mode 100644 plugin-modules/Core/resources/lang.yml create mode 100644 plugin-modules/Core/resources/plugin.yml create mode 100644 plugin-modules/Core/resources/skills.yml create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/CustomBosses.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossHelpCmd.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossKillAllCmd.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossListCmd.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossReloadCmd.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossSpawnCmd.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossTimeCmd.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/base/BossCmd.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossDamageEvent.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossDeathEvent.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossSkillEvent.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossSpawnEvent.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/AutoSpawnHandler.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/EntityHandler.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/MinionHandler.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/TauntHandler.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/AutoSpawnManager.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/BossManager.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/ItemManager.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/MinionManager.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/SkillManager.java create mode 100644 plugin-modules/Core/src/net/aminecraftdev/custombosses/utils/Message.java create mode 100644 pom.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..ffe4194 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +CustomBosses \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..2a9b34a --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_google_code_findbugs_jsr305_1_3_9.xml b/.idea/libraries/Maven__com_google_code_findbugs_jsr305_1_3_9.xml new file mode 100644 index 0000000..0e66824 --- /dev/null +++ b/.idea/libraries/Maven__com_google_code_findbugs_jsr305_1_3_9.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_google_code_gson_gson_2_2_4.xml b/.idea/libraries/Maven__com_google_code_gson_gson_2_2_4.xml new file mode 100644 index 0000000..4533c1b --- /dev/null +++ b/.idea/libraries/Maven__com_google_code_gson_gson_2_2_4.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_google_guava_guava_10_0_1.xml b/.idea/libraries/Maven__com_google_guava_guava_10_0_1.xml new file mode 100644 index 0000000..261ff44 --- /dev/null +++ b/.idea/libraries/Maven__com_google_guava_guava_10_0_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_googlecode_json_simple_json_simple_1_1_1.xml b/.idea/libraries/Maven__com_googlecode_json_simple_json_simple_1_1_1.xml new file mode 100644 index 0000000..f3f3738 --- /dev/null +++ b/.idea/libraries/Maven__com_googlecode_json_simple_json_simple_1_1_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_massivecraft_FactionsOne_1_2_1.xml b/.idea/libraries/Maven__com_massivecraft_FactionsOne_1_2_1.xml new file mode 100644 index 0000000..9f0eee9 --- /dev/null +++ b/.idea/libraries/Maven__com_massivecraft_FactionsOne_1_2_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_massivecraft_FactionsUUID_1_6_9_5_U0_1_20.xml b/.idea/libraries/Maven__com_massivecraft_FactionsUUID_1_6_9_5_U0_1_20.xml new file mode 100644 index 0000000..6cf04dc --- /dev/null +++ b/.idea/libraries/Maven__com_massivecraft_FactionsUUID_1_6_9_5_U0_1_20.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_massivecraft_factions_Factions_2_9_1_SNAPSHOT.xml b/.idea/libraries/Maven__com_massivecraft_factions_Factions_2_9_1_SNAPSHOT.xml new file mode 100644 index 0000000..c2dae64 --- /dev/null +++ b/.idea/libraries/Maven__com_massivecraft_factions_Factions_2_9_1_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_massivecraft_massivecore_MassiveCore_2_9_1_SNAPSHOT.xml b/.idea/libraries/Maven__com_massivecraft_massivecore_MassiveCore_2_9_1_SNAPSHOT.xml new file mode 100644 index 0000000..78218b6 --- /dev/null +++ b/.idea/libraries/Maven__com_massivecraft_massivecore_MassiveCore_2_9_1_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_sk89q_commandbook_2_3.xml b/.idea/libraries/Maven__com_sk89q_commandbook_2_3.xml new file mode 100644 index 0000000..589fb53 --- /dev/null +++ b/.idea/libraries/Maven__com_sk89q_commandbook_2_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_sk89q_spigot_bukkit_classloader_check_1_8_R0_1_SNAPSHOT.xml b/.idea/libraries/Maven__com_sk89q_spigot_bukkit_classloader_check_1_8_R0_1_SNAPSHOT.xml new file mode 100644 index 0000000..0f77d57 --- /dev/null +++ b/.idea/libraries/Maven__com_sk89q_spigot_bukkit_classloader_check_1_8_R0_1_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_sk89q_worldedit_6_0_0_SNAPSHOT.xml b/.idea/libraries/Maven__com_sk89q_worldedit_6_0_0_SNAPSHOT.xml new file mode 100644 index 0000000..67d8f8d --- /dev/null +++ b/.idea/libraries/Maven__com_sk89q_worldedit_6_0_0_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_sk89q_worldguard_6_0_0_SNAPSHOT.xml b/.idea/libraries/Maven__com_sk89q_worldguard_6_0_0_SNAPSHOT.xml new file mode 100644 index 0000000..af5ce36 --- /dev/null +++ b/.idea/libraries/Maven__com_sk89q_worldguard_6_0_0_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__com_spigotmc_spigot_1_11_2.xml b/.idea/libraries/Maven__com_spigotmc_spigot_1_11_2.xml new file mode 100644 index 0000000..e0117fe --- /dev/null +++ b/.idea/libraries/Maven__com_spigotmc_spigot_1_11_2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__commons_lang_commons_lang_2_6.xml b/.idea/libraries/Maven__commons_lang_commons_lang_2_6.xml new file mode 100644 index 0000000..2ec8376 --- /dev/null +++ b/.idea/libraries/Maven__commons_lang_commons_lang_2_6.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__de_schlichtherle_truezip_6_8_3.xml b/.idea/libraries/Maven__de_schlichtherle_truezip_6_8_3.xml new file mode 100644 index 0000000..31ae2cd --- /dev/null +++ b/.idea/libraries/Maven__de_schlichtherle_truezip_6_8_3.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__javax_persistence_persistence_api_1_0.xml b/.idea/libraries/Maven__javax_persistence_persistence_api_1_0.xml new file mode 100644 index 0000000..e60370e --- /dev/null +++ b/.idea/libraries/Maven__javax_persistence_persistence_api_1_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__junit_junit_4_10.xml b/.idea/libraries/Maven__junit_junit_4_10.xml new file mode 100644 index 0000000..ed8bf5f --- /dev/null +++ b/.idea/libraries/Maven__junit_junit_4_10.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__net_milkbowl_vault_VaultAPI_1_6.xml b/.idea/libraries/Maven__net_milkbowl_vault_VaultAPI_1_6.xml new file mode 100644 index 0000000..fa96a55 --- /dev/null +++ b/.idea/libraries/Maven__net_milkbowl_vault_VaultAPI_1_6.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__net_sf_opencsv_opencsv_2_0.xml b/.idea/libraries/Maven__net_sf_opencsv_opencsv_2_0.xml new file mode 100644 index 0000000..76b343e --- /dev/null +++ b/.idea/libraries/Maven__net_sf_opencsv_opencsv_2_0.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_avaje_ebean_2_8_1.xml b/.idea/libraries/Maven__org_avaje_ebean_2_8_1.xml new file mode 100644 index 0000000..91f161a --- /dev/null +++ b/.idea/libraries/Maven__org_avaje_ebean_2_8_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_bukkit_bukkit_1_8_6_R0_1_SNAPSHOT.xml b/.idea/libraries/Maven__org_bukkit_bukkit_1_8_6_R0_1_SNAPSHOT.xml new file mode 100644 index 0000000..af8dae5 --- /dev/null +++ b/.idea/libraries/Maven__org_bukkit_bukkit_1_8_6_R0_1_SNAPSHOT.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_1.xml b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_1.xml new file mode 100644 index 0000000..acdf443 --- /dev/null +++ b/.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__org_yaml_snakeyaml_1_14.xml b/.idea/libraries/Maven__org_yaml_snakeyaml_1_14.xml new file mode 100644 index 0000000..d9fbe59 --- /dev/null +++ b/.idea/libraries/Maven__org_yaml_snakeyaml_1_14.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/Maven__rhino_js_1_7R2.xml b/.idea/libraries/Maven__rhino_js_1_7R2.xml new file mode 100644 index 0000000..73d4473 --- /dev/null +++ b/.idea/libraries/Maven__rhino_js_1_7R2.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..e8942bd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..f7f3aa9 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/api-modules/FactionsM/FactionsM.iml b/api-modules/FactionsM/FactionsM.iml new file mode 100644 index 0000000..3488d97 --- /dev/null +++ b/api-modules/FactionsM/FactionsM.iml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-modules/FactionsM/pom.xml b/api-modules/FactionsM/pom.xml new file mode 100644 index 0000000..1d565d5 --- /dev/null +++ b/api-modules/FactionsM/pom.xml @@ -0,0 +1,70 @@ + + + + CustomBosses + net.aminecraftdev.custombosses + 3.0.0.0 + ../../pom.xml + + 4.0.0 + + FactionsM + jar + + + + net.aminecraftdev.custombosses + PluginAPI + 3.0.0.0 + provided + + + com.massivecraft.factions + Factions + 2.9.1-SNAPSHOT + provided + + + com.massivecraft.massivecore + MassiveCore + 2.9.1-SNAPSHOT + provided + + + + + clean package install + /target + ${project.artifactId}-${project.version} + ${basedir}/src/ + + + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 1.4 + + false + + + + package + + shade + + + + + + + + \ No newline at end of file diff --git a/api-modules/FactionsM/src/net/aminecraftdev/custombosses/innerapi/factions/FactionsM.java b/api-modules/FactionsM/src/net/aminecraftdev/custombosses/innerapi/factions/FactionsM.java new file mode 100644 index 0000000..0d1f516 --- /dev/null +++ b/api-modules/FactionsM/src/net/aminecraftdev/custombosses/innerapi/factions/FactionsM.java @@ -0,0 +1,76 @@ +package net.aminecraftdev.custombosses.innerapi.factions; + +import com.massivecraft.factions.Rel; +import com.massivecraft.factions.entity.BoardColl; +import com.massivecraft.factions.entity.Faction; +import com.massivecraft.factions.entity.MPlayer; +import com.massivecraft.massivecore.ps.PS; +import net.aminecraftdev.custombosses.innerapi.dependencies.FactionBuilder; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class FactionsM implements FactionBuilder { + + @Override + public boolean isFriendly(Player a, Player b) { + MPlayer mp1 = MPlayer.get(a); + MPlayer mp2 = MPlayer.get(b); + Faction mp2Fac = mp2.getFaction(); + Rel relation = mp1.getRelationTo(mp2); + + if(ChatColor.stripColor(mp2Fac.getName()).equalsIgnoreCase("Wilderness")) return false; + if(relation == Rel.ENEMY) return false; + if(relation == Rel.NEUTRAL) return false; + if(relation == Rel.ALLY) return true; + if(relation == Rel.TRUCE) return false; + if(relation == Rel.LEADER) return true; + if(relation == Rel.OFFICER) return true; + if(relation == Rel.MEMBER) return true; + if(relation == Rel.RECRUIT) return true; + return false; + } + + @Override + public boolean isFriendly(Player a, Location location) { + MPlayer mp1 = MPlayer.get(a); + Faction mp1Fac = mp1.getFaction(); + Faction locFac = BoardColl.get().getFactionAt(PS.valueOf(location)); + Rel relation = mp1Fac.getRelationTo(locFac); + + if(ChatColor.stripColor(locFac.getName()).equalsIgnoreCase("Wilderness")) return true; + if(relation == Rel.ENEMY) return false; + if(relation == Rel.NEUTRAL) return false; + if(relation == Rel.ALLY) return true; + if(relation == Rel.TRUCE) return true; + if(relation == Rel.LEADER) return true; + if(relation == Rel.OFFICER) return true; + if(relation == Rel.MEMBER) return true; + if(relation == Rel.RECRUIT) return true; + return false; + } + + @Override + public boolean isInWarzone(Location location) { + Faction locFac = BoardColl.get().getFactionAt(PS.valueOf(location)); + + if(ChatColor.stripColor(locFac.getName()).equalsIgnoreCase("WarZone")) return true; + return false; + } + + @Override + public boolean isInClaimedLand(Location location) { + Faction locFac = BoardColl.get().getFactionAt(PS.valueOf(location)); + String string = ChatColor.stripColor(locFac.getName()); + + if(string.equalsIgnoreCase("WarZone")) return false; + if(string.equalsIgnoreCase("SafeZone")) return false; + if(string.equalsIgnoreCase("Wilderness")) return false; + return true; + } +} diff --git a/api-modules/FactionsOne/FactionsOne.iml b/api-modules/FactionsOne/FactionsOne.iml new file mode 100644 index 0000000..d91e86e --- /dev/null +++ b/api-modules/FactionsOne/FactionsOne.iml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-modules/FactionsOne/pom.xml b/api-modules/FactionsOne/pom.xml new file mode 100644 index 0000000..f89e0de --- /dev/null +++ b/api-modules/FactionsOne/pom.xml @@ -0,0 +1,64 @@ + + + + CustomBosses + net.aminecraftdev.custombosses + 3.0.0.0 + ../../pom.xml + + 4.0.0 + + FactionsOne + jar + + + + net.aminecraftdev.custombosses + PluginAPI + 3.0.0.0 + provided + + + com.massivecraft + FactionsOne + 1.2.1 + provided + + + + + clean package install + /target + ${project.artifactId}-${project.version} + ${basedir}/src/ + + + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 1.4 + + false + + + + package + + shade + + + + + + + + \ No newline at end of file diff --git a/api-modules/FactionsOne/src/net/aminecraftdev/custombosses/innerapi/factions/FactionsOne.java b/api-modules/FactionsOne/src/net/aminecraftdev/custombosses/innerapi/factions/FactionsOne.java new file mode 100644 index 0000000..0846e9b --- /dev/null +++ b/api-modules/FactionsOne/src/net/aminecraftdev/custombosses/innerapi/factions/FactionsOne.java @@ -0,0 +1,78 @@ +package net.aminecraftdev.custombosses.innerapi.factions; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.struct.Rel; +import net.aminecraftdev.custombosses.innerapi.dependencies.FactionBuilder; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class FactionsOne implements FactionBuilder { + + @Override + public boolean isFriendly(Player a, Player b) { + Faction pFac = FPlayers.i.get(a).getFaction(); + Faction zFac = FPlayers.i.get(b).getFaction(); + Rel r = pFac.getRelationTo(zFac); + + if(ChatColor.stripColor(zFac.getId()).equalsIgnoreCase("Wilderness")) return false; + if(a == b) return true; + if(r.equals(Rel.ALLY)) return true; + if(r.equals(Rel.TRUCE)) return true; + if(r.equals(Rel.LEADER)) return true; + if(r.equals(Rel.MEMBER)) return true; + if(r.equals(Rel.OFFICER)) return true; + if(r.equals(Rel.RECRUIT)) return true; + if(r.equals(Rel.ENEMY)) return false; + if(r.equals(Rel.NEUTRAL)) return false; + return false; + } + + @Override + public boolean isFriendly(Player a, Location location) { + Faction pFac = FPlayers.i.get(a).getFaction(); + FLocation fLoc = new FLocation(location); + Faction locFac = Board.getFactionAt(fLoc); + Rel r = pFac.getRelationTo(locFac); + + if(ChatColor.stripColor(locFac.getComparisonTag()).equalsIgnoreCase("Wilderness")) return false; + if(r.equals(Rel.ALLY)) return true; + if(r.equals(Rel.TRUCE)) return true; + if(r.equals(Rel.LEADER)) return true; + if(r.equals(Rel.MEMBER)) return true; + if(r.equals(Rel.OFFICER)) return true; + if(r.equals(Rel.RECRUIT)) return true; + if(r.equals(Rel.ENEMY)) return false; + if(r.equals(Rel.NEUTRAL)) return false; + return false; + } + + @Override + public boolean isInWarzone(Location location) { + FLocation fLoc = new FLocation(location); + Faction locFac = Board.getFactionAt(fLoc); + + if(ChatColor.stripColor(locFac.getComparisonTag()).equalsIgnoreCase("WarZone")) return true; + return false; + } + + @Override + public boolean isInClaimedLand(Location location) { + FLocation fLoc = new FLocation(location); + Faction locFac = Board.getFactionAt(fLoc); + String string = ChatColor.stripColor(locFac.getComparisonTag()); + + if(string.equalsIgnoreCase("WarZone")) return false; + if(string.equalsIgnoreCase("SafeZone")) return false; + if(string.equalsIgnoreCase("Wilderness")) return false; + return true; + } +} diff --git a/api-modules/FactionsUUID/FactionsUUID.iml b/api-modules/FactionsUUID/FactionsUUID.iml new file mode 100644 index 0000000..3a4c164 --- /dev/null +++ b/api-modules/FactionsUUID/FactionsUUID.iml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-modules/FactionsUUID/pom.xml b/api-modules/FactionsUUID/pom.xml new file mode 100644 index 0000000..c73b6a4 --- /dev/null +++ b/api-modules/FactionsUUID/pom.xml @@ -0,0 +1,64 @@ + + + + CustomBosses + net.aminecraftdev.custombosses + 3.0.0.0 + ../../pom.xml + + 4.0.0 + + FactionsUUID + jar + + + + net.aminecraftdev.custombosses + PluginAPI + 3.0.0.0 + provided + + + com.massivecraft + FactionsUUID + 1.6.9.5-U0.1.20 + provided + + + + + clean package install + /target + ${project.artifactId}-${project.version} + ${basedir}/src/ + + + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 1.4 + + false + + + + package + + shade + + + + + + + + \ No newline at end of file diff --git a/api-modules/FactionsUUID/src/net.aminecraftdev.custombosses.innerapi.factions/FactionsUUID.java b/api-modules/FactionsUUID/src/net.aminecraftdev.custombosses.innerapi.factions/FactionsUUID.java new file mode 100644 index 0000000..43c3f3b --- /dev/null +++ b/api-modules/FactionsUUID/src/net.aminecraftdev.custombosses.innerapi.factions/FactionsUUID.java @@ -0,0 +1,72 @@ +package net.aminecraftdev.custombosses.innerapi.factions; + +import com.massivecraft.factions.Board; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.FPlayers; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.struct.Relation; +import net.aminecraftdev.custombosses.innerapi.dependencies.FactionBuilder; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class FactionsUUID implements FactionBuilder { + + @Override + public boolean isFriendly(Player a, Player b) { + Faction pFac = FPlayers.getInstance().getByPlayer(a).getFaction(); + Faction zFac = FPlayers.getInstance().getByPlayer(b).getFaction(); + Relation r = pFac.getRelationTo(zFac); + + if(ChatColor.stripColor(zFac.getId()).equalsIgnoreCase("Wilderness")) return false; + if(a == b) return true; + if(r.isEnemy()) return false; + if(r.isNeutral()) return false; + if(r.isTruce()) return true; + if(r.isAlly()) return true; + if(r.isMember()) return true; + return false; + } + + @Override + public boolean isFriendly(Player a, Location location) { + Faction pFac = FPlayers.getInstance().getByPlayer(a).getFaction(); + FLocation fLoc = new FLocation(location); + Faction locFac = Board.getInstance().getFactionAt(fLoc); + Relation r = pFac.getRelationTo(locFac); + + if(ChatColor.stripColor(locFac.getComparisonTag()).equalsIgnoreCase("Wilderness")) return false; + if(r.isEnemy()) return false; + if(r.isNeutral()) return false; + if(r.isTruce()) return true; + if(r.isAlly()) return true; + if(r.isMember()) return true; + return false; + } + + @Override + public boolean isInWarzone(Location location) { + FLocation fLoc = new FLocation(location); + Faction locFac = Board.getInstance().getFactionAt(fLoc); + + if(ChatColor.stripColor(locFac.getComparisonTag()).equalsIgnoreCase("WarZone")) return true; + return false; + } + + @Override + public boolean isInClaimedLand(Location location) { + FLocation fLoc = new FLocation(location); + Faction locFac = Board.getInstance().getFactionAt(fLoc); + String string = ChatColor.stripColor(locFac.getComparisonTag()); + + if(string.equalsIgnoreCase("WarZone")) return false; + if(string.equalsIgnoreCase("SafeZone")) return false; + if(string.equalsIgnoreCase("Wilderness")) return false; + return true; + } +} diff --git a/api-modules/PluginAPI/PluginAPI.iml b/api-modules/PluginAPI/PluginAPI.iml new file mode 100644 index 0000000..d49074e --- /dev/null +++ b/api-modules/PluginAPI/PluginAPI.iml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/api-modules/PluginAPI/pom.xml b/api-modules/PluginAPI/pom.xml new file mode 100644 index 0000000..e36ea33 --- /dev/null +++ b/api-modules/PluginAPI/pom.xml @@ -0,0 +1,49 @@ + + + + CustomBosses + net.aminecraftdev.custombosses + 3.0.0.0 + ../../pom.xml + + 4.0.0 + + PluginAPI + jar + + + clean package install + /target + ${project.artifactId}-${project.version} + ${basedir}/src/ + + + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 1.4 + + false + + + + package + + shade + + + + + + + + \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/FileUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/FileUtils.java new file mode 100644 index 0000000..a8e28dd --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/FileUtils.java @@ -0,0 +1,27 @@ +package net.aminecraftdev.custombosses.innerapi; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class FileUtils { + + public static final void saveFile(File file, FileConfiguration configuration) { + try { + configuration.save(file); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static final FileConfiguration getConf(File file) { + return YamlConfiguration.loadConfiguration(file); + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/FireworkUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/FireworkUtils.java new file mode 100644 index 0000000..90b02a0 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/FireworkUtils.java @@ -0,0 +1,66 @@ +package net.aminecraftdev.custombosses.innerapi; + +import org.bukkit.Color; +import org.bukkit.FireworkEffect; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Firework; +import org.bukkit.entity.Player; +import org.bukkit.inventory.meta.FireworkMeta; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class FireworkUtils { + + public static final Color getColour(String s) { + if(s.equalsIgnoreCase("AQUA")) return Color.AQUA; + if(s.equalsIgnoreCase("BLACK")) return Color.BLACK; + if(s.equalsIgnoreCase("BLUE")) return Color.BLUE; + if(s.equalsIgnoreCase("FUCHSIA")) return Color.FUCHSIA; + if(s.equalsIgnoreCase("GRAY")) return Color.GRAY; + if(s.equalsIgnoreCase("GREEN")) return Color.GREEN; + if(s.equalsIgnoreCase("LIME")) return Color.LIME; + if(s.equalsIgnoreCase("MAROON")) return Color.MAROON; + if(s.equalsIgnoreCase("NAVY")) return Color.NAVY; + if(s.equalsIgnoreCase("OLIVE")) return Color.OLIVE; + if(s.equalsIgnoreCase("ORANGE")) return Color.ORANGE; + if(s.equalsIgnoreCase("PURPLE")) return Color.PURPLE; + if(s.equalsIgnoreCase("RED")) return Color.RED; + if(s.equalsIgnoreCase("SILVER")) return Color.SILVER; + if(s.equalsIgnoreCase("TEAL")) return Color.TEAL; + if(s.equalsIgnoreCase("WHITE")) return Color.WHITE; + if(s.equalsIgnoreCase("YELLOW")) return Color.YELLOW; + + return null; + } + + public static final void spawnFirework(Location location, ConfigurationSection configurationSection) { + Firework firework = (Firework) location.getWorld().spawn(location, Firework.class); + String colour = configurationSection.getString("color").toUpperCase(); + Color fireworkColor = getColour(colour); + int fireworkPower = configurationSection.getInt("power"); + boolean fireworkFlicker = configurationSection.getBoolean("flicker"); + boolean fireworkTrail = configurationSection.getBoolean("trail"); + FireworkEffect.Type fireworkType = FireworkEffect.Type.valueOf(configurationSection.getString("type").toUpperCase()); + + FireworkMeta fireworkMeta = firework.getFireworkMeta(); + + fireworkMeta.addEffect(FireworkEffect.builder() + .flicker(fireworkFlicker) + .trail(fireworkTrail) + .with(fireworkType) + .withColor(fireworkColor) + .build()); + + fireworkMeta.setPower(fireworkPower); + firework.setFireworkMeta(fireworkMeta); + } + + public static final void spawnFirework(Player player, ConfigurationSection configurationSection) { + spawnFirework(player.getLocation(), configurationSection); + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/NumberUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/NumberUtils.java new file mode 100644 index 0000000..4647142 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/NumberUtils.java @@ -0,0 +1,53 @@ +package net.aminecraftdev.custombosses.innerapi; + +import java.text.DecimalFormat; + +/** + * Created by charl on 28-Apr-17. + */ +public class NumberUtils { + + public static final String formatDouble(double d) { + DecimalFormat format = new DecimalFormat("###,###,###,###,###.##"); + + return format.format(d); + } + + public static final String formatTime(int time) { + int hours = time / 3600; + int remainder = time % 3600; + int minutes = remainder / 60; + int seconds = remainder % 60; + String disHour = (hours < 10 ? "0" : "") + hours; + String disMinu = (minutes < 10 ? "0" : "") + minutes; + String disSeco = (seconds < 10 ? "0" : "") + seconds; + String formatted = ""; + + if(hours != 0) formatted += disHour + " hours "; + if(minutes != 0) formatted += disMinu + " minutes "; + if(seconds != 0) formatted += disSeco + " seconds."; + + return formatted; + } + + public static final boolean isStringInteger(String s) { + try { + Integer.valueOf(s); + } catch (NumberFormatException e) { + return false; + } + + return true; + } + + public static final boolean isStringDouble(String s) { + try { + Double.valueOf(s); + } catch (NumberFormatException e) { + return false; + } + + return true; + } + +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/PotionUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/PotionUtils.java new file mode 100644 index 0000000..34d2fa5 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/PotionUtils.java @@ -0,0 +1,38 @@ +package net.aminecraftdev.custombosses.innerapi; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class PotionUtils { + + public static final PotionEffect getPotionEffect(ConfigurationSection configurationSection) { + if(configurationSection.contains("enabled") && !configurationSection.getBoolean("enabled")) return null; + + int level = configurationSection.getInt("level"); + int duration = configurationSection.getInt("duration"); + String type = configurationSection.getString("type"); + + if(PotionEffectType.getByName(type) == null) { + return null; + } + + PotionEffectType potionEffectType = PotionEffectType.getByName(type); + + if(duration == -1) { + duration = 100000; + } else { + duration *= 20; + } + + level -= 1; + + return new PotionEffect(potionEffectType, duration, level); + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/RandomUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/RandomUtils.java new file mode 100644 index 0000000..751b6bc --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/RandomUtils.java @@ -0,0 +1,24 @@ +package net.aminecraftdev.custombosses.innerapi; + +import java.util.Random; + +/** + * Created by charl on 28-Apr-17. + */ +public class RandomUtils { + + private static final Random RANDOM; + + static { + RANDOM = new Random(); + } + + public static Random getRandom() { + return RANDOM; + } + + public static int getRandomInt(int input) { + return RANDOM.nextInt(input); + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/SoundUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/SoundUtils.java new file mode 100644 index 0000000..44cc7e7 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/SoundUtils.java @@ -0,0 +1,35 @@ +package net.aminecraftdev.custombosses.innerapi; + +import org.bukkit.Sound; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class SoundUtils { + + public static final void playSound(ConfigurationSection configurationSection, Player player) { + boolean enabled = configurationSection.getBoolean("enabled", true); + String type = configurationSection.getString("type"); + int volume = configurationSection.getInt("volume"); + int pitch = configurationSection.getInt("pitch"); + + if(!enabled) return; + + player.playSound(player.getLocation(), Sound.valueOf(type.toUpperCase()), (float) volume, (float) pitch); + } + + public static final Sound getSound(ConfigurationSection configurationSection) { + boolean enabled = configurationSection.getBoolean("enabled", true); + String type = configurationSection.getString("type"); + + if(!enabled) return null; + + return Sound.valueOf(type.toUpperCase()); + } + + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/CommandUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/CommandUtils.java new file mode 100644 index 0000000..e11eb17 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/CommandUtils.java @@ -0,0 +1,44 @@ +package net.aminecraftdev.custombosses.innerapi.command; + +import org.boostednetwork.factionscore.utils.NumberUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +/** + * Created by charl on 28-Apr-17. + */ +public class CommandUtils { + + public static final Player strAsPlayer(String s) { + if(Bukkit.getPlayer(s) == null) return null; + + return Bukkit.getPlayer(s); + } + + public static final Integer strAsInteger(String s) { + if(NumberUtils.isStringInteger(s)) return Integer.valueOf(s); + + return null; + } + + public static final Double strAsDouble(String s) { + if(NumberUtils.isStringDouble(s)) return Double.valueOf(s); + + return null; + } + + public static final boolean isIntegerWithinItemStackSize(int i) { + if(i > 64) return false; + if(i < 1) return false; + + return true; + } + + public static final boolean isCommandSenderPlayer(CommandSender commandSender) { + if(!(commandSender instanceof Player)) return false; + + return true; + } + +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/SubCommand.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/SubCommand.java new file mode 100644 index 0000000..c750d7f --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/SubCommand.java @@ -0,0 +1,24 @@ +package net.aminecraftdev.custombosses.innerapi.command; + +import org.bukkit.command.CommandSender; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public abstract class SubCommand { + + private String subCommand; + + public SubCommand(String subCommand) { + this.subCommand = subCommand; + } + + public String getSubCommand() { + return subCommand; + } + + public abstract void execute(T sender, String[] args); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/SubCommandBuilder.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/SubCommandBuilder.java new file mode 100644 index 0000000..5051f1a --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/SubCommandBuilder.java @@ -0,0 +1,14 @@ +package net.aminecraftdev.custombosses.innerapi.command; + +import org.bukkit.command.CommandSender; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public interface SubCommandBuilder { + + void register(SubCommand subCommand); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/CommandRemover.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/CommandRemover.java new file mode 100644 index 0000000..05b33e1 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/CommandRemover.java @@ -0,0 +1,49 @@ +package net.aminecraftdev.custombosses.innerapi.command.builder; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.command.SimpleCommandMap; +import org.bukkit.plugin.SimplePluginManager; +import org.bukkit.plugin.java.JavaPlugin; + +import java.lang.reflect.Field; +import java.util.Map; + +/** + * Created by charl on 03-May-17. + */ +public final class CommandRemover { + + private CommandMap map = new SimpleCommandMap(null); + + /** + * Remove/un-register a command. + */ + public CommandRemover(JavaPlugin plugin, String command) { + if (plugin.getServer() != null && plugin.getServer().getPluginManager() instanceof SimplePluginManager) { + final SimplePluginManager manager = (SimplePluginManager) plugin.getServer().getPluginManager(); + try { + final Field field = SimplePluginManager.class.getDeclaredField("commandMap"); + field.setAccessible(true); + + map = (CommandMap) field.get(manager); + + final Field field2 = SimpleCommandMap.class.getDeclaredField("knownCommands"); + field2.setAccessible(true); + + @SuppressWarnings("unchecked") + final Map knownCommands = (Map) field2.get(map); + + for (final Map.Entry entry : knownCommands.entrySet()) { + if (entry.getKey().equals(command)) { + entry.getValue().unregister(map); + } + } + + knownCommands.remove(command); + } catch (IllegalArgumentException | NoSuchFieldException | IllegalAccessException | SecurityException e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/CommandService.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/CommandService.java new file mode 100644 index 0000000..5942151 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/CommandService.java @@ -0,0 +1,135 @@ +package net.aminecraftdev.custombosses.innerapi.command.builder; + +import net.aminecraftdev.custombosses.innerapi.command.builder.attributes.*; +import net.aminecraftdev.custombosses.innerapi.message.MessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandMap; +import org.bukkit.command.CommandSender; +import org.bukkit.command.defaults.BukkitCommand; + +import java.lang.reflect.Field; +import java.util.Arrays; + +/** + * Created by charl on 03-May-17. + */ +public abstract class CommandService extends BukkitCommand { + + private static CommandMap _commandMap = null; + + private String _command, _description, _usage, _noPermMessage, _permission; + private String[] _aliases; + + /** + * Construct a new command. + * + * @param command The command label + * @param description The command description + * @param aliases Aliases of the command + */ + public CommandService(String command, String description, String[] aliases) { + super(command); + + _command = command; + _description = description; + _aliases = aliases; + } + + /** + * Construct a new command. + * + * @param command The command label + * @param description The command description + */ + public CommandService(String command, String description) { + this(command, description, new String[]{}); + } + + /** + * Construct a new command. + * + * @param cmd The command + */ + public CommandService(Class cmd) { + this(cmd.getAnnotation(Name.class).value(), cmd.getAnnotation(Description.class).value()); + + if(cmd.isAnnotationPresent(Alias.class)) + _aliases = cmd.getAnnotation(Alias.class).value(); + + if(cmd.isAnnotationPresent(Permission.class)) + _permission = cmd.getAnnotation(Permission.class).value(); + + if(cmd.isAnnotationPresent(Usage.class)) + _usage = cmd.getAnnotation(Usage.class).value(); + + if(cmd.isAnnotationPresent(NoPermission.class)) + _noPermMessage = cmd.getAnnotation(NoPermission.class).value(); + + register(); + } + + @Override + public final boolean execute(CommandSender commandSender, String s, String[] args) { + if(testPermission(commandSender)) return false; + + try { + execute((T) commandSender, args); + } catch (ClassCastException e) { + commandSender.sendMessage(MessageUtils.translateString("&4You cannot use that command.")); + return false; + } + return true; + } + + /** + * This is fired when the command is executed. + * + * @param sender Sender of the command + * @param args Command arguments + */ + public abstract void execute(T sender, String[] args); + + + /** + * This method will register a command without the need of plugin.yml + */ + private void register() { + if (_commandMap != null) { + setFields(); + _commandMap.register(_command, this); + return; + } + + try { + Field field = Bukkit.getServer().getClass().getDeclaredField("commandMap"); + field.setAccessible(true); + _commandMap = (CommandMap) field.get(Bukkit.getServer()); + + setFields(); + + _commandMap.register(_command, this); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + private void setFields() { + setDescription(_description); + + if(_aliases != null) setAliases(Arrays.asList(_aliases)); + if(_usage != null) setUsage(_usage); + if(_permission != null) setPermission(_permission); + + if(_noPermMessage != null) { + setPermissionMessage(MessageUtils.translateString(_noPermMessage)); + } else { + setPermissionMessage(MessageUtils.translateString("&4You do not have for that command.")); + } + } + + @Override + public String getDescription() { + return _description; + } +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Alias.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Alias.java new file mode 100644 index 0000000..b9127d6 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Alias.java @@ -0,0 +1,15 @@ +package net.aminecraftdev.custombosses.innerapi.command.builder.attributes; + +import java.lang.annotation.*; + +/** + * Created by charl on 03-May-17. + */ +@Documented +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Alias { + + String[] value(); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Description.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Description.java new file mode 100644 index 0000000..59c4369 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Description.java @@ -0,0 +1,15 @@ +package net.aminecraftdev.custombosses.innerapi.command.builder.attributes; + +import java.lang.annotation.*; + +/** + * Created by charl on 03-May-17. + */ +@Documented +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Description { + + String value(); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Name.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Name.java new file mode 100644 index 0000000..a304586 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Name.java @@ -0,0 +1,15 @@ +package net.aminecraftdev.custombosses.innerapi.command.builder.attributes; + +import java.lang.annotation.*; + +/** + * Created by LukeBingham on 03/04/2017. + */ +@Documented +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Name { + + String value(); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/NoPermission.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/NoPermission.java new file mode 100644 index 0000000..1736422 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/NoPermission.java @@ -0,0 +1,17 @@ +package net.aminecraftdev.custombosses.innerapi.command.builder.attributes; + +import java.lang.annotation.*; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +@Documented +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface NoPermission { + + String value(); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Permission.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Permission.java new file mode 100644 index 0000000..2aca448 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Permission.java @@ -0,0 +1,15 @@ +package net.aminecraftdev.custombosses.innerapi.command.builder.attributes; + +import java.lang.annotation.*; + +/** + * Created by charl on 11-May-17. + */ +@Documented +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Permission { + + String value(); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Usage.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Usage.java new file mode 100644 index 0000000..fa15626 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/command/builder/attributes/Usage.java @@ -0,0 +1,17 @@ +package net.aminecraftdev.custombosses.innerapi.command.builder.attributes; + +import java.lang.annotation.*; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +@Documented +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Usage { + + String value(); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/FactionBuilder.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/FactionBuilder.java new file mode 100644 index 0000000..9163500 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/FactionBuilder.java @@ -0,0 +1,59 @@ +package net.aminecraftdev.custombosses.innerapi.dependencies; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public interface FactionBuilder { + + /** Used to tell if 2 players are + * friendly. + * + * @param a - The first player. + * @param b - The second player. + * + */ + + boolean isFriendly(Player a, Player b); + + + /** Used to tell if a player is in friendly + * land, in other words to tell if they are + * in ally, truce or their own land. If not + * returns false. + * + * @param a - The player. + * @param location - The location we are checking. + * + */ + + boolean isFriendly(Player a, Location location); + + + /** Used to check if a location is in the warzone. + * I used this in my CustomBosses plugin to check + * if the player was inside a warzone when spawning + * the boss. + * + * @param location - The location we are checking. + * + */ + + boolean isInWarzone(Location location); + + + /** Used to check if the location is claimed by a faction + * other then Wilderness, Warzone or Safezone. If it is + * another faction it will return true, otherwise if its + * in Wilderness, Warzone or Safezone it will return false. + * + * @param location - The location that is being tested. + * + */ + boolean isInClaimedLand(Location location); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/VaultHelper.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/VaultHelper.java new file mode 100644 index 0000000..bb05662 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/VaultHelper.java @@ -0,0 +1,76 @@ +package net.aminecraftdev.custombosses.innerapi.dependencies; + +import net.milkbowl.vault.chat.Chat; +import net.milkbowl.vault.economy.Economy; +import net.milkbowl.vault.permission.Permission; +import org.bukkit.Bukkit; +import org.bukkit.plugin.RegisteredServiceProvider; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 25-May-17 + */ +public class VaultHelper { + + private static Economy economy; + private static Chat chat; + private static Permission permission; + + public static final Economy getEconomy() { + return economy; + } + + public static final Chat getChat() { + return chat; + } + + public static final Permission getPermission() { + return permission; + } + + public static boolean setupVault() { + if(!setupChat()) return false; + if(!setupPermission()) return false; + if(!setupEconomy()) return false; + return true; + } + + private static boolean setupChat() { + if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { + return false; + } + RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Chat.class); + if (rsp == null) { + return false; + } + chat = rsp.getProvider(); + return chat != null; + } + + private static boolean setupEconomy() { + if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { + return false; + } + RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class); + if (rsp == null) { + return false; + } + economy = rsp.getProvider(); + return economy != null; + } + + private static boolean setupPermission() { + if (Bukkit.getServer().getPluginManager().getPlugin("Vault") == null) { + return false; + } + RegisteredServiceProvider rsp = Bukkit.getServer().getServicesManager().getRegistration(Permission.class); + if (rsp == null) { + return false; + } + permission = rsp.getProvider(); + return permission != null; + } + + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/WorldGuardHelper.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/WorldGuardHelper.java new file mode 100644 index 0000000..5e6450f --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/dependencies/WorldGuardHelper.java @@ -0,0 +1,97 @@ +package net.aminecraftdev.custombosses.innerapi.dependencies; + +import com.sk89q.worldguard.bukkit.WGBukkit; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.flags.DefaultFlag; +import com.sk89q.worldguard.protection.flags.StateFlag; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import org.bukkit.Bukkit; +import org.bukkit.Location; + +import java.util.LinkedList; +import java.util.List; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 25-May-17 + */ +public class WorldGuardHelper { + + private static Boolean isLoaded = null; + + private static boolean isPluginLoaded() { + return isLoaded != null? isLoaded : (isLoaded = Bukkit.getServer().getPluginManager().getPlugin("WorldEdit") != null + && Bukkit.getServer().getPluginManager().getPlugin("WorldGuard") != null); + } + + public static boolean isPvPAllowed(Location loc) { + if(isPluginLoaded()) { + ApplicableRegionSet set = WGBukkit.getPlugin().getRegionManager(loc.getWorld()).getApplicableRegions(loc); + + if(set.queryState(null, DefaultFlag.PVP) == StateFlag.State.DENY) return false; + } + + return true; + } + + public static boolean isBreakAllowed(Location loc) { + if(isPluginLoaded()) { + ApplicableRegionSet set = WGBukkit.getPlugin().getRegionManager(loc.getWorld()).getApplicableRegions(loc); + + if(set.queryState(null, DefaultFlag.BLOCK_BREAK) == StateFlag.State.DENY) return false; + } + + return true; + } + + public static boolean allowsExplosions(Location loc) { + if(isPluginLoaded()) { + ApplicableRegionSet set = WGBukkit.getPlugin().getRegionManager(loc.getWorld()).getApplicableRegions(loc); + + if(set.queryState(null, DefaultFlag.OTHER_EXPLOSION) == StateFlag.State.DENY) return false; + } + + return true; + } + + public static List getRegionNames(Location loc) { + if(isPluginLoaded()) { + ApplicableRegionSet set = WGBukkit.getPlugin().getRegionManager(loc.getWorld()).getApplicableRegions(loc); + LinkedList parentNames = new LinkedList(); + LinkedList regions = new LinkedList(); + + for(ProtectedRegion region : set) { + String id = region.getId(); + + regions.add(id); + + ProtectedRegion parent = region.getParent(); + + while(parent != null) { + parentNames.add(parent.getId()); + parent = parent.getParent(); + } + } + + for(String name : parentNames) { + regions.remove(name); + } + + return regions; + } + + return null; + } + + public static boolean isMobSpawningAllowed(Location loc) { + if(isPluginLoaded()) { + ApplicableRegionSet set = WGBukkit.getPlugin().getRegionManager(loc.getWorld()).getApplicableRegions(loc); + + if(set.queryState(null, DefaultFlag.MOB_SPAWNING) == StateFlag.State.DENY) return false; + } + + return true; + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/CloneableFactory.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/CloneableFactory.java new file mode 100644 index 0000000..d5a7ca8 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/CloneableFactory.java @@ -0,0 +1,10 @@ +package net.aminecraftdev.custombosses.innerapi.factory; + +/** + * Created by charl on 04-May-17. + */ +public interface CloneableFactory { + + T clone(); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/Factory.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/Factory.java new file mode 100644 index 0000000..47471b0 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/Factory.java @@ -0,0 +1,11 @@ +package net.aminecraftdev.custombosses.innerapi.factory; + +/** + * Created by charl on 04-May-17. + */ +public abstract class Factory implements FactoryBuilder { + + protected T object; + + public abstract T build(); +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/FactoryBuilder.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/FactoryBuilder.java new file mode 100644 index 0000000..1ee9b68 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/FactoryBuilder.java @@ -0,0 +1,11 @@ +package net.aminecraftdev.custombosses.innerapi.factory; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 29-May-17 + */ +public interface FactoryBuilder { + + T build(); +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/NbtFactory.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/NbtFactory.java new file mode 100644 index 0000000..8fe7688 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/factory/NbtFactory.java @@ -0,0 +1,997 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015 Kristian Stangeland +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +package net.aminecraftdev.custombosses.innerapi.factory; + +import com.google.common.base.Splitter; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Lists; +import com.google.common.collect.MapMaker; +import com.google.common.io.Closeables; +import com.google.common.io.Files; +import com.google.common.io.InputSupplier; +import com.google.common.io.OutputSupplier; +import com.google.common.primitives.Primitives; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.inventory.ItemStack; + +import java.io.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; +import java.util.concurrent.ConcurrentMap; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +@SuppressWarnings("deprecation") +public class NbtFactory { + // Convert between NBT id and the equivalent class in java + private static final BiMap> NBT_CLASS = HashBiMap.create(); + private static final BiMap NBT_ENUM = HashBiMap.create(); + + /** + * Whether or not to enable stream compression. + * @author Kristian + */ + public enum StreamOptions { + NO_COMPRESSION, + GZIP_COMPRESSION, + } + + private enum NbtType { + TAG_END(0, Void.class), + TAG_BYTE(1, byte.class), + TAG_SHORT(2, short.class), + TAG_INT(3, int.class), + TAG_LONG(4, long.class), + TAG_FLOAT(5, float.class), + TAG_DOUBLE(6, double.class), + TAG_BYTE_ARRAY(7, byte[].class), + TAG_INT_ARRAY(11, int[].class), + TAG_STRING(8, String.class), + TAG_LIST(9, List.class), + TAG_COMPOUND(10, Map.class); + + // Unique NBT id + public final int id; + + private NbtType(int id, Class type) { + this.id = id; + NBT_CLASS.put(id, type); + NBT_ENUM.put(id, this); + } + + private String getFieldName() { + if (this == TAG_COMPOUND) + return "map"; + else if (this == TAG_LIST) + return "list"; + else + return "data"; + } + } + + // The NBT base class + private Class BASE_CLASS; + private Class COMPOUND_CLASS; + private Class STREAM_TOOLS; + private Class READ_LIMITER_CLASS; + private Method NBT_CREATE_TAG; + private Method NBT_GET_TYPE; + private Field NBT_LIST_TYPE; + private final Field[] DATA_FIELD = new Field[12]; + + // CraftItemStack + private Class CRAFT_STACK; + private Field CRAFT_HANDLE; + private Field STACK_TAG; + + // Loading/saving compounds + private LoadCompoundMethod LOAD_COMPOUND; + private Method SAVE_COMPOUND; + + // Shared instance + private static NbtFactory INSTANCE; + + /** + * Represents a root NBT compound. + *

+ * All changes to this map will be reflected in the underlying NBT compound. Values may only be one of the following: + *

    + *
  • Primitive types
  • + *
  • {@link String String}
  • + *
  • {@link NbtList}
  • + *
  • {@link NbtCompound}
  • + *
+ *

+ * See also: + *

    + *
  • {@link NbtFactory#createCompound()}
  • + *
  • {@link NbtFactory#fromCompound(Object)}
  • + *
+ * @author Kristian + */ + public final class NbtCompound extends ConvertedMap { + private NbtCompound(Object handle) { + super(handle, getDataMap(handle)); + } + + // Simplifiying access to each value + public Byte getByte(String key, Byte defaultValue) { + return containsKey(key) ? (Byte)get(key) : defaultValue; + } + public Short getShort(String key, Short defaultValue) { + return containsKey(key) ? (Short)get(key) : defaultValue; + } + public Integer getInteger(String key, Integer defaultValue) { + return containsKey(key) ? (Integer)get(key) : defaultValue; + } + public Long getLong(String key, Long defaultValue) { + return containsKey(key) ? (Long)get(key) : defaultValue; + } + public Float getFloat(String key, Float defaultValue) { + return containsKey(key) ? (Float)get(key) : defaultValue; + } + public Double getDouble(String key, Double defaultValue) { + return containsKey(key) ? (Double)get(key) : defaultValue; + } + public String getString(String key, String defaultValue) { + return containsKey(key) ? (String)get(key) : defaultValue; + } + public byte[] getByteArray(String key, byte[] defaultValue) { + return containsKey(key) ? (byte[])get(key) : defaultValue; + } + public int[] getIntegerArray(String key, int[] defaultValue) { + return containsKey(key) ? (int[])get(key) : defaultValue; + } + + /** + * Retrieve the list by the given name. + * @param key - the name of the list. + * @param createNew - whether or not to create a new list if its missing. + * @return An existing list, a new list or NULL. + */ + public NbtList getList(String key, boolean createNew) { + NbtList list = (NbtList) get(key); + + if (list == null && createNew) + put(key, list = createList()); + return list; + } + + /** + * Retrieve the map by the given name. + * @param key - the name of the map. + * @param createNew - whether or not to create a new map if its missing. + * @return An existing map, a new map or NULL. + */ + public NbtCompound getMap(String key, boolean createNew) { + return getMap(Arrays.asList(key), createNew); + } + // Done + + /** + * Set the value of an entry at a given location. + *

+ * Every element of the path (except the end) are assumed to be compounds, and will + * be created if they are missing. + * @param path - the path to the entry. + * @param value - the new value of this entry. + * @return This compound, for chaining. + */ + public NbtCompound putPath(String path, Object value) { + List entries = getPathElements(path); + Map map = getMap(entries.subList(0, entries.size() - 1), true); + + map.put(entries.get(entries.size() - 1), value); + return this; + } + + /** + * Retrieve the value of a given entry in the tree. + *

+ * Every element of the path (except the end) are assumed to be compounds. The + * retrieval operation will be cancelled if any of them are missing. + * @param path - path to the entry. + * @return The value, or NULL if not found. + */ + @SuppressWarnings("unchecked") + public T getPath(String path) { + List entries = getPathElements(path); + NbtCompound map = getMap(entries.subList(0, entries.size() - 1), false); + + if (map != null) { + return (T) map.get(entries.get(entries.size() - 1)); + } + return null; + } + + /** + * Save the content of a NBT compound to a stream. + *

+ * Use {@link Files#newOutputStreamSupplier(File)} to provide a stream supplier to a file. + * @param stream - the output stream. + * @param option - whether or not to compress the output. + * @throws IOException If anything went wrong. + */ + public void saveTo(OutputSupplier stream, StreamOptions option) throws IOException { + saveStream(this, stream, option); + } + + /** + * Retrieve a map from a given path. + * @param path - path of compounds to look up. + * @param createNew - whether or not to create new compounds on the way. + * @return The map at this location. + */ + private NbtCompound getMap(Iterable path, boolean createNew) { + NbtCompound current = this; + + for (String entry : path) { + NbtCompound child = (NbtCompound) current.get(entry); + + if (child == null) { + if (!createNew) + return null; + current.put(entry, child = createCompound()); + } + current = child; + } + return current; + } + + /** + * Split the path into separate elements. + * @param path - the path to split. + * @return The elements. + */ + private List getPathElements(String path) { + return Lists.newArrayList(Splitter.on(".").omitEmptyStrings().split(path)); + } + } + + /** + * Represents a root NBT list. + * See also: + *

    + *
  • {@link NbtFactory#fromList(Object)}
  • + *
+ * @author Kristian + */ + public final class NbtList extends ConvertedList { + private NbtList(Object handle) { + super(handle, getDataList(handle)); + } + } + + /** + * Represents an object that provides a view of a native NMS class. + * @author Kristian + */ + public static interface Wrapper { + /** + * Retrieve the underlying native NBT tag. + * @return The underlying NBT. + */ + public Object getHandle(); + } + + /** + * Retrieve or construct a shared NBT factory. + * @return The factory. + */ + private static NbtFactory get() { + if (INSTANCE == null) + INSTANCE = new NbtFactory(); + return INSTANCE; + } + + /** + * Construct an instance of the NBT factory by deducing the class of NBTBase. + */ + private NbtFactory() { + if (BASE_CLASS == null) { + try { + // Keep in mind that I do use hard-coded field names - but it's okay as long as we're dealing + // with CraftBukkit or its derivatives. This does not work in MCPC+ however. + ClassLoader loader = NbtFactory.class.getClassLoader(); + + String packageName = getPackageName(); + Class offlinePlayer = loader.loadClass(packageName + ".CraftOfflinePlayer"); + + // Prepare NBT + COMPOUND_CLASS = getMethod(0, Modifier.STATIC, offlinePlayer, "getData").getReturnType(); + BASE_CLASS = COMPOUND_CLASS.getSuperclass(); + NBT_GET_TYPE = getMethod(0, Modifier.STATIC, BASE_CLASS, "getTypeId"); + NBT_CREATE_TAG = getMethod(Modifier.STATIC, 0, BASE_CLASS, "createTag", byte.class); + + // Prepare CraftItemStack + CRAFT_STACK = loader.loadClass(packageName + ".inventory.CraftItemStack"); + CRAFT_HANDLE = getField(null, CRAFT_STACK, "handle"); + STACK_TAG = getField(null, CRAFT_HANDLE.getType(), "tag"); + + // Loading/saving + String nmsPackage = BASE_CLASS.getPackage().getName(); + initializeNMS(loader, nmsPackage); + + LOAD_COMPOUND = READ_LIMITER_CLASS != null ? + new LoadMethodSkinUpdate(STREAM_TOOLS, READ_LIMITER_CLASS) : + new LoadMethodWorldUpdate(STREAM_TOOLS); + SAVE_COMPOUND = getMethod(Modifier.STATIC, 0, STREAM_TOOLS, null, BASE_CLASS, DataOutput.class); + + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Unable to find offline player.", e); + } + } + } + + private void initializeNMS(ClassLoader loader, String nmsPackage) { + try { + STREAM_TOOLS = loader.loadClass(nmsPackage + ".NBTCompressedStreamTools"); + READ_LIMITER_CLASS = loader.loadClass(nmsPackage + ".NBTReadLimiter"); + } catch (ClassNotFoundException e) { + // Ignore - we will detect this later + } + } + + private String getPackageName() { + Server server = Bukkit.getServer(); + String name = server != null ? server.getClass().getPackage().getName() : null; + + if (name != null && name.contains("craftbukkit")) { + return name; + } else { + // Fallback + return "org.bukkit.craftbukkit.v1_7_R3"; + } + } + + @SuppressWarnings("unchecked") + private Map getDataMap(Object handle) { + return (Map) getFieldValue( + getDataField(NbtType.TAG_COMPOUND, handle), handle); + } + + @SuppressWarnings("unchecked") + private List getDataList(Object handle) { + return (List) getFieldValue( + getDataField(NbtType.TAG_LIST, handle), handle); + } + + /** + * Construct a new NBT list of an unspecified type. + * @return The NBT list. + */ + public static NbtList createList(Object... content) { + return createList(Arrays.asList(content)); + } + + /** + * Construct a new NBT list of an unspecified type. + * @return The NBT list. + */ + public static NbtList createList(Iterable iterable) { + NbtList list = get().new NbtList( + INSTANCE.createNbtTag(NbtType.TAG_LIST, null) + ); + + // Add the content as well + for (Object obj : iterable) + list.add(obj); + return list; + } + + /** + * Construct a new NBT compound. + *

+ * @return The NBT compound. + */ + public static NbtCompound createCompound() { + return get().new NbtCompound( + INSTANCE.createNbtTag(NbtType.TAG_COMPOUND, null) + ); + } + + /** + * Construct a new NBT wrapper from a list. + * @param nmsList - the NBT list. + * @return The wrapper. + */ + public static NbtList fromList(Object nmsList) { + return get().new NbtList(nmsList); + } + + /** + * Load the content of a file from a stream. + *

+ * Use {@link Files#newInputStreamSupplier(File)} to provide a stream from a file. + * @param stream - the stream supplier. + * @param option - whether or not to decompress the input stream. + * @return The decoded NBT compound. + * @throws IOException If anything went wrong. + */ + public static NbtCompound fromStream(InputSupplier stream, StreamOptions option) throws IOException { + InputStream input = null; + DataInputStream data = null; + boolean suppress = true; + + try { + input = stream.getInput(); + data = new DataInputStream(new BufferedInputStream( + option == StreamOptions.GZIP_COMPRESSION ? new GZIPInputStream(input) : input + )); + + NbtCompound result = fromCompound(get().LOAD_COMPOUND.loadNbt(data)); + suppress = false; + return result; + + } finally { + if (data != null) + Closeables.close(data, suppress); + else if (input != null) + Closeables.close(input, suppress); + } + } + + /** + * Save the content of a NBT compound to a stream. + *

+ * Use {@link Files#newOutputStreamSupplier(File)} to provide a stream supplier to a file. + * @param source - the NBT compound to save. + * @param stream - the stream. + * @param option - whether or not to compress the output. + * @throws IOException If anything went wrong. + */ + public static void saveStream(NbtCompound source, OutputSupplier stream, StreamOptions option) throws IOException { + OutputStream output = null; + DataOutputStream data = null; + boolean suppress = true; + + try { + output = stream.getOutput(); + data = new DataOutputStream( + option == StreamOptions.GZIP_COMPRESSION ? new GZIPOutputStream(output) : output + ); + + invokeMethod(get().SAVE_COMPOUND, null, source.getHandle(), data); + suppress = false; + + } finally { + if (data != null) + Closeables.close(data, suppress); + else if (output != null) + Closeables.close(output, suppress); + } + } + + /** + * Construct a new NBT wrapper from a compound. + * @param nmsCompound - the NBT compund. + * @return The wrapper. + */ + public static NbtCompound fromCompound(Object nmsCompound) { + return get().new NbtCompound(nmsCompound); + } + + /** + * Set the NBT compound tag of a given item stack. + *

+ * The item stack must be a wrapper for a CraftItemStack. Use + * @param stack - the item stack, cannot be air. + * @param compound - the new NBT compound, or NULL to remove it. + * @throws IllegalArgumentException If the stack is not a CraftItemStack, or it represents air. + */ + public static void setItemTag(ItemStack stack, NbtCompound compound) { + checkItemStack(stack); + Object nms = getFieldValue(get().CRAFT_HANDLE, stack); + + // Now update the tag compound + setFieldValue(get().STACK_TAG, nms, compound.getHandle()); + } + + /** + * Construct a wrapper for an NBT tag stored (in memory) in an item stack. This is where + * auxillary data such as enchanting, name and lore is stored. It does not include items + * material, damage value or count. + *

+ * The item stack must be a wrapper for a CraftItemStack. + * @param stack - the item stack. + * @return A wrapper for its NBT tag. + */ + public static NbtCompound fromItemTag(ItemStack stack) { + checkItemStack(stack); + Object nms = getFieldValue(get().CRAFT_HANDLE, stack); + Object tag = getFieldValue(get().STACK_TAG, nms); + + // Create the tag if it doesn't exist + if (tag == null) { + NbtCompound compound = createCompound(); + setItemTag(stack, compound); + return compound; + } + return fromCompound(tag); + } + + /** + * Retrieve a CraftItemStack version of the stack. + * @param stack - the stack to convert. + * @return The CraftItemStack version. + */ + public static ItemStack getCraftItemStack(ItemStack stack) { + // Any need to convert? + if (stack == null || get().CRAFT_STACK.isAssignableFrom(stack.getClass())) + return stack; + try { + // Call the private constructor + Constructor caller = INSTANCE.CRAFT_STACK.getDeclaredConstructor(ItemStack.class); + caller.setAccessible(true); + return (ItemStack) caller.newInstance(stack); + } catch (Exception e) { + throw new IllegalStateException("Unable to convert " + stack + " + to a CraftItemStack."); + } + } + + /** + * Ensure that the given stack can store arbitrary NBT information. + * @param stack - the stack to check. + */ + private static void checkItemStack(ItemStack stack) { + if (stack == null) + throw new IllegalArgumentException("Stack cannot be NULL."); + if (!get().CRAFT_STACK.isAssignableFrom(stack.getClass())) + throw new IllegalArgumentException("Stack must be a CraftItemStack."); + if (stack.getType() == Material.AIR) + throw new IllegalArgumentException("ItemStacks representing air cannot store NMS information."); + } + + /** + * Convert wrapped List and Map objects into their respective NBT counterparts. + * @param value - the value of the element to create. Can be a List or a Map. + * @return The NBT element. + */ + private Object unwrapValue(Object value) { + if (value == null) + return null; + + if (value instanceof Wrapper) { + return ((Wrapper) value).getHandle(); + + } else if (value instanceof List) { + throw new IllegalArgumentException("Can only insert a WrappedList."); + } else if (value instanceof Map) { + throw new IllegalArgumentException("Can only insert a WrappedCompound."); + + } else { + return createNbtTag(getPrimitiveType(value), value); + } + } + + /** + * Convert a given NBT element to a primitive wrapper or List/Map equivalent. + *

+ * All changes to any mutable objects will be reflected in the underlying NBT element(s). + * @param nms - the NBT element. + * @return The wrapper equivalent. + */ + private Object wrapNative(Object nms) { + if (nms == null) + return null; + + if (BASE_CLASS.isAssignableFrom(nms.getClass())) { + final NbtType type = getNbtType(nms); + + // Handle the different types + switch (type) { + case TAG_COMPOUND: + return new NbtCompound(nms); + case TAG_LIST: + return new NbtList(nms); + default: + return getFieldValue(getDataField(type, nms), nms); + } + } + throw new IllegalArgumentException("Unexpected type: " + nms); + } + + /** + * Construct a new NMS NBT tag initialized with the given value. + * @param type - the NBT type. + * @param value - the value, or NULL to keep the original value. + * @return The created tag. + */ + private Object createNbtTag(NbtType type, Object value) { + Object tag = invokeMethod(NBT_CREATE_TAG, null, (byte)type.id); + + if (value != null) { + setFieldValue(getDataField(type, tag), tag, value); + } + return tag; + } + + /** + * Retrieve the field where the NBT class stores its value. + * @param type - the NBT type. + * @param nms - the NBT class instance. + * @return The corresponding field. + */ + private Field getDataField(NbtType type, Object nms) { + if (DATA_FIELD[type.id] == null) + DATA_FIELD[type.id] = getField(nms, null, type.getFieldName()); + return DATA_FIELD[type.id]; + } + + /** + * Retrieve the NBT type from a given NMS NBT tag. + * @param nms - the native NBT tag. + * @return The corresponding type. + */ + private NbtType getNbtType(Object nms) { + int type = (Byte) invokeMethod(NBT_GET_TYPE, nms); + return NBT_ENUM.get(type); + } + + /** + * Retrieve the nearest NBT type for a given primitive type. + * @param primitive - the primitive type. + * @return The corresponding type. + */ + private NbtType getPrimitiveType(Object primitive) { + NbtType type = NBT_ENUM.get(NBT_CLASS.inverse().get( + Primitives.unwrap(primitive.getClass()) + )); + + // Display the illegal value at least + if (type == null) + throw new IllegalArgumentException(String.format( + "Illegal type: %s (%s)", primitive.getClass(), primitive)); + return type; + } + + /** + * Invoke a method on the given target instance using the provided parameters. + * @param method - the method to invoke. + * @param target - the target. + * @param params - the parameters to supply. + * @return The result of the method. + */ + private static Object invokeMethod(Method method, Object target, Object... params) { + try { + return method.invoke(target, params); + } catch (Exception e) { + throw new RuntimeException("Unable to invoke method " + method + " for " + target, e); + } + } + + private static void setFieldValue(Field field, Object target, Object value) { + try { + field.set(target, value); + } catch (Exception e) { + throw new RuntimeException("Unable to set " + field + " for " + target, e); + } + } + + private static Object getFieldValue(Field field, Object target) { + try { + return field.get(target); + } catch (Exception e) { + throw new RuntimeException("Unable to retrieve " + field + " for " + target, e); + } + } + + /** + * Search for the first publically and privately defined method of the given name and parameter count. + * @param requireMod - modifiers that are required. + * @param bannedMod - modifiers that are banned. + * @param clazz - a class to start with. + * @param methodName - the method name, or NULL to skip. + * @param params - the expected parameters. + * @return The first method by this name. + * @throws IllegalStateException If we cannot find this method. + */ + private static Method getMethod(int requireMod, int bannedMod, Class clazz, String methodName, Class... params) { + for (Method method : clazz.getDeclaredMethods()) { + // Limitation: Doesn't handle overloads + if ((method.getModifiers() & requireMod) == requireMod && + (method.getModifiers() & bannedMod) == 0 && + (methodName == null || method.getName().equals(methodName)) && + Arrays.equals(method.getParameterTypes(), params)) { + + method.setAccessible(true); + return method; + } + } + // Search in every superclass + if (clazz.getSuperclass() != null) + return getMethod(requireMod, bannedMod, clazz.getSuperclass(), methodName, params); + throw new IllegalStateException(String.format( + "Unable to find method %s (%s).", methodName, Arrays.asList(params))); + } + + /** + * Search for the first publically and privately defined field of the given name. + * @param instance - an instance of the class with the field. + * @param clazz - an optional class to start with, or NULL to deduce it from instance. + * @param fieldName - the field name. + * @return The first field by this name. + * @throws IllegalStateException If we cannot find this field. + */ + private static Field getField(Object instance, Class clazz, String fieldName) { + if (clazz == null) + clazz = instance.getClass(); + // Ignore access rules + for (Field field : clazz.getDeclaredFields()) { + if (field.getName().equals(fieldName)) { + field.setAccessible(true); + return field; + } + } + // Recursively fild the correct field + if (clazz.getSuperclass() != null) + return getField(instance, clazz.getSuperclass(), fieldName); + throw new IllegalStateException("Unable to find field " + fieldName + " in " + instance); + } + + /** + * Represents a class for caching wrappers. + * @author Kristian + */ + private final class CachedNativeWrapper { + // Don't recreate wrapper objects + private final ConcurrentMap cache = new MapMaker().weakKeys().makeMap(); + + public Object wrap(Object value) { + Object current = cache.get(value); + + if (current == null) { + current = wrapNative(value); + + // Only cache composite objects + if (current instanceof ConvertedMap || + current instanceof ConvertedList) { + cache.put(value, current); + } + } + return current; + } + } + + /** + * Represents a map that wraps another map and automatically + * converts entries of its type and another exposed type. + * @author Kristian + */ + private class ConvertedMap extends AbstractMap implements Wrapper { + private final Object handle; + private final Map original; + + private final CachedNativeWrapper cache = new CachedNativeWrapper(); + + public ConvertedMap(Object handle, Map original) { + this.handle = handle; + this.original = original; + } + + // For converting back and forth + protected Object wrapOutgoing(Object value) { + return cache.wrap(value); + } + protected Object unwrapIncoming(Object wrapped) { + return unwrapValue(wrapped); + } + + // Modification + @Override + public Object put(String key, Object value) { + return wrapOutgoing(original.put( + (String) key, + unwrapIncoming(value) + )); + } + + // Performance + @Override + public Object get(Object key) { + return wrapOutgoing(original.get(key)); + } + @Override + public Object remove(Object key) { + return wrapOutgoing(original.remove(key)); + } + @Override + public boolean containsKey(Object key) { + return original.containsKey(key); + } + + @Override + public Set> entrySet() { + return new AbstractSet>() { + @Override + public boolean add(Entry e) { + String key = e.getKey(); + Object value = e.getValue(); + + original.put(key, unwrapIncoming(value)); + return true; + } + + @Override + public int size() { + return original.size(); + } + + @Override + public Iterator> iterator() { + return ConvertedMap.this.iterator(); + } + }; + } + + private Iterator> iterator() { + final Iterator> proxy = original.entrySet().iterator(); + + return new Iterator>() { + public boolean hasNext() { + return proxy.hasNext(); + } + + public Entry next() { + Entry entry = proxy.next(); + + return new SimpleEntry( + entry.getKey(), wrapOutgoing(entry.getValue()) + ); + } + + public void remove() { + proxy.remove(); + } + }; + } + + public Object getHandle() { + return handle; + } + } + + /** + * Represents a list that wraps another list and converts elements + * of its type and another exposed type. + * @author Kristian + */ + private class ConvertedList extends AbstractList implements Wrapper { + private final Object handle; + + private final List original; + private final CachedNativeWrapper cache = new CachedNativeWrapper(); + + public ConvertedList(Object handle, List original) { + if (NBT_LIST_TYPE == null) + NBT_LIST_TYPE = getField(handle, null, "type"); + this.handle = handle; + this.original = original; + } + + protected Object wrapOutgoing(Object value) { + return cache.wrap(value); + } + protected Object unwrapIncoming(Object wrapped) { + return unwrapValue(wrapped); + } + + @Override + public Object get(int index) { + return wrapOutgoing(original.get(index)); + } + @Override + public int size() { + return original.size(); + } + @Override + public Object set(int index, Object element) { + return wrapOutgoing( + original.set(index, unwrapIncoming(element)) + ); + } + @Override + public void add(int index, Object element) { + Object nbt = unwrapIncoming(element); + + // Set the list type if its the first element + if (size() == 0) + setFieldValue(NBT_LIST_TYPE, handle, (byte)getNbtType(nbt).id); + original.add(index, nbt); + } + @Override + public Object remove(int index) { + return wrapOutgoing(original.remove(index)); + } + @Override + public boolean remove(Object o) { + return original.remove(unwrapIncoming(o)); + } + + public Object getHandle() { + return handle; + } + } + + /** + * Represents a method for loading an NBT compound. + * @author Kristian + */ + private static abstract class LoadCompoundMethod { + protected Method staticMethod; + + protected void setMethod(Method method) { + this.staticMethod = method; + this.staticMethod.setAccessible(true); + } + + /** + * Load an NBT compound from a given stream. + * @param input - the input stream. + * @return The loaded NBT compound. + */ + public abstract Object loadNbt(DataInput input); + } + + /** + * Load an NBT compound from the NBTCompressedStreamTools static method in 1.7.2 - 1.7.5 + */ + private static class LoadMethodWorldUpdate extends LoadCompoundMethod { + public LoadMethodWorldUpdate(Class streamClass) { + setMethod(getMethod(Modifier.STATIC, 0, streamClass, null, DataInput.class)); + } + + @Override + public Object loadNbt(DataInput input) { + return invokeMethod(staticMethod, null, input); + } + } + + /** + * Load an NBT compound from the NBTCompressedStreamTools static method in 1.7.8 + */ + private static class LoadMethodSkinUpdate extends LoadCompoundMethod { + private Object readLimiter; + + public LoadMethodSkinUpdate(Class streamClass, Class readLimiterClass) { + setMethod(getMethod(Modifier.STATIC, 0, streamClass, null, DataInput.class, readLimiterClass)); + + // Find the unlimited read limiter + for (Field field : readLimiterClass.getDeclaredFields()) { + if (readLimiterClass.isAssignableFrom(field.getType())) { + try { + readLimiter = field.get(null); + } catch (Exception e) { + throw new RuntimeException("Cannot retrieve read limiter.", e); + } + } + } + } + + @Override + public Object loadNbt(DataInput input) { + return invokeMethod(staticMethod, null, input, readLimiter); + } + } +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/IInventoryBuilder.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/IInventoryBuilder.java new file mode 100644 index 0000000..e3d7dbb --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/IInventoryBuilder.java @@ -0,0 +1,26 @@ +package net.aminecraftdev.custombosses.innerapi.inventory; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.Inventory; + +import java.util.HashMap; +import java.util.Set; + +/** + * Created by charl on 28-Apr-17. + */ +public interface IInventoryBuilder { + + Panel getInventory(); + + Inventory getClonedInventory(); + + void addReplacedMap(HashMap map); + + ConfigurationSection getConfigurationSection(); + + ConfigurationSection getItemConfigSection(); + + Set getSetOfItemSlots(); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/InventoryBuilder.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/InventoryBuilder.java new file mode 100644 index 0000000..680ec70 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/InventoryBuilder.java @@ -0,0 +1,106 @@ +package net.aminecraftdev.custombosses.innerapi.inventory; + +import net.aminecraftdev.custombosses.innerapi.factory.FactoryBuilder; +import net.aminecraftdev.custombosses.innerapi.itemstack.ItemStackUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Created by charl on 28-Apr-17. + */ +public class InventoryBuilder implements FactoryBuilder, IInventoryBuilder { + + private String name; + private int slots; + private ConfigurationSection items; + private ConfigurationSection inventoryConfigSection; + private Inventory inventory; + private Set _setOfItemSlots = new HashSet<>(); + private HashMap _map = new HashMap<>(); + private Map pageData = new HashMap<>(); + private JavaPlugin javaPlugin; + + public InventoryBuilder(ConfigurationSection inventory, JavaPlugin javaPlugin) { + this.name = ChatColor.translateAlternateColorCodes('&', inventory.getString("name")); + this.slots = inventory.getInt("slots"); + this.items = inventory.getConfigurationSection("Items"); + this.inventoryConfigSection = inventory; + this.javaPlugin = javaPlugin; + } + + @Override + public Panel getInventory() { + build(); + return new Panel(this.inventory, pageData, javaPlugin); + } + + @Override + public Inventory getClonedInventory() { + Inventory inv = getInventory().getInventory(); + Inventory inventory = Bukkit.createInventory(inv.getHolder(), inv.getSize(), inv.getTitle()); + + for(int i = 0; i < inv.getSize(); i++) { + if(inv.getItem(i) == null || inv.getItem(i).getType() == Material.AIR) continue; + + inventory.setItem(i, inv.getItem(i)); + } + + return inventory; + } + + @Override + public void addReplacedMap(HashMap map) { + _map.putAll(map); + } + + @Override + public ConfigurationSection getConfigurationSection() { + return inventoryConfigSection; + } + + @Override + public ConfigurationSection getItemConfigSection() { + return items; + } + + @Override + public Set getSetOfItemSlots() { + return _setOfItemSlots; + } + + @Override + public Inventory build() { + this.inventory = Bukkit.createInventory(null, this.slots, this.name); + + for(String s : this.items.getKeys(false)) { + int slot = Integer.valueOf(s) - 1; + ConfigurationSection section = this.items.getConfigurationSection(s); + ItemStack stack = ItemStackUtils.createItemStack(section, 1, _map); + if(section.contains("NextPage")) { + boolean b = section.getBoolean("NextPage"); + if(b) { + pageData.put(slot, 1); + } + } else if(section.contains("PreviousPage")) { + boolean b = section.getBoolean("PreviousPage"); + if(b) { + pageData.put(slot, -1); + } + } + this.inventory.setItem(slot, stack); + _setOfItemSlots.add(slot); + } + + return this.inventory; + } +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/InventoryFactory.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/InventoryFactory.java new file mode 100644 index 0000000..4abe281 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/InventoryFactory.java @@ -0,0 +1,84 @@ +package net.aminecraftdev.custombosses.innerapi.inventory; + +import net.aminecraftdev.custombosses.innerapi.factory.CloneableFactory; +import net.aminecraftdev.custombosses.innerapi.factory.Factory; +import org.bukkit.Bukkit; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by charl on 07-May-17. + */ +public class InventoryFactory extends Factory implements CloneableFactory { + + private Map mapOfItems = new HashMap<>(); + private JavaPlugin javaPlugin; + private InventoryHolder inventoryHolder; + private String name; + private int slot; + + public InventoryFactory(String name, int slot, JavaPlugin javaPlugin) { + setName(name); + setSlots(slot); + setHolder(null); + + this.javaPlugin = javaPlugin; + } + + public InventoryFactory setSlots(int amount) { + this.slot = amount; + return this; + } + + public InventoryFactory setName(String name) { + this.name = name; + return this; + } + + public InventoryFactory setHolder(InventoryHolder inventoryHolder) { + this.inventoryHolder = inventoryHolder; + return this; + } + + public InventoryFactory addItem(ItemStack... itemStacks) { + for(ItemStack itemStack : itemStacks) { + for(int i = 0; i < this.slot; i++) { + if(mapOfItems.containsKey(i)) continue; + + mapOfItems.put(i, itemStack); + } + } + + return this; + } + + public InventoryFactory setItem(ItemStack itemStack, int slot) { + mapOfItems.put(slot, itemStack); + return this; + } + + @Override + public Panel build() { + Inventory inventory = Bukkit.createInventory(this.inventoryHolder, this.slot, this.name); + + for(int i : this.mapOfItems.keySet()) { + inventory.setItem(i, this.mapOfItems.get(i)); + } + + return new Panel(inventory, javaPlugin); + } + + @Override + public InventoryFactory clone() { + InventoryFactory clone = new InventoryFactory(this.name, this.slot, javaPlugin); + clone.inventoryHolder = this.inventoryHolder; + clone.mapOfItems.putAll(this.mapOfItems); + + return clone; + } +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/Panel.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/Panel.java new file mode 100644 index 0000000..967ade0 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/Panel.java @@ -0,0 +1,333 @@ +package net.aminecraftdev.custombosses.innerapi.inventory; + +import net.aminecraftdev.custombosses.innerapi.inventory.base.ClickAction; +import net.aminecraftdev.custombosses.innerapi.inventory.base.PageAction; +import net.aminecraftdev.custombosses.innerapi.inventory.base.PanelCloseAction; +import net.aminecraftdev.custombosses.innerapi.message.MessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.*; + +/** + * @author Debugged + * @version 1.0 + * @since 13-5-2017 + */ +public class Panel { + + public static List panels = new ArrayList<>(); + private static boolean registered = false; + + private Inventory inventory; + public int viewers = 0; + private Map actions = new HashMap<>(); + private Map pageData = new HashMap<>(); + private Map currentPages = new HashMap<>(); + private Sound clickSound = null; + private boolean cancelClick = true; + private boolean destroyWhenDone = true; + + private PanelCloseAction panelClose = (p) -> {}; + private PageAction onPageChange = (player, currentPage, requestedPage) -> {return false;}; + + /** + * Creates a Panel with a title and a specific size + * + * @param title + * @param size + */ + public Panel(String title, int size, JavaPlugin javaPlugin) { + if(!registered) { + Bukkit.getPluginManager().registerEvents(getListeners(), javaPlugin); + registered = true; + } + if(size % 9 != 0 && size != 5) { + throw new UnsupportedOperationException("Inventory size must be a multiple of 9 or 5"); + } + this.inventory = size % 9 == 0 ? Bukkit.createInventory(null, size, MessageUtils.translateString(title)) : Bukkit.createInventory(null, InventoryType.HOPPER, MessageUtils.translateString(title)); + panels.add(this); + } + + public Panel(Inventory inventory, Map pageData, JavaPlugin javaPlugin) { + if(!registered) { + Bukkit.getPluginManager().registerEvents(getListeners(), javaPlugin); + registered = true; + } + this.inventory = inventory; + this.pageData = pageData; + + panels.add(this); + } + + public Panel(Inventory inventory, JavaPlugin javaPlugin) { + this(inventory, new HashMap<>(), javaPlugin); + } + + /** + * Returns the listeners that are + * needed for all Panel handlers to work properly + * + * @return Listener + */ + private Listener getListeners() { + return new Listener() { + @EventHandler + public void onInvClick(InventoryClickEvent e) { + if (e.getInventory() != null && !Panel.panels.isEmpty()) { + if(e.getInventory() == null) return; + if(e.getCurrentItem() == null && e.getCursor() == null) return; + for(Panel panel : new ArrayList<>(Panel.panels)) { + if(panel != null && panel.getInventory() != null) { + if(!panel.getInventory().equals(e.getInventory())) continue; + if(panel.getClickSound() != null) { + ((Player)e.getWhoClicked()).playSound(e.getWhoClicked().getLocation(), panel.getClickSound(), 3f, 1f); + } + if (panel.willCancelClick()) { + e.setCancelled(true); + } + if (panel.getInventory().equals(e.getInventory())) { + panel.executeAction(e.getRawSlot(), e); + } + } + } + } + } + + @EventHandler + public void onInvClose(InventoryCloseEvent e) { + if (e.getInventory() != null && !Panel.panels.isEmpty()) { + for(Panel panel : new ArrayList<>(Panel.panels)) { + if(panel != null && panel.getInventory() != null) { + if (panel.getInventory().equals(e.getInventory())) { + panel.panelClose.onClose((Player) e.getPlayer()); + panel.viewers--; + if (panel.getViewers() <= 0 && panel.willDestroyWhenDone()) { + panel.destroy(); + } + } + } + } + } + } + }; + } + + /** + * Triggers the ClickAction interfaces + * for the specified slot + * + * @param slot int + * @param e InventoryClickEvent + */ + public void executeAction(int slot, InventoryClickEvent e) { + Player clicker = (Player) e.getWhoClicked(); + if(pageData.containsKey(slot)) { + int currentPage = currentPages.getOrDefault(clicker.getUniqueId(), 0); + if(pageData.get(slot) > 0) { + if(onPageChange.onPageAction(clicker, currentPage, currentPage+1)) { + currentPages.put(clicker.getUniqueId(), currentPage+1); + } + } else { + if(currentPage != 0) { + if (onPageChange.onPageAction(clicker, currentPage, currentPage-1)) { + currentPages.put(clicker.getUniqueId(), currentPage - 1); + } + } + } + } + if(actions.containsKey(slot)) { + actions.get(slot).onClick(e); + } + } + + /** + * Sets the functional interface which will be called whenever a player closes the panel + *
+ * Builder method + * + * @param panelClose {@link PanelCloseAction} + * @return Panel + */ + public Panel onClose(PanelCloseAction panelClose) { + this.panelClose = panelClose; + return this; + } + + /** + * Specify a ClickAction for the + * given slot number + *
+ * Builder method + * + * @param slot int + * @param clickAction ClickAction + */ + public Panel setOnClick(int slot, ClickAction clickAction) { + actions.put(slot, clickAction); + return this; + } + + /** + * Sets an item at the specified slot + *
+ * Builder method + * + * @param slot int + * @param item ItemStack + * @return Panel + */ + public Panel setItem(int slot, ItemStack item){ + inventory.setItem(slot, item); + return this; + } + + /** + * Sets an item at the specified slot along with a functional interface which will
+ * be called whenever the item gets clicked + *
+ * Builder method + * + * @param slot int + * @param item ItemStack + * @param action {@link ClickAction} + * @return Panel + */ + public Panel setItem(int slot, ItemStack item, ClickAction action) { + inventory.setItem(slot, item); + actions.put(slot, action); + return this; + } + + /** + * Sets the sound that will be played whenever + * an item gets clicked + * + * @param clickSound Sound + * @return Panel + */ + public Panel setClickSound(Sound clickSound) { + this.clickSound = clickSound; + return this; + } + + /** + * Opens the Panel for the specified Player + *
+ * Builder method + * + * @param player Player + * @return Panel + */ + public Panel openFor(Player player) { + player.openInventory(inventory); + viewers++; + return this; + } + + public Panel setOnClose(PanelCloseAction panelClose) { + this.panelClose = panelClose; + return this; + } + + public Panel setOnPageChange(PageAction onPageChange) { + this.onPageChange = onPageChange; + return this; + } + + /** + * Makes sure the panel will cancel or not cancel click when an item was clicked + *
+ * Builder method + * + * @param cancelClick boolean + * @return Panel + */ + public Panel setCancelClick(boolean cancelClick) { + this.cancelClick = cancelClick; + return this; + } + + /** + * Makes sure the panel will destroy or not destroy when it has no viewers anymore + *
+ * Builder method + * + * @param destroyWhenDone boolean + * @return Panel + */ + public Panel setDestroyWhenDone(boolean destroyWhenDone) { + this.destroyWhenDone = destroyWhenDone; + return this; + } + + /** + * Returns whether or not the panel will destroy when there are no viewers anymore + * + * @return boolean + */ + public boolean willDestroyWhenDone() { + return destroyWhenDone; + } + + /** + * Returns whether or not clicking an item in this panel will cancel the InventoryClickEvent + * + * @return boolean + */ + public boolean willCancelClick() { + return cancelClick; + } + + /** + * Returns the amount of players that are viewing this panel + * + * @return int + */ + public int getViewers() { + return viewers; + } + + /** + * Returns the sound that will be played + * whenever a player clicks an item + * + * @return Sound + */ + public Sound getClickSound() { + return clickSound; + } + + /** + * Returns the bukkit Inventory object that corresponds to this panel + * + * @return Inventory + */ + public Inventory getInventory() { + return inventory; + } + + /** + * Destroys the panel in order to block further access + */ + public void destroy() { + this.actions.clear(); + this.pageData.clear(); + this.currentPages.clear(); + this.pageData = null; + this.currentPages = null; + this.actions = null; + this.inventory = null; + panels.remove(this); + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/ClickAction.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/ClickAction.java new file mode 100644 index 0000000..6158378 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/ClickAction.java @@ -0,0 +1,21 @@ +package net.aminecraftdev.custombosses.innerapi.inventory.base; + +import org.bukkit.event.inventory.InventoryClickEvent; + +/** + * @author Debugged + * @version 1.0 + * @since 13-5-2017 + */ +@FunctionalInterface +public interface ClickAction { + + /** + * Called whenever the item that this + * ClickAction is associated with is triggered + * + * @param e InventoryClickEvent + */ + void onClick(InventoryClickEvent e); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/PageAction.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/PageAction.java new file mode 100644 index 0000000..2025c0f --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/PageAction.java @@ -0,0 +1,15 @@ +package net.aminecraftdev.custombosses.innerapi.inventory.base; + +import org.bukkit.entity.Player; + +/** + * @author Debugged + * @version 1.0 + * @since 13-5-2017 + */ +@FunctionalInterface +public interface PageAction { + + boolean onPageAction(Player player, int currentPage, int requestedPage); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/PanelCloseAction.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/PanelCloseAction.java new file mode 100644 index 0000000..c44fff8 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/inventory/base/PanelCloseAction.java @@ -0,0 +1,21 @@ +package net.aminecraftdev.custombosses.innerapi.inventory.base; + +import org.bukkit.entity.Player; + +/** + * @author Debugged + * @version 1.0 + * @since 13-5-2017 + */ +@FunctionalInterface +public interface PanelCloseAction { + + /** + * Called whenever a player closes the {@link net.aminecraftdev.custombosses.innerapi.inventory.Panel} + * that this PanelCloseAction is associated with + * + * @param player Player + */ + void onClose(Player player); + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/ItemFactory.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/ItemFactory.java new file mode 100644 index 0000000..904182c --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/ItemFactory.java @@ -0,0 +1,94 @@ +package net.aminecraftdev.custombosses.innerapi.itemstack; + +import net.aminecraftdev.custombosses.innerapi.factory.CloneableFactory; +import net.aminecraftdev.custombosses.innerapi.factory.Factory; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by charl on 04-May-17. + */ +public class ItemFactory extends Factory implements CloneableFactory { + + private ItemMeta itemMeta; + + public ItemFactory(Material material, byte data) { + this.object = new ItemStack(material, 1, (short) data); + this.itemMeta = this.object.getItemMeta(); + } + + public ItemFactory(Material material) { + this(material, (byte) 0); + } + + public final ItemFactory setAmount(int amount) { + if(amount > 64) amount = 64; + + this.object.setAmount(amount); + return this; + } + + public final ItemFactory setName(String name) { + this.itemMeta.setDisplayName(name); + return this; + } + + public final ItemFactory setLore(List lore) { + this.itemMeta.setLore(lore); + return this; + } + + public final ItemFactory setLore(String... lore) { + this.itemMeta.setLore(Arrays.asList(lore)); + return this; + } + + public final ItemFactory setOwner(String name) { + if(this.object.getType() == Material.SKULL_ITEM) { + SkullMeta skullMeta = (SkullMeta) this.itemMeta; + + skullMeta.setOwner(name); + } + + return this; + } + + public final ItemFactory setDurability(short durability) { + this.object.setDurability(durability); + return this; + } + + public final ItemFactory setData(byte data) { + this.object.setDurability((short) data); + return this; + } + + public final ItemFactory setUnsafeEnchantment(Enchantment enchantment, int level) { + this.object.addUnsafeEnchantment(enchantment, level); + return this; + } + + public final ItemFactory setEnchantment(Enchantment enchantment, int level) { + this.itemMeta.addEnchant(enchantment, level, true); + return this; + } + + @Override + public final ItemStack build() { + this.object.setItemMeta(this.itemMeta); + return this.object; + } + + @Override + public final ItemFactory clone() { + ItemFactory clone = new ItemFactory(this.object.getType(), this.object.getData().getData()); + clone.itemMeta = this.itemMeta; + return clone; + } +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/ItemStackUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/ItemStackUtils.java new file mode 100644 index 0000000..039013d --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/ItemStackUtils.java @@ -0,0 +1,193 @@ +package net.aminecraftdev.custombosses.innerapi.itemstack; + +import net.aminecraftdev.custombosses.innerapi.NumberUtils; +import net.aminecraftdev.custombosses.innerapi.factory.NbtFactory; +import net.aminecraftdev.custombosses.innerapi.itemstack.enchants.GlowEnchant; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by charl on 28-Apr-17. + */ +public class ItemStackUtils { + + public static final ItemStack createItemStack(ConfigurationSection configurationSection) { + return createItemStack(configurationSection, 1, null); + } + + public static final ItemStack createItemStack(ConfigurationSection configurationSection, int amount, Map replacedMap) { + String type = configurationSection.getString("type"); + String name = configurationSection.getString("name"); + List lore = configurationSection.getStringList("lore"); + List enchants = configurationSection.getStringList("enchants"); + short durability = (short) configurationSection.getInt("durability"); + Map map = new HashMap<>(); + List newLore = new ArrayList<>(); + Material mat = getType(type); + short meta = 0; + boolean addGlow = false; + + if(type instanceof String) { + String sType = (String) type; + + if(sType.contains(":")) { + String[] split = sType.split(":"); + + meta = Short.valueOf(split[1]); + } + } + + if((replacedMap != null) && (name != null)) { + for(String z : replacedMap.keySet()) { + if(!name.contains(z)) continue; + + name = name.replace(z, replacedMap.get(z)); + } + } + + if(lore != null) { + for(String z : lore) { + String y = z; + + if(replacedMap != null) { + for(String x : replacedMap.keySet()) { + if(!y.contains(x)) continue; + + y = y.replace(x, replacedMap.get(x)); + } + } + + if(y.contains("\n")) { + String[] split = y.split("\n"); + + for(String s2 : split) { + newLore.add(ChatColor.translateAlternateColorCodes('&', s2)); + } + } else { + newLore.add(ChatColor.translateAlternateColorCodes('&', y)); + } + } + } + + if(enchants != null) { + for(String s : enchants) { + String[] spl = s.split(":"); + String ench = spl[0]; + int level = Integer.parseInt(spl[1]); + + if(ench.equalsIgnoreCase("glow")) { + addGlow = true; + continue; + } + + map.put(Enchantment.getByName(ench), level); + } + } + + ItemStack itemStack = new ItemStack(mat, amount, meta); + ItemMeta itemMeta = itemStack.getItemMeta(); + + if(!newLore.isEmpty()) { + itemMeta.setLore(newLore); + } + if(name != null) { + if(!name.equals("")) { + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', name)); + } + } + + itemStack.setItemMeta(itemMeta); + + if(!map.isEmpty()) { + itemStack.addUnsafeEnchantments(map); + } + if(configurationSection.contains("durability")) { + short dura = itemStack.getType().getMaxDurability(); + dura -= (short) durability - 1; + + itemStack.setDurability(dura); + } + + if(addGlow) return addGlow(itemStack); + + return itemStack; + } + + public static final ItemStack replicateItem(ItemStack replicatable, int amount, Map replaceableData, Map compoundData) { + ItemStack clone = replicatable.clone(); + ItemMeta itemMeta = clone.getItemMeta(); + String name = itemMeta.hasDisplayName()? itemMeta.getDisplayName() : ""; + List lore = itemMeta.hasLore()? itemMeta.getLore() : new ArrayList<>(); + List newLore = new ArrayList<>(); + + if(replaceableData != null) { + for(String line : lore) { + for(String s : replaceableData.keySet()) { + if(line.contains(s)) line = line.replace(s, replaceableData.get(s)); + } + + newLore.add(line); + } + + for(String s : replaceableData.keySet()) { + if(name.contains(s)) name = name.replace(s, replaceableData.get(s)); + } + } else { + newLore.addAll(lore); + } + + itemMeta.setLore(newLore); + itemMeta.setDisplayName(name); + clone.setItemMeta(itemMeta); + clone.setAmount(amount); + + if(compoundData == null) return clone; + + ItemStack craftStack = NbtFactory.getCraftItemStack(clone); + NbtFactory.NbtCompound compound = NbtFactory.fromItemTag(craftStack); + + for(String s : compoundData.keySet()) { + compound.put(s, compoundData.get(s)); + } + + return craftStack; + } + + public static final Material getType(String string) { + Material material = Material.getMaterial(string); + + if(material == null) { + if(NumberUtils.isStringInteger(string)) { + material = Material.getMaterial(Integer.valueOf(string)); + + if(material != null) return material; + + return null; + } else { + String[] split = string.split(":"); + + material = Material.getMaterial(Integer.valueOf(split[0])); + + if(material != null) return material; + + return null; + } + } + + return material; + } + + public static final ItemStack addGlow(ItemStack itemStack) { + return GlowEnchant.addGlow(itemStack); + } + +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/enchants/GlowEnchant.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/enchants/GlowEnchant.java new file mode 100644 index 0000000..4bc0c5a --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/itemstack/enchants/GlowEnchant.java @@ -0,0 +1,22 @@ +package net.aminecraftdev.custombosses.innerapi.itemstack.enchants; + +import net.aminecraftdev.custombosses.innerapi.factory.NbtFactory; +import org.bukkit.inventory.ItemStack; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 29-May-17 + */ +public class GlowEnchant { + + public static final ItemStack addGlow(ItemStack base) { + ItemStack craftStack = NbtFactory.getCraftItemStack(base); + NbtFactory.NbtCompound compound = NbtFactory.fromItemTag(craftStack); + NbtFactory.NbtList newList = NbtFactory.createList(); + + compound.put("ench", newList); + return craftStack; + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/DefaultFontInfo.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/DefaultFontInfo.java new file mode 100644 index 0000000..4656be7 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/DefaultFontInfo.java @@ -0,0 +1,133 @@ +package net.aminecraftdev.custombosses.innerapi.message; + +/** + * Created by charl on 28-Apr-17. + */ +public enum DefaultFontInfo { + + A('A', 5), + a('a', 5), + B('B', 5), + b('b', 5), + C('C', 5), + c('c', 5), + D('D', 5), + d('d', 5), + E('E', 5), + e('e', 5), + F('F', 5), + f('f', 4), + G('G', 5), + g('g', 5), + H('H', 5), + h('h', 5), + I('I', 3), + i('i', 1), + J('J', 5), + j('j', 5), + K('K', 5), + k('k', 4), + L('L', 5), + l('l', 1), + M('M', 5), + m('m', 5), + N('N', 5), + n('n', 5), + O('O', 5), + o('o', 5), + P('P', 5), + p('p', 5), + Q('Q', 5), + q('q', 5), + R('R', 5), + r('r', 5), + S('S', 5), + s('s', 5), + T('T', 5), + t('t', 4), + U('U', 5), + u('u', 5), + V('V', 5), + v('v', 5), + W('W', 5), + w('w', 5), + X('X', 5), + x('x', 5), + Y('Y', 5), + y('y', 5), + Z('Z', 5), + z('z', 5), + NUM_1('1', 5), + NUM_2('2', 5), + NUM_3('3', 5), + NUM_4('4', 5), + NUM_5('5', 5), + NUM_6('6', 5), + NUM_7('7', 5), + NUM_8('8', 5), + NUM_9('9', 5), + NUM_0('0', 5), + EXCLAMATION_POINT('!', 1), + AT_SYMBOL('@', 6), + NUM_SIGN('#', 5), + DOLLAR_SIGN('$', 5), + PERCENT('%', 5), + UP_ARROW('^', 5), + AMPERSAND('&', 5), + ASTERISK('*', 5), + LEFT_PARENTHESIS('(', 4), + RIGHT_PERENTHESIS(')', 4), + MINUS('-', 5), + UNDERSCORE('_', 5), + PLUS_SIGN('+', 5), + EQUALS_SIGN('=', 5), + LEFT_CURL_BRACE('{', 4), + RIGHT_CURL_BRACE('}', 4), + LEFT_BRACKET('[', 3), + RIGHT_BRACKET(']', 3), + COLON(':', 1), + SEMI_COLON(';', 1), + DOUBLE_QUOTE('"', 3), + SINGLE_QUOTE('\'', 1), + LEFT_ARROW('<', 4), + RIGHT_ARROW('>', 4), + QUESTION_MARK('?', 5), + SLASH('/', 5), + BACK_SLASH('\\', 5), + LINE('|', 1), + TILDE('~', 5), + TICK('`', 2), + PERIOD('.', 1), + COMMA(',', 1), + SPACE(' ', 3), + DEFAULT('a', 4); + + private char character; + private int length; + + DefaultFontInfo(char character, int length) { + this.character = character; + this.length = length; + } + + public char getCharacter(){ + return this.character; + } + + public int getLength(){ + return this.length; + } + + public int getBoldLength(){ + if(this == DefaultFontInfo.SPACE) return this.getLength(); + return this.length + 1; + } + + public static DefaultFontInfo getDefaultFontInfo(char c){ + for(DefaultFontInfo dFI : DefaultFontInfo.values()){ + if(dFI.getCharacter() == c) return dFI; + } + return DefaultFontInfo.DEFAULT; + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/MessageUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/MessageUtils.java new file mode 100644 index 0000000..e40b977 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/MessageUtils.java @@ -0,0 +1,153 @@ +package net.aminecraftdev.custombosses.innerapi.message; + +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by charl on 28-Apr-17. + */ +public class MessageUtils { + + private final static int CENTER_PX = 154; + private final static int MAX_PX = 250; + + public static final int getMaxPixel() { + return MAX_PX; + } + + public static final List getCenteredMessage(String message) { + if(message == null || message.equals("")) return new ArrayList<>(); + List arrayList = new ArrayList<>(); + + message = translateString(message); + + int messagePxSize = 0; + boolean previousCode = false; + boolean isBold = false; + int charIndex = 0; + int lastSpaceIndex = 0; + String toSendAfter = null; + String recentColorCode = ""; + + for(char c : message.toCharArray()) { + if(c == '§') { + previousCode = true; + continue; + } else if(previousCode) { + previousCode = false; + + if(c == 'l' || c == 'L') { + isBold = true; + continue; + } else { + isBold = false; + } + } else if(c == ' ') { + lastSpaceIndex = charIndex; + } else { + DefaultFontInfo dFI = DefaultFontInfo.getDefaultFontInfo(c); + + messagePxSize += isBold ? dFI.getBoldLength() : dFI.getLength(); + messagePxSize++; + } + + if(messagePxSize >= MAX_PX) { + toSendAfter = recentColorCode + message.substring(lastSpaceIndex + 1, message.length()); + message = message.substring(0, lastSpaceIndex + 1); + break; + } + + charIndex++; + } + + int halvedMessageSize = messagePxSize / 2; + int toCompensate = CENTER_PX - halvedMessageSize; + int spaceLength = DefaultFontInfo.SPACE.getLength() + 1; + int compensated = 0; + StringBuilder stringBuilder = new StringBuilder(); + + while (compensated < toCompensate) { + stringBuilder.append(" "); + compensated += spaceLength; + } + + String s = stringBuilder.toString() + message; + arrayList.add(s); + + if(toSendAfter != null) { + return null; + } + + return arrayList; + } + + public static final void sendCenteredMessage(CommandSender player, String message) { + if(message == null || message.equals("")) player.sendMessage(""); + + message = translateString(message); + + int messagePxSize = 0; + boolean previousCode = false; + boolean isBold = false; + int charIndex = 0; + int lastSpaceIndex = 0; + String toSendAfter = null; + String recentColorCode = ""; + + for(char c : message.toCharArray()) { + if(c == '§') { + previousCode = true; + continue; + } else if(previousCode) { + previousCode = false; + + if(c == 'l' || c == 'L') { + isBold = true; + continue; + } else { + isBold = false; + } + } else if(c == ' ') { + lastSpaceIndex = charIndex; + } else { + DefaultFontInfo dFI = DefaultFontInfo.getDefaultFontInfo(c); + + messagePxSize += isBold ? dFI.getBoldLength() : dFI.getLength(); + messagePxSize++; + } + + if(messagePxSize >= MAX_PX) { + toSendAfter = recentColorCode + message.substring(lastSpaceIndex + 1, message.length()); + message = message.substring(0, lastSpaceIndex + 1); + break; + } + + charIndex++; + } + + int halvedMessageSize = messagePxSize / 2; + int toCompensate = CENTER_PX - halvedMessageSize; + int spaceLength = DefaultFontInfo.SPACE.getLength() + 1; + int compensated = 0; + StringBuilder stringBuilder = new StringBuilder(); + + while (compensated < toCompensate) { + stringBuilder.append(" "); + compensated += spaceLength; + } + + player.sendMessage(stringBuilder.toString() + message); + + if(toSendAfter != null) { + sendCenteredMessage(player, toSendAfter); + } + } + + public static final String translateString(String message) { + return ChatColor.translateAlternateColorCodes('&', message); + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/RomanNumber.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/RomanNumber.java new file mode 100644 index 0000000..bae3c27 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/message/RomanNumber.java @@ -0,0 +1,38 @@ +package net.aminecraftdev.custombosses.innerapi.message; + +import java.util.TreeMap; + +/** + * Created by charl on 07-May-17. + */ +public class RomanNumber { + + private final static TreeMap map = new TreeMap(); + + static { + + map.put(1000, "M"); + map.put(900, "CM"); + map.put(500, "D"); + map.put(400, "CD"); + map.put(100, "C"); + map.put(90, "XC"); + map.put(50, "L"); + map.put(40, "XL"); + map.put(10, "X"); + map.put(9, "IX"); + map.put(5, "V"); + map.put(4, "IV"); + map.put(1, "I"); + + } + + public final static String toRoman(int number) { + int l = map.floorKey(number); + if ( number == l ) { + return map.get(number); + } + return map.get(l) + toRoman(number-l); + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ColoredParticle.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ColoredParticle.java new file mode 100644 index 0000000..3214a33 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ColoredParticle.java @@ -0,0 +1,20 @@ +package net.aminecraftdev.custombosses.innerapi.particles; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.List; + +/** + * Created by LukeBingham on 22/03/2017. + */ +public final class ColoredParticle { + + public static void send(ParticleEffect effect, Location location, List players, int r, int g, int b) { + effect.display(r / 255, g / 255, b / 255, 1, 0, location, players); + } + + public static void send(ParticleEffect effect, Location location, int Distance, int r, int g, int b) { + effect.display(r / 255, g / 255, b / 255, 1, 0, location, Distance); + } +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ParticleEffect.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ParticleEffect.java new file mode 100644 index 0000000..4e716bf --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ParticleEffect.java @@ -0,0 +1,1499 @@ +package net.aminecraftdev.custombosses.innerapi.particles; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * particle Library + *

+ * This library was created by @DarkBlade12 and allows you to display all Minecraft particle effects on a Bukkit server + *

+ * You are welcome to use it, modify it and redistribute it under the following conditions: + *

    + *
  • Don't claim this class as your own + *
  • Don't remove this disclaimer + *
+ *

+ * Special thanks: + *

    + *
  • @microgeek (original idea, names and packet parameters) + *
  • @ShadyPotato (1.8 names, ids and packet parameters) + *
  • @RingOfStorms (specific particle direction) + *
+ *

+ * It would be nice if you provide credit to me if you use this class in a published project + * + * @author DarkBlade12 + * @version 1.6 + */ +public enum ParticleEffect { + + /** + * A particle effect which is displayed by exploding tnt and creepers: + *

    + *
  • It looks like a white cloud + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + EXPLOSION_NORMAL("explode", 0, -1), + /** + * A particle effect which is displayed by exploding ghast fireballs and wither skulls: + *
    + *
  • It looks like a gray ball which is fading away + *
  • The speed value slightly influences the size of this particle effect + *
+ */ + EXPLOSION_LARGE("largeexplode", 1, -1), + /** + * A particle effect which is displayed by exploding tnt and creepers: + *
    + *
  • It looks like a crowd of gray balls which are fading away + *
  • The speed value has no influence on this particle effect + *
+ */ + EXPLOSION_HUGE("hugeexplosion", 2, -1), + /** + * A particle effect which is displayed by launching fireworks: + *
    + *
  • It looks like a white star which is sparkling + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + FIREWORKS_SPARK("fireworksSpark", 3, -1), + /** + * A particle effect which is displayed by swimming entities and arrows in water: + *
    + *
  • It looks like a bubble + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + WATER_BUBBLE("bubble", 4, -1, false, true), + /** + * A particle effect which is displayed by swimming entities and shaking wolves: + *
    + *
  • It looks like a blue drop + *
  • The speed value has no influence on this particle effect + *
+ */ + WATER_SPLASH("splash", 5, -1), + /** + * A particle effect which is displayed on water when fishing: + *
    + *
  • It looks like a blue droplet + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + WATER_WAKE("wake", 6, 7), + /** + * A particle effect which is displayed by water: + *
    + *
  • It looks like a tiny blue square + *
  • The speed value has no influence on this particle effect + *
+ */ + SUSPENDED("suspended", 7, -1, false, true), + /** + * A particle effect which is displayed by air when close to bedrock and the in the void: + *
    + *
  • It looks like a tiny gray square + *
  • The speed value has no influence on this particle effect + *
+ */ + SUSPENDED_DEPTH("depthSuspend", 8, -1), + /** + * A particle effect which is displayed when landing a critical hit and by arrows: + *
    + *
  • It looks like a light brown cross + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + CRIT("crit", 9, -1), + /** + * A particle effect which is displayed when landing a hit with an enchanted weapons: + *
    + *
  • It looks like a cyan star + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + CRIT_MAGIC("magicCrit", 10, -1), + /** + * A particle effect which is displayed by primed tnt, torches, droppers, dispensers, end portals, brewing stands and monster spawners: + *
    + *
  • It looks like a little gray cloud + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + SMOKE_NORMAL("smoke", 11, -1), + /** + * A particle effect which is displayed by fire, minecarts with furnace and blazes: + *
    + *
  • It looks like a large gray cloud + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + SMOKE_LARGE("largesmoke", 12, -1), + /** + * A particle effect which is displayed when splash potions or bottles o' enchanting hit something: + *
    + *
  • It looks like a white swirl + *
  • The speed value causes the particle to only move upwards when set to 0 + *
+ */ + SPELL("spell", 13, -1), + /** + * A particle effect which is displayed when instant splash potions hit something: + *
    + *
  • It looks like a white cross + *
  • The speed value causes the particle to only move upwards when set to 0 + *
+ */ + SPELL_INSTANT("instantSpell", 14, -1), + /** + * A particle effect which is displayed by entities with active potion effects: + *
    + *
  • It looks like a colored swirl + *
  • The speed value causes the particle to be colored black when set to 0 + *
  • The particle color gets lighter when increasing the speed and darker when decreasing the speed + *
+ */ + SPELL_MOB("mobSpell", 15, -1), + /** + * A particle effect which is displayed by entities with active potion effects applied through a beacon: + *
    + *
  • It looks like a transparent colored swirl + *
  • The speed value causes the particle to be always colored black when set to 0 + *
  • The particle color gets lighter when increasing the speed and darker when decreasing the speed + *
+ */ + SPELL_MOB_AMBIENT("mobSpellAmbient", 16, -1), + /** + * A particle effect which is displayed by witches: + *
    + *
  • It looks like a purple cross + *
  • The speed value causes the particle to only move upwards when set to 0 + *
+ */ + SPELL_WITCH("witchMagic", 17, -1), + /** + * A particle effect which is displayed by blocks beneath a water source: + *
    + *
  • It looks like a blue drip + *
  • The speed value has no influence on this particle effect + *
+ */ + DRIP_WATER("dripWater", 18, -1), + /** + * A particle effect which is displayed by blocks beneath a lava source: + *
    + *
  • It looks like an orange drip + *
  • The speed value has no influence on this particle effect + *
+ */ + DRIP_LAVA("dripLava", 19, -1), + /** + * A particle effect which is displayed when attacking a villager in a village: + *
    + *
  • It looks like a cracked gray heart + *
  • The speed value has no influence on this particle effect + *
+ */ + VILLAGER_ANGRY("angryVillager", 20, -1), + /** + * A particle effect which is displayed when using bone meal and trading with a villager in a village: + *
    + *
  • It looks like a green star + *
  • The speed value has no influence on this particle effect + *
+ */ + VILLAGER_HAPPY("happyVillager", 21, -1), + /** + * A particle effect which is displayed by mycelium: + *
    + *
  • It looks like a tiny gray square + *
  • The speed value has no influence on this particle effect + *
+ */ + TOWN_AURA("townaura", 22, -1), + /** + * A particle effect which is displayed by note blocks: + *
    + *
  • It looks like a colored note + *
  • The speed value causes the particle to be colored green when set to 0 + *
+ */ + NOTE("note", 23, -1), + /** + * A particle effect which is displayed by nether portals, endermen, ender pearls, eyes of ender, ender chests and dragon eggs: + *
    + *
  • It looks like a purple cloud + *
  • The speed value influences the spread of this particle effect + *
+ */ + PORTAL("portal", 24, -1), + /** + * A particle effect which is displayed by enchantment tables which are nearby bookshelves: + *
    + *
  • It looks like a cryptic white letter + *
  • The speed value influences the spread of this particle effect + *
+ */ + ENCHANTMENT_TABLE("enchantmenttable", 25, -1), + /** + * A particle effect which is displayed by torches, active furnaces, magma cubes and monster spawners: + *
    + *
  • It looks like a tiny flame + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + FLAME("flame", 26, -1), + /** + * A particle effect which is displayed by lava: + *
    + *
  • It looks like a spark + *
  • The speed value has no influence on this particle effect + *
+ */ + LAVA("lava", 27, -1), + /** + * A particle effect which is currently unused: + *
    + *
  • It looks like a transparent gray square + *
  • The speed value has no influence on this particle effect + *
+ */ + FOOTSTEP("footstep", 28, -1), + /** + * A particle effect which is displayed when a mob dies: + *
    + *
  • It looks like a large white cloud + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + CLOUD("cloud", 29, -1), + /** + * A particle effect which is displayed by redstone ore, powered redstone, redstone torches and redstone repeaters: + *
    + *
  • It looks like a tiny colored cloud + *
  • The speed value causes the particle to be colored red when set to 0 + *
+ */ + REDSTONE("reddust", 30, -1), + /** + * A particle effect which is displayed when snowballs hit a block: + *
    + *
  • It looks like a little piece with the snowball texture + *
  • The speed value has no influence on this particle effect + *
+ */ + SNOWBALL("snowballpoof", 31, -1), + /** + * A particle effect which is currently unused: + *
    + *
  • It looks like a tiny white cloud + *
  • The speed value influences the velocity at which the particle flies off + *
+ */ + SNOW_SHOVEL("snowshovel", 32, -1), + /** + * A particle effect which is displayed by slimes: + *
    + *
  • It looks like a tiny part of the slimeball icon + *
  • The speed value has no influence on this particle effect + *
+ */ + SLIME("slime", 33, -1), + /** + * A particle effect which is displayed when breeding and taming animals: + *
    + *
  • It looks like a red heart + *
  • The speed value has no influence on this particle effect + *
+ */ + HEART("heart", 34, -1), + /** + * A particle effect which is displayed by barriers: + *
    + *
  • It looks like a red box with a slash through it + *
  • The speed value has no influence on this particle effect + *
+ */ + BARRIER("barrier", 35, 8), + /** + * A particle effect which is displayed when breaking a tool or eggs hit a block: + *
    + *
  • It looks like a little piece with an item texture + *
+ */ + ITEM_CRACK("iconcrack", 36, -1, true), + /** + * A particle effect which is displayed when breaking blocks or sprinting: + *
    + *
  • It looks like a little piece with a block texture + *
  • The speed value has no influence on this particle effect + *
+ */ + BLOCK_CRACK("blockcrack", 37, -1, true), + /** + * A particle effect which is displayed when falling: + *
    + *
  • It looks like a little piece with a block texture + *
+ */ + BLOCK_DUST("blockdust", 38, 7, true), + /** + * A particle effect which is displayed when rain hits the ground: + *
    + *
  • It looks like a blue droplet + *
  • The speed value has no influence on this particle effect + *
+ */ + WATER_DROP("droplet", 39, 8), + /** + * A particle effect which is currently unused: + *
    + *
  • It has no visual effect + *
+ */ + ITEM_TAKE("take", 40, 8), + /** + * A particle effect which is displayed by elder guardians: + *
    + *
  • It looks like the shape of the elder guardian + *
  • The speed value has no influence on this particle effect + *
+ */ + MOB_APPEARANCE("mobappearance", 41, 8), + DRAGON_BREATH("dragonbreath", 42, 9), + END_ROD("endRod", 43, 9), + DAMAGE_INDICATOR("damageIndicator", 44, 9), + SWEEP_ATTACK("sweepAttack", 45, 9), + FALLING_DUST("fallingdust", 46, 10, true), + TOTEM("totem", 47, 11), + SPIT("spit", 48, 11); + + private static final int LONG_DISTANCE = 16; + private static final int LONG_DISTANCE_SQUARED = LONG_DISTANCE * LONG_DISTANCE; + private static final Map NAME_MAP = new HashMap(); + private static final Map ID_MAP = new HashMap(); + private final String name; + private final int id; + private final int requiredVersion; + private final boolean requiresData; + private final boolean requiresWater; + + // Initialize map for quick name and id lookup + static { + for (ParticleEffect effect : values()) { + NAME_MAP.put(effect.name, effect); + ID_MAP.put(effect.id, effect); + } + } + + /** + * Construct a new particle effect + * + * @param name Name of this particle effect + * @param id Id of this particle effect + * @param requiredVersion Version which is required (1.x) + * @param requiresData Indicates whether additional data is required for this particle effect + * @param requiresWater Indicates whether water is required for this particle effect to display properly + */ + private ParticleEffect(String name, int id, int requiredVersion, boolean requiresData, boolean requiresWater) { + this.name = name; + this.id = id; + this.requiredVersion = requiredVersion; + this.requiresData = requiresData; + this.requiresWater = requiresWater; + } + + /** + * Construct a new particle effect with {@link #requiresWater} set to false + * + * @param name Name of this particle effect + * @param id Id of this particle effect + * @param requiredVersion Version which is required (1.x) + * @param requiresData Indicates whether additional data is required for this particle effect + */ + private ParticleEffect(String name, int id, int requiredVersion, boolean requiresData) { + this(name, id, requiredVersion, requiresData, false); + } + + /** + * Construct a new particle effect with {@link #requiresData} and {@link #requiresWater} set to false + * + * @param name Name of this particle effect + * @param id Id of this particle effect + * @param requiredVersion Version which is required (1.x) + */ + private ParticleEffect(String name, int id, int requiredVersion) { + this(name, id, requiredVersion, false); + } + + /** + * Returns the name of this particle effect + * + * @return The name + */ + public String getName() { + return name; + } + + /** + * Returns the id of this particle effect + * + * @return The id + */ + public int getId() { + return id; + } + + /** + * Returns the required version for this particle effect (1.x) + * + * @return The required version + */ + public int getRequiredVersion() { + return requiredVersion; + } + + /** + * Determine if additional data is required for this particle effect + * + * @return Whether additional data is required or not + */ + public boolean getRequiresData() { + return requiresData; + } + + /** + * Determine if water is required for this particle effect to display properly + * + * @return Whether water is required or not + */ + public boolean getRequiresWater() { + return requiresWater; + } + + /** + * Determine if this particle effect is supported by your current server version + * + * @return Whether the particle effect is supported or not + */ + public boolean isSupported() { + if (requiredVersion == -1) { + return true; + } + return ParticlePacket.getVersion() >= requiredVersion; + } + + /** + * Returns the particle effect with the given name + * + * @param name Name of the particle effect + * @return The particle effect + */ + public static ParticleEffect fromName(String name) { + for (Entry entry : NAME_MAP.entrySet()) { + if (!entry.getKey().equalsIgnoreCase(name)) { + continue; + } + return entry.getValue(); + } + return null; + } + + /** + * Returns the particle effect with the given id + * + * @param id Id of the particle effect + * @return The particle effect + */ + public static ParticleEffect fromId(int id) { + for (Entry entry : ID_MAP.entrySet()) { + if (entry.getKey() != id) { + continue; + } + return entry.getValue(); + } + return null; + } + + /** + * Determine if water is at a certain location + * + * @param location Location to check + * @return Whether water is at this location or not + */ + private static boolean isWater(Location location) { + Material material = location.getBlock().getType(); + return material == Material.WATER || material == Material.STATIONARY_WATER; + } + + /** + * Determine if the distance between @param location and one of the players exceeds LONG_DISTANCE + * + * @param location Location to check + * @return Whether the distance exceeds 16 or not + */ + private static boolean isLongDistance(Location location, List players) { + for (Player player : players) { + if (player.getLocation().distanceSquared(location) > LONG_DISTANCE_SQUARED) { + return true; + } + } + return false; + } + + /** + * Determine if the data type for a particle effect is correct + * + * @param effect Particle effect + * @param data Particle data + * @return Whether the data type is correct or not + */ + private static boolean isDataCorrect(ParticleEffect effect, ParticleData data) { + return ((effect == BLOCK_CRACK || effect == BLOCK_DUST || effect == FALLING_DUST) && data instanceof BlockData) || effect == ITEM_CRACK && data instanceof ItemData; + } + + /** + * Displays a particle effect which is only visible for all players within a certain range in the world of @param center + * + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) + throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("The " + this + " particle effect is not supported by your server version " + ParticlePacket.getVersion()); + } + if (requiresData) { + throw new ParticleDataException("The " + this + " particle effect requires additional data"); + } + if (requiresWater && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > 16, null).sendTo(center, range); + } + + /** + * Displays a particle effect which is only visible for the specified players + * + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) + throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("The " + this + " particle effect is not supported by your server version " + ParticlePacket.getVersion()); + } + if (requiresData) { + throw new ParticleDataException("The " + this + " particle effect requires additional data"); + } + if (requiresWater && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), null).sendTo(center, players); + } + + /** + * Displays a particle effect which is only visible for the specified players + * + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see #display(float, float, float, float, int, Location, List) + */ + public void display(float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) + throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + display(offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); + } + + /** + * Displays a single particle which flies into a determined direction and is only visible for all players within a certain range in the world of @param center + * + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(Vector direction, float speed, Location center, double range) + throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("The " + this + " particle effect is not supported by your server version " + ParticlePacket.getVersion()); + } + if (requiresData) { + throw new ParticleDataException("The " + this + " particle effect requires additional data"); + } + if (requiresWater && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, direction, speed, range > LONG_DISTANCE, null).sendTo(center, range); + } + + /** + * Displays a single particle which flies into a determined direction and is only visible for the specified players + * + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(Vector direction, float speed, Location center, List players) + throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + if (!isSupported()) { + throw new ParticleVersionException("The " + this + " particle effect is not supported by your server version " + ParticlePacket.getVersion()); + } + if (requiresData) { + throw new ParticleDataException("The " + this + " particle effect requires additional data"); + } + if (requiresWater && !isWater(center)) { + throw new IllegalArgumentException("There is no water at the center location"); + } + new ParticlePacket(this, direction, speed, isLongDistance(center, players), null).sendTo(center, players); + } + + /** + * Displays a single particle which flies into a determined direction and is only visible for the specified players + * + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect requires additional data + * @throws IllegalArgumentException If the particle effect requires water and none is at the center location + * @see #display(Vector, float, Location, List) + */ + public void display(Vector direction, float speed, Location center, Player... players) + throws ParticleVersionException, ParticleDataException, IllegalArgumentException { + display(direction, speed, center, Arrays.asList(players)); + } + + /** + * Displays a particle effect which requires additional data and is only visible for all players within a certain range in the world of @param center + * + * @param data Data of the effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, double range) + throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("The " + this + " particle effect is not supported by your server version " + ParticlePacket.getVersion()); + } + if (!requiresData) { + throw new ParticleDataException("The " + this + " particle effect does not require additional data"); + } + // Just skip it if there's no data, rather than throwing an exception + if (data == null) + return; + + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect: " + data + " for " + this); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, range > LONG_DISTANCE, data).sendTo(center, range); + } + + /** + * Displays a particle effect which requires additional data and is only visible for the specified players + * + * @param data Data of the effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, List players) + throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("The " + this + " particle effect is not supported by your server version " + ParticlePacket.getVersion()); + } + if (!requiresData) { + throw new ParticleDataException("The " + this + " particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect: " + data + " for " + this); + } + new ParticlePacket(this, offsetX, offsetY, offsetZ, speed, amount, isLongDistance(center, players), data).sendTo(center, players); + } + + /** + * Displays a particle effect which requires additional data and is only visible for the specified players + * + * @param data Data of the effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see #display(ParticleData, float, float, float, float, int, Location, List) + */ + public void display(ParticleData data, float offsetX, float offsetY, float offsetZ, float speed, int amount, Location center, Player... players) + throws ParticleVersionException, ParticleDataException { + display(data, offsetX, offsetY, offsetZ, speed, amount, center, Arrays.asList(players)); + } + + /** + * Displays a single particle which requires additional data that flies into a determined direction and is only visible for all players within a certain range in the world of @param center + * + * @param data Data of the effect + * @param direction Direction of the particle + * @param speed Display speed of the particles + * @param center Center location of the effect + * @param range Range of the visibility + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, double) + */ + public void display(ParticleData data, Vector direction, float speed, Location center, double range) + throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("The " + this + " particle effect is not supported by your server version " + ParticlePacket.getVersion()); + } + if (!requiresData) { + throw new ParticleDataException("The " + this + " particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect: " + data + " for " + this); + } + new ParticlePacket(this, direction, speed, range > LONG_DISTANCE, data).sendTo(center, range); + } + + /** + * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players + * + * @param data Data of the effect + * @param direction Direction of the particle + * @param speed Display speed of the particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see ParticlePacket + * @see ParticlePacket#sendTo(Location, List) + */ + public void display(ParticleData data, Vector direction, float speed, Location center, List players) + throws ParticleVersionException, ParticleDataException { + if (!isSupported()) { + throw new ParticleVersionException("The " + this + " particle effect is not supported by your server version " + ParticlePacket.getVersion()); + } + if (!requiresData) { + throw new ParticleDataException("The " + this + " particle effect does not require additional data"); + } + if (!isDataCorrect(this, data)) { + throw new ParticleDataException("The particle data type is incorrect: " + data + " for " + this); + } + new ParticlePacket(this, direction, speed, isLongDistance(center, players), data).sendTo(center, players); + } + + /** + * Displays a single particle which requires additional data that flies into a determined direction and is only visible for the specified players + * + * @param data Data of the effect + * @param direction Direction of the particle + * @param speed Display speed of the particles + * @param center Center location of the effect + * @param players Receivers of the effect + * @throws ParticleVersionException If the particle effect is not supported by the server version + * @throws ParticleDataException If the particle effect does not require additional data or if the data type is incorrect + * @see #display(ParticleData, Vector, float, Location, List) + */ + public void display(ParticleData data, Vector direction, float speed, Location center, Player... players) + throws ParticleVersionException, ParticleDataException { + display(data, direction, speed, center, Arrays.asList(players)); + } + + /** + * Represents the particle data for effects like {@link ParticleEffect#ITEM_CRACK}, {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} + *

+ * This class is part of the particle Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + public static abstract class ParticleData { + + private final Material material; + private final byte data; + private final int[] packetData; + + /** + * Construct a new particle data + * + * @param material Material of the item/block + * @param data Data value of the item/block + */ + @SuppressWarnings("deprecation") + public ParticleData(Material material, byte data) { + this.material = material; + this.data = data; + this.packetData = new int[] { (data << 12) | (material.getId() & 4095) }; + } + + @SuppressWarnings("deprecation") + public ParticleData(Material material, byte data, int[] packetData) { + this.material = material; + this.data = data; + this.packetData = packetData; + } + + /** + * Returns the material of this data + * + * @return The material + */ + public Material getMaterial() { + return material; + } + + /** + * Returns the data value of this data + * + * @return The data value + */ + public byte getData() { + return data; + } + + /** + * Returns the data as an int array for packet construction + * + * @return The data for the packet + */ + public int[] getPacketData() { + return packetData; + } + + /** + * Returns the data as a string for pre 1.8 versions + * + * @return The data string for the packet + */ + public String getPacketDataString() { + if (packetData.length >= 2) + return "_" + packetData[0] + "_" + packetData[1]; + ; + if (packetData.length == 1) + return "_" + packetData[0]; + return ""; + } + } + + /** + * Represents the item data for the {@link ParticleEffect#ITEM_CRACK} effect + *

+ * This class is part of the particle Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + public static final class ItemData extends ParticleData { + + /** + * Construct a new item data + * + * @param material Material of the item + * @param data Data value of the item + * @see ParticleData#ParticleData(Material, byte, int[]) + */ + @SuppressWarnings("deprecation") + public ItemData(Material material, byte data) { + super(material, data, new int[] { material.getId(), data }); + } + } + + /** + * Represents the block data for the {@link ParticleEffect#BLOCK_CRACK} and {@link ParticleEffect#BLOCK_DUST} effects + *

+ * This class is part of the particle Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + public static final class BlockData extends ParticleData { + + /** + * Construct a new block data + * + * @param material Material of the block + * @param data Data value of the block + * @throws IllegalArgumentException If the material is not a block + * @see ParticleData#ParticleData(Material, byte) + */ + public BlockData(Material material, byte data) throws IllegalArgumentException { + super(material, data); + if (!material.isBlock()) { + throw new IllegalArgumentException("The material is not a block"); + } + } + } + + /** + * Represents a runtime exception that is thrown either if the displayed particle effect requires data and has none or vice-versa or if the data type is wrong + *

+ * This class is part of the particle Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + private static final class ParticleDataException extends RuntimeException { + + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new particle data exception + * + * @param message Message that will be logged + */ + public ParticleDataException(String message) { + super(message); + } + } + + /** + * Represents a runtime exception that is thrown if the displayed particle effect requires a newer version + *

+ * This class is part of the particle Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.6 + */ + private static final class ParticleVersionException extends RuntimeException { + + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new particle version exception + * + * @param message Message that will be logged + */ + public ParticleVersionException(String message) { + super(message); + } + } + + /** + * Represents a particle effect packet with all attributes which is used for sending packets to the players + *

+ * This class is part of the particle Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.5 + */ + public static final class ParticlePacket { + + private static int version; + private static boolean isKcauldron; + private static final int[] emptyData = new int[0]; + private static Object[] enumParticles; + private static Class enumParticle; + private static Constructor packetConstructor; + private static Field packet_idField; + private static Field packet_locationXField; + private static Field packet_locationYField; + private static Field packet_locationZField; + private static Field packet_offsetXField; + private static Field packet_offsetYField; + private static Field packet_offsetZField; + private static Field packet_speedField; + private static Field packet_amountField; + private static Field packet_longDistanceField; + private static Field packet_dataField; + private static Method getHandle; + private static Field playerConnection; + private static Method sendPacket; + private static boolean initialized; + private final ParticleEffect effect; + private final float offsetX; + private final float offsetY; + private final float offsetZ; + private final float speed; + private final int amount; + private final boolean longDistance; + private final ParticleData data; + private Object packet; + + /** + * Construct a new particle packet + * + * @param effect Particle effect + * @param offsetX Maximum distance particles can fly away from the center on the x-axis + * @param offsetY Maximum distance particles can fly away from the center on the y-axis + * @param offsetZ Maximum distance particles can fly away from the center on the z-axis + * @param speed Display speed of the particles + * @param amount Amount of particles + * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 + * @param data Data of the effect + * @throws IllegalArgumentException If the speed is lower than 0 or the amount is lower than 1 + * @see #initialize() + */ + public ParticlePacket(ParticleEffect effect, float offsetX, float offsetY, float offsetZ, float speed, int amount, boolean longDistance, ParticleData data) + throws IllegalArgumentException { + initialize(); + if (speed < 0) { + throw new IllegalArgumentException("The speed is lower than 0"); + } + if (amount < 0) { + throw new IllegalArgumentException("The amount is lower than 0"); + } + this.effect = effect; + this.offsetX = offsetX; + this.offsetY = offsetY; + this.offsetZ = offsetZ; + this.speed = speed; + this.amount = amount; + this.longDistance = longDistance; + this.data = data; + } + + /** + * Construct a new particle packet of a single particle flying into a determined direction + * + * @param effect Particle effect + * @param direction Direction of the particle + * @param speed Display speed of the particle + * @param longDistance Indicates whether the maximum distance is increased from 256 to 65536 + * @param data Data of the effect + * @throws IllegalArgumentException If the speed is lower than 0 + * @see #initialize() + */ + public ParticlePacket(ParticleEffect effect, Vector direction, float speed, boolean longDistance, ParticleData data) + throws IllegalArgumentException { + initialize(); + if (speed < 0) { + throw new IllegalArgumentException("The speed is lower than 0"); + } + this.effect = effect; + this.offsetX = (float) direction.getX(); + this.offsetY = (float) direction.getY(); + this.offsetZ = (float) direction.getZ(); + this.speed = speed; + this.amount = 0; + this.longDistance = longDistance; + this.data = data; + } + + /** + * Initializes {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} and sets {@link #initialized} to true if it succeeds + *

+ * Note: These fields only have to be initialized once, so it will return if {@link #initialized} is already set to true + * + * @throws VersionIncompatibleException if your bukkit version is not supported by this library + */ + public static void initialize() throws VersionIncompatibleException { + if (initialized) { + return; + } + try { + //Try and enable effect lib for bukkit + isKcauldron = false; + String[] pieces = StringUtils.split(ReflectionUtils.PackageType.getServerVersion(), "_"); + version = Integer.parseInt(pieces[1]); + if (version > 7) { + enumParticle = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("EnumParticle"); + enumParticles = enumParticle.getEnumConstants(); + } + Class packetClass = ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass(version < 7 ? "Packet63WorldParticles" : "PacketPlayOutWorldParticles"); + packetConstructor = ReflectionUtils.getConstructor(packetClass); + getHandle = ReflectionUtils.getMethod("CraftPlayer", ReflectionUtils.PackageType.CRAFTBUKKIT_ENTITY, "getHandle"); + playerConnection = ReflectionUtils.getField("EntityPlayer", ReflectionUtils.PackageType.MINECRAFT_SERVER, false, "playerConnection"); + sendPacket = ReflectionUtils.getMethod(playerConnection.getType(), "sendPacket", ReflectionUtils.PackageType.MINECRAFT_SERVER.getClass("Packet")); + + packet_idField = ReflectionUtils.getField(packetClass, true, "a"); + packet_locationXField = ReflectionUtils.getField(packetClass, true, "b"); + packet_locationYField = ReflectionUtils.getField(packetClass, true, "c"); + packet_locationZField = ReflectionUtils.getField(packetClass, true, "d"); + packet_offsetXField = ReflectionUtils.getField(packetClass, true, "e"); + packet_offsetYField = ReflectionUtils.getField(packetClass, true, "f"); + packet_offsetZField = ReflectionUtils.getField(packetClass, true, "g"); + packet_speedField = ReflectionUtils.getField(packetClass, true, "h"); + packet_amountField = ReflectionUtils.getField(packetClass, true, "i"); + + if (version > 7) { + packet_longDistanceField = ReflectionUtils.getField(packetClass, true, "j"); + packet_dataField = ReflectionUtils.getField(packetClass, true, "k"); + } + } + catch (Exception exception) { + try { + //If an error occurs try and use KCauldron classes + isKcauldron = true; + Class packetClass = Class.forName("net.minecraft.network.play.server.S2APacketParticles"); + packetConstructor = ReflectionUtils.getConstructor(packetClass); + getHandle = ReflectionUtils.getMethod("CraftPlayer", ReflectionUtils.PackageType.CRAFTBUKKIT_ENTITY, "getHandle"); + playerConnection = Class.forName("net.minecraft.entity.player.EntityPlayerMP").getDeclaredField("field_71135_a"); + sendPacket = playerConnection.getType().getDeclaredMethod("func_147359_a", Class.forName("net.minecraft.network.Packet")); + + packet_idField = ReflectionUtils.getField(packetClass, true, "field_149236_a"); + packet_locationXField = ReflectionUtils.getField(packetClass, true, "field_149234_b"); + packet_locationYField = ReflectionUtils.getField(packetClass, true, "field_149235_c"); + packet_locationZField = ReflectionUtils.getField(packetClass, true, "field_149232_d"); + packet_offsetXField = ReflectionUtils.getField(packetClass, true, "field_149233_e"); + packet_offsetYField = ReflectionUtils.getField(packetClass, true, "field_149230_f"); + packet_offsetZField = ReflectionUtils.getField(packetClass, true, "field_149231_g"); + packet_speedField = ReflectionUtils.getField(packetClass, true, "field_149237_h"); + packet_amountField = ReflectionUtils.getField(packetClass, true, "field_149238_i"); + } + catch (Exception e) { + throw new VersionIncompatibleException("Your current bukkit version seems to be incompatible with this library", exception); + } + } + initialized = true; + } + + /** + * Returns the version of your server (1.x) + * + * @return The version number + */ + public static int getVersion() { + return version; + } + + /** + * Determine if {@link #packetConstructor}, {@link #getHandle}, {@link #playerConnection} and {@link #sendPacket} are initialized + * + * @return Whether these fields are initialized or not + * @see #initialize() + */ + public static boolean isInitialized() { + return initialized; + } + + /** + * Sends the packet to a single player and caches it + * + * @param center Center location of the effect + * @param player Receiver of the packet + * @throws PacketInstantiationException if instantion fails due to an unknown error + * @throws PacketSendingException if sending fails due to an unknown error + */ + public void sendTo(Location center, Player player) throws PacketInstantiationException, PacketSendingException { + if (packet == null) { + try { + packet = packetConstructor.newInstance(); + Object id; + if (version < 8) { + id = effect.getName() + (data == null ? "" : data.getPacketDataString()); + } + else { + id = enumParticles[effect.getId()]; + } + packet_idField.set(packet, id); + packet_locationXField.set(packet, (float) center.getX()); + packet_locationYField.set(packet, (float) center.getY()); + packet_locationZField.set(packet, (float) center.getZ()); + packet_offsetXField.set(packet, offsetX); + packet_offsetYField.set(packet, offsetY); + packet_offsetZField.set(packet, offsetZ); + packet_speedField.set(packet, speed); + packet_amountField.set(packet, amount); + + if (packet_longDistanceField != null) { + packet_longDistanceField.set(packet, longDistance); + } + if (packet_dataField != null) { + packet_dataField.set(packet, data == null ? emptyData : data.getPacketData()); + } + } + catch (Exception exception) { + throw new PacketInstantiationException("Packet instantiation failed", exception); + } + } + try { + sendPacket.invoke(playerConnection.get(getHandle.invoke(player)), packet); + } + catch (Exception exception) { + throw new PacketSendingException("Failed to send the packet to player '" + player.getName() + "'", exception); + } + } + + /** + * Sends the packet to all players in the list + * + * @param center Center location of the effect + * @param players Receivers of the packet + * @throws IllegalArgumentException If the player list is empty + * @see #sendTo(Location center, Player player) + */ + public void sendTo(Location center, List players) throws IllegalArgumentException { + if (players.isEmpty()) { + throw new IllegalArgumentException("The player list is empty"); + } + for (Player player : players) { + sendTo(center, player); + } + } + + /** + * Sends the packet to all players in a certain range + * + * @param center Center location of the effect + * @param range Range in which players will receive the packet (Maximum range for particles is usually 16, but it can differ for some types) + * @throws IllegalArgumentException If the range is lower than 1 + * @see #sendTo(Location center, Player player) + */ + @SuppressWarnings("deprecation") + public void sendTo(Location center, double range) throws IllegalArgumentException { + if (range < 1) { + throw new IllegalArgumentException("The range is lower than 1"); + } + String worldName = center.getWorld().getName(); + double squared = range * range; + for (Player player : Bukkit.getOnlinePlayers()) { + if (!player.getWorld().getName().equals(worldName) || player.getLocation().distanceSquared(center) > squared) { + continue; + } + sendTo(center, player); + } + } + + /** + * Represents a runtime exception that is thrown if a bukkit version is not compatible with this library + *

+ * This class is part of the particle Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.5 + */ + private static final class VersionIncompatibleException extends RuntimeException { + + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new version incompatible exception + * + * @param message Message that will be logged + * @param cause Cause of the exception + */ + public VersionIncompatibleException(String message, Throwable cause) { + super(message, cause); + } + } + + /** + * Represents a runtime exception that is thrown if packet instantiation fails + *

+ * This class is part of the particle Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.4 + */ + private static final class PacketInstantiationException extends RuntimeException { + + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new packet instantiation exception + * + * @param message Message that will be logged + * @param cause Cause of the exception + */ + public PacketInstantiationException(String message, Throwable cause) { + super(message, cause); + } + } + + /** + * Represents a runtime exception that is thrown if packet sending fails + *

+ * This class is part of the particle Library and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.4 + */ + private static final class PacketSendingException extends RuntimeException { + + private static final long serialVersionUID = 3203085387160737484L; + + /** + * Construct a new packet sending exception + * + * @param message Message that will be logged + * @param cause Cause of the exception + */ + public PacketSendingException(String message, Throwable cause) { + super(message, cause); + } + } + + } + + /** + * Helper method to migrate pre-3.0 Effects. + * + * @param center + * @param range + * @param offsetX + * @param offsetY + * @param offsetZ + * @param speed + * @param amount + */ + @Deprecated + public void display(Location center, double range, float offsetX, float offsetY, float offsetZ, float speed, int amount) { + display(offsetX, offsetY, offsetZ, speed, amount, center, range); + } + + /** + * Helper method to migrate pre-3.0 Effects. + * + * @param center + * @param range + */ + @Deprecated + public void display(Location center, double range) { + display(0, 0, 0, 0, 1, center, range); + } + + /** + * Helper method to migrate pre-3.0 Effects, and bridge parameterized effects. + * + * @param data + * @param center + * @param range + * @param offsetX + * @param offsetY + * @param offsetZ + * @param speed + * @param amount + */ + @Deprecated + public void display(ParticleData data, Location center, double range, float offsetX, float offsetY, float offsetZ, float speed, int amount) { + if (this.requiresData) { + display(data, offsetX, offsetY, offsetZ, speed, amount, center, range); + } + else { + display(offsetX, offsetY, offsetZ, speed, amount, center, range); + } + } + + public void display(Location center, Color color, double range) { + display(null, center, color, range, 0, 0, 0, 1, 0); + } + + public void display(ParticleData data, Location center, Color color, double range, float offsetX, float offsetY, float offsetZ, float speed, int amount) { + // Colorizeable! + if (color != null && (this == ParticleEffect.REDSTONE || this == ParticleEffect.SPELL_MOB || this == ParticleEffect.SPELL_MOB_AMBIENT)) { + amount = 0; + // Colored particles can't have a speed of 0. + if (speed == 0) { + speed = 1; + } + offsetX = (float) color.getRed() / 255; + offsetY = (float) color.getGreen() / 255; + offsetZ = (float) color.getBlue() / 255; + + // The redstone particle reverts to red if R is 0! + if (offsetX < Float.MIN_NORMAL) { + offsetX = Float.MIN_NORMAL; + } + } + + if (this.requiresData) { + display(data, offsetX, offsetY, offsetZ, speed, amount, center, range); + } + else { + display(offsetX, offsetY, offsetZ, speed, amount, center, range); + } + } + + public boolean requiresData() { + return requiresData; + } + + public boolean requiresWater() { + return requiresWater; + } + + public ParticleData getData(Material material, Byte blockData) { + ParticleData data = null; + if (blockData == null) { + blockData = 0; + } + if (this == ParticleEffect.BLOCK_CRACK || this == ParticleEffect.ITEM_CRACK || this == ParticleEffect.BLOCK_DUST || this == ParticleEffect.FALLING_DUST) { + if (material != null && material != Material.AIR) { + if (this == ParticleEffect.ITEM_CRACK) { + data = new ItemData(material, blockData); + } + else { + data = new BlockData(material, blockData); + } + } + } + + return data; + } +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ReflectionUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ReflectionUtils.java new file mode 100644 index 0000000..a34bb53 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/particles/ReflectionUtils.java @@ -0,0 +1,607 @@ +package net.aminecraftdev.custombosses.innerapi.particles; + +import org.bukkit.Bukkit; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * ReflectionUtils + *

+ * This class provides useful methods which makes dealing with reflection much easier, especially when working with Bukkit + *

+ * You are welcome to use it, modify it and redistribute it under the following conditions: + *

    + *
  • Don't claim this class as your own + *
  • Don't remove this disclaimer + *
+ *

+ * It would be nice if you provide credit to me if you use this class in a published project + * + * @author DarkBlade12 + * @version 1.1 + */ +public final class ReflectionUtils { + + // Prevent accidental construction + private ReflectionUtils() { + } + + /** + * Returns the constructor of a given class with the given parameter types + * + * @param clazz Target class + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @see DataType + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Constructor constructor : clazz.getConstructors()) { + if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) { + continue; + } + return constructor; + } + throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types"); + } + + /** + * Returns the constructor of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the desired target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getConstructor(Class, Class...) + */ + public static Constructor getConstructor(String className, PackageType packageType, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getConstructor(packageType.getClass(className), parameterTypes); + } + + /** + * Returns an instance of a class with the given arguments + * + * @param clazz Target class + * @param arguments Arguments which are used to construct an object of the target class + * @return The instance of the target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + */ + public static Object instantiateObject(Class clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments); + } + + /** + * Returns an instance of a desired class with the given arguments + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param arguments Arguments which are used to construct an object of the desired target class + * @return The instance of the desired target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #instantiateObject(Class, Object...) + */ + public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return instantiateObject(packageType.getClass(className), arguments); + } + + /** + * Returns a method of a class with the given parameter types + * + * @param clazz Target class + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Method method : clazz.getMethods()) { + if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) { + continue; + } + return method; + } + throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types"); + } + + /** + * Returns a method of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the desired target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getMethod(Class, String, Class...) + */ + public static Method getMethod(String className, PackageType packageType, String methodName, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getMethod(packageType.getClass(className), methodName, parameterTypes); + } + + /** + * Invokes a method on an object with the given arguments + * + * @param instance Target object + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } + + /** + * Invokes a method of the target class on an object with the given arguments + * + * @param instance Target object + * @param clazz Target class + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, Class clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } + + /** + * Invokes a method of a desired class on an object with the given arguments + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #invokeMethod(Object, Class, String, Object...) + */ + public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return invokeMethod(instance, packageType.getClass(className), methodName, arguments); + } + + /** + * Returns a field of the target class with the given name + * + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the target class with the specified name + * @throws NoSuchFieldException If the desired field of the given class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + */ + public static Field getField(Class clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException { + Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName); + field.setAccessible(true); + return field; + } + + /** + * Returns a field of a desired class with the given name + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the desired target class with the specified name + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getField(Class, boolean, String) + */ + public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException { + return getField(packageType.getClass(className), declared, fieldName); + } + + /** + * Returns the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getField(Class, boolean, String) + */ + public static Object getValue(Object instance, Class clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + return getField(clazz, declared, fieldName).get(instance); + } + + /** + * Returns the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + return getValue(instance, packageType.getClass(className), declared, fieldName); + } + + /** + * Returns the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object) + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + return getValue(instance, instance.getClass(), declared, fieldName); + } + + /** + * Sets the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getField(Class, boolean, String) + */ + public static void setValue(Object instance, Class clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + getField(clazz, declared, fieldName).set(instance, value); + } + + /** + * Sets the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + setValue(instance, packageType.getClass(className), declared, fieldName, value); + } + + /** + * Sets the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + setValue(instance, instance.getClass(), declared, fieldName, value); + } + + /** + * Represents an enumeration of dynamic packages of NMS and CraftBukkit + *

+ * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum PackageType { + + MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), + CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), + CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), + CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), + CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), + CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), + CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), + CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), + CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), + CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), + CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), + CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), + CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), + CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), + CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), + CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), + CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), + CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), + CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), + CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"); + + private final String path; + + /** + * Construct a new package type + * + * @param path Path of the package + */ + private PackageType(String path) { + this.path = path; + } + + /** + * Construct a new package type + * + * @param parent Parent package of the package + * @param path Path of the package + */ + private PackageType(PackageType parent, String path) { + this(parent + "." + path); + } + + /** + * Returns the path of this package type + * + * @return The path + */ + public String getPath() { + return path; + } + + /** + * Returns the class with the given name + * + * @param className Name of the desired class + * @return The class with the specified name + * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found + */ + public Class getClass(String className) throws ClassNotFoundException { + return Class.forName(this + "." + className); + } + + // Override for convenience + @Override + public String toString() { + return path; + } + + /** + * Returns the version of your server + * + * @return The server version + */ + public static String getServerVersion() { + return Bukkit.getServer().getClass().getPackage().getName().substring(23); + } + } + + /** + * Represents an enumeration of Java data types with corresponding classes + *

+ * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum DataType { + + BYTE(byte.class, Byte.class), + SHORT(short.class, Short.class), + INTEGER(int.class, Integer.class), + LONG(long.class, Long.class), + CHARACTER(char.class, Character.class), + FLOAT(float.class, Float.class), + DOUBLE(double.class, Double.class), + BOOLEAN(boolean.class, Boolean.class); + + private static final Map, DataType> CLASS_MAP = new HashMap, DataType>(); + private final Class primitive; + private final Class reference; + + // Initialize map for quick class lookup + static { + for (DataType type : values()) { + CLASS_MAP.put(type.primitive, type); + CLASS_MAP.put(type.reference, type); + } + } + + /** + * Construct a new data type + * + * @param primitive Primitive class of this data type + * @param reference Reference class of this data type + */ + private DataType(Class primitive, Class reference) { + this.primitive = primitive; + this.reference = reference; + } + + /** + * Returns the primitive class of this data type + * + * @return The primitive class + */ + public Class getPrimitive() { + return primitive; + } + + /** + * Returns the reference class of this data type + * + * @return The reference class + */ + public Class getReference() { + return reference; + } + + /** + * Returns the data type with the given primitive/reference class + * + * @param clazz Primitive/Reference class of the data type + * @return The data type + */ + public static DataType fromClass(Class clazz) { + return CLASS_MAP.get(clazz); + } + + /** + * Returns the primitive class of the data type with the given reference class + * + * @param clazz Reference class of the data type + * @return The primitive class + */ + public static Class getPrimitive(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getPrimitive(); + } + + /** + * Returns the reference class of the data type with the given primitive class + * + * @param clazz Primitive class of the data type + * @return The reference class + */ + public static Class getReference(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getReference(); + } + + /** + * Returns the primitive class array of the given class array + * + * @param classes Given class array + * @return The primitive class array + */ + public static Class[] getPrimitive(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(classes[index]); + } + return types; + } + + /** + * Returns the reference class array of the given class array + * + * @param classes Given class array + * @return The reference class array + */ + public static Class[] getReference(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(classes[index]); + } + return types; + } + + /** + * Returns the primitive class array of the given object array + * + * @param objects Given object array + * @return The primitive class array + */ + public static Class[] getPrimitive(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(objects[index].getClass()); + } + return types; + } + + /** + * Returns the reference class array of the given object array + * + * @param objects Given object array + * @return The reference class array + */ + public static Class[] getReference(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(objects[index].getClass()); + } + return types; + } + + /** + * Compares two class arrays on equivalence + * + * @param primary Primary class array + * @param secondary Class array which is compared to the primary array + * @return Whether these arrays are equal or not + */ + public static boolean compare(Class[] primary, Class[] secondary) { + if (primary == null || secondary == null || primary.length != secondary.length) { + return false; + } + for (int index = 0; index < primary.length; index++) { + Class primaryClass = primary[index]; + Class secondaryClass = secondary[index]; + if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) { + continue; + } + return false; + } + return true; + } + } + +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ActionBarReflection.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ActionBarReflection.java new file mode 100644 index 0000000..a87e69b --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ActionBarReflection.java @@ -0,0 +1,131 @@ +package net.aminecraftdev.custombosses.innerapi.reflection; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Created by charl on 28-Apr-17. + */ +public class ActionBarReflection extends ReflectionUtils { + + private static Plugin _plugin; + private static boolean _use1_8_R1Methods = false; + private static boolean _use1_7Methods = false; + + static { + if(getAPIVersion().equalsIgnoreCase("v1_8_R1")) { + _use1_8_R1Methods = true; + } else if(getAPIVersion().startsWith("v1_7_")) { + _use1_7Methods = true; + } + } + + public static final Plugin getPlugin() { + return _plugin; + } + + public static final Object getPlayerConnection(Player player) { + try { + Class c1 = getOBCClass("entity.CraftPlayer"); + Object p = c1.cast(player); // (CraftPlayer) player; + Method m1 = c1.getDeclaredMethod("getHandle"); //CraftPlayer.getHandle(); + Object h = m1.invoke(p); // EntityPlayer h = ((CraftPlayer) player).getHandle(); + Field f1 = h.getClass().getDeclaredField("playerConnection"); + return f1.get(h); + + }catch(Exception e) { + e.printStackTrace(); + return null; + } + } + + public static final void sendActionBar(Player player, String message) { + if(player == null) { + return; + } + + if(message == null) { + return; + } + + try { + Object ppoc; + Class c4 = getNMSClass("PacketPlayOutChat"); + Class c5 = getNMSClass("Packet"); + + if(_use1_8_R1Methods || _use1_7Methods) { + Class c2 = getNMSClass("ChatSerializer"); + Class c3 = getNMSClass("IChatBaseComponent"); + Method m3 = c2.getDeclaredMethod("a", String.class); + Object cbc = c3.cast(m3.invoke(c2, "{\"text\": \"" + message + "\"}")); + + if(_use1_8_R1Methods) { + ppoc = c4.getConstructor(new Class[] {c3, byte.class}).newInstance(cbc, (byte) 2); + } else { + ppoc = c4.getConstructor(new Class[] {c3}).newInstance(cbc); + } + + Object playerConnection = getPlayerConnection(player); // PlayerConnection pc = h.playerConnection; + Method m5 = playerConnection.getClass().getDeclaredMethod("sendPacket", c5); // PlayerConnection.sendPacket(Packet packet); + + m5.invoke(playerConnection, ppoc); // pc.sendPacket(ppoc); + } else { + Class c2 = getNMSClass("ChatComponentText"); + Class c3 = getNMSClass("IChatBaseComponent"); + Object o = c2.getConstructor(new Class[] {String.class}).newInstance(message); + + ppoc = c4.getConstructor(new Class[] {c3, byte.class}).newInstance(o, (byte) 2); + + Object playerConnection = getPlayerConnection(player); // PlayerConnection pc = h.playerConnection; + Method m5 = playerConnection.getClass().getDeclaredMethod("sendPacket", c5); // PlayerConnection.sendPacket(Packet packet); + m5.invoke(playerConnection, ppoc); // pc.sendPacket(ppoc); + } + } catch(Exception e) { + e.printStackTrace(); + } + } + + public static final void sendActionBar(final Player player, final String message, int duration, Plugin plugin) { + sendActionBar(player, message); + _plugin = plugin; + + if (duration >= 0) { + // Sends empty message at the end of the duration. Allows messages shorter than 3 seconds, ensures precision. + new BukkitRunnable() { + + public void run() { + sendActionBar(player, ""); + } + }.runTaskLater(getPlugin(), duration + 1); + } + + // Re-sends the messages every 3 seconds so it doesn't go away from the player's screen. + while (duration > 60) { + duration -= 60; + int sched = duration % 60; + new BukkitRunnable() { + + public void run() { + sendActionBar(player, message); + } + }.runTaskLater(getPlugin(), (long) sched); + } + } + + public static final void sendActionBarToAllPlayers(String message, Plugin plugin) { + sendActionBarToAllPlayers(message, -1, plugin); + } + + public static final void sendActionBarToAllPlayers(String message, int duration, Plugin plugin) { + for(Player player : Bukkit.getOnlinePlayers()) { + sendActionBar(player, message, duration, plugin); + } + } + + +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ChunkReflection.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ChunkReflection.java new file mode 100644 index 0000000..cc220e7 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ChunkReflection.java @@ -0,0 +1,86 @@ +package net.aminecraftdev.custombosses.innerapi.reflection; + +import org.bukkit.Location; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Created by charl on 28-Apr-17. + */ +public class ChunkReflection extends ReflectionUtils { + + private static boolean _useOldMethods = false; + + static { + if(getAPIVersion().startsWith("v1_8_R") || getAPIVersion().startsWith("v1_7_R")) { + _useOldMethods = true; + } + } + + public static final Object getChunkProviderServer(Location location) { + try { + Class c1 = getOBCClass("CraftWorld"); + Object craftWorld = c1.cast(location.getWorld()); //(CraftWorld) location.getWorld(); + Method m1 = c1.getDeclaredMethod("getHandle"); // CraftWorld.getHandle(); + Object h1 = m1.invoke(craftWorld); // WorldServer h1 = ((CraftWorld) location.getWorld()).getHandle(); + Object h2; + + if(_useOldMethods) { + Field f1 = h1.getClass().getDeclaredField("chunkProviderServer"); // WorldServer.chunkProviderServer; + h2 = f1.get(h1); + } else { + Method m3 = h1.getClass().getDeclaredMethod("getChunkProviderServer"); // WorldServer.getChunkProviderServer(); + h2 = m3.invoke(h1); // ChunkProviderServer h2 = h1.getChunkProviderServer(); + } + + return h2; // ChunkProviderServer.class + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static final boolean isChunkLoaded(Location location) { + if(location == null) return false; + if(location.getWorld() == null) return false; + + int x = location.getBlockX() / 16; + int z = location.getBlockZ() / 16; + + try { + Class c1 = getChunkProviderServer(location).getClass(); + Method m1; + Object h1 = getChunkProviderServer(location); + + if(_useOldMethods) { + m1 = c1.getDeclaredMethod("isChunkLoaded", int.class, int.class); // ChunkProviderServer.isChunkLoaded(int.class, int.class); + } else { + m1 = c1.getDeclaredMethod("isLoaded", int.class, int.class); // ChunkProviderServer.isLoaded(int.class, int.class); + } + + return (Boolean) m1.invoke(h1, x, z); + } catch (Exception e) { + e.printStackTrace(); + return true; + } + } + + public static final void loadChunk(Location location) { + if(isChunkLoaded(location)) return; + + int x = location.getBlockX() / 16; + int z = location.getBlockZ() / 16; + + try { + Class c1 = getChunkProviderServer(location).getClass(); + Object h1 = getChunkProviderServer(location); + Method m1 = c1.getDeclaredMethod("loadChunk", int.class, int.class); + m1.invoke(h1, x, z); + + } catch(Exception e) { + e.printStackTrace(); + } + } + +} \ No newline at end of file diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ReflectionUtils.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ReflectionUtils.java new file mode 100644 index 0000000..ffe6779 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/reflection/ReflectionUtils.java @@ -0,0 +1,40 @@ +package net.aminecraftdev.custombosses.innerapi.reflection; + +import org.bukkit.Bukkit; + +/** + * Created by charl on 28-Apr-17. + */ +public class ReflectionUtils { + + private static String _nmsVersion = null; + + static { + if(_nmsVersion == null) { + _nmsVersion = Bukkit.getServer().getClass().getPackage().getName(); + _nmsVersion = _nmsVersion.substring(_nmsVersion.lastIndexOf(".") + 1); + } + } + + public static final String getAPIVersion() { + return _nmsVersion; + } + + public static final Class getNMSClass(String name) { + try { + return Class.forName("net.minecraft.server." + _nmsVersion + "." + name); + } catch(ClassNotFoundException e) { + e.printStackTrace(); + return null; + } + } + + public static final Class getOBCClass(String name) { + try { + return Class.forName("org.bukkit.craftbukkit." + _nmsVersion + "." + name); + } catch(ClassNotFoundException e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/BoostedGson.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/BoostedGson.java new file mode 100644 index 0000000..6b22593 --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/BoostedGson.java @@ -0,0 +1,35 @@ +package net.aminecraftdev.custombosses.innerapi.serialization; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import net.aminecraftdev.custombosses.innerapi.serialization.helpers.LocationAdapter; +import org.bukkit.Location; + +/** + * @author Debugged + * @version 1.0 + * @since 18-5-2017 + */ +public class BoostedGson { + + private static final Gson gson = new GsonBuilder() + .setPrettyPrinting() + .excludeFieldsWithoutExposeAnnotation() + .registerTypeAdapter(Location.class, new LocationAdapter()) + .create(); + + private static final Gson gsonFlat = new GsonBuilder() + .setPrettyPrinting() + .excludeFieldsWithoutExposeAnnotation() + .registerTypeAdapter(Location.class, new LocationAdapter()) + .create(); + + public static Gson getGson() { + return gson; + } + + public static Gson getGsonFlat() { + return gsonFlat; + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/Serialize.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/Serialize.java new file mode 100644 index 0000000..34b82ed --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/Serialize.java @@ -0,0 +1,40 @@ +package net.aminecraftdev.custombosses.innerapi.serialization; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +/** + * @author Debugged + * @version 1.0 + * @since 18-5-2017 + */ +public class Serialize { + + public static String serialize(Location location) { + return location.getWorld().getName() + ";" + + location.getX() + ";" + + location.getY() + ";" + + location.getZ() + ";" + + location.getYaw() + ";" + + location.getPitch() + ";"; + } + + public static Location deserializeLocation(String locationString) { + String[] split = locationString.split(";"); + + try { + World world = Bukkit.getWorld(split[0]); + double x = Double.parseDouble(split[1]); + double y = Double.parseDouble(split[2]); + double z = Double.parseDouble(split[3]); + float yaw = Float.parseFloat(split[4]); + float pitch = Float.parseFloat(split[5]); + + return new Location(world, x, y, z, yaw, pitch); + } catch (Exception ex) { + return null; + } + } + +} diff --git a/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/helpers/LocationAdapter.java b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/helpers/LocationAdapter.java new file mode 100644 index 0000000..54d2fbf --- /dev/null +++ b/api-modules/PluginAPI/src/net/aminecraftdev/custombosses/innerapi/serialization/helpers/LocationAdapter.java @@ -0,0 +1,28 @@ +package net.aminecraftdev.custombosses.innerapi.serialization.helpers; + +import com.google.gson.*; +import net.aminecraftdev.custombosses.innerapi.serialization.Serialize; +import org.bukkit.Location; + +import java.lang.reflect.Type; + +/** + * @author Debugged + * @version 1.0 + * @since 18-5-2017 + */ +public class LocationAdapter implements JsonSerializer, JsonDeserializer { + + @Override + public Location deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + return Serialize.deserializeLocation(jsonElement.getAsString()); + } + + @Override + public JsonElement serialize(Location location, Type type, JsonSerializationContext jsonSerializationContext) { + return new JsonPrimitive( + Serialize.serialize(location) + ); + } + +} diff --git a/custombosses.iml b/custombosses.iml new file mode 100644 index 0000000..c461222 --- /dev/null +++ b/custombosses.iml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugin-modules/Core/Core.iml b/plugin-modules/Core/Core.iml new file mode 100644 index 0000000..4f08f88 --- /dev/null +++ b/plugin-modules/Core/Core.iml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugin-modules/Core/pom.xml b/plugin-modules/Core/pom.xml new file mode 100644 index 0000000..e137c20 --- /dev/null +++ b/plugin-modules/Core/pom.xml @@ -0,0 +1,95 @@ + + + + CustomBosses + net.aminecraftdev.custombosses + 3.0.0.0 + ../../pom.xml + + 4.0.0 + + Core + 3.0.0.0 + jar + + + + net.aminecraftdev.custombosses + FactionsM + 3.0.0.0 + jar + compile + true + + + net.aminecraftdev.custombosses + FactionsUUID + 3.0.0.0 + jar + compile + true + + + net.aminecraftdev.custombosses + FactionsOne + 3.0.0.0 + jar + compile + true + + + net.aminecraftdev.custombosses + PluginAPI + 3.0.0.0 + jar + compile + true + + + + + clean package install + ../../target + CustomBosses-${project.version} + ${basedir}/src/ + + + . + true + ${basedir}/resources + + *.yml + + + + + + maven-compiler-plugin + 2.3.2 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 1.4 + + false + + + + package + + shade + + + + + + + + \ No newline at end of file diff --git a/plugin-modules/Core/resources/autospawns.yml b/plugin-modules/Core/resources/autospawns.yml new file mode 100644 index 0000000..043a435 --- /dev/null +++ b/plugin-modules/Core/resources/autospawns.yml @@ -0,0 +1,55 @@ +AutoSpawns: + '1': + Coords: + world: world + x: 0 + y: 150 + z: 0 + + PossibleSpawns: + - SKELETON + - ZOMBIE + - GIANT + + Settings: + spawnIfChunkNotLoaded: false + maxSpawned: 1 + bossesPerInterval: 1 + spawnRate: 30m + spawnType: INTERVAL + holographicPlaceholder: '{custombosses_1}' + + Messages: + onSpawn: [] + Intervals: + '10': + - '&e&l(!) &bThe boss (#1) is about to spawn in {0} seconds!' + '60': + - '&e&l(!) &bThe boss (#1) is about to spawn in {0} seconds!' + '300': + - '&e&l(!) &bThe boss (#1) is about to spawn in 5 minutes!' + '2': + Coords: + world: world + x: 0 + y: 150 + z: 0 + + PossibleSpawns: + - SKELETON + + Settings: + spawnIfChunkNotLoaded: false + maxSpawned: 1 + bossesPerInterval: 1 + spawnRate: 1m + spawnType: INTERVAL + holographicPlaceholder: '{custombosses_2}' + + Messages: + onSpawn: [] + Intervals: + '10': + - '&e&l(!) &bThe boss (#2) is about to spawn in {0} seconds!' + '30': + - '&e&l(!) &bThe boss (#2) is about to spawn in {0} seconds!' \ No newline at end of file diff --git a/plugin-modules/Core/resources/bosses.yml b/plugin-modules/Core/resources/bosses.yml new file mode 100644 index 0000000..49f2341 --- /dev/null +++ b/plugin-modules/Core/resources/bosses.yml @@ -0,0 +1,135 @@ +Bosses: + + #SKELETON BOSS CONFIGURATION SECTION + SKELETON: + Item: + type: '383:51' + name: '&6&lSkeleton King Boss Spawn Egg' + lore: + - '&7Right click a block to spawn' + - '&7the boss as that location.' + Boss: + targetType: VANILLA + type: SKELETON + name: '&6&l&nSkeleton King Boss' + health: 80 + Armor: + type: GOLD + enchants: + - PROTECTION_ENVIRONMENTAL:4 + - DURABILITY:3 + Weapon: + type: DIAMOND_SWORD + enchants: + - KNOCKBACK:3 + - DURABILITY:3 + Head: + owner: AMinecraftDev + Potions: + '1': + type: DAMAGE_RESISTANCE + level: 3 + duration: -1 + Skills: + overallChance: 30.0 + message: '&6&l{0} &7used &e{1}' + delay: 30s + list: + - 30:KNOCKBACK1 + - 40:CAGE1 + - 70:CAGE2 + Drops: + NaturalDrops: false + DropTable: SkeletonTable1 + Messages: + onSpawn: + - '&4' + - '&a&lA &6&l{boss} &a&lhas been spawned in the warzone!' + - '&4' + onDeath: + message: + - '&4' + - '&8&m---------&8&l[ &a&l{boss}&r &a&lKilled &8&l]&r&8&m---------' + - '&aKillers: &r{format}' + format: ' &6&l{position} &e{player} &7(&b{%}%&7) /n' + Taunts: + delay: 30s + messages: + - '&7Muahahahaha you can never beat me.' + - '&7You think that hurts someone like me?!' + Commands: + onSpawn: + - 'say onSpawn random command: {player} spawned me.' + onDeath: + - 'say onDeath random command: {player}' + + #ZOMBIE BOSS CONFIGURATION SECTION + ZOMBIE: + Item: + type: '383:54' + name: '&2&lZombie King Boss Spawn Egg' + lore: + - '&7Right click a block to spawn' + - '&7the boss as that location.' + Boss: + targetType: DAMAGE + type: ZOMBIE + name: '&2&l&nZombie King Boss' + health: 100 + Weapon: + type: DIAMOND_AXE + enchants: + - KNOCKBACK:3 + - DURABILITY:3 + Drops: + NaturalDrops: false + DropTable: ZombieTable1 + Messages: + onSpawn: + - '&4' + - '&a&lA &6&l{boss} &a&lhas been spawned in the warzone!' + - '&4' + onDeath: + message: + - '&4' + - '&8&m---------&8&l[ &a&l{boss}&r &a&lKilled &8&l]&r&8&m---------' + - '&aKillers: &r{format}' + format: ' &6&l{position} &e{player} &7(&b{%}%&7) /n' + Taunts: + delay: 30s + messages: + - '&7Muahahahaha you can never beat me.' + - '&7You think that hurts someone like me?!' + Commands: + onSpawn: + - 'say onSpawn random command: {player} spawned me.' + onDeath: + - 'say onDeath random command: {player}' + + #GIANT BOSS CONFIGURATION SECTION + GIANT: + Item: + type: '383:54' + name: '&b&lGiant Zombie Boss Spawn Egg' + lore: + - '&7Right click a block to spawn' + - '&7the boss as that location.' + Boss: + targetType: DAMAGE + type: GIANT + name: '&b&l&nGiant King Boss' + health: 100 + Drops: + NaturalDrops: false + DropTable: GiantTable1 + Messages: + onSpawn: + - '&4' + - '&a&lA &6&l{boss} &a&lhas been spawned in the warzone!' + - '&4' + onDeath: + message: + - '&4' + - '&8&m---------&8&l[ &a&l{boss}&r &a&lKilled &8&l]&r&8&m---------' + - '&aKillers: &r{format}' + format: ' &6&l{position} &e{player} &7(&b{%}%&7) /n' \ No newline at end of file diff --git a/plugin-modules/Core/resources/config.yml b/plugin-modules/Core/resources/config.yml new file mode 100644 index 0000000..11ec1ae --- /dev/null +++ b/plugin-modules/Core/resources/config.yml @@ -0,0 +1,102 @@ +Settings: + AutoSpawns: + enabled: true + sectionToTimeInCommand: '1' + BroadcastRange: + onDeath: -1 + onHealth: 150 + onSkill: 150 + onSpawn: -1 + onSpawnCommand: 0 + onTaunt: 150 + CommandsEnabled: + Help: true + KillAll: true + List: true + Reload: true + Spawn: true + Time: true + HealthBar: + ActionBar: + enabled: true + message: '&6{0}&7 has &c{1}/{2} health.' + BossBar: + enabled: false + message: '&6{0}' + useHealthBar: true +onSpawn: + Regions: + enabled: true + spawnRegions: + - 'spawn_region1' + blockedRegions: + - 'blocked_region1' + Worlds: + enabled: false + blockedWorlds: + - 'world_nether' + - 'world_the_end' +onSkill: + minionsPerSpawn: 5 + maxMinionsPerBoss: 10 + disableCageBreak: true +onDeath: + noReward: + onLava: true + onDrown: false + onSuffocate: false +GUI: + EggExtraLore: + - '&8&m-----------------------------------' + - '&7' + - '&6&lGet this egg:' + - '&f/giveegg {0} {1} [amount]' + - '&7' + - '&8&m-----------------------------------' + + Inventory: + name: '&6&lCustom Bosses' + slots: 54 + Items: + '54': + type: PAPER + name: '&e&lNext Page ->' + lore: + - '&7Click this to go to the &enext' + - '&epage&7, if there is one.' + NextPage: true + '53': + type: 102 + name: '&e' + lore: [] + '52': + type: 102 + name: '&e' + lore: [] + '51': + type: 102 + name: '&e' + lore: [] + '50': + type: 102 + name: '&e' + lore: [] + '49': + type: 102 + name: '&e' + lore: [] + '48': + type: 102 + name: '&e' + lore: [] + '47': + type: 102 + name: '&e' + lore: [] + '46': + type: PAPER + name: '&e&l<- Previous Page' + lore: + - '&7Click this to go the &eprevious' + - '&epage&7, if there is one.' + PreviousPage: true \ No newline at end of file diff --git a/plugin-modules/Core/resources/droptable.yml b/plugin-modules/Core/resources/droptable.yml new file mode 100644 index 0000000..5d3dcfb --- /dev/null +++ b/plugin-modules/Core/resources/droptable.yml @@ -0,0 +1,144 @@ +# +# ----------------------------------------------------------------------------------------------------------------------------------------- +# + +SkeletonTable1: # Used in the identifier in bosses.yml + '1': # The position for rewards (1st most damage). + RequiredPercent: 20.0 # The required % to get this reward + RandomCustomDrop: false # Choose Random Custom Drops or go in order? + MaxCustomDrops: 5 # The maximum amount of custom drops. + customDrops: # The custom drops list. + - 'Chance:50 Item:Item1' + - 'Chance:50 Item:Item2' + + RandomCommand: false # Choose Random Commands or go in order? + MaxCommands: 5 # The maximum amount of commands. + commands: # The commands list. + - '50: eco give %player% 500' # The 50: represents the chance of the command occurring, and after the ': ' is the command. + - '50: eco give %player% 2500' # If you are using the chance system you MUST put a space between the : and the commmand. + + '2': # The position for rewards (2nd most damage). + RequiredPercent: 20.0 # The required % to get this reward + RandomCustomDrop: false # Choose Random Custom Drops or go in order? + MaxCustomDrops: 5 # The maximum amount of custom drops. + customDrops: # The custom drops list. + - 'Chance:50 Item:Item1' + - 'Chance:50 Item:Item2' + + RandomCommand: false # Choose Random Commands or go in order? + MaxCommands: 5 # The maximum amount of commands. + commands: # The commands list. + - '50: eco give %player% 500' # The 50: represents the chance of the command occurring, and after the ': ' is the command. + - '50: eco give %player% 2500' # If you are using the chance system you MUST put a space between the : and the commmand. + + '3': # The position for rewards (3rd most damage). + RequiredPercent: 20.0 # The required % to get this reward + RandomCustomDrop: false # Choose Random Custom Drops or go in order? + MaxCustomDrops: 5 # The maximum amount of custom drops. + customDrops: # The custom drops list. + - 'Chance:50 Item:Item1' + - 'Chance:50 Item:Item2' + + RandomCommand: false # Choose Random Commands or go in order? + MaxCommands: 5 # The maximum amount of commands. + commands: # The commands list. + - '50: eco give %player% 500' # The 50: represents the chance of the command occurring, and after the ': ' is the command. + - '50: eco give %player% 2500' # If you are using the chance system you MUST put a space between the : and the commmand. + +# +# ----------------------------------------------------------------------------------------------------------------------------------------- +# + +ZombieTable1: + '1': + RequiredPercent: 10.0 + RandomCustomDrop: false + MaxCustomDrops: 5 + customDrops: + - 'Chance:50 Item:Item1' + - 'Chance:50 Item:Item2' + + RandomCommand: false + MaxCommands: 5 + commands: + - '50: eco give %player% 5000' + - '50: eco give %player% 10000' + + '2': + RequiredPercent: 10.0 + RandomCustomDrop: false + MaxCustomDrops: 5 + customDrops: + - 'Chance:50 Item:Item1' + - 'Chance:50 Item:Item2' + + RandomCommand: false + MaxCommands: 5 + commands: + - '50: eco give %player% 4000' + - '50: eco give %player% 7500' + + '3': + RequiredPercent: 10.0 + RandomCustomDrop: false + MaxCustomDrops: 5 + customDrops: + - 'Chance:50 Item:Item1' + - 'Chance:50 Item:Item2' + + RandomCommand: false + MaxCommands: 5 + commands: + - '50: eco give %player% 300' + - '50: eco give %player% 5000' + +# +# ----------------------------------------------------------------------------------------------------------------------------------------- +# + +GiantTable1: + '1': + RequiredPercent: 10.0 + RandomCustomDrop: false + MaxCustomDrops: 5 + customDrops: + - 'Chance:50 Item:Item1' + - 'Chance:50 Item:Item2' + + RandomCommand: false + MaxCommands: 5 + commands: + - '50: eco give %player% 10000' + - '50: eco give %player% 50000' + + '2': + RequiredPercent: 10.0 + RandomCustomDrop: false + MaxCustomDrops: 5 + customDrops: + - 'Chance:50 Item:Item1' + - 'Chance:50 Item:Item2' + + RandomCommand: false + MaxCommands: 5 + commands: + - '50: eco give %player% 5000' + - '50: eco give %player% 25000' + + '3': + RequiredPercent: 10.0 + RandomCustomDrop: false + MaxCustomDrops: 5 + customDrops: + - 'Chance:50 Item:Item1' + - 'Chance:50 Item:Item2' + + RandomCommand: false + MaxCommands: 5 + commands: + - '50: eco give %player% 5000' + - '50: eco give %player% 25000' + +# +# ----------------------------------------------------------------------------------------------------------------------------------------- +# \ No newline at end of file diff --git a/plugin-modules/Core/resources/items.yml b/plugin-modules/Core/resources/items.yml new file mode 100644 index 0000000..a3b23c1 --- /dev/null +++ b/plugin-modules/Core/resources/items.yml @@ -0,0 +1,18 @@ +Item1: + amount: 1 + type: STONE + name: '&5Epic Stone' + lore: + - '&7This stone is' + - '&7Lucky.' + enchants: + - DURABILITY:3 + - DAMAGE_ALL:5 + +Item2: + amount: 5 + type: WOOD + name: '&5Epic wood' + lore: + - '&7This wood is' + - '&7hard.' \ No newline at end of file diff --git a/plugin-modules/Core/resources/lang.yml b/plugin-modules/Core/resources/lang.yml new file mode 100644 index 0000000..b86c92d --- /dev/null +++ b/plugin-modules/Core/resources/lang.yml @@ -0,0 +1 @@ +# The configuration for all Messages. diff --git a/plugin-modules/Core/resources/plugin.yml b/plugin-modules/Core/resources/plugin.yml new file mode 100644 index 0000000..75456d0 --- /dev/null +++ b/plugin-modules/Core/resources/plugin.yml @@ -0,0 +1,4 @@ +name: CustomBosses +main: net.aminecraftdev.custombosses.CustomBosses +version: ${project.version} +author: AMinecraftDev diff --git a/plugin-modules/Core/resources/skills.yml b/plugin-modules/Core/resources/skills.yml new file mode 100644 index 0000000..56e5ddb --- /dev/null +++ b/plugin-modules/Core/resources/skills.yml @@ -0,0 +1,193 @@ +#--------------------------------------------------------------------------------------------------------------------------------- +# Available skill modes: +# +# ALL - The skill will be applied to everyone within the radius. +# RANDOM - The skill will be applied to random people within the radius, with a 50% chance per person for it to happen to them. +# ONE - Will only effect the closest person to the boss. +# BOSS - The skill will only effect the boss. +# +#--------------------------------------------------------------------------------------------------------------------------------- +# Available skill types: +# +# POTION - It's just a potion effect so it'll just apply the specified potions to the player. +# CUSTOM - It's a custom skill which requires a custom .java class, when this is used please add "customType: {type}" on the line +# underneath the type. +# COMMAND - Just runs specified commands in the commands list. +# +#--------------------------------------------------------------------------------------------------------------------------------- + +Skills: + BLIND1: + mode: ALL + type: POTION + radius: 10 + + Potions: + '1': + type: POISON + level: 1 + duration: 5 + '2': + type: BLINDNESS + level: 1 + duration: 5 + + BLIND2: + mode: ALL + type: POTION + radius: 10 + + Potions: + '1': + type: POISON + level: 2 + duration: 5 + '2': + type: BLINDNESS + level: 2 + duration: 5 + + CAGE1: + mode: ALL + type: CUSTOM + customType: CAGE + radius: 10 + + Cage: + Flat: IRON_BLOCK + Wall: IRON_FENCE + Inside: STATIONARY_LAVA + + CAGE2: + mode: ALL + type: CUSTOM + customType: CAGE + radius: 10 + + Cage: + Flat: IRON_BLOCK + Wall: IRON_FENCE + Inside: STATIONARY_WATER + + KNOCKBACK1: + mode: ALL + type: CUSTOM + customType: KNOCKBACK + radius: 10 + + multiplier: 2.5 + + KNOCKBACK2: + mode: ALL + type: CUSTOM + customType: KNOCKBACK + radius: 10 + + multiplier: 5 + + DISARM1: + mode: ONE + type: CUSTOM + customType: DISARM + radius: 10 + + WARP1: + mode: ONE + type: CUSTOM + customType: WARP + radius: 10 + + EXPLOSION1: + mode: ALL + type: POTION + radius: 2 + + Potions: + '1': + type: WITHER + level: 3 + duration: 5 + + MINIONS1: + mode: BOSS + type: CUSTOM + customType: MINIONS + radius: 10 + + Boss: + type: ZOMBIE + name: '&a&lMinion Goblin' + health: 40 + Armor: + type: LEATHER + enchants: + - PROTECTION_ENVIRONMENTAL:4 + - DURABILITY:3 + Weapon: + type: STONE + enchants: + - DAMAGE_ALL:10 + - DURABILITY:3 + Potions: + '1': + type: SPEED + level: 10 + duration: -1 + + MINIONS2: + mode: BOSS + type: CUSTOM + customType: MINIONS + radius: 10 + + Boss: + type: SKELETON + name: '&a&lMinion Goblin' + health: 40 + Armor: + type: LEATHER + enchants: + - PROTECTION_ENVIRONMENTAL:4 + - DURABILITY:3 + Weapon: + type: STONE + enchants: + - DAMAGE_ALL:10 + - DURABILITY:3 + Potions: + '1': + type: SPEED + level: 10 + duration: -1 + + INSIDIOUS1: + mode: ALL + type: CUSTOM + customType: INSIDIOUS + radius: 10 + + burnDuration: 4 + + INSIDIOUS2: + mode: ALL + type: CUSTOM + customType: INSIDIOUS + radius: 10 + + burnDuration: 6 + + LOOT1: + mode: RANDOM + type: COMMAND + radius: 10 + commands: + - '40:eco give {p} 100' + - '60:eco give {p} 1000' + + LOOT2: + mode: RANDOM + type: COMMAND + radius: 10 + commands: + - '40:eco give {p} 200' + - '60:eco give {p} 2000' \ No newline at end of file diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/CustomBosses.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/CustomBosses.java new file mode 100644 index 0000000..6b195a5 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/CustomBosses.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class CustomBosses { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossHelpCmd.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossHelpCmd.java new file mode 100644 index 0000000..a3802a6 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossHelpCmd.java @@ -0,0 +1,23 @@ +package net.aminecraftdev.custombosses.commands; + +import net.aminecraftdev.custombosses.innerapi.command.SubCommand; +import net.aminecraftdev.custombosses.utils.Message; +import org.bukkit.command.CommandSender; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossHelpCmd extends SubCommand { + + public BossHelpCmd(String subCommand) { + super(subCommand); + } + + @Override + public void execute(CommandSender sender, String[] args) { + Message.BossCommand_Help.msg(sender); + return; + } +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossKillAllCmd.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossKillAllCmd.java new file mode 100644 index 0000000..c55bc5d --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossKillAllCmd.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.commands; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossKillAllCmd { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossListCmd.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossListCmd.java new file mode 100644 index 0000000..a9e388f --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossListCmd.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.commands; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossListCmd { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossReloadCmd.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossReloadCmd.java new file mode 100644 index 0000000..bb15f9d --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossReloadCmd.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.commands; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossReloadCmd { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossSpawnCmd.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossSpawnCmd.java new file mode 100644 index 0000000..2cd705d --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossSpawnCmd.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.commands; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossSpawnCmd { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossTimeCmd.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossTimeCmd.java new file mode 100644 index 0000000..73361d3 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/BossTimeCmd.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.commands; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossTimeCmd { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/base/BossCmd.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/base/BossCmd.java new file mode 100644 index 0000000..4d2faa1 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/commands/base/BossCmd.java @@ -0,0 +1,54 @@ +package net.aminecraftdev.custombosses.commands.base; + +import net.aminecraftdev.custombosses.innerapi.command.SubCommand; +import net.aminecraftdev.custombosses.innerapi.command.SubCommandBuilder; +import net.aminecraftdev.custombosses.innerapi.command.builder.CommandService; +import net.aminecraftdev.custombosses.innerapi.command.builder.attributes.*; +import net.aminecraftdev.custombosses.utils.Message; +import org.bukkit.command.CommandSender; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +@Name("boss") +@Alias({"bosses", "custombosses", "customboss"}) +@Permission("bosses.command.use") +@Description("Access all boss related features of CustomBosses.") +@NoPermission("&cI'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error.") +public class BossCmd extends CommandService implements SubCommandBuilder { + + private final Set> subCommands = new HashSet<>(); + + public BossCmd() { + super(BossCmd.class); + } + + @Override + public void execute(CommandSender sender, String[] args) { + if(args.length == 0) { + Message.BossCommand_Help.msg(sender); + return; + } + + for(SubCommand subCommand : subCommands) { + if(subCommand.getSubCommand().equalsIgnoreCase(args[0])) { + subCommand.execute(sender, args); + return; + } + } + + Message.BossCommand_Help.msg(sender); + return; + } + + + @Override + public void register(SubCommand subCommand) { + subCommands.add(subCommand); + } +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossDamageEvent.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossDamageEvent.java new file mode 100644 index 0000000..6565dda --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossDamageEvent.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.events; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossDamageEvent { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossDeathEvent.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossDeathEvent.java new file mode 100644 index 0000000..cf4b52c --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossDeathEvent.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.events; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossDeathEvent { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossSkillEvent.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossSkillEvent.java new file mode 100644 index 0000000..172e986 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossSkillEvent.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.events; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossSkillEvent { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossSpawnEvent.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossSpawnEvent.java new file mode 100644 index 0000000..19c495a --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/events/BossSpawnEvent.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.events; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossSpawnEvent { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/AutoSpawnHandler.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/AutoSpawnHandler.java new file mode 100644 index 0000000..20ed975 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/AutoSpawnHandler.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.handlers; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class AutoSpawnHandler { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/EntityHandler.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/EntityHandler.java new file mode 100644 index 0000000..ec81203 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/EntityHandler.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.handlers; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class EntityHandler { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/MinionHandler.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/MinionHandler.java new file mode 100644 index 0000000..3b9f2fd --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/MinionHandler.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.handlers; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class MinionHandler { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/TauntHandler.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/TauntHandler.java new file mode 100644 index 0000000..d93e617 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/handlers/TauntHandler.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.handlers; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class TauntHandler { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/AutoSpawnManager.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/AutoSpawnManager.java new file mode 100644 index 0000000..a35458e --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/AutoSpawnManager.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.managers; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class AutoSpawnManager { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/BossManager.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/BossManager.java new file mode 100644 index 0000000..ba3447a --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/BossManager.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.managers; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class BossManager { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/ItemManager.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/ItemManager.java new file mode 100644 index 0000000..5735e2a --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/ItemManager.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.managers; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class ItemManager { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/MinionManager.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/MinionManager.java new file mode 100644 index 0000000..47dfb33 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/MinionManager.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.managers; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class MinionManager { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/SkillManager.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/SkillManager.java new file mode 100644 index 0000000..d65c6dc --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/managers/SkillManager.java @@ -0,0 +1,9 @@ +package net.aminecraftdev.custombosses.managers; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public class SkillManager { +} diff --git a/plugin-modules/Core/src/net/aminecraftdev/custombosses/utils/Message.java b/plugin-modules/Core/src/net/aminecraftdev/custombosses/utils/Message.java new file mode 100644 index 0000000..fabe500 --- /dev/null +++ b/plugin-modules/Core/src/net/aminecraftdev/custombosses/utils/Message.java @@ -0,0 +1,201 @@ +package net.aminecraftdev.custombosses.utils; + +import net.aminecraftdev.custombosses.innerapi.message.MessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.command.CommandSender; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +/** + * @author AMinecraftDev + * @version 1.0.0 + * @since 31-May-17 + */ +public enum Message { + + BossCommand_Help( + " &4\n" + + "&7&m-----------------&b&l[ &a&lCustomBosses&r &b&l]&7&m-----------------&r\n" + + " &4\n" + + "&6/boss spawn (type) (x) (y) (z) (world) &e&m-&f&o Spawn a boss at the coordinates.\n" + + "&7/boss spawn (type) (player) &e&m-&f&o Spawn a boss on a player.\n" + + "&6/boss time &e&m-&f&o View the time until the next boss auto-spawn.\n" + + "&6/boss reload &e&m-&f&o Reloads the YML files for CustomBosses.\n" + + "&6/boss killall &e&m-&f&o Kills all currently spawned bosses/minions.\n" + + "&6/boss list &e&m-&f&o Opens a GUI with all the available boss eggs.\n" + + "&6/giveegg (player) (boss) [amount] &e&m-&f&o Gives the specified player a boss egg.\n" + + " &4\n" + + "&7&m-----------------&b&l[ &a&lCustomBosses&r &b&l]&7&m-----------------&r\n" + + " &4"), + BossCommand_KillAll_Blocked("&c&l[!] &cThe KillAll command is blocked!"), + BossCommand_KillAll_Killed("&a&l[!] &fYou've killed &e{0}&f bosses/minions."), + BossCommand_List("&a&l[!] &fYou are now viewing all custom bosses."), + BossCommand_Reload("&a&l[!] &fYou just reloaded the files for CustomBosses."), + BossCommand_Spawn_InvalidBoss("&c&l[!] &cThe specified boss doesn't exist!"), + BossCommand_Spawn_InvalidLocation("&c&l[!] &cThe specified location is invalid!"), + BossCommand_Spawn_InvalidWorld("&c&l[!] &cThe specified world doesn't exist!"), + BossCommand_Spawn_Spawned("&a&l[!] &fYou have spawned a &e{0}&f boss at &e{1}&f."), + BossCommand_Time_Display("&a&l[!] &fThere is currently &e{0}&f left till next spawn."), + BossCommand_Time_NotEnabled("&c&l[!] &cThe boss time command has been disabled."), + + GiveEggCommand_Given_Receiver("&a&l[!] &fYou have received &e{0}x&f boss egg(s)."), + GiveEggCommand_Given_Sender("&a&l[!] &fYou have given &e{0}x&f boss egg(s) to &e{1}&f."), + GiveEggCommand_Help( + " &4\n" + + "&7&m-----------------&b&l[ &a&lCustomBosses&r &b&l]&7&m-----------------&r\n" + + " &4\n" + + "&6/boss spawn (type) (x) (y) (z) (world) &e&m-&f&o Spawn a boss at the coordinates.\n" + + "&7/boss spawn (type) (player) &e&m-&f&o Spawn a boss on a player.\n" + + "&6/boss time &e&m-&f&o View the time until the next boss auto-spawn.\n" + + "&6/boss reload &e&m-&f&o Reloads the YML files for CustomBosses.\n" + + "&6/boss killall &e&m-&f&o Kills all currently spawned bosses/minions.\n" + + "&6/boss list &e&m-&f&o Opens a GUI with all the available boss eggs.\n" + + "&6/giveegg (player) (boss) [amount] &e&m-&f&o Gives the specified player a boss egg.\n" + + " &4\n" + + "&7&m-----------------&b&l[ &a&lCustomBosses&r &b&l]&7&m-----------------&r\n" + + " &4"), + GiveEggCommand_InvalidBoss("&c&l[!] &cThe specified boss doesn't exist!"), + + Settings_InvalidNumber("&c&l[!] &cYou have specified an invalid number!"), + Settings_InventorySpace("&c&l[!] &cYou do not have enough inventory space for that!"), + Settings_ItemStack_Max("&c&l[!] &cThe maximum ItemStack size is 64!"), + Settings_ItemStack_Min("&c&l[!] &cThe minimum ItemStack size is 1!"), + Settings_ItemStack_Null("&c&l[!] &cThe specified ItemStack cannot be null or air!"), + Settings_MustBePlayer("&c&l[!] &cYou must be a player to use that feature!"), + Settings_NotOnline("&c&l[!] &cThe player you specified is offline or doesn't exist!"); + + private String path; + private String msg; + private static FileConfiguration LANG; + + Message(String string) { + this.path = "Messages." + this.name().replace("_", "."); + this.msg = string; + } + + public static void setFile(FileConfiguration configuration) { + LANG = configuration; + } + + @Override + public String toString() { + String s = ChatColor.translateAlternateColorCodes('&', LANG.getString(this.path, msg)); + + return s; + } + + public String toString(Object... args) { + String s = ChatColor.translateAlternateColorCodes('&', LANG.getString(this.path, msg)); + + return getMessageReplaced(s, args); + } + + public String getDefault() { + return this.msg; + } + + public String getPath() { + return this.path; + } + + public void msg(CommandSender p, Object... order) { + String s = toString(); + + if(s.contains("\n")) { + String[] split = s.split("\n"); + + for(String inner : split) { + messageString(p, inner, order); + } + } else { + messageString(p, s, order); + } + } + + public void broadcast(Object... order) { + String s = toString(); + + if(s.contains("\n")) { + String[] split = s.split("\n"); + + for(String s1 : split) { + for(Player player : Bukkit.getOnlinePlayers()) { + messageString(player, s1, order); + } + } + } else { + for(Player player : Bukkit.getOnlinePlayers()) { + messageString(player, s, order); + } + } + } + + + + /** + * + * Private Enum methods + * + * + */ + private void messageString(CommandSender player, String s, Object... order) { + if(s.equalsIgnoreCase("")) return; + + if(s.contains("{c}")) { + MessageUtils.sendCenteredMessage(player, getMessageReplaced(s, order).replace("{c}", "")); + } else { + player.sendMessage(getMessageReplaced(s, order)); + } + } + + private String getMessageReplaced(String s, Object... order) { + int current = 0; + + for(Object object : order) { + String placeholder = "{" + current + "}"; + + if(s.contains(placeholder)) { + if(object instanceof CommandSender) { + s = s.replace(placeholder, ((CommandSender) object).getName()); + } + + if(object instanceof Location) { + Location location = (Location) object; + String repl = location.getWorld().getName() + ", " + location.getBlockX() + ", " + location.getBlockY() + ", " + location.getBlockZ(); + + s = s.replace(placeholder, repl); + } + + if(object instanceof String) { + s = s.replace(placeholder, MessageUtils.translateString((String) object)); + } + + if(object instanceof Integer) { + s = s.replace(placeholder, ""+object); + } + + if(object instanceof ItemStack) { + s = s.replace(placeholder, getItemStackName((ItemStack) object)); + } + } + + current++; + } + + return s; + } + + private String getItemStackName(ItemStack itemStack) { + String name = itemStack.getType().toString().replace("_", " "); + + if(itemStack.hasItemMeta() && itemStack.getItemMeta().hasDisplayName()) { + return itemStack.getItemMeta().getDisplayName(); + } + + return name; + } + +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..94666dd --- /dev/null +++ b/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + net.aminecraftdev.custombosses + CustomBosses + pom + 3.0.0.0 + + api-modules/FactionsM + api-modules/FactionsOne + api-modules/FactionsUUID + api-modules/PluginAPI + plugin-modules/Core + + + + + com.spigotmc + spigot + 1.11.2 + provided + + + net.milkbowl.vault + VaultAPI + 1.6 + provided + + + com.sk89q + worldguard + 6.0.0-SNAPSHOT + provided + + + com.sk89q + worldedit + 6.0.0-SNAPSHOT + provided + + + + \ No newline at end of file