diff --git a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java index 120187c4..ce3402ea 100644 --- a/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java +++ b/src/main/java/me/libraryaddict/disguise/DisguiseConfig.java @@ -78,6 +78,15 @@ public class DisguiseConfig { private static int uuidGeneratedVersion; private static UpdatesBranch updatesBranch = UpdatesBranch.SAME_BUILDS; private static int playerDisguisesTablistExpires; + private static boolean dynamicExpiry; + + public static boolean isDynamicExpiry() { + return dynamicExpiry; + } + + public static void setDynamicExpiry(boolean setDynamicExpiry) { + dynamicExpiry = setDynamicExpiry; + } public static int getPlayerDisguisesTablistExpires() { return playerDisguisesTablistExpires; @@ -282,6 +291,7 @@ public class DisguiseConfig { setExplicitDisguisePermissions(config.getBoolean("Permissions.ExplicitDisguises")); setUUIDGeneratedVersion(config.getInt("UUIDVersion")); setPlayerDisguisesTablistExpires(config.getInt("PlayerDisguisesTablistExpires")); + setDynamicExpiry(config.getBoolean("DynamicExpiry")); if (!LibsPremium.isPremium() && (isSavePlayerDisguises() || isSaveEntityDisguises())) { DisguiseUtilities.getLogger().warning("You must purchase the plugin to use saved disguises!"); diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java index 8760ada5..54206ff1 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/Disguise.java @@ -20,6 +20,7 @@ import me.libraryaddict.disguise.events.DisguiseEvent; import me.libraryaddict.disguise.events.UndisguiseEvent; import me.libraryaddict.disguise.utilities.DisguiseUtilities; import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; +import me.libraryaddict.disguise.utilities.translations.LibsMsg; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Entity; @@ -59,6 +60,10 @@ public abstract class Disguise { private boolean velocitySent = DisguiseConfig.isVelocitySent(); private boolean viewSelfDisguise = DisguiseConfig.isViewDisguises(); private FlagWatcher watcher; + /** + * If set, how long before disguise expires + */ + private long disguiseExpires; public Disguise(DisguiseType disguiseType) { this.disguiseType = disguiseType; @@ -107,6 +112,23 @@ public abstract class Disguise { } } + public boolean isDisguiseExpired() { + return DisguiseConfig.isDynamicExpiry() ? disguiseExpires == 1 : + disguiseExpires > 0 && disguiseExpires < System.currentTimeMillis(); + } + + public long getExpires() { + return disguiseExpires; + } + + public void setExpires(long timeToExpire) { + disguiseExpires = timeToExpire; + + if (isDisguiseExpired()) { + removeDisguise(); + } + } + private void createRunnable() { final boolean alwaysSendVelocity; @@ -149,6 +171,15 @@ public abstract class Disguise { // If entity is no longer valid. Remove it. if (getEntity() instanceof Player && !((Player) getEntity()).isOnline()) { removeDisguise(); + } else if (disguiseExpires > 0 && (DisguiseConfig.isDynamicExpiry() ? --disguiseExpires == 1 : + disguiseExpires < System.currentTimeMillis())) { // If disguise expired + removeDisguise(); + + String expired = LibsMsg.EXPIRED_DISGUISE.get(); + + if (getEntity() instanceof Player && expired.length() > 0) { + getEntity().sendMessage(expired); + } } else if (!getEntity().isValid()) { // If it has been dead for 30+ ticks // This is to ensure that this disguise isn't removed while clients think its the real entity @@ -728,12 +759,12 @@ public abstract class Disguise { } public boolean startDisguise() { - if (isDisguiseInUse()) { + if (isDisguiseInUse() || isDisguiseExpired()) { return false; } if (getEntity() == null) { - throw new RuntimeException("No entity is assigned to this disguise!"); + throw new IllegalStateException("No entity is assigned to this disguise!"); } DisguiseUtilities.setPluginsUsed(); @@ -741,8 +772,7 @@ public abstract class Disguise { // Fire a disguise event DisguiseEvent event = new DisguiseEvent(entity, this); - Bukkit.getPluginManager(). - callEvent(event); + Bukkit.getPluginManager().callEvent(event); // If they cancelled this disguise event. No idea why. // Just return. diff --git a/src/main/java/me/libraryaddict/disguise/utilities/parser/DisguiseParser.java b/src/main/java/me/libraryaddict/disguise/utilities/parser/DisguiseParser.java index 96c75b71..12d80db0 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/parser/DisguiseParser.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/parser/DisguiseParser.java @@ -20,6 +20,7 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; public class DisguiseParser { private static void doCheck(CommandSender sender, DisguisePermissions permissions, DisguisePerm disguisePerm, @@ -204,6 +205,43 @@ public class DisguiseParser { return args; } + public static long parseStringToTime(String string) throws DisguiseParseException { + string = string.toLowerCase(); + + if (!string.matches("([0-9]+[a-z]+)+")) { + throw new DisguiseParseException(LibsMsg.PARSE_INVALID_TIME_SEQUENCE, string); + } + + String[] split = string.split("((?<=[a-zA-Z])(?=[0-9]))|((?<=[0-9])(?=[a-zA-Z]))"); + + long time = 0; + + for (int i = 0; i < split.length; i += 2) { + String t = split[i + 1]; + long v = Long.parseLong(split[i]); + + if (t.equals("s") || t.equals("sec") || t.equals("secs") || t.equals("seconds")) { + time += v; + } else if (t.equals("m") || t.equals("min") || t.equals("minute") || t.equals("minutes")) { + time += TimeUnit.MINUTES.toSeconds(v); + } else if (t.equals("h") || t.equals("hour") || t.equals("hours")) { + time += TimeUnit.HOURS.toSeconds(v); + } else if (t.equals("d") || t.equals("day") || t.equals("days")) { + time += TimeUnit.DAYS.toSeconds(v); + } else if (t.equals("w") || t.equals("week") || t.equals("weeks")) { + time += TimeUnit.DAYS.toSeconds(v) * 7; + } else if (t.equals("mon") || t.equals("month") || t.equals("months")) { + time += TimeUnit.DAYS.toSeconds(v) * 31; + } else if (t.equals("y") || t.equals("year") || t.equals("years")) { + time += TimeUnit.DAYS.toSeconds(v) * 365; + } else { + throw new DisguiseParseException(LibsMsg.PARSE_INVALID_TIME, t); + } + } + + return time; + } + /** * Experimentally parses the arguments to test if this is a valid disguise * diff --git a/src/main/java/me/libraryaddict/disguise/utilities/parser/ParamInfoManager.java b/src/main/java/me/libraryaddict/disguise/utilities/parser/ParamInfoManager.java index 061769b3..52fafd55 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/parser/ParamInfoManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/parser/ParamInfoManager.java @@ -4,7 +4,6 @@ import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.DisguiseType; import me.libraryaddict.disguise.disguisetypes.FlagWatcher; import me.libraryaddict.disguise.disguisetypes.watchers.LivingWatcher; -import me.libraryaddict.disguise.utilities.parser.DisguisePerm; import me.libraryaddict.disguise.utilities.parser.params.ParamInfo; import me.libraryaddict.disguise.utilities.parser.params.ParamInfoTypes; import org.bukkit.ChatColor; @@ -104,9 +103,10 @@ public class ParamInfoManager { // Add these last as it's what we want to present to be called the least for (String methodName : new String[]{"setViewSelfDisguise", "setHideHeldItemFromSelf", "setHideArmorFromSelf", - "setHearSelfDisguise", "setHidePlayer"}) { + "setHearSelfDisguise", "setHidePlayer", "setExpires"}) { try { - methods.add(Disguise.class.getMethod(methodName, boolean.class)); + methods.add(Disguise.class + .getMethod(methodName, methodName.equals("setExpires") ? long.class : boolean.class)); } catch (Exception ex) { ex.printStackTrace(); @@ -117,7 +117,7 @@ public class ParamInfoManager { } /** - * Value of the method, used namely for displaying the more unique methods to a disguise + * Value of the method, used namely for ordering the more unique methods to a disguise */ public static int getValue(Method method) { ChatColor methodColor = ChatColor.YELLOW; diff --git a/src/main/java/me/libraryaddict/disguise/utilities/parser/params/ParamInfoTypes.java b/src/main/java/me/libraryaddict/disguise/utilities/parser/params/ParamInfoTypes.java index 142a01e3..4fb4f28a 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/parser/params/ParamInfoTypes.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/parser/params/ParamInfoTypes.java @@ -82,6 +82,9 @@ public class ParamInfoTypes { paramInfos.add(new ParamInfoGameProfile(WrappedGameProfile.class, "GameProfile", "Get the gameprofile here https://sessionserver.mojang" + ".com/session/minecraft/profile/PLAYER_UUID_GOES_HERE?unsigned=false")); + paramInfos.add(new ParamInfoTime(long.class, "Expiry Time", + "Set how long the disguise lasts,