From 2c8aa20542b6fbb1555c11e9cd6485534beee39d Mon Sep 17 00:00:00 2001 From: ElgarL Date: Sun, 29 Jan 2012 21:37:50 +0000 Subject: [PATCH 01/21] .project change for Eclipse Build tool --- EssentialsGroupManager/.project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EssentialsGroupManager/.project b/EssentialsGroupManager/.project index c0e5a6f5e..0562b3e0f 100644 --- a/EssentialsGroupManager/.project +++ b/EssentialsGroupManager/.project @@ -16,7 +16,7 @@ LaunchConfigHandle - <project>/.externalToolBuilders/GroupManager.launch + <project>/.externalToolBuilders/New_Builder.launch From 5b4966c8883609b40dced835a0a38935df063f30 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Mon, 30 Jan 2012 14:41:19 +0000 Subject: [PATCH 02/21] Auto sort permissions on load to speed up population of superperms. Negating a parent node after adding all nodes with * will now correctly remove all child nodes of that parent before populating superperms. eg. - '*' - -vanish.* - vanish.standard --- EssentialsGroupManager/src/Changelog.txt | 8 ++- .../dataholder/WorldDataHolder.java | 56 ++++++++++--------- .../permissions/AnjoPermissionsHandler.java | 21 +++++-- 3 files changed, 54 insertions(+), 31 deletions(-) diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index 41b5613af..c3dce16d9 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -125,4 +125,10 @@ v 1.9: - Fixed an infinite loop error when using '/manudel' on a logged in player. It caused setDefaultGroup to trigger a bukkit update when no GM User existed yet. - do not allow inherited permissions to negate higher perms. - Fixed a bug when pushing superperms in the wrong order. - - Fix players retaining permissions when demoted. \ No newline at end of file + - Fix players retaining permissions when demoted. + - Auto sort permissions on load to speed up population of superperms. + - Negating a parent node after adding all nodes with * will now correctly remove all child nodes of that parent before populating superperms. + eg. + - '*' + - -vanish.* + - vanish.standard \ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java index 3cbfbd50b..4fe1daaa5 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java @@ -451,7 +451,7 @@ public class WorldDataHolder { Map thisGroupNode = (Map) allGroupsNode.get(groupKey); Group thisGrp = ph.createGroup(groupKey); if (thisGrp == null) { - throw new IllegalArgumentException("I think this user was declared more than once: " + groupKey + " in file: " + groupsFile.getPath()); + throw new IllegalArgumentException("I think this Group was declared more than once: " + groupKey + " in file: " + groupsFile.getPath()); } if (thisGroupNode.get("default") == null) { thisGroupNode.put("default", false); @@ -467,20 +467,22 @@ public class WorldDataHolder { //PERMISSIONS NODE if (thisGroupNode.get("permissions") == null) { thisGroupNode.put("permissions", new ArrayList()); - } - if (thisGroupNode.get("permissions") instanceof List) { - for (Object o : ((List) thisGroupNode.get("permissions"))) { - try { - thisGrp.addPermission(o.toString()); - } catch (NullPointerException e) { - // Ignore this entry as it's null. - //throw new IllegalArgumentException("Invalid permission node in group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); - } - } - } else if (thisGroupNode.get("permissions") instanceof String) { - thisGrp.addPermission((String) thisGroupNode.get("permissions")); } else { - throw new IllegalArgumentException("Unknown type of permissions node(Should be String or List) for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + if (thisGroupNode.get("permissions") instanceof List) { + for (Object o : ((List) thisGroupNode.get("permissions"))) { + try { + thisGrp.addPermission(o.toString()); + } catch (NullPointerException e) { + // Ignore this entry as it's null. + //throw new IllegalArgumentException("Invalid permission node in group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } + } + } else if (thisGroupNode.get("permissions") instanceof String) { + thisGrp.addPermission((String) thisGroupNode.get("permissions")); + } else { + throw new IllegalArgumentException("Unknown type of permissions node(Should be String or List) for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } + thisGrp.sortPermissions(); } //INFO NODE @@ -581,18 +583,20 @@ public class WorldDataHolder { } if (thisUserNode.get("permissions") == null) { thisUserNode.put("permissions", new ArrayList()); - } - if (thisUserNode.get("permissions") instanceof List) { - for (Object o : ((List) thisUserNode.get("permissions"))) { - thisUser.addPermission(o.toString()); - } - } else if (thisUserNode.get("permissions") instanceof String) { - try { - thisUser.addPermission(thisUserNode.get("permissions").toString()); - } catch (NullPointerException e) { - // Ignore this entry as it's null. - //throw new IllegalArgumentException("Invalid permission node for user: " + thisUser.getName() + " in file: " + UserFile.getPath()); - } + } else { + if (thisUserNode.get("permissions") instanceof List) { + for (Object o : ((List) thisUserNode.get("permissions"))) { + thisUser.addPermission(o.toString()); + } + } else if (thisUserNode.get("permissions") instanceof String) { + try { + thisUser.addPermission(thisUserNode.get("permissions").toString()); + } catch (NullPointerException e) { + // Ignore this entry as it's null. + //throw new IllegalArgumentException("Invalid permission node for user: " + thisUser.getName() + " in file: " + UserFile.getPath()); + } + } + thisUser.sortPermissions(); } //SUBGROUPS LOADING diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java index 2e008e223..7436bec70 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java @@ -153,15 +153,23 @@ public class AnjoPermissionsHandler extends PermissionsReaderInterface { private Set populatePerms (List perms, boolean includeChildren) { Set permArray = new HashSet(); + Boolean allPerms = false; - // Allow * node to populate ALL perms in Bukkit. + // Allow * node to populate ALL permissions to Bukkit. if (perms.contains("*")) { permArray.addAll(GroupManager.BukkitPermissions.getAllRegisteredPermissions(includeChildren)); + allPerms = true; } for (String perm : perms) { if (!perm.equalsIgnoreCase("*")) { + + /** + * all permission sets are passed here pre-sorted, alphabetically. + * This means negated nodes will be processed before all permissions + * other than *. + */ boolean negated = false; if (perm.startsWith("-")) negated = true; @@ -172,12 +180,17 @@ public class AnjoPermissionsHandler extends PermissionsReaderInterface { if ((negated) && (permArray.contains(perm.substring(1)))) permArray.remove(perm.substring(1)); - if (includeChildren) { + /** + * Process child nodes if required, + * or this is a negated node AND we used * to include all permissions, + * in which case we need to remove all children of that node. + */ + if ((includeChildren) || (negated && allPerms)) { Map children = GroupManager.BukkitPermissions.getAllChildren((negated ? perm.substring(1) : perm), new HashSet()); if (children != null) { - if (negated) { + if (negated || (negated && allPerms)) { // Remove children of negated nodes for (String child : children.keySet()) @@ -185,7 +198,7 @@ public class AnjoPermissionsHandler extends PermissionsReaderInterface { if (permArray.contains(child)) permArray.remove(child); - } else { + } else if (!negated){ // Add child nodes for (String child : children.keySet()) From fe050dd72591dc22a370ff4517bd30396fe36956 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Mon, 30 Jan 2012 17:08:55 +0000 Subject: [PATCH 03/21] Track the 'onPlayerChangeWorld' event as some teleports seem to not be triggering a world move. --- EssentialsGroupManager/src/Changelog.txt | 3 ++- .../groupmanager/permissions/BukkitPermissions.java | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index c3dce16d9..770dbe8e2 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -131,4 +131,5 @@ v 1.9: eg. - '*' - -vanish.* - - vanish.standard \ No newline at end of file + - vanish.standard + - Track the 'onPlayerChangeWorld' event as some teleports seem to not be triggering a world move. \ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java index d1193510e..1409f774d 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/BukkitPermissions.java @@ -34,6 +34,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerChangedWorldEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerPortalEvent; @@ -358,6 +359,11 @@ public class BukkitPermissions { } setPlayer_join(false); } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerChangeWorld(PlayerChangedWorldEvent event) { // will portal into another world + updatePermissions(event.getPlayer(), event.getPlayer().getWorld().getName()); + } @EventHandler(priority = EventPriority.LOWEST) public void onPlayerPortal(PlayerPortalEvent event) { // will portal into another world From 3f02bcd702f890d1ccba35e2217b61d730ff9953 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Tue, 31 Jan 2012 03:16:34 +0000 Subject: [PATCH 04/21] Catch all errors in badly formatted groups. --- EssentialsGroupManager/.project | 2 +- EssentialsGroupManager/src/Changelog.txt | 3 ++- .../groupmanager/dataholder/WorldDataHolder.java | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/EssentialsGroupManager/.project b/EssentialsGroupManager/.project index 0562b3e0f..c0e5a6f5e 100644 --- a/EssentialsGroupManager/.project +++ b/EssentialsGroupManager/.project @@ -16,7 +16,7 @@ LaunchConfigHandle - <project>/.externalToolBuilders/New_Builder.launch + <project>/.externalToolBuilders/GroupManager.launch diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index 770dbe8e2..490df8fc6 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -132,4 +132,5 @@ v 1.9: - '*' - -vanish.* - vanish.standard - - Track the 'onPlayerChangeWorld' event as some teleports seem to not be triggering a world move. \ No newline at end of file + - Track the 'onPlayerChangeWorld' event as some teleports seem to not be triggering a world move. + - Catch all errors in badly formatted groups. \ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java index 4fe1daaa5..581f17770 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java @@ -445,7 +445,7 @@ public class WorldDataHolder { //PROCESS GROUPS FILE Map> inheritance = new HashMap>(); - //try { + try { Map allGroupsNode = (Map) groupsRootDataNode.get("groups"); for (String groupKey : allGroupsNode.keySet()) { Map thisGroupNode = (Map) allGroupsNode.get(groupKey); @@ -514,10 +514,11 @@ public class WorldDataHolder { }else throw new IllegalArgumentException("Unknown entry found in inheritance section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); } - //} catch (Exception ex) { - // ex.printStackTrace(); - // throw new IllegalArgumentException("Your Permissions config file is invalid. See console for details."); - //} + } catch (Exception ex) { + ex.printStackTrace(); + throw new IllegalArgumentException("Your " + groupsFile.getPath() + " file is invalid. See console for details."); + } + if (ph.getDefaultGroup() == null) { throw new IllegalArgumentException("There was no Default Group declared in file: " + groupsFile.getPath()); } From dbf30740fb95fdacc2d3f21faa2b1c54e2e28777 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Thu, 2 Feb 2012 02:01:04 +0000 Subject: [PATCH 05/21] Fix a bug with getWorldData return the main world data for all mirrors, instead of the worlds parent data. --- EssentialsGroupManager/src/Changelog.txt | 3 ++- .../org/anjocaido/groupmanager/GroupManager.java | 2 +- .../dataholder/worlds/WorldsHolder.java | 13 ++++++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index 490df8fc6..e48365de5 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -133,4 +133,5 @@ v 1.9: - -vanish.* - vanish.standard - Track the 'onPlayerChangeWorld' event as some teleports seem to not be triggering a world move. - - Catch all errors in badly formatted groups. \ No newline at end of file + - Catch all errors in badly formatted groups. + - Fix a bug with getWorldData return the main world data for all mirrors, instead of the worlds parent data. \ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java index 43b764faf..bb61b2145 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java @@ -1762,9 +1762,9 @@ public class GroupManager extends JavaPlugin { dataHolder = worldsHolder.getWorldData(worldsHolder.getDefaultWorld().getName()); permissionHandler = dataHolder.getPermissionsHandler(); - selectedWorlds.put(sender, dataHolder.getName()); if ((dataHolder != null) && (permissionHandler != null)) { + selectedWorlds.put(sender, dataHolder.getName()); sender.sendMessage(ChatColor.RED + "Couldn't retrieve your world. Default world '" + worldsHolder.getDefaultWorld().getName() + "' selected."); return true; } diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java index 686a5495d..6d819daa5 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java @@ -320,7 +320,8 @@ public class WorldsHolder { * If the world is not on the worlds list, returns the default world * holder. * - * Mirrors return original world data. + * Mirrors return their parent world data. + * If no mirroring data it returns the default world. * * @param worldName * @return OverloadedWorldHolder @@ -328,8 +329,17 @@ public class WorldsHolder { public OverloadedWorldHolder getWorldData(String worldName) { String worldNameLowered = worldName.toLowerCase(); + // Return this worlds data if (worldsData.containsKey(worldNameLowered)) return worldsData.get(worldNameLowered); + + // If groups mirrored return the parent worlds data + if (mirrorsGroup.containsKey(worldNameLowered)) + return worldsData.get(mirrorsGroup.get(worldNameLowered).toLowerCase()); + + // If users mirrored return the parent worlds data + if (mirrorsUser.containsKey(worldNameLowered)) + return worldsData.get(mirrorsUser.get(worldNameLowered).toLowerCase()); GroupManager.logger.finest("Requested world " + worldName + " not found or badly mirrored. Returning default world..."); return getDefaultWorld(); @@ -353,6 +363,7 @@ public class WorldsHolder { /** * Retrieves the field player.getWorld().getName() and do * getWorld(worldName) + * * @param player * @return OverloadedWorldHolder */ From a0103afde373e581ce4028b7c57bef7b21bfc780 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Thu, 2 Feb 2012 02:41:10 +0000 Subject: [PATCH 06/21] fix setGroup to only block superperms update if update is false. --- .../src/org/anjocaido/groupmanager/data/User.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/User.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/User.java index 980b0846c..30fe3f709 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/User.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/User.java @@ -138,8 +138,8 @@ public class User extends DataUnit implements Cloneable { String oldGroup = this.group; this.group = group.getName(); flagAsChanged(); - if (GroupManager.isLoaded() && (updatePerms)) { - if (!GroupManager.BukkitPermissions.isPlayer_join()) + if (GroupManager.isLoaded()) { + if (!GroupManager.BukkitPermissions.isPlayer_join() && (updatePerms)) GroupManager.BukkitPermissions.updatePlayer(getBukkitPlayer()); // Do we notify of the group change? From 76ba5caeec462b53eb9bffedec3c67b646eebb1c Mon Sep 17 00:00:00 2001 From: ElgarL Date: Thu, 2 Feb 2012 18:10:35 +0000 Subject: [PATCH 07/21] Prevent getAllPlayersPermissions() processing a group more than once. Improves performance when using complex inheritance structures. --- EssentialsGroupManager/src/Changelog.txt | 3 +- .../permissions/AnjoPermissionsHandler.java | 43 +++++++++++-------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index e48365de5..0ef3add6f 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -134,4 +134,5 @@ v 1.9: - vanish.standard - Track the 'onPlayerChangeWorld' event as some teleports seem to not be triggering a world move. - Catch all errors in badly formatted groups. - - Fix a bug with getWorldData return the main world data for all mirrors, instead of the worlds parent data. \ No newline at end of file + - Fix a bug with getWorldData return the main world data for all mirrors, instead of the worlds parent data. + - Prevent getAllPlayersPermissions() processing a group more than once. Improves performance when using complex inheritance structures. \ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java index 7436bec70..bd2829f38 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java @@ -121,27 +121,34 @@ public class AnjoPermissionsHandler extends PermissionsReaderInterface { // Add the players own permissions. playerPermArray.addAll(populatePerms(ph.getUser(userName).getPermissionList(), includeChildren)); + ArrayList alreadyProcessed = new ArrayList(); + // fetch all group permissions for (String group : getGroups(userName)) { - Set groupPermArray = new HashSet(); - - if (group.startsWith("g:") && GroupManager.getGlobalGroups().hasGroup(group)) { - // GlobalGroups - groupPermArray = populatePerms(GroupManager.getGlobalGroups().getGroupsPermissions(group), includeChildren); + // Don't process a group more than once. + if (!alreadyProcessed.contains(group)) { + alreadyProcessed.add(group); - } else { - // World Groups - groupPermArray = populatePerms(ph.getGroup(group).getPermissionList(), includeChildren); - } - - // Add all group permissions, unless negated by earlier permissions. - for (String perm : groupPermArray) { - boolean negated = (perm.startsWith("-")); - // Perm doesn't already exists and there is no negation for it - // or It's a negated perm where a normal perm doesn't exists (don't allow inheritance to negate higher perms) - if ((!negated && !playerPermArray.contains(perm) && !playerPermArray.contains("-" + perm)) - || (negated && !playerPermArray.contains(perm.substring(1)))) - playerPermArray.add(perm); + Set groupPermArray = new HashSet(); + + if (group.startsWith("g:") && GroupManager.getGlobalGroups().hasGroup(group)) { + // GlobalGroups + groupPermArray = populatePerms(GroupManager.getGlobalGroups().getGroupsPermissions(group), includeChildren); + + } else { + // World Groups + groupPermArray = populatePerms(ph.getGroup(group).getPermissionList(), includeChildren); + } + + // Add all group permissions, unless negated by earlier permissions. + for (String perm : groupPermArray) { + boolean negated = (perm.startsWith("-")); + // Perm doesn't already exists and there is no negation for it + // or It's a negated perm where a normal perm doesn't exists (don't allow inheritance to negate higher perms) + if ((!negated && !playerPermArray.contains(perm) && !playerPermArray.contains("-" + perm)) + || (negated && !playerPermArray.contains(perm.substring(1)))) + playerPermArray.add(perm); + } } } From e93e50f6d273b940783e7c313610f4cfa7ed15e2 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Sun, 5 Feb 2012 16:30:58 +0000 Subject: [PATCH 08/21] Fix world mirroring so it correctly creates data files and data sources for partially mirrored worlds. Fixed world mirroring so it returns the correct data for the requested world --- EssentialsGroupManager/src/Changelog.txt | 4 +- .../anjocaido/groupmanager/GroupManager.java | 5 +- .../anjocaido/groupmanager/data/DataUnit.java | 9 ++ .../dataholder/GroupsDataHolder.java | 22 ++- .../dataholder/UsersDataHolder.java | 23 +++- .../dataholder/WorldDataHolder.java | 102 ++++++++------ .../dataholder/worlds/WorldsHolder.java | 128 +++++++++++++++--- 7 files changed, 216 insertions(+), 77 deletions(-) diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index 0ef3add6f..1e520efb3 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -135,4 +135,6 @@ v 1.9: - Track the 'onPlayerChangeWorld' event as some teleports seem to not be triggering a world move. - Catch all errors in badly formatted groups. - Fix a bug with getWorldData return the main world data for all mirrors, instead of the worlds parent data. - - Prevent getAllPlayersPermissions() processing a group more than once. Improves performance when using complex inheritance structures. \ No newline at end of file + - Prevent getAllPlayersPermissions() processing a group more than once. Improves performance when using complex inheritance structures. + - Fix world mirroring so it correctly creates data files and data sources for partially mirrored worlds. + - Fixed world mirroring so it returns the correct data for the requested world \ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java index bb61b2145..ab1ebebbb 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java @@ -1485,7 +1485,7 @@ public class GroupManager extends JavaPlugin { try { worldsHolder.saveChanges(forced); - sender.sendMessage(ChatColor.YELLOW + " The changes were saved."); + sender.sendMessage(ChatColor.YELLOW + " All changes were saved."); } catch (IllegalStateException ex) { sender.sendMessage(ChatColor.RED + ex.getMessage()); } @@ -1522,6 +1522,7 @@ public class GroupManager extends JavaPlugin { } // WORKING config.load(); + globalGroups.load(); worldsHolder.mirrorSetUp(); isLoaded = false; @@ -1538,7 +1539,7 @@ public class GroupManager extends JavaPlugin { sender.sendMessage("The request to world '" + auxString + "' was sent."); } else { worldsHolder.reloadAll(); - sender.sendMessage(ChatColor.YELLOW + " The current world was reloaded."); + sender.sendMessage(ChatColor.YELLOW + " All worlds were reloaded."); } isLoaded = true; diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java index a35b5aeee..03d31b848 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java @@ -65,6 +65,15 @@ public abstract class DataUnit { hash = 71 * hash + (this.name != null ? this.name.toLowerCase().hashCode() : 0); return hash; } + + /** + * Set the data source to point to a new worldDataHolder + * + * @param source + */ + public void setDataSource(WorldDataHolder source) { + this.dataSource = source; + } /** * @return the dataSource diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java index 4fc819245..444939251 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java @@ -17,7 +17,8 @@ public class GroupsDataHolder { /** * Root World name this set of groups is associated with. */ - private String name; + //private String name; + private WorldDataHolder dataSource; private Group defaultGroup = null; private File groupsFile; private boolean haveGroupsChanged = false; @@ -33,17 +34,24 @@ public class GroupsDataHolder { */ protected GroupsDataHolder() { } - - protected void setWorldName(String worldName) { - name = worldName; + + public void setDataSource(WorldDataHolder dataSource) { + this.dataSource = dataSource; + //push this data source to the users, so they pull the correct groups data. + for (Group group : groups.values()) + group.setDataSource(this.dataSource); } + //protected void setWorldName(String worldName) { + // name = worldName; + //} + /** * @return the name */ - public String getWorldName() { - return name; - } + //public String getWorldName() { + // return name; + //} /** * @return the defaultGroup diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java index 37e1c4b43..1d7bbb704 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java @@ -17,7 +17,8 @@ public class UsersDataHolder { /** * Root World name this set of groups is associated with. */ - private String name; + //private String name; + private WorldDataHolder dataSource; private File usersFile; private boolean haveUsersChanged = false; private long timeStampUsers = 0; @@ -32,20 +33,28 @@ public class UsersDataHolder { */ protected UsersDataHolder() { } + + public void setDataSource(WorldDataHolder dataSource) { + this.dataSource = dataSource; + //push this data source to the users, so they pull the correct groups data. + for (User user : users.values()) + user.setDataSource(this.dataSource); + + } /** * @param worldName */ - public void setWorldName(String worldName) { - this.name = worldName; - } + //public void setWorldName(String worldName) { + // this.name = worldName; + //} /** * @return the name */ - public String getWorldName() { - return this.name; - } + //public String getWorldName() { + // return this.name; + //} /** * @return the users diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java index 581f17770..69305f360 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java @@ -80,6 +80,16 @@ public class WorldDataHolder { //this.defaultGroup = defaultGroup; } + + /** + * update the dataSource to point to this object. + * + * This should be called whenever a set of world data is fetched. + */ + public void updateDataSource() { + this.groups.setDataSource(this); + this.users.setDataSource(this); + } /** * Search for a user. If it doesn't exist, create a new one with @@ -465,54 +475,66 @@ public class WorldDataHolder { } //PERMISSIONS NODE - if (thisGroupNode.get("permissions") == null) { - thisGroupNode.put("permissions", new ArrayList()); - } else { - if (thisGroupNode.get("permissions") instanceof List) { - for (Object o : ((List) thisGroupNode.get("permissions"))) { - try { - thisGrp.addPermission(o.toString()); - } catch (NullPointerException e) { - // Ignore this entry as it's null. - //throw new IllegalArgumentException("Invalid permission node in group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); - } - } - } else if (thisGroupNode.get("permissions") instanceof String) { - thisGrp.addPermission((String) thisGroupNode.get("permissions")); + try { + if (thisGroupNode.get("permissions") == null) { + thisGroupNode.put("permissions", new ArrayList()); } else { - throw new IllegalArgumentException("Unknown type of permissions node(Should be String or List) for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + if (thisGroupNode.get("permissions") instanceof List) { + for (Object o : ((List) thisGroupNode.get("permissions"))) { + try { + thisGrp.addPermission(o.toString()); + } catch (NullPointerException e) { + // Ignore this entry as it's null. + //throw new IllegalArgumentException("Invalid permission node in group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } + } + } else if (thisGroupNode.get("permissions") instanceof String) { + thisGrp.addPermission((String) thisGroupNode.get("permissions")); + } else { + throw new IllegalArgumentException("Unknown type of permissions node(Should be String or List) for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } + thisGrp.sortPermissions(); } - thisGrp.sortPermissions(); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid formatting found in permissions section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); } //INFO NODE - if (thisGroupNode.get("info") instanceof Map) { - Map infoNode = (Map) thisGroupNode.get("info"); - if (infoNode != null) { - thisGrp.setVariables(infoNode); - } - } else - throw new IllegalArgumentException("Unknown entry found in Info section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + try { + if (thisGroupNode.get("info") instanceof Map) { + Map infoNode = (Map) thisGroupNode.get("info"); + if (infoNode != null) { + thisGrp.setVariables(infoNode); + } + } else + throw new IllegalArgumentException("Unknown entry found in Info section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } catch (Exception e1) { + throw new IllegalArgumentException("Invalid formatting found in info section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } //END INFO NODE - if (thisGroupNode.get("inheritance") == null || thisGroupNode.get("inheritance") instanceof List) { - Object inheritNode = thisGroupNode.get("inheritance"); - if (inheritNode == null) { - thisGroupNode.put("inheritance", new ArrayList()); - } else if (inheritNode instanceof List) { - List groupsInh = (List) inheritNode; - for (String grp : groupsInh) { - if (inheritance.get(groupKey) == null) { - List thisInherits = new ArrayList(); - inheritance.put(groupKey, thisInherits); - } - inheritance.get(groupKey).add(grp); - - } - } - }else - throw new IllegalArgumentException("Unknown entry found in inheritance section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + try { + if (thisGroupNode.get("inheritance") == null || thisGroupNode.get("inheritance") instanceof List) { + Object inheritNode = thisGroupNode.get("inheritance"); + if (inheritNode == null) { + thisGroupNode.put("inheritance", new ArrayList()); + } else if (inheritNode instanceof List) { + List groupsInh = (List) inheritNode; + for (String grp : groupsInh) { + if (inheritance.get(groupKey) == null) { + List thisInherits = new ArrayList(); + inheritance.put(groupKey, thisInherits); + } + inheritance.get(groupKey).add(grp); + + } + } + }else + throw new IllegalArgumentException("Unknown entry found in inheritance section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } catch (Exception e2) { + throw new IllegalArgumentException("Invalid formatting found in inheritance section for group: " + thisGrp.getName() + " in file: " + groupsFile.getPath()); + } } } catch (Exception ex) { ex.printStackTrace(); diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java index 6d819daa5..e72118468 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/worlds/WorldsHolder.java @@ -10,6 +10,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; @@ -45,7 +46,7 @@ public class WorldsHolder { private Map mirrorsGroup = new HashMap(); private Map mirrorsUser = new HashMap(); - private OverloadedWorldHolder defaultWorld; + //private OverloadedWorldHolder defaultWorld; private String serverDefaultWorldName; private GroupManager plugin; private File worldsFolder; @@ -59,7 +60,7 @@ public class WorldsHolder { // Setup folders and check files exist for the primary world verifyFirstRun(); initialLoad(); - if (defaultWorld == null) { + if (serverDefaultWorldName == null) { throw new IllegalStateException("There is no default group! OMG!"); } } @@ -76,7 +77,7 @@ public class WorldsHolder { private void initialWorldLoading() { //Load the default world loadWorld(serverDefaultWorldName); - defaultWorld = worldsData.get(serverDefaultWorldName); + //defaultWorld = getUpdatedWorldData(serverDefaultWorldName); } private void loadAllSearchedWorlds() { @@ -117,6 +118,8 @@ public class WorldsHolder { mirrorsGroup.clear(); mirrorsUser.clear(); Map mirrorsMap = plugin.getGMConfig().getMirrorsMap(); + + HashSet mirroredWorlds = new HashSet(); if (mirrorsMap != null) { for (String source : mirrorsMap.keySet()) { @@ -140,6 +143,10 @@ public class WorldsHolder { } mirrorsGroup.put(world, getWorldData(source).getName()); mirrorsUser.put(world, getWorldData(source).getName()); + + // Track this world so we can create a datasource for it later + mirroredWorlds.add(o.toString()); + } else GroupManager.logger.log(Level.WARNING, "Mirroring error with " + o.toString() + ". Recursive loop detected!"); } @@ -171,11 +178,13 @@ public class WorldsHolder { if (type.equals("users")) mirrorsUser.put(key.toLowerCase(), getWorldData(source).getName()); } + + // Track this world so we can create a datasource for it later + mirroredWorlds.add(key); + } else GroupManager.logger.log(Level.WARNING, "Mirroring error with " + key + ". Recursive loop detected!"); - - } else { throw new IllegalStateException("Unknown mirroring format for " + key); } @@ -183,6 +192,14 @@ public class WorldsHolder { } } } + + // Create a datasource for any worlds not already loaded + for (String world : mirroredWorlds){ + if (!worldsData.containsKey(world.toLowerCase())) { + setupWorldFolder(world); + loadWorld(world, true); + } + } } } @@ -329,21 +346,55 @@ public class WorldsHolder { public OverloadedWorldHolder getWorldData(String worldName) { String worldNameLowered = worldName.toLowerCase(); - // Return this worlds data - if (worldsData.containsKey(worldNameLowered)) - return worldsData.get(worldNameLowered); + // Find this worlds data + if (worldsData.containsKey(worldNameLowered)) { + + String usersMirror = mirrorsUser.get(worldNameLowered); + String groupsMirror = mirrorsGroup.get(worldNameLowered); + + if (usersMirror != null) { + + // If both are mirrored + if (groupsMirror != null) { + + // if the data sources are the same, return the parent + if (usersMirror == groupsMirror) + return getUpdatedWorldData(usersMirror.toLowerCase()); + + // Both data sources are mirrors, but they are from different parents + // so we return the actual data object. + return getUpdatedWorldData(worldNameLowered); + } + + // Groups isn't a mirror so return this this worlds data source + return getUpdatedWorldData(worldNameLowered); + } + + // users isn't mirrored so we need to return this worlds data source + return getUpdatedWorldData(worldNameLowered); + } - // If groups mirrored return the parent worlds data - if (mirrorsGroup.containsKey(worldNameLowered)) - return worldsData.get(mirrorsGroup.get(worldNameLowered).toLowerCase()); - - // If users mirrored return the parent worlds data - if (mirrorsUser.containsKey(worldNameLowered)) - return worldsData.get(mirrorsUser.get(worldNameLowered).toLowerCase()); - + // Oddly no data source was found for this world so return the default. GroupManager.logger.finest("Requested world " + worldName + " not found or badly mirrored. Returning default world..."); return getDefaultWorld(); } + + /** + * Get the requested world data and update it's dataSource to be relevant for this world + * + * @param worldName + * @return updated world holder + */ + private OverloadedWorldHolder getUpdatedWorldData(String worldName) { + + if (worldsData.containsKey(worldName.toLowerCase())) { + OverloadedWorldHolder data = worldsData.get(worldName.toLowerCase()); + data.updateDataSource(); + return data; + } + return null; + + } /** * Do a matching of playerName, if its found only one player, do @@ -487,18 +538,29 @@ public class WorldsHolder { } /** + * Wrapper for LoadWorld(String,Boolean) for backwards compatibility + * * Load a world from file. * If it already been loaded, summon reload method from dataHolder. * @param worldName */ public void loadWorld(String worldName) { + loadWorld(worldName, false); + } + + /** + * Load a world from file. + * If it already been loaded, summon reload method from dataHolder. + * @param worldName + */ + public void loadWorld(String worldName, Boolean isMirror) { if (worldsData.containsKey(worldName.toLowerCase())) { worldsData.get(worldName.toLowerCase()).reload(); return; } GroupManager.logger.finest("Trying to load world " + worldName + "..."); File thisWorldFolder = new File(worldsFolder, worldName); - if (thisWorldFolder.exists() && thisWorldFolder.isDirectory()) { + if ((isMirror) || (thisWorldFolder.exists() && thisWorldFolder.isDirectory())) { // Setup file handles, if not mirrored File groupsFile = (mirrorsGroup.containsKey(worldName.toLowerCase()))? null : new File(thisWorldFolder, "groups.yml"); @@ -575,17 +637,43 @@ public class WorldsHolder { * @return the defaultWorld */ public OverloadedWorldHolder getDefaultWorld() { - return defaultWorld; + return getUpdatedWorldData(serverDefaultWorldName); } /** - * Returns all physically loaded worlds. + * Returns all physically loaded worlds which have at least + * one of their own data sets for users or groups. + * * @return ArrayList of all loaded worlds */ public ArrayList allWorldsDataList() { ArrayList list = new ArrayList(); for (OverloadedWorldHolder data : worldsData.values()) { - if (!list.contains(data)) { + if ((!list.contains(data)) && (!mirrorsGroup.containsKey(data.getName().toLowerCase()) || !mirrorsUser.containsKey(data.getName().toLowerCase()))) { + + String worldNameLowered = data.getName().toLowerCase(); + String usersMirror = mirrorsUser.get(worldNameLowered); + String groupsMirror = mirrorsGroup.get(worldNameLowered); + + // is users mirrored? + if (usersMirror != null) { + + // If both are mirrored + if (groupsMirror != null) { + + // if the data sources are the same, return the parent + if (usersMirror == groupsMirror) { + if (!list.contains(usersMirror.toLowerCase())) + list.add(worldsData.get(usersMirror.toLowerCase())); + continue; + } + // Both data sources are mirrors, but they are from different parents + // so fall through to add the actual data object. + } + // Groups isn't a mirror so fall through to add this this worlds data source + } + + // users isn't mirrored so we need to add this worlds data source list.add(data); } } From 97bd49e598ddb4725a19788098158c7bf9f1a55f Mon Sep 17 00:00:00 2001 From: ElgarL Date: Sun, 5 Feb 2012 16:41:34 +0000 Subject: [PATCH 09/21] Add some commenting --- .../anjocaido/groupmanager/data/DataUnit.java | 4 +++- .../dataholder/GroupsDataHolder.java | 17 ++-------------- .../dataholder/UsersDataHolder.java | 20 ++----------------- .../dataholder/WorldDataHolder.java | 7 +++++-- 4 files changed, 12 insertions(+), 36 deletions(-) diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java index 03d31b848..e3250a1c1 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/data/DataUnit.java @@ -67,7 +67,7 @@ public abstract class DataUnit { } /** - * Set the data source to point to a new worldDataHolder + * Set the data source to point to a different worldDataHolder * * @param source */ @@ -76,6 +76,8 @@ public abstract class DataUnit { } /** + * Get the current worldDataHolder this object is pointing to + * * @return the dataSource */ public WorldDataHolder getDataSource() { diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java index 444939251..5d681013e 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/GroupsDataHolder.java @@ -9,15 +9,13 @@ import org.anjocaido.groupmanager.data.Group; /** + * This container holds all Groups loaded from the relevant groupsFile. + * * @author ElgarL * */ public class GroupsDataHolder { - /** - * Root World name this set of groups is associated with. - */ - //private String name; private WorldDataHolder dataSource; private Group defaultGroup = null; private File groupsFile; @@ -42,17 +40,6 @@ public class GroupsDataHolder { group.setDataSource(this.dataSource); } - //protected void setWorldName(String worldName) { - // name = worldName; - //} - - /** - * @return the name - */ - //public String getWorldName() { - // return name; - //} - /** * @return the defaultGroup */ diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java index 1d7bbb704..fa2ccaf84 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/UsersDataHolder.java @@ -9,15 +9,13 @@ import org.anjocaido.groupmanager.data.User; /** + * This container holds all Users loaded from the relevant usersFile. + * * @author ElgarL * */ public class UsersDataHolder { - /** - * Root World name this set of groups is associated with. - */ - //private String name; private WorldDataHolder dataSource; private File usersFile; private boolean haveUsersChanged = false; @@ -42,20 +40,6 @@ public class UsersDataHolder { } - /** - * @param worldName - */ - //public void setWorldName(String worldName) { - // this.name = worldName; - //} - - /** - * @return the name - */ - //public String getWorldName() { - // return this.name; - //} - /** * @return the users */ diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java index 69305f360..8115b1a75 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/dataholder/WorldDataHolder.java @@ -36,8 +36,11 @@ import org.yaml.snakeyaml.constructor.SafeConstructor; import org.yaml.snakeyaml.reader.UnicodeReader; /** - * - * @author gabrielcouto + * One instance of this should exist per world/mirror + * it contains all functions to manage these data sets + * and points to the relevant users and groups objects. + * + * @author gabrielcouto, ElgarL */ public class WorldDataHolder { From 691a0ef4ce21b66cd948dc234d8659b8f8a422db Mon Sep 17 00:00:00 2001 From: KHobbits Date: Thu, 9 Feb 2012 02:11:36 +0000 Subject: [PATCH 10/21] Fixing silly typo - Fixes shout costs. --- EssentialsChat/src/com/earth2me/essentials/chat/ChatStore.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EssentialsChat/src/com/earth2me/essentials/chat/ChatStore.java b/EssentialsChat/src/com/earth2me/essentials/chat/ChatStore.java index 38239abfe..d353d5d6c 100644 --- a/EssentialsChat/src/com/earth2me/essentials/chat/ChatStore.java +++ b/EssentialsChat/src/com/earth2me/essentials/chat/ChatStore.java @@ -36,7 +36,7 @@ public class ChatStore public String getLongType() { - return type.length() > 0 ? "chat" : "chat-" + type; + return type.length() == 0 ? "chat" : "chat-" + type; } public long getRadius() From 83f9209bcc3edb20d86975ae33e608005ece555b Mon Sep 17 00:00:00 2001 From: KHobbits Date: Thu, 9 Feb 2012 22:02:24 +0000 Subject: [PATCH 11/21] Optional argument to /ping [message]- Message to be echo'd. Possible use in scripts, checking for lag, /sudo, etc. --- .../earth2me/essentials/commands/Commandping.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandping.java b/Essentials/src/com/earth2me/essentials/commands/Commandping.java index 1fad701b2..9c90866d6 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandping.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandping.java @@ -1,8 +1,9 @@ package com.earth2me.essentials.commands; import static com.earth2me.essentials.I18n._; -import com.earth2me.essentials.User; +import com.earth2me.essentials.Util; import org.bukkit.Server; +import org.bukkit.command.CommandSender; public class Commandping extends EssentialsCommand @@ -13,8 +14,16 @@ public class Commandping extends EssentialsCommand } @Override - public void run(Server server, User player, String commandLabel, String[] args) throws Exception + public void run(final Server server, final CommandSender sender, final String commandLabel, final String[] args) throws Exception { - player.sendMessage(_("pong")); + if (args.length < 1) + { + + sender.sendMessage(_("pong")); + } + else + { + sender.sendMessage(getFinalArg(args, 0)); + } } } From b3fc7900009746ad2b5a007b045c0a9d3d015008 Mon Sep 17 00:00:00 2001 From: KHobbits Date: Thu, 9 Feb 2012 22:11:46 +0000 Subject: [PATCH 12/21] New Permission: essentials.sudo.exempt If a user has this perm, they cannot be controlled. --- .../src/com/earth2me/essentials/commands/Commandsudo.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandsudo.java b/Essentials/src/com/earth2me/essentials/commands/Commandsudo.java index 7f758ad2e..86394e502 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandsudo.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandsudo.java @@ -30,7 +30,13 @@ public class Commandsudo extends EssentialsCommand } //TODO: Translate this. - sender.sendMessage("Running the command as " + user.getDisplayName()); + if (user.isAuthorized("essentials.sudo.exempt")) + { + throw new Exception("You cannot sudo this user"); + } + + //TODO: Translate this. + sender.sendMessage("Forcing " + user.getDisplayName() + " to run: /" + command + " " + arguments); final PluginCommand execCommand = ess.getServer().getPluginCommand(command); if (execCommand != null) From f0ee026fb97ac69822cd3f2f74b5e088ba7b3b66 Mon Sep 17 00:00:00 2001 From: KHobbits Date: Thu, 9 Feb 2012 22:13:00 +0000 Subject: [PATCH 13/21] Allow colour codes in /ping --- .../src/com/earth2me/essentials/commands/Commandping.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandping.java b/Essentials/src/com/earth2me/essentials/commands/Commandping.java index 9c90866d6..0956f4082 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandping.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandping.java @@ -23,7 +23,7 @@ public class Commandping extends EssentialsCommand } else { - sender.sendMessage(getFinalArg(args, 0)); + sender.sendMessage(Util.replaceColor(getFinalArg(args, 0))); } } } From 9efd0eb6f9f61b7063c469ec69148949c268a007 Mon Sep 17 00:00:00 2001 From: Wolvereness Date: Thu, 9 Feb 2012 23:14:57 -0600 Subject: [PATCH 14/21] Fix exploit with /tpaccept if sender no longer has permission --- .../src/com/earth2me/essentials/commands/Commandtpaccept.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandtpaccept.java b/Essentials/src/com/earth2me/essentials/commands/Commandtpaccept.java index 2e3e024a3..456a77c37 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandtpaccept.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandtpaccept.java @@ -22,7 +22,7 @@ public class Commandtpaccept extends EssentialsCommand final User target = user.getTeleportRequest(); if (target == null || target.getBase() instanceof OfflinePlayer - || (user.isTeleportRequestHere() && !target.isAuthorized("essentials.tpahere"))) + || (user.isTeleportRequestHere() ? !target.isAuthorized("essentials.tpahere") : !target.isAuthorized("essentials.tpa"))) { throw new Exception(_("noPendingRequest")); } From c0517c120369ac6a1de954c9d049bd0a88ff8ea6 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Sat, 11 Feb 2012 10:36:55 +0000 Subject: [PATCH 15/21] Change Service registration to register WorldsHolder instead of AnjoPermissionsHandler. This is the correct entry point for all data. --- EssentialsGroupManager/src/Changelog.txt | 3 ++- .../src/org/anjocaido/groupmanager/GroupManager.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/EssentialsGroupManager/src/Changelog.txt b/EssentialsGroupManager/src/Changelog.txt index 1e520efb3..b79d56d07 100644 --- a/EssentialsGroupManager/src/Changelog.txt +++ b/EssentialsGroupManager/src/Changelog.txt @@ -137,4 +137,5 @@ v 1.9: - Fix a bug with getWorldData return the main world data for all mirrors, instead of the worlds parent data. - Prevent getAllPlayersPermissions() processing a group more than once. Improves performance when using complex inheritance structures. - Fix world mirroring so it correctly creates data files and data sources for partially mirrored worlds. - - Fixed world mirroring so it returns the correct data for the requested world \ No newline at end of file + - Fixed world mirroring so it returns the correct data for the requested world. + - Change Service registration to register WorldsHolder instead of AnjoPermissionsHandler. This is the correct entry point for all data. \ No newline at end of file diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java index ab1ebebbb..b87d1de8c 100644 --- a/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java +++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/GroupManager.java @@ -158,7 +158,7 @@ public class GroupManager extends JavaPlugin { System.out.println(pdfFile.getName() + " version " + pdfFile.getVersion() + " is enabled!"); // Register as a service - this.getServer().getServicesManager().register(AnjoPermissionsHandler.class, this.permissionHandler, this, ServicePriority.Lowest); + this.getServer().getServicesManager().register(WorldsHolder.class, this.worldsHolder, this, ServicePriority.Lowest); } public static boolean isLoaded() { From c890ea8f87b2d798cfe4b1bbefdc8b62fd227592 Mon Sep 17 00:00:00 2001 From: Jeff Wardian Date: Fri, 10 Feb 2012 15:54:19 -0800 Subject: [PATCH 16/21] Added PrivilegesHandler.java; Implemented privileges in PermissionsHandler.java; Fixed PrivilegesHandler.canBuild(); --- Essentials/nbproject/project.properties | 4 +- .../essentials/perm/PermissionsHandler.java | 11 ++++ .../essentials/perm/PrivilegesHandler.java | 61 ++++++++++++++++++ lib/Privileges.jar | Bin 0 -> 101774 bytes 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 Essentials/src/com/earth2me/essentials/perm/PrivilegesHandler.java create mode 100644 lib/Privileges.jar diff --git a/Essentials/nbproject/project.properties b/Essentials/nbproject/project.properties index 4e80ceafa..71fea5cf9 100644 --- a/Essentials/nbproject/project.properties +++ b/Essentials/nbproject/project.properties @@ -76,6 +76,7 @@ file.reference.MultiCurrency.jar=../lib/MultiCurrency.jar file.reference.Permissions3.jar=../lib/Permissions3.jar file.reference.PermissionsBukkit-1.2.jar=../lib/PermissionsBukkit-1.2.jar file.reference.PermissionsEx.jar=../lib/PermissionsEx.jar +file.reference.Privileges.jar=..\\lib\\Privileges.jar file.reference.Vault.jar=../lib/Vault.jar includes=** jar.archive.disabled=${jnlp.enabled} @@ -95,7 +96,8 @@ javac.classpath=\ ${reference.EssentialsGroupManager.jar}:\ ${file.reference.bukkit.jar}:\ ${file.reference.craftbukkit.jar}:\ - ${file.reference.Vault.jar} + ${file.reference.Vault.jar}:\ + ${file.reference.Privileges.jar} # Space-separated list of extra javac options javac.compilerargs= javac.deprecation=false diff --git a/Essentials/src/com/earth2me/essentials/perm/PermissionsHandler.java b/Essentials/src/com/earth2me/essentials/perm/PermissionsHandler.java index 8c16aab7a..aa786934e 100644 --- a/Essentials/src/com/earth2me/essentials/perm/PermissionsHandler.java +++ b/Essentials/src/com/earth2me/essentials/perm/PermissionsHandler.java @@ -144,6 +144,17 @@ public class PermissionsHandler implements IPermissionsHandler return; } + final Plugin privPlugin = pluginManager.getPlugin("Privileges"); + if (privPlugin != null && privPlugin.isEnabled()) + { + if (!(handler instanceof PrivilegesHandler)) + { + LOGGER.log(Level.INFO, "Essentials: Using Privileges based permissions."); + handler = new PrivilegesHandler(privPlugin); + } + return; + } + final Plugin permPlugin = pluginManager.getPlugin("Permissions"); if (permPlugin != null && permPlugin.isEnabled()) { diff --git a/Essentials/src/com/earth2me/essentials/perm/PrivilegesHandler.java b/Essentials/src/com/earth2me/essentials/perm/PrivilegesHandler.java new file mode 100644 index 000000000..c81f93cbc --- /dev/null +++ b/Essentials/src/com/earth2me/essentials/perm/PrivilegesHandler.java @@ -0,0 +1,61 @@ +package com.earth2me.essentials.perm; + +import java.util.ArrayList; +import java.util.List; +import net.krinsoft.privileges.Privileges; +import net.krinsoft.privileges.groups.Group; +import net.krinsoft.privileges.groups.GroupManager; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; + +public class PrivilegesHandler extends SuperpermsHandler +{ + private final transient Privileges plugin; + private final GroupManager manager; + + public PrivilegesHandler(final Plugin plugin) + { + this.plugin = (Privileges) plugin; + this.manager = this.plugin.getGroupManager(); + } + + @Override + public String getGroup(final Player base) + { + Group group = manager.getGroup(base); + if (group == null) + { + return null; + } + return group.getName(); + } + + @Override + public List getGroups(final Player base) + { + Group group = manager.getGroup(base); + if (group == null) + { + return new ArrayList(); + } + return group.getGroupTree(); + } + + @Override + public boolean inGroup(final Player base, final String group) + { + Group pGroup = manager.getGroup(base); + if (pGroup == null) + { + return false; + } + return pGroup.isMemberOf(group); + } + + @Override + public boolean canBuild(Player base, String group) + { + return base.hasPermission("essentials.build") || base.hasPermission("privileges.build"); + } + +} diff --git a/lib/Privileges.jar b/lib/Privileges.jar new file mode 100644 index 0000000000000000000000000000000000000000..e9dd1d04df17ea27ae17524def701303944e8c8f GIT binary patch literal 101774 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

M=uQtQ-A3V8K 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 ZBF^h@!KxSpVgml6!CvaL6Ic?5{2vQ+rPcrd literal 0 HcmV?d00001 From b0d06ce6ed62657e3f6b541aa63079f8fadc1126 Mon Sep 17 00:00:00 2001 From: KHobbits Date: Sat, 11 Feb 2012 20:10:19 +0000 Subject: [PATCH 17/21] Refactoring tpaccept perm check to include tpaall. --- .../src/com/earth2me/essentials/commands/Commandtpaccept.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandtpaccept.java b/Essentials/src/com/earth2me/essentials/commands/Commandtpaccept.java index 456a77c37..891742043 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandtpaccept.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandtpaccept.java @@ -22,7 +22,9 @@ public class Commandtpaccept extends EssentialsCommand final User target = user.getTeleportRequest(); if (target == null || target.getBase() instanceof OfflinePlayer - || (user.isTeleportRequestHere() ? !target.isAuthorized("essentials.tpahere") : !target.isAuthorized("essentials.tpa"))) + || (user.isTeleportRequestHere() && !target.isAuthorized("essentials.tpahere")) + || (!user.isTeleportRequestHere() && !target.isAuthorized("essentials.tpa") && !target.isAuthorized("essentials.tpaall")) + ) { throw new Exception(_("noPendingRequest")); } From 2d56de1483a8dbd75cba146fae4a0dbe4270b1e3 Mon Sep 17 00:00:00 2001 From: KHobbits Date: Sat, 11 Feb 2012 21:15:26 +0000 Subject: [PATCH 18/21] Update trade signs properly, and visibly handle full signs. --- .../earth2me/essentials/signs/SignTrade.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/signs/SignTrade.java b/Essentials/src/com/earth2me/essentials/signs/SignTrade.java index 943a14a83..6b47ebc76 100644 --- a/Essentials/src/com/earth2me/essentials/signs/SignTrade.java +++ b/Essentials/src/com/earth2me/essentials/signs/SignTrade.java @@ -36,7 +36,7 @@ public class SignTrade extends EssentialsSign try { stored = getTrade(sign, 1, true, true, ess); - substractAmount(sign, 1, stored, ess); + subtractAmount(sign, 1, stored, ess); stored.pay(player); } catch (SignException e) @@ -53,12 +53,14 @@ public class SignTrade extends EssentialsSign final Trade charge = getTrade(sign, 1, false, false, ess); final Trade trade = getTrade(sign, 2, false, true, ess); charge.isAffordableFor(player); + addAmount(sign, 1, charge, ess); + subtractAmount(sign, 2, trade, ess); if (!trade.pay(player, false)) { + subtractAmount(sign, 1, charge, ess); + addAmount(sign, 2, trade, ess); throw new ChargeException("Full inventory"); } - substractAmount(sign, 2, trade, ess); - addAmount(sign, 1, charge, ess); charge.charge(player); Trade.log("Sign", "Trade", "Interact", sign.getLine(3), charge, username, trade, sign.getBlock().getLocation(), ess); } @@ -256,7 +258,7 @@ public class SignTrade extends EssentialsSign throw new SignException(_("invalidSignLine", index + 1)); } - protected final void substractAmount(final ISign sign, final int index, final Trade trade, final IEssentials ess) throws SignException + protected final void subtractAmount(final ISign sign, final int index, final Trade trade, final IEssentials ess) throws SignException { final Double money = trade.getMoney(); if (money != null) @@ -294,6 +296,7 @@ public class SignTrade extends EssentialsSign } } + //TODO: Translate these exceptions. private void changeAmount(final ISign sign, final int index, final double value, final IEssentials ess) throws SignException { @@ -313,7 +316,7 @@ public class SignTrade extends EssentialsSign final String newline = Util.formatCurrency(money, ess) + ":" + Util.formatCurrency(amount + value, ess).substring(1); if (newline.length() > 15) { - throw new SignException("Line too long!"); + throw new SignException("This sign is full: Line too long!"); } sign.setLine(index, newline); return; @@ -329,7 +332,7 @@ public class SignTrade extends EssentialsSign final String newline = stackamount + " " + split[1] + ":" + (amount + Math.round(value)); if (newline.length() > 15) { - throw new SignException("Line too long!"); + throw new SignException("This sign is full: Line too long!"); } sign.setLine(index, newline); return; @@ -343,7 +346,7 @@ public class SignTrade extends EssentialsSign final String newline = stackamount + " " + split[1] + ":" + (amount + Math.round(value)); if (newline.length() > 15) { - throw new SignException("Line too long!"); + throw new SignException("This sign is full: Line too long!"); } sign.setLine(index, newline); return; From 62cd219b4ecd48464037dd898ed14ab7de4972b2 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 11 Feb 2012 13:45:15 +1100 Subject: [PATCH 19/21] Clean up the CommandException stack traces so they appear as if Essentials was never there. --- .../com/earth2me/essentials/Essentials.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/Essentials.java b/Essentials/src/com/earth2me/essentials/Essentials.java index 21f2e38ea..3ee7c1777 100644 --- a/Essentials/src/com/earth2me/essentials/Essentials.java +++ b/Essentials/src/com/earth2me/essentials/Essentials.java @@ -32,15 +32,20 @@ import com.earth2me.essentials.signs.SignPlayerListener; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.lang.reflect.Array; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.bukkit.ChatColor; import org.bukkit.Server; import org.bukkit.World; import org.bukkit.command.Command; +import org.bukkit.command.CommandException; import org.bukkit.command.CommandSender; import org.bukkit.command.PluginCommand; import org.bukkit.entity.Player; @@ -277,7 +282,29 @@ public class Essentials extends JavaPlugin implements IEssentials if (pc != null) { alternativeCommandsHandler.executed(commandLabel, pc.getLabel()); - return pc.execute(sender, commandLabel, args); + try + { + return pc.execute(sender, commandLabel, args); + } + catch (final Exception ex) + { + final ArrayList elements = new ArrayList(Arrays.asList(ex.getStackTrace())); + elements.remove(0); + final ArrayList toRemove = new ArrayList(); + for (final StackTraceElement e : elements) + { + if (e.getClassName().equals("com.earth2me.essentials.Essentials")) + { + toRemove.add(e); + } + } + elements.removeAll(toRemove); + final StackTraceElement[] trace = elements.toArray(new StackTraceElement[elements.size()]); + ex.setStackTrace(trace); + ex.printStackTrace(); + sender.sendMessage(ChatColor.RED + "An internal error occurred while attempting to perform this command"); + return true; + } } } From 2699e02f96e7ab989bf518685eac3408ecfcde8c Mon Sep 17 00:00:00 2001 From: KHobbits Date: Mon, 13 Feb 2012 17:09:07 +0000 Subject: [PATCH 20/21] Add per warp command costs Make warp other commands charge the commander, not the warped. --- .../essentials/commands/Commandwarp.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandwarp.java b/Essentials/src/com/earth2me/essentials/commands/Commandwarp.java index 51b64563b..62641172b 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandwarp.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandwarp.java @@ -8,6 +8,7 @@ import com.earth2me.essentials.Warps; import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import java.util.Locale; import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; @@ -44,10 +45,10 @@ public class Commandwarp extends EssentialsCommand { throw new Exception(_("playerNotFound")); } - warpUser(otherUser, args[0]); + warpUser(user, otherUser, args[0]); throw new NoChargeException(); } - warpUser(user, args[0]); + warpUser(user, user, args[0]); throw new NoChargeException(); } } @@ -65,7 +66,7 @@ public class Commandwarp extends EssentialsCommand { throw new Exception(_("playerNotFound")); } - warpUser(otherUser, args[0]); + otherUser.getTeleport().warp(args[0], null, TeleportCause.COMMAND); throw new NoChargeException(); } @@ -112,17 +113,12 @@ public class Commandwarp extends EssentialsCommand } } - private void warpUser(final User user, final String name) throws Exception + private void warpUser(final User owner, final User user, final String name) throws Exception { - final Trade charge = new Trade(this.getName(), ess); - charge.isAffordableFor(user); - if (ess.getSettings().getPerWarpPermission()) + final Trade charge = new Trade("warp-" + name.toLowerCase(Locale.ENGLISH).replace('_', '-'), ess); + charge.isAffordableFor(owner); + if (ess.getSettings().getPerWarpPermission() && !owner.isAuthorized("essentials.warp." + name)) { - if (user.isAuthorized("essentials.warp." + name)) - { - user.getTeleport().warp(name, charge, TeleportCause.COMMAND); - return; - } throw new Exception(_("warpUsePermission")); } user.getTeleport().warp(name, charge, TeleportCause.COMMAND); From 57a2ef08d4b1f80f8794c1fafe0e7f22c88177a6 Mon Sep 17 00:00:00 2001 From: KHobbits Date: Mon, 13 Feb 2012 17:16:27 +0000 Subject: [PATCH 21/21] Allow charges for different mob types in /spawner --- .../com/earth2me/essentials/commands/Commandspawner.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Essentials/src/com/earth2me/essentials/commands/Commandspawner.java b/Essentials/src/com/earth2me/essentials/commands/Commandspawner.java index 73c86eba4..d52315241 100644 --- a/Essentials/src/com/earth2me/essentials/commands/Commandspawner.java +++ b/Essentials/src/com/earth2me/essentials/commands/Commandspawner.java @@ -2,6 +2,7 @@ package com.earth2me.essentials.commands; import static com.earth2me.essentials.I18n._; import com.earth2me.essentials.Mob; +import com.earth2me.essentials.Trade; import com.earth2me.essentials.User; import com.earth2me.essentials.Util; import java.util.Locale; @@ -47,11 +48,14 @@ public class Commandspawner extends EssentialsCommand { throw new Exception(_("unableToSpawnMob")); } - if (!user.isAuthorized("essentials.spawner." + mob.name.toLowerCase())) + if (!user.isAuthorized("essentials.spawner." + mob.name.toLowerCase(Locale.ENGLISH))) { throw new Exception(_("unableToSpawnMob")); } + final Trade charge = new Trade("spawner-" + mob.name.toLowerCase(Locale.ENGLISH), ess); + charge.isAffordableFor(user); ((CreatureSpawner)target.getBlock().getState()).setCreatureType(mob.getType()); + charge.charge(user); user.sendMessage(_("setSpawner", mob.name)); } catch (Throwable ex)