diff --git a/src/main/java/com/alttd/playerutils/PlayerUtils.java b/src/main/java/com/alttd/playerutils/PlayerUtils.java index eb4574c..7ffbfe7 100644 --- a/src/main/java/com/alttd/playerutils/PlayerUtils.java +++ b/src/main/java/com/alttd/playerutils/PlayerUtils.java @@ -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); diff --git a/src/main/java/com/alttd/playerutils/config/Config.java b/src/main/java/com/alttd/playerutils/config/Config.java index b481454..a8f9e53 100644 --- a/src/main/java/com/alttd/playerutils/config/Config.java +++ b/src/main/java/com/alttd/playerutils/config/Config.java @@ -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 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 limits = configurationSection.getKeys(false); + for (String key : limits) { + LIMIT.put(key, config.getInt(prefix, key, 10)); + } + } + } } diff --git a/src/main/java/com/alttd/playerutils/event_listeners/LimitArmorStands.java b/src/main/java/com/alttd/playerutils/event_listeners/LimitArmorStands.java new file mode 100644 index 0000000..976a363 --- /dev/null +++ b/src/main/java/com/alttd/playerutils/event_listeners/LimitArmorStands.java @@ -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("You can not place more than armor stands in a chunk", + 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("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; + } + 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("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; + } + 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(); + } + +}