mirror of
https://github.com/EssentialsX/Essentials.git
synced 2025-02-01 21:11:44 +01:00
Reduce sync loads for teleporting (#3102)
This PR reduces the number of sync loads occurring on any teleport caused by essentials. Fixes #2861 Fixes #2287 Fixes #3274 Fixes #3201 Fixes #2120 Before this PR, essentials would get a block multiple times causing sync loads to check if it was safe to teleport to. Now, the target block's chunk if fetched async with PaperLib and passed along to `LocationUtil#isBlockUnsafeForUser` (which internally calls other LocationUtil methods what that chunk object) resulting in the chunk only loading once, off the main thread. The only operations remaining on the main thread is `LocationUtil#getSafeDestination`. This is due to the method's recursion which would be a pain to move async. **However:** since the chunk was already loaded async, `LocationUtil#getSafeDestination` most of the time won't cause sync chunk loads. The only time it would cause sync chunk loads is with an unsafe location near a chunk border. ----------------------------------------- * Reduce sync teleporting loads * Avoid argument re-assigning * Remove async teleports when unnecessary * Make exceptions cleaner * Async all the things Made an async version of every method with fallbacks for deprecated methods. * Remove old now fallback method * Migrate everything to the new async teleport API * Update ITeleport javadocs * Fix invoking via async context * Fix /jail using deprecated method * Fix jail join handler using deprecated method * Rename all teleport classes to indicate async * Remove deprecated methods * Add (and deprecate) old teleport api * Revert TimedTeleport.java * Reduce Diff * Add legacy sendToJail method * Reduce Diff Further * Use getNewExceptionFuture in Commandtpo * Use getNewExceptionFuture everywhere * Fix even more usages * Revert LocationUtil.java * Fix issue causing unsafe locations to not work properly * Add deprecated notice in IUser implementation * Use CompletableFuture#completeExceptionally for exceptions * Use Essentials' logger in EssentialsCommand#showError * Return implementation rather than interface * Avoid possible deadlocks with entity ejections * Nuke some sync loads with homes Took 7 hours and 2 PRs to paper but it's here! * Fix ABI and make the codestyle worse * Make the codestyle worse because muh diff * Further ruin the codestyle * Fix error messages not showing in TimedTeleports * Improve messages around beds for /home * Fix #3274 Allow unsafe locations for different worlds + spectator mode * Fix fly safety operators
This commit is contained in:
parent
d2f2140be9
commit
d9bf099c3d
@ -63,7 +63,7 @@
|
||||
<dependency>
|
||||
<groupId>io.papermc</groupId>
|
||||
<artifactId>paperlib</artifactId>
|
||||
<version>1.0.2</version>
|
||||
<version>1.0.3</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
428
Essentials/src/com/earth2me/essentials/AsyncTeleport.java
Normal file
428
Essentials/src/com/earth2me/essentials/AsyncTeleport.java
Normal file
@ -0,0 +1,428 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.api.IAsyncTeleport;
|
||||
import com.earth2me.essentials.commands.WarpNotFoundException;
|
||||
import com.earth2me.essentials.utils.DateUtil;
|
||||
import com.earth2me.essentials.utils.LocationUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IUser;
|
||||
import net.ess3.api.InvalidWorldException;
|
||||
import net.ess3.api.events.UserTeleportEvent;
|
||||
import net.ess3.api.events.UserWarpEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class AsyncTeleport implements IAsyncTeleport {
|
||||
private final IUser teleportOwner;
|
||||
private final IEssentials ess;
|
||||
private AsyncTimedTeleport timedTeleport;
|
||||
|
||||
private TeleportType tpType;
|
||||
|
||||
public AsyncTeleport(IUser user, IEssentials ess) {
|
||||
this.teleportOwner = user;
|
||||
this.ess = ess;
|
||||
tpType = TeleportType.NORMAL;
|
||||
}
|
||||
|
||||
public enum TeleportType {
|
||||
TPA,
|
||||
BACK,
|
||||
NORMAL
|
||||
}
|
||||
|
||||
public void cooldown(boolean check) throws Throwable {
|
||||
CompletableFuture<Boolean> exceptionFuture = new CompletableFuture<>();
|
||||
if (cooldown(check, exceptionFuture)) {
|
||||
try {
|
||||
exceptionFuture.get();
|
||||
} catch (ExecutionException e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean cooldown(boolean check, CompletableFuture<Boolean> future) {
|
||||
final Calendar time = new GregorianCalendar();
|
||||
if (teleportOwner.getLastTeleportTimestamp() > 0) {
|
||||
// Take the current time, and remove the delay from it.
|
||||
final double cooldown = ess.getSettings().getTeleportCooldown();
|
||||
final Calendar earliestTime = new GregorianCalendar();
|
||||
earliestTime.add(Calendar.SECOND, -(int) cooldown);
|
||||
earliestTime.add(Calendar.MILLISECOND, -(int) ((cooldown * 1000.0) % 1000.0));
|
||||
// This value contains the most recent time a teleportPlayer could have been used that would allow another use.
|
||||
final long earliestLong = earliestTime.getTimeInMillis();
|
||||
|
||||
// When was the last teleportPlayer used?
|
||||
final long lastTime = teleportOwner.getLastTeleportTimestamp();
|
||||
|
||||
if (lastTime > time.getTimeInMillis()) {
|
||||
// This is to make sure time didn't get messed up on last teleportPlayer use.
|
||||
// If this happens, let's give the user the benifit of the doubt.
|
||||
teleportOwner.setLastTeleportTimestamp(time.getTimeInMillis());
|
||||
return false;
|
||||
} else if (lastTime > earliestLong
|
||||
&& cooldownApplies()) {
|
||||
time.setTimeInMillis(lastTime);
|
||||
time.add(Calendar.SECOND, (int) cooldown);
|
||||
time.add(Calendar.MILLISECOND, (int) ((cooldown * 1000.0) % 1000.0));
|
||||
future.completeExceptionally(new Exception(tl("timeBeforeTeleport", DateUtil.formatDateDiff(time.getTimeInMillis()))));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// if justCheck is set, don't update lastTeleport; we're just checking
|
||||
if (!check) {
|
||||
teleportOwner.setLastTeleportTimestamp(time.getTimeInMillis());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean cooldownApplies() {
|
||||
boolean applies = true;
|
||||
String globalBypassPerm = "essentials.teleport.cooldown.bypass";
|
||||
switch (tpType) {
|
||||
case NORMAL:
|
||||
applies = !teleportOwner.isAuthorized(globalBypassPerm);
|
||||
break;
|
||||
case BACK:
|
||||
applies = !(teleportOwner.isAuthorized(globalBypassPerm) &&
|
||||
teleportOwner.isAuthorized("essentials.teleport.cooldown.bypass.back"));
|
||||
break;
|
||||
case TPA:
|
||||
applies = !(teleportOwner.isAuthorized(globalBypassPerm) &&
|
||||
teleportOwner.isAuthorized("essentials.teleport.cooldown.bypass.tpa"));
|
||||
break;
|
||||
}
|
||||
return applies;
|
||||
}
|
||||
|
||||
private void warnUser(final IUser user, final double delay) {
|
||||
Calendar c = new GregorianCalendar();
|
||||
c.add(Calendar.SECOND, (int) delay);
|
||||
c.add(Calendar.MILLISECOND, (int) ((delay * 1000.0) % 1000.0));
|
||||
user.sendMessage(tl("dontMoveMessage", DateUtil.formatDateDiff(c.getTimeInMillis())));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void now(Location loc, boolean cooldown, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
if (cooldown && cooldown(false, future)) {
|
||||
return;
|
||||
}
|
||||
final ITarget target = new LocationTarget(loc);
|
||||
nowAsync(teleportOwner, target, cause, future);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void now(Player entity, boolean cooldown, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
if (cooldown && cooldown(false, future)) {
|
||||
future.complete(false);
|
||||
return;
|
||||
}
|
||||
final ITarget target = new PlayerTarget(entity);
|
||||
nowAsync(teleportOwner, target, cause, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void runOnMain(Runnable runnable) throws ExecutionException, InterruptedException {
|
||||
if (Bukkit.isPrimaryThread()) {
|
||||
runnable.run();
|
||||
return;
|
||||
}
|
||||
CompletableFuture<Object> taskLock = new CompletableFuture<>();
|
||||
Bukkit.getScheduler().runTask(ess, () -> {
|
||||
runnable.run();
|
||||
taskLock.complete(new Object());
|
||||
});
|
||||
taskLock.get();
|
||||
}
|
||||
|
||||
protected void nowAsync(IUser teleportee, ITarget target, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
cancel(false);
|
||||
|
||||
UserTeleportEvent event = new UserTeleportEvent(teleportee, cause, target.getLocation());
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
teleportee.setLastLocation();
|
||||
|
||||
if (!teleportee.getBase().isEmpty()) {
|
||||
if (!ess.getSettings().isTeleportPassengerDismount()) {
|
||||
future.completeExceptionally(new Exception(tl("passengerTeleportFail")));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
runOnMain(() -> teleportee.getBase().eject()); //EntityDismountEvent requires a sync context.
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
future.completeExceptionally(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
teleportee.setLastLocation();
|
||||
PaperLib.getChunkAtAsync(target.getLocation()).thenAccept(chunk -> {
|
||||
Location loc = target.getLocation();
|
||||
if (LocationUtil.isBlockUnsafeForUser(teleportee, chunk.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
|
||||
if (ess.getSettings().isTeleportSafetyEnabled()) {
|
||||
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
||||
//The chunk we're teleporting to is 100% going to be loaded here, no need to teleport async.
|
||||
teleportee.getBase().teleport(loc, cause);
|
||||
} else {
|
||||
try {
|
||||
//There's a chance the safer location is outside the loaded chunk so still teleport async here.
|
||||
PaperLib.teleportAsync(teleportee.getBase(), LocationUtil.getSafeDestination(ess, teleportee, loc), cause);
|
||||
} catch (Exception e) {
|
||||
future.completeExceptionally(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
future.completeExceptionally(new Exception(tl("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (ess.getSettings().isForceDisableTeleportSafety()) {
|
||||
//The chunk we're teleporting to is 100% going to be loaded here, no need to teleport async.
|
||||
teleportee.getBase().teleport(loc, cause);
|
||||
} else {
|
||||
if (ess.getSettings().isTeleportToCenterLocation()) {
|
||||
loc = LocationUtil.getRoundedDestination(loc);
|
||||
}
|
||||
//There's a *small* chance the rounded destination produces a location outside the loaded chunk so still teleport async here.
|
||||
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
|
||||
}
|
||||
}
|
||||
future.complete(true);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleport(Location loc, Trade chargeFor, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
teleport(teleportOwner, new LocationTarget(loc), chargeFor, cause, future);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleport(Player entity, Trade chargeFor, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
teleportOwner.sendMessage(tl("teleportToPlayer", entity.getDisplayName()));
|
||||
teleport(teleportOwner, new PlayerTarget(entity), chargeFor, cause, future);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleportPlayer(IUser otherUser, Location loc, Trade chargeFor, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
teleport(otherUser, new LocationTarget(loc), chargeFor, cause, future);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teleportPlayer(IUser otherUser, Player entity, Trade chargeFor, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
ITarget target = new PlayerTarget(entity);
|
||||
teleport(otherUser, target, chargeFor, cause, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
otherUser.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
|
||||
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void teleport(IUser teleportee, ITarget target, Trade chargeFor, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
double delay = ess.getSettings().getTeleportDelay();
|
||||
|
||||
Trade cashCharge = chargeFor;
|
||||
|
||||
if (chargeFor != null) {
|
||||
chargeFor.isAffordableFor(teleportOwner, future);
|
||||
if (future.isCompletedExceptionally()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
|
||||
if (!chargeFor.getCommandCost(teleportOwner).equals(BigDecimal.ZERO)) {
|
||||
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
|
||||
cashCharge = new Trade(chargeFor.getCommandCost(teleportOwner), ess);
|
||||
}
|
||||
}
|
||||
|
||||
if (cooldown(true, future)) {
|
||||
return;
|
||||
}
|
||||
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass") || teleportee.isAuthorized("essentials.teleport.timer.bypass")) {
|
||||
if (cooldown(false, future)) {
|
||||
return;
|
||||
}
|
||||
nowAsync(teleportee, target, cause, future);
|
||||
if (cashCharge != null) {
|
||||
cashCharge.charge(teleportOwner, future);
|
||||
if (future.isCompletedExceptionally()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
cancel(false);
|
||||
warnUser(teleportee, delay);
|
||||
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
|
||||
}
|
||||
|
||||
private void teleportOther(IUser teleporter, IUser teleportee, ITarget target, Trade chargeFor, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
double delay = ess.getSettings().getTeleportDelay();
|
||||
|
||||
Trade cashCharge = chargeFor;
|
||||
|
||||
if (teleporter != null && chargeFor != null) {
|
||||
chargeFor.isAffordableFor(teleporter, future);
|
||||
if (future.isCompletedExceptionally()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//This code is to make sure that commandcosts are checked in the initial world, and not in the resulting world.
|
||||
if (!chargeFor.getCommandCost(teleporter).equals(BigDecimal.ZERO)) {
|
||||
//By converting a command cost to a regular cost, the command cost permission isn't checked when executing the charge after teleport.
|
||||
cashCharge = new Trade(chargeFor.getCommandCost(teleporter), ess);
|
||||
}
|
||||
}
|
||||
|
||||
if (cooldown(true, future)) {
|
||||
return;
|
||||
}
|
||||
if (delay <= 0 || teleporter == null
|
||||
|| teleporter.isAuthorized("essentials.teleport.timer.bypass")
|
||||
|| teleportOwner.isAuthorized("essentials.teleport.timer.bypass")
|
||||
|| teleportee.isAuthorized("essentials.teleport.timer.bypass")) {
|
||||
if (cooldown(false, future)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nowAsync(teleportee, target, cause, future);
|
||||
if (teleporter != null && cashCharge != null) {
|
||||
cashCharge.charge(teleporter, future);
|
||||
if (future.isCompletedExceptionally()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
cancel(false);
|
||||
warnUser(teleportee, delay);
|
||||
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void respawn(Trade chargeFor, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
double delay = ess.getSettings().getTeleportDelay();
|
||||
if (chargeFor != null) {
|
||||
chargeFor.isAffordableFor(teleportOwner, future);
|
||||
if (future.isCompletedExceptionally()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (cooldown(true, future)) {
|
||||
return;
|
||||
}
|
||||
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass")) {
|
||||
if (cooldown(false, future)) {
|
||||
return;
|
||||
}
|
||||
respawnNow(teleportOwner, cause, future);
|
||||
if (chargeFor != null) {
|
||||
chargeFor.charge(teleportOwner, future);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
cancel(false);
|
||||
warnUser(teleportOwner, delay);
|
||||
initTimer((long) (delay * 1000.0), teleportOwner, null, chargeFor, cause, true);
|
||||
}
|
||||
|
||||
void respawnNow(IUser teleportee, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
final Player player = teleportee.getBase();
|
||||
Location bed = player.getBedSpawnLocation();
|
||||
if (bed != null) {
|
||||
nowAsync(teleportee, new LocationTarget(bed), cause, future);
|
||||
} else {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Could not find bed spawn, forcing respawn event.");
|
||||
}
|
||||
final PlayerRespawnEvent pre = new PlayerRespawnEvent(player, player.getWorld().getSpawnLocation(), false);
|
||||
ess.getServer().getPluginManager().callEvent(pre);
|
||||
nowAsync(teleportee, new LocationTarget(pre.getRespawnLocation()), cause, future);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warp(IUser otherUser, String warp, Trade chargeFor, TeleportCause cause, CompletableFuture<Boolean> future) {
|
||||
UserWarpEvent event = new UserWarpEvent(otherUser, warp, chargeFor);
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
warp = event.getWarp();
|
||||
Location loc;
|
||||
try {
|
||||
loc = ess.getWarps().getWarp(warp);
|
||||
} catch (WarpNotFoundException | InvalidWorldException e) {
|
||||
future.completeExceptionally(e);
|
||||
return;
|
||||
}
|
||||
otherUser.sendMessage(tl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
if (!otherUser.equals(teleportOwner)) {
|
||||
teleportOwner.sendMessage(tl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
}
|
||||
teleport(otherUser, new LocationTarget(loc), chargeFor, cause, future);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void back(Trade chargeFor, CompletableFuture<Boolean> future) {
|
||||
back(teleportOwner, chargeFor, future);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void back(IUser teleporter, Trade chargeFor, CompletableFuture<Boolean> future) {
|
||||
tpType = TeleportType.BACK;
|
||||
final Location loc = teleportOwner.getLastLocation();
|
||||
teleportOwner.sendMessage(tl("backUsageMsg", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
teleportOther(teleporter, teleportOwner, new LocationTarget(loc), chargeFor, TeleportCause.COMMAND, future);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void back(CompletableFuture<Boolean> future) {
|
||||
nowAsync(teleportOwner, new LocationTarget(teleportOwner.getLastLocation()), TeleportCause.COMMAND, future);
|
||||
}
|
||||
|
||||
public void setTpType(TeleportType tpType) {
|
||||
this.tpType = tpType;
|
||||
}
|
||||
|
||||
//If we need to cancelTimer a pending teleportPlayer call this method
|
||||
private void cancel(boolean notifyUser) {
|
||||
if (timedTeleport != null) {
|
||||
timedTeleport.cancelTimer(notifyUser);
|
||||
timedTeleport = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void initTimer(long delay, IUser teleportUser, ITarget target, Trade chargeFor, TeleportCause cause, boolean respawn) {
|
||||
timedTeleport = new AsyncTimedTeleport(teleportOwner, ess, this, delay, teleportUser, target, chargeFor, cause, respawn);
|
||||
}
|
||||
}
|
151
Essentials/src/com/earth2me/essentials/AsyncTimedTeleport.java
Normal file
151
Essentials/src/com/earth2me/essentials/AsyncTimedTeleport.java
Normal file
@ -0,0 +1,151 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IUser;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
public class AsyncTimedTeleport implements Runnable {
|
||||
private static final double MOVE_CONSTANT = 0.3;
|
||||
private final IUser teleportOwner;
|
||||
private final IEssentials ess;
|
||||
private final AsyncTeleport teleport;
|
||||
private final UUID timer_teleportee;
|
||||
private int timer_task;
|
||||
private final long timer_started; // time this task was initiated
|
||||
private final long timer_delay; // how long to delay the teleportPlayer
|
||||
private double timer_health;
|
||||
// note that I initially stored a clone of the location for reference, but...
|
||||
// when comparing locations, I got incorrect mismatches (rounding errors, looked like)
|
||||
// so, the X/Y/Z values are stored instead and rounded off
|
||||
private final long timer_initX;
|
||||
private final long timer_initY;
|
||||
private final long timer_initZ;
|
||||
private final ITarget timer_teleportTarget;
|
||||
private final boolean timer_respawn;
|
||||
private final boolean timer_canMove;
|
||||
private final Trade timer_chargeFor;
|
||||
private final TeleportCause timer_cause;
|
||||
|
||||
AsyncTimedTeleport(IUser user, IEssentials ess, AsyncTeleport teleport, long delay, IUser teleportUser, ITarget target, Trade chargeFor, TeleportCause cause, boolean respawn) {
|
||||
this.teleportOwner = user;
|
||||
this.ess = ess;
|
||||
this.teleport = teleport;
|
||||
this.timer_started = System.currentTimeMillis();
|
||||
this.timer_delay = delay;
|
||||
this.timer_health = teleportUser.getBase().getHealth();
|
||||
this.timer_initX = Math.round(teleportUser.getBase().getLocation().getX() * MOVE_CONSTANT);
|
||||
this.timer_initY = Math.round(teleportUser.getBase().getLocation().getY() * MOVE_CONSTANT);
|
||||
this.timer_initZ = Math.round(teleportUser.getBase().getLocation().getZ() * MOVE_CONSTANT);
|
||||
this.timer_teleportee = teleportUser.getBase().getUniqueId();
|
||||
this.timer_teleportTarget = target;
|
||||
this.timer_chargeFor = chargeFor;
|
||||
this.timer_cause = cause;
|
||||
this.timer_respawn = respawn;
|
||||
this.timer_canMove = user.isAuthorized("essentials.teleport.timer.move");
|
||||
|
||||
timer_task = ess.runTaskTimerAsynchronously(this, 20, 20).getTaskId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (teleportOwner == null || !teleportOwner.getBase().isOnline() || teleportOwner.getBase().getLocation() == null) {
|
||||
cancelTimer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final IUser teleportUser = ess.getUser(this.timer_teleportee);
|
||||
|
||||
if (teleportUser == null || !teleportUser.getBase().isOnline()) {
|
||||
cancelTimer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
final Location currLocation = teleportUser.getBase().getLocation();
|
||||
if (currLocation == null) {
|
||||
cancelTimer(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!timer_canMove && (Math.round(currLocation.getX() * MOVE_CONSTANT) != timer_initX || Math.round(currLocation.getY() * MOVE_CONSTANT) != timer_initY || Math.round(currLocation.getZ() * MOVE_CONSTANT) != timer_initZ || teleportUser.getBase().getHealth() < timer_health)) {
|
||||
// user moved, cancelTimer teleportPlayer
|
||||
cancelTimer(true);
|
||||
return;
|
||||
}
|
||||
|
||||
class DelayedTeleportTask implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
timer_health = teleportUser.getBase().getHealth(); // in case user healed, then later gets injured
|
||||
final long now = System.currentTimeMillis();
|
||||
if (now > timer_started + timer_delay) {
|
||||
try {
|
||||
teleport.cooldown(false);
|
||||
} catch (Throwable ex) {
|
||||
teleportOwner.sendMessage(tl("cooldownWithMessage", ex.getMessage()));
|
||||
if (teleportOwner != teleportUser) {
|
||||
teleportUser.sendMessage(tl("cooldownWithMessage", ex.getMessage()));
|
||||
}
|
||||
}
|
||||
try {
|
||||
cancelTimer(false);
|
||||
teleportUser.sendMessage(tl("teleportationCommencing"));
|
||||
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
future.exceptionally(e -> {
|
||||
ess.showError(teleportOwner.getSource(), e, "\\ teleport");
|
||||
return false;
|
||||
});
|
||||
if (timer_chargeFor != null) {
|
||||
timer_chargeFor.isAffordableFor(teleportOwner);
|
||||
}
|
||||
if (timer_respawn) {
|
||||
teleport.respawnNow(teleportUser, timer_cause, future);
|
||||
} else {
|
||||
teleport.nowAsync(teleportUser, timer_teleportTarget, timer_cause, future);
|
||||
}
|
||||
future.thenAccept(success -> {
|
||||
if (timer_chargeFor != null) {
|
||||
try {
|
||||
timer_chargeFor.charge(teleportOwner);
|
||||
} catch (ChargeException ex) {
|
||||
ess.showError(teleportOwner.getSource(), ex, "\\ teleport");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception ex) {
|
||||
ess.showError(teleportOwner.getSource(), ex, "\\ teleport");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ess.scheduleSyncDelayedTask(new DelayedTeleportTask());
|
||||
}
|
||||
|
||||
//If we need to cancelTimer a pending teleportPlayer call this method
|
||||
void cancelTimer(boolean notifyUser) {
|
||||
if (timer_task == -1) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ess.getServer().getScheduler().cancelTask(timer_task);
|
||||
if (notifyUser) {
|
||||
teleportOwner.sendMessage(tl("pendingTeleportCancelled"));
|
||||
if (timer_teleportee != null && !timer_teleportee.equals(teleportOwner.getBase().getUniqueId())) {
|
||||
ess.getUser(timer_teleportee).sendMessage(tl("pendingTeleportCancelled"));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
timer_task = -1;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.earth2me.essentials;
|
||||
|
||||
import com.earth2me.essentials.api.IAsyncTeleport;
|
||||
import com.earth2me.essentials.commands.IEssentialsCommand;
|
||||
import net.ess3.api.ITeleport;
|
||||
import net.ess3.api.MaxMoneyException;
|
||||
@ -54,8 +55,14 @@ public interface IUser {
|
||||
*/
|
||||
boolean hasOutstandingTeleportRequest();
|
||||
|
||||
/**
|
||||
* @deprecated This API is not asynchronous. Use {@link com.earth2me.essentials.api.IAsyncTeleport IAsyncTeleport} with {@link IUser#getAsyncTeleport()}
|
||||
*/
|
||||
@Deprecated
|
||||
ITeleport getTeleport();
|
||||
|
||||
IAsyncTeleport getAsyncTeleport();
|
||||
|
||||
BigDecimal getMoney();
|
||||
|
||||
void setMoney(final BigDecimal value) throws MaxMoneyException;
|
||||
|
@ -22,6 +22,7 @@ import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -116,7 +117,11 @@ public class Jails extends AsyncStorageObjectHolder<com.earth2me.essentials.sett
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method does not use asynchronous teleportation. Use {@link Jails#sendToJail(IUser, String, CompletableFuture)}
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public void sendToJail(final IUser user, final String jail) throws Exception {
|
||||
acquireReadLock();
|
||||
try {
|
||||
@ -130,6 +135,24 @@ public class Jails extends AsyncStorageObjectHolder<com.earth2me.essentials.sett
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendToJail(IUser user, String jail, CompletableFuture<Boolean> future) throws Exception {
|
||||
acquireReadLock();
|
||||
try {
|
||||
if (user.getBase().isOnline()) {
|
||||
Location loc = getJail(jail);
|
||||
user.getAsyncTeleport().now(loc, false, TeleportCause.COMMAND, future);
|
||||
future.thenAccept(success -> {
|
||||
user.setJail(jail);
|
||||
});
|
||||
return;
|
||||
}
|
||||
user.setJail(jail);
|
||||
} finally {
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setJail(final String jailName, final Location loc) throws Exception {
|
||||
acquireWriteLock();
|
||||
@ -254,16 +277,22 @@ public class Jails extends AsyncStorageObjectHolder<com.earth2me.essentials.sett
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
sendToJail(user, user.getJail());
|
||||
} catch (Exception ex) {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
future.exceptionally(ex -> {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()), ex);
|
||||
} else {
|
||||
LOGGER.log(Level.INFO, tl("returnPlayerToJailError", user.getName(), ex.getLocalizedMessage()));
|
||||
}
|
||||
return false;
|
||||
});
|
||||
future.thenAccept(success -> user.sendMessage(tl("jailMessage")));
|
||||
|
||||
try {
|
||||
sendToJail(user, user.getJail(), future);
|
||||
} catch (Exception ex) {
|
||||
future.completeExceptionally(ex);
|
||||
}
|
||||
user.sendMessage(tl("jailMessage"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,10 @@ import java.util.GregorianCalendar;
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated This API is not asynchronous. Use {@link com.earth2me.essentials.AsyncTeleport AsyncTeleport}
|
||||
*/
|
||||
@Deprecated
|
||||
public class Teleport implements ITeleport {
|
||||
private final IUser teleportOwner;
|
||||
private final IEssentials ess;
|
||||
@ -28,6 +32,7 @@ public class Teleport implements ITeleport {
|
||||
|
||||
private TeleportType tpType;
|
||||
|
||||
@Deprecated
|
||||
public Teleport(IUser user, IEssentials ess) {
|
||||
this.teleportOwner = user;
|
||||
this.ess = ess;
|
||||
@ -40,6 +45,7 @@ public class Teleport implements ITeleport {
|
||||
NORMAL
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void cooldown(boolean check) throws Exception {
|
||||
final Calendar time = new GregorianCalendar();
|
||||
if (teleportOwner.getLastTeleportTimestamp() > 0) {
|
||||
@ -73,6 +79,7 @@ public class Teleport implements ITeleport {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private boolean cooldownApplies() {
|
||||
boolean applies = true;
|
||||
String globalBypassPerm = "essentials.teleport.cooldown.bypass";
|
||||
@ -92,6 +99,7 @@ public class Teleport implements ITeleport {
|
||||
return applies;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void warnUser(final IUser user, final double delay) {
|
||||
Calendar c = new GregorianCalendar();
|
||||
c.add(Calendar.SECOND, (int) delay);
|
||||
@ -101,6 +109,7 @@ public class Teleport implements ITeleport {
|
||||
|
||||
//The now function is used when you want to skip tp delay when teleporting someone to a location or player.
|
||||
@Override
|
||||
@Deprecated
|
||||
public void now(Location loc, boolean cooldown, TeleportCause cause) throws Exception {
|
||||
if (cooldown) {
|
||||
cooldown(false);
|
||||
@ -110,6 +119,7 @@ public class Teleport implements ITeleport {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void now(Player entity, boolean cooldown, TeleportCause cause) throws Exception {
|
||||
if (cooldown) {
|
||||
cooldown(false);
|
||||
@ -119,6 +129,7 @@ public class Teleport implements ITeleport {
|
||||
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected void now(IUser teleportee, ITarget target, TeleportCause cause) throws Exception {
|
||||
cancel(false);
|
||||
Location loc = target.getLocation();
|
||||
@ -171,12 +182,14 @@ public class Teleport implements ITeleport {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void teleport(Location loc, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
teleport(teleportOwner, new LocationTarget(loc), chargeFor, cause);
|
||||
}
|
||||
|
||||
//This is used when teleporting to a player
|
||||
@Override
|
||||
@Deprecated
|
||||
public void teleport(Player entity, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
ITarget target = new PlayerTarget(entity);
|
||||
teleportOwner.sendMessage(tl("teleportToPlayer", entity.getDisplayName()));
|
||||
@ -185,12 +198,14 @@ public class Teleport implements ITeleport {
|
||||
|
||||
//This is used when teleporting to stored location
|
||||
@Override
|
||||
@Deprecated
|
||||
public void teleportPlayer(IUser teleportee, Location loc, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
teleport(teleportee, new LocationTarget(loc), chargeFor, cause);
|
||||
}
|
||||
|
||||
//This is used on /tphere
|
||||
@Override
|
||||
@Deprecated
|
||||
public void teleportPlayer(IUser teleportee, Player entity, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
ITarget target = new PlayerTarget(entity);
|
||||
teleport(teleportee, target, chargeFor, cause);
|
||||
@ -198,6 +213,7 @@ public class Teleport implements ITeleport {
|
||||
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void teleport(IUser teleportee, ITarget target, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
double delay = ess.getSettings().getTeleportDelay();
|
||||
|
||||
@ -228,6 +244,7 @@ public class Teleport implements ITeleport {
|
||||
initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void teleportOther(IUser teleporter, IUser teleportee, ITarget target, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
double delay = ess.getSettings().getTeleportDelay();
|
||||
|
||||
@ -263,6 +280,7 @@ public class Teleport implements ITeleport {
|
||||
|
||||
//The respawn function is a wrapper used to handle tp fallback, on /jail and /home
|
||||
@Override
|
||||
@Deprecated
|
||||
public void respawn(final Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
double delay = ess.getSettings().getTeleportDelay();
|
||||
if (chargeFor != null) {
|
||||
@ -283,6 +301,7 @@ public class Teleport implements ITeleport {
|
||||
initTimer((long) (delay * 1000.0), teleportOwner, null, chargeFor, cause, true);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
void respawnNow(IUser teleportee, TeleportCause cause) throws Exception {
|
||||
final Player player = teleportee.getBase();
|
||||
Location bed = player.getBedSpawnLocation();
|
||||
@ -300,6 +319,7 @@ public class Teleport implements ITeleport {
|
||||
|
||||
//The warp function is a wrapper used to teleportPlayer a player to a /warp
|
||||
@Override
|
||||
@Deprecated
|
||||
public void warp(IUser teleportee, String warp, Trade chargeFor, TeleportCause cause) throws Exception {
|
||||
UserWarpEvent event = new UserWarpEvent(teleportee, warp, chargeFor);
|
||||
Bukkit.getServer().getPluginManager().callEvent(event);
|
||||
@ -318,12 +338,14 @@ public class Teleport implements ITeleport {
|
||||
|
||||
//The back function is a wrapper used to teleportPlayer a player /back to their previous location.
|
||||
@Override
|
||||
@Deprecated
|
||||
public void back(Trade chargeFor) throws Exception {
|
||||
back(teleportOwner, chargeFor);
|
||||
}
|
||||
|
||||
//This function is a wrapper over the other back function for cases where another player performs back for them
|
||||
@Override
|
||||
@Deprecated
|
||||
public void back(IUser teleporter, Trade chargeFor) throws Exception {
|
||||
tpType = TeleportType.BACK;
|
||||
final Location loc = teleportOwner.getLastLocation();
|
||||
@ -333,15 +355,18 @@ public class Teleport implements ITeleport {
|
||||
|
||||
//This function is used to throw a user back after a jail sentence
|
||||
@Override
|
||||
@Deprecated
|
||||
public void back() throws Exception {
|
||||
now(teleportOwner, new LocationTarget(teleportOwner.getLastLocation()), TeleportCause.COMMAND);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setTpType(TeleportType tpType) {
|
||||
this.tpType = tpType;
|
||||
}
|
||||
|
||||
//If we need to cancelTimer a pending teleportPlayer call this method
|
||||
@Deprecated
|
||||
private void cancel(boolean notifyUser) {
|
||||
if (timedTeleport != null) {
|
||||
timedTeleport.cancelTimer(notifyUser);
|
||||
@ -349,6 +374,7 @@ public class Teleport implements ITeleport {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void initTimer(long delay, IUser teleportUser, ITarget target, Trade chargeFor, TeleportCause cause, boolean respawn) {
|
||||
timedTeleport = new TimedTeleport(teleportOwner, ess, this, delay, teleportUser, target, chargeFor, cause, respawn);
|
||||
}
|
||||
|
@ -98,19 +98,17 @@ public class TimedTeleport implements Runnable {
|
||||
cancelTimer(false);
|
||||
teleportUser.sendMessage(tl("teleportationCommencing"));
|
||||
|
||||
try {
|
||||
if (timer_chargeFor != null) {
|
||||
timer_chargeFor.isAffordableFor(teleportOwner);
|
||||
}
|
||||
if (timer_respawn) {
|
||||
teleport.respawnNow(teleportUser, timer_cause);
|
||||
} else {
|
||||
teleport.now(teleportUser, timer_teleportTarget, timer_cause);
|
||||
}
|
||||
if (timer_chargeFor != null) {
|
||||
timer_chargeFor.charge(teleportOwner);
|
||||
}
|
||||
} catch (Exception ignored) {}
|
||||
if (timer_chargeFor != null) {
|
||||
timer_chargeFor.isAffordableFor(teleportOwner);
|
||||
}
|
||||
if (timer_respawn) {
|
||||
teleport.respawnNow(teleportUser, timer_cause);
|
||||
} else {
|
||||
teleport.now(teleportUser, timer_teleportTarget, timer_cause);
|
||||
}
|
||||
if (timer_chargeFor != null) {
|
||||
timer_chargeFor.charge(teleportOwner);
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
ess.showError(teleportOwner.getSource(), ex, "\\ teleport");
|
||||
|
@ -18,6 +18,8 @@ import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -81,26 +83,43 @@ public class Trade {
|
||||
}
|
||||
|
||||
public void isAffordableFor(final IUser user) throws ChargeException {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
isAffordableFor(user, future);
|
||||
if (future.isCompletedExceptionally()) {
|
||||
try {
|
||||
future.get();
|
||||
} catch (InterruptedException e) { //If this happens, we have bigger problems...
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
throw (ChargeException) e.getCause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void isAffordableFor(final IUser user, CompletableFuture<Boolean> future) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "checking if " + user.getName() + " can afford charge.");
|
||||
}
|
||||
|
||||
if (getMoney() != null && getMoney().signum() > 0 && !user.canAfford(getMoney())) {
|
||||
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)));
|
||||
future.completeExceptionally(new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess))));
|
||||
return;
|
||||
}
|
||||
|
||||
if (getItemStack() != null && !user.getBase().getInventory().containsAtLeast(itemStack, itemStack.getAmount())) {
|
||||
throw new ChargeException(tl("missingItems", getItemStack().getAmount(), ess.getItemDb().name(getItemStack())));
|
||||
future.completeExceptionally(new ChargeException(tl("missingItems", getItemStack().getAmount(), ess.getItemDb().name(getItemStack()))));
|
||||
return;
|
||||
}
|
||||
|
||||
BigDecimal money;
|
||||
if (command != null && !command.isEmpty() && (money = getCommandCost(user)).signum() > 0 && !user.canAfford(money)) {
|
||||
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(money, ess)));
|
||||
future.completeExceptionally(new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(money, ess))));
|
||||
return;
|
||||
}
|
||||
|
||||
if (exp != null && exp > 0 && SetExpFix.getTotalExperience(user.getBase()) < exp) {
|
||||
throw new ChargeException(tl("notEnoughExperience"));
|
||||
future.completeExceptionally(new ChargeException(tl("notEnoughExperience")));
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,6 +194,20 @@ public class Trade {
|
||||
}
|
||||
|
||||
public void charge(final IUser user) throws ChargeException {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
charge(user, future);
|
||||
if (future.isCompletedExceptionally()) {
|
||||
try {
|
||||
future.get();
|
||||
} catch (InterruptedException e) { //If this happens, we have bigger problems...
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
throw (ChargeException) e.getCause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void charge(final IUser user, CompletableFuture<Boolean> future) {
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().log(Level.INFO, "attempting to charge user " + user.getName());
|
||||
}
|
||||
@ -183,7 +216,8 @@ public class Trade {
|
||||
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " money " + getMoney().toPlainString());
|
||||
}
|
||||
if (!user.canAfford(getMoney()) && getMoney().signum() > 0) {
|
||||
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess)));
|
||||
future.completeExceptionally(new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(getMoney(), ess))));
|
||||
return;
|
||||
}
|
||||
user.takeMoney(getMoney());
|
||||
}
|
||||
@ -192,7 +226,8 @@ public class Trade {
|
||||
ess.getLogger().log(Level.INFO, "charging user " + user.getName() + " itemstack " + getItemStack().toString());
|
||||
}
|
||||
if (!user.getBase().getInventory().containsAtLeast(getItemStack(), getItemStack().getAmount())) {
|
||||
throw new ChargeException(tl("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " ")));
|
||||
future.completeExceptionally(new ChargeException(tl("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " "))));
|
||||
return;
|
||||
}
|
||||
user.getBase().getInventory().removeItem(getItemStack());
|
||||
user.getBase().updateInventory();
|
||||
@ -200,7 +235,8 @@ public class Trade {
|
||||
if (command != null) {
|
||||
final BigDecimal cost = getCommandCost(user);
|
||||
if (!user.canAfford(cost) && cost.signum() > 0) {
|
||||
throw new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(cost, ess)));
|
||||
future.completeExceptionally(new ChargeException(tl("notEnoughMoney", NumberUtil.displayCurrency(cost, ess))));
|
||||
return;
|
||||
}
|
||||
user.takeMoney(cost);
|
||||
}
|
||||
@ -210,7 +246,8 @@ public class Trade {
|
||||
}
|
||||
final int experience = SetExpFix.getTotalExperience(user.getBase());
|
||||
if (experience < getExperience() && getExperience() > 0) {
|
||||
throw new ChargeException(tl("notEnoughExperience"));
|
||||
future.completeExceptionally(new ChargeException(tl("notEnoughExperience")));
|
||||
return;
|
||||
}
|
||||
SetExpFix.setTotalExperience(user.getBase(), experience - getExperience());
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ import net.ess3.api.events.JailStatusChangeEvent;
|
||||
import net.ess3.api.events.MuteStatusChangeEvent;
|
||||
import net.ess3.api.events.UserBalanceUpdateEvent;
|
||||
import net.ess3.nms.refl.ReflUtil;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -29,6 +28,7 @@ import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -42,7 +42,8 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
private transient boolean teleportRequestHere;
|
||||
private transient Location teleportLocation;
|
||||
private transient boolean vanished;
|
||||
private transient final Teleport teleport;
|
||||
private transient final AsyncTeleport teleport;
|
||||
private transient final Teleport legacyTeleport;
|
||||
private transient long teleportRequestTime;
|
||||
private transient long lastOnlineActivity;
|
||||
private transient long lastThrottledAction;
|
||||
@ -63,7 +64,8 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
|
||||
public User(final Player base, final IEssentials ess) {
|
||||
super(base, ess);
|
||||
teleport = new Teleport(this, ess);
|
||||
teleport = new AsyncTeleport(this, ess);
|
||||
legacyTeleport = new Teleport(this, ess);
|
||||
if (isAfk()) {
|
||||
afkPosition = this.getLocation();
|
||||
}
|
||||
@ -401,10 +403,19 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
}
|
||||
|
||||
@Override
|
||||
public Teleport getTeleport() {
|
||||
public AsyncTeleport getAsyncTeleport() {
|
||||
return teleport;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This API is not asynchronous. Use {@link User#getAsyncTeleport()}
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
public Teleport getTeleport() {
|
||||
return legacyTeleport;
|
||||
}
|
||||
|
||||
public long getLastOnlineActivity() {
|
||||
return lastOnlineActivity;
|
||||
}
|
||||
@ -567,14 +578,12 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
|
||||
sendMessage(tl("haveBeenReleased"));
|
||||
setJail(null);
|
||||
if (ess.getSettings().isTeleportBackWhenFreedFromJail()) {
|
||||
try {
|
||||
getTeleport().back();
|
||||
} catch (Exception ex) {
|
||||
try {
|
||||
getTeleport().respawn(null, TeleportCause.PLUGIN);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
getAsyncTeleport().back(future);
|
||||
future.exceptionally(e -> {
|
||||
getAsyncTeleport().respawn(null, TeleportCause.PLUGIN, new CompletableFuture<>());
|
||||
return false;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
123
Essentials/src/com/earth2me/essentials/api/IAsyncTeleport.java
Normal file
123
Essentials/src/com/earth2me/essentials/api/IAsyncTeleport.java
Normal file
@ -0,0 +1,123 @@
|
||||
package com.earth2me.essentials.api;
|
||||
|
||||
import com.earth2me.essentials.Trade;
|
||||
import net.ess3.api.IUser;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
||||
public interface IAsyncTeleport {
|
||||
|
||||
/**
|
||||
* Used to skip teleportPlayer delay when teleporting someone to a location or player.
|
||||
*
|
||||
* @param loc - Where should the player end up
|
||||
* @param cooldown - If cooldown should be enforced
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void now(Location loc, boolean cooldown, PlayerTeleportEvent.TeleportCause cause, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Used to skip teleportPlayer delay when teleporting someone to a location or player.
|
||||
*
|
||||
* @param entity - Where should the player end up
|
||||
* @param cooldown - If cooldown should be enforced
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void now(Player entity, boolean cooldown, PlayerTeleportEvent.TeleportCause cause, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Teleport a player to a specific location
|
||||
*
|
||||
* @param loc - Where should the player end up
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause.
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void teleport(Location loc, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Teleport a player to a specific player
|
||||
*
|
||||
* @param entity - Where should the player end up
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void teleport(Player entity, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Teleport a player to a specific location
|
||||
*
|
||||
* @param otherUser - Which user will be teleported
|
||||
* @param loc - Where should the player end up
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void teleportPlayer(IUser otherUser, Location loc, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Teleport a player to a specific player
|
||||
*
|
||||
* @param otherUser - Which user will be teleported
|
||||
* @param entity - Where should the player end up
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void teleportPlayer(IUser otherUser, Player entity, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Teleport wrapper used to handle tp fallback on /jail and /home
|
||||
*
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void respawn(final Trade chargeFor, PlayerTeleportEvent.TeleportCause cause, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Teleport wrapper used to handle /warp teleports
|
||||
*
|
||||
* @param otherUser - Which user will be teleported
|
||||
* @param warp - The name of the warp the user will be teleported too.
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param cause - The reported teleportPlayer cause
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void warp(IUser otherUser, String warp, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Teleport wrapper used to handle /back teleports
|
||||
*
|
||||
* @param chargeFor - What the user will be charged if teleportPlayer is successful
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void back(Trade chargeFor, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Teleport wrapper used to handle /back teleports that
|
||||
* are executed by a different player with this
|
||||
* instance of teleport as a target.
|
||||
*
|
||||
* @param teleporter - The user performing the /back command.
|
||||
* This value may be {@code null} to indicate console.
|
||||
* @param chargeFor - What the {@code teleporter} will be charged if teleportPlayer is successful
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void back(IUser teleporter, Trade chargeFor, CompletableFuture<Boolean> future);
|
||||
|
||||
/**
|
||||
* Teleport wrapper used to handle throwing user home after a jail sentence
|
||||
*
|
||||
* @param future - Future which is completed with the success status of the execution
|
||||
*/
|
||||
void back(CompletableFuture<Boolean> future);
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ import net.ess3.api.IUser;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
||||
public interface IJails extends IReload {
|
||||
@ -46,13 +47,27 @@ public interface IJails extends IReload {
|
||||
/**
|
||||
* Attempts to send the given user to the given jail
|
||||
*
|
||||
* @deprecated Use {@link IJails#sendToJail(IUser, String, CompletableFuture)}
|
||||
*
|
||||
* @param user the user to send to jail
|
||||
* @param jail the jail to send the user to
|
||||
*
|
||||
* @throws Exception if the user is offline or jail does not exist
|
||||
*/
|
||||
@Deprecated
|
||||
void sendToJail(IUser user, String jail) throws Exception;
|
||||
|
||||
/**
|
||||
* Attempts to send the given user to the given jail
|
||||
*
|
||||
* @param user the user to send to jail
|
||||
* @param jail the jail to send the user to
|
||||
* @param future Future which is completed with the success status of the execution
|
||||
*
|
||||
* @throws Exception if the user is offline or jail does not exist
|
||||
*/
|
||||
void sendToJail(IUser user, String jail, CompletableFuture<Boolean> future) throws Exception;
|
||||
|
||||
/**
|
||||
* Set a new jail with the given name and location
|
||||
*
|
||||
|
@ -7,6 +7,9 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated This API is not asynchronous. Use {@link com.earth2me.essentials.api.IAsyncTeleport IAsyncTeleport}
|
||||
*/
|
||||
public interface ITeleport {
|
||||
/**
|
||||
* Used to skip teleportPlayer delay when teleporting someone to a location or player.
|
||||
@ -17,6 +20,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void now(Location loc, boolean cooldown, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
/**
|
||||
@ -28,6 +32,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void now(Player entity, boolean cooldown, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
@Deprecated
|
||||
@ -42,6 +47,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void teleport(Location loc, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
/**
|
||||
@ -53,6 +59,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void teleport(Player entity, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
/**
|
||||
@ -65,6 +72,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void teleportPlayer(IUser otherUser, Location loc, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
/**
|
||||
@ -77,6 +85,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void teleportPlayer(IUser otherUser, Player entity, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
/**
|
||||
@ -87,6 +96,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void respawn(final Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
/**
|
||||
@ -99,6 +109,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void warp(IUser otherUser, String warp, Trade chargeFor, PlayerTeleportEvent.TeleportCause cause) throws Exception;
|
||||
|
||||
/**
|
||||
@ -108,6 +119,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void back(Trade chargeFor) throws Exception;
|
||||
|
||||
/**
|
||||
@ -117,10 +129,11 @@ public interface ITeleport {
|
||||
*
|
||||
* @param teleporter - The user performing the /back command.
|
||||
* This value may be {@code null} to indicate console.
|
||||
* @param chargeFor - What the {@code teleporter} will be charged if teleportPlayer is successful
|
||||
* @param chargeFor - What the {@code teleporter} will be charged if teleportPlayer is successful
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void back(IUser teleporter, Trade chargeFor) throws Exception;
|
||||
|
||||
/**
|
||||
@ -128,6 +141,7 @@ public interface ITeleport {
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
void back() throws Exception;
|
||||
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ public class Commandback extends EssentialsCommand {
|
||||
protected void run(Server server, User user, String commandLabel, String[] args) throws Exception {
|
||||
CommandSource sender = user.getSource();
|
||||
if (args.length > 0 && user.isAuthorized("essentials.back.others")) {
|
||||
this.parseCommand(server, sender, args, true);
|
||||
this.parseCommand(server, sender, args, true, commandLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
teleportBack(sender, user);
|
||||
teleportBack(sender, user, commandLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -36,10 +36,10 @@ public class Commandback extends EssentialsCommand {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
||||
this.parseCommand(server, sender, args, true);
|
||||
this.parseCommand(server, sender, args, true, commandLabel);
|
||||
}
|
||||
|
||||
private void parseCommand(Server server, CommandSource sender, String[] args, boolean allowOthers) throws Exception {
|
||||
private void parseCommand(Server server, CommandSource sender, String[] args, boolean allowOthers, String commandLabel) throws Exception {
|
||||
Collection<Player> players = new ArrayList<>();
|
||||
|
||||
if (allowOthers && args.length > 0 && args[0].trim().length() > 2) {
|
||||
@ -52,11 +52,11 @@ public class Commandback extends EssentialsCommand {
|
||||
|
||||
for (Player player : players) {
|
||||
sender.sendMessage(tl("backOther", player.getName()));
|
||||
teleportBack(sender, ess.getUser(player));
|
||||
teleportBack(sender, ess.getUser(player), commandLabel);
|
||||
}
|
||||
}
|
||||
|
||||
private void teleportBack(CommandSource sender, User user) throws Exception {
|
||||
private void teleportBack(CommandSource sender, User user, String commandLabel) throws Exception {
|
||||
if (user.getLastLocation() == null) {
|
||||
throw new Exception(tl("noLocationFound"));
|
||||
}
|
||||
@ -77,15 +77,15 @@ public class Commandback extends EssentialsCommand {
|
||||
}
|
||||
|
||||
if (requester == null) {
|
||||
user.getTeleport().back(null, null);
|
||||
user.getAsyncTeleport().back(null, null, getNewExceptionFuture(sender, commandLabel));
|
||||
} else if (!requester.equals(user)) {
|
||||
Trade charge = new Trade(this.getName(), this.ess);
|
||||
charge.isAffordableFor(requester);
|
||||
user.getTeleport().back(requester, charge);
|
||||
user.getAsyncTeleport().back(requester, charge, getNewExceptionFuture(sender, commandLabel));
|
||||
} else {
|
||||
Trade charge = new Trade(this.getName(), this.ess);
|
||||
charge.isAffordableFor(user);
|
||||
user.getTeleport().back(charge);
|
||||
user.getAsyncTeleport().back(charge, getNewExceptionFuture(sender, commandLabel));
|
||||
}
|
||||
throw new NoChargeException();
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.earth2me.essentials.commands;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.utils.StringUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
@ -10,6 +11,7 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
@ -39,41 +41,56 @@ public class Commandhome extends EssentialsCommand {
|
||||
}
|
||||
try {
|
||||
if ("bed".equalsIgnoreCase(homeName) && user.isAuthorized("essentials.home.bed")) {
|
||||
final Location bed = player.getBase().getBedSpawnLocation();
|
||||
if (bed != null) {
|
||||
user.getTeleport().teleport(bed, charge, TeleportCause.COMMAND);
|
||||
throw new NoChargeException();
|
||||
} else {
|
||||
throw new Exception(tl("bedMissing"));
|
||||
if (!player.getBase().isOnline()) {
|
||||
throw new Exception(tl("bedOffline"));
|
||||
}
|
||||
}
|
||||
goHome(user, player, homeName.toLowerCase(Locale.ENGLISH), charge);
|
||||
} catch (NotEnoughArgumentsException e) {
|
||||
Location bed = player.getBase().getBedSpawnLocation();
|
||||
final List<String> homes = player.getHomes();
|
||||
if (homes.isEmpty() && player.equals(user)) {
|
||||
if (ess.getSettings().isSpawnIfNoHome()) {
|
||||
user.getTeleport().respawn(charge, TeleportCause.COMMAND);
|
||||
} else {
|
||||
throw new Exception(tl("noHomeSetPlayer"));
|
||||
}
|
||||
} else if (homes.isEmpty()) {
|
||||
throw new Exception(tl("noHomeSetPlayer"));
|
||||
} else if (homes.size() == 1 && player.equals(user)) {
|
||||
goHome(user, player, homes.get(0), charge);
|
||||
} else {
|
||||
final int count = homes.size();
|
||||
if (user.isAuthorized("essentials.home.bed")) {
|
||||
if (bed != null) {
|
||||
homes.add(tl("bed"));
|
||||
PaperLib.getBedSpawnLocationAsync(player.getBase(), true).thenAccept(location -> {
|
||||
CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
|
||||
if (location != null) {
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
user.sendMessage(tl("teleportHome", "bed"));
|
||||
}
|
||||
});
|
||||
user.getAsyncTeleport().teleport(location, charge, TeleportCause.COMMAND, future);
|
||||
} else {
|
||||
homes.add(tl("bedNull"));
|
||||
showError(user.getBase(), new Exception(tl("bedMissing")), commandLabel);
|
||||
}
|
||||
}
|
||||
user.sendMessage(tl("homes", StringUtil.joinList(homes), count, getHomeLimit(player)));
|
||||
});
|
||||
return;
|
||||
}
|
||||
goHome(user, player, homeName.toLowerCase(Locale.ENGLISH), charge, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
} catch (NotEnoughArgumentsException e) {
|
||||
final User finalPlayer = player;
|
||||
PaperLib.getBedSpawnLocationAsync(player.getBase(), true).thenAccept(bed -> {
|
||||
final List<String> homes = finalPlayer.getHomes();
|
||||
if (homes.isEmpty() && finalPlayer.equals(user)) {
|
||||
if (ess.getSettings().isSpawnIfNoHome()) {
|
||||
user.getAsyncTeleport().respawn(charge, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
} else {
|
||||
showError(user.getBase(), new Exception(tl("noHomeSetPlayer")), commandLabel);
|
||||
}
|
||||
} else if (homes.isEmpty()) {
|
||||
showError(user.getBase(), new Exception(tl("noHomeSetPlayer")), commandLabel);
|
||||
} else if (homes.size() == 1 && finalPlayer.equals(user)) {
|
||||
try {
|
||||
goHome(user, finalPlayer, homes.get(0), charge, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
} catch (Exception exception) {
|
||||
showError(user.getBase(), exception, commandLabel);
|
||||
}
|
||||
} else {
|
||||
final int count = homes.size();
|
||||
if (user.isAuthorized("essentials.home.bed")) {
|
||||
if (bed != null) {
|
||||
homes.add(tl("bed"));
|
||||
} else {
|
||||
homes.add(tl("bedNull"));
|
||||
}
|
||||
}
|
||||
user.sendMessage(tl("homes", StringUtil.joinList(homes), count, getHomeLimit(finalPlayer)));
|
||||
}
|
||||
});
|
||||
}
|
||||
throw new NoChargeException();
|
||||
}
|
||||
|
||||
private String getHomeLimit(final User player) {
|
||||
@ -86,7 +103,7 @@ public class Commandhome extends EssentialsCommand {
|
||||
return Integer.toString(ess.getSettings().getHomeLimit(player));
|
||||
}
|
||||
|
||||
private void goHome(final User user, final User player, final String home, final Trade charge) throws Exception {
|
||||
private void goHome(final User user, final User player, final String home, final Trade charge, CompletableFuture<Boolean> future) throws Exception {
|
||||
if (home.length() < 1) {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
@ -97,8 +114,12 @@ public class Commandhome extends EssentialsCommand {
|
||||
if (user.getWorld() != loc.getWorld() && ess.getSettings().isWorldHomePermissions() && !user.isAuthorized("essentials.worlds." + loc.getWorld().getName())) {
|
||||
throw new Exception(tl("noPerm", "essentials.worlds." + loc.getWorld().getName()));
|
||||
}
|
||||
user.getTeleport().teleport(loc, charge, TeleportCause.COMMAND);
|
||||
user.sendMessage(tl("teleportHome", home));
|
||||
user.getAsyncTeleport().teleport(loc, charge, TeleportCause.COMMAND, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
user.sendMessage(tl("teleportHome", home));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,8 +46,7 @@ public class Commandjump extends EssentialsCommand {
|
||||
|
||||
final Trade charge = new Trade(this.getName(), ess);
|
||||
charge.isAffordableFor(user);
|
||||
user.getTeleport().teleport(loc, charge, TeleportCause.COMMAND);
|
||||
throw new NoChargeException();
|
||||
user.getAsyncTeleport().teleport(loc, charge, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -9,6 +9,7 @@ import org.bukkit.Server;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
@ -43,23 +44,33 @@ public class Commandtogglejail extends EssentialsCommand {
|
||||
ess.getServer().getPluginManager().callEvent(event);
|
||||
|
||||
if (!event.isCancelled()) {
|
||||
long preTimeDiff = 0;
|
||||
if (args.length > 2) {
|
||||
final String time = getFinalArg(args, 2);
|
||||
preTimeDiff = DateUtil.parseDateDiff(time, true);
|
||||
|
||||
}
|
||||
final long timeDiff = preTimeDiff;
|
||||
CompletableFuture<Boolean> future = getNewExceptionFuture(sender, commandLabel);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
player.setJailed(true);
|
||||
player.sendMessage(tl("userJailed"));
|
||||
player.setJail(null);
|
||||
player.setJail(args[1]);
|
||||
if (args.length > 2) {
|
||||
player.setJailTimeout(timeDiff);
|
||||
}
|
||||
sender.sendMessage((timeDiff > 0 ? tl("playerJailedFor", player.getName(), DateUtil.formatDateDiff(timeDiff)) : tl("playerJailed", player.getName())));
|
||||
}
|
||||
});
|
||||
if (player.getBase().isOnline()) {
|
||||
ess.getJails().sendToJail(player, args[1]);
|
||||
ess.getJails().sendToJail(player, args[1], future);
|
||||
} else {
|
||||
// Check if jail exists
|
||||
ess.getJails().getJail(args[1]);
|
||||
future.complete(true);
|
||||
}
|
||||
player.setJailed(true);
|
||||
player.sendMessage(tl("userJailed"));
|
||||
player.setJail(null);
|
||||
player.setJail(args[1]);
|
||||
long timeDiff = 0;
|
||||
if (args.length > 2) {
|
||||
final String time = getFinalArg(args, 2);
|
||||
timeDiff = DateUtil.parseDateDiff(time, true);
|
||||
player.setJailTimeout(timeDiff);
|
||||
}
|
||||
sender.sendMessage((timeDiff > 0 ? tl("playerJailedFor", player.getName(), DateUtil.formatDateDiff(timeDiff)) : tl("playerJailed", player.getName())));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -91,7 +102,14 @@ public class Commandtogglejail extends EssentialsCommand {
|
||||
player.sendMessage(tl("jailReleasedPlayerNotify"));
|
||||
player.setJail(null);
|
||||
if (player.getBase().isOnline()) {
|
||||
player.getTeleport().back();
|
||||
CompletableFuture<Boolean> future = getNewExceptionFuture(sender, commandLabel);
|
||||
player.getAsyncTeleport().back(future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
sender.sendMessage(tl("jailReleased", player.getName()));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(tl("jailReleased", player.getName()));
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
@ -22,8 +24,12 @@ public class Commandtop extends EssentialsCommand {
|
||||
final float pitch = user.getLocation().getPitch();
|
||||
final float yaw = user.getLocation().getYaw();
|
||||
final Location loc = LocationUtil.getSafeDestination(new Location(user.getWorld(), topX, user.getWorld().getMaxHeight(), topZ, yaw, pitch));
|
||||
user.getTeleport().teleport(loc, new Trade(this.getName(), ess), TeleportCause.COMMAND);
|
||||
user.sendMessage(tl("teleportTop", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
user.sendMessage(tl("teleportTop", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
}
|
||||
});
|
||||
user.getAsyncTeleport().teleport(loc, new Trade(this.getName(), ess), TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
@ -21,6 +22,7 @@ public class Commandtp extends EssentialsCommand {
|
||||
|
||||
@Override
|
||||
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
|
||||
CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
|
||||
switch (args.length) {
|
||||
case 0:
|
||||
throw new NotEnoughArgumentsException();
|
||||
@ -41,8 +43,8 @@ public class Commandtp extends EssentialsCommand {
|
||||
}
|
||||
final Trade charge = new Trade(this.getName(), ess);
|
||||
charge.isAffordableFor(user);
|
||||
user.getTeleport().teleport(player.getBase(), charge, TeleportCause.COMMAND);
|
||||
throw new NoChargeException();
|
||||
user.getAsyncTeleport().teleport(player.getBase(), charge, TeleportCause.COMMAND, future);
|
||||
break;
|
||||
case 3:
|
||||
if (!user.isAuthorized("essentials.tp.position")) {
|
||||
throw new Exception(tl("noPerm", "essentials.tp.position"));
|
||||
@ -54,8 +56,12 @@ public class Commandtp extends EssentialsCommand {
|
||||
throw new NotEnoughArgumentsException(tl("teleportInvalidLocation"));
|
||||
}
|
||||
final Location locpos = new Location(user.getWorld(), x2, y2, z2, user.getLocation().getYaw(), user.getLocation().getPitch());
|
||||
user.getTeleport().now(locpos, false, TeleportCause.COMMAND);
|
||||
user.sendMessage(tl("teleporting", locpos.getWorld().getName(), locpos.getBlockX(), locpos.getBlockY(), locpos.getBlockZ()));
|
||||
user.getAsyncTeleport().now(locpos, false, TeleportCause.COMMAND, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
user.sendMessage(tl("teleporting", locpos.getWorld().getName(), locpos.getBlockX(), locpos.getBlockY(), locpos.getBlockZ()));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 4:
|
||||
if (!user.isAuthorized("essentials.tp.others")) {
|
||||
@ -76,8 +82,12 @@ public class Commandtp extends EssentialsCommand {
|
||||
throw new Exception(tl("teleportDisabled", target2.getDisplayName()));
|
||||
}
|
||||
user.sendMessage(tl("teleporting", locposother.getWorld().getName(), locposother.getBlockX(), locposother.getBlockY(), locposother.getBlockZ()));
|
||||
target2.getTeleport().now(locposother, false, TeleportCause.COMMAND);
|
||||
target2.sendMessage(tl("teleporting", locposother.getWorld().getName(), locposother.getBlockX(), locposother.getBlockY(), locposother.getBlockZ()));
|
||||
target2.getAsyncTeleport().now(locposother, false, TeleportCause.COMMAND, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
target2.sendMessage(tl("teleporting", locposother.getWorld().getName(), locposother.getBlockX(), locposother.getBlockY(), locposother.getBlockZ()));
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
@ -96,7 +106,7 @@ public class Commandtp extends EssentialsCommand {
|
||||
throw new Exception(tl("noPerm", "essentials.worlds." + toPlayer.getWorld().getName()));
|
||||
}
|
||||
target.sendMessage(tl("teleportAtoB", user.getDisplayName(), toPlayer.getDisplayName()));
|
||||
target.getTeleport().now(toPlayer.getBase(), false, TeleportCause.COMMAND);
|
||||
target.getAsyncTeleport().now(toPlayer.getBase(), false, TeleportCause.COMMAND, future);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -111,7 +121,7 @@ public class Commandtp extends EssentialsCommand {
|
||||
if (args.length == 2) {
|
||||
final User toPlayer = getPlayer(server, args, 1, true, false);
|
||||
target.sendMessage(tl("teleportAtoB", Console.NAME, toPlayer.getDisplayName()));
|
||||
target.getTeleport().now(toPlayer.getBase(), false, TeleportCause.COMMAND);
|
||||
target.getAsyncTeleport().now(toPlayer.getBase(), false, TeleportCause.COMMAND, getNewExceptionFuture(sender, commandLabel));
|
||||
} else if (args.length > 3) {
|
||||
final double x = args[1].startsWith("~") ? target.getLocation().getX() + (args[1].length() > 1 ? Double.parseDouble(args[1].substring(1)) : 0) : Double.parseDouble(args[1]);
|
||||
final double y = args[2].startsWith("~") ? target.getLocation().getY() + (args[2].length() > 1 ? Double.parseDouble(args[2].substring(1)) : 0) : Double.parseDouble(args[2]);
|
||||
@ -121,8 +131,13 @@ public class Commandtp extends EssentialsCommand {
|
||||
}
|
||||
final Location loc = new Location(target.getWorld(), x, y, z, target.getLocation().getYaw(), target.getLocation().getPitch());
|
||||
sender.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
target.getTeleport().now(loc, false, TeleportCause.COMMAND);
|
||||
target.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
CompletableFuture<Boolean> future = getNewExceptionFuture(sender, commandLabel);
|
||||
target.getAsyncTeleport().now(loc, false, TeleportCause.COMMAND, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
target.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.Teleport;
|
||||
import com.earth2me.essentials.AsyncTeleport;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import net.ess3.api.events.TPARequestEvent;
|
||||
@ -9,6 +9,7 @@ import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
@ -44,11 +45,16 @@ public class Commandtpa extends EssentialsCommand {
|
||||
}
|
||||
if (player.isAutoTeleportEnabled() && !player.isIgnoredPlayer(user)) {
|
||||
final Trade charge = new Trade(this.getName(), ess);
|
||||
Teleport teleport = user.getTeleport();
|
||||
teleport.setTpType(Teleport.TeleportType.TPA);
|
||||
teleport.teleport(player.getBase(), charge, PlayerTeleportEvent.TeleportCause.COMMAND);
|
||||
player.sendMessage(tl("requestAcceptedAuto", user.getDisplayName()));
|
||||
user.sendMessage(tl("requestAcceptedFromAuto", player.getDisplayName()));
|
||||
AsyncTeleport teleport = (AsyncTeleport) user.getAsyncTeleport();
|
||||
teleport.setTpType(AsyncTeleport.TeleportType.TPA);
|
||||
CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
|
||||
teleport.teleport(player.getBase(), charge, PlayerTeleportEvent.TeleportCause.COMMAND, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
player.sendMessage(tl("requestAcceptedAuto", user.getDisplayName()));
|
||||
user.sendMessage(tl("requestAcceptedFromAuto", player.getDisplayName()));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import com.earth2me.essentials.Teleport;
|
||||
import com.earth2me.essentials.AsyncTeleport;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
@ -49,24 +51,31 @@ public class Commandtpaccept extends EssentialsCommand {
|
||||
user.sendMessage(tl("requestAccepted"));
|
||||
requester.sendMessage(tl("requestAcceptedFrom", user.getDisplayName()));
|
||||
|
||||
try {
|
||||
if (user.isTpRequestHere()) {
|
||||
final Location loc = user.getTpRequestLocation();
|
||||
Teleport teleport = requester.getTeleport();
|
||||
teleport.setTpType(Teleport.TeleportType.TPA);
|
||||
teleport.teleportPlayer(user, user.getTpRequestLocation(), charge, TeleportCause.COMMAND);
|
||||
requester.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
} else {
|
||||
Teleport teleport = requester.getTeleport();
|
||||
teleport.setTpType(Teleport.TeleportType.TPA);
|
||||
teleport.teleport(user.getBase(), charge, TeleportCause.COMMAND);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
CompletableFuture<Boolean> future = getNewExceptionFuture(requester.getSource(), commandLabel);
|
||||
future.exceptionally(e -> {
|
||||
user.sendMessage(tl("pendingTeleportCancelled"));
|
||||
ess.showError(requester.getSource(), ex, commandLabel);
|
||||
return false;
|
||||
});
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
user.requestTeleport(null, false);
|
||||
}
|
||||
});
|
||||
if (user.isTpRequestHere()) {
|
||||
final Location loc = user.getTpRequestLocation();
|
||||
AsyncTeleport teleport = (AsyncTeleport) requester.getAsyncTeleport();
|
||||
teleport.setTpType(AsyncTeleport.TeleportType.TPA);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
requester.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
}
|
||||
});
|
||||
teleport.teleportPlayer(user, user.getTpRequestLocation(), charge, TeleportCause.COMMAND, future);
|
||||
} else {
|
||||
AsyncTeleport teleport = (AsyncTeleport) requester.getAsyncTeleport();
|
||||
teleport.setTpType(AsyncTeleport.TeleportType.TPA);
|
||||
teleport.teleport(user.getBase(), charge, TeleportCause.COMMAND, future);
|
||||
}
|
||||
user.requestTeleport(null, false);
|
||||
throw new NoChargeException();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,17 +21,17 @@ public class Commandtpall 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()) {
|
||||
teleportAllPlayers(server, sender, ess.getUser(sender.getPlayer()));
|
||||
teleportAllPlayers(server, sender, ess.getUser(sender.getPlayer()), commandLabel);
|
||||
return;
|
||||
}
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
|
||||
final User target = getPlayer(server, sender, args, 0);
|
||||
teleportAllPlayers(server, sender, target);
|
||||
teleportAllPlayers(server, sender, target, commandLabel);
|
||||
}
|
||||
|
||||
private void teleportAllPlayers(Server server, CommandSource sender, User target) {
|
||||
private void teleportAllPlayers(Server server, CommandSource sender, User target, String label) {
|
||||
sender.sendMessage(tl("teleportAll"));
|
||||
final Location loc = target.getLocation();
|
||||
for (User player : ess.getOnlineUsers()) {
|
||||
@ -41,11 +41,7 @@ public class Commandtpall extends EssentialsCommand {
|
||||
if (sender.getSender().equals(target.getBase()) && target.getWorld() != player.getWorld() && ess.getSettings().isWorldTeleportPermissions() && !target.isAuthorized("essentials.worlds." + target.getWorld().getName())) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
player.getTeleport().now(loc, false, TeleportCause.COMMAND);
|
||||
} catch (Exception ex) {
|
||||
ess.showError(sender, ex, getName());
|
||||
}
|
||||
player.getAsyncTeleport().now(loc, false, TeleportCause.COMMAND, getNewExceptionFuture(sender, label));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,7 @@ public class Commandtphere 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()));
|
||||
}
|
||||
user.getTeleport().teleportPlayer(player, user.getBase(), new Trade(this.getName(), ess), TeleportCause.COMMAND);
|
||||
throw new NoChargeException();
|
||||
user.getAsyncTeleport().teleportPlayer(player, user.getBase(), new Trade(this.getName(), ess), TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,6 +6,7 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
@ -26,7 +27,7 @@ public class Commandtpo 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()));
|
||||
}
|
||||
user.getTeleport().now(player.getBase(), false, TeleportCause.COMMAND);
|
||||
user.getAsyncTeleport().now(player.getBase(), false, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -40,8 +41,13 @@ public class Commandtpo extends EssentialsCommand {
|
||||
throw new Exception(tl("noPerm", "essentials.worlds." + toPlayer.getWorld().getName()));
|
||||
}
|
||||
|
||||
target.getTeleport().now(toPlayer.getBase(), false, TeleportCause.COMMAND);
|
||||
target.sendMessage(tl("teleportAtoB", user.getDisplayName(), toPlayer.getDisplayName()));
|
||||
CompletableFuture<Boolean> future = getNewExceptionFuture(user.getSource(), commandLabel);
|
||||
target.getAsyncTeleport().now(toPlayer.getBase(), false, TeleportCause.COMMAND, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
target.sendMessage(tl("teleportAtoB", user.getDisplayName(), toPlayer.getDisplayName()));
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class Commandtpoffline extends EssentialsCommand {
|
||||
}
|
||||
|
||||
user.sendMessage(tl("teleporting", logout.getWorld().getName(), logout.getBlockX(), logout.getBlockY(), logout.getBlockZ()));
|
||||
user.getTeleport().now(logout, false, PlayerTeleportEvent.TeleportCause.COMMAND);
|
||||
user.getAsyncTeleport().now(logout, false, PlayerTeleportEvent.TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), label));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,7 @@ public class Commandtpohere extends EssentialsCommand {
|
||||
throw new Exception(tl("noPerm", "essentials.worlds." + user.getWorld().getName()));
|
||||
}
|
||||
|
||||
// Verify permission
|
||||
player.getTeleport().now(user.getBase(), false, TeleportCause.COMMAND);
|
||||
player.getAsyncTeleport().now(user.getBase(), false, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,8 +55,7 @@ public class Commandtppos extends EssentialsCommand {
|
||||
final Trade charge = new Trade(this.getName(), ess);
|
||||
charge.isAffordableFor(user);
|
||||
user.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
user.getTeleport().teleport(loc, charge, TeleportCause.COMMAND);
|
||||
throw new NoChargeException();
|
||||
user.getAsyncTeleport().teleport(loc, charge, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,8 +84,7 @@ public class Commandtppos extends EssentialsCommand {
|
||||
}
|
||||
sender.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
user.sendMessage(tl("teleporting", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
||||
user.getTeleport().teleport(loc, null, TeleportCause.COMMAND);
|
||||
|
||||
user.getAsyncTeleport().teleport(loc, null, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,11 +41,10 @@ public class Commandwarp extends EssentialsCommand {
|
||||
User otherUser = null;
|
||||
if (args.length == 2 && (user.isAuthorized("essentials.warp.otherplayers") || user.isAuthorized("essentials.warp.others"))) {
|
||||
otherUser = getPlayer(server, user, args, 1);
|
||||
warpUser(user, otherUser, args[0]);
|
||||
throw new NoChargeException();
|
||||
warpUser(user, otherUser, args[0], commandLabel);
|
||||
return;
|
||||
}
|
||||
warpUser(user, user, args[0]);
|
||||
throw new NoChargeException();
|
||||
warpUser(user, user, args[0], commandLabel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,9 +55,7 @@ public class Commandwarp extends EssentialsCommand {
|
||||
throw new NoChargeException();
|
||||
}
|
||||
User otherUser = getPlayer(server, args, 1, true, false);
|
||||
otherUser.getTeleport().warp(otherUser, args[0], null, TeleportCause.COMMAND);
|
||||
throw new NoChargeException();
|
||||
|
||||
otherUser.getAsyncTeleport().warp(otherUser, args[0], null, TeleportCause.COMMAND, getNewExceptionFuture(sender, commandLabel));
|
||||
}
|
||||
|
||||
//TODO: Use one of the new text classes, like /help ?
|
||||
@ -91,7 +88,7 @@ public class Commandwarp extends EssentialsCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private void warpUser(final User owner, final User user, final String name) throws Exception {
|
||||
private void warpUser(final User owner, final User user, final String name, final String commandLabel) throws Exception {
|
||||
final Trade chargeWarp = new Trade("warp-" + name.toLowerCase(Locale.ENGLISH).replace('_', '-'), ess);
|
||||
final Trade chargeCmd = new Trade(this.getName(), ess);
|
||||
final BigDecimal fullCharge = chargeWarp.getCommandCost(user).add(chargeCmd.getCommandCost(user));
|
||||
@ -100,7 +97,7 @@ public class Commandwarp extends EssentialsCommand {
|
||||
if (ess.getSettings().getPerWarpPermission() && !owner.isAuthorized("essentials.warps." + name)) {
|
||||
throw new Exception(tl("warpUsePermission"));
|
||||
}
|
||||
owner.getTeleport().warp(user, name, charge, TeleportCause.COMMAND);
|
||||
owner.getAsyncTeleport().warp(user, name, charge, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
|
||||
private List<String> getAvailableWarpsFor(final IUser user) {
|
||||
|
@ -66,8 +66,7 @@ public class Commandworld extends EssentialsCommand {
|
||||
|
||||
final Trade charge = new Trade(this.getName(), ess);
|
||||
charge.isAffordableFor(user);
|
||||
user.getTeleport().teleport(target, charge, TeleportCause.COMMAND);
|
||||
throw new NoChargeException();
|
||||
user.getAsyncTeleport().teleport(target, charge, TeleportCause.COMMAND, getNewExceptionFuture(user.getSource(), commandLabel));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.earth2me.essentials.commands;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
@ -24,6 +25,8 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
@ -346,6 +349,24 @@ public abstract class EssentialsCommand implements IEssentialsCommand {
|
||||
return command.tabComplete(sender.getSender(), label, effectiveArgs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showError(CommandSender sender, Throwable throwable, String commandLabel) {
|
||||
sender.sendMessage(tl("errorWithMessage", throwable.getMessage()));
|
||||
if (ess.getSettings().isDebug()) {
|
||||
logger.log(Level.INFO, tl("errorCallingCommand", commandLabel), throwable);
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Boolean> getNewExceptionFuture(CommandSource sender, String commandLabel) {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
future.exceptionally(e -> {
|
||||
showError(sender.getSender(), e, commandLabel);
|
||||
return false;
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common time durations (in seconds), for use in tab completion.
|
||||
*/
|
||||
|
@ -6,6 +6,8 @@ import com.earth2me.essentials.User;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@ -23,4 +25,6 @@ public interface IEssentialsCommand {
|
||||
void setEssentials(IEssentials ess);
|
||||
|
||||
void setEssentialsModule(IEssentialsModule module);
|
||||
|
||||
void showError(CommandSender sender, Throwable throwable, String commandLabel);
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import com.earth2me.essentials.User;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
@ -52,12 +54,17 @@ public class SignWarp extends EssentialsSign {
|
||||
}
|
||||
|
||||
final Trade charge = getTrade(sign, 3, ess);
|
||||
try {
|
||||
player.getTeleport().warp(player, warpName, charge, TeleportCause.PLUGIN);
|
||||
Trade.log("Sign", "Warp", "Interact", username, null, username, charge, sign.getBlock().getLocation(), ess);
|
||||
} catch (Exception ex) {
|
||||
throw new SignException(ex.getMessage(), ex);
|
||||
}
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
player.getAsyncTeleport().warp(player, warpName, charge, TeleportCause.PLUGIN, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
Trade.log("Sign", "Warp", "Interact", username, null, username, charge, sign.getBlock().getLocation(), ess);
|
||||
}
|
||||
});
|
||||
future.exceptionally(e -> {
|
||||
ess.showError(player.getSource(), e, "\\ sign: " + signName);
|
||||
return false;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ public class LocationUtil {
|
||||
}
|
||||
|
||||
public static Location getSafeDestination(final IEssentials ess, final IUser user, final Location loc) throws Exception {
|
||||
if (user.getBase().isOnline() && loc.getWorld().equals(user.getBase().getWorld()) && (user.getBase().getGameMode() == GameMode.CREATIVE || user.isGodModeEnabled()) && user.getBase().getAllowFlight()) {
|
||||
if (user.getBase().isOnline() && (user.getBase().getGameMode() == GameMode.CREATIVE || user.getBase().getGameMode() == GameMode.SPECTATOR || user.isGodModeEnabled()) || user.getBase().getAllowFlight()) {
|
||||
if (shouldFly(loc)) {
|
||||
user.getBase().setFlying(true);
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ banipCommandUsage=/<command> <address>
|
||||
bed=\u00a7obed\u00a7r
|
||||
bedMissing=\u00a74Your bed is either unset, missing or blocked.
|
||||
bedNull=\u00a7mbed\u00a7r
|
||||
bedOffline=\u00a74Cannot teleport to the beds of offline users.
|
||||
bedSet=\u00a76Bed spawn set\!
|
||||
beezookaCommandDescription=Throw an exploding bee at your opponent.
|
||||
beezookaCommandUsage=/<command>
|
||||
|
@ -1,6 +1,9 @@
|
||||
package net.ess3.api;
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated This API is not asynchronous. Use {@link com.earth2me.essentials.api.IAsyncTeleport IAsyncTeleport}
|
||||
*/
|
||||
public interface ITeleport extends com.earth2me.essentials.api.ITeleport {
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,12 @@
|
||||
package net.ess3.api.events;
|
||||
|
||||
import net.ess3.api.IUser;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
/**
|
||||
* Called when the player teleports
|
||||
*/
|
||||
@ -18,6 +19,7 @@ public class UserTeleportEvent extends Event implements Cancellable {
|
||||
private boolean cancelled = false;
|
||||
|
||||
public UserTeleportEvent(IUser user, TeleportCause cause, Location target) {
|
||||
super(!Bukkit.isPrimaryThread());
|
||||
this.user = user;
|
||||
this.cause = cause;
|
||||
this.target = target;
|
||||
|
@ -5,12 +5,13 @@ import com.earth2me.essentials.Console;
|
||||
import com.earth2me.essentials.Trade;
|
||||
import com.earth2me.essentials.User;
|
||||
import com.earth2me.essentials.commands.EssentialsCommand;
|
||||
import com.earth2me.essentials.commands.NoChargeException;
|
||||
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static com.earth2me.essentials.I18n.tl;
|
||||
|
||||
|
||||
@ -25,14 +26,18 @@ public class Commandspawn extends EssentialsCommand {
|
||||
charge.isAffordableFor(user);
|
||||
if (args.length > 0 && user.isAuthorized("essentials.spawn.others")) {
|
||||
final User otherUser = getPlayer(server, user, args, 0);
|
||||
respawn(user.getSource(), user, otherUser, charge);
|
||||
if (!otherUser.equals(user)) {
|
||||
otherUser.sendMessage(tl("teleportAtoB", user.getDisplayName(), "spawn"));
|
||||
}
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
if (!otherUser.equals(user)) {
|
||||
otherUser.sendMessage(tl("teleportAtoB", user.getDisplayName(), "spawn"));
|
||||
}
|
||||
}
|
||||
});
|
||||
respawn(user.getSource(), user, otherUser, charge, commandLabel, future);
|
||||
} else {
|
||||
respawn(user.getSource(), user, user, charge);
|
||||
respawn(user.getSource(), user, user, charge, commandLabel, new CompletableFuture<>());
|
||||
}
|
||||
throw new NoChargeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -41,19 +46,27 @@ public class Commandspawn extends EssentialsCommand {
|
||||
throw new NotEnoughArgumentsException();
|
||||
}
|
||||
final User user = getPlayer(server, args, 0, true, false);
|
||||
respawn(sender, null, user, null);
|
||||
user.sendMessage(tl("teleportAtoB", Console.NAME, "spawn"));
|
||||
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
respawn(sender, null, user, null, commandLabel, future);
|
||||
future.thenAccept(success -> {
|
||||
if (success) {
|
||||
user.sendMessage(tl("teleportAtoB", Console.NAME, "spawn"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void respawn(final CommandSource sender, final User teleportOwner, final User teleportee, final Trade charge) throws Exception {
|
||||
private void respawn(final CommandSource sender, final User teleportOwner, final User teleportee, final Trade charge, String commandLabel, CompletableFuture<Boolean> future) throws Exception {
|
||||
final SpawnStorage spawns = (SpawnStorage) this.module;
|
||||
final Location spawn = spawns.getSpawn(teleportee.getGroup());
|
||||
sender.sendMessage(tl("teleporting", spawn.getWorld().getName(), spawn.getBlockX(), spawn.getBlockY(), spawn.getBlockZ()));
|
||||
future.exceptionally(e -> {
|
||||
showError(sender.getSender(), e, commandLabel);
|
||||
return false;
|
||||
});
|
||||
if (teleportOwner == null) {
|
||||
teleportee.getTeleport().now(spawn, false, TeleportCause.COMMAND);
|
||||
teleportee.getAsyncTeleport().now(spawn, false, TeleportCause.COMMAND, future);
|
||||
} else {
|
||||
teleportOwner.getTeleport().teleportPlayer(teleportee, spawn, charge, TeleportCause.COMMAND);
|
||||
teleportOwner.getAsyncTeleport().teleportPlayer(teleportee, spawn, charge, TeleportCause.COMMAND, future);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ -135,13 +136,14 @@ class EssentialsSpawnPlayerListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final Location spawn = spawns.getSpawn(ess.getSettings().getNewbieSpawn());
|
||||
if (spawn != null) {
|
||||
user.getTeleport().now(spawn, false, TeleportCause.PLUGIN);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.WARNING, tl("teleportNewPlayerError"), ex);
|
||||
final Location spawn = spawns.getSpawn(ess.getSettings().getNewbieSpawn());
|
||||
if (spawn != null) {
|
||||
CompletableFuture<Boolean> future = new CompletableFuture<>();
|
||||
future.exceptionally(e -> {
|
||||
logger.log(Level.WARNING, tl("teleportNewPlayerError"), e);
|
||||
return false;
|
||||
});
|
||||
user.getAsyncTeleport().now(spawn, false, TeleportCause.PLUGIN, future);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user