From 863bd5a89e1b2141f7d8698240dc2099e7f86776 Mon Sep 17 00:00:00 2001 From: AgentTroll Date: Fri, 8 Mar 2019 22:37:08 -0800 Subject: [PATCH] Add /back target capability --- .../src/com/earth2me/essentials/Teleport.java | 41 ++++++++- .../earth2me/essentials/api/ITeleport.java | 13 +++ .../essentials/commands/Commandback.java | 83 +++++++++++++++++-- Essentials/src/messages.properties | 1 + Essentials/src/messages_en.properties | 1 + Essentials/src/plugin.yml | 2 +- 6 files changed, 130 insertions(+), 11 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/Teleport.java b/Essentials/src/com/earth2me/essentials/Teleport.java index 4db4543cf..e5bd41305 100644 --- a/Essentials/src/com/earth2me/essentials/Teleport.java +++ b/Essentials/src/com/earth2me/essentials/Teleport.java @@ -211,6 +211,39 @@ public class Teleport implements ITeleport { initTimer((long) (delay * 1000.0), teleportee, target, cashCharge, cause, false); } + private void teleportOther(IUser teleporter, IUser teleportee, ITarget target, Trade chargeFor, TeleportCause cause) throws Exception { + double delay = ess.getSettings().getTeleportDelay(); + + Trade cashCharge = chargeFor; + + if (teleporter != null && chargeFor != null) { + chargeFor.isAffordableFor(teleporter); + + //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); + } + } + + cooldown(true); + if (delay <= 0 || teleporter == null + || teleporter.isAuthorized("essentials.teleport.timer.bypass") + || teleportOwner.isAuthorized("essentials.teleport.timer.bypass") + || teleportee.isAuthorized("essentials.teleport.timer.bypass")) { + cooldown(false); + now(teleportee, target, cause); + if (teleporter != null && cashCharge != null) { + cashCharge.charge(teleporter); + } + 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 { @@ -269,10 +302,16 @@ public class Teleport implements ITeleport { //The back function is a wrapper used to teleportPlayer a player /back to their previous location. @Override 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 + public void back(IUser teleporter, Trade chargeFor) throws Exception { tpType = TeleportType.BACK; 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); + teleportOther(teleporter, teleportOwner, new LocationTarget(loc), chargeFor, TeleportCause.COMMAND); } //This function is used to throw a user back after a jail sentence diff --git a/Essentials/src/com/earth2me/essentials/api/ITeleport.java b/Essentials/src/com/earth2me/essentials/api/ITeleport.java index a67459333..1ebad87e5 100644 --- a/Essentials/src/com/earth2me/essentials/api/ITeleport.java +++ b/Essentials/src/com/earth2me/essentials/api/ITeleport.java @@ -110,6 +110,19 @@ public interface ITeleport { */ void back(Trade chargeFor) throws Exception; + /** + * 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 + * + * @throws Exception + */ + void back(IUser teleporter, Trade chargeFor) throws Exception; + /** * Teleport wrapper used to handle throwing user home after a jail sentence * diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandback.java b/Essentials/src/com/earth2me/essentials/commands/Commandback.java index 4e28ac0bb..e8171359b 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandback.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandback.java @@ -1,8 +1,15 @@ package com.earth2me.essentials.commands; +import com.earth2me.essentials.CommandSource; import com.earth2me.essentials.Trade; import com.earth2me.essentials.User; import org.bukkit.Server; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import static com.earth2me.essentials.I18n.tl; @@ -13,24 +20,82 @@ public class Commandback extends EssentialsCommand { } @Override - protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception { + 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); + return; + } + + teleportBack(sender, user); + } + + @Override + protected void run(Server server, CommandSource sender, String commandLabel, String[] args) throws Exception { + if (args.length < 1) { + throw new NotEnoughArgumentsException(); + } + + this.parseCommand(server, sender, args, true); + } + + private void parseCommand(Server server, CommandSource sender, String[] args, boolean allowOthers) throws Exception { + Collection players = new ArrayList<>(); + + if (allowOthers && args.length > 0 && args[0].trim().length() > 2) { + players = server.matchPlayer(args[0].trim()); + } + + if (players.size() < 1) { + throw new PlayerNotFoundException(); + } + + for (Player player : players) { + sender.sendMessage(tl("backOther", player.getName())); + teleportBack(sender, ess.getUser(player)); + } + } + + private void teleportBack(CommandSource sender, User user) throws Exception { if (user.getLastLocation() == null) { throw new Exception(tl("noLocationFound")); } String lastWorldName = user.getLastLocation().getWorld().getName(); - if (user.getWorld() != user.getLastLocation().getWorld() && ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + lastWorldName)) { - throw new Exception(tl("noPerm", "essentials.worlds." + lastWorldName)); + User requester = null; + if (sender.isPlayer()) { + requester = ess.getUser(sender.getPlayer()); + + if (user.getWorld() != user.getLastLocation().getWorld() && this.ess.getSettings().isWorldTeleportPermissions() && !user.isAuthorized("essentials.worlds." + lastWorldName)) { + throw new Exception(tl("noPerm", "essentials.worlds." + lastWorldName)); + } + + if (!requester.isAuthorized("essentials.back.into." + lastWorldName)) { + throw new Exception(tl("noPerm", "essentials.back.into." + lastWorldName)); + } } - if (!user.isAuthorized("essentials.back.into." + lastWorldName)) { - throw new Exception(tl("noPerm", "essentials.back.into." + lastWorldName)); + if (requester == null) { + user.getTeleport().back(null, null); + } else if (!requester.equals(user)) { + Trade charge = new Trade(this.getName(), this.ess); + charge.isAffordableFor(requester); + user.getTeleport().back(requester, charge); + } else { + Trade charge = new Trade(this.getName(), this.ess); + charge.isAffordableFor(user); + user.getTeleport().back(charge); } - - final Trade charge = new Trade(this.getName(), ess); - charge.isAffordableFor(user); - user.getTeleport().back(charge); throw new NoChargeException(); } + + @Override + protected List getTabCompleteOptions(Server server, User user, String commandLabel, String[] args) { + if (user.isAuthorized("essentials.back.others") && args.length == 1) { + return getPlayers(server, user); + } else { + return Collections.emptyList(); + } + } } diff --git a/Essentials/src/messages.properties b/Essentials/src/messages.properties index 2dab6ca75..af50157df 100644 --- a/Essentials/src/messages.properties +++ b/Essentials/src/messages.properties @@ -20,6 +20,7 @@ antiBuildPlace=\u00a74You are not permitted to place\u00a7c {0} \u00a74here. antiBuildUse=\u00a74You are not permitted to use\u00a7c {0}\u00a74. autoAfkKickReason=You have been kicked for idling more than {0} minutes. backAfterDeath=\u00a76Use the /back command to return to your death point. +backOther=\u00a76Returned\u00a7c {0}\u00a76 to previous location. backupDisabled=\u00a74An external backup script has not been configured. backupFinished=\u00a76Backup finished. backupStarted=\u00a76Backup started. diff --git a/Essentials/src/messages_en.properties b/Essentials/src/messages_en.properties index 93a989fa1..af3b00b54 100644 --- a/Essentials/src/messages_en.properties +++ b/Essentials/src/messages_en.properties @@ -24,6 +24,7 @@ autoTeleportDisabledFor=\u00a7c{0}\u00a76 is no longer automatically approving t autoTeleportEnabled=\u00a76You are now automatically approving teleport requests. autoTeleportEnabledFor=\u00a7c{0}\u00a76 is now automatically approving teleport requests. backAfterDeath=\u00a76Use the /back command to return to your death point. +backOther=\u00a76Returned\u00a7c {0}\u00a76 to previous location. backupDisabled=\u00a74An external backup script has not been configured. backupFinished=\u00a76Backup finished. backupStarted=\u00a76Backup started. diff --git a/Essentials/src/plugin.yml b/Essentials/src/plugin.yml index d02544e33..ca040d37b 100644 --- a/Essentials/src/plugin.yml +++ b/Essentials/src/plugin.yml @@ -19,7 +19,7 @@ commands: aliases: [eantioch,grenade,egrenade,tnt,etnt] back: description: Teleports you to your location prior to tp/spawn/warp. - usage: / + usage: / [player] aliases: [eback,return,ereturn] backup: description: Runs the backup if configured.