You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
8.0 KiB

package ru.simsonic.rscPermissions.Engine;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import ru.simsonic.rscMinecraftLibrary.Bukkit.GenericChatCodes;
import ru.simsonic.rscPermissions.API.EntityType;
import ru.simsonic.rscPermissions.API.RowEntity;
import ru.simsonic.rscPermissions.API.RowInheritance;
import ru.simsonic.rscPermissions.API.RowPermission;
import ru.simsonic.rscPermissions.API.Settings;
public class InternalCache extends InternalStorage
{
private boolean alwaysInheritDefaultGroup = false;
private boolean groupsInheritParentPrefixes = true;
public void setDefaultGroup(String defaultGroup, boolean alwaysInheritDefaultGroup, boolean groupsInheritParentPrefixes)
{
super.defaultInheritance.parent = defaultGroup;
super.defaultInheritance.deriveInstance();
this.alwaysInheritDefaultGroup = alwaysInheritDefaultGroup;
this.groupsInheritParentPrefixes = groupsInheritParentPrefixes;
}
public synchronized RowEntity findGroupRow(String group)
{
if(group != null && !"".equals(group))
{
final RowEntity row = entities_g.get(group.toLowerCase());
if(row != null)
return row;
}
return new RowEntity();
}
public synchronized Set<String> getKnownGroups()
{
final HashSet<String> result = new HashSet<>(entities_g.size());
for(RowEntity row : entities_g.values())
result.add(row.entity);
return result;
}
public synchronized ResolutionResult resolvePlayer(String player)
{
return resolvePlayer(new String[] { player });
}
public synchronized ResolutionResult resolvePlayer(String[] player)
{
final ResolutionParams params = new ResolutionParams();
params.applicableIdentifiers = player;
params.destRegions = new String[] {};
return resolvePlayer(params);
}
public synchronized ResolutionResult resolvePlayer(ResolutionParams params)
{
final ArrayList<RowEntity> applicableEntities = new ArrayList<>();
final ArrayList<RowPermission> applicablePermissions = new ArrayList<>();
final ArrayList<RowInheritance> applicableInheritance = new ArrayList<>();
if(implicit_u != null && implicit_u.permissions != null)
processPermissions(params, Arrays.asList(implicit_u.permissions));
params.groupList = new LinkedList<>();
params.finalPerms = new HashMap<>();
params.instantiator = "";
params.depth = 0;
for(RowEntity row : entities_u.values())
for(String identifier : params.applicableIdentifiers)
if(row.playerType.isEntityApplicable(row.entity, identifier))
{
// Apply direct inheritance
if(row.inheritance != null && row.inheritance.length > 0)
for(RowInheritance inheritance : row.inheritance)
if(isInheritanceApplicable(params, inheritance))
applicableInheritance.add(inheritance);
// Apply direct permissions
applicablePermissions.addAll(Arrays.asList(row.permissions));
// Apply direct prefixes and suffixes
applicableEntities.add(row);
}
Collections.sort(applicableEntities);
final ArrayList<ResolutionResult> intermediateResults = new ArrayList<>();
Collections.sort(applicableInheritance);
// Mix into default inheritance
if(applicableInheritance.isEmpty() || alwaysInheritDefaultGroup)
applicableInheritance.add(0, defaultInheritance);
for(RowInheritance row : applicableInheritance)
{
params.instantiator = "";
params.parentEntity = row.entityParent;
intermediateResults.add(resolveParent(params));
}
// Process all applicable prefixes using only entity id order
ResolutionResult result = processPrefixesAndSuffixes(params, intermediateResults);
for(RowEntity row : applicableEntities)
{
params.instantiator = "";
params.parentEntity = row;
result = processPrefixesAndSuffixes(params, Arrays.asList(new ResolutionResult[] { result }));
}
result.prefix = GenericChatCodes.processStringStatic(result.prefix);
result.suffix = GenericChatCodes.processStringStatic(result.suffix);
processPermissions(params, applicablePermissions);
result.permissions = params.finalPerms;
result.groups = params.groupList;
result.params = params;
return result;
}
private ResolutionResult resolveParent(ResolutionParams params)
{
if(implicit_g != null && implicit_g.permissions != null)
processPermissions(params, Arrays.asList(implicit_g.permissions));
final RowEntity currentParent = params.parentEntity;
final String instantiator = params.instantiator;
final ArrayList<ResolutionResult> intermediateResults = new ArrayList<>();
params.depth += 1;
for(RowInheritance row : params.parentEntity.inheritance)
if(isInheritanceApplicable(params, row))
{
params.parentEntity = row.entityParent;
params.instantiator = (row.instance != null && !"".equals(row.instance))
? row.instance
: instantiator;
intermediateResults.add(resolveParent(params));
}
params.depth -= 1;
params.groupList.add(depthPrefix(params.depth) + currentParent.entity
+ ("".equals(instantiator) ? "" : Settings.INSTANCE_SEP + instantiator));
// Prefixes and suffixes
params.parentEntity = currentParent;
params.instantiator = instantiator;
final ResolutionResult result = processPrefixesAndSuffixes(params, intermediateResults);
intermediateResults.clear();
// Permissions
if(currentParent.permissions != null)
processPermissions(params, Arrays.asList(currentParent.permissions));
return result;
}
private String depthPrefix(int depth)
{
if(depth > 0)
{
final char[] levelParent = new char[depth];
levelParent[depth - 1] = Settings.SHOW_GROUP_LEVEL;
return new String(levelParent).replace('\0', ' ');
}
return "";
}
private ResolutionResult processPrefixesAndSuffixes(ResolutionParams params, List<ResolutionResult> intermediate)
{
final ResolutionResult result = new ResolutionResult();
final boolean gipp = groupsInheritParentPrefixes || params.parentEntity.entityType.equals(EntityType.PLAYER);
result.prefix = params.parentEntity.prefix;
result.suffix = params.parentEntity.suffix;
if(result.prefix == null || "".equals(result.prefix))
result.prefix = (gipp ? Settings.TEXT_INHERITER : "");
if(result.suffix == null || "".equals(result.suffix))
result.suffix = (gipp ? Settings.TEXT_INHERITER : "");
final StringBuilder sbp = new StringBuilder();
final StringBuilder sbs = new StringBuilder();
for(ResolutionResult inherited : intermediate)
{
if(inherited.prefix != null)
sbp.append(inherited.prefix);
if(inherited.suffix != null)
sbs.append(inherited.suffix);
}
result.prefix = result.prefix.replace(Settings.TEXT_INHERITER, sbp.toString());
result.suffix = result.suffix.replace(Settings.TEXT_INHERITER, sbs.toString());
result.prefix = result.prefix.replace(Settings.INSTANTIATOR, params.instantiator);
result.suffix = result.suffix.replace(Settings.INSTANTIATOR, params.instantiator);
return result;
}
private void processPermissions(ResolutionParams params, List<RowPermission> permissions)
{
for(RowPermission row : permissions)
if(isPermissionApplicable(params, row))
params.finalPerms.put(
row.permission.replace(Settings.INSTANTIATOR, params.instantiator),
row.value);
}
private boolean isPermissionApplicable(ResolutionParams params, RowPermission row)
{
if(params.expirience < row.expirience)
return false;
return row.destination.isWorldApplicable(params.destWorld, params.instantiator)
? row.destination.isRegionApplicable(params.destRegions, params.instantiator)
: false;
}
private boolean isInheritanceApplicable(ResolutionParams params, RowInheritance row)
{
if(params.expirience < row.expirience)
return false;
return row.destination.isWorldApplicable(params.destWorld, params.instantiator)
? row.destination.isRegionApplicable(params.destRegions, params.instantiator)
: false;
}
}