From 5cfc4a2156eb61be45eeb70a761962d050929ff5 Mon Sep 17 00:00:00 2001 From: Stanislav Date: Thu, 25 Sep 2014 15:23:19 +0700 Subject: [PATCH] --- .../AbstractPermissionsCache.java | 13 + .../InternalCache/AsyncPlayerInfo.java | 97 ++++++++ .../InternalCache/BrandNewCache.java | 230 ++++++++++++++++++ .../InternalCache/LocalCacheData.java | 86 +++++++ .../InternalCache/LocalCacheFunctions.java | 101 ++++++++ .../InternalCache/LocalCacheTree.java | 176 ++++++++++++++ 6 files changed, 703 insertions(+) create mode 100644 src/main/java/ru/simsonic/rscPermissions/InternalCache/AbstractPermissionsCache.java create mode 100644 src/main/java/ru/simsonic/rscPermissions/InternalCache/AsyncPlayerInfo.java create mode 100644 src/main/java/ru/simsonic/rscPermissions/InternalCache/BrandNewCache.java create mode 100644 src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheData.java create mode 100644 src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheFunctions.java create mode 100644 src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheTree.java diff --git a/src/main/java/ru/simsonic/rscPermissions/InternalCache/AbstractPermissionsCache.java b/src/main/java/ru/simsonic/rscPermissions/InternalCache/AbstractPermissionsCache.java new file mode 100644 index 0000000..9380af9 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/InternalCache/AbstractPermissionsCache.java @@ -0,0 +1,13 @@ +package ru.simsonic.rscPermissions.InternalCache; +import ru.simsonic.rscPermissions.DataTypes.RowEntity; +import ru.simsonic.rscPermissions.DataTypes.RowInheritance; +import ru.simsonic.rscPermissions.DataTypes.RowLadder; +import ru.simsonic.rscPermissions.DataTypes.RowPermission; + +public interface AbstractPermissionsCache +{ + public int ImportEntities(RowEntity[] rows); + public int ImportPermissions(RowPermission[] rows); + public int ImportInheritance(RowInheritance[] rows); + public int ImportLadders(RowLadder[] rows); +} diff --git a/src/main/java/ru/simsonic/rscPermissions/InternalCache/AsyncPlayerInfo.java b/src/main/java/ru/simsonic/rscPermissions/InternalCache/AsyncPlayerInfo.java new file mode 100644 index 0000000..7033004 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/InternalCache/AsyncPlayerInfo.java @@ -0,0 +1,97 @@ +package ru.simsonic.rscPermissions.InternalCache; +import java.util.Set; +import java.util.UUID; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import ru.simsonic.rscPermissions.DataTypes.RowInheritance; +import ru.simsonic.rscPermissions.DataTypes.RowPermission; +import ru.simsonic.rscPermissions.InternalCache.LocalCacheTree.ResolutionLeaf; + +public class AsyncPlayerInfo +{ + public Player player; + public String name; + public UUID uuid; + public int expirience; + public Location location; + public Set regions; + public AsyncPlayerInfo() + { + } + public AsyncPlayerInfo(String playerName) + { + this.name = playerName; + } + public AsyncPlayerInfo(UUID playerUniqueId) + { + this.uuid = playerUniqueId; + } + public AsyncPlayerInfo(Player player, Set regions) + { + if(player != null) + { + this.player = player; + try + { + // minecraft <= 1.7 + this.name = player.getName(); + } catch(RuntimeException | NoSuchMethodError ex) { + // minecraft >= 1.8 + } + try + { + // minecraft >= 1.8 + this.uuid = player.getUniqueId(); + } catch(RuntimeException | NoSuchMethodError ex) { + // minecraft <= 1.7 + } + this.expirience = player.getLevel(); + this.location = player.getLocation(); + this.regions = regions; + } + } + public boolean isPlayerEntityApplicable(String entity) + { + // Test by UUID (minecraft >= 1.8) + try + { + if(this.uuid.compareTo(UUID.fromString(entity)) == 0) + return true; + } catch(RuntimeException ex) { + // Server doesn't support this yet + } + // Test by name (minecraft <= 1.7) + try + { + if(this.name.equalsIgnoreCase(entity)) + return true; + } catch(RuntimeException ex) { + // Server already doesn't support this + } + return false; + } + public boolean isPlayerPermissionApplicable(RowPermission row) + { + if(isPlayerEntityApplicable(row.entity) || "".equals(row.entity)) + return (row.destination.IsLocationApplicable(location, regions, null) && row.expirience <= expirience); + return false; + } + public boolean isGroupPermissionApplicable(RowPermission row, ResolutionLeaf leaf) + { + if(row.entity.equalsIgnoreCase(leaf.group) || "".equals(row.entity)) + return (row.destination.IsLocationApplicable(location, regions, leaf.instance) && row.expirience <= expirience); + return false; + } + public boolean isPlayerInheritanceApplicable(RowInheritance row) + { + if(isPlayerEntityApplicable(row.entity)) + return (row.destination.IsLocationApplicable(location, regions, row.instance) && row.expirience <= expirience); + return false; + } + public boolean isGroupInheritanceApplicable(RowInheritance row, ResolutionLeaf leaf) + { + if(row.entity.equalsIgnoreCase(leaf.group)) + return (row.destination.IsLocationApplicable(location, regions, leaf.instance) && row.expirience <= expirience); + return false; + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/InternalCache/BrandNewCache.java b/src/main/java/ru/simsonic/rscPermissions/InternalCache/BrandNewCache.java new file mode 100644 index 0000000..6494d93 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/InternalCache/BrandNewCache.java @@ -0,0 +1,230 @@ +package ru.simsonic.rscPermissions.InternalCache; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import org.bukkit.entity.Player; +import ru.simsonic.rscPermissions.DataTypes.EntityType; +import ru.simsonic.rscPermissions.DataTypes.RowEntity; +import ru.simsonic.rscPermissions.DataTypes.RowInheritance; +import ru.simsonic.rscPermissions.DataTypes.RowLadder; +import ru.simsonic.rscPermissions.DataTypes.RowPermission; +import ru.simsonic.rscPermissions.MainPluginClass; + +public class BrandNewCache implements AbstractPermissionsCache +{ + protected final MainPluginClass plugin; + protected BrandNewCache(MainPluginClass rscp) + { + this.plugin = rscp; + } + protected final RowInheritance defaultInheritance = new RowInheritance(); + public void setDefaultGroup(String defaultGroup) + { + defaultInheritance.parent = defaultGroup; + defaultInheritance.deriveInstance(); + } + protected final HashMap entities_g = new HashMap<>(); + protected final HashMap entities_u = new HashMap<>(); + protected final ArrayList permissions_p2g = new ArrayList<>(); + protected final ArrayList permissions_p2u = new ArrayList<>(); + protected final ArrayList inheritance_g2g = new ArrayList<>(); + protected final ArrayList inheritance_g2u = new ArrayList<>(); + protected final ArrayList ladders_g = new ArrayList<>(); + protected final ArrayList ladders_u = new ArrayList<>(); + public static class InheritanceLeaf implements Comparable + { + public RowInheritance node; + public String instantiator; + public InheritanceLeaf[] subleafs; + public String resolvedPrefix; + public String resolvedSuffix; + @Override + public int compareTo(InheritanceLeaf other) + { + return (other.node != null && node != null) ? other.node.compareTo(node) : 0; + } + } + public static class ResolutionParams + { + public String[] applicableIdentifiers; + public String[] destRegions; + public String destWorld; + public String destServerId; + } + public static class ResolutionResult + { + public String prefix; + public String suffix; + public RowPermission[] permissions; + } + final HashMap entityTrees = new HashMap<>(); + // Права по сущностям + final HashMap groupPermissions = new HashMap<>(); + final HashMap playerPermissions = new HashMap<>(); + private void buildEntityTree() + { + final HashSet entitiesWhichInherits = new HashSet<>(); + for(RowInheritance row : inheritance_g2u) + entitiesWhichInherits.add(row.entity); + for(String inheritingEntity : entitiesWhichInherits) + { + final ArrayList entityDirectParents = new ArrayList<>(); + for(RowInheritance row : inheritance_g2u) + if(row.entity.equalsIgnoreCase(inheritingEntity)) + entityDirectParents.add(row); + Collections.sort(entityDirectParents); + for(RowInheritance row : entityDirectParents) + this.entityTrees.put(inheritingEntity, buildBranch(row)); + } + } + private InheritanceLeaf buildBranch(RowInheritance source) + { + final InheritanceLeaf result = new InheritanceLeaf(); + result.node = source; + result.instantiator = source.instance; + final String entityName = source.entity.toLowerCase(); + if(entities_g.containsKey(entityName)) + { + result.resolvedPrefix = entities_g.get(entityName).prefix; + result.resolvedSuffix = entities_g.get(entityName).suffix; + } + final ArrayList parents = new ArrayList<>(); + for(RowInheritance row : inheritance_g2g) + if(row.parent.equalsIgnoreCase(source.entity)) + parents.add(row); + Collections.sort(parents); + final ArrayList subleafs = new ArrayList<>(); + for(RowInheritance row : parents) + subleafs.add(buildBranch(row)); + result.subleafs = subleafs.toArray(new InheritanceLeaf[subleafs.size()]); + return result; + } + private static String[] getPlayerIdentifiers(Player player) + { + final ArrayList result = new ArrayList<>(); + // For old servers Player's name can be used as entity name + try + { + // minecraft <= 1.7.x + result.add(player.getName()); + } catch(RuntimeException | NoSuchMethodError ex) { + // minecraft >= 1.8 + } + // For newest servers Player's UUID is used as entity name + try + { + // minecraft >= 1.8 + result.add(player.getUniqueId().toString().toLowerCase()); + } catch(RuntimeException | NoSuchMethodError ex) { + // minecraft <= 1.7.x + } + // IP address of a Player can be used as entity name too + result.add(player.getAddress().getAddress().getHostAddress()); + return result.toArray(new String[result.size()]); + } + public void resolvePlayer(Player player) + { + final ResolutionParams params = new ResolutionParams(); + params.applicableIdentifiers = getPlayerIdentifiers(player); + if(plugin.regionListProvider != null) + { + Set regionSet = plugin.regionListProvider.GetRegionList(player); + params.destRegions = regionSet.toArray(new String[regionSet.size()]); + } else + params.destRegions = new String[] {}; + params.destWorld = player.getLocation().getWorld().getName(); + params.destServerId = plugin.getServer().getServerId(); + // TO DO + } + public void resolvePlayer(String player) + { + final ResolutionParams params = new ResolutionParams(); + params.applicableIdentifiers = new String[] { player }; + params.destRegions = new String[] {}; + params.destWorld = ""; + params.destServerId = plugin.getServer().getServerId(); + // TO DO + } + private void resolvePlayer(ResolutionParams params) + { + final ArrayList leafs = new ArrayList<>(); + for(String identifier : params.applicableIdentifiers) + for(String tree : entityTrees.keySet()) + if(tree.equals(identifier)) + leafs.add(entityTrees.get(tree)); + Collections.sort(leafs); + final InheritanceLeaf root = new InheritanceLeaf(); + } + public void recoursion(ResolutionParams params, InheritanceLeaf branch) + { + for(InheritanceLeaf leaf : branch.subleafs) + { + } + } + @Override + public synchronized int ImportEntities(RowEntity[] rows) + { + entities_g.clear(); + entities_u.clear(); + if(rows == null) + return 0; + for(RowEntity row : rows) + { + if(row.entityType == EntityType.group) + entities_g.put(row.entity.toLowerCase(), row); + else + entities_u.put(row.entity.toLowerCase(), row); + } + return entities_g.size() + entities_u.size(); + } + @Override + public synchronized int ImportPermissions(RowPermission[] rows) + { + permissions_p2g.clear(); + permissions_p2u.clear(); + if(rows == null) + return 0; + for(RowPermission row : rows) + { + if(row.entityType == EntityType.group) + permissions_p2g.add(row); + else + permissions_p2u.add(row); + } + return permissions_p2g.size() + permissions_p2u.size(); + } + @Override + public synchronized int ImportInheritance(RowInheritance[] rows) + { + inheritance_g2g.clear(); + inheritance_g2u.clear(); + if(rows == null) + return 0; + for(RowInheritance row : rows) + { + if(row.childType == EntityType.group) + inheritance_g2g.add(row); + else + inheritance_g2u.add(row); + } + return inheritance_g2g.size() + inheritance_g2u.size(); + } + @Override + public synchronized int ImportLadders(RowLadder[] rows) + { + ladders_g.clear(); + ladders_u.clear(); + if(rows == null) + return 0; + for(RowLadder row : rows) + { + if(row.climberType == EntityType.group) + ladders_g.add(row); + else + ladders_u.add(row); + } + return ladders_g.size() + ladders_u.size(); + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheData.java b/src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheData.java new file mode 100644 index 0000000..44e78f2 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheData.java @@ -0,0 +1,86 @@ +package ru.simsonic.rscPermissions.InternalCache; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.concurrent.ConcurrentHashMap; +import ru.simsonic.rscPermissions.DataTypes.*; +import ru.simsonic.rscPermissions.DataTypes.EntityType; +import ru.simsonic.rscPermissions.MainPluginClass; + +public class LocalCacheData +{ + protected final MainPluginClass plugin; + protected final HashMap entities_g = new HashMap<>(); + protected final HashMap entities_u = new HashMap<>(); + protected final ConcurrentHashMap prefixes_u = new ConcurrentHashMap<>(); + protected final ConcurrentHashMap suffixes_u = new ConcurrentHashMap<>(); + protected final ArrayList permissions_p2g = new ArrayList<>(); + protected final ArrayList permissions_p2u = new ArrayList<>(); + protected final ArrayList inheritance_g2g = new ArrayList<>(); + protected final ArrayList inheritance_g2u = new ArrayList<>(); + protected final ArrayList ladders_g = new ArrayList<>(); + protected final ArrayList ladders_u = new ArrayList<>(); + protected LocalCacheData(MainPluginClass rscp) + { + this.plugin = rscp; + } + public synchronized int ImportEntities(RowEntity[] rows) + { + entities_g.clear(); + entities_u.clear(); + if(rows == null) + return 0; + for(RowEntity row : rows) + { + if(row.entityType == EntityType.group) + entities_g.put(row.entity.toLowerCase(), row); + else + entities_u.put(row.entity.toLowerCase(), row); + } + return entities_g.size() + entities_u.size(); + } + public synchronized int ImportPermissions(RowPermission[] rows) + { + permissions_p2g.clear(); + permissions_p2u.clear(); + if(rows == null) + return 0; + for(RowPermission row : rows) + { + if(row.entityType == EntityType.group) + permissions_p2g.add(row); + else + permissions_p2u.add(row); + } + return permissions_p2g.size() + permissions_p2u.size(); + } + public synchronized int ImportInheritance(RowInheritance[] rows) + { + inheritance_g2g.clear(); + inheritance_g2u.clear(); + if(rows == null) + return 0; + for(RowInheritance row : rows) + { + if(row.childType == EntityType.group) + inheritance_g2g.add(row); + else + inheritance_g2u.add(row); + } + return inheritance_g2g.size() + inheritance_g2u.size(); + } + public synchronized int ImportLadders(RowLadder[] rows) + { + ladders_g.clear(); + ladders_u.clear(); + if(rows == null) + return 0; + for(RowLadder row : rows) + { + if(row.climberType == EntityType.group) + ladders_g.add(row); + else + ladders_u.add(row); + } + return ladders_g.size() + ladders_u.size(); + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheFunctions.java b/src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheFunctions.java new file mode 100644 index 0000000..0d317b6 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheFunctions.java @@ -0,0 +1,101 @@ +package ru.simsonic.rscPermissions.InternalCache; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import ru.simsonic.rscPermissions.DataTypes.RowEntity; +import ru.simsonic.rscPermissions.DataTypes.RowInheritance; +import ru.simsonic.rscPermissions.DataTypes.RowLadder; +import ru.simsonic.rscPermissions.DataTypes.RowPermission; +import ru.simsonic.rscPermissions.MainPluginClass; +import ru.simsonic.rscPermissions.Settings; + +public class LocalCacheFunctions extends LocalCacheTree +{ + public LocalCacheFunctions(MainPluginClass rscp) + { + super(rscp); + } + public String userGetPrefix(String user) + { + return prefixes_u.get(user); + } + public String userGetSuffix(String user) + { + return suffixes_u.get(user); + } + public synchronized String groupGetPrefix(String group) + { + if(group == null || "".equals(group)) + return null; + RowEntity entity = entities_g.get(group.toLowerCase()); + return (entity != null) ? entity.prefix : null; + } + public synchronized String groupGetSuffix(String group) + { + if(group == null || "".equals(group)) + return null; + RowEntity entity = entities_g.get(group.toLowerCase()); + return (entity != null) ? entity.suffix : null; + } + public synchronized ArrayList buildLadderTemplate(String ladder) + { + final ArrayList result = new ArrayList<>(); + RowLadder prev = null; + for(RowLadder row : ladders_g) + if(row.ladder.equalsIgnoreCase(ladder)) + { + if(prev != null) + { + prev.nextNode = row; + row.prevNode = prev; + } + result.add(row); + prev = row; + } + Collections.sort(result); + return result; + } + public synchronized int getUserRank(String user, String ladder, String instance) + { + for(RowLadder row : ladders_u) + if(row.climber.equalsIgnoreCase(user) && row.ladder.equalsIgnoreCase(ladder)) + if(instance == null || "".equals(instance)) + { + if(row.instance == null || "".equals(row.instance)) + return row.rank; + } else + if(instance.equalsIgnoreCase(row.instance)) + return row.rank; + return 0; + } + public synchronized ArrayList getUserGroups(String player) + { + final ArrayList tree = mapTrees.get(player.toLowerCase()); + if(tree == null) + return null; + final ArrayList result = new ArrayList<>(); + for(ResolutionLeaf leaf : tree) + result.add(leaf.instance != null ? leaf.group + Settings.separator + leaf.instance : leaf.group); + return result; + } + public synchronized Set getAllPossibleGroups() + { + Set result = new HashSet<>(); + for(RowEntity row : entities_g.values()) + result.add(row.entity.toLowerCase()); + for(RowPermission row : permissions_p2g) + result.add(row.entity.toLowerCase()); + for(RowInheritance row : inheritance_g2g) + { + result.add(row.entity.toLowerCase()); + result.add(row.parent.toLowerCase()); + } + for(RowInheritance row : inheritance_g2u) + result.add(row.parent.toLowerCase()); + for(RowLadder row : ladders_g) + if(row.climber != null) + result.add(row.climber.toLowerCase()); + return result; + } +} \ No newline at end of file diff --git a/src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheTree.java b/src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheTree.java new file mode 100644 index 0000000..20907c6 --- /dev/null +++ b/src/main/java/ru/simsonic/rscPermissions/InternalCache/LocalCacheTree.java @@ -0,0 +1,176 @@ +package ru.simsonic.rscPermissions.InternalCache; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import org.bukkit.entity.Player; +import ru.simsonic.rscPermissions.DataTypes.RowEntity; +import ru.simsonic.rscPermissions.DataTypes.RowInheritance; +import ru.simsonic.rscPermissions.DataTypes.RowLadder; +import ru.simsonic.rscPermissions.DataTypes.RowPermission; +import ru.simsonic.rscPermissions.MainPluginClass; +import ru.simsonic.rscPermissions.Settings; +import ru.simsonic.utilities.LanguageUtility; + +public class LocalCacheTree extends LocalCacheData +{ + protected static class ResolutionLeaf + { + public String group; + public String instance; + public RowInheritance row; + } + protected LocalCacheTree(MainPluginClass rscp) + { + super(rscp); + } + public final ConcurrentHashMap> mapTrees = new ConcurrentHashMap<>(); + public final ConcurrentHashMap> mapPermissions = new ConcurrentHashMap<>(); + protected final RowInheritance defaultInheritance = new RowInheritance(); + public void setDefaultGroup(String defaultGroup) + { + defaultInheritance.parent = defaultGroup; + defaultInheritance.deriveInstance(); + } + public synchronized void clear() + { + mapTrees.clear(); + mapPermissions.clear(); + prefixes_u.clear(); + suffixes_u.clear(); + entities_g.clear(); + entities_u.clear(); + permissions_p2g.clear(); + permissions_p2u.clear(); + inheritance_g2g.clear(); + inheritance_g2u.clear(); + ladders_g.clear(); + ladders_u.clear(); + } + public synchronized void calculateStartupPermissions() + { + final HashSet playerEntities = new HashSet<>(); + // Undefined player + playerEntities.add(""); // Зачем я его тут добавил?!? + // Defined players (in any table) + playerEntities.addAll(entities_u.keySet()); + for(RowPermission row : permissions_p2u) + playerEntities.add(row.entity); + for(RowInheritance row : inheritance_g2u) + playerEntities.add(row.entity); + for(RowLadder row : ladders_u) + playerEntities.add(row.climber); + // Recalculate + for(String entityNameOrUUID : playerEntities) + calculateBasePermissions(entityNameOrUUID); + } + public synchronized void calculateBasePermissions(String playerName) + { + AsyncPlayerInfo p2rc = new AsyncPlayerInfo(playerName); + HashMap list = treeToPermissions(p2rc); + mapPermissions.put(playerName, list); + } + public synchronized void calculateBasePermissions(UUID playerUniqueId) + { + AsyncPlayerInfo p2rc = new AsyncPlayerInfo(playerUniqueId); + HashMap list = treeToPermissions(p2rc); + mapPermissions.put(playerUniqueId.toString().replace("-", "").toLowerCase(), list); + } + public void calculatePlayerPermissions(Player player) + { + final AsyncPlayerInfo api = new AsyncPlayerInfo(player, plugin.regionListProvider.GetRegionList(player)); + plugin.recalculatingPlayers.offer(api); + } + public synchronized HashMap treeToPermissions(AsyncPlayerInfo p2rc) + { + final HashMap permissions = new HashMap<>(); + String prefix = ""; + String suffix = ""; + ArrayList tree = buildUserTree(p2rc); + if(p2rc.name != null) + mapTrees.put(p2rc.name.toLowerCase(), tree); + // Group permissions + for(ResolutionLeaf leaf : tree) + { + for(RowPermission row : permissions_p2g) + if(p2rc.isGroupPermissionApplicable(row, leaf)) + { + String permission = row.permission; + // Additional processing + if(permission.contains(Settings.instantiator) && (leaf.instance != null)) + permission = permission.replaceAll(Settings.instantiatorRegExp, leaf.instance); + permissions.put(permission, row.value); + } + RowEntity entity = entities_g.get(leaf.group.toLowerCase()); + if(entity != null) + { + if(entity.prefix != null && !"".equals(entity.prefix)) + prefix = entity.prefix.replace("%", prefix); + if(entity.suffix != null && !"".equals(entity.suffix)) + suffix = entity.suffix.replace("%", suffix); + prefix = prefix.replaceAll(Settings.instantiatorRegExp, leaf.instance); + suffix = suffix.replaceAll(Settings.instantiatorRegExp, leaf.instance); + } + } + // User permissions + for(RowPermission row : permissions_p2u) + if(p2rc.isPlayerPermissionApplicable(row)) + permissions.put(row.permission, row.value); + if(p2rc.name != null) + { + RowEntity entity = entities_u.get(p2rc.name.toLowerCase()); + if(entity != null) + { + if(entity.prefix != null && !"".equals(entity.prefix)) + prefix = entity.prefix.replace("%", prefix); + if(entity.suffix != null && !"".equals(entity.suffix)) + suffix = entity.suffix.replace("%", suffix); + } + prefixes_u.put(p2rc.name, LanguageUtility.processStringStatic(prefix)); + suffixes_u.put(p2rc.name, LanguageUtility.processStringStatic(suffix)); + } + return permissions; + } + private ArrayList buildUserTree(AsyncPlayerInfo p2rc) + { + // User's direct inheritance + ArrayList parentRows = new ArrayList<>(); + for(RowInheritance row : inheritance_g2u) + if(p2rc.isPlayerInheritanceApplicable(row)) + parentRows.add(row); + Collections.sort(parentRows); + // Indirect default group + if(parentRows.isEmpty() || plugin.settings.isDefaultForever()) + parentRows.add(0, defaultInheritance); + ArrayList resultTree = new ArrayList<>(); + // Parent deep inheritances + for(RowInheritance row : parentRows) + { + ResolutionLeaf newleaf = new ResolutionLeaf(); + newleaf.group = row.parent; + newleaf.instance = row.instance; + newleaf.row = row; + buildGroupTree(p2rc, newleaf, resultTree); + } + return resultTree; + } + private void buildGroupTree(AsyncPlayerInfo p2rc, ResolutionLeaf findAndOpen, ArrayList result) + { + ArrayList parentRows = new ArrayList<>(inheritance_g2g.size() >> 2); + for(RowInheritance row : inheritance_g2g) + if(p2rc.isGroupInheritanceApplicable(row, findAndOpen)) + parentRows.add(row); + Collections.sort(parentRows); + for(RowInheritance row : parentRows) + { + ResolutionLeaf newleaf = new ResolutionLeaf(); + newleaf.group = row.parent; + newleaf.instance = (row.instance != null) ? row.instance : findAndOpen.instance; + newleaf.row = row; + buildGroupTree(p2rc, newleaf, result); + } + result.add(findAndOpen); + } +} \ No newline at end of file