diff --git a/API/src/main/java/fr/maxlego08/essentials/api/messages/Message.java b/API/src/main/java/fr/maxlego08/essentials/api/messages/Message.java index c3d9bfae..aea41c21 100644 --- a/API/src/main/java/fr/maxlego08/essentials/api/messages/Message.java +++ b/API/src/main/java/fr/maxlego08/essentials/api/messages/Message.java @@ -140,6 +140,9 @@ public enum Message { COMMAND_TELEPORT_WORLD("You need to be in the same world to teleport."), COMMAND_TPA_ERROR_TO_LATE("You do not have a teleport request."), COMMAND_TPA_ERROR_TO_LATE_2("The request has expired."), + COMMAND_TPA_ERROR_NO_REQUEST_FROM_PLAYER("You do not have a teleport request from &f%player%."), + COMMAND_TPA_ACCEPT_ALL_SUCCESS("You have accepted &f%count% teleport request(s)."), + COMMAND_TPA_DENY_ALL_SUCCESS("You have denied &f%count% teleport request(s)."), COMMAND_TP_DENY_SENDER("Denied %player% teleport request."), COMMAND_TP_DENY_RECEIVER("%player% has denied your teleport request"), COMMAND_TP_CANCEL_ERROR("You did not send a teleport request at &f%player%."), diff --git a/API/src/main/java/fr/maxlego08/essentials/api/user/User.java b/API/src/main/java/fr/maxlego08/essentials/api/user/User.java index 9f9048de..db882db4 100644 --- a/API/src/main/java/fr/maxlego08/essentials/api/user/User.java +++ b/API/src/main/java/fr/maxlego08/essentials/api/user/User.java @@ -135,6 +135,35 @@ public interface User { */ void removeTeleportRequest(User user); + /** + * Gets teleport request from specific player. + * + * @param fromUser The player who sent the request + * @return The request from specified player, or null if none exists + */ + TeleportRequest getTeleportRequestFrom(User fromUser); + + /** + * Gets all incoming teleport requests. + * + * @return Collection of all valid incoming requests + */ + Collection getIncomingTeleportRequests(); + + /** + * Adds or updates incoming teleport request. + * + * @param teleportRequest The request to add/update + */ + void setIncomingTeleportRequest(TeleportRequest teleportRequest); + + /** + * Removes incoming request from specific player. + * + * @param fromUser The player whose request should be removed + */ + void removeIncomingTeleportRequest(User fromUser); + /** * Teleports the user to the specified location immediately. * diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/CommandTeleportAccept.java b/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/CommandTeleportAccept.java index cf20be37..9e365185 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/CommandTeleportAccept.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/CommandTeleportAccept.java @@ -5,8 +5,14 @@ import fr.maxlego08.essentials.api.commands.Permission; import fr.maxlego08.essentials.api.messages.Message; import fr.maxlego08.essentials.api.user.TeleportRequest; +import fr.maxlego08.essentials.api.user.User; import fr.maxlego08.essentials.module.modules.TeleportationModule; import fr.maxlego08.essentials.zutils.utils.commands.VCommand; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collection; public class CommandTeleportAccept extends VCommand { @@ -15,26 +21,90 @@ public CommandTeleportAccept(EssentialsPlugin plugin) { this.setModule(TeleportationModule.class); this.setPermission(Permission.ESSENTIALS_TPA_ACCEPT); this.setDescription(Message.DESCRIPTION_TPA_ACCEPT); + this.addOptionalArg("player"); this.onlyPlayers(); } @Override protected CommandResultType perform(EssentialsPlugin plugin) { - TeleportRequest teleportRequest = this.user.getTeleportRequest(); - if (teleportRequest == null) { - message(sender, Message.COMMAND_TPA_ERROR_TO_LATE); - return CommandResultType.DEFAULT; - } + String arg = this.argAsString(0, null); - if (!teleportRequest.isValid()) { - this.user.setTeleportRequest(null); - message(sender, Message.COMMAND_TPA_ERROR_TO_LATE_2); - return CommandResultType.DEFAULT; - } + if (arg == null) { + // accept latest request + TeleportRequest teleportRequest = this.user.getTeleportRequest(); + if (teleportRequest == null) { + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE); + return CommandResultType.DEFAULT; + } + + if (!teleportRequest.isValid()) { + this.user.removeIncomingTeleportRequest(teleportRequest.getFromUser()); + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE_2); + return CommandResultType.DEFAULT; + } + + teleportRequest.accept(); + this.user.removeIncomingTeleportRequest(teleportRequest.getFromUser()); + + } else if (arg.equals("*")) { + // accept all pending requests + Collection requests = this.user.getIncomingTeleportRequests(); + if (requests.isEmpty()) { + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE); + return CommandResultType.DEFAULT; + } + + int count = 0; + for (TeleportRequest request : new ArrayList<>(requests)) { + if (request.isValid()) { + request.accept(); + this.user.removeIncomingTeleportRequest(request.getFromUser()); + count++; + } + } - teleportRequest.accept(); - this.user.setTeleportRequest(null); + if (count > 0) { + message(sender, Message.COMMAND_TPA_ACCEPT_ALL_SUCCESS, "%count%", count); + } else { + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE); + return CommandResultType.DEFAULT; + } + + } else { + // accept request from that player + Player targetPlayer = this.argAsPlayer(0); + User targetUser = null; + + if (targetPlayer != null) { + targetUser = plugin.getStorageManager().getStorage().getUser(targetPlayer.getUniqueId()); + } else { + OfflinePlayer offlinePlayer = this.argAsOfflinePlayer(0); + if (offlinePlayer != null && offlinePlayer.hasPlayedBefore()) { + targetUser = plugin.getStorageManager().getStorage().getUser(offlinePlayer.getUniqueId()); + } + } + + if (targetUser == null) { + message(sender, Message.PLAYER_NOT_FOUND, "%player%", arg); + return CommandResultType.DEFAULT; + } + + TeleportRequest teleportRequest = this.user.getTeleportRequestFrom(targetUser); + if (teleportRequest == null) { + message(sender, Message.COMMAND_TPA_ERROR_NO_REQUEST_FROM_PLAYER, "%player%", targetUser.getName()); + return CommandResultType.DEFAULT; + } + + if (!teleportRequest.isValid()) { + this.user.removeIncomingTeleportRequest(targetUser); + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE_2); + return CommandResultType.DEFAULT; + } + + teleportRequest.accept(); + this.user.removeIncomingTeleportRequest(targetUser); + } return CommandResultType.SUCCESS; } diff --git a/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/CommandTeleportDeny.java b/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/CommandTeleportDeny.java index 20d67eaa..2b684989 100644 --- a/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/CommandTeleportDeny.java +++ b/src/main/java/fr/maxlego08/essentials/commands/commands/teleport/CommandTeleportDeny.java @@ -5,8 +5,14 @@ import fr.maxlego08.essentials.api.commands.Permission; import fr.maxlego08.essentials.api.messages.Message; import fr.maxlego08.essentials.api.user.TeleportRequest; +import fr.maxlego08.essentials.api.user.User; import fr.maxlego08.essentials.module.modules.TeleportationModule; import fr.maxlego08.essentials.zutils.utils.commands.VCommand; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collection; public class CommandTeleportDeny extends VCommand { @@ -15,26 +21,90 @@ public CommandTeleportDeny(EssentialsPlugin plugin) { this.setModule(TeleportationModule.class); this.setPermission(Permission.ESSENTIALS_TPA_DENY); this.setDescription(Message.DESCRIPTION_TPA_DENY); + this.addOptionalArg("player"); this.onlyPlayers(); } @Override protected CommandResultType perform(EssentialsPlugin plugin) { - TeleportRequest teleportRequest = this.user.getTeleportRequest(); - if (teleportRequest == null) { - message(sender, Message.COMMAND_TPA_ERROR_TO_LATE); - return CommandResultType.DEFAULT; - } + String arg = this.argAsString(0, null); - if (!teleportRequest.isValid()) { - this.user.setTeleportRequest(null); - message(sender, Message.COMMAND_TPA_ERROR_TO_LATE_2); - return CommandResultType.DEFAULT; - } + if (arg == null) { + // deny latest request + TeleportRequest teleportRequest = this.user.getTeleportRequest(); + if (teleportRequest == null) { + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE); + return CommandResultType.DEFAULT; + } + + if (!teleportRequest.isValid()) { + this.user.removeIncomingTeleportRequest(teleportRequest.getFromUser()); + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE_2); + return CommandResultType.DEFAULT; + } + + teleportRequest.deny(); + this.user.removeIncomingTeleportRequest(teleportRequest.getFromUser()); + + } else if (arg.equals("*")) { + // deny all pending requests + Collection requests = this.user.getIncomingTeleportRequests(); + if (requests.isEmpty()) { + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE); + return CommandResultType.DEFAULT; + } + + int count = 0; + for (TeleportRequest request : new ArrayList<>(requests)) { + if (request.isValid()) { + request.deny(); + this.user.removeIncomingTeleportRequest(request.getFromUser()); + count++; + } + } - teleportRequest.deny(); - this.user.setTeleportRequest(null); + if (count > 0) { + message(sender, Message.COMMAND_TPA_DENY_ALL_SUCCESS, "%count%", count); + } else { + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE); + return CommandResultType.DEFAULT; + } + + } else { + // deny request from that player + Player targetPlayer = this.argAsPlayer(0); + User targetUser = null; + + if (targetPlayer != null) { + targetUser = plugin.getStorageManager().getStorage().getUser(targetPlayer.getUniqueId()); + } else { + OfflinePlayer offlinePlayer = this.argAsOfflinePlayer(0); + if (offlinePlayer != null && offlinePlayer.hasPlayedBefore()) { + targetUser = plugin.getStorageManager().getStorage().getUser(offlinePlayer.getUniqueId()); + } + } + + if (targetUser == null) { + message(sender, Message.PLAYER_NOT_FOUND, "%player%", arg); + return CommandResultType.DEFAULT; + } + + TeleportRequest teleportRequest = this.user.getTeleportRequestFrom(targetUser); + if (teleportRequest == null) { + message(sender, Message.COMMAND_TPA_ERROR_NO_REQUEST_FROM_PLAYER, "%player%", targetUser.getName()); + return CommandResultType.DEFAULT; + } + + if (!teleportRequest.isValid()) { + this.user.removeIncomingTeleportRequest(targetUser); + message(sender, Message.COMMAND_TPA_ERROR_TO_LATE_2); + return CommandResultType.DEFAULT; + } + + teleportRequest.deny(); + this.user.removeIncomingTeleportRequest(targetUser); + } return CommandResultType.SUCCESS; } diff --git a/src/main/java/fr/maxlego08/essentials/user/ZUser.java b/src/main/java/fr/maxlego08/essentials/user/ZUser.java index 993dd70a..89f7418a 100644 --- a/src/main/java/fr/maxlego08/essentials/user/ZUser.java +++ b/src/main/java/fr/maxlego08/essentials/user/ZUser.java @@ -43,6 +43,7 @@ public class ZUser extends ZUtils implements User { private final EssentialsPlugin plugin; private final Map teleports = new HashMap<>(); + private final Map incomingTeleportRequests = new LinkedHashMap<>(); private final Map cooldowns = new HashMap<>(); private final UUID uniqueId; private final Map options = new HashMap<>(); @@ -53,7 +54,6 @@ public class ZUser extends ZUtils implements User { private final Selection selection = new ZSelection(); private WorldEditTask worldEditTask; private String name; - private TeleportRequest teleportRequest; private User targetUser; private BigDecimal targetAmount; private Economy targetEconomy; @@ -251,12 +251,22 @@ public Collection getTeleportRequests() { @Override public TeleportRequest getTeleportRequest() { - return teleportRequest; + this.incomingTeleportRequests.entrySet().removeIf(entry -> !entry.getValue().isValid()); + + TeleportRequest latestRequest = null; + for (TeleportRequest request : this.incomingTeleportRequests.values()) { + if (request.isValid()) { + latestRequest = request; + } + } + return latestRequest; } @Override public void setTeleportRequest(TeleportRequest teleportRequest) { - this.teleportRequest = teleportRequest; + if (teleportRequest != null) { + this.setIncomingTeleportRequest(teleportRequest); + } } @Override @@ -264,6 +274,42 @@ public void removeTeleportRequest(User user) { this.teleports.remove(user.getUniqueId()); } + @Override + public TeleportRequest getTeleportRequestFrom(User fromUser) { + if (fromUser == null) return null; + + // Cleanup expired requests + this.incomingTeleportRequests.entrySet().removeIf(entry -> !entry.getValue().isValid()); + + TeleportRequest request = this.incomingTeleportRequests.get(fromUser.getUniqueId()); + return (request != null && request.isValid()) ? request : null; + } + + @Override + public Collection getIncomingTeleportRequests() { + this.incomingTeleportRequests.entrySet().removeIf(entry -> !entry.getValue().isValid()); + + return this.incomingTeleportRequests.values().stream() + .filter(TeleportRequest::isValid) + .collect(Collectors.toList()); + } + + @Override + public void setIncomingTeleportRequest(TeleportRequest teleportRequest) { + if (teleportRequest == null) return; + + this.incomingTeleportRequests.entrySet().removeIf(entry -> !entry.getValue().isValid()); + + UUID fromUserId = teleportRequest.getFromUser().getUniqueId(); + this.incomingTeleportRequests.put(fromUserId, teleportRequest); + } + + @Override + public void removeIncomingTeleportRequest(User fromUser) { + if (fromUser == null) return; + this.incomingTeleportRequests.remove(fromUser.getUniqueId()); + } + @Override public void teleportNow(Location location) { // ToDo, https://github.com/PaperMC/Folia/?tab=readme-ov-file#current-broken-api