diff --git a/README.md b/README.md index 23898942..faa51676 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # LuckPerms -A (fairly bad) permissions implementation for Bukkit/BungeeCord. +A permissions implementation for Bukkit/BungeeCord. ## Features * **Group inheritance** - users can be members of multiple groups, groups can inherit other groups @@ -8,19 +8,20 @@ A (fairly bad) permissions implementation for Bukkit/BungeeCord. * **Multi-server support** - data is synced across all servers/platforms * **Full offline-mode/mixed-mode support** - player permissions are synced properly over offline-mode or mixed online/offline-mode networks. * **Per-server permissions/groups** - define user/group permissions that only apply on certain servers -* **Server-specific groups** - define groups that only apply on certain servers -* **Tracks / paths** - users can be promoted/demoted along multiple group tracks +* **Per-world permissions/groups** - define user/group permissions that only apply on certain worlds (on BungeeCord, a connected Bukkit/Spigot instance is treated as a world) +* **Tracks / paths / ladders** - users can be promoted/demoted along multiple group tracks * **Vault Support** - hooks into Vault to integrate with other plugins * **Developer API** - easily integrate LuckPerms into your own projects * **Easy and simple setup and configuration using commands** - no editing yml files, yuck +* **Negated permissions and groups** - define special rules for certain users/groups +* **Full support for UUIDs, even in Offline Mode** - users can change their usernames without losing permissions. In offline mode, a single user has the same internal UUID across a network. +* **Permission data stored within MySQL in a json format** - easily integrate the LuckPerms backend into your other projects +* **Well documented** - API methods have comprehensive Java docs, it's clear what each method does. * **Efficient/lightweight** - maybe? Who knows, it might be. +* **Open Sourced, Free...** - you shouldn't have to pay $10+ for a "powerful" permissions plugin. * **BungeeCord compatible** - permissions, users and groups are synced across Bukkit/BungeeCord instances * **Support for MySQL, SQLite & Flatfile (JSON)** - other storage methods coming soon (maybe) -##### Possible Caveats -* Currently only supports MySQL, SQLite & Flatfile (JSON) (support for more methods might come in the future) -* Not at all tested and could produce unexpected/buggy results and errors - ## Setup All configuration options are in the **config.yml** file, which is generated automagically when the plugin first starts. @@ -34,13 +35,17 @@ Permissions are calculated based on a priority system as follows. Example: if a user has a false permission set for "test.node", and a temporary true permission set for "test.node", the temporary permission will override the permanent one, and the user will be granted the true node. +* World specific permissions will override generic permissions. + +Example: if a user has a global "fly.use" permission, and then has a negated "fly.use" permission in the "world_nether" world, the world specific permission will override the globally defined one, and the user will be granted the negated node (provided they're in that world, of course.). + * Server specific permissions will override generic/global permissions. Example: if a user has a global "fly.use" permission, and then has a negated "fly.use" permission on the "factions" server, the server specific permission will override the globally defined one, and the user will be granted the negated node. * Inherited permissions will be overridden by an objects own permissions. -Example: A user is a member of the default group, which grants "some.thing.perm", but the users own permissions has "some.thing.perm" set to false. The inherited permission will be overridden by the users own permissions, and the user will be granted the negative node. +Example: A user is a member of the default group, which grants "some.thing.perm", but the users own permissions has "some.thing.perm" set to false. The inherited permission will be overridden by the users own permissions, and the user will be granted the negative node (provided they're on that server). ### Temporary Permissions Temporary permissions are checked each time a user/group is loaded, and when the sync task runs. This means if you set a temporary permission to expire after 30 seconds, it won't actually be removed until the sync task runs. @@ -101,15 +106,16 @@ Additionally, you can use wildcards to grant users access to a selection of comm * /perms user \ info - luckperms.user.info * /perms user \ getuuid - luckperms.user.getuuid * /perms user \ listnodes - luckperms.user.listnodes -* /perms user \ haspermission \ [server] - luckperms.user.haspermission -* /perms user \ inheritspermission \ [server] - luckperms.user.inheritspermission -* /perms user \ set \ \ [server] - luckperms.user.setpermission -* /perms user \ unset \ [server] - luckperms.user.unsetpermission -* /perms user \ addgroup \ [server] - luckperms.user.addgroup -* /perms user \ removegroup \ [server] - luckperms.user.removegroup -* /perms user \ settemp \ \ \ [server] - luckperms.user.settemppermission -* /perms user \ addtempgroup \ \ [server] - luckperms.user.addtempgroup -* /perms user \ removetempgroup \ [server] - luckperms.user.removetempgroup +* /perms user \ haspermission \ [server] [world] - luckperms.user.haspermission +* /perms user \ inheritspermission \ [server] [world] - luckperms.user.inheritspermission +* /perms user \ set \ \ [server] [world] - luckperms.user.setpermission +* /perms user \ unset \ [server] [world] - luckperms.user.unsetpermission +* /perms user \ addgroup \ [server] [world] - luckperms.user.addgroup +* /perms user \ removegroup \ [server] [world] - luckperms.user.removegroup +* /perms user \ settemp \ \ \ [server] [world] - luckperms.user.settemppermission +* /perms user \ unsettemp \ [server] [world] - luckperms.user.unsettemppermission +* /perms user \ addtempgroup \ \ [server] [world] - luckperms.user.addtempgroup +* /perms user \ removetempgroup \ [server] [world] - luckperms.user.removetempgroup * /perms user \ setprimarygroup \ - luckperms.user.setprimarygroup * /perms user \ showtracks - luckperms.user.showtracks * /perms user \ promote \ - luckperms.user.promote @@ -120,16 +126,16 @@ Additionally, you can use wildcards to grant users access to a selection of comm ### Group * /perms group \ info - luckperms.group.info * /perms group \ listnodes - luckperms.group.listnodes -* /perms group \ haspermission \ [server] - luckperms.group.haspermission -* /perms group \ inheritspermission \ [server] - luckperms.group.inheritspermission -* /perms group \ set \ \ [server] - luckperms.group.setpermission -* /perms group \ unset \ [server] - luckperms.group.unsetpermission -* /perms group \ setinherit \ [server] - luckperms.group.setinherit -* /perms group \ unsetinherit \ [server] - luckperms.group.unsetinherit -* /perms group \ settemp \ \ \ [server] - settemppermission -* /perms group \ unsettemp \ [server] - luckperms.group.unsettemppermission -* /perms group \ settempinherit \ \ [server] - luckperms.group.settempinherit -* /perms group \ unsettempinherit \ [server] - luckperms.group.unsettempinherit +* /perms group \ haspermission \ [server] [world] - luckperms.group.haspermission +* /perms group \ inheritspermission \ [server] [world] - luckperms.group.inheritspermission +* /perms group \ set \ \ [server] [world] - luckperms.group.setpermission +* /perms group \ unset \ [server] [world] - luckperms.group.unsetpermission +* /perms group \ setinherit \ [server] [world] - luckperms.group.setinherit +* /perms group \ unsetinherit \ [server] [world] - luckperms.group.unsetinherit +* /perms group \ settemp \ \ \ [server] [world] - settemppermission +* /perms group \ unsettemp \ [server] [world] - luckperms.group.unsettemppermission +* /perms group \ settempinherit \ \ [server] [world] - luckperms.group.settempinherit +* /perms group \ unsettempinherit \ [server] [world] - luckperms.group.unsettempinherit * /perms group \ showtracks - luckperms.group.showtracks * /perms group \ clear - luckperms.group.clear diff --git a/api/src/main/java/me/lucko/luckperms/api/PermissionObject.java b/api/src/main/java/me/lucko/luckperms/api/PermissionObject.java index ac982565..f743348d 100644 --- a/api/src/main/java/me/lucko/luckperms/api/PermissionObject.java +++ b/api/src/main/java/me/lucko/luckperms/api/PermissionObject.java @@ -35,6 +35,16 @@ public interface PermissionObject { */ boolean hasPermission(String node, boolean b, String server); + /** + * Checks to see the the object has a permission on a certain server + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server + * @param world The world + * @return true if the user has the permission + */ + boolean hasPermission(String node, boolean b, String server, String world); + /** * Checks to see the the object has a permission on a certain server * @param node The permission node @@ -44,6 +54,27 @@ public interface PermissionObject { */ boolean hasPermission(String node, boolean b, boolean temporary); + /** + * Checks to see the the object has a permission on a certain server + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server to check on + * @param temporary if the permission is temporary + * @return true if the user has the permission + */ + boolean hasPermission(String node, boolean b, String server, boolean temporary); + + /** + * Checks to see the the object has a permission on a certain server + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server to check on + * @param world The world to check on + * @param temporary if the permission is temporary + * @return true if the user has the permission + */ + boolean hasPermission(String node, boolean b, String server, String world, boolean temporary); + /** * Checks to see if the object inherits a certain permission * @param node The permission node @@ -61,6 +92,16 @@ public interface PermissionObject { */ boolean inheritsPermission(String node, boolean b, String server); + /** + * Checks to see the the object inherits a permission on a certain server + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server + * @param world The world + * @return true if the user inherits the permission + */ + boolean inheritsPermission(String node, boolean b, String server, String world); + /** * Checks to see if the object inherits a certain permission * @param node The permission node @@ -70,6 +111,27 @@ public interface PermissionObject { */ boolean inheritsPermission(String node, boolean b, boolean temporary); + /** + * Checks to see if the object inherits a certain permission + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server + * @param temporary if the permission is temporary + * @return true if the user inherits the permission + */ + boolean inheritsPermission(String node, boolean b, String server, boolean temporary); + + /** + * Checks to see if the object inherits a certain permission + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server + * @param world The world + * @param temporary if the permission is temporary + * @return true if the user inherits the permission + */ + boolean inheritsPermission(String node, boolean b, String server, String world, boolean temporary); + /** * Sets a permission for the object * @param node The node to be set @@ -87,6 +149,16 @@ public interface PermissionObject { */ void setPermission(String node, boolean value, String server) throws ObjectAlreadyHasException; + /** + * Sets a permission for the object + * @param node The node to set + * @param value What to set the node to - true/false(negated) + * @param server The server to set the permission on + * @param world The world to set the permission on + * @throws ObjectAlreadyHasException if the object already has the permission + */ + void setPermission(String node, boolean value, String server, String world) throws ObjectAlreadyHasException; + /** * Sets a permission for the object * @param node The node to set @@ -106,6 +178,17 @@ public interface PermissionObject { */ void setPermission(String node, boolean value, String server, long expireAt) throws ObjectAlreadyHasException; + /** + * Sets a permission for the object + * @param node The node to set + * @param value What to set the node to - true/false(negated) + * @param server The server to set the permission on + * @param world The world to set the permission on + * @param expireAt The time in unixtime when the permission will expire + * @throws ObjectAlreadyHasException if the object already has the permission + */ + void setPermission(String node, boolean value, String server, String world, long expireAt) throws ObjectAlreadyHasException; + /** * Unsets a permission for the object * @param node The node to be unset @@ -129,6 +212,15 @@ public interface PermissionObject { */ void unsetPermission(String node, String server) throws ObjectLacksException; + /** + * Unsets a permission for the object + * @param node The node to be unset + * @param server The server to unset the node on + * @param world The world to unset the node on + * @throws ObjectLacksException if the node wasn't already set + */ + void unsetPermission(String node, String server, String world) throws ObjectLacksException; + /** * Unsets a permission for the object * @param node The node to be unset @@ -138,6 +230,25 @@ public interface PermissionObject { */ void unsetPermission(String node, String server, boolean temporary) throws ObjectLacksException; + /** + * Unsets a permission for the object + * @param node The node to be unset + * @param server The server to unset the node on + * @param world The world to unset the node on + * @param temporary if the permission being unset is temporary + * @throws ObjectLacksException if the node wasn't already set + */ + void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException; + + /** + * Gets the permissions and inherited permissions that apply to a specific server + * @param server The server to get nodes for + * @param world The world to get nodes for + * @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues) + * @return a {@link Map} of the permissions + */ + Map getLocalPermissions(String server, String world, List excludedGroups); + /** * Gets the permissions and inherited permissions that apply to a specific server * @param server The server to get nodes for (can be null) 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 f09a9886..0c938496 100644 --- a/api/src/main/java/me/lucko/luckperms/api/User.java +++ b/api/src/main/java/me/lucko/luckperms/api/User.java @@ -14,10 +14,32 @@ import java.util.UUID; @SuppressWarnings("unused") public interface User extends PermissionObject { + /** + * @return the users Mojang assigned unique id + */ UUID getUuid(); + + /** + * @return the Users Username + */ String getName(); + + /** + * Gets the users primary group + * @return the users primary group + */ String getPrimaryGroup(); + + /** + * Sets a users primary group + * @param s the new primary group + * @throws ObjectAlreadyHasException if the user already has this set as their primary group + */ void setPrimaryGroup(String s) throws ObjectAlreadyHasException; + + /** + * Refresh and re-assign the users permissions + */ void refreshPermissions(); /** @@ -35,6 +57,15 @@ public interface User extends PermissionObject { */ boolean isInGroup(Group group, String server); + /** + * Check to see if a user is a member of a group on a specific server + * @param group The group to check membership of + * @param server The server to check on + * @param world The world to check on + * @return true if the user is a member of the group + */ + boolean isInGroup(Group group, String server, String world); + /** * Add a user to a group * @param group The group to add the user to @@ -50,6 +81,15 @@ public interface User extends PermissionObject { */ void addGroup(Group group, String server) throws ObjectAlreadyHasException; + /** + * Add a user to a group on a specific server + * @param group The group to add the user to + * @param server The server to add the group on + * @param world The world to add the group on + * @throws ObjectAlreadyHasException if the user is already a member of the group on that server + */ + void addGroup(Group group, String server, String world) throws ObjectAlreadyHasException; + /** * Add a user to a group on a specific server * @param group The group to add the user to @@ -67,6 +107,16 @@ public interface User extends PermissionObject { */ void addGroup(Group group, String server, long expireAt) throws ObjectAlreadyHasException; + /** + * Add a user to a group on a specific server + * @param group The group to add the user to + * @param server The server to add the group on + * @param world The world to add the group on + * @param expireAt when the group should expire + * @throws ObjectAlreadyHasException if the user is already a member of the group on that server + */ + void addGroup(Group group, String server, String world, long expireAt) throws ObjectAlreadyHasException; + /** * Remove the user from a group * @param group the group to remove the user from @@ -90,6 +140,15 @@ public interface User extends PermissionObject { */ void removeGroup(Group group, String server) throws ObjectLacksException; + /** + * Remove the user from a group + * @param group The group to remove the user from + * @param server The server to remove the group on + * @param world The world to remove the group on + * @throws ObjectLacksException if the user isn't a member of the group + */ + void removeGroup(Group group, String server, String world) throws ObjectLacksException; + /** * Remove the user from a group * @param group The group to remove the user from @@ -99,6 +158,16 @@ public interface User extends PermissionObject { */ void removeGroup(Group group, String server, boolean temporary) throws ObjectLacksException; + /** + * Remove the user from a group + * @param group The group to remove the user from + * @param server The server to remove the group on + * @param world The world to remove the group on + * @param temporary if the group being removed is temporary + * @throws ObjectLacksException if the user isn't a member of the group + */ + void removeGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException; + /** * Clear all of the users permission nodes */ @@ -110,6 +179,13 @@ public interface User extends PermissionObject { */ List getGroupNames(); + /** + * Get a {@link List} of the groups the user is a member of on a specific server + * @param server the server to check + * @return a {@link List} of group names + */ + List getLocalGroups(String server, String world); + /** * Get a {@link List} of the groups the user is a member of on a specific server * @param server the server to check diff --git a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java index 2d1b5460..f09f27e6 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java +++ b/bukkit/src/main/java/me/lucko/luckperms/LPBukkitPlugin.java @@ -151,7 +151,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { @Override public String getPlayerStatus(UUID uuid) { - return getServer().getPlayer(uuid) != null ? "&aOnline" : "&cOffline"; + return getServer().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? "&aOnline" : "&cOffline"; } @Override diff --git a/bukkit/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java b/bukkit/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java index 9e8dafa8..a553c9bd 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java +++ b/bukkit/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java @@ -1,6 +1,6 @@ package me.lucko.luckperms.listeners; -import lombok.RequiredArgsConstructor; +import lombok.AllArgsConstructor; import me.lucko.luckperms.LPBukkitPlugin; import me.lucko.luckperms.commands.Util; import me.lucko.luckperms.constants.Message; @@ -10,38 +10,15 @@ 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.AsyncPlayerPreLoginEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerLoginEvent; -import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.*; import java.util.UUID; -@RequiredArgsConstructor +@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; - /* - cache: username --> uuid - returns mojang if not in offline mode - - - if server in offline mode: - go to datastore, look for uuid, add to cache. - - *** player prelogin, load or create, using CACHE uuid - - - - *** player login, we get their username and check if it's there - - *** player join, save uuid data and refresh - - *** player quit, unload - - */ - @EventHandler public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) { if (!plugin.getDatastore().isAcceptingLogins()) { @@ -54,22 +31,24 @@ public class PlayerListener implements Listener { if (!cache.isOnlineMode()) { UUID uuid = plugin.getDatastore().getUUID(e.getName()); if (uuid != null) { - cache.addToCache(e.getName(), uuid); + cache.addToCache(e.getUniqueId(), uuid); } else { - cache.addToCache(e.getName(), e.getUniqueId()); + // 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.getName(), e.getUniqueId()), e.getName()); + plugin.getDatastore().loadOrCreateUser(cache.getUUID(e.getUniqueId()), e.getName()); } @EventHandler public void onPlayerLogin(PlayerLoginEvent e) { final Player player = e.getPlayer(); - final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getName(), e.getPlayer().getUniqueId())); + final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId())); if (user == null) { e.disallow(PlayerLoginEvent.Result.KICK_OTHER, KICK_MESSAGE); @@ -87,10 +66,7 @@ public class PlayerListener implements Listener { @EventHandler public void onPlayerJoin(PlayerJoinEvent e) { // Refresh permissions again - final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getName(), e.getPlayer().getUniqueId())); - if (user != null) { - user.refreshPermissions(); - } + refreshPlayer(e.getPlayer()); } @EventHandler @@ -99,10 +75,22 @@ public class PlayerListener implements Listener { final UuidCache cache = plugin.getUuidCache(); // Unload the user from memory when they disconnect; - cache.clearCache(player.getName()); + cache.clearCache(player.getUniqueId()); - final User user = plugin.getUserManager().getUser(cache.getUUID(player.getName(), player.getUniqueId())); + final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId())); plugin.getUserManager().unloadUser(user); } + @EventHandler + public void onPlayerChangedWorld(PlayerChangedWorldEvent e) { + refreshPlayer(e.getPlayer()); + } + + private void refreshPlayer(Player p) { + final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(p.getUniqueId())); + if (user != null) { + user.refreshPermissions(); + } + } + } diff --git a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java index 2b98ff58..f56078eb 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java +++ b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUser.java @@ -30,7 +30,7 @@ public class BukkitUser extends User { @Override public void refreshPermissions() { plugin.doSync(() -> { - final Player player = plugin.getServer().getPlayer(getUuid()); + final Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid())); if (player == null) return; if (attachment == null) { @@ -42,7 +42,7 @@ public class BukkitUser extends User { attachment.getPermissions().keySet().forEach(p -> attachment.setPermission(p, false)); // Re-add all defined permissions for the user - Map local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null); + Map local = getLocalPermissions(getPlugin().getConfiguration().getServer(), player.getWorld().getName(), null); local.entrySet().forEach(e -> attachment.setPermission(e.getKey(), e.getValue())); }); } diff --git a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUserManager.java b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUserManager.java index 2bec0238..6fd78aee 100644 --- a/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUserManager.java +++ b/bukkit/src/main/java/me/lucko/luckperms/users/BukkitUserManager.java @@ -23,7 +23,7 @@ public class BukkitUserManager extends UserManager { BukkitUser u = (BukkitUser) user; if (u.getAttachment() != null) { - Player player = plugin.getServer().getPlayer(u.getUuid()); + Player player = plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(u.getUuid())); if (player != null) { player.removeAttachment(u.getAttachment()); @@ -38,7 +38,7 @@ public class BukkitUserManager extends UserManager { @Override public void cleanupUser(User user) { - if (plugin.getServer().getPlayer(user.getUuid()) == null) { + if (plugin.getServer().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) { unloadUser(user); } } @@ -58,7 +58,7 @@ public class BukkitUserManager extends UserManager { // Sometimes called async, so we need to get the players on the Bukkit thread. plugin.doSync(() -> { Set players = plugin.getServer().getOnlinePlayers().stream() - .map(p -> plugin.getUuidCache().getUUID(p.getName(), p.getUniqueId())) + .map(p -> plugin.getUuidCache().getUUID(p.getUniqueId())) .collect(Collectors.toSet()); plugin.doAsync(() -> players.forEach(u -> plugin.getDatastore().loadUser(u))); }); diff --git a/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java b/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java index c631c35b..05e3b158 100644 --- a/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java +++ b/bungee/src/main/java/me/lucko/luckperms/LPBungeePlugin.java @@ -111,7 +111,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin { @Override public String getPlayerStatus(UUID uuid) { - return getProxy().getPlayer(uuid) != null ? "&aOnline" : "&cOffline"; + return getProxy().getPlayer(getUuidCache().getExternalUUID(uuid)) != null ? "&aOnline" : "&cOffline"; } @Override diff --git a/bungee/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java b/bungee/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java index ec822d55..c47bc967 100644 --- a/bungee/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java +++ b/bungee/src/main/java/me/lucko/luckperms/listeners/PlayerListener.java @@ -12,6 +12,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.LoginEvent; import net.md_5.bungee.api.event.PlayerDisconnectEvent; import net.md_5.bungee.api.event.PostLoginEvent; +import net.md_5.bungee.api.event.ServerSwitchEvent; import net.md_5.bungee.api.plugin.Listener; import net.md_5.bungee.event.EventHandler; @@ -39,18 +40,20 @@ public class PlayerListener implements Listener { if (!cache.isOnlineMode()) { UUID uuid = plugin.getDatastore().getUUID(c.getName()); if (uuid != null) { - cache.addToCache(c.getName(), uuid); + cache.addToCache(c.getUniqueId(), uuid); } else { - cache.addToCache(c.getName(), c.getUniqueId()); + // No previous data for this player + cache.addToCache(c.getUniqueId(), c.getUniqueId()); plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId()); } } else { + // Online mode, no cache needed. This is just for name -> uuid lookup. plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId()); } // We have to make a new user on this thread whilst the connection is being held, or we get concurrency issues as the Bukkit server // and the BungeeCord server try to make a new user at the same time. - plugin.getDatastore().loadOrCreateUser(cache.getUUID(c.getName(), c.getUniqueId()), c.getName()); + plugin.getDatastore().loadOrCreateUser(cache.getUUID(c.getUniqueId()), c.getName()); e.completeIntent(plugin); }); } @@ -60,7 +63,7 @@ public class PlayerListener implements Listener { final ProxiedPlayer player = e.getPlayer(); final WeakReference p = new WeakReference<>(player); - final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getName(), e.getPlayer().getUniqueId())); + final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId())); if (user == null) { plugin.getProxy().getScheduler().schedule(plugin, () -> { final ProxiedPlayer pl = p.get(); @@ -79,9 +82,17 @@ public class PlayerListener implements Listener { final UuidCache cache = plugin.getUuidCache(); // Unload the user from memory when they disconnect; - cache.clearCache(player.getName()); + cache.clearCache(player.getUniqueId()); - final User user = plugin.getUserManager().getUser(cache.getUUID(player.getName(), player.getUniqueId())); + final User user = plugin.getUserManager().getUser(cache.getUUID(player.getUniqueId())); plugin.getUserManager().unloadUser(user); } + + @EventHandler + public void onPlayerServerSwitch(ServerSwitchEvent e) { + final User user = plugin.getUserManager().getUser(plugin.getUuidCache().getUUID(e.getPlayer().getUniqueId())); + if (user != null) { + user.refreshPermissions(); + } + } } diff --git a/bungee/src/main/java/me/lucko/luckperms/users/BungeeUser.java b/bungee/src/main/java/me/lucko/luckperms/users/BungeeUser.java index 1815b272..e9f1cb2e 100644 --- a/bungee/src/main/java/me/lucko/luckperms/users/BungeeUser.java +++ b/bungee/src/main/java/me/lucko/luckperms/users/BungeeUser.java @@ -24,7 +24,7 @@ public class BungeeUser extends User { @Override public void refreshPermissions() { - ProxiedPlayer player = plugin.getProxy().getPlayer(getUuid()); + ProxiedPlayer player = plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(getUuid())); if (player == null) return; // Clear existing permissions @@ -32,7 +32,8 @@ public class BungeeUser extends User { perms.forEach(p -> player.setPermission(p, false)); // Re-add all defined permissions for the user - Map local = getLocalPermissions(getPlugin().getConfiguration().getServer(), null); + final String server = player.getServer() == null ? null : (player.getServer().getInfo() == null ? null : player.getServer().getInfo().getName()); + Map local = getLocalPermissions(getPlugin().getConfiguration().getServer(), server, null); local.entrySet().forEach(e -> player.setPermission(e.getKey(), e.getValue())); } } diff --git a/bungee/src/main/java/me/lucko/luckperms/users/BungeeUserManager.java b/bungee/src/main/java/me/lucko/luckperms/users/BungeeUserManager.java index 517293d5..61134ea2 100644 --- a/bungee/src/main/java/me/lucko/luckperms/users/BungeeUserManager.java +++ b/bungee/src/main/java/me/lucko/luckperms/users/BungeeUserManager.java @@ -23,7 +23,7 @@ public class BungeeUserManager extends UserManager { @Override public void cleanupUser(User user) { - if (plugin.getProxy().getPlayer(user.getUuid()) == null) { + if (plugin.getProxy().getPlayer(plugin.getUuidCache().getExternalUUID(user.getUuid())) == null) { unloadUser(user); } } @@ -41,7 +41,7 @@ public class BungeeUserManager extends UserManager { @Override public void updateAllUsers() { plugin.getProxy().getPlayers().stream() - .map(p -> plugin.getUuidCache().getUUID(p.getName(), p.getUniqueId())) + .map(p -> plugin.getUuidCache().getUUID(p.getUniqueId())) .forEach(u -> plugin.getDatastore().loadUser(u)); } } 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/PermissionObjectLink.java index a28f448d..0e065e6e 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/PermissionObjectLink.java @@ -64,11 +64,26 @@ class PermissionObjectLink implements PermissionObject { return master.hasPermission(node, b, checkServer(server)); } + @Override + public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world) { + return master.hasPermission(node, b, checkServer(server), world); + } + @Override public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull boolean temporary) { return master.hasPermission(node, b, temporary); } + @Override + public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull boolean temporary) { + return master.hasPermission(node, b, checkServer(server), temporary); + } + + @Override + public boolean hasPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world, @NonNull boolean temporary) { + return master.hasPermission(node, b, checkServer(server), world, temporary); + } + @Override public boolean inheritsPermission(@NonNull String node, @NonNull boolean b) { return master.inheritsPermission(node, b); @@ -79,11 +94,26 @@ class PermissionObjectLink implements PermissionObject { return master.inheritsPermission(node, b, checkServer(server)); } + @Override + public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world) { + return master.inheritsPermission(node, b, checkServer(server), world); + } + @Override public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull boolean temporary) { return master.inheritsPermission(node, b, temporary); } + @Override + public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull boolean temporary) { + return master.inheritsPermission(node, b, checkServer(server), temporary); + } + + @Override + public boolean inheritsPermission(@NonNull String node, @NonNull boolean b, @NonNull String server, @NonNull String world, @NonNull boolean temporary) { + return master.inheritsPermission(node, b, checkServer(server), world, temporary); + } + @Override public void setPermission(@NonNull String node, @NonNull boolean value) throws ObjectAlreadyHasException { master.setPermission(checkNode(node), value); @@ -94,6 +124,11 @@ class PermissionObjectLink implements PermissionObject { master.setPermission(checkNode(node), value, checkServer(server)); } + @Override + public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server, @NonNull String world) throws ObjectAlreadyHasException { + master.setPermission(checkNode(node), value, checkServer(server), world); + } + @Override public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull long expireAt) throws ObjectAlreadyHasException { master.setPermission(checkNode(node), value, checkTime(expireAt)); @@ -104,6 +139,11 @@ class PermissionObjectLink implements PermissionObject { master.setPermission(checkNode(node), value, checkServer(server), checkTime(expireAt)); } + @Override + public void setPermission(@NonNull String node, @NonNull boolean value, @NonNull String server, @NonNull String world, @NonNull long expireAt) throws ObjectAlreadyHasException { + master.setPermission(checkNode(node), value, checkServer(server), world, checkTime(expireAt)); + } + @Override public void unsetPermission(@NonNull String node, @NonNull boolean temporary) throws ObjectLacksException { master.unsetPermission(checkNode(node), temporary); @@ -119,11 +159,26 @@ class PermissionObjectLink implements PermissionObject { master.unsetPermission(checkNode(node), checkServer(server)); } + @Override + public void unsetPermission(@NonNull String node, @NonNull String server, @NonNull String world) throws ObjectLacksException { + master.unsetPermission(checkNode(node), checkServer(server), world); + } + @Override public void unsetPermission(@NonNull String node, @NonNull String server, @NonNull boolean temporary) throws ObjectLacksException { master.unsetPermission(checkNode(node), checkServer(server), temporary); } + @Override + public void unsetPermission(@NonNull String node, @NonNull String server, @NonNull String world, @NonNull boolean temporary) throws ObjectLacksException { + master.unsetPermission(checkNode(node), checkServer(server), world, temporary); + } + + @Override + public Map getLocalPermissions(String server, String world, List excludedGroups) { + return master.getLocalPermissions(server, world, excludedGroups); + } + @Override public Map getLocalPermissions(String server, List excludedGroups) { return master.getLocalPermissions(server, excludedGroups); 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 12256b4d..5c5956fc 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 @@ -70,6 +70,12 @@ public class UserLink extends PermissionObjectLink implements User { return master.isInGroup(((GroupLink) group).getMaster(), server); } + @Override + public boolean isInGroup(@NonNull Group group, @NonNull String server, @NonNull String world) { + Utils.checkGroup(group); + return master.isInGroup(((GroupLink) group).getMaster(), server, world); + } + @Override public void addGroup(@NonNull Group group) throws ObjectAlreadyHasException { Utils.checkGroup(group); @@ -82,6 +88,12 @@ public class UserLink extends PermissionObjectLink implements User { master.addGroup(((GroupLink) group).getMaster(), checkServer(server)); } + @Override + public void addGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectAlreadyHasException { + Utils.checkGroup(group); + master.addGroup(((GroupLink) group).getMaster(), checkServer(server), world); + } + @Override public void addGroup(@NonNull Group group, @NonNull long expireAt) throws ObjectAlreadyHasException { Utils.checkGroup(group); @@ -94,6 +106,12 @@ public class UserLink extends PermissionObjectLink implements User { master.addGroup(((GroupLink) group).getMaster(), checkServer(server), checkTime(expireAt)); } + @Override + public void addGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull long expireAt) throws ObjectAlreadyHasException { + Utils.checkGroup(group); + master.addGroup(((GroupLink) group).getMaster(), checkServer(server), world, checkTime(expireAt)); + } + @Override public void removeGroup(@NonNull Group group) throws ObjectLacksException { Utils.checkGroup(group); @@ -112,12 +130,24 @@ public class UserLink extends PermissionObjectLink implements User { master.removeGroup(((GroupLink) group).getMaster(), checkServer(server)); } + @Override + public void removeGroup(@NonNull Group group, @NonNull String server, @NonNull String world) throws ObjectLacksException { + Utils.checkGroup(group); + master.removeGroup(((GroupLink) group).getMaster(), checkServer(server), world); + } + @Override public void removeGroup(@NonNull Group group, @NonNull String server, @NonNull boolean temporary) throws ObjectLacksException { Utils.checkGroup(group); master.removeGroup(((GroupLink) group).getMaster(), checkServer(server), temporary); } + @Override + public void removeGroup(@NonNull Group group, @NonNull String server, @NonNull String world, @NonNull boolean temporary) throws ObjectLacksException { + Utils.checkGroup(group); + master.removeGroup(((GroupLink) group).getMaster(), checkServer(server), world, temporary); + } + @Override public void clearNodes() { master.clearNodes(); @@ -128,6 +158,11 @@ public class UserLink extends PermissionObjectLink implements User { return master.getGroupNames(); } + @Override + public List getLocalGroups(@NonNull String server, @NonNull String world) { + return master.getLocalGroups(checkServer(server), world); + } + @Override public List getLocalGroups(@NonNull String server) { return master.getLocalGroups(checkServer(server)); diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupHasPerm.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupHasPerm.java index 28f17c93..62fc5fac 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupHasPerm.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupHasPerm.java @@ -14,18 +14,23 @@ import java.util.List; public class GroupHasPerm extends GroupSubCommand { public GroupHasPerm() { super("haspermission", "Checks to see if a group has a certain permission node", - "/%s group haspermission [server]", Permission.GROUP_HASPERMISSION); + "/%s group haspermission [server] [world]", Permission.GROUP_HASPERMISSION); } @Override protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List args, String label) { - if (args.size() == 2) { + if (args.size() >= 2) { if (Patterns.NON_ALPHA_NUMERIC.matcher(args.get(1)).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1).toLowerCase())); + if (args.size() == 2) { + Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1))); + } else { + Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, args.get(1), args.get(2))); + } + } else { Util.sendBoolean(sender, args.get(0), group.hasPermission(args.get(0), true, "global")); } @@ -33,6 +38,6 @@ public class GroupHasPerm extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupInheritsPerm.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupInheritsPerm.java index 1025fc98..0cb993eb 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupInheritsPerm.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupInheritsPerm.java @@ -14,18 +14,23 @@ import java.util.List; public class GroupInheritsPerm extends GroupSubCommand { public GroupInheritsPerm() { super("inheritspermission", "Checks to see if a group inherits a certain permission node", - "/%s group inheritspermission [server]", Permission.GROUP_INHERITSPERMISSION); + "/%s group inheritspermission [server] [world]", Permission.GROUP_INHERITSPERMISSION); } @Override protected void execute(LuckPermsPlugin plugin, Sender sender, Group group, List args, String label) { - if (args.size() == 2) { + if (args.size() >= 2) { if (Patterns.NON_ALPHA_NUMERIC.matcher(args.get(1)).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1).toLowerCase())); + if (args.size() == 2) { + Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1))); + } else { + Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true, args.get(1), args.get(2))); + } + } else { Util.sendBoolean(sender, args.get(0), group.inheritsPermission(args.get(0), true)); } @@ -33,6 +38,6 @@ public class GroupInheritsPerm extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetInherit.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetInherit.java index 03eea93a..8009e49a 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetInherit.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetInherit.java @@ -14,7 +14,7 @@ import java.util.List; public class GroupSetInherit extends GroupSubCommand { public GroupSetInherit() { super("setinherit", "Sets another group for this group to inherit permissions from", - "/%s group setinherit [server]", Permission.GROUP_SETINHERIT); + "/%s group setinherit [server] [world]", Permission.GROUP_SETINHERIT); } @Override @@ -31,15 +31,22 @@ public class GroupSetInherit extends GroupSubCommand { Message.GROUP_LOAD_ERROR.send(sender); } else { try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - group.setPermission("group." + groupName, true, server); - Message.GROUP_SETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server); + if (args.size() == 2) { + group.setPermission("group." + groupName, true, server); + Message.GROUP_SETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server); + } else { + final String world = args.get(2).toLowerCase(); + group.setPermission("group." + groupName, true, server, world); + Message.GROUP_SETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world); + } + } else { group.setPermission("group." + groupName, true); Message.GROUP_SETINHERIT_SUCCESS.send(sender, group.getName(), groupName); @@ -60,6 +67,6 @@ public class GroupSetInherit extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetPermission.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetPermission.java index 6afbb0c9..0e091e8f 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetPermission.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetPermission.java @@ -13,7 +13,7 @@ import java.util.List; public class GroupSetPermission extends GroupSubCommand { public GroupSetPermission() { - super("set", "Sets a permission for a group", "/%s group set [server]", + super("set", "Sets a permission for a group", "/%s group set [server] [world]", Permission.GROUP_SETPERMISSION); } @@ -40,15 +40,22 @@ public class GroupSetPermission extends GroupSubCommand { boolean b = Boolean.parseBoolean(bool); try { - if (args.size() == 3) { + if (args.size() >= 3) { final String server = args.get(2).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - group.setPermission(node, b, server); - Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server); + if (args.size() == 3) { + group.setPermission(node, b, server); + Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server); + } else { + final String world = args.get(3).toLowerCase(); + group.setPermission(node, b, server, world); + Message.SETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getName(), server, world); + } + } else { group.setPermission(node, b); Message.SETPERMISSION_SUCCESS.send(sender, node, bool, group.getName()); @@ -67,6 +74,6 @@ public class GroupSetPermission extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 2 && argLength != 3; + return argLength != 2 && argLength != 3 && argLength != 4; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetTempInherit.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetTempInherit.java index e74ed936..1d4a5737 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetTempInherit.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetTempInherit.java @@ -15,7 +15,7 @@ import java.util.List; public class GroupSetTempInherit extends GroupSubCommand { public GroupSetTempInherit() { super("settempinherit", "Sets another group for this group to inherit permissions from temporarily", - "/%s group settempinherit [server]", Permission.GROUP_SET_TEMP_INHERIT); + "/%s group settempinherit [server] [world]", Permission.GROUP_SET_TEMP_INHERIT); } @Override @@ -45,16 +45,24 @@ public class GroupSetTempInherit extends GroupSubCommand { Message.GROUP_LOAD_ERROR.send(sender); } else { try { - if (args.size() == 3) { + if (args.size() >= 3) { final String server = args.get(2).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - group.setPermission("group." + groupName, true, server, duration); - Message.GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server, - DateUtil.formatDateDiff(duration)); + if (args.size() == 3) { + group.setPermission("group." + groupName, true, server, duration); + Message.GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server, + DateUtil.formatDateDiff(duration)); + } else { + final String world = args.get(3).toLowerCase(); + group.setPermission("group." + groupName, true, server, world, duration); + Message.GROUP_SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, + world, DateUtil.formatDateDiff(duration)); + } + } else { group.setPermission("group." + groupName, true, duration); Message.GROUP_SET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), groupName, DateUtil.formatDateDiff(duration)); @@ -75,6 +83,6 @@ public class GroupSetTempInherit extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 2 && argLength != 3; + return argLength != 2 && argLength != 3 && argLength != 4; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetTempPermission.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetTempPermission.java index aae1eed2..469a54ab 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetTempPermission.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupSetTempPermission.java @@ -14,8 +14,8 @@ import java.util.List; public class GroupSetTempPermission extends GroupSubCommand { public GroupSetTempPermission() { - super("settemp", "Sets a temporary permission for a group", "/%s group settemp [server]", - Permission.GROUP_SET_TEMP_PERMISSION); + super("settemp", "Sets a temporary permission for a group", + "/%s group settemp [server] [world]", Permission.GROUP_SET_TEMP_PERMISSION); } @Override @@ -54,15 +54,24 @@ public class GroupSetTempPermission extends GroupSubCommand { } try { - if (args.size() == 4) { + if (args.size() >= 4) { final String server = args.get(3).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - group.setPermission(node, b, server, duration); - Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server, DateUtil.formatDateDiff(duration)); + if (args.size() == 4) { + group.setPermission(node, b, server, duration); + Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, group.getName(), server, + DateUtil.formatDateDiff(duration)); + } else { + final String world = args.get(4).toLowerCase(); + group.setPermission(node, b, server, world, duration); + Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, bool, group.getName(), server, + world, DateUtil.formatDateDiff(duration)); + } + } else { group.setPermission(node, b, duration); Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, bool, group.getName(), DateUtil.formatDateDiff(duration)); @@ -81,6 +90,6 @@ public class GroupSetTempPermission extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 3 && argLength != 4; + return argLength != 3 && argLength != 4 && argLength != 5; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnSetPermission.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnSetPermission.java index f9a085d2..3c3f5ea7 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnSetPermission.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnSetPermission.java @@ -14,7 +14,7 @@ import java.util.List; public class GroupUnSetPermission extends GroupSubCommand { public GroupUnSetPermission() { super("unset", "Unsets a permission for a group", - "/%s group unset [server]", Permission.GROUP_UNSETPERMISSION); + "/%s group unset [server] [world]", Permission.GROUP_UNSETPERMISSION); } @Override @@ -32,15 +32,22 @@ public class GroupUnSetPermission extends GroupSubCommand { } try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - group.unsetPermission(node, server); - Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server); + if (args.size() == 2) { + group.unsetPermission(node, server); + Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server); + } else { + final String world = args.get(2).toLowerCase(); + group.unsetPermission(node, server, world); + Message.UNSETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getName(), server, world); + } + } else { group.unsetPermission(node); Message.UNSETPERMISSION_SUCCESS.send(sender, node, group.getName()); @@ -54,6 +61,6 @@ public class GroupUnSetPermission extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetInherit.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetInherit.java index cfae1b03..dfb3f86b 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetInherit.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetInherit.java @@ -14,7 +14,7 @@ import java.util.List; public class GroupUnsetInherit extends GroupSubCommand { public GroupUnsetInherit() { super("unsetinherit", "Unsets another group for this group to inherit permissions from", - "/%s group unsetinherit [server]", Permission.GROUP_UNSETINHERIT); + "/%s group unsetinherit [server] [world]", Permission.GROUP_UNSETINHERIT); } @Override @@ -27,15 +27,22 @@ public class GroupUnsetInherit extends GroupSubCommand { } try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - group.unsetPermission("group." + groupName, server); - Message.GROUP_UNSETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server); + if (args.size() == 2) { + group.unsetPermission("group." + groupName, server); + Message.GROUP_UNSETINHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server); + } else { + final String world = args.get(2).toLowerCase(); + group.unsetPermission("group." + groupName, server, world); + Message.GROUP_UNSETINHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world); + } + } else { group.unsetPermission("group." + groupName); Message.GROUP_UNSETINHERIT_SUCCESS.send(sender, group.getName(), groupName); @@ -54,6 +61,6 @@ public class GroupUnsetInherit extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetTempInherit.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetTempInherit.java index 6a3b809b..fef16051 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetTempInherit.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetTempInherit.java @@ -14,7 +14,7 @@ import java.util.List; public class GroupUnsetTempInherit extends GroupSubCommand { public GroupUnsetTempInherit() { super("unsettempinherit", "Unsets another group for this group to inherit permissions from", - "/%s group unsettempinherit [server]", Permission.GROUP_UNSET_TEMP_INHERIT); + "/%s group unsettempinherit [server] [world]", Permission.GROUP_UNSET_TEMP_INHERIT); } @Override @@ -27,15 +27,22 @@ public class GroupUnsetTempInherit extends GroupSubCommand { } try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - group.unsetPermission("group." + groupName, server, true); - Message.GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server); + if (args.size() == 2) { + group.unsetPermission("group." + groupName, server, true); + Message.GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS.send(sender, group.getName(), groupName, server); + } else { + final String world = args.get(2).toLowerCase(); + group.unsetPermission("group." + groupName, server, world, true); + Message.GROUP_UNSET_TEMP_INHERIT_SERVER_WORLD_SUCCESS.send(sender, group.getName(), groupName, server, world); + } + } else { group.unsetPermission("group." + groupName, true); Message.GROUP_UNSET_TEMP_INHERIT_SUCCESS.send(sender, group.getName(), groupName); @@ -54,6 +61,6 @@ public class GroupUnsetTempInherit extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetTempPermission.java b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetTempPermission.java index 54242a75..1c2af0a4 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetTempPermission.java +++ b/common/src/main/java/me/lucko/luckperms/commands/group/subcommands/GroupUnsetTempPermission.java @@ -14,7 +14,7 @@ import java.util.List; public class GroupUnsetTempPermission extends GroupSubCommand { public GroupUnsetTempPermission() { super("unsettemp", "Unsets a temporary permission for a group", - "/%s group unsettemp [server]", Permission.GROUP_UNSET_TEMP_PERMISSION); + "/%s group unsettemp [server] [world]", Permission.GROUP_UNSET_TEMP_PERMISSION); } @Override @@ -32,15 +32,22 @@ public class GroupUnsetTempPermission extends GroupSubCommand { } try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - group.unsetPermission(node, server); - Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server, true); + if (args.size() == 2) { + group.unsetPermission(node, server); + Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, group.getName(), server); + } else { + final String world = args.get(2).toLowerCase(); + group.unsetPermission(node, server, world); + Message.UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, group.getName(), server, world); + } + } else { group.unsetPermission(node, true); Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, group.getName()); @@ -54,6 +61,6 @@ public class GroupUnsetTempPermission extends GroupSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserAddGroup.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserAddGroup.java index fc25c318..22e4486c 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserAddGroup.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserAddGroup.java @@ -14,7 +14,7 @@ import java.util.List; public class UserAddGroup extends UserSubCommand { public UserAddGroup() { - super("addgroup", "Adds the user to a group", "/%s user addgroup [server]", Permission.USER_ADDGROUP); + super("addgroup", "Adds the user to a group", "/%s user addgroup [server] [world]", Permission.USER_ADDGROUP); } @Override @@ -37,15 +37,22 @@ public class UserAddGroup extends UserSubCommand { } try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - user.addGroup(group, server); - Message.USER_ADDGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server); + if (args.size() == 2) { + user.addGroup(group, server); + Message.USER_ADDGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server); + } else { + final String world = args.get(2).toLowerCase(); + user.addGroup(group, server, world); + Message.USER_ADDGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world); + } + } else { user.addGroup(group); Message.USER_ADDGROUP_SUCCESS.send(sender, user.getName(), groupName); @@ -66,6 +73,6 @@ public class UserAddGroup extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return (argLength != 1 && argLength != 2); + return (argLength != 1 && argLength != 2 && argLength != 3); } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserAddTempGroup.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserAddTempGroup.java index 10e25533..0571ff55 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserAddTempGroup.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserAddTempGroup.java @@ -15,8 +15,8 @@ import java.util.List; public class UserAddTempGroup extends UserSubCommand { public UserAddTempGroup() { - super("addtempgroup", "Adds the user to a group temporarily", "/%s user addtempgroup [server]", - Permission.USER_ADDTEMPGROUP); + super("addtempgroup", "Adds the user to a group temporarily", + "/%s user addtempgroup [server] [world]", Permission.USER_ADDTEMPGROUP); } @Override @@ -52,16 +52,24 @@ public class UserAddTempGroup extends UserSubCommand { } try { - if (args.size() == 3) { + if (args.size() >= 3) { final String server = args.get(2).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - user.addGroup(group, server, duration); - Message.USER_ADDTEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server, - DateUtil.formatDateDiff(duration)); + if (args.size() == 3) { + user.addGroup(group, server, duration); + Message.USER_ADDTEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server, + DateUtil.formatDateDiff(duration)); + } else { + final String world = args.get(3).toLowerCase(); + user.addGroup(group, server, world, duration); + Message.USER_ADDTEMPGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, + world, DateUtil.formatDateDiff(duration)); + } + } else { user.addGroup(group, duration); Message.USER_ADDTEMPGROUP_SUCCESS.send(sender, user.getName(), groupName, DateUtil.formatDateDiff(duration)); @@ -82,6 +90,6 @@ public class UserAddTempGroup extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return (argLength != 2 && argLength != 3); + return (argLength != 2 && argLength != 3 && argLength != 4); } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserHasPerm.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserHasPerm.java index 78a4975f..a5ab03dc 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserHasPerm.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserHasPerm.java @@ -14,7 +14,7 @@ import java.util.List; public class UserHasPerm extends UserSubCommand { public UserHasPerm() { super("haspermission", "Checks to see if a user has a certain permission node", - "/%s user haspermission [server]", Permission.USER_HASPERMISSION); + "/%s user haspermission [server] [world]", Permission.USER_HASPERMISSION); } @Override @@ -25,7 +25,12 @@ public class UserHasPerm extends UserSubCommand { return; } - Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, args.get(1))); + if (args.size() == 2) { + Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, args.get(1))); + } else { + Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, args.get(1), args.get(2))); + } + } else { Util.sendBoolean(sender, args.get(0), user.hasPermission(args.get(0), true, "global")); } @@ -33,6 +38,6 @@ public class UserHasPerm extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserInheritsPerm.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserInheritsPerm.java index 5673c472..24290892 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserInheritsPerm.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserInheritsPerm.java @@ -14,7 +14,7 @@ import java.util.List; public class UserInheritsPerm extends UserSubCommand { public UserInheritsPerm() { super("inheritspermission", "Checks to see if a user inherits a certain permission node", - "/%s user inheritspermission [server]", Permission.USER_INHERITSPERMISSION); + "/%s user inheritspermission [server] [world]", Permission.USER_INHERITSPERMISSION); } @Override @@ -25,7 +25,12 @@ public class UserInheritsPerm extends UserSubCommand { return; } - Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true, args.get(1))); + if (args.size() == 2) { + Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true, args.get(1))); + } else { + Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true, args.get(1), args.get(2))); + } + } else { Util.sendBoolean(sender, args.get(0), user.inheritsPermission(args.get(0), true)); } @@ -33,6 +38,6 @@ public class UserInheritsPerm extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserRemoveGroup.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserRemoveGroup.java index ad9c9f7f..7e9f952a 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserRemoveGroup.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserRemoveGroup.java @@ -13,7 +13,7 @@ import java.util.List; public class UserRemoveGroup extends UserSubCommand { public UserRemoveGroup() { - super("removegroup", "Removes a user from a group", "/%s user removegroup [server]", Permission.USER_REMOVEGROUP); + super("removegroup", "Removes a user from a group", "/%s user removegroup [server] [world]", Permission.USER_REMOVEGROUP); } @Override @@ -32,15 +32,22 @@ public class UserRemoveGroup extends UserSubCommand { } try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - user.unsetPermission("group." + groupName, server); - Message.USER_REMOVEGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server); + if (args.size() == 2) { + user.unsetPermission("group." + groupName, server); + Message.USER_REMOVEGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server); + } else { + final String world = args.get(2).toLowerCase(); + user.unsetPermission("group." + groupName, server, world); + Message.USER_REMOVEGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world); + } + } else { user.unsetPermission("group." + groupName); Message.USER_REMOVEGROUP_SUCCESS.send(sender, user.getName(), groupName); @@ -59,6 +66,6 @@ public class UserRemoveGroup extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return (argLength != 1 && argLength != 2); + return (argLength != 1 && argLength != 2 && argLength != 3); } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserRemoveTempGroup.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserRemoveTempGroup.java index 5a2a2abc..129dd93a 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserRemoveTempGroup.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserRemoveTempGroup.java @@ -13,7 +13,8 @@ import java.util.List; public class UserRemoveTempGroup extends UserSubCommand { public UserRemoveTempGroup() { - super("removetempgroup", "Removes a user from a temporary group", "/%s user removetempgroup [server]", Permission.USER_REMOVETEMPGROUP); + super("removetempgroup", "Removes a user from a temporary group", + "/%s user removetempgroup [server] [world]", Permission.USER_REMOVETEMPGROUP); } @Override @@ -26,15 +27,22 @@ public class UserRemoveTempGroup extends UserSubCommand { } try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - user.unsetPermission("group." + groupName, server, true); - Message.USER_REMOVETEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server); + if (args.size() == 2) { + user.unsetPermission("group." + groupName, server, true); + Message.USER_REMOVETEMPGROUP_SERVER_SUCCESS.send(sender, user.getName(), groupName, server); + } else { + final String world = args.get(2).toLowerCase(); + user.unsetPermission("group." + groupName, server, world, true); + Message.USER_REMOVETEMPGROUP_SERVER_WORLD_SUCCESS.send(sender, user.getName(), groupName, server, world); + } + } else { user.unsetPermission("group." + groupName, true); Message.USER_REMOVETEMPGROUP_SUCCESS.send(sender, user.getName(), groupName); @@ -53,6 +61,6 @@ public class UserRemoveTempGroup extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return (argLength != 1 && argLength != 2); + return (argLength != 1 && argLength != 2 && argLength != 3); } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserSetPermission.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserSetPermission.java index cf95eea4..a7395204 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserSetPermission.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserSetPermission.java @@ -14,7 +14,7 @@ import java.util.List; public class UserSetPermission extends UserSubCommand { public UserSetPermission() { super("set", "Sets a permission for a user", - "/%s user set [server]", Permission.USER_SETPERMISSION); + "/%s user set [server] [world]", Permission.USER_SETPERMISSION); } @Override @@ -40,15 +40,22 @@ public class UserSetPermission extends UserSubCommand { boolean b = Boolean.parseBoolean(bool); try { - if (args.size() == 3) { + if (args.size() >= 3) { final String server = args.get(2).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - user.setPermission(node, b, server); - Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server); + if (args.size() == 3) { + user.setPermission(node, b, server); + Message.SETPERMISSION_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server); + } else { + final String world = args.get(3).toLowerCase(); + user.setPermission(node, b, server, world); + Message.SETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, bool, user.getName(), server, world); + } + } else { user.setPermission(node, b); Message.SETPERMISSION_SUCCESS.send(sender, node, bool, user.getName()); @@ -67,6 +74,6 @@ public class UserSetPermission extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 2 && argLength != 3; + return argLength != 2 && argLength != 3 && argLength != 4; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserSetTempPermission.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserSetTempPermission.java index 4decd4e3..c3dc644f 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserSetTempPermission.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserSetTempPermission.java @@ -15,7 +15,7 @@ import java.util.List; public class UserSetTempPermission extends UserSubCommand { public UserSetTempPermission() { super("settemp", "Sets a temporary permission for a user", - "/%s user settemp [server]", Permission.USER_SET_TEMP_PERMISSION); + "/%s user settemp [server] [world]", Permission.USER_SET_TEMP_PERMISSION); } @Override @@ -54,15 +54,22 @@ public class UserSetTempPermission extends UserSubCommand { } try { - if (args.size() == 4) { + if (args.size() >= 4) { final String server = args.get(3).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - user.setPermission(node, b, server, duration); - Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server, DateUtil.formatDateDiff(duration)); + if (args.size() == 4) { + user.setPermission(node, b, server, duration); + Message.SETPERMISSION_TEMP_SERVER_SUCCESS.send(sender, node, bool, user.getName(), server, DateUtil.formatDateDiff(duration)); + } else { + final String world = args.get(4).toLowerCase(); + user.setPermission(node, b, server, world, duration); + Message.SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS.send(sender, node, bool, user.getName(), server, world, DateUtil.formatDateDiff(duration)); + } + } else { user.setPermission(node, b, duration); Message.SETPERMISSION_TEMP_SUCCESS.send(sender, node, bool, user.getName(), DateUtil.formatDateDiff(duration)); @@ -81,6 +88,6 @@ public class UserSetTempPermission extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 3 && argLength != 4; + return argLength != 3 && argLength != 4 && argLength != 5; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserUnSetPermission.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserUnSetPermission.java index a59e3530..a775cd5a 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserUnSetPermission.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserUnSetPermission.java @@ -14,7 +14,7 @@ import java.util.List; public class UserUnSetPermission extends UserSubCommand { public UserUnSetPermission() { super("unset", "Unsets a permission for a user", - "/%s user unset [server]", Permission.USER_UNSETPERMISSION); + "/%s user unset [server] [world]", Permission.USER_UNSETPERMISSION); } @Override @@ -32,15 +32,22 @@ public class UserUnSetPermission extends UserSubCommand { } try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - user.unsetPermission(node, server); - Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server); + if (args.size() == 2) { + user.unsetPermission(node, server); + Message.UNSETPERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server); + } else { + final String world = args.get(2).toLowerCase(); + user.unsetPermission(node, server, world); + Message.UNSETPERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, user.getName(), server, world); + } + } else { user.unsetPermission(node); Message.UNSETPERMISSION_SUCCESS.send(sender, node, user.getName()); @@ -54,6 +61,6 @@ public class UserUnSetPermission extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } diff --git a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserUnsetTempPermission.java b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserUnsetTempPermission.java index 26442dc1..c119dcf6 100644 --- a/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserUnsetTempPermission.java +++ b/common/src/main/java/me/lucko/luckperms/commands/user/subcommands/UserUnsetTempPermission.java @@ -14,7 +14,7 @@ import java.util.List; public class UserUnsetTempPermission extends UserSubCommand { public UserUnsetTempPermission() { super("unsettemp", "Unsets a temporary permission for a user", - "/%s user unsettemp [server]", Permission.USER_UNSET_TEMP_PERMISSION); + "/%s user unsettemp [server] [world]", Permission.USER_UNSET_TEMP_PERMISSION); } @Override @@ -32,15 +32,22 @@ public class UserUnsetTempPermission extends UserSubCommand { } try { - if (args.size() == 2) { + if (args.size() >= 2) { final String server = args.get(1).toLowerCase(); if (Patterns.NON_ALPHA_NUMERIC.matcher(server).find()) { Message.SERVER_INVALID_ENTRY.send(sender); return; } - user.unsetPermission(node, server, true); - Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server); + if (args.size() == 2) { + user.unsetPermission(node, server, true); + Message.UNSET_TEMP_PERMISSION_SERVER_SUCCESS.send(sender, node, user.getName(), server); + } else { + final String world = args.get(2).toLowerCase(); + user.unsetPermission(node, server, world, true); + Message.UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS.send(sender, node, user.getName(), server, world); + } + } else { user.unsetPermission(node, true); Message.UNSET_TEMP_PERMISSION_SUCCESS.send(sender, node, user.getName()); @@ -54,6 +61,6 @@ public class UserUnsetTempPermission extends UserSubCommand { @Override public boolean isArgLengthInvalid(int argLength) { - return argLength != 1 && argLength != 2; + return argLength != 1 && argLength != 2 && argLength != 3; } } 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 357cc772..71ec2f78 100644 --- a/common/src/main/java/me/lucko/luckperms/constants/Message.java +++ b/common/src/main/java/me/lucko/luckperms/constants/Message.java @@ -1,11 +1,9 @@ package me.lucko.luckperms.constants; -import lombok.AllArgsConstructor; import me.lucko.luckperms.commands.Sender; import me.lucko.luckperms.commands.Util; @SuppressWarnings("SpellCheckingInspection") -@AllArgsConstructor public enum Message { /** @@ -125,12 +123,16 @@ public enum Message { LISTNODES_TEMP("&e%s's Temporary Nodes:" + "\n" + "%s", true), SETPERMISSION_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a.", true), SETPERMISSION_SERVER_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a.", true), + SETPERMISSION_SERVER_WORLD_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a, world &b%s&a.", true), SETPERMISSION_TEMP_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a for a duration of &b%s&a.", true), SETPERMISSION_TEMP_SERVER_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a for a duration of &b%s&a.", true), + SETPERMISSION_TEMP_SERVER_WORLD_SUCCESS("&aSet &b%s&a to &b%s&a for &b%s&a on server &b%s&a, world &b%s&a, for a duration of &b%s&a.", true), UNSETPERMISSION_SUCCESS("&aUnset &b%s&a for &b%s&a.", true), UNSETPERMISSION_SERVER_SUCCESS("&aUnset &b%s&a for &b%s&a on server &b%$s&a.", true), + UNSETPERMISSION_SERVER_WORLD_SUCCESS("&aUnset &b%s&a for &b%s&a on server &b%$s&a, world &b%$s&a.", true), UNSET_TEMP_PERMISSION_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a.", true), UNSET_TEMP_PERMISSION_SERVER_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a on server &b%$s&a.", true), + UNSET_TEMP_PERMISSION_SERVER_WORLD_SUCCESS("&aUnset temporary permission &b%s&a for &b%s&a on server &b%$s&a, world &b%$s&a.", true), CLEAR_SUCCESS("&b%s&a's permissions were cleared.", true), ILLEGAL_DATE_ERROR("Could not parse date '%s'.", true), PAST_DATE_ERROR("You cannot set a date in the past!", true), @@ -149,12 +151,16 @@ public enum Message { USER_GETUUID("&bThe UUID of &e%s&b is &e%s&b.", true), USER_ADDGROUP_SUCCESS("&b%s&a successfully added to group &b%s&a.", true), USER_ADDGROUP_SERVER_SUCCESS("&b%s&a successfully added to group &b%s&a on server &b%s&a.", true), + USER_ADDGROUP_SERVER_WORLD_SUCCESS("&b%s&a successfully added to group &b%s&a on server &b%s&a, world &b%s&a.", true), USER_ADDTEMPGROUP_SUCCESS("&b%s&a successfully added to group &b%s&a for a duration of &b%s&a.", true), USER_ADDTEMPGROUP_SERVER_SUCCESS("&b%s&a successfully added to group &b%s&a on server &b%s&a for a duration of &b%s&a.", true), + USER_ADDTEMPGROUP_SERVER_WORLD_SUCCESS("&b%s&a successfully added to group &b%s&a on server &b%s&a, world &b%s&a, for a duration of &b%s&a.", true), USER_REMOVEGROUP_SUCCESS("&b%s&a was removed from group &b%s&a.", true), USER_REMOVEGROUP_SERVER_SUCCESS("&b%s&a was removed from group &b%s&a on server &b%s&a.", true), + USER_REMOVEGROUP_SERVER_WORLD_SUCCESS("&b%s&a was removed from group &b%s&a on server &b%s&a, world &b%s&a.", true), USER_REMOVETEMPGROUP_SUCCESS("&b%s&a was removed from temproary group &b%s&a.", true), USER_REMOVETEMPGROUP_SERVER_SUCCESS("&b%s&a was removed from temporary group &b%s&a on server &b%s&a.", true), + USER_REMOVETEMPGROUP_SERVER_WORLD_SUCCESS("&b%s&a was removed from temporary group &b%s&a on server &b%s&a, world &b%s&a.", true), USER_REMOVEGROUP_ERROR_PRIMARY("You cannot remove a user from their primary group.", true), USER_PRIMARYGROUP_SUCCESS("&b%s&a's primary group was set to &b%s&a.", true), USER_PRIMARYGROUP_ERROR_ALREADYHAS("The user already has this group set as their primary group.", true), @@ -189,12 +195,16 @@ public enum Message { ), GROUP_SETINHERIT_SUCCESS("&b%s&a now inherits permissions from &b%s&a.", true), GROUP_SETINHERIT_SERVER_SUCCESS("&b%s&a now inherits permissions from &b%s&a on server &b%s&a.", true), + GROUP_SETINHERIT_SERVER_WORLD_SUCCESS("&b%s&a now inherits permissions from &b%s&a on server &b%s&a, world &b%s&a.", true), GROUP_SET_TEMP_INHERIT_SUCCESS("&b%s&a now inherits permissions from &b%s&a for a duration of &b%s&a.", true), GROUP_SET_TEMP_INHERIT_SERVER_SUCCESS("&b%s&a now inherits permissions from &b%s&a on server &b%s&a for a duration of &b%s&a.", true), + GROUP_SET_TEMP_INHERIT_SERVER_WORLD_SUCCESS("&b%s&a now inherits permissions from &b%s&a on server &b%s&a, world &b%s&a, for a duration of &b%s&a.", true), GROUP_UNSETINHERIT_SUCCESS("&b%s&a no longer inherits permissions from &b%s&a.", true), GROUP_UNSETINHERIT_SERVER_SUCCESS("&b%s&a no longer inherits permissions from &b%s&a on server &b%s&a.", true), + GROUP_UNSETINHERIT_SERVER_WORLD_SUCCESS("&b%s&a no longer inherits permissions from &b%s&a on server &b%s&a, world &b%s&a.", true), GROUP_UNSET_TEMP_INHERIT_SUCCESS("&b%s&a no longer temporarily inherits permissions from &b%s&a.", true), GROUP_UNSET_TEMP_INHERIT_SERVER_SUCCESS("&b%s&a no longer temporarily inherits permissions from &b%s&a on server &b%s&a.", true), + GROUP_UNSET_TEMP_INHERIT_SERVER_WORLD_SUCCESS("&b%s&a no longer temporarily inherits permissions from &b%s&a on server &b%s&a, world &b%s&a.", true), TRACK_INFO( PREFIX + "&d-> &eTrack: &6%s" + "\n" + @@ -211,6 +221,11 @@ public enum Message { private String message; private boolean showPrefix; + Message(String message, boolean showPrefix) { + this.message = Util.color(message); + this.showPrefix = showPrefix; + } + @Override public String toString() { return message; @@ -218,9 +233,9 @@ public enum Message { public void send(Sender sender, Object... objects) { if (showPrefix) { - sender.sendMessage(Util.color(PREFIX + String.format(message, objects))); + sender.sendMessage(PREFIX + String.format(message, objects)); } else { - sender.sendMessage(Util.color(String.format(message, objects))); + sender.sendMessage(String.format(message, objects)); } } } 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 4fde2d40..61954eb5 100644 --- a/common/src/main/java/me/lucko/luckperms/users/User.java +++ b/common/src/main/java/me/lucko/luckperms/users/User.java @@ -11,7 +11,9 @@ import me.lucko.luckperms.groups.Group; import me.lucko.luckperms.utils.Patterns; import me.lucko.luckperms.utils.PermissionObject; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.UUID; import java.util.stream.Collectors; @ToString(of = {"uuid"}) @@ -74,6 +76,17 @@ public abstract class User extends PermissionObject { return hasPermission("group." + group.getName(), true, server); } + /** + * Check to see if a user is a member of a group on a specific server + * @param group The group to check membership of + * @param server The server to check on + * @param world The world to check on + * @return true if the user is a member of the group + */ + public boolean isInGroup(Group group, String server, String world) { + return hasPermission("group." + group.getName(), true, server, world); + } + /** * Add a user to a group * @param group The group to add the user to @@ -97,6 +110,21 @@ public abstract class User extends PermissionObject { setPermission("group." + group.getName(), true, server); } + /** + * Add a user to a group on a specific server + * @param group The group to add the user to + * @param server The server to add the group on + * @param world The world to add the group on + * @throws ObjectAlreadyHasException if the user is already a member of the group on that server + */ + public void addGroup(Group group, String server, String world) throws ObjectAlreadyHasException { + if (server == null) { + server = "global"; + } + + setPermission("group." + group.getName(), true, server, world); + } + /** * Add a user to a group on a specific server * @param group The group to add the user to @@ -122,6 +150,22 @@ public abstract class User extends PermissionObject { setPermission("group." + group.getName(), true, server, expireAt); } + /** + * Add a user to a group on a specific server + * @param group The group to add the user to + * @param server The server to add the group on + * @param world The world to add the group on + * @param expireAt when the group should expire + * @throws ObjectAlreadyHasException if the user is already a member of the group on that server + */ + public void addGroup(Group group, String server, String world, long expireAt) throws ObjectAlreadyHasException { + if (server == null) { + server = "global"; + } + + setPermission("group." + group.getName(), true, server, world, expireAt); + } + /** * Remove the user from a group * @param group the group to remove the user from @@ -155,6 +199,21 @@ public abstract class User extends PermissionObject { unsetPermission("group." + group.getName(), server); } + /** + * Remove the user from a group + * @param group The group to remove the user from + * @param server The server to remove the group on + * @param world The world to remove the group on + * @throws ObjectLacksException if the user isn't a member of the group + */ + public void removeGroup(Group group, String server, String world) throws ObjectLacksException { + if (server == null) { + server = "global"; + } + + unsetPermission("group." + group.getName(), server, world); + } + /** * Remove the user from a group * @param group The group to remove the user from @@ -170,6 +229,22 @@ public abstract class User extends PermissionObject { unsetPermission("group." + group.getName(), server, temporary); } + /** + * Remove the user from a group + * @param group The group to remove the user from + * @param server The server to remove the group on + * @param world The world to remove the group on + * @param temporary if the group being removed is temporary + * @throws ObjectLacksException if the user isn't a member of the group + */ + public void removeGroup(Group group, String server, String world, boolean temporary) throws ObjectLacksException { + if (server == null) { + server = "global"; + } + + unsetPermission("group." + group.getName(), server, world, temporary); + } + /** * Clear all of the users permission nodes */ @@ -187,96 +262,38 @@ public abstract class User extends PermissionObject { return getGroups(null, null, true); } + /** + * Get a {@link List} of the groups the user is a member of on a specific server + * @param server the server to check + * @return a {@link List} of group names + */ + public List getLocalGroups(String server, String world) { + return getGroups(server, world, false); + } + /** * Get a {@link List} of the groups the user is a member of on a specific server * @param server the server to check * @return a {@link List} of group names */ public List getLocalGroups(String server) { - return getGroups(server, null, false); + return getLocalGroups(server, null); } /** * Get a {@link List} of the groups the user is a member of on a specific server with the option to include global * groups or all groups * @param server Which server to check on - * @param excludedGroups groups to exclude (prevents circular inheritance issues) + * @param world Which world to check on * @param includeGlobal Whether to include global groups * @return a {@link List} of group names */ - private List getGroups(String server, List excludedGroups, boolean includeGlobal) { - if (excludedGroups == null) { - excludedGroups = new ArrayList<>(); - } - - excludedGroups.add(getObjectName()); - List groups = new ArrayList<>(); - - if (server == null || server.equals("")) { - server = "global"; - } - - /* - Priority: - - 1. server specific group nodes - 2. group nodes - */ - - final Map serverSpecificGroups = new HashMap<>(); - final Map groupNodes = new HashMap<>(); - - // Sorts the permissions and puts them into a priority order - for (Map.Entry node : convertTemporaryPerms().entrySet()) { - serverSpecific: - if (node.getKey().contains("/")) { - String[] parts = Patterns.SERVER_SPLIT.split(node.getKey(), 2); - - if (parts[0].equalsIgnoreCase("global")) { - // REGULAR - break serverSpecific; - } - - if (!parts[0].equalsIgnoreCase(server)) { - // SERVER SPECIFIC BUT DOES NOT APPLY - continue; - } - - if (Patterns.GROUP_MATCH.matcher(parts[1]).matches()) { - // SERVER SPECIFIC AND GROUP - serverSpecificGroups.put(node.getKey(), node.getValue()); - continue; - } - - continue; - } - - // Skip adding global permissions if they are not requested - if (!includeGlobal) continue; - - if (Patterns.GROUP_MATCH.matcher(node.getKey()).matches()) { - // GROUP - groupNodes.put(node.getKey(), node.getValue()); - } - - } - - // If a group is negated at a higher priority, the group should not then be applied at a lower priority - serverSpecificGroups.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> { - groupNodes.remove(node.getKey()); - groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]); - }); - - groups.addAll(serverSpecificGroups.entrySet().stream() - .filter(Map.Entry::getValue) - .map(e -> Patterns.DOT_SPLIT.split(e.getKey(), 2)[1]) - .collect(Collectors.toList()) - ); - groups.addAll(groupNodes.entrySet().stream() - .filter(Map.Entry::getValue) - .map(e -> Patterns.DOT_SPLIT.split(e.getKey(), 2)[1]) - .collect(Collectors.toList()) - ); - return groups; + private List getGroups(String server, String world, boolean includeGlobal) { + // Call super #getPermissions method, and just sort through those + 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]) + .collect(Collectors.toList()); } } 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 8dea0935..dc69e49b 100644 --- a/common/src/main/java/me/lucko/luckperms/utils/Patterns.java +++ b/common/src/main/java/me/lucko/luckperms/utils/Patterns.java @@ -7,6 +7,7 @@ import java.util.regex.Pattern; @UtilityClass public class Patterns { 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 GROUP_MATCH = Pattern.compile("group\\..*"); diff --git a/common/src/main/java/me/lucko/luckperms/utils/PermissionObject.java b/common/src/main/java/me/lucko/luckperms/utils/PermissionObject.java index d50a696a..80320b33 100644 --- a/common/src/main/java/me/lucko/luckperms/utils/PermissionObject.java +++ b/common/src/main/java/me/lucko/luckperms/utils/PermissionObject.java @@ -89,6 +89,18 @@ public abstract class PermissionObject { return hasPermission(server + "/" + node, b); } + /** + * Checks to see the the object has a permission on a certain server + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server + * @param world The world + * @return true if the user has the permission + */ + public boolean hasPermission(String node, boolean b, String server, String world) { + return hasPermission(server + "-" + world + "/" + node, b); + } + /** * Checks to see the the object has a permission on a certain server * @param node The permission node @@ -100,6 +112,31 @@ public abstract class PermissionObject { return hasPermission(node + (temporary ? "$a" : ""), b); } + /** + * Checks to see the the object has a permission on a certain server + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server to check on + * @param temporary if the permission is temporary + * @return true if the user has the permission + */ + public boolean hasPermission(String node, boolean b, String server, boolean temporary) { + return hasPermission(server + "/" + node + (temporary ? "$a" : ""), b); + } + + /** + * Checks to see the the object has a permission on a certain server + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server to check on + * @param world The world to check on + * @param temporary if the permission is temporary + * @return true if the user has the permission + */ + public boolean hasPermission(String node, boolean b, String server, String world, boolean temporary) { + return hasPermission(server + "-" + world + "/" + node + (temporary ? "$a" : ""), b); + } + /** * Checks to see if the object inherits a certain permission * @param node The permission node @@ -124,10 +161,29 @@ public abstract class PermissionObject { * @return true if the user inherits the permission */ public boolean inheritsPermission(String node, boolean b, String server) { + if (server.contains("-")) { + // Use other method + final String[] parts = Patterns.WORLD_SPLIT.split(server, 2); + return inheritsPermission(node, b, parts[0], parts[1]); + } + final Map local = getLocalPermissions(server, null); return hasPermission(local, node, b); } + /** + * Checks to see the the object inherits a permission on a certain server + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server + * @param world The world + * @return true if the user inherits the permission + */ + public boolean inheritsPermission(String node, boolean b, String server, String world) { + final Map local = getLocalPermissions(server, world, null); + return hasPermission(local, node, b); + } + /** * Checks to see if the object inherits a certain permission * @param node The permission node @@ -139,6 +195,31 @@ public abstract class PermissionObject { return inheritsPermission(node + (temporary ? "$a" : ""), b); } + /** + * Checks to see if the object inherits a certain permission + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server + * @param temporary if the permission is temporary + * @return true if the user inherits the permission + */ + public boolean inheritsPermission(String node, boolean b, String server, boolean temporary) { + return inheritsPermission(server + "/" + node + (temporary ? "$a" : ""), b); + } + + /** + * Checks to see if the object inherits a certain permission + * @param node The permission node + * @param b If the node is true/false(negated) + * @param server The server + * @param world The world + * @param temporary if the permission is temporary + * @return true if the user inherits the permission + */ + public boolean inheritsPermission(String node, boolean b, String server, String world, boolean temporary) { + return inheritsPermission(server + "-" + world + "/" + node + (temporary ? "$a" : ""), b); + } + /** * Sets a permission for the object * @param node The node to be set @@ -164,6 +245,18 @@ public abstract class PermissionObject { setPermission(server + "/" + node, value); } + /** + * Sets a permission for the object + * @param node The node to set + * @param value What to set the node to - true/false(negated) + * @param server The server to set the permission on + * @param world The world to set the permission on + * @throws ObjectAlreadyHasException if the object already has the permission + */ + public void setPermission(String node, boolean value, String server, String world) throws ObjectAlreadyHasException { + setPermission(server + "-" + world + "/" + node, value); + } + /** * Sets a permission for the object * @param node The node to set @@ -187,6 +280,19 @@ public abstract class PermissionObject { setPermission(node + "$" + expireAt, value, server); } + /** + * Sets a permission for the object + * @param node The node to set + * @param value What to set the node to - true/false(negated) + * @param server The server to set the permission on + * @param world The world to set the permission on + * @param expireAt The time in unixtime when the permission will expire + * @throws ObjectAlreadyHasException if the object already has the permission + */ + public void setPermission(String node, boolean value, String server, String world, long expireAt) throws ObjectAlreadyHasException { + setPermission(node + "$" + expireAt, value, server, world); + } + /** * Unsets a permission for the object * @param node The node to be unset @@ -234,6 +340,17 @@ public abstract class PermissionObject { unsetPermission(server + "/" + node); } + /** + * Unsets a permission for the object + * @param node The node to be unset + * @param server The server to unset the node on + * @param world The world to unset the node on + * @throws ObjectLacksException if the node wasn't already set + */ + public void unsetPermission(String node, String server, String world) throws ObjectLacksException { + unsetPermission(server + "-" + world + "/" + node); + } + /** * Unsets a permission for the object * @param node The node to be unset @@ -245,6 +362,29 @@ public abstract class PermissionObject { unsetPermission(server + "/" + node, temporary); } + /** + * Unsets a permission for the object + * @param node The node to be unset + * @param server The server to unset the node on + * @param world The world to unset the node on + * @param temporary if the permission being unset is temporary + * @throws ObjectLacksException if the node wasn't already set + */ + public void unsetPermission(String node, String server, String world, boolean temporary) throws ObjectLacksException { + unsetPermission(server + "-" + world + "/" + node, temporary); + } + + /** + * Gets the permissions and inherited permissions that apply to a specific server + * @param server The server to get nodes for + * @param world The world to get nodes for + * @param excludedGroups Groups that shouldn't be inherited (to prevent circular inheritance issues) + * @return a {@link Map} of the permissions + */ + public Map getLocalPermissions(String server, String world, List excludedGroups) { + return getPermissions(server, world, excludedGroups, plugin.getConfiguration().getIncludeGlobalPerms()); + } + /** * Gets the permissions and inherited permissions that apply to a specific server * @param server The server to get nodes for @@ -252,7 +392,7 @@ public abstract class PermissionObject { * @return a {@link Map} of the permissions */ public Map getLocalPermissions(String server, List excludedGroups) { - return getPermissions(server, excludedGroups, plugin.getConfiguration().getIncludeGlobalPerms()); + return getLocalPermissions(server, null, excludedGroups); } /** @@ -287,7 +427,7 @@ public abstract class PermissionObject { .forEach(s -> this.nodes.remove(s)); } - protected Map convertTemporaryPerms() { + private Map convertTemporaryPerms() { auditTemporaryPermissions(); Map nodes = new HashMap<>(); @@ -306,7 +446,7 @@ public abstract class PermissionObject { return nodes; } - private Map getPermissions(String server, List excludedGroups, boolean includeGlobal) { + protected Map getPermissions(String server, String world, List excludedGroups, boolean includeGlobal) { if (excludedGroups == null) { excludedGroups = new ArrayList<>(); } @@ -318,17 +458,25 @@ public abstract class PermissionObject { server = "global"; } + if (world != null && world.equalsIgnoreCase("")) { + world = null; + } + /* Priority: - 1. server specific nodes - 2. user nodes - 3. server specific group nodes - 4. group nodes + 1. server+world specific nodes + 2. server specific nodes + 3. user nodes + 4. server+world specific group nodes + 5. server specific group nodes + 6. group nodes */ + final Map serverWorldSpecificNodes = new HashMap<>(); final Map serverSpecificNodes = new HashMap<>(); final Map userNodes = new HashMap<>(); + final Map serverWorldSpecificGroups = new HashMap<>(); final Map serverSpecificGroups = new HashMap<>(); final Map groupNodes = new HashMap<>(); @@ -337,6 +485,33 @@ public abstract class PermissionObject { serverSpecific: if (node.getKey().contains("/")) { String[] parts = Patterns.SERVER_SPLIT.split(node.getKey(), 2); + // 0=server(+world) 1=node + + // WORLD SPECIFIC + if (parts[0].contains("-")) { + String[] serverParts = Patterns.WORLD_SPLIT.split(parts[0], 2); + // 0=server 1=world + + if ((!serverParts[0].equalsIgnoreCase("global") || !includeGlobal) && (!serverParts[0].equalsIgnoreCase(server))) { + // GLOBAL AND UNWANTED OR SERVER SPECIFIC BUT DOES NOT APPLY :((( + continue; + } + + if (world != null && !serverParts[1].equalsIgnoreCase(world)) { + // WORLD SPECIFIC BUT DOES NOT APPLY + continue; + } + + if (Patterns.GROUP_MATCH.matcher(parts[1]).matches()) { + // SERVER+WORLD SPECIFIC AND GROUP + serverWorldSpecificGroups.put(node.getKey(), node.getValue()); + continue; + } + + // SERVER+WORLD SPECIFIC + serverWorldSpecificNodes.put(node.getKey(), node.getValue()); + continue; + } if (parts[0].equalsIgnoreCase("global")) { // REGULAR @@ -362,17 +537,30 @@ public abstract class PermissionObject { // Skip adding global permissions if they are not requested if (!includeGlobal) continue; - if (Patterns.GROUP_MATCH.matcher(node.getKey()).matches()) { + // Could be here if the server was set to global. + String n = node.getKey(); + if (n.contains("/")) { + n = Patterns.SERVER_SPLIT.split(n, 2)[0]; + } + + if (Patterns.GROUP_MATCH.matcher(n).matches()) { // GROUP - groupNodes.put(node.getKey(), node.getValue()); + groupNodes.put(n, node.getValue()); continue; } // JUST NORMAL - userNodes.put(node.getKey(), node.getValue()); + userNodes.put(n, node.getValue()); } // 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]); + 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.entrySet().stream().filter(node -> !node.getValue()).forEach(node -> { groupNodes.remove(node.getKey()); groupNodes.remove(Patterns.SERVER_SPLIT.split(node.getKey(), 2)[1]); @@ -399,24 +587,26 @@ public abstract class PermissionObject { } } - // Apply next priority: serverSpecificGroups - for (Map.Entry groupNode : serverSpecificGroups.entrySet()) { - final String rawNode = Patterns.SERVER_SPLIT.split(groupNode.getKey())[1]; + // 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]; - // Add the actual group perm node, so other plugins can hook - perms.put(rawNode, groupNode.getValue()); + // Add the actual group perm node, so other plugins can hook + perms.put(rawNode, groupNode.getValue()); - // Don't add negated groups - if (!groupNode.getValue()) continue; + // Don't add negated groups + if (!groupNode.getValue()) continue; - String groupName = Patterns.DOT_SPLIT.split(rawNode, 2)[1]; - if (!excludedGroups.contains(groupName)) { - Group group = plugin.getGroupManager().getGroup(groupName); - if (group != null) { - perms.putAll(group.getLocalPermissions(server, excludedGroups)); - } else { - plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." + - "\n The group '" + groupName + "' is not loaded."); + String groupName = Patterns.DOT_SPLIT.split(rawNode, 2)[1]; + if (!excludedGroups.contains(groupName)) { + Group group = plugin.getGroupManager().getGroup(groupName); + if (group != null) { + perms.putAll(group.getLocalPermissions(server, excludedGroups)); + } else { + plugin.getLogger().warning("Error whilst refreshing the permissions of '" + objectName + "'." + + "\n The group '" + groupName + "' is not loaded."); + } } } } @@ -424,10 +614,12 @@ public abstract class PermissionObject { // Apply next priority: userNodes perms.putAll(userNodes); - // Apply highest priority: serverSpecificNodes - for (Map.Entry node : serverSpecificNodes.entrySet()) { - final String rawNode = Patterns.SERVER_SPLIT.split(node.getKey())[1]; - perms.put(rawNode, node.getValue()); + // 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]; + perms.put(rawNode, node.getValue()); + } } return perms; diff --git a/common/src/main/java/me/lucko/luckperms/utils/UuidCache.java b/common/src/main/java/me/lucko/luckperms/utils/UuidCache.java index 3de1cad8..73a135bb 100644 --- a/common/src/main/java/me/lucko/luckperms/utils/UuidCache.java +++ b/common/src/main/java/me/lucko/luckperms/utils/UuidCache.java @@ -3,12 +3,14 @@ package me.lucko.luckperms.utils; import lombok.Getter; import java.util.Map; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; public class UuidCache { - private Map cache; + // External UUID --> Internal UUID + private Map cache; @Getter private final boolean onlineMode; @@ -21,18 +23,25 @@ public class UuidCache { } } - public UUID getUUID(String name, UUID fallback) { - return onlineMode ? fallback : (cache.containsKey(name) ? cache.get(name) : fallback); + public UUID getUUID(UUID external) { + return onlineMode ? external : (cache.containsKey(external) ? cache.get(external) : external); } - public void addToCache(String name, UUID uuid) { - if (onlineMode) return; - cache.put(name, uuid); + public UUID getExternalUUID(UUID internal) { + if (onlineMode) return internal; + + Optional external = cache.entrySet().stream().filter(e -> e.getValue().equals(internal)).map(Map.Entry::getKey).findFirst(); + return external.isPresent() ? external.get() : internal; } - public void clearCache(String name) { + public void addToCache(UUID external, UUID internal) { if (onlineMode) return; - cache.remove(name); + cache.put(external, internal); + } + + public void clearCache(UUID external) { + if (onlineMode) return; + cache.remove(external); } }