From 3cc1e5f391e0cf08960b266055141c05633a8001 Mon Sep 17 00:00:00 2001 From: MagmaGuy Date: Mon, 27 Nov 2023 02:32:14 +0000 Subject: [PATCH] EliteMobs 8.7.0 - [New] Added FreeMinecraftModels as a drop-in replacement for ModelEngine! ModelEngine R3 will still work for now, but support will be dropped in the future - [New] Arenas are now able to spawn Mythic Mobs as wave bosses! - [New] Added the elitemobs-explosion-block-damage flag, which when denied makes fireballs still do damage but not damage the terrain - [Fix/Revert] Fixed issue where players couldn't pick up elite currency. This reverts a previous compatibility fix for plugins that change item pickup behavior - [Fix] Fireballs now do damage correctly when appropriate - [Fix] Custom boss spawn with level command will now work correctly for bosses with a dynamic level - [Tweak] Remove command stops removing if you relog - [Tweak] Thoroughly optimized the PlasmaBlaster power based on feedback - ...and more Signed-off-by: MagmaGuy --- build.gradle | 10 +- .../com/magmaguy/elitemobs/EliteMobs.java | 5 +- .../magmaguy/elitemobs/EventsRegistrer.java | 12 +- .../api/EliteMobDamagedByPlayerEvent.java | 2 +- .../elitemobs/api/EliteMobDamagedEvent.java | 2 +- .../api/EliteMobEnterCombatEvent.java | 1 - .../api/PlayerDamagedByEliteMobEvent.java | 5 +- .../commands/admin/RemoveCommand.java | 6 + .../config/ConfigurationExporter.java | 67 ++++---- .../config/ConfigurationImporter.java | 37 ++-- .../CustomArenasConfigFields.java | 4 + .../CustomBossesConfigFields.java | 5 +- .../elitemobs/events/CustomEvent.java | 2 +- .../instanced/arena/ArenaEntity.java | 6 + .../instanced/arena/ArenaInstance.java | 47 +++-- .../elitemobs/instanced/arena/ArenaWaves.java | 28 ++- .../elitemobs/items/ItemLootShower.java | 1 - .../DrillingEnchantment.java | 7 +- .../customloottable/CommandLootTable.java | 84 +++++++++ .../customloottable/CustomLootTable.java | 1 + .../customloottable/EliteCustomLootEntry.java | 1 - .../elitemobs/mobconstructor/EliteEntity.java | 2 +- .../custombosses/CustomBossEntity.java | 12 +- .../custombosses/CustomBossMegaConsumer.java | 8 +- .../custombosses/RegionalBossEntity.java | 2 +- .../NaturalMobSpawnEventHandler.java | 2 +- .../magmaguy/elitemobs/npcs/NPCEntity.java | 2 +- .../elitemobs/pathfinding/Navigation.java | 2 +- .../elitemobs/powers/PlasmaBlaster.java | 19 +-- .../powers/meta/CombatEnterScanPower.java | 2 + .../powers/scripts/ScriptConditions.java | 3 + .../thirdparty/custommodels/CustomModel.java | 160 ++++++++++++++++++ .../custommodels/CustomModelInterface.java | 13 ++ .../freeminecraftmodels/CustomModelFMM.java | 65 +++++++ .../modelengine/CustomModelMEG.java} | 46 +---- .../ModelEngineReservedAddresses.java | 2 +- .../thirdparty/mythicmobs/MythicMobs.java | 20 +++ .../mythicmobs/MythicMobsInterface.java | 12 ++ .../worldguard/WorldGuardCompatibility.java | 77 ++++----- .../worldguard/WorldGuardDungeonFlag.java | 2 +- .../WorldGuardEliteMobOnlySpawnFlag.java | 2 +- .../WorldGuardExplosionBlockDamageFlag.java | 16 ++ .../worldguard/WorldGuardFlagChecker.java | 10 +- src/main/resources/plugin.yml | 3 +- 44 files changed, 605 insertions(+), 210 deletions(-) create mode 100644 src/main/java/com/magmaguy/elitemobs/items/customloottable/CommandLootTable.java create mode 100644 src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/CustomModel.java create mode 100644 src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/CustomModelInterface.java create mode 100644 src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/freeminecraftmodels/CustomModelFMM.java rename src/main/java/com/magmaguy/elitemobs/thirdparty/{modelengine/CustomModel.java => custommodels/modelengine/CustomModelMEG.java} (73%) rename src/main/java/com/magmaguy/elitemobs/thirdparty/{ => custommodels}/modelengine/ModelEngineReservedAddresses.java (97%) create mode 100644 src/main/java/com/magmaguy/elitemobs/thirdparty/mythicmobs/MythicMobs.java create mode 100644 src/main/java/com/magmaguy/elitemobs/thirdparty/mythicmobs/MythicMobsInterface.java create mode 100644 src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardExplosionBlockDamageFlag.java diff --git a/build.gradle b/build.gradle index d1237a7a1..be6fc6c20 100644 --- a/build.gradle +++ b/build.gradle @@ -120,10 +120,14 @@ dependencies { //Model Engine compileOnly "com.ticxo.modelengine:api:R3.1.7" - implementation group: 'com.magmaguy', name: 'EasyMinecraftGoals-dist', version: '1.6.1' + //Advanced AI goals + implementation group: 'com.magmaguy', name: 'EasyMinecraftGoals-dist', version: '1.7.0' - //Local test, you can ignore this - //implementation files('C:\\Users\\Tiago\\Documents\\MineCraftProjects\\EasyMinecraftGoals\\EasyMinecraftGoals\\dist\\target\\EasyMinecraftGoals-dist-1.6.0-shaded.jar') + //Free Minecraft Models + compileOnly group: 'com.magmaguy', name: 'FreeMinecraftModels', version: '1.1.0-SNAPSHOT' + + // Mythic Mobs integration + compileOnly group: 'io.lumine', name: 'Mythic-Dist', version: '5.3.5' } artifacts { // task 'build' runs generates uberjar diff --git a/src/main/java/com/magmaguy/elitemobs/EliteMobs.java b/src/main/java/com/magmaguy/elitemobs/EliteMobs.java index c509227a0..96b5d18fc 100644 --- a/src/main/java/com/magmaguy/elitemobs/EliteMobs.java +++ b/src/main/java/com/magmaguy/elitemobs/EliteMobs.java @@ -53,8 +53,9 @@ import com.magmaguy.elitemobs.quests.DynamicQuest; import com.magmaguy.elitemobs.quests.QuestTracking; import com.magmaguy.elitemobs.thirdparty.bstats.CustomCharts; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModel; +import com.magmaguy.elitemobs.thirdparty.custommodels.modelengine.ModelEngineReservedAddresses; import com.magmaguy.elitemobs.thirdparty.libsdisguises.DisguiseEntity; -import com.magmaguy.elitemobs.thirdparty.modelengine.ModelEngineReservedAddresses; import com.magmaguy.elitemobs.thirdparty.placeholderapi.Placeholders; import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardCompatibility; import com.magmaguy.elitemobs.treasurechest.TreasureChest; @@ -171,6 +172,8 @@ public void onEnable() { if (Bukkit.getPluginManager().isPluginEnabled("LibsDisguises")) DisguiseEntity.initialize(); + //Initializes custom models + CustomModel.initialize(); //Reserves ModelEngine addresses if present ModelEngineReservedAddresses.reserve(); diff --git a/src/main/java/com/magmaguy/elitemobs/EventsRegistrer.java b/src/main/java/com/magmaguy/elitemobs/EventsRegistrer.java index 6fa76e5ed..d35b065bb 100644 --- a/src/main/java/com/magmaguy/elitemobs/EventsRegistrer.java +++ b/src/main/java/com/magmaguy/elitemobs/EventsRegistrer.java @@ -62,9 +62,10 @@ import com.magmaguy.elitemobs.quests.objectives.DialogObjective; import com.magmaguy.elitemobs.quests.objectives.KillObjective; import com.magmaguy.elitemobs.quests.playercooldowns.PlayerQuestCooldownsLogout; -import com.magmaguy.elitemobs.thirdparty.modelengine.CustomModel; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModel; import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardDungeonFlag; import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardEliteMobOnlySpawnFlag; +import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardExplosionBlockDamageFlag; import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardSpawnEventBypasser; import com.magmaguy.elitemobs.treasurechest.TreasureChest; import com.magmaguy.elitemobs.versionnotifier.VersionChecker; @@ -362,9 +363,12 @@ public static void registerEvents() { register(new NPCProximitySensor()); register(new NPCEntity.NPCEntityEvents()); register(new FindNewWorlds()); - register(new WorldGuardSpawnEventBypasser()); - register(new WorldGuardEliteMobOnlySpawnFlag()); - register(new WorldGuardDungeonFlag()); + if (EliteMobs.worldGuardIsEnabled) { + register(new WorldGuardSpawnEventBypasser()); + register(new WorldGuardEliteMobOnlySpawnFlag()); + register(new WorldGuardDungeonFlag()); + register(new WorldGuardExplosionBlockDamageFlag()); + } register(new EntityTransformHandler()); register(new EliteBlazeWaterDamagePrevention()); diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerEvent.java index 79aecea58..d7e3eabd6 100644 --- a/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerEvent.java +++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedByPlayerEvent.java @@ -252,7 +252,7 @@ else if (event.getCause().equals(EntityDamageEvent.DamageCause.PROJECTILE)) eliteEntity.syncPluginHealth(((LivingEntity) event.getEntity()).getHealth()); //No antiexploit checks for dungeons - if (!(EliteMobs.worldGuardIsEnabled && !WorldGuardFlagChecker.checkFlag(eliteEntity.getLocation(), WorldGuardCompatibility.getEliteMobsAntiExploitFlag())) && event.getCause().equals(EntityDamageEvent.DamageCause.ENTITY_ATTACK) && !eliteEntity.isInAntiExploitCooldown() && eliteEntity.getLivingEntity() != null) + if (!(EliteMobs.worldGuardIsEnabled && !WorldGuardFlagChecker.checkFlag(eliteEntity.getLocation(), WorldGuardCompatibility.getELITEMOBS_ANTIEXPLOIT())) && event.getCause().equals(EntityDamageEvent.DamageCause.ENTITY_ATTACK) && !eliteEntity.isInAntiExploitCooldown() && eliteEntity.getLivingEntity() != null) Bukkit.getServer().getPluginManager().callEvent(new EliteMobDamagedByPlayerAntiExploitEvent(eliteEntity, eliteMobDamagedByPlayerEvent)); } diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedEvent.java index f5784263b..89309699c 100644 --- a/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedEvent.java +++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobDamagedEvent.java @@ -60,7 +60,7 @@ public void onEntityDamagedEvent(EntityDamageEvent event) { if (!eliteEntity.isValid()) return; if (EliteMobs.worldGuardIsEnabled && !WorldGuardFlagChecker.checkFlag(eliteEntity.getLivingEntity().getLocation(), - WorldGuardCompatibility.getEliteMobsAntiExploitFlag())) + WorldGuardCompatibility.getELITEMOBS_ANTIEXPLOIT())) return; Bukkit.getServer().getPluginManager().callEvent(new GenericAntiExploitEvent(eliteEntity, event)); diff --git a/src/main/java/com/magmaguy/elitemobs/api/EliteMobEnterCombatEvent.java b/src/main/java/com/magmaguy/elitemobs/api/EliteMobEnterCombatEvent.java index 821c8d5a4..103004212 100644 --- a/src/main/java/com/magmaguy/elitemobs/api/EliteMobEnterCombatEvent.java +++ b/src/main/java/com/magmaguy/elitemobs/api/EliteMobEnterCombatEvent.java @@ -90,7 +90,6 @@ public void onEliteMobDamage(PlayerDamagedByEliteMobEvent event) { @EventHandler(ignoreCancelled = true) public void onEliteMobTarget(EliteMobTargetPlayerEvent event) { if (event.getEliteMobEntity().isInCombat()) return; - if (!(event.getEliteMobEntity().getLivingEntity() instanceof Mob)) return; Bukkit.getServer().getPluginManager().callEvent(new EliteMobEnterCombatEvent(event.getEliteMobEntity(), event.getPlayer())); } } diff --git a/src/main/java/com/magmaguy/elitemobs/api/PlayerDamagedByEliteMobEvent.java b/src/main/java/com/magmaguy/elitemobs/api/PlayerDamagedByEliteMobEvent.java index 5fecbb83e..80c94b87c 100644 --- a/src/main/java/com/magmaguy/elitemobs/api/PlayerDamagedByEliteMobEvent.java +++ b/src/main/java/com/magmaguy/elitemobs/api/PlayerDamagedByEliteMobEvent.java @@ -129,7 +129,7 @@ private static double eliteToPlayerDamageFormula(Player player, EliteEntity elit finalDamage = Math.max(baseDamage + bonusDamage - damageReduction - potionEffectDamageReduction, 1) * customBossDamageMultiplier * specialMultiplier * MobCombatSettingsConfig.getNormalizedDamageToPlayerMultiplier(); else - finalDamage= Math.max(baseDamage + bonusDamage - damageReduction - potionEffectDamageReduction, 1) * + finalDamage = Math.max(baseDamage + bonusDamage - damageReduction - potionEffectDamageReduction, 1) * customBossDamageMultiplier * specialMultiplier * MobCombatSettingsConfig.getDamageToPlayerMultiplier(); if (specialMultiplier != 1) specialMultiplier = 1; @@ -156,7 +156,8 @@ private void explosionEvent(EntityExplodeEvent event) { public void onEliteDamagePlayer(EntityDamageByEntityEvent event) { if (event.isCancelled()) { bypass = false; - return; + if (!(event.getDamager() instanceof Explosive)) + return; } if (!(event.getEntity() instanceof Player player)) return; diff --git a/src/main/java/com/magmaguy/elitemobs/commands/admin/RemoveCommand.java b/src/main/java/com/magmaguy/elitemobs/commands/admin/RemoveCommand.java index 55c54e2e4..cc533cde0 100644 --- a/src/main/java/com/magmaguy/elitemobs/commands/admin/RemoveCommand.java +++ b/src/main/java/com/magmaguy/elitemobs/commands/admin/RemoveCommand.java @@ -17,6 +17,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerQuitEvent; import java.util.HashSet; import java.util.Set; @@ -39,6 +40,11 @@ public static void remove(Player player) { } public static class RemoveCommandEvents implements Listener { + @EventHandler (ignoreCancelled = true) + public void quitEvent(PlayerQuitEvent event) { + removingPlayers.remove(event.getPlayer().getUniqueId()); + } + @EventHandler(priority = EventPriority.LOWEST) public void removeEliteEntity(EntityDamageByEntityEvent event) { if (!removingPlayers.contains(event.getDamager().getUniqueId())) return; diff --git a/src/main/java/com/magmaguy/elitemobs/config/ConfigurationExporter.java b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationExporter.java index d24ed9fe3..5b2af23f4 100644 --- a/src/main/java/com/magmaguy/elitemobs/config/ConfigurationExporter.java +++ b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationExporter.java @@ -2,8 +2,8 @@ import com.magmaguy.elitemobs.ChatColorConverter; import com.magmaguy.elitemobs.MetadataHandler; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModel; import com.magmaguy.elitemobs.utils.*; -import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -44,42 +44,28 @@ public static void initializeConfigs() { } public static void createResourcePack(CommandSender commandSender) { - if (!Bukkit.getPluginManager().isPluginEnabled("ModelEngine")) { + if (!CustomModel.isUsingModels()) { commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Could not generate resource pack because ModelEngine is not installed! Install ModelEngine to use this feature.")); return; } - File modelEngineResourcePackFile = new File(MetadataHandler.PLUGIN.getDataFolder().getParentFile().toString() + File.separatorChar + "ModelEngine" + File.separatorChar + "resource pack"); - if (!modelEngineResourcePackFile.exists()) { - commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Could not generate resource pack because ModelEngine is not installed! Install ModelEngine to use this feature.")); - return; - } - - - try { - if (!Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack").toFile().exists()) - Files.createDirectory(Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack")); - } catch (Exception ex) { - commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Failed to generate target directory plugins/EliteMobs/exports/elitemobs_resource_pack required for storing the resource pack! Report this to the dev!")); - return; + if (CustomModel.getModelPlugin() == CustomModel.ModelPlugin.FREE_MINECRAFT_MODELS) { + copyResourcePack(commandSender, "FreeMinecraftModels", "output"); + commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&f Copied all files from Free Minecraft Models to " + MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack")); + } else { + copyResourcePack(commandSender, "ModelEngine", "resource pack"); + commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&f Copied all files from Model Engine to " + MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack")); } - copyDirectory(modelEngineResourcePackFile, Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack")); - commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&f Copied all files from Model Engine to " + MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack")); - - if (ZipFile.zip(new File(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack"), - MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip")) - commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&f Packaged texture pack into " + - MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip") + - " , ready to distribute!"); + if (ZipFile.zip(new File(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack"), MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip")) + commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&f Packaged texture pack into " + MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip") + " , ready to distribute!"); else { commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Failed to package the resource pack into a zipped file! Report this to the dev!")); return; } if (commandSender instanceof Player) { - ((Player) commandSender).spigot().sendMessage(SpigotMessage.commandHoverMessage(ChatColorConverter.convert("Done! &2You can click here to update your server.properties with the new SHA1 value of this texture pack!"), - "Click runs the /em updateresourcepack command!", "/em updateresourcepack")); + ((Player) commandSender).spigot().sendMessage(SpigotMessage.commandHoverMessage(ChatColorConverter.convert("Done! &2You can click here to update your server.properties with the new SHA1 value of this texture pack!"), "Click runs the /em updateresourcepack command!", "/em updateresourcepack")); commandSender.sendMessage("If you want to do it manually, your SHA1 code is " + generateResourcePackSHA1(commandSender)); } else { commandSender.sendMessage("Done! You can run the command /em updateresourcepack in order to put the right SHA1 value into server.properties. Don't forget to upload the texture place to some place where players can get it!"); @@ -88,6 +74,25 @@ public static void createResourcePack(CommandSender commandSender) { } + private static void copyResourcePack(CommandSender commandSender, String pluginDirectoryName, String resourcePackFolderName) { + File originalResourcePackFile = new File(MetadataHandler.PLUGIN.getDataFolder().getParentFile().toString() + File.separatorChar + pluginDirectoryName + File.separatorChar + resourcePackFolderName); + if (!originalResourcePackFile.exists()) { + commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Could not generate resource pack because ModelEngine is not installed! Install ModelEngine to use this feature.")); + return; + } + + + try { + if (!Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack").toFile().exists()) + Files.createDirectory(Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack")); + } catch (Exception ex) { + commandSender.sendMessage(ChatColorConverter.convert("&8[EliteMobs]&c Failed to generate target directory plugins/EliteMobs/exports/elitemobs_resource_pack required for storing the resource pack! Report this to the dev!")); + return; + } + + copyDirectory(originalResourcePackFile, Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack")); + } + private static String generateResourcePackSHA1(CommandSender commandSender) { File zippedResourcePack = Paths.get(MetadataHandler.PLUGIN.getDataFolder() + "" + File.separatorChar + "exports" + File.separatorChar + "elitemobs_resource_pack.zip").toFile(); if (!zippedResourcePack.exists()) { @@ -115,8 +120,7 @@ public static String sha1Code(File file) throws IOException, NoSuchAlgorithmExce DigestInputStream digestInputStream = new DigestInputStream(fileInputStream, digest); byte[] bytes = new byte[1024]; // read all file content - while (digestInputStream.read(bytes) > 0) - digest = digestInputStream.getMessageDigest(); + while (digestInputStream.read(bytes) > 0) digest = digestInputStream.getMessageDigest(); byte[] resultByteArry = digest.digest(); return bytesToHexString(resultByteArry); } @@ -154,12 +158,10 @@ private static void copyFile(File file, Path targetPath) { for (File iteratedFile : file.listFiles()) copyFile(iteratedFile, Paths.get(targetPath + "" + File.separatorChar + file.getName())); } else { - if (!Paths.get(targetPath + "" + File.separatorChar + file.getName()).toFile().exists() || - !targetPath.toString().contains("pack.png") && !targetPath.toString().contains("pack.mcmeta")) { + if (!Paths.get(targetPath + "" + File.separatorChar + file.getName()).toFile().exists() || !targetPath.toString().contains("pack.png") && !targetPath.toString().contains("pack.mcmeta")) { if (!targetPath.toFile().exists()) targetPath.toFile().mkdirs(); Files.copy(file.toPath(), Paths.get(targetPath + "" + File.separatorChar + file.getName()), StandardCopyOption.REPLACE_EXISTING); - } - else + } else new InfoMessage("File " + targetPath + "" + File.separatorChar + file.getName() + " already existed and should not be overwritten, skipping!"); } } catch (Exception exception) { @@ -187,8 +189,7 @@ public static void overwriteSHA1(CommandSender commandSender) { if (ServerPropertiesModifier.modify(commandSender, "resource-pack-sha1", sha1)) { commandSender.sendMessage(ChatColor.GREEN + "[EliteMobs] Successfully set the value resource-pack-sha1=" + sha1 + " in server.properties!"); - commandSender.sendMessage(ChatColor.RED + "[EliteMobs] Don't forget to update the downloadable resource pack at your online location of choice!" + - " If you don't update the version people download things won't work correctly!"); + commandSender.sendMessage(ChatColor.RED + "[EliteMobs] Don't forget to update the downloadable resource pack at your online location of choice!" + " If you don't update the version people download things won't work correctly!"); commandSender.sendMessage(ChatColor.GREEN + "[EliteMobs] The server.properties modification will work starting with the next restart!"); } else { commandSender.sendMessage(ChatColor.RED + "[EliteMobs] Failed to write SHA1 value! You will have to add this manually. For reference, you SHA1 value is " + sha1); diff --git a/src/main/java/com/magmaguy/elitemobs/config/ConfigurationImporter.java b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationImporter.java index ceca63193..14ca72720 100644 --- a/src/main/java/com/magmaguy/elitemobs/config/ConfigurationImporter.java +++ b/src/main/java/com/magmaguy/elitemobs/config/ConfigurationImporter.java @@ -2,7 +2,7 @@ import com.magmaguy.elitemobs.ChatColorConverter; import com.magmaguy.elitemobs.MetadataHandler; -import com.magmaguy.elitemobs.thirdparty.modelengine.CustomModel; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModel; import com.magmaguy.elitemobs.utils.InfoMessage; import com.magmaguy.elitemobs.utils.SpigotMessage; import com.magmaguy.elitemobs.utils.WarningMessage; @@ -41,15 +41,13 @@ public static void initializeConfigs() { return; } - if (importsFile.listFiles().length == 0) - return; + if (importsFile.listFiles().length == 0) return; boolean importedModels = false; for (File zippedFile : importsFile.listFiles()) { File unzippedFile; try { - if (zippedFile.getName().contains(".zip")) - unzippedFile = ZipFile.unzip(zippedFile.getName()); + if (zippedFile.getName().contains(".zip")) unzippedFile = ZipFile.unzip(zippedFile.getName()); else unzippedFile = zippedFile; } catch (Exception e) { new WarningMessage("Failed to unzip config file " + zippedFile.getName() + " ! Tell the dev!"); @@ -100,14 +98,14 @@ public static void initializeConfigs() { break; case "ModelEngine": //todo: check if the "force" code is required, check if file is getting saved with modelengine doesn't have a configuration folder - if (Bukkit.getPluginManager().isPluginEnabled("ModelEngine_Beta")) //todo: this is just temporary - moveDirectory(file, Paths.get(file.getParentFile().getParentFile().getParentFile().getParentFile().toString() - + File.separatorChar + "ModelEngine_Beta" + File.separatorChar + "blueprints"), true); - moveDirectory(file, Paths.get(file.getParentFile().getParentFile().getParentFile().getParentFile().toString() - + File.separatorChar + "ModelEngine" + File.separatorChar + "blueprints"), true); - if (Bukkit.getPluginManager().isPluginEnabled("ModelEngine")) { + if (CustomModel.getModelPlugin() == CustomModel.ModelPlugin.MODEL_ENGINE) + moveDirectory(file, Paths.get(file.getParentFile().getParentFile().getParentFile().getParentFile().toString() + File.separatorChar + "ModelEngine" + File.separatorChar + "blueprints"), true); + else + moveDirectory(file, Paths.get(file.getParentFile().getParentFile().getParentFile().getParentFile().toString() + File.separatorChar + "FreeMinecraftModels" + File.separatorChar + "imports"), true); + if (CustomModel.customModelsEnabled()) { importedModels = true; - } else new WarningMessage("You need ModelEngine to use custom models!"); + } else + new WarningMessage("You need FreeMinecraftModels or ModelEngine (ModelEngine R3 specifically, R4+ won't work) to use custom models!"); break; case "schematics": moveDirectory(file, Paths.get(configurationsPath.normalize() + "" + File.separatorChar + "schematics"), false); @@ -135,22 +133,15 @@ public static void initializeConfigs() { CustomModel.reloadModels(); for (Player player : Bukkit.getOnlinePlayers()) if (player.hasPermission("elitemobs.*")) - player.spigot().sendMessage(SpigotMessage.commandHoverMessage( - ChatColorConverter.convert("&8[EliteMobs] &fEliteMobs just detected that recently imported files had Custom Models in them! " + - "&2Click here to generate the EliteMobs resource pack for those models!"), - "Clicking will run the command /em generateresourcepack", - "/em generateresourcepack")); + player.spigot().sendMessage(SpigotMessage.commandHoverMessage(ChatColorConverter.convert("&8[EliteMobs] &fEliteMobs just detected that recently imported files had Custom Models in them! " + "&2Click here to generate the EliteMobs resource pack for those models!"), "Clicking will run the command /em generateresourcepack", "/em generateresourcepack")); } } private static void deleteDirectory(File file) { - if (file == null) - return; - if (file.isDirectory()) - for (File iteratedFile : file.listFiles()) - if (iteratedFile != null) - deleteDirectory(iteratedFile); + if (file == null) return; + if (file.isDirectory()) for (File iteratedFile : file.listFiles()) + if (iteratedFile != null) deleteDirectory(iteratedFile); new InfoMessage("Cleaning up " + file.getPath()); file.delete(); } diff --git a/src/main/java/com/magmaguy/elitemobs/config/customarenas/CustomArenasConfigFields.java b/src/main/java/com/magmaguy/elitemobs/config/customarenas/CustomArenasConfigFields.java index ce1e45eb3..0ea2b3740 100644 --- a/src/main/java/com/magmaguy/elitemobs/config/customarenas/CustomArenasConfigFields.java +++ b/src/main/java/com/magmaguy/elitemobs/config/customarenas/CustomArenasConfigFields.java @@ -5,6 +5,7 @@ import com.magmaguy.elitemobs.items.customloottable.CustomLootTable; import lombok.Getter; import lombok.Setter; +import org.bukkit.Location; import java.util.ArrayList; import java.util.List; @@ -59,6 +60,8 @@ public class CustomArenasConfigFields extends CustomConfigFields implements Cust @Getter @Setter private String permission = null; + @Getter + private Location teleportLocation = null; public CustomArenasConfigFields(String filename, boolean isEnabled) { super(filename, isEnabled); @@ -83,6 +86,7 @@ public void processConfigFields() { this.arenaMessages = translatable(filename, "arenaMessages", processStringList("arenaMessages", arenaMessages, new ArrayList<>(), false)); this.cylindricalArena = processBoolean("cylindricalArena", cylindricalArena, false, false); this.permission = processString("permission", permission, null, false); + this.teleportLocation = processLocation("teleportLocation", teleportLocation, null, false); } } diff --git a/src/main/java/com/magmaguy/elitemobs/config/custombosses/CustomBossesConfigFields.java b/src/main/java/com/magmaguy/elitemobs/config/custombosses/CustomBossesConfigFields.java index c40c25fd2..6483dfbe8 100644 --- a/src/main/java/com/magmaguy/elitemobs/config/custombosses/CustomBossesConfigFields.java +++ b/src/main/java/com/magmaguy/elitemobs/config/custombosses/CustomBossesConfigFields.java @@ -8,11 +8,10 @@ import com.magmaguy.elitemobs.items.customloottable.CustomLootTable; import com.magmaguy.elitemobs.mobconstructor.mobdata.aggressivemobs.EliteMobProperties; import com.magmaguy.elitemobs.powers.scripts.caching.EliteScriptBlueprint; -import com.magmaguy.elitemobs.thirdparty.modelengine.CustomModel; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModel; import com.magmaguy.elitemobs.utils.WarningMessage; import lombok.Getter; import lombok.Setter; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.EntityType; @@ -380,7 +379,7 @@ public void processConfigFields() { } public boolean isCustomModelExists() { - if (Bukkit.getPluginManager().isPluginEnabled("ModelEngine") && CustomModel.modelExists(customModel)) + if (CustomModel.customModelsEnabled() && CustomModel.modelExists(customModel)) return customModelExists = true; return false; } diff --git a/src/main/java/com/magmaguy/elitemobs/events/CustomEvent.java b/src/main/java/com/magmaguy/elitemobs/events/CustomEvent.java index fd84ba786..8ed92029a 100644 --- a/src/main/java/com/magmaguy/elitemobs/events/CustomEvent.java +++ b/src/main/java/com/magmaguy/elitemobs/events/CustomEvent.java @@ -59,7 +59,7 @@ public static boolean isLocationValid(Location location) { if (!ValidWorldsConfig.getValidWorlds().contains(Objects.requireNonNull(location.getWorld()).getName())) return false; return !(EliteMobs.worldGuardIsEnabled && - !WorldGuardFlagChecker.checkFlag(location, WorldGuardCompatibility.getEliteMobsEventsFlag())); + !WorldGuardFlagChecker.checkFlag(location, WorldGuardCompatibility.getELITEMOBS_EVENTS())); } public CustomEventsConfigFields getCustomEventsConfigFields() { diff --git a/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaEntity.java b/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaEntity.java index e419e80c2..7de2d2a72 100644 --- a/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaEntity.java +++ b/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaEntity.java @@ -18,6 +18,12 @@ public class ArenaEntity { @Getter @Setter private String bossfile; + @Getter + @Setter + private boolean mythicMob = false; + @Getter + @Setter + private int level = -1; public ArenaEntity(String spawnPointName, int wave, String bossfile) { this.spawnPointName = spawnPointName; diff --git a/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaInstance.java b/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaInstance.java index ca6e9086a..c781d92e4 100644 --- a/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaInstance.java +++ b/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaInstance.java @@ -12,6 +12,7 @@ import com.magmaguy.elitemobs.instanced.MatchInstance; import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity; import com.magmaguy.elitemobs.playerdata.database.PlayerData; +import com.magmaguy.elitemobs.thirdparty.mythicmobs.MythicMobsInterface; import com.magmaguy.elitemobs.utils.ConfigurationLocation; import com.magmaguy.elitemobs.utils.EventCaller; import com.magmaguy.elitemobs.utils.WarningMessage; @@ -19,6 +20,7 @@ import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -39,6 +41,7 @@ public class ArenaInstance extends MatchInstance { private final ArenaWaves arenaWaves; @Getter private final HashSet customBosses = new HashSet<>(); + private final HashSet nonEliteMobsEntities = new HashSet<>(); private final HashMap waveMessage = new HashMap<>(); private final int minX; private final int maxX; @@ -60,6 +63,7 @@ public ArenaInstance(CustomArenasConfigFields customArenasConfigFields, Location super(startLocation, exitLocation, customArenasConfigFields.getMinimumPlayerCount(), customArenasConfigFields.getMaximumPlayerCount()); this.cylindricalArena = customArenasConfigFields.isCylindricalArena(); + super.lobbyLocation = customArenasConfigFields.getTeleportLocation(); if (corner1.getX() < corner2.getX()) { minX = (int) corner1.getX(); @@ -215,33 +219,48 @@ public void run() { if (arenaState != ArenaState.ACTIVE) return; for (CustomBossEntity customBossEntity : (HashSet) customBosses.clone()) if (!customBossEntity.exists()) removeBoss(customBossEntity); + if (!nonEliteMobsEntities.isEmpty()) + for (Entity entity : (HashSet) nonEliteMobsEntities.clone()) + if (!entity.isValid()) removeBoss(entity); } }.runTaskTimer(MetadataHandler.PLUGIN, 0L, 20L); } public void removeBoss(CustomBossEntity customBossEntity) { customBosses.remove(customBossEntity); - if (customBosses.isEmpty()) nextWave(); + if (customBosses.isEmpty() && nonEliteMobsEntities.isEmpty()) nextWave(); + } + + public void removeBoss(Entity nonEliteEntity) { + nonEliteMobsEntities.remove(nonEliteEntity); + if (customBosses.isEmpty() && nonEliteMobsEntities.isEmpty()) nextWave(); } private void spawnBosses() { if (arenaWaves.getWaveEntities(currentWave) == null) return; for (ArenaEntity arenaEntity : arenaWaves.getWaveEntities(currentWave)) { - CustomBossEntity customBossEntity = CustomBossEntity.createCustomBossEntity(arenaEntity.getBossfile()); - if (customBossEntity == null) { - new WarningMessage("Failed to generate custom boss " + arenaEntity.getBossfile() + " because the filename was not valid!"); - continue; + if (!arenaEntity.isMythicMob()) { + CustomBossEntity customBossEntity = CustomBossEntity.createCustomBossEntity(arenaEntity.getBossfile()); + if (customBossEntity == null) { + new WarningMessage("Failed to generate custom boss " + arenaEntity.getBossfile() + " because the filename was not valid!"); + continue; + } + customBossEntity.setNormalizedCombat(); + customBossEntity.setEliteLoot(false); + customBossEntity.setVanillaLoot(false); + customBossEntity.setRandomLoot(false); + customBossEntity.spawn(spawnPoints.get(arenaEntity.getSpawnPointName()), true); + if (!customBossEntity.exists()) { + new WarningMessage("Arena " + getCustomArenasConfigFields().getArenaName() + " failed to spawn boss " + customBossEntity.getCustomBossesConfigFields().getFilename()); + continue; + } else customBosses.add(customBossEntity); + + } else { + //MythicMobs integration + Entity mythicMob = MythicMobsInterface.spawn(spawnPoints.get(arenaEntity.getSpawnPointName()),arenaEntity.getBossfile(), arenaEntity.getLevel()); + if (mythicMob != null) nonEliteMobsEntities.add(mythicMob); } - customBossEntity.setNormalizedCombat(); - customBossEntity.setEliteLoot(false); - customBossEntity.setVanillaLoot(false); - customBossEntity.setRandomLoot(false); - customBossEntity.spawn(spawnPoints.get(arenaEntity.getSpawnPointName()), true); - if (!customBossEntity.exists()) { - new WarningMessage("Arena " + getCustomArenasConfigFields().getArenaName() + " failed to spawn boss " + customBossEntity.getCustomBossesConfigFields().getFilename()); - continue; - } else customBosses.add(customBossEntity); } } diff --git a/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaWaves.java b/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaWaves.java index 2746277be..f2f8a9b00 100644 --- a/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaWaves.java +++ b/src/main/java/com/magmaguy/elitemobs/instanced/arena/ArenaWaves.java @@ -11,13 +11,15 @@ public class ArenaWaves { private final HashMap> arenaEntities = new HashMap(); - //wave=X:spawnPoint=Y:boss=Z.yml + //wave=X:spawnPoint=Y:boss=Z.yml:mythicmob=false public ArenaWaves(List rawBosses) { for (String iteratedBoss : rawBosses) { String[] subString = iteratedBoss.split(":"); String waveString = ""; String spawnpointString = ""; String boss = ""; + String mythicMobString = ""; + String levelString = ""; for (String iteratedString : subString) { String[] valuesString = iteratedString.split("="); switch (valuesString[0].toLowerCase(Locale.ROOT)) { @@ -30,6 +32,12 @@ public ArenaWaves(List rawBosses) { case "boss": boss = valuesString[1]; break; + case "mythicmob": + mythicMobString = valuesString[1]; + break; + case "level": + levelString = valuesString[1]; + break; } } int wave; @@ -39,7 +47,25 @@ public ArenaWaves(List rawBosses) { new WarningMessage("Invalid value for wave in arena wave: " + waveString); continue; } + boolean mythicMob; + if (mythicMobString.isEmpty()) mythicMob = false; + else + try { + mythicMob = Boolean.valueOf(mythicMobString); + } catch (Exception exception) { + new WarningMessage("Invalid value for mythic mob in arena wave: " + waveString); + continue; + } + int level = -1; + if (!levelString.isEmpty()) try { + level = Integer.valueOf(levelString); + } catch (Exception exception) { + new WarningMessage("Invalid value for level in: " + levelString); + continue; + } ArenaEntity arenaEntity = new ArenaEntity(spawnpointString, wave, boss); + if (mythicMob) arenaEntity.setMythicMob(true); + if (level != -1) arenaEntity.setLevel(level); if (arenaEntities.get(wave) == null) arenaEntities.put(wave, new ArrayList<>(List.of(arenaEntity))); else diff --git a/src/main/java/com/magmaguy/elitemobs/items/ItemLootShower.java b/src/main/java/com/magmaguy/elitemobs/items/ItemLootShower.java index d3a4c1f9d..19d0c6ac1 100644 --- a/src/main/java/com/magmaguy/elitemobs/items/ItemLootShower.java +++ b/src/main/java/com/magmaguy/elitemobs/items/ItemLootShower.java @@ -209,7 +209,6 @@ private Item generateCurrencyItem(Material material, Location location, double v } setCoinModel(currencyItemStack, model); Item currencyItem = location.getWorld().dropItem(location.clone().add(new Vector(0, 1, 0)), currencyItemStack); - currencyItem.setPickupDelay(Integer.MAX_VALUE); EntityTracker.registerVisualEffects(currencyItem); currencyItem.setInvulnerable(true); diff --git a/src/main/java/com/magmaguy/elitemobs/items/customenchantments/DrillingEnchantment.java b/src/main/java/com/magmaguy/elitemobs/items/customenchantments/DrillingEnchantment.java index a6c11cd39..693660bae 100644 --- a/src/main/java/com/magmaguy/elitemobs/items/customenchantments/DrillingEnchantment.java +++ b/src/main/java/com/magmaguy/elitemobs/items/customenchantments/DrillingEnchantment.java @@ -1,6 +1,7 @@ package com.magmaguy.elitemobs.items.customenchantments; import com.magmaguy.elitemobs.MetadataHandler; +import com.magmaguy.elitemobs.config.enchantments.EnchantmentsConfig; import com.magmaguy.elitemobs.items.ItemTagger; import com.magmaguy.elitemobs.utils.EventCaller; import org.bukkit.Location; @@ -36,13 +37,13 @@ public static class DrillingEnchantmentEvents implements Listener { @EventHandler(priority = EventPriority.HIGHEST) public void onDig(BlockBreakEvent event) { if (event.isCancelled()) return; - if (event.getPlayer().isSneaking()) return; - if (activePlayers.contains(event.getPlayer())) return; if (!event.getPlayer().getInventory().getItemInMainHand().hasItemMeta() || event.getPlayer().getInventory().getItemInMainHand().getItemMeta() == null) return; if (!ItemTagger.hasEnchantment(event.getPlayer().getInventory().getItemInMainHand().getItemMeta(), new NamespacedKey(MetadataHandler.PLUGIN, key))) return; - + if (event.getPlayer().isSneaking()) return; + if (!EnchantmentsConfig.getEnchantment("drilling.yml").isEnabled()) return; + if (activePlayers.contains(event.getPlayer())) return; drillBlocks(event.getBlock(), ItemTagger.getEnchantment(event.getPlayer().getInventory().getItemInMainHand().getItemMeta(), new NamespacedKey(MetadataHandler.PLUGIN, key)), diff --git a/src/main/java/com/magmaguy/elitemobs/items/customloottable/CommandLootTable.java b/src/main/java/com/magmaguy/elitemobs/items/customloottable/CommandLootTable.java new file mode 100644 index 000000000..f374830f7 --- /dev/null +++ b/src/main/java/com/magmaguy/elitemobs/items/customloottable/CommandLootTable.java @@ -0,0 +1,84 @@ +package com.magmaguy.elitemobs.items.customloottable; + +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.io.Serializable; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.ThreadLocalRandom; + +public class CommandLootTable extends CustomLootEntry implements Serializable { + @Getter + private String command = null; + + public CommandLootTable(List entries, String rawString, String configFilename) { + super(); + parseNewFormat(rawString, configFilename); + entries.add(this); + } + + //Format: command=my cool command:chance=X.Y:amount=X:permission=per.miss.ion + private void parseNewFormat(String rawString, String configFilename) { + for (String string : rawString.split(":")) { + String[] strings = string.split("="); + switch (strings[0].toLowerCase(Locale.ROOT)) { + case "command": + try { + this.command = strings[1]; + } catch (Exception ex) { + errorMessage(rawString, configFilename, "filename"); + } + break; + case "amount": + try { + super.setAmount(Integer.parseInt(strings[1])); + } catch (Exception ex) { + errorMessage(rawString, configFilename, "amount"); + } + break; + case "chance": + try { + super.setChance(Double.parseDouble(strings[1])); + } catch (Exception ex) { + errorMessage(rawString, configFilename, "chance"); + } + break; + case "permission": + try { + super.setPermission(strings[1]); + } catch (Exception ex) { + errorMessage(rawString, configFilename, "permission"); + } + break; + case "wave": + try { + super.setWave(Integer.parseInt(strings[1])); + } catch (Exception ex) { + errorMessage(rawString, configFilename, "wave"); + } + break; + default: + } + } + } + + //treasure chest + @Override + public void locationDrop(int itemTier, Player player, Location location) { + if (!getPermission().isEmpty() && !player.hasPermission(getPermission())) return; + if (ThreadLocalRandom.current().nextDouble() < getChance()) return; + for (int i = 0; i < getAmount(); i++) + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("%player%", player.getName())); + } + + @Override + public void directDrop(int itemTier, Player player) { + if (!getPermission().isEmpty() && !player.hasPermission(getPermission())) return; + if (ThreadLocalRandom.current().nextDouble() < getChance()) return; + for (int i = 0; i < getAmount(); i++) + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("%player%", player.getName())); + } +} diff --git a/src/main/java/com/magmaguy/elitemobs/items/customloottable/CustomLootTable.java b/src/main/java/com/magmaguy/elitemobs/items/customloottable/CustomLootTable.java index 1016ee633..3fdcb9b53 100644 --- a/src/main/java/com/magmaguy/elitemobs/items/customloottable/CustomLootTable.java +++ b/src/main/java/com/magmaguy/elitemobs/items/customloottable/CustomLootTable.java @@ -56,6 +56,7 @@ private void parseConfig(List lootTable, String filename) { if (rawString.toLowerCase(Locale.ROOT).contains("currencyamount=")) new CurrencyCustomLootEntry(entries, rawString, filename); else if (rawString.contains("material=")) new VanillaCustomLootEntry(entries, rawString, filename); + else if (rawString.contains("command=")) new CommandLootTable(entries, rawString, filename); else new EliteCustomLootEntry(entries, rawString, filename); } else if (object instanceof Map configMap) diff --git a/src/main/java/com/magmaguy/elitemobs/items/customloottable/EliteCustomLootEntry.java b/src/main/java/com/magmaguy/elitemobs/items/customloottable/EliteCustomLootEntry.java index 1012ecbc3..c609777f4 100644 --- a/src/main/java/com/magmaguy/elitemobs/items/customloottable/EliteCustomLootEntry.java +++ b/src/main/java/com/magmaguy/elitemobs/items/customloottable/EliteCustomLootEntry.java @@ -20,7 +20,6 @@ import java.util.Map; public class EliteCustomLootEntry extends CustomLootEntry implements Serializable { - private final String permission = null; @Getter private String filename = null; private String difficultyID = null; diff --git a/src/main/java/com/magmaguy/elitemobs/mobconstructor/EliteEntity.java b/src/main/java/com/magmaguy/elitemobs/mobconstructor/EliteEntity.java index 2944caaae..38b037a90 100644 --- a/src/main/java/com/magmaguy/elitemobs/mobconstructor/EliteEntity.java +++ b/src/main/java/com/magmaguy/elitemobs/mobconstructor/EliteEntity.java @@ -61,7 +61,7 @@ public class EliteEntity { protected LivingEntity unsyncedLivingEntity; @Getter @Setter - protected int level; + protected int level = -1; @Getter protected double maxHealth; @Getter diff --git a/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/CustomBossEntity.java b/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/CustomBossEntity.java index a27a8cc64..d6dc6636e 100644 --- a/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/CustomBossEntity.java +++ b/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/CustomBossEntity.java @@ -20,9 +20,9 @@ import com.magmaguy.elitemobs.playerdata.ElitePlayerInventory; import com.magmaguy.elitemobs.powers.meta.CustomSummonPower; import com.magmaguy.elitemobs.powers.meta.ElitePower; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModel; import com.magmaguy.elitemobs.thirdparty.discordsrv.DiscordSRVAnnouncement; import com.magmaguy.elitemobs.thirdparty.libsdisguises.DisguiseEntity; -import com.magmaguy.elitemobs.thirdparty.modelengine.CustomModel; import com.magmaguy.elitemobs.utils.*; import lombok.Getter; import lombok.Setter; @@ -203,8 +203,8 @@ public void spawn(boolean silent) { return; } - //This is a bit dumb but -1 is reserved for dynamic levels - if (customBossesConfigFields.getLevel() == -1) + //This is a bit dumb but -1 is reserved for dynamic levels, commands can force a dynamic to spawn with a level so check that + if (customBossesConfigFields.getLevel() == -1 && level == -1) getDynamicLevel(spawnLocation); if (ChunkLocationChecker.locationIsLoaded(spawnLocation) || isMount) { @@ -218,7 +218,11 @@ public void spawn(boolean silent) { //this may seem odd but not setting it to null can cause double spawn attempts as the plugin catches itself //correctly as not have a valid living entity but the checks are set up in such a way that if a living entity //object is referenced then trying to spawn it again is a double spawn of the same entity - super.livingEntity = null; + if (super.livingEntity != null) { + //Under very specific chunk loading conditions mobs can double spawn. It's never incorrect to remove the living entity silently when it spawns + super.livingEntity.remove(); + super.livingEntity = null; + } if (existsFailureCount > 10) { if (existsFailureCount == 11) { new WarningMessage("EliteMobs tried and failed to spawn " + customBossesConfigFields.getFilename() + " " + existsFailureCount + "times, probably due to regional protections or third party plugin incompatibilities."); diff --git a/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/CustomBossMegaConsumer.java b/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/CustomBossMegaConsumer.java index 469cddda8..e46a0d291 100644 --- a/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/CustomBossMegaConsumer.java +++ b/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/CustomBossMegaConsumer.java @@ -6,8 +6,8 @@ import com.magmaguy.elitemobs.config.custombosses.CustomBossesConfigFields; import com.magmaguy.elitemobs.entitytracker.EntityTracker; import com.magmaguy.elitemobs.powers.meta.ElitePower; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModel; import com.magmaguy.elitemobs.thirdparty.libsdisguises.DisguiseEntity; -import com.magmaguy.elitemobs.thirdparty.modelengine.CustomModel; import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardCompatibility; import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardFlagChecker; import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardSpawnEventBypasser; @@ -61,7 +61,7 @@ public LivingEntity spawn() { return null; } if (EliteMobs.worldGuardIsEnabled) { - if (!WorldGuardFlagChecker.checkFlag(spawnLocation, WorldGuardCompatibility.getEliteMobsSpawnFlag())) { + if (!WorldGuardFlagChecker.checkFlag(spawnLocation, WorldGuardCompatibility.getELITEMOBS_SPAWN_FLAG())) { new WarningMessage("Attempted to spawn " + customBossesConfigFields.getFilename() + " in location " + spawnLocation + " which is protected by WorldGuard with elitemobs-spawning deny! This should not have happened."); return null; @@ -114,7 +114,7 @@ private void setBaby(LivingEntity livingEntity) { private void setDisguise(LivingEntity livingEntity) { if (customBossesConfigFields.getDisguise() == null || - Bukkit.getPluginManager().isPluginEnabled("ModelEngine") && + CustomModel.customModelsEnabled() && customBossesConfigFields.isCustomModelExists() && customBossesConfigFields.getCustomModel() != null && !customBossesConfigFields.getCustomModel().isEmpty()) @@ -128,8 +128,6 @@ private void setDisguise(LivingEntity livingEntity) { } private void setCustomModel(LivingEntity livingEntity) { - if (!Bukkit.getPluginManager().isPluginEnabled("ModelEngine")) - return; if (!customBossesConfigFields.isCustomModelExists()) return; if (customBossesConfigFields.getCustomModel() == null || customBossesConfigFields.getCustomModel().isEmpty()) return; diff --git a/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/RegionalBossEntity.java b/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/RegionalBossEntity.java index 617adaf3a..2058b84d8 100644 --- a/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/RegionalBossEntity.java +++ b/src/main/java/com/magmaguy/elitemobs/mobconstructor/custombosses/RegionalBossEntity.java @@ -322,7 +322,7 @@ public void onNewMinidungeonRelativeBossLocationEvent(NewSchematicPackageRelativ } public void removeSlow() { - if (getCustomBossesConfigFields().isAlert()) return; + if (getCustomBossesConfigFields().isAlert() || getLivingEntity() == null) return; getLivingEntity().getAttribute(Attribute.GENERIC_FOLLOW_RANGE).setBaseValue(getFollowDistance()); getLivingEntity().getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(getMovementSpeedAttribute()); } diff --git a/src/main/java/com/magmaguy/elitemobs/mobspawning/NaturalMobSpawnEventHandler.java b/src/main/java/com/magmaguy/elitemobs/mobspawning/NaturalMobSpawnEventHandler.java index 220ba90b5..35ce21a3f 100644 --- a/src/main/java/com/magmaguy/elitemobs/mobspawning/NaturalMobSpawnEventHandler.java +++ b/src/main/java/com/magmaguy/elitemobs/mobspawning/NaturalMobSpawnEventHandler.java @@ -96,7 +96,7 @@ public void onSpawn(CreatureSpawnEvent event) { return; if (EliteMobs.worldGuardIsEnabled) - if (!WorldGuardFlagChecker.checkFlag(event.getLocation(), WorldGuardCompatibility.getEliteMobsSpawnFlag())) + if (!WorldGuardFlagChecker.checkFlag(event.getLocation(), WorldGuardCompatibility.getELITEMOBS_SPAWN_FLAG())) return; //This fires for custom bosses, so don't override those spawns diff --git a/src/main/java/com/magmaguy/elitemobs/npcs/NPCEntity.java b/src/main/java/com/magmaguy/elitemobs/npcs/NPCEntity.java index 0e1eb8b40..7d63878f2 100644 --- a/src/main/java/com/magmaguy/elitemobs/npcs/NPCEntity.java +++ b/src/main/java/com/magmaguy/elitemobs/npcs/NPCEntity.java @@ -12,8 +12,8 @@ import com.magmaguy.elitemobs.mobconstructor.PersistentObject; import com.magmaguy.elitemobs.mobconstructor.PersistentObjectHandler; import com.magmaguy.elitemobs.npcs.chatter.NPCChatBubble; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModel; import com.magmaguy.elitemobs.thirdparty.libsdisguises.DisguiseEntity; -import com.magmaguy.elitemobs.thirdparty.modelengine.CustomModel; import com.magmaguy.elitemobs.thirdparty.worldguard.WorldGuardSpawnEventBypasser; import com.magmaguy.elitemobs.utils.ChunkLocationChecker; import com.magmaguy.elitemobs.utils.ConfigurationLocation; diff --git a/src/main/java/com/magmaguy/elitemobs/pathfinding/Navigation.java b/src/main/java/com/magmaguy/elitemobs/pathfinding/Navigation.java index 20734a5b6..b6b8d4ae3 100644 --- a/src/main/java/com/magmaguy/elitemobs/pathfinding/Navigation.java +++ b/src/main/java/com/magmaguy/elitemobs/pathfinding/Navigation.java @@ -59,7 +59,7 @@ public void makeReturningBossesInvulnerable(WanderBackToPointStartEvent event) { EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getLivingEntity()); if (!(eliteEntity instanceof RegionalBossEntity regionalBossEntity)) return; event.getLivingEntity().setInvulnerable(true); - eliteEntity.getLivingEntity().getAttribute(Attribute.GENERIC_FOLLOW_RANGE).setBaseValue(regionalBossEntity.getCustomBossesConfigFields().getLeashRadius() * 1.5); + event.getLivingEntity().getAttribute(Attribute.GENERIC_FOLLOW_RANGE).setBaseValue(regionalBossEntity.getCustomBossesConfigFields().getLeashRadius() * 1.5); } @EventHandler(ignoreCancelled = true) diff --git a/src/main/java/com/magmaguy/elitemobs/powers/PlasmaBlaster.java b/src/main/java/com/magmaguy/elitemobs/powers/PlasmaBlaster.java index 77d514210..996495f6f 100644 --- a/src/main/java/com/magmaguy/elitemobs/powers/PlasmaBlaster.java +++ b/src/main/java/com/magmaguy/elitemobs/powers/PlasmaBlaster.java @@ -10,7 +10,6 @@ import org.bukkit.Particle; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; @@ -43,12 +42,12 @@ private void doPower(EliteEntity eliteEntity) { if (entity.getType().equals(EntityType.PLAYER)) { if (((Player) entity).getGameMode().equals(GameMode.SPECTATOR)) continue; Vector shotVector = entity.getLocation().subtract(eliteEntity.getLivingEntity().getLocation()).toVector().normalize().multiply(0.5); - createProjectile(shotVector, eliteEntity.getLocation(), eliteEntity); + createProjectile(shotVector, eliteEntity.getLocation(), eliteEntity, (Player) entity); break; } } - private void createProjectile(Vector shotVector, Location sourceLocation, EliteEntity sourceEntity) { + private void createProjectile(Vector shotVector, Location sourceLocation, EliteEntity sourceEntity, Player player) { new BukkitRunnable() { final Location currentLocation = sourceLocation.clone().add(new Vector(0, 1, 0)); int counter = 0; @@ -60,15 +59,11 @@ public void run() { return; } counter++; - for (Entity entity : currentLocation.getWorld().getNearbyEntities(currentLocation, 0.1 * counter / 12d, 0.1 * counter / 12d, 0.1 * counter / 12d)) { - if (entity.equals(sourceEntity.getLivingEntity())) continue; - if (!(entity instanceof LivingEntity)) continue; - cancel(); - if (entity.getType() == EntityType.PLAYER) doDamage((Player) entity, sourceEntity); - break; - } - doVisualEffect(currentLocation, counter); + if (player.getBoundingBox().overlaps(new Vector(currentLocation.getX() - .5, currentLocation.getY() - .5, currentLocation.getZ() - .5), new Vector(currentLocation.getX() + .5, currentLocation.getY() + .5, currentLocation.getZ() + .5))) + doDamage(player, sourceEntity); + if (counter % 5 == 0) + doVisualEffect(currentLocation, counter); currentLocation.add(shotVector); if (!currentLocation.getBlock().isPassable()) cancel(); @@ -95,7 +90,7 @@ private void doDamageFireworks(Location endLocation) { private void doVisualEffect(Location location, int counter) { location.getWorld().spawnParticle(Particle.REDSTONE, location.getX(), location.getY(), location.getZ(), - 20, 0.1 * counter / 12d, 0.1 * counter / 12d, 0.1 * counter / 12d, 1, new Particle.DustOptions(Color.fromRGB( + 10, 0.1 * counter / 12d, 0.1 * counter / 12d, 0.1 * counter / 12d, 1, new Particle.DustOptions(Color.fromRGB( ThreadLocalRandom.current().nextInt(0, 100), ThreadLocalRandom.current().nextInt(122, 255), ThreadLocalRandom.current().nextInt(0, 100) diff --git a/src/main/java/com/magmaguy/elitemobs/powers/meta/CombatEnterScanPower.java b/src/main/java/com/magmaguy/elitemobs/powers/meta/CombatEnterScanPower.java index abcad0c53..6e91841ca 100644 --- a/src/main/java/com/magmaguy/elitemobs/powers/meta/CombatEnterScanPower.java +++ b/src/main/java/com/magmaguy/elitemobs/powers/meta/CombatEnterScanPower.java @@ -4,6 +4,7 @@ import com.magmaguy.elitemobs.api.EliteMobExitCombatEvent; import com.magmaguy.elitemobs.config.powers.PowersConfigFields; import com.magmaguy.elitemobs.mobconstructor.EliteEntity; +import com.magmaguy.elitemobs.utils.DebugMessage; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.scheduler.BukkitTask; @@ -61,6 +62,7 @@ public void onCombatEnter(EliteMobEnterCombatEvent event) { @EventHandler public void onCombatExit(EliteMobExitCombatEvent event) { + new DebugMessage("Exiting combat for " + event.getEliteMobEntity().getName()); for (CombatEnterScanPower combatEnterScanPower : combatEnterScanPowers) { ElitePower elitePowerInstance = event.getEliteMobEntity().getPower(combatEnterScanPower); if (elitePowerInstance == null) diff --git a/src/main/java/com/magmaguy/elitemobs/powers/scripts/ScriptConditions.java b/src/main/java/com/magmaguy/elitemobs/powers/scripts/ScriptConditions.java index 6f0910e36..4668c4e9b 100644 --- a/src/main/java/com/magmaguy/elitemobs/powers/scripts/ScriptConditions.java +++ b/src/main/java/com/magmaguy/elitemobs/powers/scripts/ScriptConditions.java @@ -21,9 +21,11 @@ public class ScriptConditions { private final ScriptConditionsBlueprint conditionsBlueprint; private ScriptTargets scriptTargets = null; + private EliteScript eliteScript; public ScriptConditions(ScriptConditionsBlueprint scriptConditionsBlueprint, EliteScript eliteScript, boolean actionCondition) { this.conditionsBlueprint = scriptConditionsBlueprint; + this.eliteScript = eliteScript; //This is null if no conditions are set if (conditionsBlueprint.getScriptTargets() != null) this.scriptTargets = new ScriptTargets(conditionsBlueprint.getScriptTargets(), eliteScript); @@ -79,6 +81,7 @@ private boolean isOnFloor(Location targetLocation) { if (conditionsBlueprint.getIsOnFloor() == null) return true; Block currentBlock = targetLocation.getBlock(); Block floorBlock = targetLocation.clone().subtract(0, 1, 0).getBlock(); + //Developer.message("Running isOnFloor" + eliteScript.getFileName()); return conditionsBlueprint.getIsOnFloor() == !currentBlock.getType().isSolid() && floorBlock.getType().isSolid(); } diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/CustomModel.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/CustomModel.java new file mode 100644 index 000000000..33b7f4250 --- /dev/null +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/CustomModel.java @@ -0,0 +1,160 @@ +package com.magmaguy.elitemobs.thirdparty.custommodels; + +import com.magmaguy.elitemobs.api.EliteMobDeathEvent; +import com.magmaguy.elitemobs.entitytracker.EntityTracker; +import com.magmaguy.elitemobs.mobconstructor.EliteEntity; +import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity; +import com.magmaguy.elitemobs.thirdparty.custommodels.freeminecraftmodels.CustomModelFMM; +import com.magmaguy.elitemobs.thirdparty.custommodels.modelengine.CustomModelMEG; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Projectile; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntitySpawnEvent; + + +public class CustomModel implements CustomModelInterface { + @Getter + private static final boolean usingModels = false; + @Getter + private static ModelPlugin modelPlugin; + private CustomModelMEG customModelMEG; + private CustomModelFMM customModelFMM; + private boolean initialized = false; + + private CustomModel(LivingEntity livingEntity, String modelName, String nametagName) { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS: + customModelFMM = new CustomModelFMM(livingEntity, modelName, nametagName); + initialized = true; + break; + case MODEL_ENGINE: + customModelMEG = new CustomModelMEG(livingEntity, modelName, nametagName); + initialized = true; + break; + } + } + + public static void initialize() { + if (Bukkit.getPluginManager().isPluginEnabled("FreeMinecraftModels")) + modelPlugin = ModelPlugin.FREE_MINECRAFT_MODELS; + else if (Bukkit.getPluginManager().isPluginEnabled("ModelEngine") && Bukkit.getPluginManager().getPlugin("ModelEngine").getDescription().getVersion().contains("R3")) + modelPlugin = ModelPlugin.MODEL_ENGINE; + else modelPlugin = ModelPlugin.NONE; + } + + public static void reloadModels() { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS -> CustomModelFMM.reloadModels(); + case MODEL_ENGINE -> CustomModelMEG.reloadModels(); + } + } + + public static boolean modelExists(String modelName) { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS: + return CustomModelFMM.modelExists(modelName); + case MODEL_ENGINE: + return CustomModelMEG.modelExists(modelName); + } + return false; + } + + public static CustomModel generateCustomModel(LivingEntity livingEntity, String modelName, String nametagName) { + CustomModel customModel = new CustomModel(livingEntity, modelName, nametagName); + return customModel.initialized ? customModel : null; + } + + public static boolean customModelsEnabled() { + return modelPlugin != ModelPlugin.NONE; + } + + @Override + public void shoot() { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS -> customModelFMM.shoot(); + case MODEL_ENGINE -> customModelMEG.shoot(); + } + } + + @Override + public void melee() { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS -> customModelFMM.melee(); + case MODEL_ENGINE -> customModelMEG.melee(); + } + } + + @Override + public void playAnimationByName(String animationName) { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS -> customModelFMM.playAnimationByName(animationName); + case MODEL_ENGINE -> customModelMEG.playAnimationByName(animationName); + } + } + + @Override + public void setName(String nametagName, boolean visible) { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS -> customModelFMM.setName(nametagName, visible); + case MODEL_ENGINE -> customModelMEG.setName(nametagName, visible); + } + } + + @Override + public void setNameVisible(boolean visible) { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS -> customModelFMM.setNameVisible(visible); + case MODEL_ENGINE -> customModelMEG.setNameVisible(visible); + } + } + + @Override + public void addPassenger(CustomBossEntity passenger) { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS -> customModelFMM.addPassenger(passenger); + case MODEL_ENGINE -> customModelMEG.addPassenger(passenger); + } + } + + @Override + public void switchPhase() { + switch (modelPlugin) { + case FREE_MINECRAFT_MODELS -> customModelFMM.switchPhase(); + case MODEL_ENGINE -> customModelMEG.switchPhase(); + } + } + + public enum ModelPlugin { + NONE, FREE_MINECRAFT_MODELS, MODEL_ENGINE + } + + public static class ModelEntityEvents implements Listener { + @EventHandler(ignoreCancelled = true) + public void onMeleeHit(EntityDamageByEntityEvent event) { + EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getDamager()); + if (!(eliteEntity instanceof CustomBossEntity)) return; + if (((CustomBossEntity) eliteEntity).getCustomModel() == null) return; + ((CustomBossEntity) eliteEntity).getCustomModel().melee(); + } + + @EventHandler(ignoreCancelled = true) + public void onRangedShot(EntitySpawnEvent event) { + if (!(event.getEntity() instanceof Projectile)) return; + if (!(((Projectile) event.getEntity()).getShooter() instanceof LivingEntity)) return; + EliteEntity eliteEntity = EntityTracker.getEliteMobEntity((LivingEntity) ((Projectile) event.getEntity()).getShooter()); + if (!(eliteEntity instanceof CustomBossEntity)) return; + if (((CustomBossEntity) eliteEntity).getCustomModel() == null) return; + ((CustomBossEntity) eliteEntity).getCustomModel().shoot(); + } + + @EventHandler + public void onDeathEvent(EliteMobDeathEvent event) { + if (event.getEliteEntity() instanceof CustomBossEntity customBossEntity && customBossEntity.getCustomModel() != null) + customBossEntity.getCustomModel().playAnimationByName("death"); + } + } +} diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/CustomModelInterface.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/CustomModelInterface.java new file mode 100644 index 000000000..1c242e102 --- /dev/null +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/CustomModelInterface.java @@ -0,0 +1,13 @@ +package com.magmaguy.elitemobs.thirdparty.custommodels; + +import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity; + +public interface CustomModelInterface { + public void shoot(); + public void melee(); + public void playAnimationByName(String animationName); + public void setName(String nametagName, boolean visible); + public void setNameVisible(boolean visible); + public void addPassenger(CustomBossEntity passenger); + public void switchPhase(); +} diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/freeminecraftmodels/CustomModelFMM.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/freeminecraftmodels/CustomModelFMM.java new file mode 100644 index 000000000..54190049d --- /dev/null +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/freeminecraftmodels/CustomModelFMM.java @@ -0,0 +1,65 @@ +package com.magmaguy.elitemobs.thirdparty.custommodels.freeminecraftmodels; + +import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModelInterface; +import com.magmaguy.freeminecraftmodels.api.ModeledEntityManager; +import com.magmaguy.freeminecraftmodels.customentity.DynamicEntity; +import lombok.Getter; +import org.bukkit.entity.LivingEntity; + +public class CustomModelFMM implements CustomModelInterface { + @Getter + private DynamicEntity dynamicEntity; + + public CustomModelFMM(LivingEntity livingEntity, String modelName, String nametagName) { + dynamicEntity = DynamicEntity.create(modelName, livingEntity); + if (dynamicEntity == null) return; + dynamicEntity.setName(nametagName); + } + + public static void reloadModels() { + ModeledEntityManager.reload(); + } + + public static boolean modelExists(String modelName) { + return ModeledEntityManager.modelExists(modelName); + } + + @Override + public void shoot() { + if (dynamicEntity.hasAnimation("attack_ranged")) dynamicEntity.playAnimation("attack_ranged", false); + else dynamicEntity.playAnimation("attack", false); + } + + @Override + public void melee() { + if (dynamicEntity.hasAnimation("attack_melee")) dynamicEntity.playAnimation("attack_melee", false); + else dynamicEntity.playAnimation("attack", false); + } + + @Override + public void playAnimationByName(String animationName) { + dynamicEntity.playAnimation(animationName, false); + } + + @Override + public void setName(String nametagName, boolean visible) { + dynamicEntity.setName(nametagName); + dynamicEntity.setNameVisible(visible); + } + + @Override + public void setNameVisible(boolean visible) { + dynamicEntity.setNameVisible(visible); + } + + @Override + public void addPassenger(CustomBossEntity passenger) { + //currently unimplemented + } + + @Override + public void switchPhase() { + dynamicEntity.stopCurrentAnimations(); + } +} diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/modelengine/CustomModel.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/modelengine/CustomModelMEG.java similarity index 73% rename from src/main/java/com/magmaguy/elitemobs/thirdparty/modelengine/CustomModel.java rename to src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/modelengine/CustomModelMEG.java index 77be739e0..7cbc9d2ca 100644 --- a/src/main/java/com/magmaguy/elitemobs/thirdparty/modelengine/CustomModel.java +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/modelengine/CustomModelMEG.java @@ -1,9 +1,7 @@ -package com.magmaguy.elitemobs.thirdparty.modelengine; +package com.magmaguy.elitemobs.thirdparty.custommodels.modelengine; -import com.magmaguy.elitemobs.api.EliteMobDeathEvent; -import com.magmaguy.elitemobs.entitytracker.EntityTracker; -import com.magmaguy.elitemobs.mobconstructor.EliteEntity; import com.magmaguy.elitemobs.mobconstructor.custombosses.CustomBossEntity; +import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModelInterface; import com.magmaguy.elitemobs.utils.InfoMessage; import com.magmaguy.elitemobs.utils.WarningMessage; import com.ticxo.modelengine.api.ModelEngineAPI; @@ -14,13 +12,8 @@ import com.ticxo.modelengine.api.model.bone.Nameable; import lombok.Getter; import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Projectile; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntitySpawnEvent; -public class CustomModel { +public class CustomModelMEG implements CustomModelInterface { ActiveModel activeModel; ModeledEntity modeledEntity; @@ -30,7 +23,7 @@ public class CustomModel { @Getter private boolean success = false; - private CustomModel(LivingEntity livingEntity, String modelName, String nametagName) { + public CustomModelMEG(LivingEntity livingEntity, String modelName, String nametagName) { try { if (ModelEngineAPI.api.getModelRegistry().getBlueprint(modelName) == null) { new InfoMessage("Model " + modelName + " was not found! Make sure you install the model correctly if you have it. This entry will be skipped!"); @@ -71,8 +64,8 @@ private CustomModel(LivingEntity livingEntity, String modelName, String nametagN } - public static CustomModel generateCustomModel(LivingEntity livingEntity, String modelName, String nametagName) { - CustomModel customModel = new CustomModel(livingEntity, modelName, nametagName); + public static CustomModelMEG generateCustomModel(LivingEntity livingEntity, String modelName, String nametagName) { + CustomModelMEG customModel = new CustomModelMEG(livingEntity, modelName, nametagName); return customModel.isSuccess() ? customModel : null; } @@ -121,6 +114,7 @@ public void playAnimationByName(String string) { activeModel.getAnimationHandler().playAnimation(string, .1, .1, 1, true); } + @Override public void setName(String nametagName, boolean visible) { if (modeledEntity == null) return; Nameable nametag = getNameableBone(); @@ -161,30 +155,4 @@ public void switchPhase() { activeModel.getAnimationHandler().forceStopAllAnimations(); } - public static class ModelEntityEvents implements Listener { - @EventHandler(ignoreCancelled = true) - public void onMeleeHit(EntityDamageByEntityEvent event) { - EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getDamager()); - if (!(eliteEntity instanceof CustomBossEntity)) return; - if (((CustomBossEntity) eliteEntity).getCustomModel() == null) return; - ((CustomBossEntity) eliteEntity).getCustomModel().melee(); - } - - @EventHandler(ignoreCancelled = true) - public void onRangedShot(EntitySpawnEvent event) { - if (!(event.getEntity() instanceof Projectile)) return; - if (!(((Projectile) event.getEntity()).getShooter() instanceof LivingEntity)) return; - EliteEntity eliteEntity = EntityTracker.getEliteMobEntity((LivingEntity) ((Projectile) event.getEntity()).getShooter()); - if (!(eliteEntity instanceof CustomBossEntity)) return; - if (((CustomBossEntity) eliteEntity).getCustomModel() == null) return; - ((CustomBossEntity) eliteEntity).getCustomModel().shoot(); - } - - @EventHandler - public void onDeathEvent(EliteMobDeathEvent event){ - if (event.getEliteEntity() instanceof CustomBossEntity customBossEntity && - customBossEntity.getCustomModel() != null) - customBossEntity.getCustomModel().playAnimationByName("death"); - } - } } diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/modelengine/ModelEngineReservedAddresses.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/modelengine/ModelEngineReservedAddresses.java similarity index 97% rename from src/main/java/com/magmaguy/elitemobs/thirdparty/modelengine/ModelEngineReservedAddresses.java rename to src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/modelengine/ModelEngineReservedAddresses.java index eead6f1fb..556bc7a8c 100644 --- a/src/main/java/com/magmaguy/elitemobs/thirdparty/modelengine/ModelEngineReservedAddresses.java +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/custommodels/modelengine/ModelEngineReservedAddresses.java @@ -1,4 +1,4 @@ -package com.magmaguy.elitemobs.thirdparty.modelengine; +package com.magmaguy.elitemobs.thirdparty.custommodels.modelengine; import com.magmaguy.elitemobs.MetadataHandler; import org.bukkit.Bukkit; diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/mythicmobs/MythicMobs.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/mythicmobs/MythicMobs.java new file mode 100644 index 000000000..ad1656244 --- /dev/null +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/mythicmobs/MythicMobs.java @@ -0,0 +1,20 @@ +package com.magmaguy.elitemobs.thirdparty.mythicmobs; + + +import io.lumine.mythic.api.mobs.MythicMob; +import io.lumine.mythic.bukkit.BukkitAdapter; +import io.lumine.mythic.bukkit.MythicBukkit; +import io.lumine.mythic.core.mobs.ActiveMob; +import org.bukkit.Location; +import org.bukkit.entity.Entity; + +public class MythicMobs { + public static Entity spawn(Location location, String name, int level) { + MythicMob mythicMob = MythicBukkit.inst().getMobManager().getMythicMob(name).orElse(null); + if (mythicMob != null){ + ActiveMob activeMob = mythicMob.spawn(BukkitAdapter.adapt(location), level); + return activeMob.getEntity().getBukkitEntity(); + } + return null; + } +} diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/mythicmobs/MythicMobsInterface.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/mythicmobs/MythicMobsInterface.java new file mode 100644 index 000000000..528f3f775 --- /dev/null +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/mythicmobs/MythicMobsInterface.java @@ -0,0 +1,12 @@ +package com.magmaguy.elitemobs.thirdparty.mythicmobs; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Entity; + +public class MythicMobsInterface { + public static Entity spawn(Location location, String name, int level){ + if (!Bukkit.getPluginManager().isPluginEnabled("MythicMobs")) return null; + return MythicMobs.spawn(location,name,level); + } +} diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardCompatibility.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardCompatibility.java index e06816349..55f51be84 100644 --- a/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardCompatibility.java +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardCompatibility.java @@ -18,6 +18,7 @@ import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion; import com.sk89q.worldguard.protection.regions.ProtectedRegion; import com.sk89q.worldguard.protection.regions.RegionContainer; +import lombok.Getter; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.World; @@ -26,16 +27,28 @@ public class WorldGuardCompatibility { - private static final StateFlag.State allow = StateFlag.State.ALLOW; - private static final StateFlag.State deny = StateFlag.State.DENY; - private static StateFlag ELITEMOBS_SPAWN_FLAG; - private static StateFlag ELITEMOBS_ONLY_SPAWN_FLAG; - private static StateFlag ELITEMOBS_ANTIEXPLOIT; - private static StateFlag ELITEMOBS_DUNGEON; - private static StateFlag ELITEMOBS_EVENTS; - private static IntegerFlag ELITEMOBS_MINIMUM_LEVEL; - private static IntegerFlag ELITEMOBS_MAXIMUM_LEVEL; - private static StateFlag ELITEMOBS_EXPLOSION_REGEN; + @Getter + private static final StateFlag.State allow = StateFlag.State.ALLOW; + @Getter + private static final StateFlag.State deny = StateFlag.State.DENY; + @Getter + private static StateFlag ELITEMOBS_SPAWN_FLAG; + @Getter + private static StateFlag ELITEMOBS_ONLY_SPAWN_FLAG; + @Getter + private static StateFlag ELITEMOBS_ANTIEXPLOIT; + @Getter + private static StateFlag ELITEMOBS_DUNGEON; + @Getter + private static StateFlag ELITEMOBS_EVENTS; + @Getter + private static IntegerFlag ELITEMOBS_MINIMUM_LEVEL; + @Getter + private static IntegerFlag ELITEMOBS_MAXIMUM_LEVEL; + @Getter + private static StateFlag ELITEMOBS_EXPLOSION_REGEN; + @Getter + private static StateFlag ELITEMOBS_EXPLOSION_BLOCK_DAMAGE; public static boolean initialize() { @@ -121,40 +134,17 @@ public static boolean initialize() { ELITEMOBS_EXPLOSION_REGEN = (StateFlag) registry.get("elitemobs-explosion-regen"); } - return true; - - } - - public static final StateFlag getEliteMobsSpawnFlag() { - return ELITEMOBS_SPAWN_FLAG; - } - - public static final StateFlag getEliteMobsOnlySpawnFlag() { - return ELITEMOBS_ONLY_SPAWN_FLAG; - } - - public static final StateFlag getEliteMobsAntiExploitFlag() { - return ELITEMOBS_ANTIEXPLOIT; - } - - public static final StateFlag getEliteMobsDungeonFlag() { - return ELITEMOBS_DUNGEON; - } - - public static final StateFlag getEliteMobsEventsFlag() { - return ELITEMOBS_EVENTS; - } - - public static final IntegerFlag getEliteMobsMinimumLevel() { - return ELITEMOBS_MINIMUM_LEVEL; - } + try { + ELITEMOBS_EXPLOSION_BLOCK_DAMAGE = new StateFlag("elitemobs-explosion-block-damage", true); + registry.register(ELITEMOBS_EXPLOSION_BLOCK_DAMAGE); + Bukkit.getLogger().info("[EliteMobs] - elitemobs-explosion-block-damage"); + } catch (FlagConflictException | IllegalStateException e) { + Bukkit.getLogger().warning("[EliteMobs] Warning: flag elitemobs-explosion-block-damage already exists! This is normal if you've just now reloaded EliteMobs."); + ELITEMOBS_EXPLOSION_REGEN = (StateFlag) registry.get("elitemobs-explosion-block-damage"); + } - public static final IntegerFlag getEliteMobsMaximumLevel() { - return ELITEMOBS_MAXIMUM_LEVEL; - } + return true; - public static final StateFlag getEliteMobsExplosionRegen() { - return ELITEMOBS_EXPLOSION_REGEN; } public static void protectWorldMinidugeonArea(Location location, WorldDungeonPackage dungeonWorldPackage) { @@ -293,7 +283,8 @@ public static void protectMinidungeonArea(ProtectedRegion protectedRegion) { protectedRegion.setFlag(Flags.SOIL_DRY, deny); //missing coral-fade //missing ravager-grief - protectedRegion.setFlag(Flags.GHAST_FIREBALL, deny); + //protectedRegion.setFlag(Flags.GHAST_FIREBALL, deny); - this completely stops fireballs from working + protectedRegion.setFlag(ELITEMOBS_EXPLOSION_BLOCK_DAMAGE, deny); protectedRegion.setFlag(Flags.WITHER_DAMAGE, deny); protectedRegion.setFlag(Flags.ENDER_BUILD, deny); protectedRegion.setFlag(Flags.ITEM_FRAME_ROTATE, deny); diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardDungeonFlag.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardDungeonFlag.java index ddda7eb47..174125359 100644 --- a/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardDungeonFlag.java +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardDungeonFlag.java @@ -17,7 +17,7 @@ public void onSpawn(CreatureSpawnEvent event) { if (event.getEntity().getType().equals(EntityType.ARMOR_STAND) || event.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.CUSTOM)) return; - if (WorldGuardFlagChecker.checkFlag(event.getLocation(), WorldGuardCompatibility.getEliteMobsDungeonFlag())) { + if (WorldGuardFlagChecker.checkFlag(event.getLocation(), WorldGuardCompatibility.getELITEMOBS_DUNGEON())) { EliteEntity eliteEntity = EntityTracker.getEliteMobEntity(event.getEntity()); if (eliteEntity instanceof CustomBossEntity) return; diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardEliteMobOnlySpawnFlag.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardEliteMobOnlySpawnFlag.java index eed8485ca..f75d95850 100644 --- a/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardEliteMobOnlySpawnFlag.java +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardEliteMobOnlySpawnFlag.java @@ -16,7 +16,7 @@ public void onSpawn(CreatureSpawnEvent event) { if (event.getEntity().getType().equals(EntityType.ARMOR_STAND) || event.getEntity().getType().equals(EntityType.VILLAGER) && event.getSpawnReason().equals(CreatureSpawnEvent.SpawnReason.CUSTOM)) return; - if (WorldGuardFlagChecker.checkFlag(event.getLocation(), WorldGuardCompatibility.getEliteMobsOnlySpawnFlag())) { + if (WorldGuardFlagChecker.checkFlag(event.getLocation(), WorldGuardCompatibility.getELITEMOBS_ONLY_SPAWN_FLAG())) { if (EntityTracker.isEliteMob(event.getEntity())) return; event.setCancelled(true); event.getEntity().remove(); diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardExplosionBlockDamageFlag.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardExplosionBlockDamageFlag.java new file mode 100644 index 000000000..089a6b703 --- /dev/null +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardExplosionBlockDamageFlag.java @@ -0,0 +1,16 @@ +package com.magmaguy.elitemobs.thirdparty.worldguard; + +import com.magmaguy.elitemobs.entitytracker.EntityTracker; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; + +public class WorldGuardExplosionBlockDamageFlag implements Listener { + @EventHandler(priority = EventPriority.LOWEST) + public void WorldGuardExplosionBlockDamageFlag(EntityExplodeEvent event){ + if (WorldGuardFlagChecker.checkFlag(event.getLocation(), WorldGuardCompatibility.getELITEMOBS_EXPLOSION_BLOCK_DAMAGE())) return; + if (!EntityTracker.isProjectileEntity(event.getEntity()) && !EntityTracker.isEliteMob(event.getEntity())) return; + event.blockList().clear(); + } +} diff --git a/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardFlagChecker.java b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardFlagChecker.java index 7127c7df9..d6fca9314 100644 --- a/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardFlagChecker.java +++ b/src/main/java/com/magmaguy/elitemobs/thirdparty/worldguard/WorldGuardFlagChecker.java @@ -37,12 +37,12 @@ public static Integer getIntegerFlagValue(Location location, Flag flag) { @Nullable public static Integer getRegionMinimumLevel(Location location) { - return WorldGuardFlagChecker.getIntegerFlagValue(location, WorldGuardCompatibility.getEliteMobsMinimumLevel()); + return WorldGuardFlagChecker.getIntegerFlagValue(location, WorldGuardCompatibility.getELITEMOBS_MINIMUM_LEVEL()); } @Nullable public static Integer getRegionMaximumLevel(Location location) { - return WorldGuardFlagChecker.getIntegerFlagValue(location, WorldGuardCompatibility.getEliteMobsMaximumLevel()); + return WorldGuardFlagChecker.getIntegerFlagValue(location, WorldGuardCompatibility.getELITEMOBS_MAXIMUM_LEVEL()); } public static boolean doExplosionRegenFlag(Location location) { @@ -50,7 +50,7 @@ public static boolean doExplosionRegenFlag(Location location) { RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); RegionQuery query = container.createQuery(); ApplicableRegionSet set = query.getApplicableRegions(wgLocation); - return set.testState(null, WorldGuardCompatibility.getEliteMobsExplosionRegen()); + return set.testState(null, WorldGuardCompatibility.getELITEMOBS_EXPLOSION_REGEN()); } public static boolean doEventFlag(Location location) { @@ -58,7 +58,7 @@ public static boolean doEventFlag(Location location) { RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); RegionQuery query = container.createQuery(); ApplicableRegionSet set = query.getApplicableRegions(wgLocation); - return set.testState(null, WorldGuardCompatibility.getEliteMobsEventsFlag()); + return set.testState(null, WorldGuardCompatibility.getELITEMOBS_EVENTS()); } public static boolean doEliteMobsSpawnFlag(Location location) { @@ -66,7 +66,7 @@ public static boolean doEliteMobsSpawnFlag(Location location) { RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); RegionQuery query = container.createQuery(); ApplicableRegionSet set = query.getApplicableRegions(wgLocation); - return set.testState(null, WorldGuardCompatibility.getEliteMobsSpawnFlag()); + return set.testState(null, WorldGuardCompatibility.getELITEMOBS_SPAWN_FLAG()); } public static boolean doMobSpawnFlag(Location location) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 4788dc6c5..9e36a2e4d 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: EliteMobs -version: 8.6.2 +version: 8.7.0 author: MagmaGuy main: com.magmaguy.elitemobs.EliteMobs api-version: 1.14 @@ -17,6 +17,7 @@ softdepend: - MythicMobs - LevelledMobs - InfernalMobs +- FreeMinecraftModels permissions: elitemobs.*: