Compare commits

...

2 Commits

Author SHA1 Message Date
Teriuihi 7c04361ea5 Add armor stand placement limits per chunk
Implemented functionality to restrict the number of armor stands a player can place in a chunk based on permissions. Added configuration support for customizable limits and proper error handling for edge cases. Registered the LimitArmorStands event listener in the plugin manager.
2025-03-22 20:33:31 +01:00
Teriuihi 10449f4a80 Refactor message-sending to use sendRichMessage API.
Replaced all instances of sendMiniMessage with sendRichMessage for improved readability and consistency across the codebase. This change ensures better handling of message formatting and placeholders.
2025-03-22 19:12:28 +01:00
13 changed files with 154 additions and 38 deletions

View File

@ -41,4 +41,4 @@ dependencies {
compileOnly("com.alttd:Galaxy-API:1.21-R0.1-SNAPSHOT") {
isChanging = true
}
}
}

View File

@ -14,4 +14,4 @@ pluginManagement {
repositories {
gradlePluginPortal()
}
}
}

View File

@ -5,10 +5,7 @@ import com.alttd.playerutils.commands.playerutils_subcommands.RotateBlock;
import com.alttd.playerutils.config.Config;
import com.alttd.playerutils.config.KeyStorage;
import com.alttd.playerutils.config.Messages;
import com.alttd.playerutils.event_listeners.GoatHornEvent;
import com.alttd.playerutils.event_listeners.RotateBlockEvent;
import com.alttd.playerutils.event_listeners.TeleportEvent;
import com.alttd.playerutils.event_listeners.XpBottleEvent;
import com.alttd.playerutils.event_listeners.*;
import com.alttd.playerutils.util.Logger;
import org.bukkit.Bukkit;
import org.bukkit.plugin.PluginManager;
@ -44,6 +41,7 @@ public final class PlayerUtils extends JavaPlugin {
pluginManager.registerEvents(new XpBottleEvent(this, logger), this);
pluginManager.registerEvents(new TeleportEvent(), this);
pluginManager.registerEvents(new GoatHornEvent(logger), this);
pluginManager.registerEvents(new LimitArmorStands(this, logger), this);
RotateBlockEvent rotateBlockEvent = new RotateBlockEvent(logger);
pluginManager.registerEvents(rotateBlockEvent, this);

View File

@ -41,10 +41,10 @@ public class PlayerUtilsCommand implements CommandExecutor, TabExecutor {
@Override
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String cmd, @NotNull String[] args) {
if (args.length == 0) {
commandSender.sendMiniMessage(Messages.HELP.HELP_MESSAGE_WRAPPER.replaceAll("<commands>", subCommands.stream()
commandSender.sendRichMessage(Messages.HELP.HELP_MESSAGE_WRAPPER.replaceAll("<commands>", subCommands.stream()
.filter(subCommand -> commandSender.hasPermission(subCommand.getPermission()))
.map(SubCommand::getHelpMessage)
.collect(Collectors.joining("\n"))), null);
.collect(Collectors.joining("\n"))));
return true;
}
@ -53,13 +53,13 @@ public class PlayerUtilsCommand implements CommandExecutor, TabExecutor {
return false;
if (!commandSender.hasPermission(subCommand.getPermission())) {
commandSender.sendMiniMessage(Messages.GENERIC.NO_PERMISSION, Placeholder.parsed("permission", subCommand.getPermission()));
commandSender.sendRichMessage(Messages.GENERIC.NO_PERMISSION, Placeholder.parsed("permission", subCommand.getPermission()));
return true;
}
boolean executedCorrectly = subCommand.onCommand(commandSender, args);
if (!executedCorrectly) {
commandSender.sendMiniMessage(subCommand.getHelpMessage(), null);
commandSender.sendRichMessage(subCommand.getHelpMessage());
}
return true;
}
@ -102,4 +102,4 @@ public class PlayerUtilsCommand implements CommandExecutor, TabExecutor {
}
subCommands.add(subCommand);
}
}
}

View File

@ -54,7 +54,7 @@ public class Glow extends SubCommand {
Optional<DyeColor> any = Arrays.stream(DyeColor.values()).filter(chatColor -> chatColor.name().equalsIgnoreCase(args[1])).findAny();
if (any.isEmpty()) {
commandSender.sendMiniMessage(getHelpMessage(), null);
commandSender.sendRichMessage(getHelpMessage());
return true;
}
@ -75,36 +75,36 @@ public class Glow extends SubCommand {
private Optional<Player> getTargetPlayer(CommandSender commandSender, String[] args) {
if (args.length == 2) {
if (!(commandSender instanceof Player commandPlayer)) {
commandSender.sendMiniMessage(Messages.GENERIC.PLAYER_ONLY, null);
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY);
return Optional.empty();
}
return Optional.of(commandPlayer);
}
if (!commandSender.hasPermission(getPermission() + ".other")) {
commandSender.sendMiniMessage(Messages.GENERIC.NO_PERMISSION, Placeholder.parsed("permission", getPermission() + ".other"));
commandSender.sendRichMessage(Messages.GENERIC.NO_PERMISSION, Placeholder.parsed("permission", getPermission() + ".other"));
return Optional.empty();
}
Optional<? extends Player> any = Bukkit.getOnlinePlayers().stream().filter(offlinePlayer -> offlinePlayer.getName().equalsIgnoreCase(args[2])).findAny();
if (any.isPresent()) {
return Optional.of(any.get());
} else {
commandSender.sendMiniMessage(Messages.GENERIC.PLAYER_NOT_FOUND, Placeholder.parsed("player", args[2]));
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_NOT_FOUND, Placeholder.parsed("player", args[2]));
return Optional.empty();
}
}
private void turnOffGlow(CommandSender commandSender, Player player, boolean otherPlayer) {
player.sendMiniMessage(Messages.GLOW.GLOW_OFF, null);
player.sendRichMessage(Messages.GLOW.GLOW_OFF);
player.setGlowing(false);
if (otherPlayer) {
commandSender.sendMiniMessage(Messages.GLOW.GLOW_OFF_FOR_PLAYER, Placeholder.component("player", player.name()));
commandSender.sendRichMessage(Messages.GLOW.GLOW_OFF_FOR_PLAYER, Placeholder.component("player", player.name()));
}
}
private void turnOnGlow(CommandSender commandSender, Player player, Team team, DyeColor dyeColor, boolean otherPlayer) {
if (team.getScoreboard() == null) {
commandSender.sendMiniMessage(Messages.GLOW.UNABLE_TO_GET_SCOREBOARD, null);
commandSender.sendRichMessage(Messages.GLOW.UNABLE_TO_GET_SCOREBOARD);
logger.warning("Unable to get scoreboard for team");
return;
}
@ -114,9 +114,9 @@ public class Glow extends SubCommand {
player.setScoreboard(team.getScoreboard());
player.setGlowing(true);
player.sendMiniMessage(Messages.GLOW.GLOW_ON, Placeholder.parsed("color", dyeColor.name()));
player.sendRichMessage(Messages.GLOW.GLOW_ON, Placeholder.parsed("color", dyeColor.name()));
if (otherPlayer) {
commandSender.sendMiniMessage(Messages.GLOW.GLOW_ON_FOR_PLAYER, TagResolver.resolver(
commandSender.sendRichMessage(Messages.GLOW.GLOW_ON_FOR_PLAYER, TagResolver.resolver(
Placeholder.parsed("color", dyeColor.name()),
Placeholder.component("player", player.name())
));

View File

@ -26,7 +26,7 @@ public class Key extends SubCommand {
@Override
public boolean onCommand(CommandSender commandSender, String[] args) {
if (!(commandSender instanceof Player player)) {
commandSender.sendMiniMessage(Messages.GENERIC.PLAYER_ONLY, null);
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY);
return true;
}
@ -36,7 +36,7 @@ public class Key extends SubCommand {
String crate = args[1].toLowerCase();
if (!Config.KEY.CRATES.containsKey(crate)) {
commandSender.sendMiniMessage(Messages.KEY.CRATE_NOT_EXIST, Placeholder.parsed("crate", crate));
commandSender.sendRichMessage(Messages.KEY.CRATE_NOT_EXIST, Placeholder.parsed("crate", crate));
return true;
}
@ -45,7 +45,7 @@ public class Key extends SubCommand {
int totalKeys = Config.KEY.CRATES.getOrDefault(crate, 0);
int keys = crateMap.getOrDefault(uuid, 0);
if (keys >= totalKeys) {
commandSender.sendMiniMessage(Messages.KEY.RETRIEVED_ALL_KEYS, TagResolver.resolver(
commandSender.sendRichMessage(Messages.KEY.RETRIEVED_ALL_KEYS, TagResolver.resolver(
Placeholder.parsed("crate", crate),
Placeholder.parsed("keys", String.valueOf(keys))));
return true;
@ -55,11 +55,11 @@ public class Key extends SubCommand {
logger.info(String.format("Gave %s one key for %s", player.getName(), crate));
commandSender.getServer().dispatchCommand(Bukkit.getConsoleSender(), String.format("crate give v %s 1 %s", crate, player.getName()));
if (keys + 1 == totalKeys) {
commandSender.sendMiniMessage(Messages.KEY.GAVE_FINAL_KEY, TagResolver.resolver(
commandSender.sendRichMessage(Messages.KEY.GAVE_FINAL_KEY, TagResolver.resolver(
Placeholder.parsed("crate", crate),
Placeholder.parsed("keys", String.valueOf(keys + 1))));
} else {
commandSender.sendMiniMessage(Messages.KEY.GAVE_KEY, TagResolver.resolver(
commandSender.sendRichMessage(Messages.KEY.GAVE_KEY, TagResolver.resolver(
Placeholder.parsed("crate", crate),
Placeholder.parsed("keys", String.valueOf(keys + 1)),
Placeholder.parsed("total_keys", String.valueOf(totalKeys))));

View File

@ -18,7 +18,7 @@ public class Reload extends SubCommand {
@Override
public boolean onCommand(CommandSender commandSender, String[] args) {
playerUtils.reloadConfigs();
commandSender.sendMiniMessage(Messages.RELOAD.RELOADED, null);
commandSender.sendRichMessage(Messages.RELOAD.RELOADED);
return true;
}

View File

@ -19,15 +19,15 @@ public class RotateBlock extends SubCommand {
@Override
public boolean onCommand(CommandSender commandSender, String[] args) {
if (!(commandSender instanceof Player player)) {
commandSender.sendMiniMessage(Messages.GENERIC.PLAYER_ONLY, null);
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY);
return true;
}
boolean enabled = rotateBlockEvent.toggleRotate(player.getUniqueId());
if (enabled)
commandSender.sendMiniMessage(Messages.ROTATE_BLOCK.ENABLED, null);
commandSender.sendRichMessage(Messages.ROTATE_BLOCK.ENABLED);
else
commandSender.sendMiniMessage(Messages.ROTATE_BLOCK.DISABLED, null);
commandSender.sendRichMessage(Messages.ROTATE_BLOCK.DISABLED);
return true;
}

View File

@ -34,7 +34,7 @@ public class XPCalc extends SubCommand {
startingLevel++;
}
commandSender.sendMiniMessage(Messages.XP_CALC.XP_NEEDED, Placeholder.parsed("xp_needed", String.valueOf(totalXpNeeded)));
commandSender.sendRichMessage(Messages.XP_CALC.XP_NEEDED, Placeholder.parsed("xp_needed", String.valueOf(totalXpNeeded)));
return true;
}

View File

@ -31,7 +31,7 @@ public class XPCheque extends SubCommand {
@Override
public boolean onCommand(CommandSender commandSender, String[] args) {
if (!(commandSender instanceof Player player)) {
commandSender.sendMiniMessage(Messages.GENERIC.PLAYER_ONLY, null);
commandSender.sendRichMessage(Messages.GENERIC.PLAYER_ONLY);
return true;
}
@ -48,7 +48,7 @@ public class XPCheque extends SubCommand {
}
if (amount > 64 || amount < 1) {
commandSender.sendMiniMessage(Messages.XP_CHEQUE.INVALID_AMOUNT, null);
commandSender.sendRichMessage(Messages.XP_CHEQUE.INVALID_AMOUNT);
return true;
}
@ -60,24 +60,24 @@ public class XPCheque extends SubCommand {
}
if ((xpValue <= 0)) {
commandSender.sendMiniMessage(Messages.XP_CHEQUE.NEGATIVE, null);
commandSender.sendRichMessage(Messages.XP_CHEQUE.NEGATIVE);
return true;
}
int totalExperience = player.getTotalExperience();
if (totalExperience < (xpValue * amount)) {
commandSender.sendMiniMessage(Messages.XP_CHEQUE.NOT_ENOUGH_XP, Placeholder.parsed("xp", String.valueOf(totalExperience)));
commandSender.sendRichMessage(Messages.XP_CHEQUE.NOT_ENOUGH_XP, Placeholder.parsed("xp", String.valueOf(totalExperience)));
return true;
}
ItemStack heldItem = player.getInventory().getItemInMainHand();
if (!heldItem.getType().equals(Material.GLASS_BOTTLE)) {
commandSender.sendMiniMessage(Messages.XP_CHEQUE.NOT_HOLDING_BOTTLE, null);
commandSender.sendRichMessage(Messages.XP_CHEQUE.NOT_HOLDING_BOTTLE);
return true;
}
if (heldItem.getAmount() < amount) {
commandSender.sendMiniMessage(Messages.XP_CHEQUE.NOT_ENOUGH_BOTTLE, Placeholder.parsed("amount", String.valueOf(amount)));
commandSender.sendRichMessage(Messages.XP_CHEQUE.NOT_ENOUGH_BOTTLE, Placeholder.parsed("amount", String.valueOf(amount)));
return true;
}
@ -122,7 +122,7 @@ public class XPCheque extends SubCommand {
NamespacedKey customXp = NamespacedKey.fromString("custom_xp", playerUtils);
if (customXp == null) {
player.sendMiniMessage(Messages.XP_CHEQUE.FAILED_STORAGE, null);
player.sendRichMessage(Messages.XP_CHEQUE.FAILED_STORAGE);
return Optional.empty();
}
persistentDataContainer.set(customXp, PersistentDataType.INTEGER, xpValue);

View File

@ -62,4 +62,24 @@ public class Config extends AbstractConfig{
}
}
}
public static class ARMOR_STAND_LIMIT {
private static final String prefix = "armor_stand_limit.";
public static HashMap<String, Integer> LIMIT = new HashMap<>();
@SuppressWarnings("unused")
private static void load() {
LIMIT.clear();
ConfigurationSection configurationSection = config.getConfigurationSection(prefix.substring(0, prefix.length() - 1));
if (configurationSection == null) {
config.logger.warning("No limits configured, adding default");
config.set(prefix, "default", 10);
}
Set<String> limits = configurationSection.getKeys(false);
for (String key : limits) {
LIMIT.put(key, config.getInt(prefix, key, 10));
}
}
}
}

View File

@ -0,0 +1,98 @@
package com.alttd.playerutils.event_listeners;
import com.alttd.playerutils.PlayerUtils;
import com.alttd.playerutils.config.Config;
import com.alttd.playerutils.util.Logger;
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
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.player.PlayerInteractEvent;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
public class LimitArmorStands implements Listener {
private final PlayerUtils playerUtils;
private final Logger logger;
public LimitArmorStands(PlayerUtils playerUtils, Logger logger) {
this.playerUtils = playerUtils;
this.logger = logger;
}
@FunctionalInterface
private interface ArmorStandCountConsumer {
void apply(int armorStandCount, @NotNull Player player, @NotNull NamespacedKey namespacedKey,
@NotNull PersistentDataContainer persistentDataContainer);
}
@EventHandler
public void onArmorStandSpawn(PlayerInteractEvent event) {
handleArmorStandPlacing(event, (armorStandCount, player, namespacedKey, persistentDataContainer) -> {
int max = 0;
for (String permission : Config.ARMOR_STAND_LIMIT.LIMIT.keySet()) {
if (player.hasPermission("pu.limit." + permission)) {
max = Math.max(max, Config.ARMOR_STAND_LIMIT.LIMIT.get(permission));
}
}
if (armorStandCount >= max) {
event.setCancelled(true);
player.sendRichMessage("<red>You can not place more than <max> armor stands in a chunk</red>",
Placeholder.parsed("max", String.valueOf(max)));
return;
}
persistentDataContainer.set(namespacedKey, PersistentDataType.INTEGER, ++armorStandCount);
});
}
private void handleArmorStandPlacing(PlayerInteractEvent event, ArmorStandCountConsumer consumer) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return;
}
if (!event.getMaterial().equals(Material.ARMOR_STAND)) {
return;
}
if (event.getClickedBlock() == null) {
return;
}
Player player = event.getPlayer();;
Chunk chunk = event.getClickedBlock().getChunk();
NamespacedKey namespacedKey = NamespacedKey.fromString("armor_stand_count", playerUtils);
if (namespacedKey == null) {
event.setCancelled(true);
logger.warning("Unable to retrieve name spaced key for 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;
}
PersistentDataContainer persistentDataContainer = chunk.getPersistentDataContainer();
if (!persistentDataContainer.has(namespacedKey, PersistentDataType.INTEGER)) {
persistentDataContainer.set(namespacedKey, PersistentDataType.INTEGER, countArmorStands(chunk));
}
Integer armorStandCount = persistentDataContainer.get(namespacedKey, PersistentDataType.INTEGER);
if (armorStandCount == null) {
event.setCancelled(true);
logger.warning("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);
}
private int countArmorStands(Chunk chunk) {
return (int) Arrays.stream(chunk.getEntities())
.filter(entity -> entity.getType().equals(EntityType.ARMOR_STAND))
.count();
}
}

View File

@ -103,7 +103,7 @@ public class XpBottleEvent implements Listener {
NamespacedKey customXp = NamespacedKey.fromString("custom_xp", playerUtils);
if (customXp == null) {
player.sendMiniMessage(Messages.XP_CHEQUE.FAILED_STORAGE, null);
player.sendRichMessage(Messages.XP_CHEQUE.FAILED_STORAGE);
return Optional.empty();
}
persistentDataContainer.set(customXp, PersistentDataType.INTEGER, xpValue);