From f0dabdd4b17da7fea1083dd941e2f092c6e8aaa1 Mon Sep 17 00:00:00 2001 From: snowleo Date: Sat, 10 Dec 2011 03:04:10 +0100 Subject: [PATCH] Re-Implemented User class --- .../AlternativeCommandsHandler.java | 3 +- .../src/com/earth2me/essentials/Backup.java | 42 +- .../src/com/earth2me/essentials/Console.java | 5 +- .../com/earth2me/essentials/Enchantments.java | 9 +- .../com/earth2me/essentials/Essentials.java | 56 +- .../com/earth2me/essentials/IEssentials.java | 3 +- .../essentials/IEssentialsModule.java | 2 +- .../src/com/earth2me/essentials/IReplyTo.java | 1 + .../com/earth2me/essentials/ISettings.java | 4 +- .../src/com/earth2me/essentials/IUser.java | 2 +- .../src/com/earth2me/essentials/Jails.java | 14 +- .../src/com/earth2me/essentials/Settings.java | 30 + .../src/com/earth2me/essentials/Teleport.java | 44 +- .../src/com/earth2me/essentials/Trade.java | 37 +- .../src/com/earth2me/essentials/User.java | 52 +- .../src/com/earth2me/essentials/UserData.java | 2 +- .../src/com/earth2me/essentials/UserMap.java | 11 +- .../src/com/earth2me/essentials/Util.java | 54 +- .../src/com/earth2me/essentials/Worth.java | 9 +- .../com/earth2me/essentials/api/IBackup.java | 7 + .../earth2me/essentials/api/IEssentials.java | 8 +- .../essentials/api/IEssentialsModule.java | 5 + .../com/earth2me/essentials/api/IGroups.java | 16 + .../com/earth2me/essentials/api/IReplyTo.java | 9 + .../earth2me/essentials/api/ITeleport.java | 3 + .../com/earth2me/essentials/api/IUser.java | 29 +- .../com/earth2me/essentials/api/IUserMap.java | 2 +- .../essentials/commands/Commandafk.java | 7 +- .../essentials/commands/Commandantioch.java | 4 +- .../essentials/commands/Commandback.java | 4 +- .../commands/EssentialsCommand.java | 20 +- .../commands/IEssentialsCommand.java | 6 +- .../EssentialsBlockListener.java | 6 +- .../EssentialsEntityListener.java | 4 +- .../EssentialsPlayerListener.java | 106 ++-- .../EssentialsPluginListener.java | 4 +- .../{ => listener}/TNTExplodeListener.java | 3 +- .../earth2me/essentials/settings/Chat.java | 8 +- .../essentials/settings/Commands.java | 17 + .../earth2me/essentials/settings/Economy.java | 10 + .../essentials/settings/GroupsHolder.java | 124 ++++ .../essentials/settings/Settings.java | 18 +- .../essentials/settings/SettingsHolder.java | 21 + .../essentials/settings/WorldOptions.java | 14 + .../earth2me/essentials/settings/Worlds.java | 15 + .../essentials/settings/commands/Afk.java | 4 +- .../essentials/settings/commands/Back.java | 19 + .../AbstractDelayedYamlFileReader.java | 2 +- .../AbstractDelayedYamlFileWriter.java | 2 +- .../storage/AsyncStorageObjectHolder.java | 8 +- .../essentials/storage/BukkitConstructor.java | 14 + .../essentials/storage/YamlStorageWriter.java | 9 + .../essentials/user/CooldownException.java | 12 + .../com/earth2me/essentials/user/User.java | 528 +++++++++++++++--- .../earth2me/essentials/user/UserBase.java | 189 ++++++- .../earth2me/essentials/user/UserData.java | 20 +- .../com/earth2me/essentials/user/UserMap.java | 22 +- 57 files changed, 1420 insertions(+), 259 deletions(-) create mode 100644 Essentials/src/com/earth2me/essentials/api/IBackup.java create mode 100644 Essentials/src/com/earth2me/essentials/api/IEssentialsModule.java create mode 100644 Essentials/src/com/earth2me/essentials/api/IGroups.java create mode 100644 Essentials/src/com/earth2me/essentials/api/IReplyTo.java rename Essentials/src/com/earth2me/essentials/{ => listener}/EssentialsBlockListener.java (87%) rename Essentials/src/com/earth2me/essentials/{ => listener}/EssentialsEntityListener.java (96%) rename Essentials/src/com/earth2me/essentials/{ => listener}/EssentialsPlayerListener.java (73%) rename Essentials/src/com/earth2me/essentials/{ => listener}/EssentialsPluginListener.java (93%) rename Essentials/src/com/earth2me/essentials/{ => listener}/TNTExplodeListener.java (92%) create mode 100644 Essentials/src/com/earth2me/essentials/settings/GroupsHolder.java create mode 100644 Essentials/src/com/earth2me/essentials/settings/SettingsHolder.java create mode 100644 Essentials/src/com/earth2me/essentials/settings/WorldOptions.java create mode 100644 Essentials/src/com/earth2me/essentials/settings/Worlds.java create mode 100644 Essentials/src/com/earth2me/essentials/settings/commands/Back.java create mode 100644 Essentials/src/com/earth2me/essentials/user/CooldownException.java diff --git a/Essentials/src/com/earth2me/essentials/AlternativeCommandsHandler.java b/Essentials/src/com/earth2me/essentials/AlternativeCommandsHandler.java index e75644ad5..ee192bce0 100644 --- a/Essentials/src/com/earth2me/essentials/AlternativeCommandsHandler.java +++ b/Essentials/src/com/earth2me/essentials/AlternativeCommandsHandler.java @@ -1,5 +1,6 @@ package com.earth2me.essentials; +import com.earth2me.essentials.api.IAlternativeCommandsHandler; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; @@ -9,7 +10,7 @@ import org.bukkit.command.PluginCommandYamlParser; import org.bukkit.plugin.Plugin; -public class AlternativeCommandsHandler +public class AlternativeCommandsHandler implements IAlternativeCommandsHandler { private static final Logger LOGGER = Logger.getLogger("Minecraft"); private final transient Map> altcommands = new HashMap>(); diff --git a/Essentials/src/com/earth2me/essentials/Backup.java b/Essentials/src/com/earth2me/essentials/Backup.java index ada36c9d7..205dba19e 100644 --- a/Essentials/src/com/earth2me/essentials/Backup.java +++ b/Essentials/src/com/earth2me/essentials/Backup.java @@ -1,23 +1,29 @@ package com.earth2me.essentials; +import com.earth2me.essentials.api.IBackup; import static com.earth2me.essentials.I18n._; +import com.earth2me.essentials.api.IEssentials; +import com.earth2me.essentials.api.ISettings; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; +import lombok.Cleanup; +import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.command.CommandSender; -public class Backup implements Runnable +public class Backup implements Runnable, IBackup { - private static final Logger LOGGER = Logger.getLogger("Minecraft"); + private static final Logger LOGGER = Bukkit.getLogger(); private transient final Server server; private transient final IEssentials ess; - private transient boolean running = false; + private transient final AtomicBoolean running = new AtomicBoolean(false); private transient int taskId = -1; - private transient boolean active = false; + private transient final AtomicBoolean active = new AtomicBoolean(false); public Backup(final IEssentials ess) { @@ -29,34 +35,34 @@ public class Backup implements Runnable } } - void onPlayerJoin() + public void startTask() { - startTask(); - } - - private void startTask() - { - if (!running) + if (running.compareAndSet(false, true)) { - final long interval = ess.getSettings().getBackupInterval() * 1200; // minutes -> ticks + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + final long interval = settings.getData().getGeneral().getBackup().getInterval() * 1200; // minutes -> ticks if (interval < 1200) { + running.set(false); return; } taskId = ess.scheduleSyncRepeatingTask(this, interval, interval); - running = true; } } @Override public void run() { - if (active) + if (!active.compareAndSet(false, true)) { return; } - active = true; - final String command = ess.getSettings().getBackupCommand(); + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + final String command = settings.getData().getGeneral().getBackup().getCommand(); if (command == null || "".equals(command)) { return; @@ -117,13 +123,13 @@ public class Backup implements Runnable server.dispatchCommand(cs, "save-on"); if (server.getOnlinePlayers().length == 0) { - running = false; + running.set(false); if (taskId != -1) { server.getScheduler().cancelTask(taskId); } } - active = false; + active.set(false); LOGGER.log(Level.INFO, _("backupFinished")); } }); diff --git a/Essentials/src/com/earth2me/essentials/Console.java b/Essentials/src/com/earth2me/essentials/Console.java index d07171c63..16a8aefd0 100644 --- a/Essentials/src/com/earth2me/essentials/Console.java +++ b/Essentials/src/com/earth2me/essentials/Console.java @@ -2,6 +2,7 @@ package com.earth2me.essentials; import org.bukkit.Server; import org.bukkit.command.CommandSender; +import com.earth2me.essentials.api.IReplyTo; public final class Console implements IReplyTo @@ -14,13 +15,13 @@ public final class Console implements IReplyTo { } - public static CommandSender getCommandSender(Server server) throws Exception + public static CommandSender getCommandSender(final Server server) throws Exception { return server.getConsoleSender(); } @Override - public void setReplyTo(CommandSender user) + public void setReplyTo(final CommandSender user) { replyTo = user; } diff --git a/Essentials/src/com/earth2me/essentials/Enchantments.java b/Essentials/src/com/earth2me/essentials/Enchantments.java index dac789353..da42bf71c 100644 --- a/Essentials/src/com/earth2me/essentials/Enchantments.java +++ b/Essentials/src/com/earth2me/essentials/Enchantments.java @@ -9,8 +9,13 @@ import java.util.regex.Pattern; import org.bukkit.enchantments.Enchantment; -public class Enchantments +public final class Enchantments { + + private Enchantments() + { + } + private static final transient Pattern NUMPATTERN = Pattern.compile("\\d+"); private static final Map ENCHANTMENTS = new HashMap(); @@ -56,7 +61,7 @@ public class Enchantments ENCHANTMENTS.put("aquaaffinity", Enchantment.WATER_WORKER); } - public static Enchantment getByName(String name) { + public static Enchantment getByName(final String name) { Enchantment enchantment; if (NUMPATTERN.matcher(name).matches()) { enchantment = Enchantment.getById(Integer.parseInt(name)); diff --git a/Essentials/src/com/earth2me/essentials/Essentials.java b/Essentials/src/com/earth2me/essentials/Essentials.java index 10e6f9a4c..6ab74e16c 100644 --- a/Essentials/src/com/earth2me/essentials/Essentials.java +++ b/Essentials/src/com/earth2me/essentials/Essentials.java @@ -19,7 +19,11 @@ package com.earth2me.essentials; import static com.earth2me.essentials.I18n._; import com.earth2me.essentials.api.Economy; +import com.earth2me.essentials.api.IEssentialsEconomy; +import com.earth2me.essentials.api.IGroups; import com.earth2me.essentials.api.IJails; +import com.earth2me.essentials.api.IReload; +import com.earth2me.essentials.api.IWarps; import com.earth2me.essentials.commands.EssentialsCommand; import com.earth2me.essentials.commands.IEssentialsCommand; import com.earth2me.essentials.commands.NoChargeException; @@ -360,7 +364,15 @@ public class Essentials extends JavaPlugin implements IEssentials } else { - cmd.run(getServer(), user, commandLabel, command, args); + user.acquireReadLock(); + try + { + cmd.run(getServer(), user, commandLabel, command, args); + } + finally + { + user.unlock(); + } } return true; } @@ -585,4 +597,46 @@ public class Essentials extends JavaPlugin implements IEssentials { return i18n; } + + @Override + public void addReloadListener(IReload listener) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public int broadcastMessage(com.earth2me.essentials.api.IUser sender, String message) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public IGroups getGroups() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public IWarps getWarps2() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public IEssentialsEconomy getEconomy() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void showCommandError(CommandSender sender, String commandLabel, Throwable exception) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void onReload() + { + throw new UnsupportedOperationException("Not supported yet."); + } } diff --git a/Essentials/src/com/earth2me/essentials/IEssentials.java b/Essentials/src/com/earth2me/essentials/IEssentials.java index 20c6c300e..d1faad0cb 100644 --- a/Essentials/src/com/earth2me/essentials/IEssentials.java +++ b/Essentials/src/com/earth2me/essentials/IEssentials.java @@ -1,5 +1,6 @@ package com.earth2me.essentials; +import com.earth2me.essentials.listener.TNTExplodeListener; import com.earth2me.essentials.api.IJails; import com.earth2me.essentials.perm.PermissionsHandler; import com.earth2me.essentials.register.payment.Methods; @@ -13,7 +14,7 @@ import org.bukkit.scheduler.BukkitScheduler; * @deprecated This will be moved to the api package soon */ @Deprecated -public interface IEssentials extends Plugin +public interface IEssentials extends Plugin, com.earth2me.essentials.api.IEssentials { void addReloadListener(IConf listener); diff --git a/Essentials/src/com/earth2me/essentials/IEssentialsModule.java b/Essentials/src/com/earth2me/essentials/IEssentialsModule.java index 69a1a494c..06ed63e1a 100644 --- a/Essentials/src/com/earth2me/essentials/IEssentialsModule.java +++ b/Essentials/src/com/earth2me/essentials/IEssentialsModule.java @@ -1,6 +1,6 @@ package com.earth2me.essentials; - +@Deprecated public interface IEssentialsModule { } diff --git a/Essentials/src/com/earth2me/essentials/IReplyTo.java b/Essentials/src/com/earth2me/essentials/IReplyTo.java index 5bef5fced..877ecfe13 100644 --- a/Essentials/src/com/earth2me/essentials/IReplyTo.java +++ b/Essentials/src/com/earth2me/essentials/IReplyTo.java @@ -2,6 +2,7 @@ package com.earth2me.essentials; import org.bukkit.command.CommandSender; +@Deprecated public interface IReplyTo { public void setReplyTo(CommandSender user); diff --git a/Essentials/src/com/earth2me/essentials/ISettings.java b/Essentials/src/com/earth2me/essentials/ISettings.java index 5c53a6790..06322d4ed 100644 --- a/Essentials/src/com/earth2me/essentials/ISettings.java +++ b/Essentials/src/com/earth2me/essentials/ISettings.java @@ -7,8 +7,8 @@ import java.util.Set; import org.bukkit.ChatColor; import org.bukkit.event.Event.Priority; - -public interface ISettings extends IConf +@Deprecated +public interface ISettings extends IConf, com.earth2me.essentials.api.ISettings { boolean areSignsDisabled(); diff --git a/Essentials/src/com/earth2me/essentials/IUser.java b/Essentials/src/com/earth2me/essentials/IUser.java index 09d3c294d..ce7e19c77 100644 --- a/Essentials/src/com/earth2me/essentials/IUser.java +++ b/Essentials/src/com/earth2me/essentials/IUser.java @@ -11,7 +11,7 @@ import org.bukkit.inventory.PlayerInventory; * @deprecated This will be moved to the api package soon */ @Deprecated -public interface IUser +public interface IUser extends com.earth2me.essentials.api.IUser { int getHealth(); diff --git a/Essentials/src/com/earth2me/essentials/Jails.java b/Essentials/src/com/earth2me/essentials/Jails.java index 4c1090c5c..2101dfdf6 100644 --- a/Essentials/src/com/earth2me/essentials/Jails.java +++ b/Essentials/src/com/earth2me/essentials/Jails.java @@ -145,7 +145,7 @@ public class Jails extends AsyncStorageObjectHolder 0) + try { - double cooldown = ess.getSettings().getTeleportCooldown(); - Calendar cooldownTime = new GregorianCalendar(); - cooldownTime.setTimeInMillis(user.getLastTeleportTimestamp()); - cooldownTime.add(Calendar.SECOND, (int)cooldown); - cooldownTime.add(Calendar.MILLISECOND, (int)((cooldown * 1000.0) % 1000.0)); - if (cooldownTime.after(now) && !user.isAuthorized("essentials.teleport.cooldown.bypass")) - { - throw new Exception(_("timeBeforeTeleport", Util.formatDateDiff(cooldownTime.getTimeInMillis()))); - } + user.checkCooldown(TimestampType.LASTTELEPORT, ess.getGroups().getTeleportCooldown(user), !check, "essentials.teleport.cooldown.bypass"); } - // if justCheck is set, don't update lastTeleport; we're just checking - if (!check) + catch (CooldownException ex) { - user.setLastTeleportTimestamp(now.getTimeInMillis()); + throw new Exception(_("timeBeforeTeleport", ex.getMessage())); + } } @@ -190,7 +184,7 @@ public class Teleport implements Runnable, ITeleport { cancel(false); } - + public void teleport(Location loc, Trade chargeFor) throws Exception { teleport(new Target(loc), chargeFor, TeleportCause.PLUGIN); @@ -270,12 +264,28 @@ public class Teleport implements Runnable, ITeleport public void back(Trade chargeFor) throws Exception { - teleport(new Target(user.getLastLocation()), chargeFor, TeleportCause.COMMAND); + user.acquireReadLock(); + try + { + teleport(new Target(user.getData().getLastLocation()), chargeFor, TeleportCause.COMMAND); + } + finally + { + user.unlock(); + } } public void back() throws Exception { - now(new Target(user.getLastLocation()), TeleportCause.COMMAND); + user.acquireReadLock(); + try + { + now(new Target(user.getData().getLastLocation()), TeleportCause.COMMAND); + } + finally + { + user.unlock(); + } } public void home(IUser user, String home, Trade chargeFor) throws Exception diff --git a/Essentials/src/com/earth2me/essentials/Trade.java b/Essentials/src/com/earth2me/essentials/Trade.java index 1c8e20db9..fabe1e06c 100644 --- a/Essentials/src/com/earth2me/essentials/Trade.java +++ b/Essentials/src/com/earth2me/essentials/Trade.java @@ -1,6 +1,9 @@ package com.earth2me.essentials; import com.earth2me.essentials.craftbukkit.InventoryWorkaround; +import com.earth2me.essentials.api.IUser; +import com.earth2me.essentials.api.IEssentials; +import com.earth2me.essentials.api.ISettings; import static com.earth2me.essentials.I18n._; import java.io.File; import java.io.FileWriter; @@ -11,6 +14,7 @@ import java.util.Locale; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; +import lombok.Cleanup; import org.bukkit.Location; import org.bukkit.inventory.ItemStack; @@ -37,7 +41,7 @@ public class Trade { this(null, null, items, null, ess); } - + public Trade(final int exp, final IEssentials ess) { this(null, null, null, exp, ess); @@ -69,18 +73,23 @@ public class Trade throw new ChargeException(_("missingItems", getItemStack().getAmount(), getItemStack().getType().toString().toLowerCase(Locale.ENGLISH).replace("_", " "))); } + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + if (command != null && !command.isEmpty() && !user.isAuthorized("essentials.nocommandcost.all") && !user.isAuthorized("essentials.nocommandcost." + command) - && mon < ess.getSettings().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command) - && 0 < ess.getSettings().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command) + && mon < settings.getData().getEconomy().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command) + && 0 < settings.getData().getEconomy().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command) && !user.isAuthorized("essentials.eco.loan")) { throw new ChargeException(_("notEnoughMoney")); } - - if (exp != null && exp > 0 - && user.getTotalExperience() < exp) { + + if (exp != null && exp > 0 + && user.getTotalExperience() < exp) + { throw new ChargeException(_("notEnoughExperience")); } } @@ -144,8 +153,11 @@ public class Trade && !user.isAuthorized("essentials.nocommandcost.all") && !user.isAuthorized("essentials.nocommandcost." + command)) { + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); final double mon = user.getMoney(); - final double cost = ess.getSettings().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command); + final double cost = settings.getData().getEconomy().getCommandCost(command.charAt(0) == '/' ? command.substring(1) : command); if (mon < cost && cost > 0 && !user.isAuthorized("essentials.eco.loan")) { throw new ChargeException(_("notEnoughMoney")); @@ -172,7 +184,7 @@ public class Trade { return itemStack; } - + public Integer getExperience() { return exp; @@ -181,7 +193,10 @@ public class Trade public static void log(String type, String subtype, String event, String sender, Trade charge, String receiver, Trade pay, Location loc, IEssentials ess) { - if (!ess.getSettings().isEcoLogEnabled()) + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + if (!settings.getData().getEconomy().isLogEnabled()) { return; } @@ -221,7 +236,7 @@ public class Trade { sb.append(charge.getMoney()).append(","); sb.append("money").append(","); - sb.append(ess.getSettings().getCurrencySymbol()); + sb.append(settings.getData().getEconomy().getCurrencySymbol()); } if (charge.getExperience() != null) { @@ -252,7 +267,7 @@ public class Trade { sb.append(pay.getMoney()).append(","); sb.append("money").append(","); - sb.append(ess.getSettings().getCurrencySymbol()); + sb.append(settings.getData().getEconomy().getCurrencySymbol()); } if (pay.getExperience() != null) { diff --git a/Essentials/src/com/earth2me/essentials/User.java b/Essentials/src/com/earth2me/essentials/User.java index d07351758..c9a061d38 100644 --- a/Essentials/src/com/earth2me/essentials/User.java +++ b/Essentials/src/com/earth2me/essentials/User.java @@ -3,6 +3,8 @@ package com.earth2me.essentials; import static com.earth2me.essentials.I18n._; import com.earth2me.essentials.commands.IEssentialsCommand; import com.earth2me.essentials.register.payment.Method; +import com.earth2me.essentials.user.CooldownException; +import com.earth2me.essentials.user.UserData.TimestampType; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.logging.Level; @@ -12,7 +14,7 @@ import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; - +@Deprecated public class User extends UserData implements Comparable, IReplyTo, IUser { private CommandSender replyTo = null; @@ -544,4 +546,52 @@ public class User extends UserData implements Comparable, IReplyTo, IUser { return teleportRequestTime; } + + @Override + public void onReload() + { + reloadConfig(); + } + + @Override + public void checkCooldown(TimestampType cooldownType, double cooldown, boolean set, String bypassPermission) throws CooldownException + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public com.earth2me.essentials.user.UserData getData() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void acquireReadLock() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void acquireWriteLock() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void close() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void unlock() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void updateDisplayName() + { + throw new UnsupportedOperationException("Not supported yet."); + } } diff --git a/Essentials/src/com/earth2me/essentials/UserData.java b/Essentials/src/com/earth2me/essentials/UserData.java index 9df1b0342..2febe577a 100644 --- a/Essentials/src/com/earth2me/essentials/UserData.java +++ b/Essentials/src/com/earth2me/essentials/UserData.java @@ -8,7 +8,7 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; - +@Deprecated public abstract class UserData extends PlayerExtension implements IConf { protected final transient IEssentials ess; diff --git a/Essentials/src/com/earth2me/essentials/UserMap.java b/Essentials/src/com/earth2me/essentials/UserMap.java index 467c2693b..2c17fad98 100644 --- a/Essentials/src/com/earth2me/essentials/UserMap.java +++ b/Essentials/src/com/earth2me/essentials/UserMap.java @@ -1,5 +1,6 @@ package com.earth2me.essentials; +import com.earth2me.essentials.api.IUserMap; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -12,8 +13,8 @@ import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.ExecutionException; import org.bukkit.entity.Player; - -public class UserMap extends CacheLoader implements IConf +@Deprecated +public class UserMap extends CacheLoader implements IConf, IUserMap { private final transient IEssentials ess; private final transient Cache users = CacheBuilder.newBuilder().softValues().build(this); @@ -121,4 +122,10 @@ public class UserMap extends CacheLoader implements IConf final File userFolder = new File(ess.getDataFolder(), "userdata"); return new File(userFolder, Util.sanitizeFileName(name) + ".yml"); } + + @Override + public void onReload() + { + loadAllUsersAsync(ess); + } } diff --git a/Essentials/src/com/earth2me/essentials/Util.java b/Essentials/src/com/earth2me/essentials/Util.java index fe86fd167..bfabf1b02 100644 --- a/Essentials/src/com/earth2me/essentials/Util.java +++ b/Essentials/src/com/earth2me/essentials/Util.java @@ -13,18 +13,30 @@ import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.ItemStack; +import org.bukkit.permissions.Permission; +import org.bukkit.permissions.PermissionDefault; +import org.bukkit.plugin.PluginManager; public class Util { + + private Util() { } private final static Logger logger = Logger.getLogger("Minecraft"); + + private static Pattern unsafeChars = Pattern.compile("[^a-z0-9]"); public static String sanitizeFileName(String name) { - return name.toLowerCase(Locale.ENGLISH).replaceAll("[^a-z0-9]", "_"); + return unsafeChars.matcher(name.toLowerCase(Locale.ENGLISH)).replaceAll("_"); + } + + public static String sanitizeKey(String name) + { + return unsafeChars.matcher(name.toLowerCase(Locale.ENGLISH)).replaceAll("_"); } public static String formatDateDiff(long date) @@ -477,4 +489,44 @@ public class Util } return buf.toString(); } + + public static void registerPermissions(String path, Collection nodes, boolean hasDefault, IEssentials ess) + { + if (nodes == null || nodes.isEmpty()) + { + return; + } + final PluginManager pluginManager = ess.getServer().getPluginManager(); + Permission basePerm = pluginManager.getPermission(path +".*"); + if (basePerm != null && !basePerm.getChildren().isEmpty()) + { + basePerm.getChildren().clear(); + } + if (basePerm == null) + { + basePerm = new Permission(path + ".*", PermissionDefault.OP); + pluginManager.addPermission(basePerm); + Permission mainPerm = pluginManager.getPermission("essentials.*"); + if (mainPerm == null) + { + mainPerm = new Permission("essentials.*", PermissionDefault.OP); + pluginManager.addPermission(mainPerm); + } + mainPerm.getChildren().put(basePerm.getName(), Boolean.TRUE); + } + + for (String nodeName : nodes) + { + final String permissionName = path + "." + nodeName; + Permission perm = pluginManager.getPermission(permissionName); + if (perm == null) + { + final PermissionDefault defaultPerm = hasDefault && nodeName.equalsIgnoreCase("default") ? PermissionDefault.TRUE : PermissionDefault.OP; + perm = new Permission(permissionName, defaultPerm); + pluginManager.addPermission(perm); + } + basePerm.getChildren().put(permissionName, Boolean.TRUE); + } + basePerm.recalculatePermissibles(); + } } diff --git a/Essentials/src/com/earth2me/essentials/Worth.java b/Essentials/src/com/earth2me/essentials/Worth.java index b597bd3e8..dba4cbb15 100644 --- a/Essentials/src/com/earth2me/essentials/Worth.java +++ b/Essentials/src/com/earth2me/essentials/Worth.java @@ -1,12 +1,13 @@ package com.earth2me.essentials; +import com.earth2me.essentials.api.IWorth; import java.io.File; import java.util.Locale; import java.util.logging.Logger; import org.bukkit.inventory.ItemStack; -public class Worth implements IConf +public class Worth implements IConf, IWorth { private static final Logger logger = Logger.getLogger("Minecraft"); private final EssentialsConf config; @@ -58,4 +59,10 @@ public class Worth implements IConf { config.load(); } + + @Override + public void onReload() + { + reloadConfig(); + } } diff --git a/Essentials/src/com/earth2me/essentials/api/IBackup.java b/Essentials/src/com/earth2me/essentials/api/IBackup.java new file mode 100644 index 000000000..8af074c54 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/api/IBackup.java @@ -0,0 +1,7 @@ +package com.earth2me.essentials.api; + + +public interface IBackup extends Runnable +{ + public void startTask(); +} diff --git a/Essentials/src/com/earth2me/essentials/api/IEssentials.java b/Essentials/src/com/earth2me/essentials/api/IEssentials.java index c04bed0bd..5431a0bd8 100644 --- a/Essentials/src/com/earth2me/essentials/api/IEssentials.java +++ b/Essentials/src/com/earth2me/essentials/api/IEssentials.java @@ -18,16 +18,20 @@ public interface IEssentials extends Plugin, IReload II18n getI18n(); ISettings getSettings(); + + IGroups getGroups(); - IJails getJail(); + IJails getJails(); - IWarps getWarps(); + IWarps getWarps2(); IWorth getWorth(); IItemDb getItemDb(); IUserMap getUserMap(); + + IBackup getBackup(); IEssentialsEconomy getEconomy(); diff --git a/Essentials/src/com/earth2me/essentials/api/IEssentialsModule.java b/Essentials/src/com/earth2me/essentials/api/IEssentialsModule.java new file mode 100644 index 000000000..eea919f9d --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/api/IEssentialsModule.java @@ -0,0 +1,5 @@ +package com.earth2me.essentials.api; + +public interface IEssentialsModule +{ +} diff --git a/Essentials/src/com/earth2me/essentials/api/IGroups.java b/Essentials/src/com/earth2me/essentials/api/IGroups.java new file mode 100644 index 000000000..1e1b229a4 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/api/IGroups.java @@ -0,0 +1,16 @@ +package com.earth2me.essentials.api; + +import com.earth2me.essentials.settings.Groups; +import com.earth2me.essentials.storage.IStorageObjectHolder; + + +public interface IGroups extends IStorageObjectHolder +{ + double getHealCooldown(IUser player); + + double getTeleportCooldown(IUser player); + + String getPrefix(IUser player); + + String getSuffix(IUser player); +} diff --git a/Essentials/src/com/earth2me/essentials/api/IReplyTo.java b/Essentials/src/com/earth2me/essentials/api/IReplyTo.java new file mode 100644 index 000000000..c2a1deec5 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/api/IReplyTo.java @@ -0,0 +1,9 @@ +package com.earth2me.essentials.api; + +import org.bukkit.command.CommandSender; + +public interface IReplyTo { + void setReplyTo(CommandSender user); + + CommandSender getReplyTo(); +} diff --git a/Essentials/src/com/earth2me/essentials/api/ITeleport.java b/Essentials/src/com/earth2me/essentials/api/ITeleport.java index 5b9a19757..2f2bd9a5e 100644 --- a/Essentials/src/com/earth2me/essentials/api/ITeleport.java +++ b/Essentials/src/com/earth2me/essentials/api/ITeleport.java @@ -1,5 +1,6 @@ package com.earth2me.essentials.api; +import com.earth2me.essentials.Trade; import org.bukkit.Location; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; @@ -7,4 +8,6 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; public interface ITeleport { void now(Location loc, boolean cooldown, TeleportCause cause) throws Exception; + + void back(Trade chargeFor) throws Exception; } diff --git a/Essentials/src/com/earth2me/essentials/api/IUser.java b/Essentials/src/com/earth2me/essentials/api/IUser.java index 5d2f9d4b8..497303ca9 100644 --- a/Essentials/src/com/earth2me/essentials/api/IUser.java +++ b/Essentials/src/com/earth2me/essentials/api/IUser.java @@ -1,24 +1,21 @@ package com.earth2me.essentials.api; import com.earth2me.essentials.commands.IEssentialsCommand; +import com.earth2me.essentials.storage.IStorageObjectHolder; +import com.earth2me.essentials.user.CooldownException; +import com.earth2me.essentials.user.UserData; import org.bukkit.Location; import org.bukkit.entity.Player; -public interface IUser extends Player, IReload +public interface IUser extends Player, IStorageObjectHolder, IReload, IReplyTo { - long getLastTeleportTimestamp(); - boolean isAuthorized(String node); boolean isAuthorized(IEssentialsCommand cmd); boolean isAuthorized(IEssentialsCommand cmd, String permissionPrefix); - void setLastTeleportTimestamp(long time); - - Location getLastLocation(); - Player getBase(); double getMoney(); @@ -36,8 +33,22 @@ public interface IUser extends Player, IReload Location getHome(Location loc) throws Exception; boolean isHidden(); - + ITeleport getTeleport(); + + void checkCooldown(UserData.TimestampType cooldownType, double cooldown, boolean set, String bypassPermission) throws CooldownException; + + boolean toggleAfk(); - void setJail(String jail); + void updateActivity(boolean broadcast); + + void updateDisplayName(); + + boolean checkJailTimeout(final long currentTime); + + boolean checkMuteTimeout(final long currentTime); + + boolean checkBanTimeout(final long currentTime); + + void setTimestamp(final UserData.TimestampType name, final long value); } diff --git a/Essentials/src/com/earth2me/essentials/api/IUserMap.java b/Essentials/src/com/earth2me/essentials/api/IUserMap.java index 9e609ab37..2f79d73c9 100644 --- a/Essentials/src/com/earth2me/essentials/api/IUserMap.java +++ b/Essentials/src/com/earth2me/essentials/api/IUserMap.java @@ -4,7 +4,7 @@ import java.io.File; import java.util.Set; -public interface IUserMap +public interface IUserMap extends IReload { boolean userExists(final String name); diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandafk.java b/Essentials/src/com/earth2me/essentials/commands/Commandafk.java index a1c83606c..4962cba5e 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandafk.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandafk.java @@ -2,6 +2,7 @@ package com.earth2me.essentials.commands; import static com.earth2me.essentials.I18n._; import com.earth2me.essentials.User; +import com.earth2me.essentials.api.IUser; import org.bukkit.Server; @@ -13,11 +14,11 @@ public class Commandafk extends EssentialsCommand } @Override - public void run(Server server, User user, String commandLabel, String[] args) throws Exception + public void run(Server server, IUser user, String commandLabel, String[] args) throws Exception { if (args.length > 0 && user.isAuthorized("essentials.afk.others")) { - User afkUser = ess.getUser(ess.getServer().matchPlayer(args[0])); + IUser afkUser = ess.getUser(ess.getServer().matchPlayer(args[0])); if (afkUser != null) { toggleAfk(afkUser); @@ -29,7 +30,7 @@ public class Commandafk extends EssentialsCommand } } - private void toggleAfk(User user) + private void toggleAfk(IUser user) { if (!user.toggleAfk()) { diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandantioch.java b/Essentials/src/com/earth2me/essentials/commands/Commandantioch.java index 54277d466..03eaa88ec 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandantioch.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandantioch.java @@ -1,7 +1,7 @@ package com.earth2me.essentials.commands; -import com.earth2me.essentials.User; import com.earth2me.essentials.Util; +import com.earth2me.essentials.api.IUser; import org.bukkit.Location; import org.bukkit.Server; import org.bukkit.entity.TNTPrimed; @@ -15,7 +15,7 @@ public class Commandantioch extends EssentialsCommand } @Override - public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception + public void run(final Server server, final IUser user, final String commandLabel, final String[] args) throws Exception { ess.broadcastMessage(user, "...lobbest thou thy Holy Hand Grenade of Antioch towards thy foe,"); ess.broadcastMessage(user, "who being naughty in My sight, shall snuff it."); diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandback.java b/Essentials/src/com/earth2me/essentials/commands/Commandback.java index 67698598a..ae36087c2 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandback.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandback.java @@ -2,7 +2,7 @@ package com.earth2me.essentials.commands; import static com.earth2me.essentials.I18n._; import com.earth2me.essentials.Trade; -import com.earth2me.essentials.User; +import com.earth2me.essentials.api.IUser; import org.bukkit.Server; @@ -14,7 +14,7 @@ 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(final Server server, final IUser user, final String commandLabel, final String[] args) throws Exception { final Trade charge = new Trade(this.getName(), ess); charge.isAffordableFor(user); diff --git a/Essentials/src/com/earth2me/essentials/commands/EssentialsCommand.java b/Essentials/src/com/earth2me/essentials/commands/EssentialsCommand.java index 13328e1b5..1daf67b32 100644 --- a/Essentials/src/com/earth2me/essentials/commands/EssentialsCommand.java +++ b/Essentials/src/com/earth2me/essentials/commands/EssentialsCommand.java @@ -1,11 +1,11 @@ package com.earth2me.essentials.commands; import static com.earth2me.essentials.I18n._; -import com.earth2me.essentials.IEssentials; +import com.earth2me.essentials.api.IEssentials; import com.earth2me.essentials.IEssentialsModule; import com.earth2me.essentials.OfflinePlayer; import com.earth2me.essentials.Trade; -import com.earth2me.essentials.User; +import com.earth2me.essentials.api.IUser; import java.util.List; import java.util.logging.Logger; import org.bukkit.Server; @@ -44,12 +44,12 @@ public abstract class EssentialsCommand implements IEssentialsCommand return name; } - protected User getPlayer(final Server server, final String[] args, final int pos) throws NoSuchFieldException, NotEnoughArgumentsException + protected IUser getPlayer(final Server server, final String[] args, final int pos) throws NoSuchFieldException, NotEnoughArgumentsException { return getPlayer(server, args, pos, false); } - protected User getPlayer(final Server server, final String[] args, final int pos, final boolean getOffline) throws NoSuchFieldException, NotEnoughArgumentsException + protected IUser getPlayer(final Server server, final String[] args, final int pos, final boolean getOffline) throws NoSuchFieldException, NotEnoughArgumentsException { if (args.length <= pos) { @@ -59,7 +59,7 @@ public abstract class EssentialsCommand implements IEssentialsCommand { throw new NoSuchFieldException(_("playerNotFound")); } - final User user = ess.getUser(args[pos]); + final IUser user = ess.getUser(args[pos]); if (user != null) { if (!getOffline && (user.getBase() instanceof OfflinePlayer || user.isHidden())) @@ -74,13 +74,13 @@ public abstract class EssentialsCommand implements IEssentialsCommand { for (Player player : matches) { - final User userMatch = ess.getUser(player); + final IUser userMatch = ess.getUser(player); if (userMatch.getDisplayName().startsWith(args[pos]) && (getOffline || !userMatch.isHidden())) { return userMatch; } } - final User userMatch = ess.getUser(matches.get(0)); + final IUser userMatch = ess.getUser(matches.get(0)); if (getOffline || !userMatch.isHidden()) { return userMatch; @@ -90,15 +90,15 @@ public abstract class EssentialsCommand implements IEssentialsCommand } @Override - public final void run(final Server server, final User user, final String commandLabel, final Command cmd, final String[] args) throws Exception + public final void run(final Server server, final IUser user, final String commandLabel, final Command cmd, final String[] args) throws Exception { - final Trade charge = new Trade(this.getName(), ess); + final Trade charge = new Trade(this.getName(), (com.earth2me.essentials.IEssentials)ess); charge.isAffordableFor(user); run(server, user, commandLabel, args); charge.charge(user); } - protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception + protected void run(final Server server, final IUser user, final String commandLabel, final String[] args) throws Exception { run(server, (CommandSender)user.getBase(), commandLabel, args); } diff --git a/Essentials/src/com/earth2me/essentials/commands/IEssentialsCommand.java b/Essentials/src/com/earth2me/essentials/commands/IEssentialsCommand.java index 439c14d70..0143bade4 100644 --- a/Essentials/src/com/earth2me/essentials/commands/IEssentialsCommand.java +++ b/Essentials/src/com/earth2me/essentials/commands/IEssentialsCommand.java @@ -1,8 +1,8 @@ package com.earth2me.essentials.commands; -import com.earth2me.essentials.IEssentials; import com.earth2me.essentials.IEssentialsModule; -import com.earth2me.essentials.User; +import com.earth2me.essentials.api.IEssentials; +import com.earth2me.essentials.api.IUser; import org.bukkit.Server; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -12,7 +12,7 @@ public interface IEssentialsCommand { String getName(); - void run(Server server, User user, String commandLabel, Command cmd, String[] args) + void run(Server server, IUser user, String commandLabel, Command cmd, String[] args) throws Exception; void run(Server server, CommandSender sender, String commandLabel, Command cmd, String[] args) diff --git a/Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java b/Essentials/src/com/earth2me/essentials/listener/EssentialsBlockListener.java similarity index 87% rename from Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java rename to Essentials/src/com/earth2me/essentials/listener/EssentialsBlockListener.java index ceda6a60c..76329ad72 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsBlockListener.java +++ b/Essentials/src/com/earth2me/essentials/listener/EssentialsBlockListener.java @@ -1,8 +1,10 @@ -package com.earth2me.essentials; +package com.earth2me.essentials.listener; +import com.earth2me.essentials.IEssentials; +import com.earth2me.essentials.User; +import com.earth2me.essentials.Util; import java.util.logging.Logger; import org.bukkit.GameMode; -import org.bukkit.Material; import org.bukkit.event.block.BlockListener; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; diff --git a/Essentials/src/com/earth2me/essentials/EssentialsEntityListener.java b/Essentials/src/com/earth2me/essentials/listener/EssentialsEntityListener.java similarity index 96% rename from Essentials/src/com/earth2me/essentials/EssentialsEntityListener.java rename to Essentials/src/com/earth2me/essentials/listener/EssentialsEntityListener.java index 214fc8c01..1ead71451 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsEntityListener.java +++ b/Essentials/src/com/earth2me/essentials/listener/EssentialsEntityListener.java @@ -1,5 +1,7 @@ -package com.earth2me.essentials; +package com.earth2me.essentials.listener; +import com.earth2me.essentials.IEssentials; +import com.earth2me.essentials.User; import static com.earth2me.essentials.I18n._; import java.util.List; import java.util.logging.Logger; diff --git a/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java b/Essentials/src/com/earth2me/essentials/listener/EssentialsPlayerListener.java similarity index 73% rename from Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java rename to Essentials/src/com/earth2me/essentials/listener/EssentialsPlayerListener.java index a90e98013..5ca77e91a 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsPlayerListener.java +++ b/Essentials/src/com/earth2me/essentials/listener/EssentialsPlayerListener.java @@ -1,11 +1,16 @@ -package com.earth2me.essentials; +package com.earth2me.essentials.listener; +import com.earth2me.essentials.api.ISettings; +import com.earth2me.essentials.api.IEssentials; +import com.earth2me.essentials.api.IUser; +import com.earth2me.essentials.Util; import static com.earth2me.essentials.I18n._; import com.earth2me.essentials.craftbukkit.SetBed; import com.earth2me.essentials.textreader.IText; import com.earth2me.essentials.textreader.KeywordReplacer; import com.earth2me.essentials.textreader.TextInput; import com.earth2me.essentials.textreader.TextPager; +import com.earth2me.essentials.user.UserData.TimestampType; import java.io.IOException; import java.util.Arrays; import java.util.Iterator; @@ -13,6 +18,7 @@ import java.util.List; import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; +import lombok.Cleanup; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Server; @@ -40,7 +46,7 @@ public class EssentialsPlayerListener extends PlayerListener @Override public void onPlayerRespawn(final PlayerRespawnEvent event) { - final User user = ess.getUser(event.getPlayer()); + final IUser user = ess.getUser(event.getPlayer()); updateCompass(user); if (ess.getSettings().changeDisplayName()) { @@ -128,32 +134,35 @@ public class EssentialsPlayerListener extends PlayerListener @Override public void onPlayerJoin(final PlayerJoinEvent event) { - ess.getBackup().onPlayerJoin(); - final User user = ess.getUser(event.getPlayer()); + ess.getBackup().startTask(); + @Cleanup + final IUser user = ess.getUser(event.getPlayer()); + user.acquireWriteLock(); - if (ess.getSettings().changeDisplayName()) - { - user.setDisplayNick(); - } - user.setLastLoginAddress(user.getAddress().getAddress().getHostAddress()); + user.updateDisplayName(); + user.getData().setIpAddress(user.getAddress().getAddress().getHostAddress()); user.updateActivity(false); if (user.isAuthorized("essentials.sleepingignored")) { user.setSleepingIgnored(true); } - if (!ess.getSettings().isCommandDisabled("motd") && user.isAuthorized("essentials.motd")) + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + + if (!settings.getData().getCommands().isDisabled("motd") && user.isAuthorized("essentials.motd")) { try { - final IText input = new TextInput(user, "motd", true, ess); - final IText output = new KeywordReplacer(input, user, ess); + final IText input = new TextInput(user, "motd", true, (com.earth2me.essentials.IEssentials)ess); + final IText output = new KeywordReplacer(input, user, (com.earth2me.essentials.IEssentials)ess); final TextPager pager = new TextPager(output, true); pager.showPage("1", null, "motd", user); } catch (IOException ex) { - if (ess.getSettings().isDebug()) + if (settings.getData().getGeneral().isDebug()) { LOGGER.log(Level.WARNING, ex.getMessage(), ex); } @@ -164,10 +173,10 @@ public class EssentialsPlayerListener extends PlayerListener } } - if (!ess.getSettings().isCommandDisabled("mail") && user.isAuthorized("essentials.mail")) + if (!settings.getData().getCommands().isDisabled("mail") && user.isAuthorized("essentials.mail")) { - final List mail = user.getMails(); - if (mail.isEmpty()) + final List mail = user.getData().getMails(); + if (mail == null || mail.isEmpty()) { user.sendMessage(_("noNewMail")); } @@ -186,17 +195,19 @@ public class EssentialsPlayerListener extends PlayerListener LOGGER.log(Level.INFO, "Disconnecting user " + event.getPlayer().toString() + " due to " + event.getResult().toString()); return; } - User user = ess.getUser(event.getPlayer()); - user.setNPC(false); + @Cleanup + final IUser user = ess.getUser(event.getPlayer()); + user.acquireWriteLock(); + user.getData().setNpc(false); final long currentTime = System.currentTimeMillis(); final boolean banExpired = user.checkBanTimeout(currentTime); user.checkMuteTimeout(currentTime); user.checkJailTimeout(currentTime); - if (banExpired == false && (user.isBanned() || event.getResult() == Result.KICK_BANNED)) + if (!banExpired && (user.isBanned() || event.getResult() == Result.KICK_BANNED)) { - final String banReason = user.getBanReason(); + final String banReason = user.getData().getBan() == null ? "" : user.getData().getBan().getReason(); event.disallow(Result.KICK_BANNED, banReason != null && !banReason.isEmpty() && !banReason.equalsIgnoreCase("ban") ? banReason : _("defaultBanReason")); return; } @@ -208,11 +219,11 @@ public class EssentialsPlayerListener extends PlayerListener } event.allow(); - user.setLastLogin(System.currentTimeMillis()); + user.setTimestamp(TimestampType.LOGIN, System.currentTimeMillis()); updateCompass(user); } - private void updateCompass(final User user) + private void updateCompass(final IUser user) { Location loc = user.getHome(user.getLocation()); if (loc == null) @@ -233,26 +244,28 @@ public class EssentialsPlayerListener extends PlayerListener return; } - final User user = ess.getUser(event.getPlayer()); + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + final IUser user = ess.getUser(event.getPlayer()); //There is TeleportCause.COMMMAND but plugins have to actively pass the cause in on their teleports. - if ((event.getCause() == TeleportCause.PLUGIN || event.getCause() == TeleportCause.COMMAND) && ess.getSettings().registerBackInListener()) + if ((event.getCause() == TeleportCause.PLUGIN || event.getCause() == TeleportCause.COMMAND) && settings.getData().getCommands().getBack().isRegisterBackInListener()) { user.setLastLocation(); } - if (ess.getSettings().changeDisplayName()) - { - user.setDisplayNick(); - } + user.updateDisplayName(); updateCompass(user); } @Override public void onPlayerEggThrow(final PlayerEggThrowEvent event) { - final User user = ess.getUser(event.getPlayer()); + @Cleanup + final IUser user = ess.getUser(event.getPlayer()); + user.acquireReadLock(); final ItemStack is = new ItemStack(Material.EGG, 1); - if (user.hasUnlimited(is)) + if (user.getData().hasUnlimited(is.getType())) { user.getInventory().addItem(is); user.updateInventory(); @@ -262,8 +275,10 @@ public class EssentialsPlayerListener extends PlayerListener @Override public void onPlayerBucketEmpty(final PlayerBucketEmptyEvent event) { - final User user = ess.getUser(event.getPlayer()); - if (user.hasUnlimited(new ItemStack(event.getBucket()))) + @Cleanup + final IUser user = ess.getUser(event.getPlayer()); + user.acquireReadLock(); + if (user.getData().hasUnlimited(event.getBucket())) { event.getItemStack().setType(event.getBucket()); ess.scheduleSyncDelayedTask(new Runnable() @@ -280,7 +295,7 @@ public class EssentialsPlayerListener extends PlayerListener @Override public void onPlayerAnimation(final PlayerAnimationEvent event) { - final User user = ess.getUser(event.getPlayer()); + final IUser user = ess.getUser(event.getPlayer()); user.updateActivity(true); usePowertools(event); } @@ -291,13 +306,15 @@ public class EssentialsPlayerListener extends PlayerListener { return; } - final User user = ess.getUser(event.getPlayer()); + @Cleanup + final IUser user = ess.getUser(event.getPlayer()); + user.acquireReadLock(); final ItemStack is = user.getItemInHand(); - if (is == null || is.getType() == Material.AIR || !user.arePowerToolsEnabled()) + if (is == null || is.getType() == Material.AIR || !user.getData().isPowertoolsenabled()) { return; } - final List commandList = user.getPowertool(is); + final List commandList = user.getData().getPowertool(is.getType()); if (commandList == null || commandList.isEmpty()) { return; @@ -332,15 +349,17 @@ public class EssentialsPlayerListener extends PlayerListener { return; } - final User user = ess.getUser(event.getPlayer()); + final IUser user = ess.getUser(event.getPlayer()); final String cmd = event.getMessage().toLowerCase(Locale.ENGLISH).split(" ")[0].replace("/", "").toLowerCase(Locale.ENGLISH); final List commands = Arrays.asList("msg", "r", "mail", "m", "t", "emsg", "tell", "er", "reply", "ereply", "email"); if (commands.contains(cmd)) { for (Player player : ess.getServer().getOnlinePlayers()) { - User spyer = ess.getUser(player); - if (spyer.isSocialSpyEnabled() && !user.equals(spyer)) + @Cleanup + IUser spyer = ess.getUser(player); + spyer.acquireReadLock(); + if (spyer.getData().isSocialspy() && !user.equals(spyer)) { player.sendMessage(user.getDisplayName() + " : " + event.getMessage()); } @@ -355,9 +374,14 @@ public class EssentialsPlayerListener extends PlayerListener @Override public void onPlayerChangedWorld(final PlayerChangedWorldEvent event) { - if (ess.getSettings().getNoGodWorlds().contains(event.getPlayer().getLocation().getWorld().getName())) + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + if (!settings.getData().getWorldOptions(event.getPlayer().getLocation().getWorld().getName()).isGodmode()) { - User user = ess.getUser(event.getPlayer()); + @Cleanup + final IUser user = ess.getUser(event.getPlayer()); + user.acquireReadLock(); if (user.isGodModeEnabledRaw()) { user.sendMessage(_("noGodWorldWarning")); diff --git a/Essentials/src/com/earth2me/essentials/EssentialsPluginListener.java b/Essentials/src/com/earth2me/essentials/listener/EssentialsPluginListener.java similarity index 93% rename from Essentials/src/com/earth2me/essentials/EssentialsPluginListener.java rename to Essentials/src/com/earth2me/essentials/listener/EssentialsPluginListener.java index b0ee0b543..3f87bf731 100644 --- a/Essentials/src/com/earth2me/essentials/EssentialsPluginListener.java +++ b/Essentials/src/com/earth2me/essentials/listener/EssentialsPluginListener.java @@ -1,5 +1,7 @@ -package com.earth2me.essentials; +package com.earth2me.essentials.listener; +import com.earth2me.essentials.IConf; +import com.earth2me.essentials.IEssentials; import java.util.logging.Level; import java.util.logging.Logger; import org.bukkit.event.server.PluginDisableEvent; diff --git a/Essentials/src/com/earth2me/essentials/TNTExplodeListener.java b/Essentials/src/com/earth2me/essentials/listener/TNTExplodeListener.java similarity index 92% rename from Essentials/src/com/earth2me/essentials/TNTExplodeListener.java rename to Essentials/src/com/earth2me/essentials/listener/TNTExplodeListener.java index 4ae259a32..76bd87bb2 100644 --- a/Essentials/src/com/earth2me/essentials/TNTExplodeListener.java +++ b/Essentials/src/com/earth2me/essentials/listener/TNTExplodeListener.java @@ -1,5 +1,6 @@ -package com.earth2me.essentials; +package com.earth2me.essentials.listener; +import com.earth2me.essentials.IEssentials; import com.earth2me.essentials.craftbukkit.FakeExplosion; import org.bukkit.entity.LivingEntity; import org.bukkit.event.entity.EntityExplodeEvent; diff --git a/Essentials/src/com/earth2me/essentials/settings/Chat.java b/Essentials/src/com/earth2me/essentials/settings/Chat.java index 623228c4e..82a18e051 100644 --- a/Essentials/src/com/earth2me/essentials/settings/Chat.java +++ b/Essentials/src/com/earth2me/essentials/settings/Chat.java @@ -12,8 +12,12 @@ public class Chat implements StorageObject { @Comment("The character(s) to prefix all nicknames, so that you know they are not true usernames.") private String nicknamePrefix = "~"; - @Comment("Disable this if you have any other plugin, that modifies the displayname of a user.") - private boolean changeDisplayname = true; + @Comment( + { + "Disable this if you have any other plugin, that modifies the displayname of a user.", + "If it is not set, it will be enabled if EssentialsChat is installed, otherwise not." + }) + private Boolean changeDisplayname; private String displaynameFormat = "{PREFIX}{NICKNAMEPREFIX}{NAME}{SUFFIX}"; @Comment( { diff --git a/Essentials/src/com/earth2me/essentials/settings/Commands.java b/Essentials/src/com/earth2me/essentials/settings/Commands.java index 08efc881c..27b8f4e2c 100644 --- a/Essentials/src/com/earth2me/essentials/settings/Commands.java +++ b/Essentials/src/com/earth2me/essentials/settings/Commands.java @@ -15,6 +15,7 @@ import lombok.EqualsAndHashCode; public class Commands implements StorageObject { private Afk afk = new Afk(); + private Back back = new Back(); private God god = new God(); private Help help = new Help(); private Home home = new Home(); @@ -37,4 +38,20 @@ public class Commands implements StorageObject @ListType @Comment("Disabled commands will be completelly unavailable on the server.") private List disabled = new ArrayList(); + + public boolean isDisabled(final String commandName) + { + if (disabled == null) + { + return false; + } + for (String disabledCommand : disabled) + { + if (commandName.equalsIgnoreCase(disabledCommand)) + { + return true; + } + } + return false; + } } diff --git a/Essentials/src/com/earth2me/essentials/settings/Economy.java b/Essentials/src/com/earth2me/essentials/settings/Economy.java index 5872dada9..2019ac583 100644 --- a/Essentials/src/com/earth2me/essentials/settings/Economy.java +++ b/Essentials/src/com/earth2me/essentials/settings/Economy.java @@ -40,4 +40,14 @@ public class Economy implements StorageObject @Comment("Enable this to log all interactions with trade/buy/sell signs and sell command") private boolean logEnabled = false; private Worth worth = new Worth(); + + public double getCommandCost(String command) + { + if (commandCosts == null) + { + return 0; + } + Double price = commandCosts.get(command); + return price == null || Double.isNaN(price) || Double.isInfinite(price) ? 0 : price; + } } diff --git a/Essentials/src/com/earth2me/essentials/settings/GroupsHolder.java b/Essentials/src/com/earth2me/essentials/settings/GroupsHolder.java new file mode 100644 index 000000000..39609553f --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/settings/GroupsHolder.java @@ -0,0 +1,124 @@ +package com.earth2me.essentials.settings; + +import com.earth2me.essentials.Util; +import com.earth2me.essentials.api.IEssentials; +import com.earth2me.essentials.api.IGroups; +import com.earth2me.essentials.api.IUser; +import com.earth2me.essentials.storage.AsyncStorageObjectHolder; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Map.Entry; + + +public class GroupsHolder extends AsyncStorageObjectHolder implements IGroups +{ + public GroupsHolder(final IEssentials ess) + { + super(ess, Groups.class); + } + + @Override + public File getStorageFile() + { + return new File(ess.getDataFolder(), "groups.yml"); + } + + public void registerPermissions() + { + acquireReadLock(); + try + { + final Map groups = getData().getGroups(); + if (groups == null || groups.isEmpty()) + { + return; + } + Util.registerPermissions("essentials.groups", groups.keySet(), true, (com.earth2me.essentials.IEssentials)ess); + } + finally + { + unlock(); + } + } + + public Collection getGroups(final IUser player) + { + acquireReadLock(); + try + { + final Map groups = getData().getGroups(); + if (groups == null || groups.isEmpty()) + { + return Collections.emptyList(); + } + final ArrayList list = new ArrayList(); + for (Entry entry : groups.entrySet()) + { + if (player.isAuthorized("essentials.groups." + entry.getKey())) + { + list.add(entry.getValue()); + } + } + return list; + } + finally + { + unlock(); + } + } + + @Override + public double getHealCooldown(final IUser player) + { + for (GroupOptions groupOptions : getGroups(player)) + { + if (groupOptions.getHealCooldown() != null) + { + return groupOptions.getHealCooldown(); + } + } + return 0; + } + + @Override + public double getTeleportCooldown(final IUser player) + { + for (GroupOptions groupOptions : getGroups(player)) + { + if (groupOptions.getTeleportCooldown() != null) + { + return groupOptions.getTeleportCooldown(); + } + } + return 0; + } + + @Override + public String getPrefix(final IUser player) + { + for (GroupOptions groupOptions : getGroups(player)) + { + if (groupOptions.getPrefix() != null) + { + return groupOptions.getPrefix(); + } + } + return ""; + } + + @Override + public String getSuffix(final IUser player) + { + for (GroupOptions groupOptions : getGroups(player)) + { + if (groupOptions.getSuffix() != null) + { + return groupOptions.getSuffix(); + } + } + return ""; + } +} diff --git a/Essentials/src/com/earth2me/essentials/settings/Settings.java b/Essentials/src/com/earth2me/essentials/settings/Settings.java index 4c2ff2dd9..6e5ec9793 100644 --- a/Essentials/src/com/earth2me/essentials/settings/Settings.java +++ b/Essentials/src/com/earth2me/essentials/settings/Settings.java @@ -1,7 +1,10 @@ package com.earth2me.essentials.settings; import com.earth2me.essentials.storage.Comment; +import com.earth2me.essentials.storage.MapValueType; import com.earth2me.essentials.storage.StorageObject; +import java.util.HashMap; +import java.util.Map; import lombok.Data; import lombok.EqualsAndHashCode; @@ -50,9 +53,20 @@ public class Settings implements StorageObject { "##########################################################", "+------------------------------------------------------+ #", - "| Group Settings | #", + "| Worlds Settings | #", "+------------------------------------------------------+ #", "##########################################################" }) - private Groups groups = new Groups(); + @MapValueType(WorldOptions.class) + private Map worlds = new HashMap(); + + public WorldOptions getWorldOptions(final String name) + { + if (worlds == null) + { + worlds = new HashMap(); + } + final WorldOptions options = worlds.get(name); + return (options == null) ? new WorldOptions() : options; + } } diff --git a/Essentials/src/com/earth2me/essentials/settings/SettingsHolder.java b/Essentials/src/com/earth2me/essentials/settings/SettingsHolder.java new file mode 100644 index 000000000..9acbf83db --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/settings/SettingsHolder.java @@ -0,0 +1,21 @@ +package com.earth2me.essentials.settings; + +import com.earth2me.essentials.api.IEssentials; +import com.earth2me.essentials.api.ISettings; +import com.earth2me.essentials.storage.AsyncStorageObjectHolder; +import java.io.File; + + +public class SettingsHolder extends AsyncStorageObjectHolder implements ISettings +{ + public SettingsHolder(final IEssentials ess) + { + super(ess, Settings.class); + } + + @Override + public File getStorageFile() + { + return new File(ess.getDataFolder(), "settings.yml"); + } +} diff --git a/Essentials/src/com/earth2me/essentials/settings/WorldOptions.java b/Essentials/src/com/earth2me/essentials/settings/WorldOptions.java new file mode 100644 index 000000000..33271b460 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/settings/WorldOptions.java @@ -0,0 +1,14 @@ +package com.earth2me.essentials.settings; + +import com.earth2me.essentials.storage.Comment; +import com.earth2me.essentials.storage.StorageObject; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +public class WorldOptions implements StorageObject +{ + @Comment("Disables godmode for all players if they teleport to this world.") + private boolean godmode = true; +} diff --git a/Essentials/src/com/earth2me/essentials/settings/Worlds.java b/Essentials/src/com/earth2me/essentials/settings/Worlds.java new file mode 100644 index 000000000..88d435c4b --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/settings/Worlds.java @@ -0,0 +1,15 @@ +package com.earth2me.essentials.settings; + +import com.earth2me.essentials.storage.MapValueType; +import com.earth2me.essentials.storage.StorageObject; +import java.util.HashMap; +import java.util.Map; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = false) +public class Worlds implements StorageObject +{ + +} \ No newline at end of file diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/Afk.java b/Essentials/src/com/earth2me/essentials/settings/commands/Afk.java index 80cae7e8a..89151d737 100644 --- a/Essentials/src/com/earth2me/essentials/settings/commands/Afk.java +++ b/Essentials/src/com/earth2me/essentials/settings/commands/Afk.java @@ -15,14 +15,14 @@ public class Afk implements StorageObject "After this timeout in seconds, the user will be set as afk.", "Set to -1 for no timeout." }) - private int autoAFK = 300; + private long autoAFK = 300; @Comment( { "Auto-AFK Kick", "After this timeout in seconds, the user will be kicked from the server.", "Set to -1 for no timeout." }) - private int autoAFKKick = -1; + private long autoAFKKick = -1; @Comment( { "Set this to true, if you want to freeze the player, if he is afk.", diff --git a/Essentials/src/com/earth2me/essentials/settings/commands/Back.java b/Essentials/src/com/earth2me/essentials/settings/commands/Back.java new file mode 100644 index 000000000..bd2afdd62 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/settings/commands/Back.java @@ -0,0 +1,19 @@ +package com.earth2me.essentials.settings.commands; + +import com.earth2me.essentials.storage.Comment; +import com.earth2me.essentials.storage.StorageObject; +import lombok.Data; +import lombok.EqualsAndHashCode; + + +@Data +@EqualsAndHashCode(callSuper = false) +public class Back implements StorageObject +{ + @Comment( + { + "Do you want essentials to keep track of previous location for /back in the teleport listener?", + "If you set this to true any plugin that uses teleport will have the previous location registered." + }) + private boolean registerBackInListener = false; +} diff --git a/Essentials/src/com/earth2me/essentials/storage/AbstractDelayedYamlFileReader.java b/Essentials/src/com/earth2me/essentials/storage/AbstractDelayedYamlFileReader.java index 43bfc358d..22ff7adb7 100644 --- a/Essentials/src/com/earth2me/essentials/storage/AbstractDelayedYamlFileReader.java +++ b/Essentials/src/com/earth2me/essentials/storage/AbstractDelayedYamlFileReader.java @@ -1,6 +1,6 @@ package com.earth2me.essentials.storage; -import com.earth2me.essentials.IEssentials; +import com.earth2me.essentials.api.IEssentials; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; diff --git a/Essentials/src/com/earth2me/essentials/storage/AbstractDelayedYamlFileWriter.java b/Essentials/src/com/earth2me/essentials/storage/AbstractDelayedYamlFileWriter.java index 697ef7730..f2c2632fd 100644 --- a/Essentials/src/com/earth2me/essentials/storage/AbstractDelayedYamlFileWriter.java +++ b/Essentials/src/com/earth2me/essentials/storage/AbstractDelayedYamlFileWriter.java @@ -1,6 +1,6 @@ package com.earth2me.essentials.storage; -import com.earth2me.essentials.IEssentials; +import com.earth2me.essentials.api.IEssentials; import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; diff --git a/Essentials/src/com/earth2me/essentials/storage/AsyncStorageObjectHolder.java b/Essentials/src/com/earth2me/essentials/storage/AsyncStorageObjectHolder.java index 31c61a63f..db8299f12 100644 --- a/Essentials/src/com/earth2me/essentials/storage/AsyncStorageObjectHolder.java +++ b/Essentials/src/com/earth2me/essentials/storage/AsyncStorageObjectHolder.java @@ -1,7 +1,7 @@ package com.earth2me.essentials.storage; import com.earth2me.essentials.IConf; -import com.earth2me.essentials.IEssentials; +import com.earth2me.essentials.api.IEssentials; import com.earth2me.essentials.api.IReload; import java.io.File; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -30,6 +30,12 @@ public abstract class AsyncStorageObjectHolder implemen } } + /** + * Warning: If you access this method, you have to acquire a read or write lock first + * + * + * @return Object storing all the data + */ public T getData() { return data; diff --git a/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java b/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java index 5070be552..b04b89448 100644 --- a/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java +++ b/Essentials/src/com/earth2me/essentials/storage/BukkitConstructor.java @@ -215,6 +215,20 @@ public class BukkitConstructor extends Constructor } return new EnchantmentLevel(enchant, level); } + if (node.getType().isEnum()) { + final String val = (String)constructScalar((ScalarNode)node); + if (val.isEmpty()) + { + return null; + } + for (Object object : node.getType().getEnumConstants()) + { + if (object.toString().equalsIgnoreCase(val)) { + return object; + } + } + return null; + } return super.construct(node); } } diff --git a/Essentials/src/com/earth2me/essentials/storage/YamlStorageWriter.java b/Essentials/src/com/earth2me/essentials/storage/YamlStorageWriter.java index fd1f0f863..fe12735ef 100644 --- a/Essentials/src/com/earth2me/essentials/storage/YamlStorageWriter.java +++ b/Essentials/src/com/earth2me/essentials/storage/YamlStorageWriter.java @@ -218,6 +218,11 @@ public class YamlStorageWriter implements IStorageWriter YAML.dumpAll(Collections.singletonList(data).iterator(), writer); } } + else if (data instanceof Enum) + { + writeMaterial(data.toString()); + writer.println(); + } else if (data instanceof Material) { writeMaterial(data); @@ -260,6 +265,10 @@ public class YamlStorageWriter implements IStorageWriter writer.print(output); } } + else if (data instanceof Enum) + { + writeMaterial(data.toString()); + } else if (data instanceof Material) { writeMaterial(data); diff --git a/Essentials/src/com/earth2me/essentials/user/CooldownException.java b/Essentials/src/com/earth2me/essentials/user/CooldownException.java new file mode 100644 index 000000000..b986a5552 --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/user/CooldownException.java @@ -0,0 +1,12 @@ +package com.earth2me.essentials.user; + + +public class CooldownException extends Exception +{ + + public CooldownException(String timeLeft) + { + super(timeLeft); + } + +} diff --git a/Essentials/src/com/earth2me/essentials/user/User.java b/Essentials/src/com/earth2me/essentials/user/User.java index 0e544ae06..bc1ebfe23 100644 --- a/Essentials/src/com/earth2me/essentials/user/User.java +++ b/Essentials/src/com/earth2me/essentials/user/User.java @@ -1,25 +1,60 @@ package com.earth2me.essentials.user; -import com.earth2me.essentials.IEssentials; -import com.earth2me.essentials.IUser; +import com.earth2me.essentials.Console; +import com.earth2me.essentials.api.IEssentials; +import com.earth2me.essentials.api.IUser; import com.earth2me.essentials.Teleport; +import com.earth2me.essentials.Util; +import com.earth2me.essentials.api.IGroups; +import com.earth2me.essentials.api.ISettings; import com.earth2me.essentials.commands.IEssentialsCommand; +import com.earth2me.essentials.register.payment.Method; +import com.earth2me.essentials.settings.WorldOptions; +import static com.earth2me.essentials.I18n._; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.logging.Logger; import lombok.Cleanup; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; public class User extends UserBase implements IUser { + @Getter + @Setter + private CommandSender replyTo = null; + private transient User teleportRequester; + private transient boolean teleportRequestHere; + @Getter + private transient final Teleport teleport; + @Getter + private transient long teleportRequestTime; + @Getter + @Setter + private transient long lastOnlineActivity; + private transient long lastActivity = System.currentTimeMillis(); + @Getter + @Setter + private boolean hidden = false; + private transient Location afkPosition; + private static final Logger logger = Bukkit.getLogger(); + public User(final Player base, final IEssentials ess) { super(base, ess); + teleport = new Teleport(this, (com.earth2me.essentials.IEssentials)ess); } public User(final OfflinePlayer offlinePlayer, final IEssentials ess) { super(offlinePlayer, ess); + teleport = new Teleport(this, (com.earth2me.essentials.IEssentials)ess); } public void example() @@ -37,45 +72,144 @@ public class User extends UserBase implements IUser user.getData().setMoney(10 + money); } - @Override - public long getLastTeleportTimestamp() - { - acquireReadLock(); - try - { - return getData().getTimestamps().get("lastteleport"); - } - finally - { - unlock(); - } - } - @Override public boolean isAuthorized(String node) { - throw new UnsupportedOperationException("Not supported yet."); + if (!isOnlineUser()) + { + return false; + } + + if (getData().isJailed()) + { + return false; + } + + return ess.getPermissionsHandler().hasPermission(base, node); } @Override public boolean isAuthorized(IEssentialsCommand cmd) { - throw new UnsupportedOperationException("Not supported yet."); + return isAuthorized(cmd, "essentials."); } @Override public boolean isAuthorized(IEssentialsCommand cmd, String permissionPrefix) { - throw new UnsupportedOperationException("Not supported yet."); + return isAuthorized(permissionPrefix + (cmd.getName().equals("r") ? "msg" : cmd.getName())); + } + + public void checkCooldown(final UserData.TimestampType cooldownType,final double cooldown, final boolean set, final String bypassPermission) throws CooldownException + { + final Calendar now = new GregorianCalendar(); + if (getTimestamp(cooldownType) > 0) + { + final Calendar cooldownTime = new GregorianCalendar(); + cooldownTime.setTimeInMillis(getTimestamp(cooldownType)); + cooldownTime.add(Calendar.SECOND, (int)cooldown); + cooldownTime.add(Calendar.MILLISECOND, (int)((cooldown * 1000.0) % 1000.0)); + if (cooldownTime.after(now) && !isAuthorized(bypassPermission)) + { + throw new CooldownException(Util.formatDateDiff(cooldownTime.getTimeInMillis())); + } + } + if (set) { + setTimestamp(cooldownType, now.getTimeInMillis()); + } } @Override - public void setLastTeleportTimestamp(long time) + public void giveMoney(final double value) + { + giveMoney(value, null); + } + + public void giveMoney(final double value, final CommandSender initiator) + { + + if (value == 0) + { + return; + } + acquireWriteLock(); + try + { + setMoney(getMoney() + value); + sendMessage(_("addedToAccount", Util.formatCurrency(value, (com.earth2me.essentials.IEssentials)ess))); + if (initiator != null) + { + initiator.sendMessage(_("addedToOthersAccount", Util.formatCurrency(value, (com.earth2me.essentials.IEssentials)ess), this.getDisplayName())); + } + } + finally + { + unlock(); + } + } + + public void payUser(final User reciever, final double value) throws Exception + { + if (value == 0) + { + return; + } + if (canAfford(value)) + { + setMoney(getMoney() - value); + reciever.setMoney(reciever.getMoney() + value); + sendMessage(_("moneySentTo", Util.formatCurrency(value, (com.earth2me.essentials.IEssentials)ess), reciever.getDisplayName())); + reciever.sendMessage(_("moneyRecievedFrom", Util.formatCurrency(value, (com.earth2me.essentials.IEssentials)ess), getDisplayName())); + } + else + { + throw new Exception(_("notEnoughMoney")); + } + } + + @Override + public void takeMoney(final double value) + { + takeMoney(value, null); + } + + public void takeMoney(final double value, final CommandSender initiator) + { + if (value == 0) + { + return; + } + setMoney(getMoney() - value); + sendMessage(_("takenFromAccount", Util.formatCurrency(value, (com.earth2me.essentials.IEssentials)ess))); + if (initiator != null) + { + initiator.sendMessage(_("takenFromOthersAccount", Util.formatCurrency(value, (com.earth2me.essentials.IEssentials)ess), this.getDisplayName())); + } + } + + public boolean canAfford(final double cost) + { + final double mon = getMoney(); + return mon >= cost || isAuthorized("essentials.eco.loan"); + } + + public void setHome() + { + setHome("home", getLocation()); + } + + public void setHome(final String name) + { + setHome(name, getLocation()); + } + + @Override + public void setLastLocation() { acquireWriteLock(); try { - getData().getTimestamps().put("lastteleport", time); + getData().setLastLocation(getLocation()); } finally { @@ -83,13 +217,60 @@ public class User extends UserBase implements IUser } } - @Override - public Location getLastLocation() + public void requestTeleport(final User player, final boolean here) + { + teleportRequestTime = System.currentTimeMillis(); + teleportRequester = player; + teleportRequestHere = here; + } + + public User getTeleportRequest() + { + return teleportRequester; + } + + public boolean isTeleportRequestHere() + { + return teleportRequestHere; + } + + public String getNick(boolean addprefixsuffix) { acquireReadLock(); try { - return getData().getLastLocation(); + final String nick = getData().getNickname(); + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + @Cleanup + final IGroups groups = ess.getGroups(); + groups.acquireReadLock(); + // default: {PREFIX}{NICKNAMEPREFIX}{NAME}{SUFFIX} + String displayname = settings.getData().getChat().getDisplaynameFormat(); + if (settings.getData().getCommands().isDisabled("nick") || nick == null || nick.isEmpty() || nick.equals(getName())) + { + displayname = displayname.replace("{NAME}", getName()); + } + else + { + displayname = displayname.replace("{NAME}", nick); + displayname = displayname.replace("{NICKNAMEPREFIX}", settings.getData().getChat().getNicknamePrefix()); + } + + if (displayname.contains("{PREFIX}")) + { + displayname = displayname.replace("{PREFIX}", groups.getPrefix(this)); + } + if (displayname.contains("{SUFFIX}")) + { + displayname = displayname.replace("{SUFFIX}", groups.getSuffix(this)); + } + displayname = displayname.replace("{WORLDNAME}", this.getWorld().getName()); + displayname = displayname.replace('&', '§'); + displayname = displayname.concat("§f"); + + return displayname; } finally { @@ -97,13 +278,141 @@ public class User extends UserBase implements IUser } } + public void setDisplayNick() + { + String name = getNick(true); + setDisplayName(name); + if (name.length() > 16) + { + name = getNick(false); + } + if (name.length() > 16) + { + name = name.substring(0, name.charAt(15) == '§' ? 15 : 16); + } + try + { + setPlayerListName(name); + } + catch (IllegalArgumentException e) + { + logger.info("Playerlist for " + name + " was not updated. Use a shorter displayname prefix."); + } + } + + @Override + public String getDisplayName() + { + return super.getDisplayName() == null ? super.getName() : super.getDisplayName(); + } + + @Override + public void updateDisplayName() + { + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + if (isOnlineUser() && settings.getData().getChat().getChangeDisplayname()) + { + setDisplayNick(); + } + } + @Override public double getMoney() + { + if (ess.getPaymentMethod().hasMethod()) + { + try + { + final Method method = ess.getPaymentMethod().getMethod(); + if (!method.hasAccount(this.getName())) + { + throw new Exception(); + } + final Method.MethodAccount account = ess.getPaymentMethod().getMethod().getAccount(this.getName()); + return account.balance(); + } + catch (Throwable ex) + { + } + } + return super.getMoney(); + } + + @Override + public void setMoney(final double value) + { + if (ess.getPaymentMethod().hasMethod()) + { + try + { + final Method method = ess.getPaymentMethod().getMethod(); + if (!method.hasAccount(this.getName())) + { + throw new Exception(); + } + final Method.MethodAccount account = ess.getPaymentMethod().getMethod().getAccount(this.getName()); + account.set(value); + } + catch (Throwable ex) + { + } + } + super.setMoney(value); + } + + public void setAfk(final boolean set) + { + acquireWriteLock(); + try + { + this.setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") ? true : set); + if (set && !getData().isAfk()) + { + afkPosition = getLocation(); + } + getData().setAfk(set); + } + finally + { + unlock(); + } + } + + @Override + public boolean toggleAfk() + { + final boolean now = super.toggleAfk(); + this.setSleepingIgnored(this.isAuthorized("essentials.sleepingignored") ? true : now); + return now; + } + + //Returns true if status expired during this check + public boolean checkJailTimeout(final long currentTime) { acquireReadLock(); try { - return getData().getMoney(); + if (getTimestamp(UserData.TimestampType.JAIL) > 0 && getTimestamp(UserData.TimestampType.JAIL) < currentTime && getData().isJailed()) + { + acquireWriteLock(); + + setTimestamp(UserData.TimestampType.JAIL, 0); + getData().setJailed(false); + sendMessage(_("haveBeenReleased")); + getData().setJail(null); + + try + { + teleport.back(); + } + catch (Exception ex) + { + } + return true; + } + return false; } finally { @@ -111,13 +420,21 @@ public class User extends UserBase implements IUser } } - @Override - public void takeMoney(double value) + //Returns true if status expired during this check + public boolean checkMuteTimeout(final long currentTime) { - acquireWriteLock(); + acquireReadLock(); try { - getData().setMoney(getData().getMoney() - value); + if (getTimestamp(UserData.TimestampType.MUTE) > 0 && getTimestamp(UserData.TimestampType.MUTE) < currentTime && getData().isMuted()) + { + acquireWriteLock(); + setTimestamp(UserData.TimestampType.MUTE, 0); + sendMessage(_("canTalkAgain")); + getData().setMuted(false); + return true; + } + return false; } finally { @@ -125,13 +442,116 @@ public class User extends UserBase implements IUser } } - @Override - public void giveMoney(double value) + //Returns true if status expired during this check + public boolean checkBanTimeout(final long currentTime) { - acquireWriteLock(); + acquireReadLock(); try { - getData().setMoney(getData().getMoney() + value); + if (getData().getBan() != null && getData().getBan().getTimeout() > 0 && getData().getBan().getTimeout() < currentTime && isBanned()) + { + acquireWriteLock(); + getData().setBan(null); + setBanned(false); + return true; + } + return false; + } + finally + { + unlock(); + } + } + + public void updateActivity(final boolean broadcast) + { + acquireReadLock(); + try + { + if (getData().isAfk()) + { + acquireWriteLock(); + getData().setAfk(false); + if (broadcast && !hidden) + { + ess.broadcastMessage(this, _("userIsNotAway", getDisplayName())); + } + } + lastActivity = System.currentTimeMillis(); + } + finally + { + unlock(); + } + } + + public void checkActivity() + { + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + final long autoafkkick = settings.getData().getCommands().getAfk().getAutoAFKKick(); + if (autoafkkick > 0 && lastActivity > 0 && (lastActivity + (autoafkkick * 1000)) < System.currentTimeMillis() + && !hidden && !isAuthorized("essentials.kick.exempt") && !isAuthorized("essentials.afk.kickexempt")) + { + final String kickReason = _("autoAfkKickReason", autoafkkick / 60.0); + lastActivity = 0; + kickPlayer(kickReason); + + + for (Player player : ess.getServer().getOnlinePlayers()) + { + final IUser user = ess.getUser(player); + if (user.isAuthorized("essentials.kick.notify")) + { + player.sendMessage(_("playerKicked", Console.NAME, getName(), kickReason)); + } + } + } + final long autoafk = settings.getData().getCommands().getAfk().getAutoAFK(); + acquireReadLock(); + try + { + if (!getData().isAfk() && autoafk > 0 && lastActivity + autoafk * 1000 < System.currentTimeMillis() && isAuthorized("essentials.afk")) + { + setAfk(true); + if (!hidden) + { + ess.broadcastMessage(this, _("userIsAway", getDisplayName())); + } + } + } + finally + { + unlock(); + } + } + + public Location getAfkPosition() + { + return afkPosition; + } + + public boolean toggleGodModeEnabled() + { + if (!isGodModeEnabled()) + { + setFoodLevel(20); + } + return super.toggleGodmode(); + } + + public boolean isGodModeEnabled() + { + acquireReadLock(); + try + { + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + return (getData().isGodmode() + && !settings.getData().getWorldOptions(getLocation().getWorld().getName()).isGodmode()) + || (getData().isAfk() && settings.getData().getCommands().getAfk().isFreezeAFKPlayers()); } finally { @@ -142,27 +562,17 @@ public class User extends UserBase implements IUser @Override public String getGroup() { - throw new UnsupportedOperationException("Not supported yet."); + return ess.getPermissionsHandler().getGroup(base); } - @Override - public void setLastLocation() + public boolean inGroup(final String group) { - acquireWriteLock(); - try - { - getData().setLastLocation(base.getLocation()); - } - finally - { - unlock(); - } + return ess.getPermissionsHandler().inGroup(base, group); } - @Override - public Location getHome(String name) throws Exception + public boolean canBuild() { - throw new UnsupportedOperationException("Not supported yet."); + return ess.getPermissionsHandler().canBuild(base, getGroup()); } @Override @@ -172,28 +582,8 @@ public class User extends UserBase implements IUser } @Override - public boolean isHidden() + public Location getHome(String name) throws Exception { throw new UnsupportedOperationException("Not supported yet."); } - - @Override - public Teleport getTeleport() - { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void setJail(final String jail) - { - acquireWriteLock(); - try - { - getData().setJail(jail); - } - finally - { - unlock(); - } - } } diff --git a/Essentials/src/com/earth2me/essentials/user/UserBase.java b/Essentials/src/com/earth2me/essentials/user/UserBase.java index 9dda2f950..3a67efdd2 100644 --- a/Essentials/src/com/earth2me/essentials/user/UserBase.java +++ b/Essentials/src/com/earth2me/essentials/user/UserBase.java @@ -1,9 +1,14 @@ package com.earth2me.essentials.user; -import com.earth2me.essentials.IEssentials; +import com.earth2me.essentials.Util; +import com.earth2me.essentials.api.IEssentials; +import com.earth2me.essentials.api.ISettings; import com.earth2me.essentials.craftbukkit.OfflineBedLocation; import com.earth2me.essentials.storage.AsyncStorageObjectHolder; import java.io.File; +import java.util.HashMap; +import java.util.Map; +import lombok.Cleanup; import lombok.Delegate; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -20,13 +25,12 @@ import org.bukkit.OfflinePlayer; public abstract class UserBase extends AsyncStorageObjectHolder implements Player, IOfflineUser { - @Delegate(types = { Player.class, Entity.class, CommandSender.class, ServerOperator.class, HumanEntity.class, ConfigurationSerializable.class, LivingEntity.class, Permissible.class - },excludes=IOfflinePlayer.class) + }, excludes = IOfflinePlayer.class) protected Player base; protected transient OfflinePlayer offlinePlayer; @@ -36,7 +40,7 @@ public abstract class UserBase extends AsyncStorageObjectHolder implem this.base = base; reloadConfig(); } - + public UserBase(final OfflinePlayer offlinePlayer, final IEssentials ess) { super(ess, UserData.class); @@ -58,58 +62,71 @@ public abstract class UserBase extends AsyncStorageObjectHolder implem { setBase(base); } - + public void update(final OfflinePlayer offlinePlayer) { this.offlinePlayer = offlinePlayer; } - + public void dispose() { this.offlinePlayer = Bukkit.getOfflinePlayer(base.getName()); this.base = null; } - - public boolean isOnlineUser() { + + public boolean isOnlineUser() + { return base != null; } @Override public String getName() { - if (isOnlineUser()) { + if (isOnlineUser()) + { return base.getName(); - } else { + } + else + { return offlinePlayer.getName(); } } - + @Override public String getDisplayName() { - if (isOnlineUser()) { + if (isOnlineUser()) + { return base.getDisplayName(); - } else { + } + else + { return offlinePlayer.getName(); } } - + @Override public Location getBedSpawnLocation() { - if (isOnlineUser()) { + if (isOnlineUser()) + { return base.getBedSpawnLocation(); - } else { - return OfflineBedLocation.getBedLocation(base.getName(), ess); - } + } + else + { + return OfflineBedLocation.getBedLocation(base.getName(), (com.earth2me.essentials.IEssentials)ess); + } } @Override public void setBanned(boolean bln) { - if (isOnlineUser()) { + if (isOnlineUser()) + { base.setBanned(bln); - } else { + } + else + { offlinePlayer.setBanned(bln); } } @@ -119,4 +136,136 @@ public abstract class UserBase extends AsyncStorageObjectHolder implem { return ess.getUserMap().getUserFile(getName()); } + + public long getTimestamp(final UserData.TimestampType name) + { + acquireReadLock(); + try + { + if (getData().getTimestamps() == null) + { + return 0; + } + Long ts = getData().getTimestamps().get(name); + return ts == null ? 0 : ts; + } + finally + { + unlock(); + } + } + + public void setTimestamp(final UserData.TimestampType name, final long value) + { + acquireWriteLock(); + try + { + if (getData().getTimestamps() == null) + { + getData().setTimestamps(new HashMap()); + } + getData().getTimestamps().put(name, value); + } + finally + { + unlock(); + } + } + + public void setMoney(final double value) + { + acquireWriteLock(); + try + { + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + if (Math.abs(getData().getMoney()) > settings.getData().getEconomy().getMaxMoney()) + { + getData().setMoney(getData().getMoney() < 0 ? -settings.getData().getEconomy().getMaxMoney() : settings.getData().getEconomy().getMaxMoney()); + } + else + { + getData().setMoney(value); + } + } + finally + { + unlock(); + } + } + + public double getMoney() + { + acquireReadLock(); + try + { + Double money = getData().getMoney(); + @Cleanup + final ISettings settings = ess.getSettings(); + settings.acquireReadLock(); + if (money == null) + { + money = (double)settings.getData().getEconomy().getStartingBalance(); + } + if (Math.abs(money) > settings.getData().getEconomy().getMaxMoney()) + { + money = money < 0 ? -settings.getData().getEconomy().getMaxMoney() : settings.getData().getEconomy().getMaxMoney(); + } + return money; + } + finally + { + unlock(); + } + } + + public void setHome(String name, Location loc) + { + acquireWriteLock(); + try + { + Map homes = getData().getHomes(); + if (homes == null) + { + homes = new HashMap(); + getData().setHomes(homes); + } + homes.put(Util.sanitizeKey(name), loc); + } + finally + { + unlock(); + } + } + + public boolean toggleAfk() + { + acquireWriteLock(); + try + { + boolean ret = !getData().isAfk(); + getData().setAfk(ret); + return ret; + } + finally + { + unlock(); + } + } + + public boolean toggleGodmode() + { + acquireWriteLock(); + try + { + boolean ret = !getData().isGodmode(); + getData().setGodmode(ret); + return ret; + } + finally + { + unlock(); + } + } } diff --git a/Essentials/src/com/earth2me/essentials/user/UserData.java b/Essentials/src/com/earth2me/essentials/user/UserData.java index 4586d0627..f36f42eed 100644 --- a/Essentials/src/com/earth2me/essentials/user/UserData.java +++ b/Essentials/src/com/earth2me/essentials/user/UserData.java @@ -15,8 +15,12 @@ import org.bukkit.Material; @EqualsAndHashCode(callSuper = false) public class UserData implements StorageObject { + public enum TimestampType + { + JAIL, MUTE, LASTHEAL, LASTTELEPORT, LOGIN + } private String nickname; - private double money; + private Double money; @MapValueType(Location.class) private Map homes = new HashMap(); @ListType(Material.class) @@ -25,8 +29,9 @@ public class UserData implements StorageObject @MapKeyType(Material.class) private Map> powerTools = new HashMap>(); private Location lastLocation; + @MapKeyType(TimestampType.class) @MapValueType(Long.class) - private Map timestamps; + private Map timestamps = new HashMap(); private String jail; @ListType private List mails; @@ -52,5 +57,16 @@ public class UserData implements StorageObject unlimited.add(Material.ARROW); unlimited.add(Material.APPLE); powerTools.put(Material.DEAD_BUSH, Collections.singletonList("test")); + timestamps.put(TimestampType.JAIL, Long.MIN_VALUE); + } + + public boolean hasUnlimited(Material mat) + { + return unlimited != null && unlimited.contains(mat); + } + + public List getPowertool(Material mat) + { + return powerTools == null ? Collections.emptyList() : powerTools.get(mat); } } diff --git a/Essentials/src/com/earth2me/essentials/user/UserMap.java b/Essentials/src/com/earth2me/essentials/user/UserMap.java index 821ee4c8f..f898a1b2e 100644 --- a/Essentials/src/com/earth2me/essentials/user/UserMap.java +++ b/Essentials/src/com/earth2me/essentials/user/UserMap.java @@ -1,8 +1,8 @@ package com.earth2me.essentials.user; -import com.earth2me.essentials.IConf; -import com.earth2me.essentials.IEssentials; +import com.earth2me.essentials.api.IEssentials; import com.earth2me.essentials.Util; +import com.earth2me.essentials.api.IUserMap; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -17,7 +17,7 @@ import org.bukkit.Bukkit; import org.bukkit.entity.Player; -public class UserMap extends CacheLoader implements IConf +public class UserMap extends CacheLoader implements IUserMap { private final transient IEssentials ess; private final transient Cache users = CacheBuilder.newBuilder().softValues().build(this); @@ -27,10 +27,10 @@ public class UserMap extends CacheLoader implements IConf { super(); this.ess = ess; - loadAllUsersAsync(ess); + loadAllUsersAsync(); } - private void loadAllUsersAsync(final IEssentials ess) + private void loadAllUsersAsync() { ess.scheduleAsyncDelayedTask(new Runnable() { @@ -98,12 +98,6 @@ public class UserMap extends CacheLoader implements IConf throw new Exception("User not found!"); } - @Override - public void reloadConfig() - { - loadAllUsersAsync(ess); - } - public void removeUser(final String name) { keys.remove(name.toLowerCase(Locale.ENGLISH)); @@ -125,4 +119,10 @@ public class UserMap extends CacheLoader implements IConf final File userFolder = new File(ess.getDataFolder(), "userdata"); return new File(userFolder, Util.sanitizeFileName(name) + ".yml"); } + + @Override + public void onReload() + { + loadAllUsersAsync(); + } }