diff --git a/src/main/java/com/alttd/playerutils/commands/PlayerUtilsCommand.java b/src/main/java/com/alttd/playerutils/commands/PlayerUtilsCommand.java index 669a1fb..21af07f 100644 --- a/src/main/java/com/alttd/playerutils/commands/PlayerUtilsCommand.java +++ b/src/main/java/com/alttd/playerutils/commands/PlayerUtilsCommand.java @@ -34,7 +34,8 @@ public class PlayerUtilsCommand implements CommandExecutor, TabExecutor { new XPCheque(playerUtils), new XPCalc(), new Reload(playerUtils), - new Key()) + new Key(), + new ReCountArmorStands(playerUtils)) ); } diff --git a/src/main/java/com/alttd/playerutils/commands/playerutils_subcommands/ReCountArmorStands.java b/src/main/java/com/alttd/playerutils/commands/playerutils_subcommands/ReCountArmorStands.java new file mode 100644 index 0000000..8c4a4f0 --- /dev/null +++ b/src/main/java/com/alttd/playerutils/commands/playerutils_subcommands/ReCountArmorStands.java @@ -0,0 +1,75 @@ +package com.alttd.playerutils.commands.playerutils_subcommands; + +import com.alttd.playerutils.PlayerUtils; +import com.alttd.playerutils.commands.SubCommand; +import com.alttd.playerutils.config.Messages; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.Chunk; +import org.bukkit.NamespacedKey; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +@Slf4j +@RequiredArgsConstructor +public class ReCountArmorStands extends SubCommand { + + private final PlayerUtils playerUtils; + + @Override + public boolean onCommand(CommandSender commandSender, String[] args) { + if (!(commandSender instanceof Player player)) { + return false; + } + Chunk chunk = player.getLocation().getChunk(); + Optional armorStandCount = recountArmorStands(chunk); + if (armorStandCount.isEmpty()) { + player.sendRichMessage(Messages.RECOUNT_ARMOR_STANDS.FAILED_COUNT); + return true; + } + player.sendRichMessage(Messages.RECOUNT_ARMOR_STANDS.SUCCESS, Placeholder.parsed("count", String.valueOf(armorStandCount.get()))); + return true; + } + + @Override + public String getName() { + return "recount_armor_stands"; + } + + @Override + public List getTabComplete(CommandSender commandSender, String[] args) { + return List.of(); + } + + @Override + public String getHelpMessage() { + return Messages.HELP.RECOUNT_ARMOR_STANDS; + } + + private Optional recountArmorStands(Chunk chunk) { + NamespacedKey namespacedKey = NamespacedKey.fromString("armor_stand_count", playerUtils); + if (namespacedKey == null) { + log.warn("Unable to retrieve name spaced key for armor stand count."); + return Optional.empty(); + } + PersistentDataContainer persistentDataContainer = chunk.getPersistentDataContainer(); + int armorStands = countArmorStands(chunk); + persistentDataContainer.set(namespacedKey, PersistentDataType.INTEGER, armorStands); + + return Optional.of(armorStands); + } + + private int countArmorStands(Chunk chunk) { + return (int) Arrays.stream(chunk.getEntities()) + .filter(entity -> entity.getType().equals(EntityType.ARMOR_STAND)) + .count(); + } +} diff --git a/src/main/java/com/alttd/playerutils/config/Messages.java b/src/main/java/com/alttd/playerutils/config/Messages.java index 040e32a..c4ae211 100644 --- a/src/main/java/com/alttd/playerutils/config/Messages.java +++ b/src/main/java/com/alttd/playerutils/config/Messages.java @@ -1,5 +1,7 @@ package com.alttd.playerutils.config; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.util.List; @@ -32,6 +34,7 @@ public class Messages extends AbstractConfig { public static String ROTATE_BLOCK = "Enable rotating blocks with a blaze rod: /pu rotateblock"; public static String KEY = "Receive a key that you are owed: /pu key"; public static String GHAST_SPEED = "Set the speed of a ghast: /pu ghastspeed "; + public static String RECOUNT_ARMOR_STANDS = "Recount armor stands in current chunk: /pu recount"; @SuppressWarnings("unused") private static void load() { @@ -43,6 +46,7 @@ public class Messages extends AbstractConfig { RELOAD = config.getString(prefix, "reload", RELOAD); ROTATE_BLOCK = config.getString(prefix, "rotate-block", ROTATE_BLOCK); GHAST_SPEED = config.getString(prefix, "ghast-speed", GHAST_SPEED); + RECOUNT_ARMOR_STANDS = config.getString(prefix, "recount-armor-stands", RECOUNT_ARMOR_STANDS); } } @@ -180,4 +184,17 @@ public class Messages extends AbstractConfig { } } + + public static class RECOUNT_ARMOR_STANDS { + private static final String prefix = "recount-armor-stands."; + + public static String FAILED_COUNT = "Unable to recount armor stands."; + public static String SUCCESS = "Recounted armor stands and the count to chunk data."; + + @SuppressWarnings("unused") + private static void load() { + FAILED_COUNT = config.getString(prefix, "failed-count", FAILED_COUNT); + SUCCESS = config.getString(prefix, "success", SUCCESS); + } + } } diff --git a/src/main/java/com/alttd/playerutils/event_listeners/LimitArmorStands.java b/src/main/java/com/alttd/playerutils/event_listeners/LimitArmorStands.java index 97fb742..c51b8cc 100644 --- a/src/main/java/com/alttd/playerutils/event_listeners/LimitArmorStands.java +++ b/src/main/java/com/alttd/playerutils/event_listeners/LimitArmorStands.java @@ -12,17 +12,20 @@ import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.block.Block; import org.bukkit.block.TrialSpawner; +import org.bukkit.entity.ArmorStand; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; import org.jetbrains.annotations.NotNull; import java.util.Arrays; +import java.util.Optional; @Slf4j public class LimitArmorStands implements Listener { @@ -72,6 +75,31 @@ import java.util.Arrays; } } + @EventHandler + public void onPlayerDamageEntity(EntityDamageByEntityEvent event) { + if (!(event.getDamager() instanceof Player player)) { + return; + } + if (!(event.getEntity() instanceof ArmorStand armorStand)) { + return; + } + boolean willBreak = armorStand.getHealth() - event.getFinalDamage() <= 0.0; + if (!willBreak) { + return; + } + Optional optionalResult = getGetChunkContainerAndNamespacedKey(armorStand.getLocation().getChunk(), player); + if (optionalResult.isEmpty()) { + event.setCancelled(true); + return; + } + ChunkContainerAndNamespacedKey result = optionalResult.get(); + int newArmorStandCount = Math.max(0, result.armorStandCount() - 1); + result.persistentDataContainer().set(result.namespacedKey(), PersistentDataType.INTEGER, newArmorStandCount); + } + + private record ChunkContainerAndNamespacedKey(NamespacedKey namespacedKey, PersistentDataContainer persistentDataContainer, int armorStandCount) { + } + private void handleArmorStandPlacing(PlayerInteractEvent event, ArmorStandCountConsumer consumer) { if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { return; @@ -82,15 +110,24 @@ import java.util.Arrays; if (event.getClickedBlock() == null) { return; } - Player player = event.getPlayer();; + Player player = event.getPlayer(); Chunk chunk = event.getClickedBlock().getChunk(); + Optional getChunkContainerAndNamespacedKey = getGetChunkContainerAndNamespacedKey(chunk, player); + if (getChunkContainerAndNamespacedKey.isEmpty()) { + event.setCancelled(true); + return; + } + ChunkContainerAndNamespacedKey result = getChunkContainerAndNamespacedKey.get(); + consumer.apply(result.armorStandCount(), event.getPlayer(), result.namespacedKey(), result.persistentDataContainer()); + } + + private Optional getGetChunkContainerAndNamespacedKey(Chunk chunk, Player player) { NamespacedKey namespacedKey = NamespacedKey.fromString("armor_stand_count", playerUtils); if (namespacedKey == null) { - event.setCancelled(true); log.warn("Unable to retrieve name spaced key for armor stand count."); player.sendRichMessage("Something went wrong while checking the armor stand count. " + - "You will not be able to place this until this is fixed. Please contact a staff member"); - return; + "You will not be able to place this until this is fixed. Please contact a staff member"); + return Optional.empty(); } PersistentDataContainer persistentDataContainer = chunk.getPersistentDataContainer(); if (!persistentDataContainer.has(namespacedKey, PersistentDataType.INTEGER)) { @@ -98,13 +135,9 @@ import java.util.Arrays; } Integer armorStandCount = persistentDataContainer.get(namespacedKey, PersistentDataType.INTEGER); if (armorStandCount == null) { - event.setCancelled(true); - log.warn("Unable to retrieve armor stand count."); - player.sendRichMessage("Something went wrong while checking the armor stand count. " + - "You will not be able to place this until this is fixed. Please contact a staff member"); - return; + return Optional.empty(); } - consumer.apply(armorStandCount, event.getPlayer(), namespacedKey, persistentDataContainer); + return Optional.of(new ChunkContainerAndNamespacedKey(namespacedKey, persistentDataContainer, armorStandCount)); } private void handleRightClickTrialSpawner(PlayerInteractEvent event, TrialSpawnerTimerConsumer consumer) { diff --git a/src/main/java/com/alttd/playerutils/event_listeners/PlayerJoin.java b/src/main/java/com/alttd/playerutils/event_listeners/PlayerJoin.java index a1bc11d..a0690a4 100644 --- a/src/main/java/com/alttd/playerutils/event_listeners/PlayerJoin.java +++ b/src/main/java/com/alttd/playerutils/event_listeners/PlayerJoin.java @@ -52,7 +52,7 @@ public class PlayerJoin implements Listener { AttributeModifier.Operation.ADD_NUMBER ); - attributeInstance.addModifier(attributeModifier); + attributeInstance.addTransientModifier(attributeModifier); } double actualValue = attributeInstance.getValue();