Add ReCountArmorStands command and handle armorstands being removed

This commit is contained in:
akastijn 2026-01-21 06:59:35 +01:00
parent cb98c3761b
commit f7313f8f25
5 changed files with 138 additions and 12 deletions

View File

@ -34,7 +34,8 @@ public class PlayerUtilsCommand implements CommandExecutor, TabExecutor {
new XPCheque(playerUtils), new XPCheque(playerUtils),
new XPCalc(), new XPCalc(),
new Reload(playerUtils), new Reload(playerUtils),
new Key()) new Key(),
new ReCountArmorStands(playerUtils))
); );
} }

View File

@ -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<Integer> 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<String> getTabComplete(CommandSender commandSender, String[] args) {
return List.of();
}
@Override
public String getHelpMessage() {
return Messages.HELP.RECOUNT_ARMOR_STANDS;
}
private Optional<Integer> 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();
}
}

View File

@ -1,5 +1,7 @@
package com.alttd.playerutils.config; package com.alttd.playerutils.config;
import org.jetbrains.annotations.NotNull;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
@ -32,6 +34,7 @@ public class Messages extends AbstractConfig {
public static String ROTATE_BLOCK = "<green>Enable rotating blocks with a blaze rod: <gold>/pu rotateblock</gold></green>"; public static String ROTATE_BLOCK = "<green>Enable rotating blocks with a blaze rod: <gold>/pu rotateblock</gold></green>";
public static String KEY = "<green>Receive a key that you are owed: <gold>/pu key</gold></green>"; public static String KEY = "<green>Receive a key that you are owed: <gold>/pu key</gold></green>";
public static String GHAST_SPEED = "<green>Set the speed of a ghast: <gold>/pu ghastspeed <speed></gold></green>"; public static String GHAST_SPEED = "<green>Set the speed of a ghast: <gold>/pu ghastspeed <speed></gold></green>";
public static String RECOUNT_ARMOR_STANDS = "<green>Recount armor stands in current chunk: <gold>/pu recount</gold></green>";
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static void load() { private static void load() {
@ -43,6 +46,7 @@ public class Messages extends AbstractConfig {
RELOAD = config.getString(prefix, "reload", RELOAD); RELOAD = config.getString(prefix, "reload", RELOAD);
ROTATE_BLOCK = config.getString(prefix, "rotate-block", ROTATE_BLOCK); ROTATE_BLOCK = config.getString(prefix, "rotate-block", ROTATE_BLOCK);
GHAST_SPEED = config.getString(prefix, "ghast-speed", GHAST_SPEED); 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 = "<red>Unable to recount armor stands.</red>";
public static String SUCCESS = "<green>Recounted <count> armor stands and the count to chunk data.</green>";
@SuppressWarnings("unused")
private static void load() {
FAILED_COUNT = config.getString(prefix, "failed-count", FAILED_COUNT);
SUCCESS = config.getString(prefix, "success", SUCCESS);
}
}
} }

View File

@ -12,17 +12,20 @@ import org.bukkit.Material;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.TrialSpawner; import org.bukkit.block.TrialSpawner;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.Action; import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Arrays; import java.util.Arrays;
import java.util.Optional;
@Slf4j public class LimitArmorStands implements Listener { @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<ChunkContainerAndNamespacedKey> 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) { private void handleArmorStandPlacing(PlayerInteractEvent event, ArmorStandCountConsumer consumer) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return; return;
@ -82,15 +110,24 @@ import java.util.Arrays;
if (event.getClickedBlock() == null) { if (event.getClickedBlock() == null) {
return; return;
} }
Player player = event.getPlayer();; Player player = event.getPlayer();
Chunk chunk = event.getClickedBlock().getChunk(); Chunk chunk = event.getClickedBlock().getChunk();
Optional<ChunkContainerAndNamespacedKey> 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<LimitArmorStands.ChunkContainerAndNamespacedKey> getGetChunkContainerAndNamespacedKey(Chunk chunk, Player player) {
NamespacedKey namespacedKey = NamespacedKey.fromString("armor_stand_count", playerUtils); NamespacedKey namespacedKey = NamespacedKey.fromString("armor_stand_count", playerUtils);
if (namespacedKey == null) { if (namespacedKey == null) {
event.setCancelled(true);
log.warn("Unable to retrieve name spaced key for armor stand count."); log.warn("Unable to retrieve name spaced key for armor stand count.");
player.sendRichMessage("<red>Something went wrong while checking the armor stand count. " + player.sendRichMessage("<red>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</red>"); "You will not be able to place this until this is fixed. Please contact a staff member</red>");
return; return Optional.empty();
} }
PersistentDataContainer persistentDataContainer = chunk.getPersistentDataContainer(); PersistentDataContainer persistentDataContainer = chunk.getPersistentDataContainer();
if (!persistentDataContainer.has(namespacedKey, PersistentDataType.INTEGER)) { if (!persistentDataContainer.has(namespacedKey, PersistentDataType.INTEGER)) {
@ -98,13 +135,9 @@ import java.util.Arrays;
} }
Integer armorStandCount = persistentDataContainer.get(namespacedKey, PersistentDataType.INTEGER); Integer armorStandCount = persistentDataContainer.get(namespacedKey, PersistentDataType.INTEGER);
if (armorStandCount == null) { if (armorStandCount == null) {
event.setCancelled(true); return Optional.empty();
log.warn("Unable to retrieve armor stand count.");
player.sendRichMessage("<red>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</red>");
return;
} }
consumer.apply(armorStandCount, event.getPlayer(), namespacedKey, persistentDataContainer); return Optional.of(new ChunkContainerAndNamespacedKey(namespacedKey, persistentDataContainer, armorStandCount));
} }
private void handleRightClickTrialSpawner(PlayerInteractEvent event, TrialSpawnerTimerConsumer consumer) { private void handleRightClickTrialSpawner(PlayerInteractEvent event, TrialSpawnerTimerConsumer consumer) {

View File

@ -52,7 +52,7 @@ public class PlayerJoin implements Listener {
AttributeModifier.Operation.ADD_NUMBER AttributeModifier.Operation.ADD_NUMBER
); );
attributeInstance.addModifier(attributeModifier); attributeInstance.addTransientModifier(attributeModifier);
} }
double actualValue = attributeInstance.getValue(); double actualValue = attributeInstance.getValue();