From 2c8aa20542b6fbb1555c11e9cd6485534beee39d Mon Sep 17 00:00:00 2001 From: ElgarL Date: Sun, 29 Jan 2012 21:37:50 +0000 Subject: [PATCH 01/10] .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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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 c0517c120369ac6a1de954c9d049bd0a88ff8ea6 Mon Sep 17 00:00:00 2001 From: ElgarL Date: Sat, 11 Feb 2012 10:36:55 +0000 Subject: [PATCH 10/10] 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() {