From caf03379f208148b5bc196dbb40c0237eb0ef8a9 Mon Sep 17 00:00:00 2001 From: Luck Date: Sat, 6 Aug 2016 00:11:00 +0200 Subject: [PATCH] Move stuff into commons, rename PermissionObject, add more javadocs to api --- .../java/me/lucko/luckperms/LuckPerms.java | 19 +++- .../java/me/lucko/luckperms/api/Group.java | 2 +- .../java/me/lucko/luckperms/api/Logger.java | 5 + .../me/lucko/luckperms/api/LuckPermsApi.java | 58 ++++++++++ ...ssionObject.java => PermissionHolder.java} | 4 +- .../java/me/lucko/luckperms/api/User.java | 2 +- .../exceptions/ObjectAlreadyHasException.java | 4 + .../exceptions/ObjectLacksException.java | 4 + bukkit/pom.xml | 14 +++ .../me/lucko/luckperms/BukkitCommand.java | 34 +++--- .../me/lucko/luckperms/BukkitListener.java | 64 +++++++++++ .../me/lucko/luckperms/LPBukkitPlugin.java | 8 +- .../api/vault/VaultPermissionHook.java | 10 +- .../luckperms/listeners/PlayerListener.java | 101 ----------------- bungee/pom.xml | 14 +++ .../me/lucko/luckperms/BungeeCommand.java | 33 +++--- ...layerListener.java => BungeeListener.java} | 32 ++---- .../me/lucko/luckperms/LPBungeePlugin.java | 8 +- common/pom.xml | 21 ++++ .../me/lucko/luckperms/LuckPermsPlugin.java | 7 +- .../implementation/internal/GroupLink.java | 2 +- ...ectLink.java => PermissionHolderLink.java} | 8 +- .../api/implementation/internal/UserLink.java | 2 +- .../api/implementation/internal/Utils.java | 2 + .../luckperms/commands/SenderFactory.java | 30 +++++ .../me/lucko/luckperms/constants/Message.java | 5 +- .../java/me/lucko/luckperms/groups/Group.java | 6 +- .../java/me/lucko/luckperms/users/User.java | 6 +- .../luckperms/utils/AbstractListener.java | 62 ++++++++++ .../me/lucko/luckperms/utils/Patterns.java | 10 +- ...ssionObject.java => PermissionHolder.java} | 40 +++---- pom.xml | 21 ---- sponge/pom.xml | 14 +++ .../me/lucko/luckperms/LPSpongePlugin.java | 25 ++-- .../me/lucko/luckperms/SpongeCommand.java | 48 ++++---- .../java/me/lucko/luckperms/SpongeConfig.java | 3 +- .../me/lucko/luckperms/SpongeListener.java | 69 +++++++++++ .../luckperms/listeners/PlayerListener.java | 107 ------------------ 38 files changed, 516 insertions(+), 388 deletions(-) rename api/src/main/java/me/lucko/luckperms/api/{PermissionObject.java => PermissionHolder.java} (99%) create mode 100644 bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java delete mode 100644 bukkit/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java rename bungee/src/main/java/me/lucko/luckperms/{listeners/PlayerListener.java => BungeeListener.java} (79%) rename common/src/main/java/me/lucko/luckperms/api/implementation/internal/{PermissionObjectLink.java => PermissionHolderLink.java} (96%) create mode 100644 common/src/main/java/me/lucko/luckperms/commands/SenderFactory.java create mode 100644 common/src/main/java/me/lucko/luckperms/utils/AbstractListener.java rename common/src/main/java/me/lucko/luckperms/utils/{PermissionObject.java => PermissionHolder.java} (94%) create mode 100644 sponge/src/main/java/me/lucko/luckperms/SpongeListener.java delete mode 100644 sponge/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java diff --git a/api/src/main/java/me/lucko/luckperms/LuckPerms.java b/api/src/main/java/me/lucko/luckperms/LuckPerms.java index 18a49cb9..83235548 100644 --- a/api/src/main/java/me/lucko/luckperms/LuckPerms.java +++ b/api/src/main/java/me/lucko/luckperms/LuckPerms.java @@ -4,14 +4,22 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import me.lucko.luckperms.api.LuckPermsApi; +import java.util.Optional; + /** * Static access to LuckPerms */ @NoArgsConstructor(access = AccessLevel.PRIVATE) -public class LuckPerms { +public final class LuckPerms { private static LuckPermsApi api = null; + + /** + * Gets an instance of {@link LuckPermsApi} + * @return an api instance + * @throws IllegalStateException if the api is not loaded + */ public static LuckPermsApi getApi() { if (api == null) { throw new IllegalStateException("API is not loaded."); @@ -19,6 +27,15 @@ public class LuckPerms { return api; } + /** + * Gets an instance of {@link LuckPermsApi} safely. Unlike {@link LuckPerms#getApi}, this method will not throw an + * {@link IllegalStateException} if the api is not loaded, rather return an empty {@link Optional}. + * @return an optional api instance + */ + public static Optional getApiSafe() { + return Optional.ofNullable(api); + } + static void registerProvider(LuckPermsApi luckPermsApi) { api = luckPermsApi; } diff --git a/api/src/main/java/me/lucko/luckperms/api/Group.java b/api/src/main/java/me/lucko/luckperms/api/Group.java index ede2177a..038b934a 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Group.java +++ b/api/src/main/java/me/lucko/luckperms/api/Group.java @@ -11,7 +11,7 @@ import java.util.List; * errors and ensure all API interactions to not damage the state of the group. */ @SuppressWarnings("unused") -public interface Group extends PermissionObject { +public interface Group extends PermissionHolder { /** * @return the name of the group diff --git a/api/src/main/java/me/lucko/luckperms/api/Logger.java b/api/src/main/java/me/lucko/luckperms/api/Logger.java index 102b5b4b..10ef6669 100644 --- a/api/src/main/java/me/lucko/luckperms/api/Logger.java +++ b/api/src/main/java/me/lucko/luckperms/api/Logger.java @@ -1,5 +1,10 @@ package me.lucko.luckperms.api; +/** + * A wrapper class for platform logger instances. + * Bukkit/Bungee both use java.util.logging, and Sponge uses org.slf4j. This class wraps those classes so the commons + * module can access a logger. + */ public interface Logger { void info(String s); diff --git a/api/src/main/java/me/lucko/luckperms/api/LuckPermsApi.java b/api/src/main/java/me/lucko/luckperms/api/LuckPermsApi.java index ce3a16cb..144cd3a4 100644 --- a/api/src/main/java/me/lucko/luckperms/api/LuckPermsApi.java +++ b/api/src/main/java/me/lucko/luckperms/api/LuckPermsApi.java @@ -2,23 +2,81 @@ package me.lucko.luckperms.api; import java.util.UUID; +/** + * The root Api interface in LuckPerms + */ @SuppressWarnings("unused") public interface LuckPermsApi { + /** + * Schedules an update task to run + */ void runUpdateTask(); + + /** + * @return the version of the plugin running on the platform + */ String getVersion(); + /** + * Gets a wrapped {@link Datastore} instance, with somewhat limited access + * @return a datastore instance + */ Datastore getDatastore(); + + /** + * Gets the {@link Logger} wrapping used by the platform + * @return the logger instance + */ Logger getLogger(); + /** + * Gets a wrapped user object from the user storage + * @param uuid the uuid of the user to get + * @return a {@link User} object, if one matching the uuid is loaded, or null if not + */ User getUser(UUID uuid); + + /** + * Gets a wrapped user object from the user storage + * @param name the username of the user to get + * @return a a {@link User} object, if one matching the uuid is loaded, or null if not + */ User getUser(String name); + + /** + * Check if a user is loaded in memory + * @param uuid the uuid to check for + * @return true if the user is loaded + */ boolean isUserLoaded(UUID uuid); + /** + * Gets a wrapped group object from the group storage + * @param name the name of the group to get + * @return a {@link Group} object, if one matching the name exists, or null if not + */ Group getGroup(String name); + + /** + * Check if a group is loaded in memory + * @param name the name to check for + * @return true if the group is loaded + */ boolean isGroupLoaded(String name); + /** + * Gets a wrapped track object from the track storage + * @param name the name of the track to get + * @return a {@link Track} object, if one matching the name exists, or null if not + */ Track getTrack(String name); + + /** + * Check if a track is loaded in memory + * @param name the name to check for + * @return true if the track is loaded + */ boolean isTrackLoaded(String name); } diff --git a/api/src/main/java/me/lucko/luckperms/api/PermissionObject.java b/api/src/main/java/me/lucko/luckperms/api/PermissionHolder.java similarity index 99% rename from api/src/main/java/me/lucko/luckperms/api/PermissionObject.java rename to api/src/main/java/me/lucko/luckperms/api/PermissionHolder.java index f743348d..9637c976 100644 --- a/api/src/main/java/me/lucko/luckperms/api/PermissionObject.java +++ b/api/src/main/java/me/lucko/luckperms/api/PermissionHolder.java @@ -7,12 +7,12 @@ import java.util.List; import java.util.Map; /** - * Wrapper interface for internal PermissionObject (user/group) instances + * Wrapper interface for internal PermissionHolder (user/group) instances * The implementations of this interface limit access to the object and add parameter checks to further prevent * errors and ensure all API interactions to not damage the state of the object. */ @SuppressWarnings("unused") -public interface PermissionObject { +public interface PermissionHolder { String getObjectName(); diff --git a/api/src/main/java/me/lucko/luckperms/api/User.java b/api/src/main/java/me/lucko/luckperms/api/User.java index d0fee8a9..f1c6aef2 100644 --- a/api/src/main/java/me/lucko/luckperms/api/User.java +++ b/api/src/main/java/me/lucko/luckperms/api/User.java @@ -12,7 +12,7 @@ import java.util.UUID; * errors and ensure all API interactions to not damage the state of the user. */ @SuppressWarnings("unused") -public interface User extends PermissionObject { +public interface User extends PermissionHolder { /** * @return the users Mojang assigned unique id diff --git a/api/src/main/java/me/lucko/luckperms/exceptions/ObjectAlreadyHasException.java b/api/src/main/java/me/lucko/luckperms/exceptions/ObjectAlreadyHasException.java index b797019b..23e66cec 100644 --- a/api/src/main/java/me/lucko/luckperms/exceptions/ObjectAlreadyHasException.java +++ b/api/src/main/java/me/lucko/luckperms/exceptions/ObjectAlreadyHasException.java @@ -1,4 +1,8 @@ package me.lucko.luckperms.exceptions; +/** + * Thrown when a permission holding object already has a permission, is already a member of a group, or when a track + * already contains a group. + */ public class ObjectAlreadyHasException extends Exception { } diff --git a/api/src/main/java/me/lucko/luckperms/exceptions/ObjectLacksException.java b/api/src/main/java/me/lucko/luckperms/exceptions/ObjectLacksException.java index 0fb7c3be..ec09e731 100644 --- a/api/src/main/java/me/lucko/luckperms/exceptions/ObjectLacksException.java +++ b/api/src/main/java/me/lucko/luckperms/exceptions/ObjectLacksException.java @@ -1,4 +1,8 @@ package me.lucko.luckperms.exceptions; +/** + * Thrown when a permission holding object does not already have a permission, is not already a member of a group, + * or when a track doesn't contain a group. + */ public class ObjectLacksException extends Exception { } diff --git a/bukkit/pom.xml b/bukkit/pom.xml index edfaf2bd..104355f1 100644 --- a/bukkit/pom.xml +++ b/bukkit/pom.xml @@ -82,5 +82,19 @@ 1.5 compile + + + com.zaxxer + HikariCP + 2.4.7 + compile + + + + org.slf4j + slf4j-simple + 1.7.9 + compile + diff --git a/bukkit/src/main/java/me/lucko/luckperms/BukkitCommand.java b/bukkit/src/main/java/me/lucko/luckperms/BukkitCommand.java index a8849744..d1ba711b 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/BukkitCommand.java +++ b/bukkit/src/main/java/me/lucko/luckperms/BukkitCommand.java @@ -1,49 +1,43 @@ package me.lucko.luckperms; import me.lucko.luckperms.commands.CommandManager; -import me.lucko.luckperms.commands.Sender; +import me.lucko.luckperms.commands.SenderFactory; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; -import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.List; class BukkitCommand extends CommandManager implements CommandExecutor, TabExecutor { + private static final Factory FACTORY = new Factory(); + BukkitCommand(LuckPermsPlugin plugin) { super(plugin); } @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - return onCommand(makeSender(sender), label, Arrays.asList(args)); + return onCommand(FACTORY.wrap(sender), label, Arrays.asList(args)); } @Override public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { - return onTabComplete(makeSender(sender), Arrays.asList(args)); + return onTabComplete(FACTORY.wrap(sender), Arrays.asList(args)); } - private static Sender makeSender(CommandSender sender) { - return new Sender() { - final WeakReference cs = new WeakReference<>(sender); + private static class Factory extends SenderFactory { - @Override - public void sendMessage(String s) { - final CommandSender c = cs.get(); - if (c != null) { - c.sendMessage(s); - } - } + @Override + protected void sendMessage(CommandSender sender, String s) { + sender.sendMessage(s); + } - @Override - public boolean hasPermission(String node) { - final CommandSender c = cs.get(); - return c != null && c.hasPermission(node); - } - }; + @Override + protected boolean hasPermission(CommandSender sender, String node) { + return sender.hasPermission(node); + } } } diff --git a/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java b/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java new file mode 100644 index 00000000..b0ad7262 --- /dev/null +++ b/bukkit/src/main/java/me/lucko/luckperms/BukkitListener.java @@ -0,0 +1,64 @@ +package me.lucko.luckperms; + +import me.lucko.luckperms.constants.Message; +import me.lucko.luckperms.users.BukkitUser; +import me.lucko.luckperms.users.User; +import me.lucko.luckperms.utils.AbstractListener; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.*; + +class BukkitListener extends AbstractListener implements Listener { + private final LPBukkitPlugin plugin; + + BukkitListener(LPBukkitPlugin plugin) { + super(plugin); + this.plugin = plugin; + } + + @EventHandler + public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) { + if (!plugin.getDatastore().isAcceptingLogins()) { + // Datastore is disabled, prevent players from joining the server + e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString()); + return; + } + + onAsyncLogin(e.getUniqueId(), e.getName()); + } + + @EventHandler + public void onPlayerLogin(PlayerLoginEvent e) { + final Player player = e.getPlayer(); + final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(player.getUniqueId())); + + if (user == null) { + e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString()); + return; + } + + if (user instanceof BukkitUser) { + BukkitUser u = (BukkitUser) user; + u.setAttachment(player.addAttachment(plugin)); + } + + user.refreshPermissions(); + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent e) { + // Refresh permissions again + refreshPlayer(e.getPlayer().getUniqueId()); + } + + @EventHandler + public void onPlayerChangedWorld(PlayerChangedWorldEvent e) { + refreshPlayer(e.getPlayer().getUniqueId()); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent e) { + onLeave(e.getPlayer().getUniqueId()); + } +} diff --git a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java index cd7acc8c..3642c0d3 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java +++ b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java @@ -5,12 +5,12 @@ import me.lucko.luckperms.api.Logger; import me.lucko.luckperms.api.LuckPermsApi; import me.lucko.luckperms.api.implementation.ApiProvider; import me.lucko.luckperms.api.vault.VaultHook; +import me.lucko.luckperms.constants.Message; import me.lucko.luckperms.data.Datastore; import me.lucko.luckperms.data.methods.FlatfileDatastore; import me.lucko.luckperms.data.methods.MySQLDatastore; import me.lucko.luckperms.data.methods.SQLiteDatastore; import me.lucko.luckperms.groups.GroupManager; -import me.lucko.luckperms.listeners.PlayerListener; import me.lucko.luckperms.runnables.UpdateTask; import me.lucko.luckperms.tracks.TrackManager; import me.lucko.luckperms.users.BukkitUserManager; @@ -47,7 +47,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { // register events PluginManager pm = Bukkit.getPluginManager(); - pm.registerEvents(new PlayerListener(this), this); + pm.registerEvents(new BukkitListener(this), this); // register commands getLog().info("Registering commands..."); @@ -149,8 +149,8 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { } @Override - public String getPlayerStatus(UUID uuid) { - return getServer().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? "&aOnline" : "&cOffline"; + public Message getPlayerStatus(UUID uuid) { + return getServer().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE; } @Override diff --git a/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultPermissionHook.java b/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultPermissionHook.java index d23ba125..7567d75a 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultPermissionHook.java +++ b/bukkit/src/main/java/me/lucko/luckperms/api/vault/VaultPermissionHook.java @@ -7,7 +7,7 @@ import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.groups.Group; import me.lucko.luckperms.users.User; -import me.lucko.luckperms.utils.PermissionObject; +import me.lucko.luckperms.utils.PermissionHolder; import net.milkbowl.vault.permission.Permission; /** @@ -33,7 +33,7 @@ class VaultPermissionHook extends Permission { return true; } - private boolean objectHas(String world, PermissionObject object, String permission) { + private boolean objectHas(String world, PermissionHolder object, String permission) { if (object == null) return false; if (world != null && !world.equals("")) { @@ -43,7 +43,7 @@ class VaultPermissionHook extends Permission { } } - private boolean objectAdd(String world, PermissionObject object, String permission) { + private boolean objectAdd(String world, PermissionHolder object, String permission) { if (object == null) return false; try { @@ -58,7 +58,7 @@ class VaultPermissionHook extends Permission { return true; } - private boolean objectRemove(String world, PermissionObject object, String permission) { + private boolean objectRemove(String world, PermissionHolder object, String permission) { if (object == null) return false; try { @@ -73,7 +73,7 @@ class VaultPermissionHook extends Permission { return true; } - private void objectSave(PermissionObject t) { + private void objectSave(PermissionHolder t) { if (t instanceof User) { ((User) t).refreshPermissions(); plugin.getDatastore().saveUser(((User) t), aBoolean -> {}); diff --git a/bukkit/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java b/bukkit/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java deleted file mode 100644 index 6b644310..00000000 --- a/bukkit/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java +++ /dev/null @@ -1,101 +0,0 @@ -package me.lucko.luckperms.listeners; - -import lombok.AllArgsConstructor; -import me.lucko.luckperms.LPBukkitPlugin; -import me.lucko.luckperms.commands.Util; -import me.lucko.luckperms.constants.Message; -import me.lucko.luckperms.users.BukkitUser; -import me.lucko.luckperms.users.User; -import me.lucko.luckperms.utils.UuidCache; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.*; - -import java.util.UUID; - -@AllArgsConstructor -public class PlayerListener implements Listener { - private static final String KICK_MESSAGE = Util.color(Message.PREFIX + "User data could not be loaded. Please contact an administrator."); - private final LPBukkitPlugin plugin; - - @EventHandler - public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) { - final long startTime = System.currentTimeMillis(); - if (!plugin.getDatastore().isAcceptingLogins()) { - // Datastore is disabled, prevent players from joining the server - e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, KICK_MESSAGE); - return; - } - - final UuidCache cache = plugin.getUuidCache(); - if (!cache.isOnlineMode()) { - UUID uuid = plugin.getDatastore().getUUID(e.getName()); - if (uuid != null) { - cache.addToCache(e.getUniqueId(), uuid); - } else { - // No previous data for this player - cache.addToCache(e.getUniqueId(), e.getUniqueId()); - plugin.getDatastore().saveUUIDData(e.getName(), e.getUniqueId(), b -> {}); - } - } else { - // Online mode, no cache needed. This is just for name -> uuid lookup. - plugin.getDatastore().saveUUIDData(e.getName(), e.getUniqueId(), b -> {}); - } - - plugin.getDatastore().loadOrCreateUser(cache.getUUID(e.getUniqueId()), e.getName()); - final long time = System.currentTimeMillis() - startTime; - if (time >= 1000) { - plugin.getLog().warn("Processing login for " + e.getName() + " took " + time + "ms."); - } - } - - @EventHandler - public void onPlayerLogin(PlayerLoginEvent e) { - final Player player = e.getPlayer(); - final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(player.getUniqueId())); - - if (user == null) { - e.disallow(PlayerLoginEvent.Result.KICK_OTHER, KICK_MESSAGE); - return; - } - - if (user instanceof BukkitUser) { - BukkitUser u = (BukkitUser) user; - u.setAttachment(player.addAttachment(plugin)); - } - - user.refreshPermissions(); - } - - @EventHandler - public void onPlayerJoin(PlayerJoinEvent e) { - // Refresh permissions again - refreshPlayer(e.getPlayer()); - } - - @EventHandler - public void onPlayerChangedWorld(PlayerChangedWorldEvent e) { - refreshPlayer(e.getPlayer()); - } - - @EventHandler - public void onPlayerQuit(PlayerQuitEvent e) { - final Player player = e.getPlayer(); - final UuidCache cache = plugin.getUuidCache(); - - // Unload the user from memory when they disconnect; - cache.clearCache(player.getUniqueId()); - - final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId())); - plugin.getUserManager().unloadUser(user); - } - - private void refreshPlayer(Player p) { - final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(p.getUniqueId())); - if (user != null) { - user.refreshPermissions(); - } - } - -} diff --git a/bungee/pom.xml b/bungee/pom.xml index 6bd35a7a..0d9d6bdf 100644 --- a/bungee/pom.xml +++ b/bungee/pom.xml @@ -75,6 +75,20 @@ 1.5 compile + + + com.zaxxer + HikariCP + 2.4.7 + compile + + + + org.slf4j + slf4j-simple + 1.7.9 + compile + diff --git a/bungee/src/main/java/me/lucko/luckperms/BungeeCommand.java b/bungee/src/main/java/me/lucko/luckperms/BungeeCommand.java index 6ec83b4d..6fe91ae4 100644 --- a/bungee/src/main/java/me/lucko/luckperms/BungeeCommand.java +++ b/bungee/src/main/java/me/lucko/luckperms/BungeeCommand.java @@ -1,16 +1,16 @@ package me.lucko.luckperms; import me.lucko.luckperms.commands.CommandManager; -import me.lucko.luckperms.commands.Sender; +import me.lucko.luckperms.commands.SenderFactory; import net.md_5.bungee.api.CommandSender; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.plugin.Command; import net.md_5.bungee.api.plugin.TabExecutor; -import java.lang.ref.WeakReference; import java.util.Arrays; class BungeeCommand extends Command implements TabExecutor { + private static final Factory FACTORY = new Factory(); private final CommandManager manager; public BungeeCommand(CommandManager manager) { @@ -20,31 +20,24 @@ class BungeeCommand extends Command implements TabExecutor { @Override public void execute(CommandSender sender, String[] args) { - manager.onCommand(makeSender(sender), "bperms", Arrays.asList(args)); + manager.onCommand(FACTORY.wrap(sender), "bperms", Arrays.asList(args)); } @Override public Iterable onTabComplete(CommandSender sender, String[] args) { - return manager.onTabComplete(makeSender(sender), Arrays.asList(args)); + return manager.onTabComplete(FACTORY.wrap(sender), Arrays.asList(args)); } - private static Sender makeSender(CommandSender sender) { - return new Sender() { - final WeakReference cs = new WeakReference<>(sender); + private static class Factory extends SenderFactory { - @Override - public void sendMessage(String s) { - final CommandSender c = cs.get(); - if (c != null) { - c.sendMessage(new TextComponent(s)); - } - } + @Override + protected void sendMessage(CommandSender sender, String s) { + sender.sendMessage(new TextComponent(s)); + } - @Override - public boolean hasPermission(String node) { - final CommandSender c = cs.get(); - return c != null && c.hasPermission(node); - } - }; + @Override + protected boolean hasPermission(CommandSender sender, String node) { + return sender.hasPermission(node); + } } } diff --git a/bungee/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java b/bungee/src/main/java/me/lucko/luckperms/BungeeListener.java similarity index 79% rename from bungee/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java rename to bungee/src/main/java/me/lucko/luckperms/BungeeListener.java index 1fcc96cc..d7534d3a 100644 --- a/bungee/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java +++ b/bungee/src/main/java/me/lucko/luckperms/BungeeListener.java @@ -1,10 +1,8 @@ -package me.lucko.luckperms.listeners; +package me.lucko.luckperms; -import lombok.AllArgsConstructor; -import me.lucko.luckperms.LPBungeePlugin; -import me.lucko.luckperms.commands.Util; import me.lucko.luckperms.constants.Message; import me.lucko.luckperms.users.User; +import me.lucko.luckperms.utils.AbstractListener; import me.lucko.luckperms.utils.UuidCache; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.connection.PendingConnection; @@ -20,13 +18,15 @@ import java.lang.ref.WeakReference; import java.util.UUID; import java.util.concurrent.TimeUnit; -@AllArgsConstructor -public class PlayerListener implements Listener { - private static final TextComponent WARN_MESSAGE = new TextComponent(Util.color( - Message.PREFIX + "Permissions data could not be loaded. Please contact an administrator.") - ); +class BungeeListener extends AbstractListener implements Listener { + private static final TextComponent WARN_MESSAGE = new TextComponent(Message.LOADING_ERROR.toString()); private final LPBungeePlugin plugin; + BungeeListener(LPBungeePlugin plugin) { + super(plugin); + this.plugin = plugin; + } + @EventHandler public void onPlayerLogin(LoginEvent e) { /* Delay the login here, as we want to cache UUID data before the player is connected to a backend bukkit server. @@ -83,21 +83,11 @@ public class PlayerListener implements Listener { @EventHandler public void onPlayerQuit(PlayerDisconnectEvent e) { - final ProxiedPlayer player = e.getPlayer(); - final UuidCache cache = plugin.getUuidCache(); - - // Unload the user from memory when they disconnect; - cache.clearCache(player.getUniqueId()); - - final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId())); - plugin.getUserManager().unloadUser(user); + onLeave(e.getPlayer().getUniqueId()); } @EventHandler public void onPlayerServerSwitch(ServerSwitchEvent e) { - final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId())); - if (user != null) { - user.refreshPermissions(); - } + refreshPlayer(e.getPlayer().getUniqueId()); } } diff --git a/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java b/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java index e19ba06e..d26a88a8 100644 --- a/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java +++ b/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java @@ -4,11 +4,11 @@ import lombok.Getter; import me.lucko.luckperms.api.Logger; import me.lucko.luckperms.api.implementation.ApiProvider; import me.lucko.luckperms.commands.CommandManager; +import me.lucko.luckperms.constants.Message; import me.lucko.luckperms.data.Datastore; import me.lucko.luckperms.data.methods.FlatfileDatastore; import me.lucko.luckperms.data.methods.MySQLDatastore; import me.lucko.luckperms.groups.GroupManager; -import me.lucko.luckperms.listeners.PlayerListener; import me.lucko.luckperms.runnables.UpdateTask; import me.lucko.luckperms.tracks.TrackManager; import me.lucko.luckperms.users.BungeeUserManager; @@ -39,7 +39,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin { configuration = new BungeeConfig(this); // register events - getProxy().getPluginManager().registerListener(this, new PlayerListener(this)); + getProxy().getPluginManager().registerListener(this, new BungeeListener(this)); // register commands getLog().info("Registering commands..."); @@ -109,8 +109,8 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin { } @Override - public String getPlayerStatus(UUID uuid) { - return getProxy().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? "&aOnline" : "&cOffline"; + public Message getPlayerStatus(UUID uuid) { + return getProxy().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE; } @Override diff --git a/common/pom.xml b/common/pom.xml index 50362a34..047d0af6 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -33,6 +33,27 @@ 1.5 compile + + + com.zaxxer + HikariCP + 2.4.7 + compile + + + + org.slf4j + slf4j-simple + 1.7.9 + compile + + + + com.google.code.gson + gson + 2.7 + provided + diff --git a/common/src/main/java/me/lucko/luckperms/LuckPermsPlugin.java b/common/src/main/java/me/lucko/luckperms/LuckPermsPlugin.java index 1e581bf0..fbf7961c 100644 --- a/common/src/main/java/me/lucko/luckperms/LuckPermsPlugin.java +++ b/common/src/main/java/me/lucko/luckperms/LuckPermsPlugin.java @@ -1,6 +1,7 @@ package me.lucko.luckperms; import me.lucko.luckperms.api.Logger; +import me.lucko.luckperms.constants.Message; import me.lucko.luckperms.data.Datastore; import me.lucko.luckperms.groups.GroupManager; import me.lucko.luckperms.tracks.TrackManager; @@ -11,6 +12,10 @@ import me.lucko.luckperms.utils.UuidCache; import java.util.List; import java.util.UUID; +/** + * Main internal interface for LuckPerms plugins, allowing the luckperms-common module to bind with the plugin instance. + * All plugin platforms implement this interface. + */ public interface LuckPermsPlugin { /** @@ -65,7 +70,7 @@ public interface LuckPermsPlugin { * @param uuid The player's uuid * @return a formatted status string */ - String getPlayerStatus(UUID uuid); + Message getPlayerStatus(UUID uuid); /** * Gets the number of users online on the platform diff --git a/common/src/main/java/me/lucko/luckperms/api/implementation/internal/GroupLink.java b/common/src/main/java/me/lucko/luckperms/api/implementation/internal/GroupLink.java index 593053ae..150e036c 100644 --- a/common/src/main/java/me/lucko/luckperms/api/implementation/internal/GroupLink.java +++ b/common/src/main/java/me/lucko/luckperms/api/implementation/internal/GroupLink.java @@ -13,7 +13,7 @@ import java.util.List; * Provides a link between {@link Group} and {@link me.lucko.luckperms.groups.Group} */ @SuppressWarnings("unused") -public class GroupLink extends PermissionObjectLink implements Group { +public class GroupLink extends PermissionHolderLink implements Group { @Getter(AccessLevel.PACKAGE) private final me.lucko.luckperms.groups.Group master; diff --git a/common/src/main/java/me/lucko/luckperms/api/implementation/internal/PermissionObjectLink.java b/common/src/main/java/me/lucko/luckperms/api/implementation/internal/PermissionHolderLink.java similarity index 96% rename from common/src/main/java/me/lucko/luckperms/api/implementation/internal/PermissionObjectLink.java rename to common/src/main/java/me/lucko/luckperms/api/implementation/internal/PermissionHolderLink.java index 0e065e6e..f11cbc08 100644 --- a/common/src/main/java/me/lucko/luckperms/api/implementation/internal/PermissionObjectLink.java +++ b/common/src/main/java/me/lucko/luckperms/api/implementation/internal/PermissionHolderLink.java @@ -3,7 +3,7 @@ package me.lucko.luckperms.api.implementation.internal; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.NonNull; -import me.lucko.luckperms.api.PermissionObject; +import me.lucko.luckperms.api.PermissionHolder; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.utils.DateUtil; @@ -14,14 +14,14 @@ import java.util.List; import java.util.Map; /** - * Provides a link between {@link PermissionObject} and {@link me.lucko.luckperms.utils.PermissionObject} + * Provides a link between {@link PermissionHolder} and {@link me.lucko.luckperms.utils.PermissionHolder} */ @SuppressWarnings("unused") @AllArgsConstructor(access = AccessLevel.PACKAGE) -class PermissionObjectLink implements PermissionObject { +class PermissionHolderLink implements PermissionHolder { @NonNull - private final me.lucko.luckperms.utils.PermissionObject master; + private final me.lucko.luckperms.utils.PermissionHolder master; static String checkServer(String s) { if (Patterns.NON_ALPHA_NUMERIC.matcher(s).find()) { diff --git a/common/src/main/java/me/lucko/luckperms/api/implementation/internal/UserLink.java b/common/src/main/java/me/lucko/luckperms/api/implementation/internal/UserLink.java index 5c5956fc..336480ab 100644 --- a/common/src/main/java/me/lucko/luckperms/api/implementation/internal/UserLink.java +++ b/common/src/main/java/me/lucko/luckperms/api/implementation/internal/UserLink.java @@ -15,7 +15,7 @@ import java.util.UUID; * Provides a link between {@link User} and {@link me.lucko.luckperms.users.User} */ @SuppressWarnings("unused") -public class UserLink extends PermissionObjectLink implements User { +public class UserLink extends PermissionHolderLink implements User { @Getter(AccessLevel.PACKAGE) private final me.lucko.luckperms.users.User master; diff --git a/common/src/main/java/me/lucko/luckperms/api/implementation/internal/Utils.java b/common/src/main/java/me/lucko/luckperms/api/implementation/internal/Utils.java index efed0d6b..338ee449 100644 --- a/common/src/main/java/me/lucko/luckperms/api/implementation/internal/Utils.java +++ b/common/src/main/java/me/lucko/luckperms/api/implementation/internal/Utils.java @@ -1,9 +1,11 @@ package me.lucko.luckperms.api.implementation.internal; +import lombok.experimental.UtilityClass; import me.lucko.luckperms.api.Group; import me.lucko.luckperms.api.Track; import me.lucko.luckperms.api.User; +@UtilityClass class Utils { static void checkUser(User user) { diff --git a/common/src/main/java/me/lucko/luckperms/commands/SenderFactory.java b/common/src/main/java/me/lucko/luckperms/commands/SenderFactory.java new file mode 100644 index 00000000..a18f0723 --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/commands/SenderFactory.java @@ -0,0 +1,30 @@ +package me.lucko.luckperms.commands; + +import java.lang.ref.WeakReference; + +public abstract class SenderFactory { + + protected abstract void sendMessage(T t, String s); + protected abstract boolean hasPermission(T t, String node); + + public Sender wrap(T t) { + final SenderFactory factory = this; + return new Sender() { + final WeakReference cs = new WeakReference<>(t); + + @Override + public void sendMessage(String s) { + final T c = cs.get(); + if (c != null) { + factory.sendMessage(c, s); + } + } + + @Override + public boolean hasPermission(String node) { + final T c = cs.get(); + return c != null && factory.hasPermission(c, node); + } + }; + } +} diff --git a/common/src/main/java/me/lucko/luckperms/constants/Message.java b/common/src/main/java/me/lucko/luckperms/constants/Message.java index 07cf7681..f88aa431 100644 --- a/common/src/main/java/me/lucko/luckperms/constants/Message.java +++ b/common/src/main/java/me/lucko/luckperms/constants/Message.java @@ -13,6 +13,9 @@ public enum Message { */ PREFIX("&7&l[&b&lL&a&lP&7&l] &c", false), EMPTY("%s", true), + PLAYER_ONLINE("&aOnline", false), + PLAYER_OFFLINE("&cOffline", false), + LOADING_ERROR("Permissions data could not be loaded. Please contact an administrator.", true), COMMAND_NOT_RECOGNISED("Command not recognised.", true), COMMAND_NO_PERMISSION("You do not have permission to use this command!", true), @@ -225,7 +228,7 @@ public enum Message { @Override public String toString() { - return message; + return Util.color(showPrefix ? PREFIX + message : message); } public void send(Sender sender, Object... objects) { diff --git a/common/src/main/java/me/lucko/luckperms/groups/Group.java b/common/src/main/java/me/lucko/luckperms/groups/Group.java index 4a8031d5..1101a61e 100644 --- a/common/src/main/java/me/lucko/luckperms/groups/Group.java +++ b/common/src/main/java/me/lucko/luckperms/groups/Group.java @@ -7,7 +7,7 @@ import me.lucko.luckperms.LuckPermsPlugin; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.utils.Patterns; -import me.lucko.luckperms.utils.PermissionObject; +import me.lucko.luckperms.utils.PermissionHolder; import java.util.List; import java.util.Map; @@ -15,7 +15,7 @@ import java.util.stream.Collectors; @ToString(of = {"name"}) @EqualsAndHashCode(of = {"name"}, callSuper = false) -public class Group extends PermissionObject { +public class Group extends PermissionHolder { /** * The name of the group @@ -263,7 +263,7 @@ public class Group extends PermissionObject { Map perms = getPermissions(server, world, null, includeGlobal); return perms.keySet().stream() .filter(s -> Patterns.GROUP_MATCH.matcher(s).matches()) - .map(s -> Patterns.DOT_SPLIT.split(s, 2)[1]) + .map(s -> Patterns.DOT.split(s, 2)[1]) .collect(Collectors.toList()); } } diff --git a/common/src/main/java/me/lucko/luckperms/users/User.java b/common/src/main/java/me/lucko/luckperms/users/User.java index 9484b01f..9e038877 100644 --- a/common/src/main/java/me/lucko/luckperms/users/User.java +++ b/common/src/main/java/me/lucko/luckperms/users/User.java @@ -9,7 +9,7 @@ import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectLacksException; import me.lucko.luckperms.groups.Group; import me.lucko.luckperms.utils.Patterns; -import me.lucko.luckperms.utils.PermissionObject; +import me.lucko.luckperms.utils.PermissionHolder; import java.util.List; import java.util.Map; @@ -18,7 +18,7 @@ import java.util.stream.Collectors; @ToString(of = {"uuid"}) @EqualsAndHashCode(of = {"uuid"}, callSuper = false) -public abstract class User extends PermissionObject { +public abstract class User extends PermissionHolder { /** * The users Mojang UUID @@ -294,7 +294,7 @@ public abstract class User extends PermissionObject { Map perms = getPermissions(server, world, null, includeGlobal); return perms.keySet().stream() .filter(s -> Patterns.GROUP_MATCH.matcher(s).matches()) - .map(s -> Patterns.DOT_SPLIT.split(s, 2)[1]) + .map(s -> Patterns.DOT.split(s, 2)[1]) .collect(Collectors.toList()); } } diff --git a/common/src/main/java/me/lucko/luckperms/utils/AbstractListener.java b/common/src/main/java/me/lucko/luckperms/utils/AbstractListener.java new file mode 100644 index 00000000..dacbfd0f --- /dev/null +++ b/common/src/main/java/me/lucko/luckperms/utils/AbstractListener.java @@ -0,0 +1,62 @@ +package me.lucko.luckperms.utils; + +import lombok.AllArgsConstructor; +import me.lucko.luckperms.LuckPermsPlugin; +import me.lucko.luckperms.users.User; + +import java.util.UUID; + +@AllArgsConstructor +public class AbstractListener { + private final LuckPermsPlugin plugin; + + protected void onAsyncLogin(UUID u, String username) { + final long startTime = System.currentTimeMillis(); + + final UuidCache cache = plugin.getUuidCache(); + if (!cache.isOnlineMode()) { + UUID uuid = plugin.getDatastore().getUUID(username); + if (uuid != null) { + cache.addToCache(u, uuid); + } else { + // No previous data for this player + cache.addToCache(u, u); + plugin.getDatastore().saveUUIDData(username, u, b -> {}); + } + } else { + // Online mode, no cache needed. This is just for name -> uuid lookup. + plugin.getDatastore().saveUUIDData(username, u, b -> {}); + } + + plugin.getDatastore().loadOrCreateUser(cache.getUUID(u), username); + final long time = System.currentTimeMillis() - startTime; + if (time >= 1000) { + plugin.getLog().warn("Processing login for " + username + " took " + time + "ms."); + } + } + + protected void onLogin(UUID uuid, String username) { + + } + + protected void onJoin(UUID uuid, String username) { + + } + + protected void onLeave(UUID uuid) { + final UuidCache cache = plugin.getUuidCache(); + + // Unload the user from memory when they disconnect; + cache.clearCache(uuid); + + final User user = plugin.getUserManager().getUser(cache.getUUID(uuid)); + plugin.getUserManager().unloadUser(user); + } + + protected void refreshPlayer(UUID uuid) { + final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(uuid)); + if (user != null) { + user.refreshPermissions(); + } + } +} diff --git a/common/src/main/java/me/lucko/luckperms/utils/Patterns.java b/common/src/main/java/me/lucko/luckperms/utils/Patterns.java index 159a62e3..f68a2ad7 100644 --- a/common/src/main/java/me/lucko/luckperms/utils/Patterns.java +++ b/common/src/main/java/me/lucko/luckperms/utils/Patterns.java @@ -6,11 +6,11 @@ import java.util.regex.Pattern; @UtilityClass public class Patterns { - public static final Pattern SPACE_SPLIT = Pattern.compile(" "); - public static final Pattern SERVER_SPLIT = Pattern.compile("\\/"); - public static final Pattern WORLD_SPLIT = Pattern.compile("\\-"); - public static final Pattern TEMP_SPLIT = Pattern.compile("\\$"); - public static final Pattern DOT_SPLIT = Pattern.compile("\\."); + public static final Pattern SPACE = Pattern.compile(" "); + public static final Pattern SERVER_DELIMITER = Pattern.compile("\\/"); + public static final Pattern WORLD_DELIMITER = Pattern.compile("\\-"); + public static final Pattern TEMP_DELIMITER = Pattern.compile("\\$"); + public static final Pattern DOT = Pattern.compile("\\."); public static final Pattern GROUP_MATCH = Pattern.compile("group\\..*"); public static final Pattern NON_ALPHA_NUMERIC = Pattern.compile("[^A-Za-z0-9]"); public static final Pattern NON_USERNAME = Pattern.compile("[^A-Za-z0-9_]"); diff --git a/common/src/main/java/me/lucko/luckperms/utils/PermissionObject.java b/common/src/main/java/me/lucko/luckperms/utils/PermissionHolder.java similarity index 94% rename from common/src/main/java/me/lucko/luckperms/utils/PermissionObject.java rename to common/src/main/java/me/lucko/luckperms/utils/PermissionHolder.java index 8cfc2a90..6a1d8235 100644 --- a/common/src/main/java/me/lucko/luckperms/utils/PermissionObject.java +++ b/common/src/main/java/me/lucko/luckperms/utils/PermissionHolder.java @@ -17,7 +17,7 @@ import java.util.stream.Collectors; * For example a User or a Group */ @RequiredArgsConstructor(access = AccessLevel.PROTECTED) -public abstract class PermissionObject { +public abstract class PermissionHolder { /** * The UUID of the user / name of the group. @@ -53,11 +53,11 @@ public abstract class PermissionObject { return b ? toQuery.containsKey(node) && toQuery.get(node) : toQuery.containsKey(node) && !toQuery.get(node); } - node = Patterns.TEMP_SPLIT.split(node)[0]; + node = Patterns.TEMP_DELIMITER.split(node)[0]; for (Map.Entry e : toQuery.entrySet()) { if (e.getKey().contains("$")) { - String[] parts = Patterns.TEMP_SPLIT.split(e.getKey()); + String[] parts = Patterns.TEMP_DELIMITER.split(e.getKey()); if (parts[0].equalsIgnoreCase(node)) { return b ? e.getValue() : !e.getValue(); } @@ -146,7 +146,7 @@ public abstract class PermissionObject { public boolean inheritsPermission(String node, boolean b) { if (node.contains("/")) { // Use other method - final String[] parts = Patterns.SERVER_SPLIT.split(node, 2); + final String[] parts = Patterns.SERVER_DELIMITER.split(node, 2); return inheritsPermission(parts[1], b, parts[0]); } @@ -163,7 +163,7 @@ public abstract class PermissionObject { public boolean inheritsPermission(String node, boolean b, String server) { if (server.contains("-")) { // Use other method - final String[] parts = Patterns.WORLD_SPLIT.split(server, 2); + final String[] parts = Patterns.WORLD_DELIMITER.split(server, 2); return inheritsPermission(node, b, parts[0], parts[1]); } @@ -306,7 +306,7 @@ public abstract class PermissionObject { if (temporary) { match = this.nodes.keySet().stream() - .filter(n -> n.contains("$")).filter(n -> Patterns.TEMP_SPLIT.split(n)[0].equalsIgnoreCase(fNode)) + .filter(n -> n.contains("$")).filter(n -> Patterns.TEMP_DELIMITER.split(n)[0].equalsIgnoreCase(fNode)) .findFirst(); } else { if (this.nodes.containsKey(fNode)) { @@ -401,7 +401,7 @@ public abstract class PermissionObject { */ public Map, Long> getTemporaryNodes() { return this.nodes.entrySet().stream().filter(e -> e.getKey().contains("$")).map(e -> { - final String[] parts = Patterns.TEMP_SPLIT.split(e.getKey()); + final String[] parts = Patterns.TEMP_DELIMITER.split(e.getKey()); final long expiry = Long.parseLong(parts[1]); return new AbstractMap.SimpleEntry, Long>(new AbstractMap.SimpleEntry<>(parts[0], e.getValue()), expiry); @@ -423,7 +423,7 @@ public abstract class PermissionObject { public void auditTemporaryPermissions() { this.nodes.keySet().stream() .filter(s -> s.contains("$")) - .filter(s -> DateUtil.shouldExpire(Long.parseLong(Patterns.TEMP_SPLIT.split(s)[1]))) + .filter(s -> DateUtil.shouldExpire(Long.parseLong(Patterns.TEMP_DELIMITER.split(s)[1]))) .forEach(s -> this.nodes.remove(s)); } @@ -484,12 +484,12 @@ public abstract class PermissionObject { for (Map.Entry node : convertTemporaryPerms().entrySet()) { serverSpecific: if (node.getKey().contains("/")) { - String[] parts = Patterns.SERVER_SPLIT.split(node.getKey(), 2); + String[] parts = Patterns.SERVER_DELIMITER.split(node.getKey(), 2); // 0=server(+world) 1=node // WORLD SPECIFIC if (parts[0].contains("-")) { - String[] serverParts = Patterns.WORLD_SPLIT.split(parts[0], 2); + String[] serverParts = Patterns.WORLD_DELIMITER.split(parts[0], 2); // 0=server 1=world if ((!serverParts[0].equalsIgnoreCase("global") || !includeGlobal) && (!serverParts[0].equalsIgnoreCase(server))) { @@ -540,7 +540,7 @@ public abstract class PermissionObject { // Could be here if the server was set to global. String n = node.getKey(); if (n.contains("/")) { - n = Patterns.SERVER_SPLIT.split(n, 2)[1]; + n = Patterns.SERVER_DELIMITER.split(n, 2)[1]; } if (Patterns.GROUP_MATCH.matcher(n).matches()) { @@ -556,14 +556,14 @@ public abstract class PermissionObject { // If a group is negated at a higher priority, the group should not then be applied at a lower priority serverWorldSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> { groupNodes.remove(node.getKey()); - groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]); + groupNodes.remove(Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]); serverSpecificGroups.remove(node.getKey()); - serverSpecificGroups.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]); - serverSpecificGroups.remove(Patterns.WORLD_SPLIT.split(node.getKey(), 2)[0] + "/" + Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]); + serverSpecificGroups.remove(Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]); + serverSpecificGroups.remove(Patterns.WORLD_DELIMITER.split(node.getKey(), 2)[0] + "/" + Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]); }); serverSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> { groupNodes.remove(node.getKey()); - groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]); + groupNodes.remove(Patterns.SERVER_DELIMITER.split(node.getKey(), 2)[1]); }); // Apply lowest priority: groupNodes @@ -574,7 +574,7 @@ public abstract class PermissionObject { // Don't add negated groups if (!groupNode.getValue()) continue; - String groupName = Patterns.DOT_SPLIT.split(groupNode.getKey(), 2)[1]; + String groupName = Patterns.DOT.split(groupNode.getKey(), 2)[1]; if (!excludedGroups.contains(groupName)) { Group group = plugin.getGroupManager().getGroup(groupName); if (group != null) { @@ -589,7 +589,7 @@ public abstract class PermissionObject { // Apply next priorities: serverSpecificGroups and then serverWorldSpecificGroups for (Map m : Arrays.asList(serverSpecificGroups, serverWorldSpecificGroups)) { for (Map.Entry groupNode : m.entrySet()) { - final String rawNode = Patterns.SERVER_SPLIT.split(groupNode.getKey())[1]; + final String rawNode = Patterns.SERVER_DELIMITER.split(groupNode.getKey())[1]; // Add the actual group perm node, so other plugins can hook perms.put(rawNode, groupNode.getValue()); @@ -597,7 +597,7 @@ public abstract class PermissionObject { // Don't add negated groups if (!groupNode.getValue()) continue; - String groupName = Patterns.DOT_SPLIT.split(rawNode, 2)[1]; + String groupName = Patterns.DOT.split(rawNode, 2)[1]; if (!excludedGroups.contains(groupName)) { Group group = plugin.getGroupManager().getGroup(groupName); if (group != null) { @@ -616,7 +616,7 @@ public abstract class PermissionObject { // Apply final priorities: serverSpecificNodes and then serverWorldSpecificNodes for (Map m : Arrays.asList(serverSpecificNodes, serverWorldSpecificNodes)) { for (Map.Entry node : m.entrySet()) { - final String rawNode = Patterns.SERVER_SPLIT.split(node.getKey())[1]; + final String rawNode = Patterns.SERVER_DELIMITER.split(node.getKey())[1]; perms.put(rawNode, node.getValue()); } } @@ -626,7 +626,7 @@ public abstract class PermissionObject { private static String stripTime(String s) { if (s.contains("$")) { - return Patterns.TEMP_SPLIT.split(s)[0]; + return Patterns.TEMP_DELIMITER.split(s)[0]; } return s; } diff --git a/pom.xml b/pom.xml index b46f0d78..7ac318d2 100644 --- a/pom.xml +++ b/pom.xml @@ -41,27 +41,6 @@ - - - com.zaxxer - HikariCP - 2.4.7 - compile - - - - org.slf4j - slf4j-simple - 1.7.9 - compile - - - - com.google.code.gson - gson - 2.7 - provided - org.projectlombok diff --git a/sponge/pom.xml b/sponge/pom.xml index 88bd373b..a37157c4 100644 --- a/sponge/pom.xml +++ b/sponge/pom.xml @@ -75,5 +75,19 @@ 1.5 compile + + + com.zaxxer + HikariCP + 2.4.7 + compile + + + + org.slf4j + slf4j-simple + 1.7.9 + compile + diff --git a/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java b/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java index 1b93eab2..f8e7fe83 100644 --- a/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java +++ b/sponge/src/main/java/me/lucko/luckperms/LPSpongePlugin.java @@ -4,12 +4,12 @@ import com.google.inject.Inject; import lombok.Getter; import me.lucko.luckperms.api.LuckPermsApi; import me.lucko.luckperms.api.implementation.ApiProvider; +import me.lucko.luckperms.constants.Message; import me.lucko.luckperms.data.Datastore; import me.lucko.luckperms.data.methods.FlatfileDatastore; import me.lucko.luckperms.data.methods.MySQLDatastore; import me.lucko.luckperms.data.methods.SQLiteDatastore; import me.lucko.luckperms.groups.GroupManager; -import me.lucko.luckperms.listeners.PlayerListener; import me.lucko.luckperms.runnables.UpdateTask; import me.lucko.luckperms.tracks.TrackManager; import me.lucko.luckperms.users.SpongeUserManager; @@ -37,7 +37,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Getter -@Plugin(id = "luckperms", name = "LuckPerms", version = LPSpongePlugin.VERSION) +@Plugin(id = "luckperms", name = "LuckPerms", version = LPSpongePlugin.VERSION, authors = {"Luck"}, description = "A permissions plugin") public class LPSpongePlugin implements LuckPermsPlugin { static final String VERSION = "1.5"; // TODO load this from pom @@ -59,14 +59,17 @@ public class LPSpongePlugin implements LuckPermsPlugin { private TrackManager trackManager; private Datastore datastore; private UuidCache uuidCache; + private me.lucko.luckperms.api.Logger log; @Listener public void onEnable(GamePreInitializationEvent event) { + log = LogUtil.wrap(logger); + getLog().info("Loading configuration..."); configuration = new SpongeConfig(this); // register events - Sponge.getEventManager().registerListeners(this, new PlayerListener(this)); + Sponge.getEventManager().registerListeners(this, new SpongeListener(this)); // register commands getLog().info("Registering commands..."); @@ -129,16 +132,12 @@ public class LPSpongePlugin implements LuckPermsPlugin { LuckPerms.unregisterProvider(); } + @SuppressWarnings("ResultOfMethodCallIgnored") private File getStorageDir() { File base = configDir.toFile().getParentFile().getParentFile(); - File luckperms = new File(base, "luckperms"); - luckperms.mkdirs(); - return luckperms; - } - - @Override - public me.lucko.luckperms.api.Logger getLog() { - return LogUtil.wrap(getLogger()); + File luckPermsDir = new File(base, "luckperms"); + luckPermsDir.mkdirs(); + return luckPermsDir; } @Override @@ -147,8 +146,8 @@ public class LPSpongePlugin implements LuckPermsPlugin { } @Override - public String getPlayerStatus(UUID uuid) { - return game.getServer().getPlayer(getUuidCache().getExternalUUID(uuid)).isPresent() ? "&aOnline" : "&cOffline"; + public Message getPlayerStatus(UUID uuid) { + return game.getServer().getPlayer(getUuidCache().getExternalUUID(uuid)).isPresent() ? Message.PLAYER_ONLINE : Message.PLAYER_OFFLINE; } @Override diff --git a/sponge/src/main/java/me/lucko/luckperms/SpongeCommand.java b/sponge/src/main/java/me/lucko/luckperms/SpongeCommand.java index d0a66d04..10d56ac7 100644 --- a/sponge/src/main/java/me/lucko/luckperms/SpongeCommand.java +++ b/sponge/src/main/java/me/lucko/luckperms/SpongeCommand.java @@ -1,7 +1,7 @@ package me.lucko.luckperms; import me.lucko.luckperms.commands.CommandManager; -import me.lucko.luckperms.commands.Sender; +import me.lucko.luckperms.commands.SenderFactory; import me.lucko.luckperms.utils.Patterns; import org.spongepowered.api.command.CommandCallable; import org.spongepowered.api.command.CommandException; @@ -10,65 +10,59 @@ import org.spongepowered.api.command.CommandSource; import org.spongepowered.api.text.Text; import org.spongepowered.api.text.serializer.TextSerializers; -import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.List; import java.util.Optional; -public class SpongeCommand extends CommandManager implements CommandCallable { - public SpongeCommand(LuckPermsPlugin plugin) { +class SpongeCommand extends CommandManager implements CommandCallable { + private static final Factory FACTORY = new Factory(); + + SpongeCommand(LuckPermsPlugin plugin) { super(plugin); } @Override public CommandResult process(CommandSource source, String s) throws CommandException { - onCommand(makeSender(source), "perms", Arrays.asList(Patterns.SPACE_SPLIT.split(s))); + onCommand(FACTORY.wrap(source), "perms", Arrays.asList(Patterns.SPACE.split(s))); return CommandResult.success(); } @Override public List getSuggestions(CommandSource source, String s) throws CommandException { - return onTabComplete(makeSender(source), Arrays.asList(Patterns.SPACE_SPLIT.split(s))); + return onTabComplete(FACTORY.wrap(source), Arrays.asList(Patterns.SPACE.split(s))); } @Override - public boolean testPermission(CommandSource commandSource) { + public boolean testPermission(CommandSource source) { return true; } @Override - public Optional getShortDescription(CommandSource commandSource) { + public Optional getShortDescription(CommandSource source) { return Optional.of(Text.of("LuckPerms main command.")); } @Override - public Optional getHelp(CommandSource commandSource) { + public Optional getHelp(CommandSource source) { return Optional.of(Text.of("Type /perms for help.")); } @Override - public Text getUsage(CommandSource commandSource) { + public Text getUsage(CommandSource source) { return Text.of("/perms"); } - private static Sender makeSender(CommandSource source) { - return new Sender() { - final WeakReference cs = new WeakReference<>(source); + private static class Factory extends SenderFactory { - @SuppressWarnings("deprecation") - @Override - public void sendMessage(String s) { - final CommandSource c = cs.get(); - if (c != null) { - c.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(s)); - } - } + @SuppressWarnings("deprecation") + @Override + protected void sendMessage(CommandSource source, String s) { + source.sendMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(s)); + } - @Override - public boolean hasPermission(String node) { - final CommandSource c = cs.get(); - return c != null && c.hasPermission(node); - } - }; + @Override + protected boolean hasPermission(CommandSource source, String node) { + return source.hasPermission(node); + } } } diff --git a/sponge/src/main/java/me/lucko/luckperms/SpongeConfig.java b/sponge/src/main/java/me/lucko/luckperms/SpongeConfig.java index 4d08a96c..af7792e2 100644 --- a/sponge/src/main/java/me/lucko/luckperms/SpongeConfig.java +++ b/sponge/src/main/java/me/lucko/luckperms/SpongeConfig.java @@ -1,6 +1,7 @@ package me.lucko.luckperms; import me.lucko.luckperms.utils.LPConfiguration; +import me.lucko.luckperms.utils.Patterns; import ninja.leaping.configurate.ConfigurationNode; import ninja.leaping.configurate.commented.CommentedConfigurationNode; import ninja.leaping.configurate.hocon.HoconConfigurationLoader; @@ -47,7 +48,7 @@ class SpongeConfig extends LPConfiguration { } private ConfigurationNode getNode(String path) { - String[] paths = path.split("\\."); + String[] paths = Patterns.DOT.split(path); ConfigurationNode node = root; for (String s : paths) { diff --git a/sponge/src/main/java/me/lucko/luckperms/SpongeListener.java b/sponge/src/main/java/me/lucko/luckperms/SpongeListener.java new file mode 100644 index 00000000..492baa39 --- /dev/null +++ b/sponge/src/main/java/me/lucko/luckperms/SpongeListener.java @@ -0,0 +1,69 @@ +package me.lucko.luckperms; + +import me.lucko.luckperms.constants.Message; +import me.lucko.luckperms.users.User; +import me.lucko.luckperms.utils.AbstractListener; +import org.spongepowered.api.entity.Entity; +import org.spongepowered.api.entity.living.player.Player; +import org.spongepowered.api.event.Listener; +import org.spongepowered.api.event.entity.DisplaceEntityEvent; +import org.spongepowered.api.event.network.ClientConnectionEvent; +import org.spongepowered.api.profile.GameProfile; +import org.spongepowered.api.text.serializer.TextSerializers; + +class SpongeListener extends AbstractListener { + private final LPSpongePlugin plugin; + + SpongeListener(LPSpongePlugin plugin) { + super(plugin); + this.plugin = plugin; + } + + @Listener + public void onClientAuth(ClientConnectionEvent.Auth e) { + if (!plugin.getDatastore().isAcceptingLogins()) { + // Datastore is disabled, prevent players from joining the server + // Just don't load their data, they will be kicked at login + return; + } + + final GameProfile p = e.getProfile(); + onAsyncLogin(p.getUniqueId(), p.getName().get()); + } + + @SuppressWarnings("deprecation") + @Listener + public void onClientLogin(ClientConnectionEvent.Login e) { + final GameProfile player = e.getProfile(); + final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(player.getUniqueId())); + + if (user == null) { + e.setCancelled(true); + e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(Message.LOADING_ERROR.toString())); + return; + } + + user.refreshPermissions(); + } + + @Listener + public void onClientJoin(ClientConnectionEvent.Join e) { + // Refresh permissions again + refreshPlayer(e.getTargetEntity().getUniqueId()); + } + + @Listener + public void onPlayerTeleport(DisplaceEntityEvent.Teleport e) { + final Entity entity = e.getTargetEntity(); + if (!(entity instanceof Player)){ + return; + } + + refreshPlayer(entity.getUniqueId()); + } + + @Listener + public void onClientLeave(ClientConnectionEvent.Disconnect e) { + onLeave(e.getTargetEntity().getUniqueId()); + } +} diff --git a/sponge/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java b/sponge/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java deleted file mode 100644 index 84e6aa9f..00000000 --- a/sponge/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java +++ /dev/null @@ -1,107 +0,0 @@ -package me.lucko.luckperms.listeners; - -import lombok.AllArgsConstructor; -import me.lucko.luckperms.LPSpongePlugin; -import me.lucko.luckperms.commands.Util; -import me.lucko.luckperms.constants.Message; -import me.lucko.luckperms.users.User; -import me.lucko.luckperms.utils.UuidCache; -import org.spongepowered.api.entity.Entity; -import org.spongepowered.api.entity.living.player.Player; -import org.spongepowered.api.event.Listener; -import org.spongepowered.api.event.entity.DisplaceEntityEvent; -import org.spongepowered.api.event.network.ClientConnectionEvent; -import org.spongepowered.api.profile.GameProfile; -import org.spongepowered.api.text.serializer.TextSerializers; - -import java.util.UUID; - -@AllArgsConstructor -public class PlayerListener { - private static final String KICK_MESSAGE = Util.color(Message.PREFIX + "User data could not be loaded. Please contact an administrator."); - private final LPSpongePlugin plugin; - - @Listener - public void onClientAuth(ClientConnectionEvent.Auth e) { - final long startTime = System.currentTimeMillis(); - if (!plugin.getDatastore().isAcceptingLogins()) { - // Datastore is disabled, prevent players from joining the server - // Just don't load their data, they will be kickec at login - return; - } - - final UuidCache cache = plugin.getUuidCache(); - final GameProfile p = e.getProfile(); - final String name = p.getName().get(); - - if (!cache.isOnlineMode()) { - UUID uuid = plugin.getDatastore().getUUID(name); - if (uuid != null) { - cache.addToCache(p.getUniqueId(), uuid); - } else { - // No previous data for this player - cache.addToCache(p.getUniqueId(), p.getUniqueId()); - plugin.getDatastore().saveUUIDData(name, p.getUniqueId(), b -> {}); - } - } else { - // Online mode, no cache needed. This is just for name -> uuid lookup. - plugin.getDatastore().saveUUIDData(name, p.getUniqueId(), b -> {}); - } - - plugin.getDatastore().loadOrCreateUser(cache.getUUID(p.getUniqueId()), name); - final long time = System.currentTimeMillis() - startTime; - if (time >= 1000) { - plugin.getLog().warn("Processing login for " + p.getName() + " took " + time + "ms."); - } - } - - @SuppressWarnings("deprecation") - @Listener - public void onClientLogin(ClientConnectionEvent.Login e) { - final GameProfile player = e.getProfile(); - final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(player.getUniqueId())); - - if (user == null) { - e.setCancelled(true); - e.setMessage(TextSerializers.LEGACY_FORMATTING_CODE.deserialize(KICK_MESSAGE)); - return; - } - - user.refreshPermissions(); - } - - @Listener - public void onClientJoin(ClientConnectionEvent.Join e) { - // Refresh permissions again - refreshPlayer(e.getTargetEntity()); - } - - @Listener - public void onPlayerTeleport(DisplaceEntityEvent.Teleport e) { - final Entity entity = e.getTargetEntity(); - if (!(entity instanceof Player)){ - return; - } - - refreshPlayer((Player) entity); - } - - @Listener - public void onClientLeave(ClientConnectionEvent.Disconnect e) { - final Player player = e.getTargetEntity(); - final UuidCache cache = plugin.getUuidCache(); - - // Unload the user from memory when they disconnect; - cache.clearCache(player.getUniqueId()); - - final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId())); - plugin.getUserManager().unloadUser(user); - } - - private void refreshPlayer(Player p) { - final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(p.getUniqueId())); - if (user != null) { - user.refreshPermissions(); - } - } -}