diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/BlazeSMP.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/BlazeSMP.java index 0390fac..100cfec 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/BlazeSMP.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/BlazeSMP.java @@ -13,6 +13,7 @@ import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitTask; +import org.bukkit.scoreboard.Team; import org.slf4j.Logger; public final class BlazeSMP extends JavaPlugin { @@ -82,7 +83,7 @@ public final class BlazeSMP extends JavaPlugin { pm.registerEvents(new ChunkInventoryListener(), this); pm.registerEvents(new PressurePlateListener(), this); pm.registerEvents(new PlayerVsPlayerListener(clans), this); - pm.registerEvents(new ProtectedBlockListener(), this); + //pm.registerEvents(new ProtectedBlockListener(), this); this.log.info("Registered EventListeners!"); this.log.info("Starting Timer tasks..."); @@ -113,6 +114,10 @@ public final class BlazeSMP extends JavaPlugin { this.clans.saveAllClans(); this.log.info("Saved Clans!"); + this.log.info("Clearing Teams..."); + getServer().getScoreboardManager().getMainScoreboard().getTeams().forEach(Team::unregister); + this.log.info("Cleared Teams!"); + this.log.info("Disabling BlazeSMP!"); } } diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClaimCommand.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClaimCommand.java index c3b4eab..0b356cf 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClaimCommand.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ClaimCommand.java @@ -56,7 +56,7 @@ public class ClaimCommand extends SimpleCommand { player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("error.chunk_already_claimed"))); } else { // claim too close to spawn 8 chunks - if (playerChunk.getX() < 8 && playerChunk.getZ() < 8) { + if (player.getX() < 152 && player.getZ() < 152) { player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("error.chunk_too_close_to_spawn"))); return true; } diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/command/DiscordCommand.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/DiscordCommand.java index 2550aa1..a4e9742 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/command/DiscordCommand.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/DiscordCommand.java @@ -23,8 +23,7 @@ public class DiscordCommand extends SimpleCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { - if (sender instanceof Player) { - Player player = (Player) sender; + if (sender instanceof Player player) { Component message = MiniMessage.miniMessage().deserialize("Click here to join our Discord!"); player.sendMessage(message); } else { diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ReloadCommand.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ReloadCommand.java new file mode 100644 index 0000000..578a5b4 --- /dev/null +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/command/ReloadCommand.java @@ -0,0 +1,39 @@ +package me.freezy.plugins.papermc.blazesmp.command; + +import me.freezy.plugins.papermc.blazesmp.BlazeSMP; +import me.freezy.plugins.papermc.blazesmp.command.util.SimpleCommand; +import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4; +import net.kyori.adventure.text.minimessage.MiniMessage; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class ReloadCommand extends SimpleCommand { + public ReloadCommand() { + super("reloadconf"); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("error.not_a_player"))); + return true; + } + BlazeSMP.getInstance().getClans().saveAllClans(); + BlazeSMP.getInstance().saveConfig(); + BlazeSMP.getInstance().reloadConfig(); + BlazeSMP.getInstance().getProtectedBlocks().save(); + BlazeSMP.getInstance().getHomes().save(); + player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("config.reloaded"))); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + return List.of(); + } +} diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/ChunkInventoryListener.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/ChunkInventoryListener.java index 673cdda..dfb84fb 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/ChunkInventoryListener.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/ChunkInventoryListener.java @@ -2,6 +2,7 @@ package me.freezy.plugins.papermc.blazesmp.listener; import me.freezy.plugins.papermc.blazesmp.BlazeSMP; import me.freezy.plugins.papermc.blazesmp.module.Clan; +import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; @@ -89,6 +90,7 @@ public class ChunkInventoryListener implements Listener { Component itemName = MiniMessage.miniMessage().deserialize("Chunk [" + chunk.getX() + ", " + chunk.getZ() + "]"); skullMeta.displayName(itemName); List lore = new ArrayList<>(); + lore.add(MiniMessage.miniMessage().deserialize(L4M4.get("chunk.unclaim_lore"))); lore.add(MiniMessage.miniMessage().deserialize("World: " + chunk.getWorld().getName() + "")); lore.add(MiniMessage.miniMessage().deserialize("Owner: " + ownerPlayer.getName() + "")); lore.add(MiniMessage.miniMessage().deserialize("Index: " + (i + 1) + "")); @@ -128,7 +130,7 @@ public class ChunkInventoryListener implements Listener { if (!(event.getWhoClicked() instanceof Player player)) return; Component invTitle = event.getView().title(); Component expectedTitle = MiniMessage.miniMessage().deserialize( - me.freezy.plugins.papermc.blazesmp.module.manager.L4M4.get("chunk.title") + L4M4.get("chunk.title") ); if (!PlainTextComponentSerializer.plainText().serialize(invTitle) .equals(PlainTextComponentSerializer.plainText().serialize(expectedTitle))) { @@ -164,11 +166,18 @@ public class ChunkInventoryListener implements Listener { } } else { // Nutze den zentralen Nachrichtentext für Klicks - String msg = String.format( - me.freezy.plugins.papermc.blazesmp.module.manager.L4M4.get("chunk.clicked"), - displayName - ); - player.sendMessage(MiniMessage.miniMessage().deserialize(msg)); + String[] parts = displayName.substring(1, displayName.length() - 1).split(","); + int x = Integer.parseInt(parts[0].trim()); + int y = Integer.parseInt(parts[1].trim()); + Chunk chunk = Objects.requireNonNull(Bukkit.getWorld("world")).getChunkAt(x, y); + if (clan.getChunkOwnerMap().containsKey(chunk)) { + clan.getChunkOwnerMap().remove(chunk); + clan.save(); + player.sendMessage(MiniMessage.miniMessage().deserialize( + L4M4.get("chunk.unclaimed") + )); + openChunksMenu(player, chunkEntries, currentPage, totalPages, itemsPerPage, clan); + } } } diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/PlayerChatListener.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/PlayerChatListener.java index 07e5993..fe48ca5 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/PlayerChatListener.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/PlayerChatListener.java @@ -2,6 +2,7 @@ package me.freezy.plugins.papermc.blazesmp.listener; import io.papermc.paper.event.player.AsyncChatEvent; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -11,25 +12,16 @@ public class PlayerChatListener implements Listener { @EventHandler public void onChat(AsyncChatEvent event) { Player player = event.getPlayer(); - Team team = player.getScoreboard().getEntryTeam(player.getName()); - - Component prefix = Component.empty(); - Component suffix = Component.empty(); - - if (team != null) { - prefix = team.prefix(); - suffix = team.suffix(); - } Component messageComponent = event.message(); Component chatComponent = Component.empty() - //.append(prefix) - .append(player.teamDisplayName()) - //.append(suffix) + .append(player.playerListName()) .append(Component.text(": ")) .append(messageComponent); + player.sendMessage(player.playerListName()); + event.renderer((source, sourceDisplayName, msg, viewer) -> chatComponent); } } diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/PlayerJoinListener.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/PlayerJoinListener.java index 40fd323..4e7b705 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/PlayerJoinListener.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/PlayerJoinListener.java @@ -2,20 +2,25 @@ package me.freezy.plugins.papermc.blazesmp.listener; import me.freezy.plugins.papermc.blazesmp.manager.PlayerManager; import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.minimessage.MiniMessage; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.scoreboard.Team; public class PlayerJoinListener implements Listener { @EventHandler public void onJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); new PlayerManager().setPlayerTeam(player); + Team team = player.getScoreboard().getEntryTeam(player.getName()); // Verwende den zentral konfigurierten Join-Text aus der JSON-Datei + assert team != null; event.joinMessage(MiniMessage.miniMessage().deserialize(L4M4.get("player.join")) - .append(player.teamDisplayName())); + .append(player.playerListName())); } } diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/ProtectedBlockListener.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/ProtectedBlockListener.java index a400da4..42323c5 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/ProtectedBlockListener.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/listener/ProtectedBlockListener.java @@ -6,8 +6,11 @@ import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4; import me.freezy.plugins.papermc.blazesmp.module.manager.ProtectedBlocks; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; -import org.bukkit.*; -import org.bukkit.block.*; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.Container; import org.bukkit.entity.HumanEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -30,49 +33,61 @@ public class ProtectedBlockListener implements Listener { private final ProtectedBlocks protectedBlocks = BlazeSMP.getInstance().getProtectedBlocks(); // Supported storage block types - private final Set STORAGE_BLOCKS = Set.of( + private static final Set STORAGE_BLOCKS = Set.of( Material.CHEST, Material.TRAPPED_CHEST, Material.BARREL, Material.HOPPER, Material.DROPPER, Material.DISPENSER, Material.FURNACE, Material.BLAST_FURNACE, Material.SMOKER ); + /* + * Prevents items from being transferred into protected storages. + */ @EventHandler public void onItemTransferHopperEvent(InventoryMoveItemEvent event) { - Block destinationBlock = Objects.requireNonNull(event.getDestination().getLocation()).getBlock(); + Location destLocation = event.getDestination().getLocation(); + if (destLocation == null) return; + Block destinationBlock = destLocation.getBlock(); if (isProtected(destinationBlock)) { event.setCancelled(true); } } + /* + * Handles player interactions with storage blocks. + * Supports locking, unlocking, linking keys, and opening GUIs. + */ @EventHandler public void onBlockInteractEvent(PlayerInteractEvent event) { Player player = event.getPlayer(); Block block = event.getClickedBlock(); - if (block == null || !STORAGE_BLOCKS.contains(block.getType())) return; + + if (block == null || !STORAGE_BLOCKS.contains(block.getType())) { + return; + } ItemStack mainHandItem = player.getInventory().getItemInMainHand(); ProtectedBlock protectedBlock = getProtectedBlock(block); - // Owner (if the block is locked) can always access the management GUI. + // Owner can manage keys with shift-right-click if the block is already locked. if (player.isSneaking() && protectedBlock != null && protectedBlock.owner().equals(player.getUniqueId())) { openManageKeysGUI(player, block); return; } - // Shift + Right-click with a trial key: Relink the key to the new container. + // Shift + Right-click with a valid trial key relinks the key to the new container. if (player.isSneaking() && isValidKey(mainHandItem)) { relinkKey(player, mainHandItem, block); return; } - // Shift + Right-click without a key (and if the container is not locked) → open lock GUI. + // Shift + Right-click on an unlocked container opens the lock GUI. if (player.isSneaking() && protectedBlock == null) { openLockGUI(player, block); return; } - // Normal right-click with a valid key: open the container inventory. + // Normal right-click: if a valid key is held for a locked container, open the inventory. if (protectedBlock != null && isValidKey(mainHandItem, protectedBlock.key())) { if (block.getState() instanceof Container container) { player.openInventory(container.getInventory()); @@ -80,19 +95,24 @@ public class ProtectedBlockListener implements Listener { return; } - // Normal right-click without a key on a locked container: show locked message. + // Normal right-click on a locked container without a valid key shows a locked message. if (protectedBlock != null) { String lockedMsg = String.format(L4M4.get("storage.locked"), "minecraft:trial_key"); player.sendMessage(miniMessage.deserialize(lockedMsg)); } } + /* + * Opens the lock GUI for a container. + * Two trial keys are created and the container is then registered as protected. + */ private void openLockGUI(Player player, Block block) { String titleRaw = String.format(L4M4.get("storage.lock_gui_title"), block.getType().toString()); Inventory lockInventory = Bukkit.createInventory(player, InventoryType.HOPPER, miniMessage.deserialize(titleRaw)); UUID lockUUID = UUID.randomUUID(); + // Create two identical trial keys for symmetry ItemStack trialKey1 = createTrialKey(lockUUID); ItemStack trialKey2 = createTrialKey(lockUUID); @@ -100,24 +120,33 @@ public class ProtectedBlockListener implements Listener { lockInventory.setItem(4, trialKey2); player.openInventory(lockInventory); - // Save the protected block. + // Save the protected block information protectedBlocks.addBlock(new ProtectedBlock(player.getUniqueId(), lockUUID, block.getLocation())); } + /* + * Opens the manage keys GUI for the owner to add or remove keys. + */ private void openManageKeysGUI(Player player, Block block) { String titleRaw = String.format(L4M4.get("storage.manage_gui_title"), block.getType().toString()); Inventory manageKeysInventory = Bukkit.createInventory(player, InventoryType.HOPPER, miniMessage.deserialize(titleRaw)); + // Create "Add Key" button ItemStack addKey = new ItemStack(Material.PAPER); ItemMeta addKeyMeta = addKey.getItemMeta(); - addKeyMeta.displayName(miniMessage.deserialize(L4M4.get("storage.add_key"))); - addKey.setItemMeta(addKeyMeta); + if (addKeyMeta != null) { + addKeyMeta.displayName(miniMessage.deserialize(L4M4.get("storage.add_key"))); + addKey.setItemMeta(addKeyMeta); + } + // Create "Remove Key" button ItemStack removeKey = new ItemStack(Material.BARRIER); ItemMeta removeKeyMeta = removeKey.getItemMeta(); - removeKeyMeta.displayName(miniMessage.deserialize(L4M4.get("storage.remove_key"))); - removeKey.setItemMeta(removeKeyMeta); + if (removeKeyMeta != null) { + removeKeyMeta.displayName(miniMessage.deserialize(L4M4.get("storage.remove_key"))); + removeKey.setItemMeta(removeKeyMeta); + } manageKeysInventory.setItem(1, addKey); manageKeysInventory.setItem(3, removeKey); @@ -125,20 +154,29 @@ public class ProtectedBlockListener implements Listener { player.openInventory(manageKeysInventory); } + /* + * Relinks the provided trial key to the new block. + * A new lock UUID is generated and the key’s lore is updated. + */ private void relinkKey(Player player, ItemStack key, Block newBlock) { UUID newLockUUID = UUID.randomUUID(); ItemMeta meta = key.getItemMeta(); if (meta != null) { - meta.lore(List.of( + List newLore = List.of( miniMessage.deserialize(String.format(L4M4.get("storage.linked_to"), newLockUUID.toString())), miniMessage.deserialize(L4M4.get("storage.not_usable_on_vaults")) - )); + ); + meta.lore(newLore); key.setItemMeta(meta); } protectedBlocks.addBlock(new ProtectedBlock(player.getUniqueId(), newLockUUID, newBlock.getLocation())); player.sendMessage(miniMessage.deserialize(L4M4.get("storage.link_success"))); } + /* + * Prevents any changes in the lock or manage keys GUIs. + * Also informs the player that the action was completed. + */ @EventHandler public void onInventoryClick(InventoryClickEvent event) { String title = event.getView().title().toString(); @@ -153,6 +191,10 @@ public class ProtectedBlockListener implements Listener { } } + /* + * Handles block breaking. + * If the block is protected, only the owner can break it. + */ @EventHandler public void onBlockBreak(BlockBreakEvent event) { Player player = event.getPlayer(); @@ -170,11 +212,17 @@ public class ProtectedBlockListener implements Listener { } } + /* + * Prevents explosions from destroying protected storage blocks. + */ @EventHandler public void onExplosion(EntityExplodeEvent event) { event.blockList().removeIf(this::isProtected); } + /* + * Helper method to create a trial key with linked lock information. + */ private ItemStack createTrialKey(UUID lockUUID) { ItemStack trialKey = new ItemStack(Material.TRIPWIRE_HOOK); ItemMeta meta = trialKey.getItemMeta(); @@ -189,10 +237,16 @@ public class ProtectedBlockListener implements Listener { return trialKey; } + /* + * Validates if the provided item is a trial key. + */ private boolean isValidKey(ItemStack item) { return item != null && item.getType() == Material.TRIPWIRE_HOOK && item.hasItemMeta(); } + /* + * Validates if the provided item is a trial key that is linked to the given lock UUID. + */ private boolean isValidKey(ItemStack item, UUID lockUUID) { if (!isValidKey(item)) return false; ItemMeta meta = item.getItemMeta(); @@ -200,6 +254,9 @@ public class ProtectedBlockListener implements Listener { return Objects.requireNonNull(meta.lore()).stream().anyMatch(line -> line.contains(Component.text(lockUUID.toString()))); } + /* + * Returns the ProtectedBlock associated with the given block, or null if not found. + */ private ProtectedBlock getProtectedBlock(Block block) { return protectedBlocks.getBlocks().stream() .filter(pb -> pb.location().equals(block.getLocation())) @@ -207,6 +264,9 @@ public class ProtectedBlockListener implements Listener { .orElse(null); } + /* + * Checks if a block is protected. + */ private boolean isProtected(Block block) { return getProtectedBlock(block) != null; } diff --git a/src/main/java/me/freezy/plugins/papermc/blazesmp/manager/PlayerManager.java b/src/main/java/me/freezy/plugins/papermc/blazesmp/manager/PlayerManager.java index 74a35f3..ac3671d 100644 --- a/src/main/java/me/freezy/plugins/papermc/blazesmp/manager/PlayerManager.java +++ b/src/main/java/me/freezy/plugins/papermc/blazesmp/manager/PlayerManager.java @@ -30,8 +30,9 @@ public class PlayerManager { public void setPlayerTeam(Player player) { Clans clans = BlazeSMP.getInstance().getClans(); UUID playerUUID = player.getUniqueId(); - player.setScoreboard(player.getServer().getScoreboardManager().getMainScoreboard()); Scoreboard scoreboard = player.getScoreboard(); + if (!scoreboard.equals(player.getServer().getScoreboardManager().getMainScoreboard())) + player.setScoreboard(player.getServer().getScoreboardManager().getMainScoreboard()); String teamName; if (clans.isInClan(playerUUID)) { teamName=clanChars.get(clans.getClanByMember(playerUUID)); @@ -46,8 +47,7 @@ public class PlayerManager { teamName="zzzm"; } teamName+=generateRandomString(); - scoreboard.getTeams().forEach(Team::unregister); - Team team = scoreboard.getTeam(teamName); + Team team = scoreboard.getPlayerTeam(player); if (team == null) { team = scoreboard.registerNewTeam(teamName); } diff --git a/src/main/resources/storage/messages.json b/src/main/resources/storage/messages.json index aface9e..9763b10 100644 --- a/src/main/resources/storage/messages.json +++ b/src/main/resources/storage/messages.json @@ -105,6 +105,7 @@ "chunk.navigation.previous": "Previous Page", "chunk.navigation.next": "Next Page", "chunk.clicked": "You clicked on Chunk item: %s.", + "chunk.unclaim_lore": "Click to unclaim!", "claim.entered": "You entered the claim of %s!", "claim.territory": "Territory of %s - %s!", @@ -124,7 +125,7 @@ ], "tablist.footer": [ "hosted by merged.games", - "made by BlazeHC Team & Freezy/DaTTV" + "made by BlazeHC Team & Freezy/DaTTV" ], "storage.locked": "This storage is locked! You need a %s to open it.", @@ -140,5 +141,7 @@ "storage.action_completed": "Action completed successfully!", "storage.removed_lock": "You removed the lock from this storage.", "storage.break_denied": "You cannot break this locked storage!", - "storage.trial_key": "Linked Trial Key" + "storage.trial_key": "Linked Trial Key", + + "config.reloaded": "Config reloaded!" }