mirror of
https://github.com/EssentialsX/Essentials.git
synced 2024-12-22 17:18:37 +01:00
Add support for multiple queued TPA requests (#3801)
This PR adds support for players to receive multiple teleport requests, which are queued and can be managed independently of one another. All commands should retain their current behavior but have some new additions; * `/tpaccept`: now allows you to specify a player or `*` to accept a specific player's or all players' teleport request(s) respectively. - Using a wildcard will only accept all tpahere requests, as players can't teleport to multiple places simultaneously. * `/tpdeny`: now allows you to specify a player or `*` to deny a specific player's or all players' teleport request(s) respectively. This PR also adds a new setting for the maximum amount of pending TPA requests a user can have at once. ```yml # The maximum amount of simultaneous tpa requests that can be pending for any given user. # Once at this threshold, any new tpa requests will bump the oldest tpa requests out of queue. # Defaults to 5. tpa-max-amount: 5 ``` Closes #3769 Closes #1550 Co-authored-by: Mariell Hoversholm <proximyst@proximy.st> Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
This commit is contained in:
parent
d091d6902c
commit
7794634d37
@ -238,6 +238,8 @@ public interface ISettings extends IConf {
|
||||
|
||||
long getTpaAcceptCancellation();
|
||||
|
||||
int getTpaMaxRequests();
|
||||
|
||||
long getTeleportInvulnerability();
|
||||
|
||||
boolean isTeleportInvulnerability();
|
||||
|
@ -12,13 +12,16 @@ import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
@ -61,8 +64,11 @@ public interface IUser {
|
||||
/**
|
||||
* Returns whether this user has an outstanding teleport request to deal with.
|
||||
*
|
||||
* @deprecated The teleport request system has been moved into a multi-user teleport request queue.
|
||||
* @see IUser#hasPendingTpaRequests(boolean, boolean)
|
||||
* @return whether there is a teleport request
|
||||
*/
|
||||
@Deprecated
|
||||
boolean hasOutstandingTeleportRequest();
|
||||
|
||||
/**
|
||||
@ -98,6 +104,11 @@ public interface IUser {
|
||||
|
||||
boolean canBuild();
|
||||
|
||||
/**
|
||||
* @deprecated The teleport request system has been moved into a multi-user teleport request queue.
|
||||
* @see IUser#getNextTpaRequest(boolean, boolean, boolean)
|
||||
*/
|
||||
@Deprecated
|
||||
long getTeleportRequestTime();
|
||||
|
||||
void enableInvulnerabilityAfterTeleport();
|
||||
@ -205,6 +216,8 @@ public interface IUser {
|
||||
|
||||
String getName();
|
||||
|
||||
UUID getUUID();
|
||||
|
||||
String getDisplayName();
|
||||
|
||||
String getFormattedNickname();
|
||||
@ -238,4 +251,74 @@ public interface IUser {
|
||||
void setToggleShout(boolean toggleShout);
|
||||
|
||||
boolean isToggleShout();
|
||||
|
||||
/**
|
||||
* Gets information about the most-recently-made, non-expired TPA request in the tpa queue of this {@link IUser}.
|
||||
* <p>
|
||||
* The TPA Queue is Last-In-First-Out queue which stores all the active pending teleport
|
||||
* requests of this {@link IUser}. Timeout calculations are also done during the
|
||||
* iteration process of this method, ensuring that teleport requests made past the timeout
|
||||
* period are removed from queue and therefore not returned here. The maximum size of this
|
||||
* queue is determined by {@link ISettings#getTpaMaxRequests()}.
|
||||
*
|
||||
* @param inform true if the underlying {@link IUser} should be informed if a request expires during iteration.
|
||||
* @param performExpirations true if this method should not spend time validating time for all items in the queue and just return the first item in the queue.
|
||||
* @param excludeHere true if /tphere requests should be ignored in fetching the next tpa request.
|
||||
* @return A {@link TpaRequest} corresponding to the next available request or null if no valid request is present.
|
||||
*/
|
||||
@Nullable TpaRequest getNextTpaRequest(boolean inform, boolean performExpirations, boolean excludeHere);
|
||||
|
||||
/**
|
||||
* Whether or not this {@link IUser} has any valid TPA requests in queue.
|
||||
*
|
||||
* @param inform true if the user should be informed if a request expires during iteration.
|
||||
* @param excludeHere true if /tpahere requests should be ignored in checking if a tpa request is available.
|
||||
* @return true if the user has an available pending request in queue.
|
||||
*/
|
||||
boolean hasPendingTpaRequests(boolean inform, boolean excludeHere);
|
||||
|
||||
class TpaRequest {
|
||||
private final String name;
|
||||
private final UUID requesterUuid;
|
||||
private boolean here;
|
||||
private Location location;
|
||||
private long time;
|
||||
|
||||
public TpaRequest(String name, UUID requesterUuid) {
|
||||
this.name = name;
|
||||
this.requesterUuid = requesterUuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public UUID getRequesterUuid() {
|
||||
return requesterUuid;
|
||||
}
|
||||
|
||||
public boolean isHere() {
|
||||
return here;
|
||||
}
|
||||
|
||||
public void setHere(boolean here) {
|
||||
this.here = here;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(Location location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1264,6 +1264,11 @@ public class Settings implements net.ess3.api.ISettings {
|
||||
return config.getLong("tpa-accept-cancellation", 120);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTpaMaxRequests() {
|
||||
return config.getInt("tpa-max-requests", 5);
|
||||
}
|
||||
|
||||
private long _getTeleportInvulnerability() {
|
||||
return config.getLong("teleport-invulnerability", 0) * 1000;
|
||||
}
|
||||
|
@ -31,16 +31,21 @@ import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -49,28 +54,37 @@ import static com.earth2me.essentials.I18n.tl;
|
||||
public class User extends UserData implements Comparable<User>, IMessageRecipient, net.ess3.api.IUser {
|
||||
private static final Statistic PLAY_ONE_TICK = EnumUtil.getStatistic("PLAY_ONE_MINUTE", "PLAY_ONE_TICK");
|
||||
private static final Logger logger = Logger.getLogger("Essentials");
|
||||
|
||||
// User modules
|
||||
private final IMessageRecipient messageRecipient;
|
||||
private transient final AsyncTeleport teleport;
|
||||
private transient final Teleport legacyTeleport;
|
||||
|
||||
// User command confirmation strings
|
||||
private final Map<User, BigDecimal> confirmingPayments = new WeakHashMap<>();
|
||||
private transient UUID teleportRequester;
|
||||
private transient boolean teleportRequestHere;
|
||||
private transient Location teleportLocation;
|
||||
|
||||
// User teleport variables
|
||||
private final transient LinkedHashMap<String, TpaRequest> teleportRequestQueue = new LinkedHashMap<>();
|
||||
|
||||
// User properties
|
||||
private transient boolean vanished;
|
||||
private transient long teleportRequestTime;
|
||||
private transient long lastOnlineActivity;
|
||||
private transient long lastThrottledAction;
|
||||
private transient long lastActivity = System.currentTimeMillis();
|
||||
private boolean hidden = false;
|
||||
private boolean rightClickJump = false;
|
||||
private transient Location afkPosition = null;
|
||||
private boolean invSee = false;
|
||||
private boolean recipeSee = false;
|
||||
private boolean enderSee = false;
|
||||
private transient long teleportInvulnerabilityTimestamp = 0;
|
||||
private boolean ignoreMsg = false;
|
||||
|
||||
// User afk variables
|
||||
private String afkMessage;
|
||||
private long afkSince;
|
||||
private transient Location afkPosition = null;
|
||||
|
||||
// Misc
|
||||
private transient long lastOnlineActivity;
|
||||
private transient long lastThrottledAction;
|
||||
private transient long lastActivity = System.currentTimeMillis();
|
||||
private transient long teleportInvulnerabilityTimestamp = 0;
|
||||
private String confirmingClearCommand;
|
||||
private long lastNotifiedAboutMailsMs;
|
||||
private String lastHomeConfirmation;
|
||||
@ -91,9 +105,8 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
this.messageRecipient = new SimpleMessageRecipient(ess, this);
|
||||
}
|
||||
|
||||
User update(final Player base) {
|
||||
void update(final Player base) {
|
||||
setBase(base);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -328,44 +341,95 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
|
||||
@Override
|
||||
public void requestTeleport(final User player, final boolean here) {
|
||||
teleportRequestTime = System.currentTimeMillis();
|
||||
teleportRequester = player == null ? null : player.getBase().getUniqueId();
|
||||
teleportRequestHere = here;
|
||||
if (player == null) {
|
||||
teleportLocation = null;
|
||||
} else {
|
||||
teleportLocation = here ? player.getLocation() : this.getLocation();
|
||||
final TpaRequest request = teleportRequestQueue.getOrDefault(player.getName(), new TpaRequest(player.getName(), player.getUUID()));
|
||||
request.setTime(System.currentTimeMillis());
|
||||
request.setHere(here);
|
||||
request.setLocation(here ? player.getLocation() : this.getLocation());
|
||||
|
||||
// Handle max queue size
|
||||
teleportRequestQueue.remove(request.getName());
|
||||
if (teleportRequestQueue.size() >= ess.getSettings().getTpaMaxRequests()) {
|
||||
String lastKey = null;
|
||||
for (Map.Entry<String, TpaRequest> entry : teleportRequestQueue.entrySet()) {
|
||||
lastKey = entry.getKey();
|
||||
}
|
||||
teleportRequestQueue.remove(lastKey);
|
||||
}
|
||||
|
||||
// Add request to queue
|
||||
teleportRequestQueue.put(request.getName(), request);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean hasOutstandingTeleportRequest() {
|
||||
if (getTeleportRequest() != null) { // Player has outstanding teleport request.
|
||||
final long timeout = ess.getSettings().getTpaAcceptCancellation();
|
||||
if (timeout != 0) {
|
||||
if ((System.currentTimeMillis() - getTeleportRequestTime()) / 1000 <= timeout) { // Player has outstanding request
|
||||
return true;
|
||||
} else { // outstanding request expired.
|
||||
requestTeleport(null, false);
|
||||
return false;
|
||||
return getNextTpaRequest(false, false, false) != null;
|
||||
}
|
||||
|
||||
public Collection<String> getPendingTpaKeys() {
|
||||
return teleportRequestQueue.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPendingTpaRequests(boolean inform, boolean excludeHere) {
|
||||
return getNextTpaRequest(inform, false, excludeHere) != null;
|
||||
}
|
||||
|
||||
public boolean hasOutstandingTpaRequest(String playerUsername, boolean here) {
|
||||
final TpaRequest request = getOutstandingTpaRequest(playerUsername, false);
|
||||
return request != null && request.isHere() == here;
|
||||
}
|
||||
|
||||
public @Nullable TpaRequest getOutstandingTpaRequest(String playerUsername, boolean inform) {
|
||||
if (!teleportRequestQueue.containsKey(playerUsername)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final long timeout = ess.getSettings().getTpaAcceptCancellation();
|
||||
final TpaRequest request = teleportRequestQueue.get(playerUsername);
|
||||
if (timeout < 1 || System.currentTimeMillis() - request.getTime() <= timeout * 1000) {
|
||||
return request;
|
||||
}
|
||||
teleportRequestQueue.remove(playerUsername);
|
||||
if (inform) {
|
||||
sendMessage(tl("requestTimedOutFrom", ess.getUser(request.getRequesterUuid()).getDisplayName()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public TpaRequest removeTpaRequest(String playerUsername) {
|
||||
return teleportRequestQueue.remove(playerUsername);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TpaRequest getNextTpaRequest(boolean inform, boolean performExpirations, boolean excludeHere) {
|
||||
if (teleportRequestQueue.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final long timeout = ess.getSettings().getTpaAcceptCancellation();
|
||||
final Iterator<Map.Entry<String, TpaRequest>> iterator = teleportRequestQueue.entrySet().iterator();
|
||||
TpaRequest nextRequest = null;
|
||||
while (iterator.hasNext()) {
|
||||
final TpaRequest request = iterator.next().getValue();
|
||||
if (timeout < 1 || (System.currentTimeMillis() - request.getTime()) <= TimeUnit.SECONDS.toMillis(timeout)) {
|
||||
if (excludeHere && request.isHere()) {
|
||||
continue;
|
||||
}
|
||||
} else { // outstanding request does not expire
|
||||
return true;
|
||||
|
||||
if (performExpirations) {
|
||||
return request;
|
||||
} else if (nextRequest == null) {
|
||||
nextRequest = request;
|
||||
}
|
||||
} else {
|
||||
if (inform) {
|
||||
sendMessage(tl("requestTimedOutFrom", ess.getUser(request.getRequesterUuid()).getDisplayName()));
|
||||
}
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public UUID getTeleportRequest() {
|
||||
return teleportRequester;
|
||||
}
|
||||
|
||||
public boolean isTpRequestHere() {
|
||||
return teleportRequestHere;
|
||||
}
|
||||
|
||||
public Location getTpRequestLocation() {
|
||||
return teleportLocation;
|
||||
return nextRequest;
|
||||
}
|
||||
|
||||
public String getNick() {
|
||||
@ -824,8 +888,11 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
return ess.getPermissionsHandler().canBuild(base, getGroup());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public long getTeleportRequestTime() {
|
||||
return teleportRequestTime;
|
||||
final TpaRequest request = getNextTpaRequest(false, false, false);
|
||||
return request == null ? 0L : request.getTime();
|
||||
}
|
||||
|
||||
public boolean isInvSee() {
|
||||
@ -993,7 +1060,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return getBase().getUniqueId();
|
||||
return this.getBase().getUniqueId();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -37,11 +37,12 @@ public class Commandtpa extends EssentialsCommand {
|
||||
if (user.getWorld() != player.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + player.getWorld().getName())) {
|
||||
throw new Exception(tl("noPerm", "essentials.worlds." + player.getWorld().getName()));
|
||||
}
|
||||
|
||||
// Don't let sender request teleport twice to the same player.
|
||||
if (user.getConfigUUID().equals(player.getTeleportRequest()) && player.hasOutstandingTeleportRequest() // Check timeout
|
||||
&& !player.isTpRequestHere()) { // Make sure the last teleport request was actually tpa and not tpahere
|
||||
if (player.hasOutstandingTpaRequest(user.getName(), false)) {
|
||||
throw new Exception(tl("requestSentAlready", player.getDisplayName()));
|
||||
}
|
||||
|
||||
if (player.isAutoTeleportEnabled() && !player.isIgnoredPlayer(user)) {
|
||||
final Trade charge = new Trade(this.getName(), ess);
|
||||
final AsyncTeleport teleport = user.getAsyncTeleport();
|
||||
@ -71,6 +72,7 @@ public class Commandtpa extends EssentialsCommand {
|
||||
player.sendMessage(tl("teleportRequestTimeoutInfo", ess.getSettings().getTpaAcceptCancellation()));
|
||||
}
|
||||
}
|
||||
|
||||
user.sendMessage(tl("requestSent", player.getDisplayName()));
|
||||
if (user.isAuthorized("essentials.tpacancel")) {
|
||||
user.sendMessage(tl("typeTpacancel"));
|
||||
|
@ -19,17 +19,17 @@ public class Commandtpaall extends EssentialsCommand {
|
||||
public void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
|
||||
if (args.length < 1) {
|
||||
if (sender.isPlayer()) {
|
||||
teleportAAllPlayers(server, sender, ess.getUser(sender.getPlayer()));
|
||||
tpaAll(sender, ess.getUser(sender.getPlayer()));
|
||||
return;
|
||||
}
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
||||
final User target = getPlayer(server, sender, args, 0);
|
||||
teleportAAllPlayers(server, sender, target);
|
||||
tpaAll(sender, target);
|
||||
}
|
||||
|
||||
private void teleportAAllPlayers(final Server server, final CommandSource sender, final User target) {
|
||||
private void tpaAll(final CommandSource sender, final User target) {
|
||||
sender.sendMessage(tl("teleportAAll"));
|
||||
for (final User player : ess.getOnlineUsers()) {
|
||||
if (target == player) {
|
||||
@ -41,6 +41,7 @@ public class Commandtpaall extends EssentialsCommand {
|
||||
if (sender.getSender().equals(target.getBase()) && target.getWorld() != player.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !target.isAuthorized("essentials.worlds." + target.getWorld().getName())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
final TPARequestEvent tpaEvent = new TPARequestEvent(sender, player, true);
|
||||
ess.getServer().getPluginManager().callEvent(tpaEvent);
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.User;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
@ -15,20 +14,12 @@ public class Commandtpacancel extends EssentialsCommand {
|
||||
/**
|
||||
* Cancel {@link User}'s tp request if its {@code requester} is equal to the given {@code requester}.
|
||||
*
|
||||
* @param ess ess instance
|
||||
* @param user user holding tp request
|
||||
* @param requester tp requester
|
||||
* @return whether tp was cancelled
|
||||
*/
|
||||
public static boolean cancelTeleportRequest(final IEssentials ess, final User user, final User requester) throws Exception {
|
||||
if (user.getTeleportRequest() != null) {
|
||||
final User userRequester = ess.getUser(user.getTeleportRequest());
|
||||
if (requester.equals(userRequester)) {
|
||||
user.requestTeleport(null, false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
public static boolean cancelTeleportRequest(final User user, final User requester) {
|
||||
return user.removeTpaRequest(requester.getName()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -37,7 +28,7 @@ public class Commandtpacancel extends EssentialsCommand {
|
||||
int cancellations = 0;
|
||||
for (final User onlineUser : ess.getOnlineUsers()) {
|
||||
if (onlineUser == user) continue;
|
||||
if (cancelTeleportRequest(ess, onlineUser, user)) {
|
||||
if (cancelTeleportRequest(onlineUser, user)) {
|
||||
cancellations++;
|
||||
}
|
||||
}
|
||||
@ -48,7 +39,7 @@ public class Commandtpacancel extends EssentialsCommand {
|
||||
}
|
||||
} else {
|
||||
final User targetPlayer = getPlayer(server, user, args, 0);
|
||||
if (cancelTeleportRequest(ess, targetPlayer, user)) {
|
||||
if (cancelTeleportRequest(targetPlayer, user)) {
|
||||
user.sendMessage(tl("teleportRequestSpecificCancelled", targetPlayer.getName()));
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,18 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.AsyncTeleport;
|
||||
import com.earth2me.essentials.IUser;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import net.essentialsx.api.v2.events.TeleportRequestResponseEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
@ -18,36 +24,87 @@ public class Commandtpaccept extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
final User requester;
|
||||
try {
|
||||
requester = ess.getUser(user.getTeleportRequest());
|
||||
} catch (final Exception ex) {
|
||||
final boolean acceptAll;
|
||||
if (args.length > 0) {
|
||||
acceptAll = args[0].equals("*") || args[0].equalsIgnoreCase("all");
|
||||
} else {
|
||||
acceptAll = false;
|
||||
}
|
||||
|
||||
if (!user.hasPendingTpaRequests(true, acceptAll)) {
|
||||
throw new Exception(tl("noPendingRequest"));
|
||||
}
|
||||
|
||||
if (args.length > 0) {
|
||||
if (acceptAll) {
|
||||
acceptAllRequests(user, commandLabel);
|
||||
throw new NoChargeException();
|
||||
}
|
||||
user.sendMessage(tl("requestAccepted"));
|
||||
handleTeleport(user, user.getOutstandingTpaRequest(getPlayer(server, user, args, 0).getName(), true), commandLabel);
|
||||
} else {
|
||||
user.sendMessage(tl("requestAccepted"));
|
||||
handleTeleport(user, user.getNextTpaRequest(true, false, false), commandLabel);
|
||||
}
|
||||
throw new NoChargeException();
|
||||
}
|
||||
|
||||
private void acceptAllRequests(final User user, final String commandLabel) throws Exception {
|
||||
IUser.TpaRequest request;
|
||||
int count = 0;
|
||||
while ((request = user.getNextTpaRequest(true, true, true)) != null) {
|
||||
try {
|
||||
handleTeleport(user, request, commandLabel);
|
||||
count++;
|
||||
} catch (Exception e) {
|
||||
ess.showError(user.getSource(), e, commandLabel);
|
||||
} finally {
|
||||
user.removeTpaRequest(request.getName());
|
||||
}
|
||||
}
|
||||
user.sendMessage(tl("requestAcceptedAll", count));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) {
|
||||
if (args.length == 1) {
|
||||
final List<String> options = new ArrayList<>(user.getPendingTpaKeys());
|
||||
options.add("*");
|
||||
return options;
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTeleport(final User user, final IUser.TpaRequest request, String commandLabel) throws Exception {
|
||||
if (request == null) {
|
||||
throw new Exception(tl("noPendingRequest"));
|
||||
}
|
||||
final User requester = ess.getUser(request.getRequesterUuid());
|
||||
|
||||
if (!requester.getBase().isOnline()) {
|
||||
user.removeTpaRequest(request.getName());
|
||||
throw new Exception(tl("noPendingRequest"));
|
||||
}
|
||||
|
||||
if (user.isTpRequestHere() && ((!requester.isAuthorized("essentials.tpahere") && !requester.isAuthorized("essentials.tpaall")) || (user.getWorld() != requester.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + user.getWorld().getName())))) {
|
||||
if (request.isHere() && ((!requester.isAuthorized("essentials.tpahere") && !requester.isAuthorized("essentials.tpaall")) || (user.getWorld() != requester.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + user.getWorld().getName())))) {
|
||||
throw new Exception(tl("noPendingRequest"));
|
||||
}
|
||||
|
||||
if (!user.isTpRequestHere() && (!requester.isAuthorized("essentials.tpa") || (user.getWorld() != requester.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + requester.getWorld().getName())))) {
|
||||
if (!request.isHere() && (!requester.isAuthorized("essentials.tpa") || (user.getWorld() != requester.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + requester.getWorld().getName())))) {
|
||||
throw new Exception(tl("noPendingRequest"));
|
||||
}
|
||||
|
||||
if (args.length > 0 && !requester.getName().contains(args[0])) {
|
||||
throw new Exception(tl("noPendingRequest"));
|
||||
}
|
||||
|
||||
if (!user.hasOutstandingTeleportRequest()) {
|
||||
user.requestTeleport(null, false);
|
||||
throw new Exception(tl("requestTimedOut"));
|
||||
final TeleportRequestResponseEvent event = new TeleportRequestResponseEvent(user, requester, request, true);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
logger.info("TPA accept cancelled by API for " + user.getName() + " (requested by " + requester.getName() + ")");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final Trade charge = new Trade(this.getName(), ess);
|
||||
user.sendMessage(tl("requestAccepted"));
|
||||
requester.sendMessage(tl("requestAcceptedFrom", user.getDisplayName()));
|
||||
|
||||
final CompletableFuture<Boolean> future = getNewExceptionFuture(requester.getSource(), commandLabel);
|
||||
@ -55,8 +112,8 @@ public class Commandtpaccept extends EssentialsCommand {
|
||||
user.sendMessage(tl("pendingTeleportCancelled"));
|
||||
return false;
|
||||
});
|
||||
if (user.isTpRequestHere()) {
|
||||
final Location loc = user.getTpRequestLocation();
|
||||
if (request.isHere()) {
|
||||
final Location loc = request.getLocation();
|
||||
final AsyncTeleport teleport = requester.getAsyncTeleport();
|
||||
teleport.setTpType(AsyncTeleport.TeleportType.TPA);
|
||||
future.thenAccept(success -> {
|
||||
@ -64,14 +121,12 @@ public class Commandtpaccept extends EssentialsCommand {
|
||||
requester.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
}
|
||||
});
|
||||
teleport.teleportPlayer(user, user.getTpRequestLocation(), charge, TeleportCause.COMMAND, future);
|
||||
teleport.teleportPlayer(user, loc, charge, TeleportCause.COMMAND, future);
|
||||
} else {
|
||||
final AsyncTeleport teleport = requester.getAsyncTeleport();
|
||||
teleport.setTpType(AsyncTeleport.TeleportType.TPA);
|
||||
teleport.teleport(user.getBase(), charge, TeleportCause.COMMAND, future);
|
||||
}
|
||||
user.requestTeleport(null, false);
|
||||
throw new NoChargeException();
|
||||
user.removeTpaRequest(request.getName());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -33,11 +33,12 @@ public class Commandtpahere extends EssentialsCommand {
|
||||
if (user.getWorld() != player.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + user.getWorld().getName())) {
|
||||
throw new Exception(tl("noPerm", "essentials.worlds." + user.getWorld().getName()));
|
||||
}
|
||||
|
||||
// Don't let sender request teleport twice to the same player.
|
||||
if (user.getConfigUUID().equals(player.getTeleportRequest()) && player.hasOutstandingTeleportRequest() // Check timeout
|
||||
&& player.isTpRequestHere()) { // Make sure the last teleport request was actually tpahere and not tpa
|
||||
if (player.hasOutstandingTpaRequest(user.getName(), true)) {
|
||||
throw new Exception(tl("requestSentAlready", player.getDisplayName()));
|
||||
}
|
||||
|
||||
if (!player.isIgnoredPlayer(user)) {
|
||||
final TPARequestEvent tpaEvent = new TPARequestEvent(user.getSource(), player, true);
|
||||
ess.getServer().getPluginManager().callEvent(tpaEvent);
|
||||
|
@ -1,8 +1,15 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.IUser;
|
||||
import com.earth2me.essentials.User;
|
||||
import net.essentialsx.api.v2.events.TeleportRequestResponseEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
public class Commandtpdeny extends EssentialsCommand {
|
||||
@ -12,16 +19,84 @@ public class Commandtpdeny extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
if (user.getTeleportRequest() == null) {
|
||||
final boolean denyAll;
|
||||
if (args.length > 0) {
|
||||
denyAll = args[0].equals("*") || args[0].equalsIgnoreCase("all");
|
||||
} else {
|
||||
denyAll = false;
|
||||
}
|
||||
|
||||
if (!user.hasPendingTpaRequests(false, false)) {
|
||||
throw new Exception(tl("noPendingRequest"));
|
||||
}
|
||||
final User player = ess.getUser(user.getTeleportRequest());
|
||||
if (player == null) {
|
||||
|
||||
final IUser.TpaRequest denyRequest;
|
||||
if (args.length > 0) {
|
||||
if (denyAll) {
|
||||
denyAllRequests(user);
|
||||
return;
|
||||
}
|
||||
denyRequest = user.getOutstandingTpaRequest(getPlayer(server, user, args, 0).getName(), false);
|
||||
} else {
|
||||
denyRequest = user.getNextTpaRequest(false, true, false);
|
||||
}
|
||||
|
||||
if (denyRequest == null) {
|
||||
throw new Exception(tl("noPendingRequest"));
|
||||
}
|
||||
|
||||
final User player = ess.getUser(denyRequest.getRequesterUuid());
|
||||
if (player == null || !player.getBase().isOnline()) {
|
||||
throw new Exception(tl("noPendingRequest"));
|
||||
}
|
||||
|
||||
if (sendEvent(user, player, denyRequest)) {
|
||||
return;
|
||||
}
|
||||
|
||||
user.sendMessage(tl("requestDenied"));
|
||||
player.sendMessage(tl("requestDeniedFrom", user.getDisplayName()));
|
||||
user.requestTeleport(null, false);
|
||||
user.removeTpaRequest(denyRequest.getName());
|
||||
}
|
||||
|
||||
private void denyAllRequests(User user) {
|
||||
IUser.TpaRequest request;
|
||||
int count = 0;
|
||||
while ((request = user.getNextTpaRequest(false, true, false)) != null) {
|
||||
final User player = ess.getUser(request.getRequesterUuid());
|
||||
|
||||
if (sendEvent(user, player, request)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player != null && player.getBase().isOnline()) {
|
||||
player.sendMessage(tl("requestDeniedFrom", user.getDisplayName()));
|
||||
}
|
||||
|
||||
user.removeTpaRequest(request.getName());
|
||||
count++;
|
||||
}
|
||||
user.sendMessage(tl("requestDeniedAll", count));
|
||||
}
|
||||
|
||||
private boolean sendEvent(User user, User player, IUser.TpaRequest request) {
|
||||
final TeleportRequestResponseEvent event = new TeleportRequestResponseEvent(user, player, request, false);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
final boolean cancelled = event.isCancelled();
|
||||
if (cancelled && ess.getSettings().isDebug()) {
|
||||
logger.info("TPA deny cancelled by API for " + user.getName() + " (requested by " + player.getName() + ")");
|
||||
}
|
||||
return event.isCancelled();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) {
|
||||
if (args.length == 1) {
|
||||
final List<String> options = new ArrayList<>(user.getPendingTpaKeys());
|
||||
options.add("*");
|
||||
return options;
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,90 @@
|
||||
package net.essentialsx.api.v2.events;
|
||||
|
||||
import com.earth2me.essentials.IUser;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/**
|
||||
* Called when a player accepts or denies a teleport.
|
||||
*/
|
||||
public class TeleportRequestResponseEvent extends Event implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
|
||||
private final net.ess3.api.IUser requestee;
|
||||
private final net.ess3.api.IUser requester;
|
||||
private final IUser.TpaRequest tpaRequest;
|
||||
private final boolean accept;
|
||||
private boolean canceled = false;
|
||||
|
||||
public TeleportRequestResponseEvent(net.ess3.api.IUser requestee, net.ess3.api.IUser requester, IUser.TpaRequest tpaRequest, boolean accept) {
|
||||
this.requestee = requestee;
|
||||
this.requester = requester;
|
||||
this.tpaRequest = tpaRequest;
|
||||
this.accept = accept;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user who is accepting/denying this teleport request.
|
||||
* @return the user accepting/denying the request.
|
||||
*/
|
||||
public net.ess3.api.IUser getRequestee() {
|
||||
return requestee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user who submitted this teleport request.
|
||||
* @return the user who sent the request.
|
||||
*/
|
||||
public net.ess3.api.IUser getRequester() {
|
||||
return requester;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets information about this teleport request.
|
||||
* @return the {@link com.earth2me.essentials.IUser.TpaRequest} object of this event.
|
||||
*/
|
||||
public IUser.TpaRequest getTpaRequest() {
|
||||
return tpaRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the request has been accepted.
|
||||
* @return true if accepted, false if denied.
|
||||
*/
|
||||
public boolean isAccept() {
|
||||
return accept;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the request has been denied.
|
||||
* @return true if denied, false if accepted.
|
||||
*/
|
||||
public boolean isDeny() {
|
||||
return !isAccept();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return canceled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not to cancel this teleport request.
|
||||
* Note that cancelling this event will not show a message to users about the cancellation.
|
||||
* @param cancel whether or not to cancel this teleport request.
|
||||
*/
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.canceled = cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public static HandlerList getHandlerList() {
|
||||
return handlers;
|
||||
}
|
||||
}
|
@ -698,6 +698,11 @@ jail-online-time: false
|
||||
# Set to 0 for no timeout.
|
||||
tpa-accept-cancellation: 120
|
||||
|
||||
# The maximum number of simultaneous tpa requests that can be pending for any player.
|
||||
# Once past this threshold, old requests will instantly time out.
|
||||
# Defaults to 5.
|
||||
tpa-max-requests: 5
|
||||
|
||||
# Allow players to set hats by clicking on their helmet slot.
|
||||
allow-direct-hat: true
|
||||
|
||||
|
@ -1023,14 +1023,17 @@ replyLastRecipientDisabledFor=\u00a76Replying to last message recipient \u00a7cd
|
||||
replyLastRecipientEnabled=\u00a76Replying to last message recipient \u00a7cenabled\u00a76.
|
||||
replyLastRecipientEnabledFor=\u00a76Replying to last message recipient \u00a7cenabled \u00a76for \u00a7c{0}\u00a76.
|
||||
requestAccepted=\u00a76Teleport request accepted.
|
||||
requestAcceptedAll=\u00a76Accepted \u00a7c{0} \u00a76pending teleport request(s).
|
||||
requestAcceptedAuto=\u00a76Automatically accepted a teleport request from {0}.
|
||||
requestAcceptedFrom=\u00a7c{0} \u00a76accepted your teleport request.
|
||||
requestAcceptedFromAuto=\u00a7c{0} \u00a76accepted your teleport request automatically.
|
||||
requestDenied=\u00a76Teleport request denied.
|
||||
requestDeniedAll=\u00a76Denied \u00a7c{0} \u00a76pending teleport request(s).
|
||||
requestDeniedFrom=\u00a7c{0} \u00a76denied your teleport request.
|
||||
requestSent=\u00a76Request sent to\u00a7c {0}\u00a76.
|
||||
requestSentAlready=\u00a74You have already sent {0}\u00a74 a teleport request.
|
||||
requestTimedOut=\u00a74Teleport request has timed out.
|
||||
requestTimedOutFrom=\u00a74Teleport request from \u00a7c{0} \u00a74has timed out.
|
||||
resetBal=\u00a76Balance has been reset to \u00a7c{0} \u00a76for all online players.
|
||||
resetBalAll=\u00a76Balance has been reset to \u00a7c{0} \u00a76for all players.
|
||||
rest=\u00a76You feel well rested.
|
||||
@ -1290,10 +1293,14 @@ tpacancelCommandUsage1=/<command>
|
||||
tpacancelCommandUsage1Description=Cancels all your outstanding teleport requests
|
||||
tpacancelCommandUsage2=/<command> <player>
|
||||
tpacancelCommandUsage2Description=Cancels all your outstanding teleport request with the specified player
|
||||
tpacceptCommandDescription=Accepts a teleport request.
|
||||
tpacceptCommandDescription=Accepts teleport requests.
|
||||
tpacceptCommandUsage=/<command> [otherplayer]
|
||||
tpacceptCommandUsage1=/<command>
|
||||
tpacceptCommandUsage1Description=Accepts an incoming teleport request
|
||||
tpacceptCommandUsage1Description=Accepts the most recent teleport request
|
||||
tpacceptCommandUsage2=/<command> <player>
|
||||
tpacceptCommandUsage2Description=Accepts a teleport request from the specified player
|
||||
tpacceptCommandUsage3=/<command> *
|
||||
tpacceptCommandUsage3Description=Accepts all teleport requests
|
||||
tpahereCommandDescription=Request that the specified player teleport to you.
|
||||
tpahereCommandUsage=/<command> <player>
|
||||
tpahereCommandUsage1=/<command> <player>
|
||||
@ -1306,10 +1313,14 @@ tpautoCommandDescription=Automatically accept teleportation requests.
|
||||
tpautoCommandUsage=/<command> [player]
|
||||
tpautoCommandUsage1=/<command> [player]
|
||||
tpautoCommandUsage1Description=Toggles if tpa requests are auto accepted for yourself or another player if specified
|
||||
tpdenyCommandDescription=Reject a teleport request.
|
||||
tpdenyCommandDescription=Rejects teleport requests.
|
||||
tpdenyCommandUsage=/<command>
|
||||
tpdenyCommandUsage1=/<command>
|
||||
tpdenyCommandUsage1Description=Rejects an incoming teleport request
|
||||
tpdenyCommandUsage1Description=Rejects the most recent teleport request
|
||||
tpdenyCommandUsage2=/<command> <player>
|
||||
tpdenyCommandUsage2Description=Rejects a teleport request from the specified player
|
||||
tpdenyCommandUsage3=/<command> *
|
||||
tpdenyCommandUsage3Description=Rejects all teleport requests
|
||||
tphereCommandDescription=Teleport a player to you.
|
||||
tphereCommandUsage=/<command> <player>
|
||||
tphereCommandUsage1=/<command> <player>
|
||||
|
@ -509,8 +509,8 @@ commands:
|
||||
usage: /<command> <player>
|
||||
aliases: [etpaall]
|
||||
tpaccept:
|
||||
description: Accepts a teleport request.
|
||||
usage: /<command> [otherplayer]
|
||||
description: Accepts teleport requests.
|
||||
usage: /<command> [player|*]
|
||||
aliases: [etpaccept,tpyes,etpyes]
|
||||
tpahere:
|
||||
description: Request that the specified player teleport to you.
|
||||
@ -529,8 +529,8 @@ commands:
|
||||
usage: /<command> [player]
|
||||
aliases: [etpacancel]
|
||||
tpdeny:
|
||||
description: Reject a teleport request.
|
||||
usage: /<command>
|
||||
description: Rejects teleport requests.
|
||||
usage: /<command> [player|*]
|
||||
aliases: [etpdeny,tpno,etpno]
|
||||
tphere:
|
||||
description: Teleport a player to you.
|
||||
|
Loading…
Reference in New Issue
Block a user