diff --git a/src/main/java/com/froobworld/nabsuite/modules/protect/command/LockCommand.java b/src/main/java/com/froobworld/nabsuite/modules/protect/command/LockCommand.java index 8d39d7b..a4796ba 100644 --- a/src/main/java/com/froobworld/nabsuite/modules/protect/command/LockCommand.java +++ b/src/main/java/com/froobworld/nabsuite/modules/protect/command/LockCommand.java @@ -70,18 +70,20 @@ public void execute(CommandContext context) { return; } Sign sign = (Sign) block.getState(); - if (sign.getLine(0).equalsIgnoreCase(LockManager.LOCK_HEADER) && line == 2 && !sender.hasPermission(LockManager.PERM_BYPASS_LOCKS)) { + if (SignUtils.getLine(sign, 0).equalsIgnoreCase(LockManager.LOCK_HEADER) && line == 2 && !sender.hasPermission(LockManager.PERM_BYPASS_LOCKS)) { sender.sendMessage(Component.text("You can't change the owner of the sign.", NamedTextColor.RED)); return; } - String string; - if (input instanceof PlayerIdentity) { - string = SignUtils.encodeName(((PlayerIdentity) input).getLastName(), ((PlayerIdentity) input).getUuid()); + if (input instanceof PlayerIdentity playerIdentity) { + lockManager.updateUser(sign, line - 1, playerIdentity.getLastName(), playerIdentity.getUuid()); } else { - string = input.toString(); + if (SignUtils.getLine(sign, 0).equalsIgnoreCase(LockManager.LOCK_HEADER) && line == 2) { + // Don't allow null uuid for owner + sender.sendMessage(Component.text("New owner must be a known player.", NamedTextColor.RED)); + return; + } + lockManager.updateUser(sign, line - 1, input.toString(), null); } - sign.setLine(line - 1, string); - sign.update(true); } @Override diff --git a/src/main/java/com/froobworld/nabsuite/modules/protect/lock/LockManager.java b/src/main/java/com/froobworld/nabsuite/modules/protect/lock/LockManager.java index 95b73e4..a0e138e 100644 --- a/src/main/java/com/froobworld/nabsuite/modules/protect/lock/LockManager.java +++ b/src/main/java/com/froobworld/nabsuite/modules/protect/lock/LockManager.java @@ -1,10 +1,14 @@ package com.froobworld.nabsuite.modules.protect.lock; import com.destroystokyo.paper.MaterialTags; +import com.froobworld.nabsuite.data.identity.PlayerIdentity; import com.froobworld.nabsuite.modules.basics.BasicsModule; import com.froobworld.nabsuite.modules.basics.player.PlayerDataManager; import com.froobworld.nabsuite.modules.protect.ProtectModule; -import net.md_5.bungee.api.ChatColor; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -15,6 +19,7 @@ import org.bukkit.block.data.type.Bed.Part; import org.bukkit.block.data.type.Chest.Type; import org.bukkit.block.data.type.Door.Hinge; +import org.bukkit.block.sign.Side; import org.bukkit.entity.Player; import org.bukkit.event.block.*; import org.bukkit.event.entity.EntityExplodeEvent; @@ -34,8 +39,10 @@ public class LockManager { public Map selectedSigns = new HashMap<>(); private final Map lockCache = new HashMap<>(); private final PlayerDataManager playerDataManager; + private final ProtectModule protectModule; public LockManager(ProtectModule protectModule) { + this.protectModule = protectModule; playerDataManager = protectModule.getPlugin().getModule(BasicsModule.class).getPlayerDataManager(); Bukkit.getPluginManager().registerEvents(new LockListener(this), protectModule.getPlugin()); } @@ -52,55 +59,78 @@ public UUID getOwner(Location location, boolean useCache) { } } - for (Sign sign : getAllRelevantSigns(location.getBlock())) { - if (sign.getLine(0).equalsIgnoreCase(LOCK_HEADER)) { - return SignUtils.decodeUUID(sign.getLine(1)); + ArrayList relevantSigns = getAllRelevantSigns(location.getBlock()); + for (Sign sign : relevantSigns) { + if (SignUtils.getLine(sign, 0).equalsIgnoreCase(LOCK_HEADER)) { + UUID owner = SignUtils.decodePlayer(sign.getSide(Side.FRONT).line(1)); + if (owner == null) { + // Sign might have been rolled back, try to populate uuids from names again for all signs + for (Sign sign2 : relevantSigns) { + if (isLockSign(sign2)) { + restoreSignUuids(sign2); + } + } + owner = SignUtils.decodePlayer(sign.getSide(Side.FRONT).line(1)); + } + return owner; } } return null; } - public boolean isUser(Location location, Player player) { - ArrayList relevantSigns = getAllRelevantSigns(location.getBlock()); - for (Sign sign : relevantSigns) { - if (sign.getLine(0).equalsIgnoreCase(LOCK_HEADER) || sign.getLine(0).equalsIgnoreCase(MORE_HEADER)) { - for (int i = 1; i <= 3; i++) { - if (sign.getLine(i).contains("�")) { - sign.setLine(i, sign.getLine(i).replaceAll("�", "§")); - sign.update(true); - } - } + private void restoreSignUuids(Sign sign) { + boolean save = false; + for (int i = 1; i <= 3; i++) { + TextComponent row = (TextComponent)sign.getSide(Side.FRONT).line(i); + if (row.content().equalsIgnoreCase(FRIENDS) || row.content().equalsIgnoreCase(EVERYONE)) { + continue; } + HoverEvent hoverEvent = row.hoverEvent(); + if (hoverEvent != null && hoverEvent.value() instanceof HoverEvent.ShowEntity) { + continue; + } + Set players = protectModule.getPlugin().getPlayerIdentityManager().getPlayerIdentity(row.content()); + if (players.size() == 1) { + PlayerIdentity player = players.stream().findFirst().get(); + sign.getSide(Side.FRONT).line(i, SignUtils.encodePlayer(player)); + save = true; + } + } + if (save) { + sign.update(true); } + } + public boolean isUser(Location location, Player player) { + ArrayList relevantSigns = getAllRelevantSigns(location.getBlock()); UUID owner = getOwner(location, false); if (owner == null) { return true; } for (Sign sign : relevantSigns) { - if (sign.getLine(0).equalsIgnoreCase(LOCK_HEADER) || sign.getLine(0).equalsIgnoreCase(MORE_HEADER)) { + if (isLockSign(sign)) { for (int i = 1; i <= 3; i++) { - if (sign.getLine(i).equalsIgnoreCase(EVERYONE)) { + if (SignUtils.getLine(sign, i).equalsIgnoreCase(EVERYONE)) { return true; } - if (sign.getLine(i).equalsIgnoreCase(FRIENDS)) { + if (SignUtils.getLine(sign, i).equalsIgnoreCase(FRIENDS)) { if (playerDataManager.getFriendManager().areFriends(player, owner)) { return true; } } - String name = SignUtils.decodeName(sign.getLine(i)); - UUID uuid = SignUtils.decodeUUID(sign.getLine(i)); + String name = SignUtils.getLine(sign, i); + UUID uuid = SignUtils.decodePlayer(sign.getSide(Side.FRONT).line(i)); if (player.getUniqueId().equals(uuid)) { if (!Objects.equals(name, player.getName())) { - sign.setLine(i, SignUtils.encodeName(player.getName(), player.getUniqueId())); - sign.update(); + sign.getSide(Side.FRONT).line(i, SignUtils.encodePlayer(player)); + sign.update(true); } return true; } if (uuid == null && name.equalsIgnoreCase(player.getName())) { - sign.setLine(i, SignUtils.encodeName(player.getName(), player.getUniqueId())); - sign.update(); + sign.getSide(Side.FRONT).line(i, SignUtils.encodePlayer(player)); + sign.update(true); return true; } } @@ -239,7 +269,16 @@ public boolean isLockable(Material material) { } public boolean isLockSign(Sign sign) { - return sign.getLine(0).equalsIgnoreCase(LOCK_HEADER) || sign.getLine(0).equalsIgnoreCase(MORE_HEADER); + return SignUtils.getLine(sign, 0).equalsIgnoreCase(LOCK_HEADER) || SignUtils.getLine(sign, 0).equalsIgnoreCase(MORE_HEADER); + } + + public boolean isLockSign(SignChangeEvent sign) { + return SignUtils.getLine(sign, 0).equalsIgnoreCase(LOCK_HEADER) || SignUtils.getLine(sign, 0).equalsIgnoreCase(MORE_HEADER); + } + + public void updateUser(Sign sign, int index, String name, UUID uuid) { + sign.getSide(Side.FRONT).line(index, SignUtils.encodePlayer(name, uuid)); + sign.update(); } public void onBlockBreak(BlockBreakEvent event) { @@ -258,7 +297,7 @@ public void onBlockBreak(BlockBreakEvent event) { if (getAttachedLockables(connected).isEmpty()) { return; } - if (sign.getLine(0).equalsIgnoreCase(LOCK_HEADER) || sign.getLine(0).equalsIgnoreCase(MORE_HEADER)) { + if (isLockSign(sign)) { UUID owner = getOwner(connected.getLocation(), false); if (!event.getPlayer().hasPermission(PERM_BYPASS_LOCKS) && !event.getPlayer().getUniqueId().equals(owner)) { event.setCancelled(true); @@ -273,7 +312,7 @@ public void onPlayerInteract(PlayerInteractEvent event) { if (isLockSign(sign)) { if (!selectedSigns.containsKey(event.getPlayer()) || selectedSigns.get(event.getPlayer()) != event.getClickedBlock().getLocation()) { selectedSigns.put(event.getPlayer(), event.getClickedBlock().getLocation()); - event.getPlayer().sendMessage(ChatColor.YELLOW + "Sign selected. Use /lock to edit it."); + event.getPlayer().sendMessage(Component.text("Sign selected. Use /lock to edit it.").color(NamedTextColor.YELLOW)); } } @@ -291,7 +330,7 @@ public void onBlockExplode(BlockExplodeEvent event) { for (Block b : event.blockList()) { if (b.getBlockData() instanceof WallSign) { Sign sign = (Sign) b.getState(); - if (sign.getLine(0).equalsIgnoreCase(LOCK_HEADER) || sign.getLine(0).equalsIgnoreCase(MORE_HEADER)) { + if (isLockSign(sign)) { toRemove.add(b); } continue; @@ -311,7 +350,7 @@ public void onEntityExplode(EntityExplodeEvent event) { for (Block b : event.blockList()) { if (b.getBlockData() instanceof WallSign) { Sign sign = (Sign) b.getState(); - if (sign.getLine(0).equalsIgnoreCase(LOCK_HEADER) || sign.getLine(0).equalsIgnoreCase(MORE_HEADER)) { + if (isLockSign(sign)) { toRemove.add(b); } continue; @@ -339,32 +378,32 @@ public void onSignChange(SignChangeEvent event) { if (!(event.getBlock().getBlockData() instanceof WallSign)) { return; } - if (!event.getLine(0).equalsIgnoreCase(LOCK_HEADER) && !event.getLine(0).equalsIgnoreCase(MORE_HEADER) && !(event.getLine(0).isEmpty() && event.getLine(1).isEmpty() && event.getLine(2).isEmpty() && event.getLine(3).isEmpty())) { + if (!isLockSign(event) && !(SignUtils.getLine(event, 0).isEmpty() && SignUtils.getLine(event, 1).isEmpty() && SignUtils.getLine(event, 2).isEmpty() && SignUtils.getLine(event, 3).isEmpty())) { return; } WallSign wallSign = (WallSign) event.getBlock().getBlockData(); Block connected = event.getBlock().getRelative(wallSign.getFacing().getOppositeFace()); if (getAttachedLockables(connected).isEmpty()) { - if (event.getLine(0).equalsIgnoreCase(LOCK_HEADER) || event.getLine(0).equalsIgnoreCase(MORE_HEADER)) { - event.setLine(0, ERROR_HEADER); - event.getPlayer().sendMessage(ChatColor.RED + "This cannot be locked."); + if (isLockSign(event)) { + event.line(0, Component.text(ERROR_HEADER)); + event.getPlayer().sendMessage(Component.text("This cannot be locked.").color(NamedTextColor.RED)); } return; } UUID owner = getOwner(connected.getLocation(), false); if (owner != null && !owner.equals(event.getPlayer().getUniqueId())) { - event.setLine(0, ERROR_HEADER); - event.getPlayer().sendMessage(ChatColor.RED + "This is already locked."); + event.line(0, Component.text(ERROR_HEADER)); + event.getPlayer().sendMessage(Component.text("This is already locked.").color(NamedTextColor.RED)); return; } if (owner == null) { - event.setLine(0, LOCK_HEADER); - event.setLine(1, SignUtils.encodeName(event.getPlayer().getName(), event.getPlayer().getUniqueId())); + event.line(0, Component.text(LOCK_HEADER)); + event.line(1, SignUtils.encodePlayer(event.getPlayer().getName(), event.getPlayer().getUniqueId())); } else { - event.setLine(0, MORE_HEADER); - event.setLine(1, FRIENDS); + event.line(0, Component.text(MORE_HEADER)); + event.line(1, Component.text(FRIENDS)); } } diff --git a/src/main/java/com/froobworld/nabsuite/modules/protect/lock/SignUtils.java b/src/main/java/com/froobworld/nabsuite/modules/protect/lock/SignUtils.java index a298c2e..6ce6af5 100644 --- a/src/main/java/com/froobworld/nabsuite/modules/protect/lock/SignUtils.java +++ b/src/main/java/com/froobworld/nabsuite/modules/protect/lock/SignUtils.java @@ -1,8 +1,17 @@ package com.froobworld.nabsuite.modules.protect.lock; +import com.froobworld.nabsuite.data.identity.PlayerIdentity; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.HoverEvent; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.block.Sign; import org.bukkit.block.data.type.WallSign; +import org.bukkit.block.sign.Side; +import org.bukkit.entity.Player; +import org.bukkit.event.block.SignChangeEvent; import java.util.UUID; @@ -21,6 +30,30 @@ public static Block[] getAdjacentBlocks(Block block) { return faces; } + public static TextComponent encodePlayer(String name, UUID uuid) { + TextComponent data = Component.text(name); + if (uuid != null) { + data = data.hoverEvent(HoverEvent.showEntity(Key.key("player"), uuid, Component.text(name))); + } + return data; + } + + public static TextComponent encodePlayer(Player player) { + return encodePlayer(player.getName(), player.getUniqueId()); + } + + public static TextComponent encodePlayer(PlayerIdentity player) { + return encodePlayer(player.getLastName(), player.getUuid()); + } + + public static UUID decodePlayer(Component row) { + HoverEvent hoverEvent = row.hoverEvent(); + if (hoverEvent != null && hoverEvent.value() instanceof HoverEvent.ShowEntity showEntity) { + return showEntity.id(); + } + return null; + } + public static Block getAttachedBlock(Block sb) { if (sb.getBlockData() instanceof WallSign) { return sb.getRelative(((WallSign) sb.getBlockData()).getFacing().getOppositeFace()); @@ -46,121 +79,20 @@ public static Block getLR(Block block, BlockFace facing, boolean left) { return null; } - public static String encodeUUID(UUID uuid) { - String str = uuid.toString(); - String concat = ""; - for (char c : str.toCharArray()) { - concat += "§" + getEncoding(c); - } - - return concat; - } - - public static UUID decodeUUID(String line) { - String[] split = line.split("§="); - - if (split.length < 2) { - return null; + public static String getLine(Sign sign, int index) { + Component line = sign.getSide(Side.FRONT).line(index); + if (line instanceof TextComponent textLine) { + return textLine.content(); } - String decoded = ""; - for (String s : split[1].replaceFirst("§", "").split("§")) { - decoded += getDecoded(s); - } - - return UUID.fromString(decoded); + return ""; } - public static String decodeName(String line) { - String[] split = line.split("§="); - - return split[0]; - } - - public static String encodeName(String name, UUID uuid) { - - return name + "§=" + encodeUUID(uuid); - } - - private static char getEncoding(char c) { - switch (c) { - case '0': - return ')'; - case '1': - return '!'; - case '2': - return '@'; - case '3': - return '#'; - case '4': - return '$'; - case '5': - return '%'; - case '6': - return '^'; - case '7': - return '&'; - case '8': - return '*'; - case '9': - return '('; - case 'a': - return '_'; - case 'b': - return '+'; - case 'c': - return '['; - case 'd': - return ']'; - case 'e': - return '{'; - case 'f': - return '}'; - case '-': - return '-'; + public static String getLine(SignChangeEvent event, int index) { + Component line = event.line(index); + if (line instanceof TextComponent textLine) { + return textLine.content(); } - - return c; - } - - private static char getDecoded(String s) { - switch (s) { - case ")": - return '0'; - case "!": - return '1'; - case "@": - return '2'; - case "#": - return '3'; - case "$": - return '4'; - case "%": - return '5'; - case "^": - return '6'; - case "&": - return '7'; - case "*": - return '8'; - case "(": - return '9'; - case "_": - return 'a'; - case "+": - return 'b'; - case "[": - return 'c'; - case "]": - return 'd'; - case "{": - return 'e'; - case "}": - return 'f'; - case "-": - return '-'; - } - - return 'x'; + return ""; } }