diff --git a/src/main/java/me/gallowsdove/foxymachines/FoxyMachines.java b/src/main/java/me/gallowsdove/foxymachines/FoxyMachines.java index 51d1a98..296cdcf 100644 --- a/src/main/java/me/gallowsdove/foxymachines/FoxyMachines.java +++ b/src/main/java/me/gallowsdove/foxymachines/FoxyMachines.java @@ -8,6 +8,7 @@ import me.gallowsdove.foxymachines.abstracts.AbstractWand; import me.gallowsdove.foxymachines.abstracts.CustomBoss; import me.gallowsdove.foxymachines.commands.KillallCommand; +import me.gallowsdove.foxymachines.commands.ListallCommand; import me.gallowsdove.foxymachines.commands.QuestCommand; import me.gallowsdove.foxymachines.commands.SacrificialAltarCommand; import me.gallowsdove.foxymachines.commands.SummonCommand; @@ -37,6 +38,7 @@ public FoxyMachines() { public void enable() { instance = this; + Events.registerListener(new ChunkLoadListener()); Events.registerListener(new ChunkLoaderListener()); Events.registerListener(new BoostedRailListener()); Events.registerListener(new BerryBushListener()); @@ -69,7 +71,7 @@ public void enable() { new Metrics(this, 10568); getAddonCommand().addSub(new KillallCommand()).addSub((new QuestCommand())). - addSub(new SacrificialAltarCommand()).addSub(new SummonCommand()); + addSub(new SacrificialAltarCommand()).addSub(new SummonCommand()).addSub(new ListallCommand()); } @SneakyThrows diff --git a/src/main/java/me/gallowsdove/foxymachines/abstracts/CustomBoss.java b/src/main/java/me/gallowsdove/foxymachines/abstracts/CustomBoss.java index c553468..c2c33a2 100644 --- a/src/main/java/me/gallowsdove/foxymachines/abstracts/CustomBoss.java +++ b/src/main/java/me/gallowsdove/foxymachines/abstracts/CustomBoss.java @@ -31,7 +31,7 @@ public abstract class CustomBoss extends CustomMob { private final Set resistances; - public CustomBoss(@Nonnull String id, @Nonnull String name, @Nonnull EntityType type, int health, @Nonnull DamageCause... resistances) { + protected CustomBoss(@Nonnull String id, @Nonnull String name, @Nonnull EntityType type, int health, @Nonnull DamageCause... resistances) { super(id, name, type, health); this.resistances = Set.of(resistances); } @@ -60,20 +60,28 @@ public void onSpawn(@Nonnull LivingEntity spawned) { @Override @OverridingMethodsMustInvokeSuper - public final void onHit(@Nonnull EntityDamageEvent e) { - this.onBossDamaged(e); + public void onMobTick(@Nonnull LivingEntity mob, int tick) { + if (tick == 100) { + onBossPattern(mob); + } + } + + @Override + @OverridingMethodsMustInvokeSuper + public final void onHit(@Nonnull EntityDamageEvent event) { + this.onBossDamaged(event); - if (!e.isCancelled() && e.getEntity() instanceof LivingEntity entity) { + if (!event.isCancelled() && event.getEntity() instanceof LivingEntity entity) { BossBar bossbar = getBossBarForEntity(entity); if (entity.isInsideVehicle() && entity.getVehicle() instanceof LivingEntity vehicle) { - double finalHealth = entity.getHealth() + vehicle.getHealth() - e.getFinalDamage(); + double finalHealth = entity.getHealth() + vehicle.getHealth() - event.getFinalDamage(); if (finalHealth > 0) { bossbar.setProgress(Math.min(finalHealth / (entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue() + vehicle.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue()), 1)); } } else { - double finalHealth = entity.getHealth() - e.getFinalDamage(); + double finalHealth = entity.getHealth() - event.getFinalDamage(); if (finalHealth > 0) { bossbar.setProgress(Math.min(finalHealth / entity.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue(), 1)); } @@ -90,8 +98,10 @@ protected void onBossDamaged(@Nonnull EntityDamageEvent e) { @Override @OverridingMethodsMustInvokeSuper - public void onDeath(@Nonnull EntityDeathEvent e) { - BossBar bossbar = getBossBarForEntity(e.getEntity()); + public void onDeath(@Nonnull EntityDeathEvent event) { + super.onDeath(event); + + BossBar bossbar = getBossBarForEntity(event.getEntity()); bossbar.setVisible(false); bossbar.removeAll(); } diff --git a/src/main/java/me/gallowsdove/foxymachines/abstracts/CustomMob.java b/src/main/java/me/gallowsdove/foxymachines/abstracts/CustomMob.java index 2e97a84..c933dfe 100644 --- a/src/main/java/me/gallowsdove/foxymachines/abstracts/CustomMob.java +++ b/src/main/java/me/gallowsdove/foxymachines/abstracts/CustomMob.java @@ -8,6 +8,7 @@ import io.github.thebusybiscuit.slimefun4.libraries.dough.common.ChatColors; import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.NamespacedKey; @@ -24,27 +25,35 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import javax.annotation.OverridingMethodsMustInvokeSuper; +import javax.annotation.ParametersAreNonnullByDefault; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; public abstract class CustomMob { public static final Map MOBS = new HashMap<>(); + public static final Map> MOB_CACHE = new HashMap<>(); @Nullable - public static CustomMob getByID(@Nonnull String id) { + public static CustomMob getById(@Nonnull String id) { return MOBS.get(id); } @Nullable public static CustomMob getByEntity(@Nonnull Entity entity) { String id = PersistentDataAPI.getString(entity, CustomMob.KEY); - return id == null ? null : getByID(id); + return id == null ? null : getById(id); } private static final NamespacedKey KEY = new NamespacedKey(FoxyMachines.getInstance(), "mob"); + @Getter @Nonnull private final String id; @Nonnull @@ -54,7 +63,8 @@ public static CustomMob getByEntity(@Nonnull Entity entity) { private final EntityType type; private final int health; - public CustomMob(@Nonnull String id, @Nonnull String name, @Nonnull EntityType type, int health) { + @ParametersAreNonnullByDefault + protected CustomMob(String id, String name, EntityType type, int health) { Validate.notNull(this.id = id); Validate.notNull(this.name = ChatColors.color(name)); Validate.notNull(this.type = type); @@ -78,6 +88,7 @@ public final LivingEntity spawn(@Nonnull Location loc) { entity.setRemoveWhenFarAway(true); onSpawn(entity); + cacheEntity(entity); return entity; } @@ -88,98 +99,126 @@ protected void onSpawn(@Nonnull LivingEntity spawned) { } public void onMobTick(@Nonnull LivingEntity mob, int tick) { } - protected void onHit(@Nonnull EntityDamageEvent e) { } + protected void onHit(@Nonnull EntityDamageEvent event) { } - protected void onAttack(@Nonnull EntityDamageByEntityEvent e) { } + protected void onAttack(@Nonnull EntityDamageByEntityEvent event) { } - protected void onInteract(@Nonnull PlayerInteractEntityEvent e) { } + protected void onInteract(@Nonnull PlayerInteractEntityEvent event) { } - protected void onTarget(@Nonnull EntityTargetEvent e) { } + protected void onTarget(@Nonnull EntityTargetEvent event) { } - protected void onDeath(@Nonnull EntityDeathEvent e) { } + @OverridingMethodsMustInvokeSuper + protected void onDeath(@Nonnull EntityDeathEvent event) { + uncacheEntity(event.getEntity()); + } - protected void onCastSpell(EntitySpellCastEvent e) { } + protected void onCastSpell(@Nonnull EntitySpellCastEvent event) { } - protected void onDamage(EntityDamageEvent e) { } + protected void onDamage(@Nonnull EntityDamageEvent event) { } protected Vector getSpawnOffset() { return new Vector(); } + public void cacheEntity(@Nonnull Entity entity) { + cacheEntity(entity.getUniqueId()); + } + + public void cacheEntity(@Nonnull UUID uuid) { + Set entities = MOB_CACHE.getOrDefault(this, new HashSet<>()); + entities.add(uuid); + MOB_CACHE.put(this, entities); + } + + public void uncacheEntity(@Nonnull Entity entity) { + uncacheEntity(entity.getUniqueId()); + } + + public void uncacheEntity(@Nonnull UUID uuid) { + Set entities = MOB_CACHE.getOrDefault(this, new HashSet<>()); + entities.remove(uuid); + MOB_CACHE.put(this, entities); + } + + public static void debug() { + Bukkit.broadcastMessage("CACHE:"); + for (Map.Entry> entry : CustomMob.MOB_CACHE.entrySet()) { + Bukkit.broadcastMessage(entry.getKey().getId() + " (" + entry.getValue().size() + ")\n" + entry.getValue().stream().map(UUID::toString).collect(Collectors.joining("\n"))); + } + } + static { Events.registerListener(new Listener() { @EventHandler - public void onTarget(@Nonnull EntityTargetEvent e) { - CustomMob customMob = CustomMob.getByEntity(e.getEntity()); + public void onTarget(@Nonnull EntityTargetEvent event) { + CustomMob customMob = CustomMob.getByEntity(event.getEntity()); if (customMob != null) { - customMob.onTarget(e); + customMob.onTarget(event); } } @EventHandler - public void onInteract(@Nonnull PlayerInteractEntityEvent e) { - CustomMob customMob = CustomMob.getByEntity(e.getRightClicked()); + public void onInteract(@Nonnull PlayerInteractEntityEvent event) { + CustomMob customMob = CustomMob.getByEntity(event.getRightClicked()); if (customMob != null) { - customMob.onInteract(e); + customMob.onInteract(event); } } @EventHandler - public void onHit(@Nonnull EntityDamageByEntityEvent e) { - CustomMob customMob = CustomMob.getByEntity(e.getDamager()); + public void onHit(@Nonnull EntityDamageByEntityEvent event) { + CustomMob customMob = CustomMob.getByEntity(event.getDamager()); if (customMob != null) { - customMob.onAttack(e); + customMob.onAttack(event); } } @EventHandler - public void onDamaged(@Nonnull EntityDamageEvent e) { - CustomMob customMob = CustomMob.getByEntity(e.getEntity()); + public void onDamaged(@Nonnull EntityDamageEvent event) { + CustomMob customMob = CustomMob.getByEntity(event.getEntity()); if (customMob != null) { - customMob.onHit(e); + customMob.onHit(event); } } @EventHandler - public void onDeath(@Nonnull EntityDeathEvent e) { - CustomMob customMob = CustomMob.getByEntity(e.getEntity()); + public void onDeath(@Nonnull EntityDeathEvent event) { + CustomMob customMob = CustomMob.getByEntity(event.getEntity()); if (customMob != null) { - customMob.onDeath(e); + customMob.onDeath(event); } } @EventHandler - public void onSpellCast(@Nonnull EntitySpellCastEvent e) { - CustomMob customMob = CustomMob.getByEntity(e.getEntity()); + public void onSpellCast(@Nonnull EntitySpellCastEvent event) { + CustomMob customMob = CustomMob.getByEntity(event.getEntity()); if (customMob != null) { - customMob.onCastSpell(e); + customMob.onCastSpell(event); } } @EventHandler - public void onDamage(@Nonnull EntityDamageEvent e) { - CustomMob customMob = CustomMob.getByEntity(e.getEntity()); + public void onDamage(@Nonnull EntityDamageEvent event) { + CustomMob customMob = CustomMob.getByEntity(event.getEntity()); if (customMob != null) { - customMob.onDamage(e); + customMob.onDamage(event); } } @EventHandler(ignoreCancelled = true) - private void onNametagEvent(PlayerInteractEntityEvent e) { - ItemStack item = e.getPlayer().getInventory().getItemInMainHand(); + private void onNametagEvent(PlayerInteractEntityEvent event) { + ItemStack item = event.getPlayer().getInventory().getItemInMainHand(); - if (item.getType() == Material.NAME_TAG) { - if (CustomMob.getByEntity(e.getRightClicked()) != null) { - e.setCancelled(true); - } + if (item.getType() == Material.NAME_TAG && CustomMob.getByEntity(event.getRightClicked()) != null) { + event.setCancelled(true); } } @EventHandler(ignoreCancelled = true) - private void onCombust(EntityCombustEvent e) { - if (CustomMob.getByEntity(e.getEntity()) != null) { - e.setCancelled(true); + private void onCombust(EntityCombustEvent event) { + if (CustomMob.getByEntity(event.getEntity()) != null) { + event.setCancelled(true); } } }); diff --git a/src/main/java/me/gallowsdove/foxymachines/commands/KillallCommand.java b/src/main/java/me/gallowsdove/foxymachines/commands/KillallCommand.java index f8c6de5..3495e44 100644 --- a/src/main/java/me/gallowsdove/foxymachines/commands/KillallCommand.java +++ b/src/main/java/me/gallowsdove/foxymachines/commands/KillallCommand.java @@ -3,38 +3,48 @@ import io.github.mooy1.infinitylib.commands.SubCommand; import me.gallowsdove.foxymachines.abstracts.CustomBoss; import me.gallowsdove.foxymachines.abstracts.CustomMob; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import javax.annotation.Nonnull; import java.util.List; +import java.util.Set; +import java.util.UUID; public class KillallCommand extends SubCommand { public KillallCommand() { - super("killall", "Kills all Custom Mobs from FoxyMachines.", "foxymachines.admin"); + super("killall", "Kills all Custom Mobs from FoxyMachines in your current World.", "foxymachines.admin"); } @Override - protected void execute(@Nonnull CommandSender commandSender, @Nonnull String[] args) { - if (!(commandSender instanceof Player p)) { + protected void execute(@Nonnull CommandSender sender, @Nonnull String[] args) { + if (!(sender instanceof Player player)) { return; } if (args.length != 0) { - commandSender.sendMessage(ChatColor.LIGHT_PURPLE + "Usage: /foxy killall"); + sender.sendMessage(ChatColor.LIGHT_PURPLE + "Usage: /foxy killall"); return; } - for (LivingEntity entity : p.getWorld().getLivingEntities()) { - CustomMob mob = CustomMob.getByEntity(entity); - if (mob != null) { - entity.remove(); + int count = 0; + for (Set uuids : CustomMob.MOB_CACHE.values()) { + for (UUID uuid : uuids) { + Entity entity = Bukkit.getEntity(uuid); + if (entity instanceof LivingEntity && entity.getWorld().equals(player.getWorld())) { + entity.remove(); + count++; + } } } CustomBoss.removeBossBars(); + + player.sendMessage("Killed %s Entities".formatted(count)); } @Override diff --git a/src/main/java/me/gallowsdove/foxymachines/commands/ListallCommand.java b/src/main/java/me/gallowsdove/foxymachines/commands/ListallCommand.java new file mode 100644 index 0000000..e945b20 --- /dev/null +++ b/src/main/java/me/gallowsdove/foxymachines/commands/ListallCommand.java @@ -0,0 +1,28 @@ +package me.gallowsdove.foxymachines.commands; + +import io.github.mooy1.infinitylib.commands.SubCommand; +import me.gallowsdove.foxymachines.abstracts.CustomMob; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +import javax.annotation.Nonnull; +import java.util.List; + +public class ListallCommand extends SubCommand { + public ListallCommand() { + super("listall", "Lists all Custom Mobs from FoxyMachines", "foxymachines.admin"); + } + + @Override + protected void execute(@Nonnull CommandSender sender, @Nonnull String[] args) { + if (args.length != 0) { + sender.sendMessage(ChatColor.LIGHT_PURPLE + "Usage: /foxy listall"); + return; + } + + CustomMob.debug(); + } + + @Override + protected void complete(@Nonnull CommandSender commandSender, @Nonnull String[] strings, @Nonnull List list) { } +} \ No newline at end of file diff --git a/src/main/java/me/gallowsdove/foxymachines/commands/SummonCommand.java b/src/main/java/me/gallowsdove/foxymachines/commands/SummonCommand.java index eb523ec..1ffd150 100644 --- a/src/main/java/me/gallowsdove/foxymachines/commands/SummonCommand.java +++ b/src/main/java/me/gallowsdove/foxymachines/commands/SummonCommand.java @@ -16,26 +16,26 @@ public SummonCommand() { } @Override - protected void execute(@Nonnull CommandSender commandSender, @Nonnull String[] args) { - if (!(commandSender instanceof Player p)) { + protected void execute(@Nonnull CommandSender sender, @Nonnull String[] args) { + if (!(sender instanceof Player player)) { return; } if (args.length != 1) { - commandSender.sendMessage(ChatColor.LIGHT_PURPLE + "Usage: /foxy summon "); + sender.sendMessage(ChatColor.LIGHT_PURPLE + "Usage: /foxy summon "); return; } - CustomMob mob = CustomMob.getByID(args[0]); + CustomMob mob = CustomMob.getById(args[0]); if (mob != null) { - mob.spawn(p.getLocation()); + mob.spawn(player.getLocation()); } } @Override - protected void complete(@Nonnull CommandSender commandSender, @Nonnull String[] args, @Nonnull List tabs) { + protected void complete(@Nonnull CommandSender sender, @Nonnull String[] args, @Nonnull List tabs) { tabs.addAll(CustomMob.MOBS.keySet()); } } \ No newline at end of file diff --git a/src/main/java/me/gallowsdove/foxymachines/implementation/consumables/CustomMobSpawnEgg.java b/src/main/java/me/gallowsdove/foxymachines/implementation/consumables/CustomMobSpawnEgg.java index cf924b3..01968fe 100644 --- a/src/main/java/me/gallowsdove/foxymachines/implementation/consumables/CustomMobSpawnEgg.java +++ b/src/main/java/me/gallowsdove/foxymachines/implementation/consumables/CustomMobSpawnEgg.java @@ -7,8 +7,9 @@ import io.github.thebusybiscuit.slimefun4.implementation.Slimefun; import io.github.thebusybiscuit.slimefun4.implementation.items.SimpleSlimefunItem; import io.github.thebusybiscuit.slimefun4.libraries.dough.protection.Interaction; -import io.github.thebusybiscuit.slimefun4.utils.SlimefunUtils; import me.gallowsdove.foxymachines.abstracts.CustomMob; +import org.bukkit.GameMode; +import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -17,26 +18,34 @@ public class CustomMobSpawnEgg extends SimpleSlimefunItem { - String id; - SlimefunItemStack slimefunItem; + private final String id; @ParametersAreNonnullByDefault public CustomMobSpawnEgg(SubItemGroup itemGroup, String id, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { super(itemGroup, item, recipeType, recipe); + this.id = id; - this.slimefunItem = item; } @Nonnull @Override public ItemUseHandler getItemHandler() { - return e -> { - e.cancel(); - Player p = e.getPlayer(); - if (Slimefun.getProtectionManager().hasPermission(e.getPlayer(), p.getLocation(), Interaction.ATTACK_PLAYER)) { - ItemStack item = SlimefunUtils.isItemSimilar(p.getInventory().getItemInMainHand(), slimefunItem, false, false) ? p.getInventory().getItemInMainHand() : p.getInventory().getItemInOffHand(); + return event -> { + event.cancel(); + Player player = event.getPlayer(); + Location location = player.getLocation(); + if (!Slimefun.getProtectionManager().hasPermission(player, location, Interaction.ATTACK_PLAYER)) { + return; + } + + ItemStack item = event.getItem(); + if (player.getGameMode() != GameMode.CREATIVE) { item.setAmount(item.getAmount() - 1); - CustomMob.getByID(id).spawn(e.getPlayer().getLocation()); + } + + CustomMob mob = CustomMob.getById(this.id); + if (mob != null) { + mob.spawn(event.getPlayer().getLocation()); } }; } diff --git a/src/main/java/me/gallowsdove/foxymachines/implementation/materials/GhostBlock.java b/src/main/java/me/gallowsdove/foxymachines/implementation/materials/GhostBlock.java index c23b65f..f78becd 100644 --- a/src/main/java/me/gallowsdove/foxymachines/implementation/materials/GhostBlock.java +++ b/src/main/java/me/gallowsdove/foxymachines/implementation/materials/GhostBlock.java @@ -13,6 +13,7 @@ import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.block.Block; +import org.bukkit.entity.Entity; import org.bukkit.entity.FallingBlock; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -20,7 +21,9 @@ import org.bukkit.util.Vector; import javax.annotation.Nonnull; +import java.util.HashSet; import java.util.Set; +import java.util.UUID; public class GhostBlock extends SlimefunItem { @@ -29,6 +32,8 @@ public class GhostBlock extends SlimefunItem { public static final Set EXCLUDED = Set.of(Material.BARRIER, Material.SPAWNER, Material.COMMAND_BLOCK, Material.STRUCTURE_BLOCK, Material.REPEATING_COMMAND_BLOCK, Material.CHAIN_COMMAND_BLOCK, Material.JIGSAW); + public static final Set BLOCK_CACHE = new HashSet<>(); + @Nonnull private final Material material; @@ -51,30 +56,38 @@ public void preRegister() { private ItemUseHandler onUse() { return e -> { e.cancel(); - if (e.getClickedBlock().isPresent()) { + if (e.getClickedBlock().isEmpty()) { + return; + } - Player p = e.getPlayer(); - Block b = e.getClickedBlock().get().getRelative(e.getClickedFace()); + Player p = e.getPlayer(); + Block b = e.getClickedBlock().get().getRelative(e.getClickedFace()); + + if (!Slimefun.getProtectionManager().hasPermission(p, b, Interaction.PLACE_BLOCK)) { + p.sendMessage(ChatColor.LIGHT_PURPLE + "You don't have permission to place this here!"); + return; + } - if (b.getWorld().getNearbyEntities(b.getLocation().add(0.5, 0, 0.5), 0.01, 0.01, 0.01).isEmpty()) { - if (Slimefun.getProtectionManager().hasPermission(p, b, Interaction.PLACE_BLOCK)) { - FallingBlock block = b.getWorld().spawnFallingBlock(b.getLocation().add(0.5, 0, 0.5), material.createBlockData()); - block.setVelocity(new Vector(0, 0, 0)); - block.setGravity(false); - block.setDropItem(false); - block.setPersistent(true); - block.setInvulnerable(true); - block.getPersistentDataContainer().set(KEY, PersistentDataType.STRING, "true"); + if (!b.getWorld().getNearbyEntities(b.getLocation().add(0.5, 0, 0.5), 0.01, 0.01, 0.01).isEmpty()) { + return; + } + FallingBlock block = b.getWorld().spawnFallingBlock(b.getLocation().add(0.5, 0, 0.5), material.createBlockData()); + block.setVelocity(new Vector(0, 0, 0)); + block.setGravity(false); + block.setDropItem(false); + block.setPersistent(true); + block.setInvulnerable(true); + block.getPersistentDataContainer().set(KEY, PersistentDataType.STRING, "true"); - ItemStack item = e.getInteractEvent().getItem(); + ItemStack item = e.getInteractEvent().getItem(); + item.setAmount(item.getAmount() - 1); - item.setAmount(item.getAmount() - 1); - } else { - p.sendMessage(ChatColor.LIGHT_PURPLE + "You don't have permission to place this here!"); - } - } - } + BLOCK_CACHE.add(block.getUniqueId()); }; } + + public static boolean isGhostBlock(Entity entity) { + return entity.getPersistentDataContainer().has(KEY, PersistentDataType.STRING); + } } diff --git a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/HeadlessHorseman.java b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/HeadlessHorseman.java index c2b584d..6bbcac1 100644 --- a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/HeadlessHorseman.java +++ b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/HeadlessHorseman.java @@ -2,6 +2,7 @@ import io.github.mooy1.infinitylib.common.Scheduler; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; +import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI; import me.gallowsdove.foxymachines.FoxyMachines; import me.gallowsdove.foxymachines.Items; import me.gallowsdove.foxymachines.abstracts.CustomBoss; @@ -25,15 +26,14 @@ import org.bukkit.potion.PotionEffectType; import javax.annotation.Nonnull; -import java.util.Collection; import java.util.concurrent.ThreadLocalRandom; public class HeadlessHorseman extends CustomBoss { public static class AttackPattern { - public static short LIGHTNING = 0; - public static short SHOOT = 1; - public static short SUMMON = 2; + public static final short LIGHTNING = 0; + public static final short SHOOT = 1; + public static final short SUMMON = 2; } private static final NamespacedKey PATTERN_KEY = new NamespacedKey(FoxyMachines.getInstance(), "pattern"); @@ -49,7 +49,7 @@ public void onSpawn(@Nonnull LivingEntity spawned) { spawned.setInvisible(true); - CustomMob mob = CustomMob.getByID("SKELETON_HORSE"); + CustomMob mob = CustomMob.getById("SKELETON_HORSE"); SkeletonHorse horse = (SkeletonHorse) mob.spawn(spawned.getLocation()); horse.addPassenger(spawned); @@ -68,16 +68,16 @@ protected BossBarStyle getBossBarStyle() { } @Override - protected void onTarget(@Nonnull EntityTargetEvent e) { - if (!(e.getTarget() instanceof Player)) { - e.setCancelled(true); + protected void onTarget(@Nonnull EntityTargetEvent event) { + if (!(event.getTarget() instanceof Player)) { + event.setCancelled(true); } } @Override - protected void onAttack(@Nonnull EntityDamageByEntityEvent e) { - if (!e.isCancelled()) { - Utils.dealDamageBypassingArmor((LivingEntity) e.getEntity(), (e.getDamage() - e.getFinalDamage()) * 0.12); + protected void onAttack(@Nonnull EntityDamageByEntityEvent event) { + if (!event.isCancelled()) { + Utils.dealDamageBypassingArmor((LivingEntity) event.getEntity(), (event.getDamage() - event.getFinalDamage()) * 0.12); } } @@ -90,117 +90,119 @@ public void onBossPattern(@Nonnull LivingEntity mob) { pattern = AttackPattern.LIGHTNING; } else if (pattern < 5) { pattern = AttackPattern.SHOOT; - if (mob.isInsideVehicle() && mob.getVehicle() instanceof LivingEntity) { - ((LivingEntity) mob.getVehicle()).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 100, 100)); + if (mob.getVehicle() instanceof LivingEntity vehicle) { + vehicle.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 100, 100)); } } else { pattern = AttackPattern.SUMMON; } - mob.getPersistentDataContainer().set(PATTERN_KEY, PersistentDataType.SHORT, pattern); + PersistentDataAPI.setShort(mob, PATTERN_KEY, pattern); } @Override - public void onBossDamaged(@Nonnull EntityDamageEvent e) { - super.onBossDamaged(e); + public void onBossDamaged(@Nonnull EntityDamageEvent event) { + super.onBossDamaged(event); - Skeleton headlessHorseman = (Skeleton) e.getEntity(); + Skeleton headlessHorseman = (Skeleton) event.getEntity(); if (headlessHorseman.isInsideVehicle()) { - e.setCancelled(true); + event.setCancelled(true); } } @Override public void onMobTick(@Nonnull LivingEntity entity, int tick) { - Skeleton headlessHorseman = (Skeleton) entity; + super.onMobTick(entity, tick); - short pattern = entity.getPersistentDataContainer().get(PATTERN_KEY, PersistentDataType.SHORT); + Skeleton headlessHorseman = (Skeleton) entity; + short pattern = PersistentDataAPI.getShort(entity, PATTERN_KEY); if ((tick + 4) % 5 == 0) { - Collection entities = headlessHorseman.getWorld().getNearbyEntities(headlessHorseman.getLocation(), 30, 20, 30); + headlessHorseman.setTarget(Utils.getNearbyPlayerInSurvival(headlessHorseman.getLocation(), 30, 20, 30)); + } - for (Entity player : entities) { - if (player instanceof Player && ((Player) player).getGameMode() == GameMode.SURVIVAL) { - headlessHorseman.setTarget((LivingEntity) player); - } + if (pattern == AttackPattern.SUMMON && tick == 25) { + spawnHelldogs(headlessHorseman.getLocation()); + return; + } + + Entity target = headlessHorseman.getTarget(); + if (!(target instanceof Player player)) { + return; + } + + if (tick % 5 == 0 && pattern == AttackPattern.SHOOT) { + Arrow arrow = entity.launchProjectile(Arrow.class); + arrow.setDamage(22); + arrow.setColor(Color.RED); + arrow.setGlowing(true); + arrow.setSilent(true); + arrow.setGravity(false); + arrow.setPersistent(false); + try { + // TODO: Find out why this sometimes throws an error + arrow.setVelocity(target.getLocation().toVector().subtract(headlessHorseman.getLocation().toVector()).normalize().multiply(1.64)); + } catch (IllegalArgumentException ignored) { + arrow.remove(); } + return; } - if (pattern == AttackPattern.SHOOT) { - if (headlessHorseman.getTarget() != null) { - Player target = (Player) headlessHorseman.getTarget(); - if (tick % 5 == 0) { - Arrow arrow = entity.launchProjectile(Arrow.class); - arrow.setDamage(22); - arrow.setColor(Color.RED); - arrow.setGlowing(true); - arrow.setSilent(true); - arrow.setGravity(false); - try { - arrow.setVelocity(target.getLocation().toVector().subtract(headlessHorseman.getLocation().toVector()).normalize().multiply(1.64)); - } catch (IllegalArgumentException e) { } - } + if (tick % 8 == 0 && pattern == AttackPattern.LIGHTNING) { + Location playerLocation = player.getLocation().clone(); + Location horsemanLocation = headlessHorseman.getLocation(); + + if (playerLocation.distanceSquared(horsemanLocation) >= Math.pow(26, 2)) { + return; } - } else if (pattern == AttackPattern.LIGHTNING) { - if (headlessHorseman.getTarget() != null) { - if (tick % 8 == 0) { - Player player = (Player) headlessHorseman.getTarget(); - Location loc = player.getLocation().clone(); - Location l = headlessHorseman.getLocation(); - - if (Math.sqrt((loc.getX() - l.getX()) * (loc.getX() - l.getX()) + - (loc.getY() - l.getY()) * (loc.getY() - l.getY()) + - (loc.getZ() - l.getZ()) * (loc.getZ() - l.getZ())) < 26) { - - Scheduler.run(4, () -> { - loc.getWorld().strikeLightningEffect(loc); - if (player.isValid()) { - Location playerLoc = player.getLocation(); - if (Math.sqrt((loc.getX() - playerLoc.getX()) * (loc.getX() - playerLoc.getX()) + - (loc.getY() - playerLoc.getY()) * (loc.getY() - playerLoc.getY())) < 0.72) { - EntityDamageEvent e = new EntityDamageEvent(player, DamageCause.CUSTOM, 12); - Bukkit.getServer().getPluginManager().callEvent(e); - if (!e.isCancelled()) { - player.damage(12.4); - Utils.dealDamageBypassingArmor(player, 1.72); - } - } - } - }); - } + + Scheduler.run(4, () -> { + playerLocation.getWorld().strikeLightningEffect(playerLocation); + if (!player.isValid()) { + return; } - } - } else if (pattern == AttackPattern.SUMMON) { - if (tick == 25) { - spawnHelldogs(headlessHorseman.getLocation()); - } + + Location newLocation = player.getLocation(); + if (Math.pow(playerLocation.getX() - newLocation.getX(), 2) + + Math.pow(playerLocation.getY() - newLocation.getY(), 2) >= Math.pow(0.72, 2)) { + return; + } + + EntityDamageEvent event = new EntityDamageEvent(player, DamageCause.CUSTOM, 12); + Bukkit.getServer().getPluginManager().callEvent(event); + if (!event.isCancelled()) { + player.damage(12.4); + Utils.dealDamageBypassingArmor(player, 1.72); + } + }); } } @Override - public void onDeath(@Nonnull EntityDeathEvent e) { - super.onDeath(e); + public void onDeath(@Nonnull EntityDeathEvent event) { + super.onDeath(event); - e.getDrops().clear(); - Location loc = e.getEntity().getLocation(); - loc.getWorld().dropItemNaturally(loc, new SlimefunItemStack(Items.VILE_PUMPKIN, 1)); - loc.getWorld().spawn(loc, ExperienceOrb.class).setExperience(2000 + ThreadLocalRandom.current().nextInt(800)); + event.getDrops().clear(); + Location location = event.getEntity().getLocation(); + location.getWorld().dropItemNaturally(location, new SlimefunItemStack(Items.VILE_PUMPKIN, 1)); + location.getWorld().spawn(location, ExperienceOrb.class).setExperience(2000 + ThreadLocalRandom.current().nextInt(800)); } - private void spawnHelldogs(Location loc) { - CustomMob mob = CustomMob.getByID("HELLDOG"); - - assert mob != null; + private void spawnHelldogs(Location location) { + CustomMob helldog = CustomMob.getById("HELLDOG"); + if (helldog == null) { + FoxyMachines.getInstance().getLogger().warning("Could not spawn Helldogs! Please report this to the github!"); + return; + } ThreadLocalRandom random = ThreadLocalRandom.current(); - for (int i = 0; i < 3; i++) { - mob.spawn(new Location(loc.getWorld(), loc.getX() + random.nextDouble(-1, 1), - loc.getY() + random.nextDouble(0.6, 1.2), loc.getZ() + random.nextDouble(-1, 1))); + helldog.spawn(new Location(location.getWorld(), location.getX() + random.nextDouble(-1, 1), + location.getY() + random.nextDouble(0.6, 1.2), location.getZ() + random.nextDouble(-1, 1))); } for (int i = 0; i < 20; i++) { - loc.getWorld().spawnParticle(Particle.FLAME, loc, 1, random.nextDouble(-1.5, 1.5), + location.getWorld().spawnParticle(Particle.FLAME, location, 1, random.nextDouble(-1.5, 1.5), random.nextDouble(-1.2, 2.4), random.nextDouble(-1.5, 1.5), 0); } } diff --git a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/Helldog.java b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/Helldog.java index 4c7a2d2..c5c28fa 100644 --- a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/Helldog.java +++ b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/Helldog.java @@ -3,7 +3,6 @@ import me.gallowsdove.foxymachines.abstracts.CustomMob; import me.gallowsdove.foxymachines.utils.Utils; import org.bukkit.DyeColor; -import org.bukkit.GameMode; import org.bukkit.attribute.Attribute; import org.bukkit.entity.*; import org.bukkit.event.entity.EntityDamageByEntityEvent; @@ -13,7 +12,7 @@ import org.bukkit.potion.PotionEffectType; import javax.annotation.Nonnull; -import java.util.Collection; +import java.util.List; public class Helldog extends CustomMob { @@ -38,42 +37,49 @@ public void onMobTick(@Nonnull LivingEntity entity, int tick) { Wolf helldog = (Wolf) entity; entity.setFireTicks(999999999); - Collection entities = helldog.getWorld().getNearbyEntities(helldog.getLocation(), 1.54, 1.54, 1.54); - for (Entity player : entities) { - if (player instanceof Player && ((Player) player).getGameMode() == GameMode.SURVIVAL) { - if (tick % 10 == 0) - helldog.attack(player); - } + List players = null; + if (tick % 20 == 0) { + players = Utils.getNearbyPlayersInSurvival(helldog.getLocation(), 16); + helldog.setTarget(players.isEmpty() ? null : players.get(0)); } - if (tick % 20 == 0) { - entities = helldog.getWorld().getNearbyEntities(helldog.getLocation(), 16, 16, 16); + if (tick % 10 == 0) { + if (players == null) { + for (Player player : Utils.getNearbyPlayersInSurvival(helldog.getLocation(), 1.54)) { + helldog.attack(player); + } + return; + } - for (Entity player : entities) { - if (player instanceof Player && ((Player) player).getGameMode() == GameMode.SURVIVAL) { - helldog.setTarget((LivingEntity) player); + for (Player player : players) { + if (Utils.isWithinBox(helldog.getLocation(), player.getLocation(), 1.54)) { + helldog.attack(player); } } } + + } @Override - public void onDeath(@Nonnull EntityDeathEvent e) { - e.getDrops().clear(); + public void onDeath(@Nonnull EntityDeathEvent event) { + super.onDeath(event); + + event.getDrops().clear(); } @Override - protected void onAttack(@Nonnull EntityDamageByEntityEvent e) { - if (!e.isCancelled()) { - Utils.dealDamageBypassingArmor((LivingEntity) e.getEntity(), (e.getDamage() - e.getFinalDamage()) * 0.2); + protected void onAttack(@Nonnull EntityDamageByEntityEvent event) { + if (!event.isCancelled()) { + Utils.dealDamageBypassingArmor((LivingEntity) event.getEntity(), (event.getDamage() - event.getFinalDamage()) * 0.2); } } @Override - protected void onTarget(@Nonnull EntityTargetEvent e) { - if (!(e.getTarget() instanceof Player)) { - e.setCancelled(true); + protected void onTarget(@Nonnull EntityTargetEvent event) { + if (!(event.getTarget() instanceof Player)) { + event.setCancelled(true); } } } diff --git a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/Pixie.java b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/Pixie.java index 7e48d0a..a8beb35 100644 --- a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/Pixie.java +++ b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/Pixie.java @@ -23,21 +23,23 @@ public void onSpawn(@Nonnull LivingEntity spawned) { } @Override - public void onDeath(@Nonnull EntityDeathEvent e) { - e.getDrops().clear(); + public void onDeath(@Nonnull EntityDeathEvent event) { + super.onDeath(event); + + event.getDrops().clear(); } @Override - protected void onAttack(@Nonnull EntityDamageByEntityEvent e) { - if (!e.isCancelled()) { - Utils.dealDamageBypassingArmor((LivingEntity) e.getEntity(), (e.getDamage() - e.getFinalDamage()) * 0.2); + protected void onAttack(@Nonnull EntityDamageByEntityEvent event) { + if (!event.isCancelled()) { + Utils.dealDamageBypassingArmor((LivingEntity) event.getEntity(), (event.getDamage() - event.getFinalDamage()) * 0.2); } } @Override - protected void onTarget(@Nonnull EntityTargetEvent e) { - if (!(e.getTarget() instanceof Player)) { - e.setCancelled(true); + protected void onTarget(@Nonnull EntityTargetEvent event) { + if (!(event.getTarget() instanceof Player)) { + event.setCancelled(true); } } } diff --git a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/PixieQueen.java b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/PixieQueen.java index 5951e4d..996e6fb 100644 --- a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/PixieQueen.java +++ b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/PixieQueen.java @@ -1,6 +1,7 @@ package me.gallowsdove.foxymachines.implementation.mobs; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; +import io.github.thebusybiscuit.slimefun4.libraries.dough.data.persistent.PersistentDataAPI; import me.gallowsdove.foxymachines.FoxyMachines; import me.gallowsdove.foxymachines.Items; import me.gallowsdove.foxymachines.abstracts.CustomBoss; @@ -21,16 +22,16 @@ import org.bukkit.potion.PotionEffectType; import javax.annotation.Nonnull; -import java.util.Collection; +import java.util.List; import java.util.concurrent.ThreadLocalRandom; public class PixieQueen extends CustomBoss { public static class AttackPattern { - public static short CHARGE = 0; - public static short SHOOT = 1; - public static short SUMMON = 2; - public static short IDLE = 3; + public static final short CHARGE = 0; + public static final short SHOOT = 1; + public static final short SUMMON = 2; + public static final short IDLE = 3; } private static final NamespacedKey PATTERN_KEY = new NamespacedKey(FoxyMachines.getInstance(), "pattern"); @@ -57,16 +58,16 @@ protected BossBarStyle getBossBarStyle() { } @Override - protected void onTarget(@Nonnull EntityTargetEvent e) { - if (!(e.getTarget() instanceof Player)) { - e.setCancelled(true); + protected void onTarget(@Nonnull EntityTargetEvent event) { + if (!(event.getTarget() instanceof Player)) { + event.setCancelled(true); } } @Override - protected void onAttack(@Nonnull EntityDamageByEntityEvent e) { - if (!e.isCancelled()) { - Utils.dealDamageBypassingArmor((LivingEntity) e.getEntity(), (e.getDamage() - e.getFinalDamage()) * 0.12); + protected void onAttack(@Nonnull EntityDamageByEntityEvent event) { + if (!event.isCancelled()) { + Utils.dealDamageBypassingArmor((LivingEntity) event.getEntity(), (event.getDamage() - event.getFinalDamage()) * 0.12); } } @@ -86,84 +87,93 @@ public void onBossPattern(@Nonnull LivingEntity mob) { pattern = AttackPattern.IDLE; } - mob.getPersistentDataContainer().set(PATTERN_KEY, PersistentDataType.SHORT, pattern); + PersistentDataAPI.setShort(mob, PATTERN_KEY, pattern); } @Override public void onMobTick(@Nonnull LivingEntity entity, int tick) { + super.onMobTick(entity, tick); + Vex pixieQueen = (Vex) entity; + short pattern = PersistentDataAPI.getShort(entity, PATTERN_KEY); - short pattern = entity.getPersistentDataContainer().get(PATTERN_KEY, PersistentDataType.SHORT); + if (pattern == AttackPattern.SUMMON && tick == 25) { + summonPixieSwarm(pixieQueen.getLocation()); + return; + } if (pattern == AttackPattern.CHARGE) { - Collection entities = pixieQueen.getWorld().getNearbyEntities(pixieQueen.getLocation(), 1.6, 1.6, 1.6); - + Location location = pixieQueen.getLocation(); if (tick % 10 == 0) { - for (Entity player : entities) { - if (player instanceof Player && ((Player) player).getGameMode() == GameMode.SURVIVAL) { - pixieQueen.attack(player); - } + List players = Utils.getNearbyPlayersInSurvival(location, 1.6); + for (Player player : players) { + pixieQueen.attack(player); } } - entities = pixieQueen.getWorld().getNearbyEntities(pixieQueen.getLocation(), 10, 10, 10); - - for (Entity player : entities) { - if (player instanceof Player && ((Player) player).getGameMode() == GameMode.SURVIVAL) { - pixieQueen.setTarget((LivingEntity) player); - pixieQueen.setCharging(false); - if ((tick + 2) % 3 == 0) { - // TODO find out why this sometimes produces error - try { - pixieQueen.setVelocity(player.getLocation().toVector().subtract(entity.getLocation().toVector()).normalize().multiply(0.32)); - } catch (IllegalArgumentException e) { } - } - } + Player player = Utils.getNearbyPlayerInSurvival(location, 10); + pixieQueen.setCharging(false); + pixieQueen.setTarget(player); + + if (player == null) { + return; } - } else if (pattern == AttackPattern.SHOOT) { + + if ((tick + 2) % 3 == 0) { + try { + // TODO: Find out why this sometimes throws an error + pixieQueen.setVelocity(player.getLocation().toVector().subtract(location.toVector()).normalize().multiply(0.32)); + } catch (IllegalArgumentException ignored) { } + } + return; + } + + if (pattern == AttackPattern.SHOOT) { pixieQueen.setCharging(false); - if (pixieQueen.getTarget() != null) { - if (tick % 5 == 0) { - Arrow arrow = entity.launchProjectile(Arrow.class); - arrow.setDamage(24); - arrow.setColor(Color.LIME); - arrow.setGlowing(true); - arrow.setSilent(true); - arrow.setGravity(false); + if (tick % 5 == 0 && pixieQueen.getTarget() != null) { + Arrow arrow = entity.launchProjectile(Arrow.class); + arrow.setDamage(24); + arrow.setColor(Color.LIME); + arrow.setGlowing(true); + arrow.setSilent(true); + arrow.setGravity(false); + arrow.setPersistent(false); + try { + // TODO: Find out why this sometimes throws an error arrow.setVelocity(pixieQueen.getTarget().getLocation().toVector().subtract(pixieQueen.getLocation().toVector()).normalize().multiply(1.42)); + } catch (IllegalArgumentException ignored) { + arrow.remove(); } } - } else if (pattern == AttackPattern.SUMMON) { - if (tick == 25) { - summonPixieSwarm(pixieQueen.getLocation()); - } } } @Override - public void onDeath(@Nonnull EntityDeathEvent e) { - super.onDeath(e); + public void onDeath(@Nonnull EntityDeathEvent event) { + super.onDeath(event); - e.getDrops().clear(); - Location loc = e.getEntity().getLocation(); + event.getDrops().clear(); + Location loc = event.getEntity().getLocation(); loc.getWorld().dropItemNaturally(loc, new SlimefunItemStack(Items.PIXIE_QUEEN_HEART, 1)); loc.getWorld().spawn(loc, ExperienceOrb.class).setExperience(1400 + ThreadLocalRandom.current().nextInt(600)); } - private void summonPixieSwarm(Location loc) { - CustomMob mob = CustomMob.getByID("PIXIE"); + private void summonPixieSwarm(Location location) { + CustomMob mob = CustomMob.getById("PIXIE"); + if (mob == null) { + FoxyMachines.getInstance().getLogger().warning("Could not spawn Pixies! Please report this to the github!"); + return; + } - assert mob != null; ThreadLocalRandom random = ThreadLocalRandom.current(); - for (int i = 0; i < random.nextInt(2) + 3; i++) { - mob.spawn(new Location(loc.getWorld(), loc.getX() + random.nextDouble(-2, 2), - loc.getY() + random.nextDouble(1.2, 2.4), loc.getZ() + random.nextDouble(-2, 2))); + mob.spawn(new Location(location.getWorld(), location.getX() + random.nextDouble(-2, 2), + location.getY() + random.nextDouble(1.2, 2.4), location.getZ() + random.nextDouble(-2, 2))); } for (int i = 0; i < 10; i++) { - loc.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, loc, 1, random.nextDouble(-1.5, 1.5), + location.getWorld().spawnParticle(Particle.VILLAGER_HAPPY, location, 1, random.nextDouble(-1.5, 1.5), random.nextDouble(-1.2, 2.4), random.nextDouble(-1.5, 1.5), 0); } } diff --git a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/RiddenSkeletonHorse.java b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/RiddenSkeletonHorse.java index b0eb47f..76b4456 100644 --- a/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/RiddenSkeletonHorse.java +++ b/src/main/java/me/gallowsdove/foxymachines/implementation/mobs/RiddenSkeletonHorse.java @@ -18,8 +18,7 @@ import java.util.Set; public class RiddenSkeletonHorse extends CustomMob { - private static final Set RESISTANCES = Set.of(new DamageCause[] { - DamageCause.CRAMMING, DamageCause.POISON, DamageCause.BLOCK_EXPLOSION, DamageCause.ENTITY_EXPLOSION}); + private static final Set RESISTANCES = Set.of(DamageCause.CRAMMING, DamageCause.POISON, DamageCause.BLOCK_EXPLOSION, DamageCause.ENTITY_EXPLOSION); public RiddenSkeletonHorse() { super("SKELETON_HORSE", "Skeleton Horse", EntityType.SKELETON_HORSE, 132); @@ -35,38 +34,38 @@ public void onSpawn(@Nonnull LivingEntity spawned) { } @Override - protected void onHit(@Nonnull EntityDamageEvent e) { - if (RESISTANCES.contains(e.getCause())) { - e.setCancelled(true); + protected void onHit(@Nonnull EntityDamageEvent event) { + if (RESISTANCES.contains(event.getCause())) { + event.setCancelled(true); } - SkeletonHorse horse = (SkeletonHorse) e.getEntity(); + SkeletonHorse horse = (SkeletonHorse) event.getEntity(); - if (!e.isCancelled()) { - for (Entity entity : horse.getPassengers()) { - if (entity instanceof LivingEntity passenger) { - CustomMob mob = RiddenSkeletonHorse.getByEntity(entity); - if (mob instanceof CustomBoss boss) { - double finalHealth = horse.getHealth() + passenger.getHealth() - e.getFinalDamage(); - if (finalHealth > 0) { - boss.updateBossBar(passenger, finalHealth / (passenger.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue() + - horse.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue())); - } - } + if (event.isCancelled()) { + return; + } + + for (Entity entity : horse.getPassengers()) { + if (entity instanceof LivingEntity passenger && CustomMob.getByEntity(entity) instanceof CustomBoss boss) { + double finalHealth = horse.getHealth() + passenger.getHealth() - event.getFinalDamage(); + if (finalHealth > 0) { + boss.updateBossBar(passenger, finalHealth / (passenger.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue() + + horse.getAttribute(Attribute.GENERIC_MAX_HEALTH).getBaseValue())); } } } } @Override - protected void onDeath(@Nonnull EntityDeathEvent e) { - e.getDrops().clear(); + protected void onDeath(@Nonnull EntityDeathEvent event) { + super.onDeath(event); - List passengers = e.getEntity().getPassengers(); + event.getDrops().clear(); + List passengers = event.getEntity().getPassengers(); for (Entity passenger: passengers) { - if (passenger instanceof LivingEntity) { - ((LivingEntity) passenger).setHealth(0); + if (passenger instanceof LivingEntity livingEntity) { + livingEntity.setHealth(0); } } } diff --git a/src/main/java/me/gallowsdove/foxymachines/listeners/ChunkLoadListener.java b/src/main/java/me/gallowsdove/foxymachines/listeners/ChunkLoadListener.java new file mode 100644 index 0000000..0009a13 --- /dev/null +++ b/src/main/java/me/gallowsdove/foxymachines/listeners/ChunkLoadListener.java @@ -0,0 +1,40 @@ +package me.gallowsdove.foxymachines.listeners; + +import io.github.thebusybiscuit.slimefun4.libraries.dough.blocks.ChunkPosition; +import me.gallowsdove.foxymachines.abstracts.CustomMob; +import me.gallowsdove.foxymachines.implementation.materials.GhostBlock; +import org.bukkit.Chunk; +import org.bukkit.entity.Entity; +import org.bukkit.entity.FallingBlock; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.world.ChunkLoadEvent; + +import javax.annotation.Nonnull; +import java.util.HashSet; +import java.util.Set; + +public class ChunkLoadListener implements Listener { + private static final Set SCANNED_CHUNKS = new HashSet<>(); + + @EventHandler + public void onChunkLoad(@Nonnull ChunkLoadEvent e) { + Chunk chunk = e.getChunk(); + ChunkPosition chunkPosition = new ChunkPosition(chunk); + if (SCANNED_CHUNKS.contains(chunkPosition)) { + return; + } + SCANNED_CHUNKS.add(chunkPosition); + + for (Entity entity : chunk.getEntities()) { + CustomMob customMob = CustomMob.getByEntity(entity); + if (customMob != null) { + customMob.cacheEntity(entity); + } + + if (entity instanceof FallingBlock && GhostBlock.isGhostBlock(entity)) { + GhostBlock.BLOCK_CACHE.add(entity.getUniqueId()); + } + } + } +} diff --git a/src/main/java/me/gallowsdove/foxymachines/listeners/ChunkLoaderListener.java b/src/main/java/me/gallowsdove/foxymachines/listeners/ChunkLoaderListener.java index 9dc0189..6998b5a 100644 --- a/src/main/java/me/gallowsdove/foxymachines/listeners/ChunkLoaderListener.java +++ b/src/main/java/me/gallowsdove/foxymachines/listeners/ChunkLoaderListener.java @@ -46,7 +46,7 @@ public void onChunkLoaderPlace(@Nonnull BlockPlaceEvent e) { Config cfg = new Config(FoxyMachines.getInstance()); if (!p.hasPermission("foxymachines.bypass-chunk-loader-limit")) { int max = cfg.getInt("max-chunk-loaders"); - if(max != 0 && max < i) { + if (max != 0 && max < i) { p.sendMessage(ChatColor.LIGHT_PURPLE + "Maximum amount of chunk loaders already placed: " + max); e.setCancelled(true); return; diff --git a/src/main/java/me/gallowsdove/foxymachines/tasks/GhostBlockTask.java b/src/main/java/me/gallowsdove/foxymachines/tasks/GhostBlockTask.java index 6b02dc0..ce8b4b8 100644 --- a/src/main/java/me/gallowsdove/foxymachines/tasks/GhostBlockTask.java +++ b/src/main/java/me/gallowsdove/foxymachines/tasks/GhostBlockTask.java @@ -2,20 +2,24 @@ import me.gallowsdove.foxymachines.implementation.materials.GhostBlock; import org.bukkit.Bukkit; -import org.bukkit.World; +import org.bukkit.entity.Entity; import org.bukkit.entity.FallingBlock; -import org.bukkit.persistence.PersistentDataType; import org.bukkit.scheduler.BukkitRunnable; +import java.util.HashSet; +import java.util.UUID; + public class GhostBlockTask extends BukkitRunnable { @Override public void run() { - for (World world : Bukkit.getWorlds()) { - for (FallingBlock block : world.getEntitiesByClass(FallingBlock.class)) { - if (block.getPersistentDataContainer().has(GhostBlock.KEY, PersistentDataType.STRING)) { - block.setTicksLived(1); - } + for (UUID uuid : new HashSet<>(GhostBlock.BLOCK_CACHE)) { + Entity entity = Bukkit.getEntity(uuid); + if (!(entity instanceof FallingBlock)) { + GhostBlock.BLOCK_CACHE.remove(uuid); + continue; } + + entity.setTicksLived(1); } } } diff --git a/src/main/java/me/gallowsdove/foxymachines/tasks/MobTicker.java b/src/main/java/me/gallowsdove/foxymachines/tasks/MobTicker.java index bb2106d..3e22757 100644 --- a/src/main/java/me/gallowsdove/foxymachines/tasks/MobTicker.java +++ b/src/main/java/me/gallowsdove/foxymachines/tasks/MobTicker.java @@ -1,12 +1,16 @@ package me.gallowsdove.foxymachines.tasks; -import me.gallowsdove.foxymachines.abstracts.CustomBoss; import me.gallowsdove.foxymachines.abstracts.CustomMob; import org.bukkit.Bukkit; -import org.bukkit.World; +import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; -public class MobTicker implements Runnable{ +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +public class MobTicker implements Runnable { int tick = 0; @Override @@ -15,17 +19,24 @@ public void run() { mob.onUniqueTick(tick); } - for (World world: Bukkit.getWorlds()) { - for (LivingEntity entity : world.getLivingEntities()) { - CustomMob mob = CustomMob.getByEntity(entity); - if (mob != null) { - mob.onMobTick(entity, tick); - if (mob instanceof CustomBoss customBoss && tick == 100) { - customBoss.onBossPattern(entity); + for (Map.Entry> entry : CustomMob.MOB_CACHE.entrySet()) { + CustomMob customMob = entry.getKey(); + Set entities = entry.getValue(); + for (UUID uuid : new HashSet<>(entities)) { + Entity entity = Bukkit.getEntity(uuid); + if (!(entity instanceof LivingEntity livingEntity)) { + if (entity != null) { + entity.remove(); } + + customMob.uncacheEntity(uuid); + continue; } + + customMob.onMobTick(livingEntity, tick); } } + if (tick == 100) { tick = 0; } diff --git a/src/main/java/me/gallowsdove/foxymachines/utils/Utils.java b/src/main/java/me/gallowsdove/foxymachines/utils/Utils.java index b8f8599..2a9c35e 100644 --- a/src/main/java/me/gallowsdove/foxymachines/utils/Utils.java +++ b/src/main/java/me/gallowsdove/foxymachines/utils/Utils.java @@ -1,11 +1,19 @@ package me.gallowsdove.foxymachines.utils; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.Bukkit; import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; public class Utils { private Utils() {} @@ -45,4 +53,51 @@ public static int countItemInInventory(@Nonnull Inventory inventory, @Nonnull It return amount; } + + public static boolean isWithinBox(Location centerLocation, Location location, double radius) { + return isWithinBox(centerLocation, location, radius, radius, radius); + } + + public static boolean isWithinBox(Location centerLocation, Location location, double x, double y, double z) { + return Math.abs(centerLocation.getX() - location.getX()) <= x + && Math.abs(centerLocation.getY() - location.getY()) <= y + && Math.abs(centerLocation.getZ() - location.getZ()) <= z; + } + + public static List getNearbyPlayersInSurvival(Location location, double radius) { + return getNearbyPlayersInSurvival(location, radius, radius, radius); + } + + public static List getNearbyPlayersInSurvival(Location location, double x, double y, double z) { + World world = location.getWorld(); + if (world == null) { + return new ArrayList<>(); + } + + List players = new ArrayList<>(); + for (Entity entity : world.getNearbyEntities(location, x, y, z)) { + if (entity instanceof Player player && player.getGameMode() == GameMode.SURVIVAL) { + players.add(player); + } + } + return players; + } + + public static Player getNearbyPlayerInSurvival(Location location, double radius) { + return getNearbyPlayerInSurvival(location, radius, radius, radius); + } + + public static @Nullable Player getNearbyPlayerInSurvival(Location location, double x, double y, double z) { + World world = location.getWorld(); + if (world == null) { + return null; + } + + for (Entity entity : world.getNearbyEntities(location, x, y, z)) { + if (entity instanceof Player player && player.getGameMode() == GameMode.SURVIVAL) { + return player; + } + } + return null; + } }