mirror of
https://github.com/TotalFreedomMC/TF-EssentialsX.git
synced 2024-09-12 13:19:33 +00:00
293 lines
9.9 KiB
Java
293 lines
9.9 KiB
Java
package com.earth2me.essentials;
|
|
|
|
import static com.earth2me.essentials.I18n.tl;
|
|
import com.earth2me.essentials.utils.DateUtil;
|
|
import com.earth2me.essentials.utils.LocationUtil;
|
|
import java.math.BigDecimal;
|
|
import java.util.Calendar;
|
|
import java.util.GregorianCalendar;
|
|
import net.ess3.api.IEssentials;
|
|
import net.ess3.api.IUser;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.event.player.PlayerRespawnEvent;
|
|
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
|
|
|
|
|
public class Teleport implements net.ess3.api.ITeleport
|
|
{
|
|
private final IUser teleportOwner;
|
|
private final IEssentials ess;
|
|
private TimedTeleport timedTeleport;
|
|
|
|
public Teleport(IUser user, IEssentials ess)
|
|
{
|
|
this.teleportOwner = user;
|
|
this.ess = ess;
|
|
}
|
|
|
|
public void cooldown(boolean check) throws Exception
|
|
{
|
|
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;
|
|
}
|
|
else if (lastTime > earliestLong && !teleportOwner.isAuthorized("essentials.teleport.cooldown.bypass"))
|
|
{
|
|
time.setTimeInMillis(lastTime);
|
|
time.add(Calendar.SECOND, (int)cooldown);
|
|
time.add(Calendar.MILLISECOND, (int)((cooldown * 1000.0) % 1000.0));
|
|
throw new Exception(tl("timeBeforeTeleport", DateUtil.formatDateDiff(time.getTimeInMillis())));
|
|
}
|
|
}
|
|
// if justCheck is set, don't update lastTeleport; we're just checking
|
|
if (!check)
|
|
{
|
|
teleportOwner.setLastTeleportTimestamp(time.getTimeInMillis());
|
|
}
|
|
}
|
|
|
|
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())));
|
|
}
|
|
|
|
//The now function is used when you want to skip tp delay when teleporting someone to a location or player.
|
|
@Override
|
|
public void now(Location loc, boolean cooldown, TeleportCause cause) throws Exception
|
|
{
|
|
if (cooldown)
|
|
{
|
|
cooldown(false);
|
|
}
|
|
final ITarget target = new LocationTarget(loc);
|
|
now(teleportOwner, target, cause);
|
|
}
|
|
|
|
@Override
|
|
public void now(Player entity, boolean cooldown, TeleportCause cause) throws Exception
|
|
{
|
|
if (cooldown)
|
|
{
|
|
cooldown(false);
|
|
}
|
|
final ITarget target = new PlayerTarget(entity);
|
|
now(teleportOwner, target, cause);
|
|
teleportOwner.sendMessage(tl("teleporting", target.getLocation().getWorld().getName(), target.getLocation().getBlockX(), target.getLocation().getBlockY(), target.getLocation().getBlockZ()));
|
|
}
|
|
|
|
protected void now(IUser teleportee, ITarget target, TeleportCause cause) throws Exception
|
|
{
|
|
cancel(false);
|
|
teleportee.setLastLocation();
|
|
final Location loc = target.getLocation();
|
|
|
|
if (LocationUtil.isBlockUnsafe(loc.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()))
|
|
{
|
|
if (ess.getSettings().isTeleportSafetyEnabled())
|
|
{
|
|
if (teleportee.getBase().isInsideVehicle())
|
|
{
|
|
teleportee.getBase().leaveVehicle();
|
|
}
|
|
teleportee.getBase().teleport(LocationUtil.getSafeDestination(teleportee, loc), cause);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception(tl("unsafeTeleportDestination", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (teleportee.getBase().isInsideVehicle())
|
|
{
|
|
teleportee.getBase().leaveVehicle();
|
|
}
|
|
teleportee.getBase().teleport(LocationUtil.getRoundedDestination(loc), cause);
|
|
}
|
|
}
|
|
|
|
//The teleportPlayer function is used when you want to normally teleportPlayer someone to a location or player.
|
|
//This method is nolonger used internally and will be removed.
|
|
@Deprecated
|
|
@Override
|
|
public void teleport(Location loc, Trade chargeFor) throws Exception
|
|
{
|
|
teleport(loc, chargeFor, TeleportCause.PLUGIN);
|
|
}
|
|
|
|
@Override
|
|
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
|
|
public void teleport(Player entity, Trade chargeFor, TeleportCause cause) throws Exception
|
|
{
|
|
ITarget target = new PlayerTarget(entity);
|
|
teleport(teleportOwner, target, chargeFor, cause);
|
|
teleportOwner.sendMessage(tl("teleportToPlayer", entity.getDisplayName()));
|
|
}
|
|
|
|
//This is used when teleporting to stored location
|
|
@Override
|
|
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
|
|
public void teleportPlayer(IUser teleportee, Player entity, Trade chargeFor, TeleportCause cause) throws Exception
|
|
{
|
|
ITarget target = new PlayerTarget(entity);
|
|
teleport(teleportee, target, chargeFor, cause);
|
|
teleportee.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) throws Exception
|
|
{
|
|
double delay = ess.getSettings().getTeleportDelay();
|
|
|
|
Trade cashCharge = chargeFor;
|
|
|
|
if (chargeFor != null)
|
|
{
|
|
chargeFor.isAffordableFor(teleportOwner);
|
|
|
|
//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);
|
|
}
|
|
}
|
|
|
|
cooldown(true);
|
|
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass")
|
|
|| teleportee.isAuthorized("essentials.teleport.timer.bypass"))
|
|
{
|
|
cooldown(false);
|
|
now(teleportee, target, cause);
|
|
if (cashCharge != null)
|
|
{
|
|
cashCharge.charge(teleportOwner);
|
|
}
|
|
return;
|
|
}
|
|
|
|
cancel(false);
|
|
warnUser(teleportee, delay);
|
|
initTimer((long)(delay * 1000.0), teleportee, target, cashCharge, cause, false);
|
|
}
|
|
|
|
//The respawn function is a wrapper used to handle tp fallback, on /jail and /home
|
|
@Override
|
|
public void respawn(final Trade chargeFor, TeleportCause cause) throws Exception
|
|
{
|
|
double delay = ess.getSettings().getTeleportDelay();
|
|
if (chargeFor != null)
|
|
{
|
|
chargeFor.isAffordableFor(teleportOwner);
|
|
}
|
|
cooldown(true);
|
|
if (delay <= 0 || teleportOwner.isAuthorized("essentials.teleport.timer.bypass"))
|
|
{
|
|
cooldown(false);
|
|
respawnNow(teleportOwner, cause);
|
|
if (chargeFor != null)
|
|
{
|
|
chargeFor.charge(teleportOwner);
|
|
}
|
|
return;
|
|
}
|
|
|
|
cancel(false);
|
|
warnUser(teleportOwner, delay);
|
|
initTimer((long)(delay * 1000.0), teleportOwner, null, chargeFor, cause, true);
|
|
}
|
|
|
|
protected void respawnNow(IUser teleportee, TeleportCause cause) throws Exception
|
|
{
|
|
final Player player = teleportee.getBase();
|
|
Location bed = player.getBedSpawnLocation();
|
|
if (bed != null)
|
|
{
|
|
now(teleportee, new LocationTarget(bed), cause);
|
|
}
|
|
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);
|
|
now(teleportee, new LocationTarget(pre.getRespawnLocation()), cause);
|
|
}
|
|
}
|
|
|
|
//The warp function is a wrapper used to teleportPlayer a player to a /warp
|
|
@Override
|
|
public void warp(IUser teleportee, String warp, Trade chargeFor, TeleportCause cause) throws Exception
|
|
{
|
|
Location loc = ess.getWarps().getWarp(warp);
|
|
teleportee.sendMessage(tl("warpingTo", warp, loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
|
teleport(teleportee, new LocationTarget(loc), chargeFor, cause);
|
|
}
|
|
|
|
//The back function is a wrapper used to teleportPlayer a player /back to their previous location.
|
|
@Override
|
|
public void back(Trade chargeFor) throws Exception
|
|
{
|
|
final Location loc = teleportOwner.getLastLocation();
|
|
teleportOwner.sendMessage(tl("backUsageMsg", loc.getWorld().getName(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
|
|
teleport(teleportOwner, new LocationTarget(loc), chargeFor, TeleportCause.COMMAND);
|
|
}
|
|
|
|
//This function is used to throw a user back after a jail sentence
|
|
@Override
|
|
public void back() throws Exception
|
|
{
|
|
now(teleportOwner, new LocationTarget(teleportOwner.getLastLocation()), TeleportCause.COMMAND);
|
|
}
|
|
|
|
//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 TimedTeleport(teleportOwner, ess, this, delay, teleportUser, target, chargeFor, cause, respawn);
|
|
}
|
|
}
|