GriefDefender/bukkit/src/main/java/com/griefdefender/permission/GDPermissionManager.java

1869 lines
89 KiB
Java

/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.permission;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.Subject;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimContexts;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.claim.TrustType;
import com.griefdefender.api.permission.Context;
import com.griefdefender.api.permission.ContextKeys;
import com.griefdefender.api.permission.PermissionManager;
import com.griefdefender.api.permission.PermissionResult;
import com.griefdefender.api.permission.ResultTypes;
import com.griefdefender.api.permission.flag.Flag;
import com.griefdefender.api.permission.flag.FlagDefinition;
import com.griefdefender.api.permission.flag.Flags;
import com.griefdefender.api.permission.option.Option;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.api.permission.option.type.CreateModeType;
import com.griefdefender.api.permission.option.type.CreateModeTypes;
import com.griefdefender.api.permission.option.type.GameModeType;
import com.griefdefender.api.permission.option.type.GameModeTypes;
import com.griefdefender.api.permission.option.type.WeatherType;
import com.griefdefender.api.permission.option.type.WeatherTypes;
import com.griefdefender.cache.EventResultCache;
import com.griefdefender.cache.MessageCache;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.claim.GDClaimManager;
import com.griefdefender.command.CommandHelper;
import com.griefdefender.configuration.MessageStorage;
import com.griefdefender.configuration.category.BanCategory;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDFlagPermissionEvent;
import com.griefdefender.internal.registry.BlockTypeRegistryModule;
import com.griefdefender.internal.registry.EntityTypeRegistryModule;
import com.griefdefender.internal.registry.GDEntityType;
import com.griefdefender.internal.registry.GDTileType;
import com.griefdefender.internal.registry.ItemTypeRegistryModule;
import com.griefdefender.internal.registry.TileEntityTypeRegistryModule;
import com.griefdefender.internal.tracking.chunk.GDChunk;
import com.griefdefender.internal.util.NMSUtil;
import com.griefdefender.permission.option.GDOptions;
import com.griefdefender.provider.PermissionProvider.PermissionDataType;
import com.griefdefender.registry.FlagRegistryModule;
import com.griefdefender.util.EconomyUtil;
import com.griefdefender.util.PermissionUtil;
import com.griefdefender.util.PlayerUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.CreatureSpawner;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.ThrownPotion;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.Event;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.EntityChangeBlockEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerBucketEvent;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class GDPermissionManager implements PermissionManager {
private static final Pattern BLOCKSTATE_PATTERN = Pattern.compile("(?:\\w+=\\w+,)*\\w+=\\w+", Pattern.MULTILINE);
private static GDPermissionManager instance;
public boolean blacklistCheck = false;
private Event currentEvent;
private Location eventLocation;
private GDPermissionHolder eventSubject;
private GDPlayerData eventPlayerData;
private String eventSourceId = "none";
private String eventTargetId = "none";
private Set<Context> eventContexts = new HashSet<>();
private Component eventMessage;
private static final Pattern PATTERN_META = Pattern.compile("\\.[\\d+]*$");
private enum BanType {
BLOCK,
ENTITY,
ITEM
}
public GDPermissionHolder getDefaultHolder() {
return GriefDefenderPlugin.DEFAULT_HOLDER;
}
@Override
public Tristate getActiveFlagPermissionValue(Claim claim, Subject subject, Flag flag, Object source, Object target, Set<Context> contexts, TrustType type, boolean checkOverride) {
return getFinalPermission(null, null, contexts, claim, flag, source, target, (GDPermissionHolder) subject, type, checkOverride);
}
public Tristate getFinalPermission(Event event, Location location, Claim claim, Flag flag, Object source, Object target, GDPermissionHolder permissionHolder) {
return getFinalPermission(event, location, claim, flag, source, target, permissionHolder, null, false);
}
public Tristate getFinalPermission(Event event, Location location, Claim claim, Flag flag, Object source, Object target, Player player) {
final GDPermissionHolder permissionHolder = PermissionHolderCache.getInstance().getOrCreateUser(player);
return getFinalPermission(event, location, claim, flag, source, target, permissionHolder, null, false);
}
public Tristate getFinalPermission(Event event, Location location, Claim claim, Flag flag, Object source, Object target, Player player, boolean checkOverride) {
final GDPermissionHolder permissionHolder = PermissionHolderCache.getInstance().getOrCreateUser(player);
return getFinalPermission(event, location, claim, flag, source, target, permissionHolder, null, checkOverride);
}
public Tristate getFinalPermission(Event event, Location location, Claim claim, Flag flag, Object source, Object target, GDPermissionHolder permissionHolder, boolean checkOverride) {
return getFinalPermission(event, location, claim, flag, source, target, permissionHolder, null, checkOverride);
}
public Tristate getFinalPermission(Event event, Location location, Claim claim, Flag flag, Object source, Object target, Player player, TrustType type, boolean checkOverride) {
final GDPermissionHolder permissionHolder = PermissionHolderCache.getInstance().getOrCreateUser(player);
return getFinalPermission(event, location, claim, flag, source, target, permissionHolder, type, checkOverride);
}
public Tristate getFinalPermission(Event event, Location location, Claim claim, Flag flag, Object source, Object target, GDPermissionHolder permissionHolder, TrustType type, boolean checkOverride) {
return getFinalPermission(event, location, new HashSet<>(), claim, flag, source, target, permissionHolder, type, checkOverride);
}
public Tristate getFinalPermission(Event event, Location location, Set<Context> contexts, Claim claim, Flag flag, Object source, Object target, GDPermissionHolder permissionHolder, TrustType type, boolean checkOverride) {
if (claim == null) {
return Tristate.TRUE;
}
GDPlayerData playerData = null;
final GDPermissionUser user = permissionHolder instanceof GDPermissionUser ? (GDPermissionUser) permissionHolder : null;
this.eventSubject = user;
this.eventMessage = null;
this.eventSourceId = "none";
this.eventTargetId = "none";
if (permissionHolder != null) {
if (user != null) {
playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(claim.getWorldUniqueId(), user.getUniqueId());
}
}
this.currentEvent = event;
this.eventLocation = location;
// refresh contexts
this.eventContexts = new HashSet<>();
if (source instanceof Player && flag != Flags.COLLIDE_BLOCK && flag != Flags.COLLIDE_ENTITY) {
this.addPlayerContexts((Player) source, contexts, flag);
}
if (!(source instanceof Player) && user != null && user.getOnlinePlayer() != null) {
boolean addPlayerContext = false;
if (!(target instanceof Player)) {
addPlayerContext = true;
} else if (!user.getUniqueId().equals(((Player) target).getUniqueId())) {
addPlayerContext = true;
}
if (addPlayerContext) {
// add source player context
// this allows users to block all pvp actions when direct source isn't a player
contexts.add(new Context(ContextKeys.SOURCE, this.getPermissionIdentifier(user.getOnlinePlayer())));
}
}
if (source instanceof Block && event instanceof EntityChangeBlockEvent && flag == Flags.BLOCK_MODIFY) {
final EntityChangeBlockEvent entityChangeBlockEvent = (EntityChangeBlockEvent) event;
contexts.add(new Context(ContextKeys.SOURCE, this.getPermissionIdentifier(entityChangeBlockEvent.getEntity())));
}
final Set<Context> sourceContexts = this.getPermissionContexts((GDClaim) claim, source, true);
if (sourceContexts == null) {
return Tristate.FALSE;
}
final Set<Context> targetContexts = this.getPermissionContexts((GDClaim) claim, target, false);
if (targetContexts == null) {
return Tristate.FALSE;
}
contexts.addAll(sourceContexts);
contexts.addAll(targetContexts);
contexts.add(((GDClaim) claim).getWorldContext());
this.eventContexts = contexts;
this.eventPlayerData = playerData;
final String targetPermission = flag.getPermission();
if (flag == Flags.ENTITY_SPAWN && GDOptions.SPAWN_LIMIT && target instanceof LivingEntity) {
// Check spawn limit
final GDClaim gdClaim = (GDClaim) claim;
final int spawnLimit = gdClaim.getSpawnLimit(contexts);
if (spawnLimit > -1) {
final Entity entity = (Entity) target;
final int currentEntityCount = gdClaim.countEntities(entity);
if (currentEntityCount >= spawnLimit) {
if (user != null && user.getOnlinePlayer() != null && (source == SpawnReason.ENDER_PEARL || source == SpawnReason.SPAWNER_EGG || source == SpawnReason.SPAWNER)) {
final String name = entity.getType().getName() == null ? entity.getType().name().toLowerCase() : entity.getType().getName();
final GDEntityType entityType = EntityTypeRegistryModule.getInstance().getById(name).orElse(null);
final Component message = GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.OPTION_APPLY_SPAWN_LIMIT,
ImmutableMap.of(
"type", entityType.getId(),
"limit", spawnLimit));
GriefDefenderPlugin.sendMessage(user.getOnlinePlayer(), message);
}
return this.processResult(claim, flag.getPermission(), "spawn-limit", Tristate.FALSE, this.eventSubject);
}
}
}
if (user != null && playerData != null && !playerData.debugClaimPermissions && playerData.canIgnoreClaim(claim)) {
return processResult(claim, targetPermission, "ignore", Tristate.TRUE, user);
}
if (checkOverride) {
// First check for claim flag overrides
final Tristate override = getFlagOverride(claim, permissionHolder == null ? GriefDefenderPlugin.DEFAULT_HOLDER : permissionHolder, playerData, targetPermission);
if (override != Tristate.UNDEFINED) {
return processResult(claim, targetPermission, type == null ? "none" : type.getName().toLowerCase(), override, user);
}
}
if (playerData != null && user != null) {
if (playerData.debugClaimPermissions) {
if (type != null && claim.isUserTrusted(user.getUniqueId(), type)) {
return processResult(claim, targetPermission, type.getName().toLowerCase(), Tristate.TRUE, user);
}
return getClaimFlagPermission(claim, targetPermission);
}
// Check for ignoreclaims after override and debug checks
if (playerData.canIgnoreClaim(claim)) {
return processResult(claim, targetPermission, "ignore", Tristate.TRUE, user);
}
}
if (user != null) {
// check if rented
if (claim.getEconomyData() != null && claim.getEconomyData().isRented() &&
flag != Flags.COMMAND_EXECUTE &&
flag != Flags.COMMAND_EXECUTE_PVP &&
flag != Flags.ENTER_CLAIM &&
flag != Flags.EXIT_CLAIM &&
flag != Flags.ENTITY_TELEPORT_FROM &&
flag != Flags.ENTITY_TELEPORT_TO &&
flag != Flags.INTERACT_INVENTORY_CLICK) {
if (claim.getOwnerUniqueId() != null && user != null && claim.getOwnerUniqueId().equals(user.getUniqueId())) {
return processResult(claim, targetPermission, "rent-owner-deny", Tristate.FALSE, user);
}
if (EconomyUtil.getInstance().isRenter(claim, user) && (targetPermission.contains("interact") || targetPermission.contains("block"))) {
if ((targetPermission.contains("interact") || targetPermission.contains("block-place"))) {
final boolean hasInventory = NMSUtil.getInstance().isTileInventory(location) || location.getBlock().getType() == Material.ENDER_CHEST;
if (!hasInventory || flag == Flags.BLOCK_PLACE) {
return processResult(claim, targetPermission, "renter-interact", Tristate.TRUE, user);
}
// check entity interactions
if (targetPermission.contains("interact-entity") && target instanceof LivingEntity) {
// Allow interaction with all living entities
return processResult(claim, targetPermission, "renter-interact", Tristate.TRUE, user);
}
}
// Allow renters to break/change their own blocks
final GDClaimManager claimWorldManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(location.getWorld().getUID());
final GDChunk gdChunk = claimWorldManager.getChunk(location.getBlock().getChunk());
final GDPermissionUser owner = gdChunk.getBlockOwner(location);
if (owner != null && owner.getUniqueId().equals(user.getUniqueId())) {
// allow
return processResult(claim, targetPermission, "renter-owned", Tristate.TRUE, user);
}
}
}
if (type != null) {
if (((GDClaim) claim).isUserTrusted(user, type)) {
// check persisted flags
if (!claim.isWilderness()) {
if ((claim.isAdminClaim() && !user.getInternalPlayerData().canManageAdminClaims) || !user.getUniqueId().equals(claim.getOwnerUniqueId())) {
final Tristate result = getUserPermission(user, claim, targetPermission, PermissionDataType.USER_PERSISTENT);
if (result != Tristate.UNDEFINED) {
return processResult(claim, targetPermission, result, user);
}
}
}
return processResult(claim, targetPermission, type.getName().toLowerCase(), Tristate.TRUE, permissionHolder);
}
}
return getUserPermission(user, claim, targetPermission, PermissionDataType.PERSISTENT);
}
return getClaimFlagPermission(claim, targetPermission);
}
private Tristate getUserPermission(GDPermissionHolder holder, Claim claim, String permission, PermissionDataType dataType) {
final List<Claim> inheritParents = claim.getInheritedParents();
final Set<Context> contexts = new HashSet<>();
contexts.addAll(this.eventContexts);
for (Claim parentClaim : inheritParents) {
GDClaim parent = (GDClaim) parentClaim;
// check parent context
contexts.add(parent.getContext());
Tristate value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, holder, permission, contexts, dataType);
if (value != Tristate.UNDEFINED) {
return processResult(claim, permission, value, holder);
}
contexts.remove(parent.getContext());
}
// Check claim context
contexts.add(claim.getContext());
Tristate value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, holder, permission, contexts, dataType);
if (value != Tristate.UNDEFINED) {
return processResult(claim, permission, value, holder);
}
if (dataType == PermissionDataType.USER_PERSISTENT) {
// don't log, just return result
return value;
}
// Group MUST inherit default group or above will return undefined if no permission set on non-default group/user.
contexts.remove(claim.getContext());
return getFlagDefaultPermission(claim, permission, contexts);
}
private Tristate getClaimFlagPermission(Claim claim, String permission) {
return this.getClaimFlagPermission(claim, permission, new HashSet<>(), null);
}
private Tristate getClaimFlagPermission(Claim claim, String permission, Set<Context> contexts, List<Claim> inheritParents) {
if (contexts.isEmpty()) {
if (inheritParents == null) {
inheritParents = claim.getInheritedParents();
}
contexts.addAll(this.eventContexts);
for (Claim parentClaim : inheritParents) {
GDClaim parent = (GDClaim) parentClaim;
// check parent context
contexts.add(parent.getContext());
Tristate value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, GriefDefenderPlugin.DEFAULT_HOLDER, permission, contexts, PermissionDataType.PERSISTENT);
if (value != Tristate.UNDEFINED) {
return processResult(claim, permission, value, GriefDefenderPlugin.DEFAULT_HOLDER);
}
contexts.remove(parent.getContext());
}
contexts.add(claim.getContext());
}
Tristate value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, GriefDefenderPlugin.DEFAULT_HOLDER, permission, contexts, PermissionDataType.PERSISTENT);
if (value != Tristate.UNDEFINED) {
return processResult(claim, permission, value, GriefDefenderPlugin.DEFAULT_HOLDER);
}
return getFlagDefaultPermission(claim, permission, contexts);
}
// Only uses world and claim type contexts
private Tristate getFlagDefaultPermission(Claim claim, String permission, Set<Context> contexts) {
contexts.add(claim.getDefaultTypeContext());
Tristate value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, GriefDefenderPlugin.DEFAULT_HOLDER, permission, contexts, PermissionDataType.PERSISTENT);
if (value != Tristate.UNDEFINED) {
return processResult(claim, permission, value, GriefDefenderPlugin.DEFAULT_HOLDER);
}
contexts.remove(claim.getDefaultTypeContext());
if (!claim.isWilderness()) {
contexts.add(ClaimContexts.GLOBAL_DEFAULT_CONTEXT);
contexts.add(ClaimContexts.USER_DEFAULT_CONTEXT);
value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, GriefDefenderPlugin.DEFAULT_HOLDER, permission, contexts, PermissionDataType.PERSISTENT);
if (value != Tristate.UNDEFINED) {
return processResult(claim, permission, value, GriefDefenderPlugin.DEFAULT_HOLDER);
}
contexts.remove(ClaimContexts.USER_DEFAULT_CONTEXT);
} else {
contexts.add(ClaimContexts.GLOBAL_DEFAULT_CONTEXT);
value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, GriefDefenderPlugin.DEFAULT_HOLDER, permission, contexts, PermissionDataType.PERSISTENT);
if (value != Tristate.UNDEFINED) {
return processResult(claim, permission, value, GriefDefenderPlugin.DEFAULT_HOLDER);
}
}
contexts.remove(ClaimContexts.GLOBAL_DEFAULT_CONTEXT);
contexts.add(ClaimContexts.USER_DEFAULT_CONTEXT);
contexts.add(claim.getDefaultTypeContext());
value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, GriefDefenderPlugin.GD_DEFAULT_HOLDER, permission, contexts, PermissionDataType.TRANSIENT);
if (value != Tristate.UNDEFINED) {
return processResult(claim, permission, value, GriefDefenderPlugin.GD_DEFAULT_HOLDER);
}
return processResult(claim, permission, Tristate.UNDEFINED, GriefDefenderPlugin.DEFAULT_HOLDER);
}
private Tristate getFlagOverride(Claim claim, GDPermissionHolder permissionHolder, GDPlayerData playerData, String flagPermission) {
if (!((GDClaim) claim).getInternalClaimData().allowFlagOverrides()) {
return Tristate.UNDEFINED;
}
Player player = null;
Set<Context> contexts = new HashSet<>();
if (claim.isAdminClaim()) {
contexts.add(ClaimContexts.ADMIN_OVERRIDE_CONTEXT);
} else if (claim.isTown()) {
contexts.add(ClaimContexts.TOWN_OVERRIDE_CONTEXT);
} else if (claim.isBasicClaim()) {
contexts.add(ClaimContexts.BASIC_OVERRIDE_CONTEXT);
} else if (claim.isWilderness()) {
contexts.add(ClaimContexts.WILDERNESS_OVERRIDE_CONTEXT);
player = permissionHolder instanceof GDPermissionUser ? ((GDPermissionUser) permissionHolder).getOnlinePlayer() : null;
}
if (!claim.isWilderness()) {
contexts.add(ClaimContexts.USER_OVERRIDE_CONTEXT);
}
contexts.add(((GDClaim) claim).getWorldContext());
contexts.add(ClaimContexts.GLOBAL_OVERRIDE_CONTEXT);
contexts.addAll(this.eventContexts);
Tristate value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, permissionHolder, flagPermission, contexts, PermissionDataType.PERSISTENT);
if (value == Tristate.UNDEFINED) {
// check claim owner parent override
/*final List<Claim> inheritParents = claim.getInheritedParents();
contexts = new HashSet<>();
contexts.add(((GDClaim) claim).getWorldContext());
contexts.addAll(this.eventContexts);
for (Claim parentClaim : inheritParents) {
GDClaim parent = (GDClaim) parentClaim;
// check parent override claim context
contexts.add(parent.getOverrideClaimContext());
value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, permissionHolder, flagPermission, contexts);
if (value != Tristate.UNDEFINED) {
if (value == Tristate.FALSE) {
this.eventMessage = MessageCache.getInstance().PERMISSION_OVERRIDE_DENY;
}
return processResult(claim, flagPermission, value, permissionHolder);
}
contexts.remove(parent.getOverrideClaimContext());
}*/
// check claim owner override
contexts = new HashSet<>();
contexts.add(((GDClaim) claim).getWorldContext());
contexts.addAll(this.eventContexts);
contexts.add(claim.getOverrideClaimContext());
value = PermissionUtil.getInstance().getPermissionValue((GDClaim) claim, permissionHolder, flagPermission, contexts, PermissionDataType.PERSISTENT);
}
if (value != Tristate.UNDEFINED) {
if (value == Tristate.FALSE) {
this.eventMessage = MessageCache.getInstance().PERMISSION_OVERRIDE_DENY;
}
return processResult(claim, flagPermission, value, permissionHolder);
}
return Tristate.UNDEFINED;
}
public Tristate processResult(Claim claim, String permission, Tristate permissionValue, GDPermissionHolder permissionHolder) {
return processResult(claim, permission, null, permissionValue, permissionHolder);
}
public Tristate processResult(Claim claim, String permission, String trust, Tristate permissionValue, GDPermissionHolder permissionHolder) {
if (GriefDefenderPlugin.debugActive && this.currentEvent != null) {
// Use the event subject always if available
// This prevents debug showing 'default' for users
if (eventSubject != null) {
permissionHolder = eventSubject;
} else if (permissionHolder == null) {
final Object source = GDCauseStackManager.getInstance().getCurrentCause().root();
if (source instanceof GDPermissionUser) {
permissionHolder = (GDPermissionUser) source;
} else {
permissionHolder = GriefDefenderPlugin.DEFAULT_HOLDER;
}
}
if (this.currentEvent instanceof BlockPhysicsEvent) {
if (((GDClaim) claim).getWorld().getTime() % 100 != 0L) {
return permissionValue;
}
}
GriefDefenderPlugin.addEventLogEntry(this.currentEvent, claim, this.eventLocation, this.eventSourceId, this.eventTargetId, this.eventSubject == null ? permissionHolder : this.eventSubject, permission, trust, permissionValue, this.eventContexts);
}
if (eventPlayerData != null && eventPlayerData.eventResultCache != null) {
final Flag flag = FlagRegistryModule.getInstance().getById(permission).orElse(null);
if (flag != null) {
eventPlayerData.eventResultCache = new EventResultCache((GDClaim) claim, flag.getName().toLowerCase(), permissionValue);
}
}
return permissionValue;
}
public void processEventLog(Event event, Location location, Claim claim, String permission, Object source, Object target, GDPermissionHolder user, String trust, Tristate value) {
final String sourceId = this.getPermissionIdentifier(source, true);
final String targetId = this.getPermissionIdentifier(target);
final Set<Context> sourceContexts = this.getPermissionContexts((GDClaim) claim, source, true);
if (sourceContexts == null) {
return;
}
final Set<Context> targetContexts = this.getPermissionContexts((GDClaim) claim, target, false);
if (targetContexts == null) {
return;
}
final Set<Context> contexts = new HashSet<>();
if (!(source instanceof Player) && target instanceof Player && user instanceof GDPermissionUser && ((GDPermissionUser) user).getOnlinePlayer() != null && !((GDPermissionUser) user).getUniqueId().equals(((Player) target).getUniqueId())) {
// add source player context
// this allows users to block all pvp actions when direct source isn't a player
contexts.add(new Context(ContextKeys.SOURCE, this.getPermissionIdentifier(((GDPermissionUser) user).getOnlinePlayer())));
}
contexts.addAll(sourceContexts);
contexts.addAll(targetContexts);
contexts.add(((GDClaim) claim).getWorldContext());
if (GriefDefenderPlugin.debugActive) {
if (user == null) {
final Object root = GDCauseStackManager.getInstance().getCurrentCause().root();
if (source instanceof GDPermissionUser) {
user = (GDPermissionUser) root;
} else {
user = GriefDefenderPlugin.DEFAULT_HOLDER;
}
}
GriefDefenderPlugin.addEventLogEntry(event, claim, location, sourceId, targetId, user, permission, trust.toLowerCase(), value, contexts);
}
}
public String getPermissionIdentifier(Object obj) {
return getPermissionIdentifier(obj, false);
}
public String getPermissionIdentifier(Object obj, boolean isSource) {
if (obj != null) {
if (obj instanceof Entity) {
Entity targetEntity = (Entity) obj;
if (targetEntity instanceof Item) {
return getPermissionIdentifier(((Item) targetEntity).getItemStack(), isSource);
}
if (targetEntity.getType() == null) {
// Plugin sending fake player and violating API contract so just ignore...
return "unknown";
}
final String name = targetEntity.getType().getName() == null ? targetEntity.getType().name().toLowerCase() : targetEntity.getType().getName();
final GDEntityType type = EntityTypeRegistryModule.getInstance().getByBukkitType(targetEntity);
if (type == null) {
// Should never happen
return name;
}
String id = type.getId();
return populateEventSourceTarget(id, isSource);
} else if (obj instanceof Block) {
final Block block = (Block) obj;
if (GriefDefenderPlugin.getInstance().getSlimefunProvider() != null) {
final String customItemId = GriefDefenderPlugin.getInstance().getSlimefunProvider().getSlimeBlockId(block);
if (customItemId != null && !customItemId.isEmpty()) {
return populateEventSourceTarget(customItemId, isSource);
}
}
final String id = BlockTypeRegistryModule.getInstance().getNMSKey(block);
return populateEventSourceTarget(id, isSource);
} else if (obj instanceof BlockState) {
final BlockState blockstate = (BlockState) obj;
if (blockstate.getBlock().getType() != blockstate.getType()) {
return populateEventSourceTarget(blockstate.getType().name().toLowerCase(), isSource);
}
if (GriefDefenderPlugin.getInstance().getSlimefunProvider() != null) {
final String customItemId = GriefDefenderPlugin.getInstance().getSlimefunProvider().getSlimeBlockId(blockstate.getBlock());
if (customItemId != null && !customItemId.isEmpty()) {
return populateEventSourceTarget(customItemId, isSource);
}
}
final String id = BlockTypeRegistryModule.getInstance().getNMSKey(blockstate);
return populateEventSourceTarget(id, isSource);
} else if (obj instanceof Material) {
final String id = ((Material) obj).name().toLowerCase();
return populateEventSourceTarget(id, isSource);
} /*else if (obj instanceof TileEntity) {
TileEntity tileEntity = (TileEntity) obj;
final String id = tileEntity.getMinecraftKeyString();
return populateEventSourceTarget(id, isSource);
}*/ else if (obj instanceof Inventory) {
final String id = ((Inventory) obj).getType().name().toLowerCase();
return populateEventSourceTarget(id, isSource);
} else if (obj instanceof InventoryType) {
final String id = ((InventoryType) obj).name().toLowerCase();
populateEventSourceTarget(id, isSource);
return id;
} else if (obj instanceof Item) {
} else if (obj instanceof ItemStack) {
final ItemStack itemstack = (ItemStack) obj;
if (GriefDefenderPlugin.getInstance().isCustomItemsInstalled) {
final String customItemId = NMSUtil.getInstance().getItemStackNBTString(itemstack, "com.jojodmo.customitems.itemID");
if (customItemId != null && !customItemId.isEmpty()) {
return populateEventSourceTarget("customitems:" + customItemId, isSource);
}
}
if (GriefDefenderPlugin.getInstance().getSlimefunProvider() != null) {
final String customItemId = GriefDefenderPlugin.getInstance().getSlimefunProvider().getSlimeItemId(itemstack);
if (customItemId != null && !customItemId.isEmpty()) {
return populateEventSourceTarget(customItemId, isSource);
}
}
String id = ItemTypeRegistryModule.getInstance().getNMSKey(itemstack);
return populateEventSourceTarget(id, isSource);
} else if (obj instanceof DamageCause) {
final DamageCause damageCause = (DamageCause) obj;
String id = damageCause.name().toLowerCase();
return populateEventSourceTarget(id, isSource);
} else if (obj instanceof TeleportCause) {
final TeleportCause teleportCause = (TeleportCause) obj;
String id = teleportCause.name().toLowerCase();
return populateEventSourceTarget(id, isSource);
} else if (obj instanceof SpawnReason) {
return populateEventSourceTarget("spawnreason:" + ((SpawnReason) obj).name().toLowerCase(), isSource);
} else if (obj instanceof CreatureSpawner) {
final CreatureSpawner spawner = (CreatureSpawner) obj;
return this.getPermissionIdentifier(spawner.getBlock());
} else if (obj instanceof String) {
final String id = obj.toString().toLowerCase();
return populateEventSourceTarget(id, isSource);
}
}
populateEventSourceTarget("none", isSource);
return "";
}
public Set<Context> getPermissionContexts(GDClaim claim, Object obj, boolean isSource) {
final Set<Context> contexts = new HashSet<>();
if (obj == null) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_ANY);
} else {
contexts.add(ContextGroups.TARGET_ANY);
}
return contexts;
}
if (obj instanceof Entity) {
Entity targetEntity = (Entity) obj;
if (targetEntity instanceof Item) {
return getPermissionContexts(claim, ((Item) targetEntity).getItemStack(), isSource);
}
if (targetEntity.getType() == null) {
// Plugin sending fake player and violating API contract so just ignore...
return contexts;
}
final GDEntityType type = EntityTypeRegistryModule.getInstance().getByBukkitType(targetEntity);
String id = type.getId();
if (!(targetEntity instanceof Player)) {
addCustomEntityTypeContexts(targetEntity, id, contexts, type, isSource);
} else {
final Player player = (Player) targetEntity;
if (PlayerUtil.getInstance().isFakePlayer(player)) {
final String modId = EntityTypeRegistryModule.getInstance().findModIdFromBukkit(targetEntity);
id = modId + ":fakeplayer_" + EntityTypeRegistryModule.getInstance().getFriendlyName(targetEntity.getName());
}
}
if (this.isObjectIdBanned(claim, id, BanType.ENTITY)) {
return null;
}
return populateEventSourceTargetContext(contexts, id, isSource);
} else if (obj instanceof Block) {
final Block block = (Block) obj;
if (GriefDefenderPlugin.getInstance().getSlimefunProvider() != null) {
final String customItemId = GriefDefenderPlugin.getInstance().getSlimefunProvider().getSlimeBlockId(block, contexts);
if (customItemId != null && !customItemId.isEmpty()) {
return populateEventSourceTargetContext(contexts, customItemId, isSource);
}
}
String id = BlockTypeRegistryModule.getInstance().getNMSKey(block);
if (GriefDefenderPlugin.getGlobalConfig().getConfig().mod.convertBlockId(id)) {
final GDTileType tileType = TileEntityTypeRegistryModule.getInstance().getByBlock(block.getLocation());
if (tileType != null) {
id = tileType.getId();
}
}
this.addBlockContexts(contexts, block, isSource);
if (this.isObjectIdBanned(claim, id, BanType.BLOCK)) {
return null;
}
return populateEventSourceTargetContext(contexts, id, isSource);
} else if (obj instanceof BlockState) {
final BlockState blockstate = (BlockState) obj;
final Block block = blockstate.getBlock();
if (block.getType() != blockstate.getType()) {
return populateEventSourceTargetContext(contexts, blockstate.getType().name().toLowerCase(), isSource);
}
if (GriefDefenderPlugin.getInstance().getSlimefunProvider() != null) {
final String customItemId = GriefDefenderPlugin.getInstance().getSlimefunProvider().getSlimeBlockId(block, contexts);
if (customItemId != null && !customItemId.isEmpty()) {
return populateEventSourceTargetContext(contexts, customItemId, isSource);
}
}
String id = BlockTypeRegistryModule.getInstance().getNMSKey(blockstate);
if (GriefDefenderPlugin.getGlobalConfig().getConfig().mod.convertBlockId(id)) {
final GDTileType tileType = TileEntityTypeRegistryModule.getInstance().getByBlock(block.getLocation());
if (tileType != null) {
id = tileType.getId();
}
}
this.addBlockContexts(contexts, block, isSource);
if (this.isObjectIdBanned(claim, id, BanType.BLOCK)) {
return null;
}
return populateEventSourceTargetContext(contexts, id, isSource);
} else if (obj instanceof Material) {
final String id = BlockTypeRegistryModule.getInstance().getNMSKey((Material) obj);
return populateEventSourceTargetContext(contexts, id, isSource);
} else if (obj instanceof Inventory) {
final String id = ((Inventory) obj).getType().name().toLowerCase();
return populateEventSourceTargetContext(contexts, id, isSource);
} else if (obj instanceof InventoryType) {
final String id = ((InventoryType) obj).name().toLowerCase();
return populateEventSourceTargetContext(contexts, id, isSource);
} else if (obj instanceof ItemStack) {
final ItemStack itemstack = (ItemStack) obj;
if (GriefDefenderPlugin.getInstance().isCustomItemsInstalled) {
final String customItemId = NMSUtil.getInstance().getItemStackNBTString(itemstack, "com.jojodmo.customitems.itemID");
if (customItemId != null && !customItemId.isEmpty()) {
return populateEventSourceTargetContext(contexts, "customitems:" + customItemId, isSource);
}
}
if (GriefDefenderPlugin.getInstance().getSlimefunProvider() != null) {
final String customItemId = GriefDefenderPlugin.getInstance().getSlimefunProvider().getSlimeItemId(itemstack, contexts);
if (customItemId != null && !customItemId.isEmpty()) {
return populateEventSourceTargetContext(contexts, customItemId, isSource);
}
}
if (NMSUtil.getInstance().isItemFood(itemstack)) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_FOOD);
} else {
contexts.add(ContextGroups.TARGET_FOOD);
}
}
if (NMSUtil.getInstance().isItemHanging(itemstack)) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_HANGING);
} else {
contexts.add(ContextGroups.TARGET_HANGING);
}
}
if (NMSUtil.getInstance().isItemBoat(itemstack) || NMSUtil.getInstance().isItemMinecart(itemstack)) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_VEHICLE);
} else {
contexts.add(ContextGroups.TARGET_VEHICLE);
}
}
if (NMSUtil.getInstance().isItemPotion(itemstack)) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_POTION);
} else {
contexts.add(ContextGroups.TARGET_POTION);
}
if (GriefDefenderPlugin.getGlobalConfig().getConfig().context.potionEffects) {
final List<String> effects = NMSUtil.getInstance().getPotionEffects(itemstack);
for (String effect : effects) {
contexts.add(new Context("potion_effect", effect.toLowerCase()));
}
if (!effects.isEmpty()) {
contexts.add(new Context("potion_effect", ContextGroupKeys.ANY));
}
}
}
if (GriefDefenderPlugin.getGlobalConfig().getConfig().context.enchantments) {
// add enchantment contexts
final List<String> enchantments = NMSUtil.getInstance().getEnchantments(itemstack);
for (String enchantment : enchantments) {
final String[] parts = enchantment.split(",");
for (String part : parts) {
if (part.startsWith("id:")) {
part = part.replace("id:", "");
part = part.replace("\"", "");
part = part.substring(0, part.length() - 1);
if (Character.isDigit(part.charAt(0))) {
part = part.replaceAll("[^0-9]", "");
part = NMSUtil.getInstance().getEnchantmentId(Integer.valueOf(part));
}
contexts.add(new Context("enchant", part));
}
}
enchantment = enchantment.replace("\"", "");
enchantment = enchantment.substring(1, enchantment.length() - 1);
contexts.add(new Context("enchant_data", enchantment));
}
if (!enchantments.isEmpty()) {
contexts.add(new Context("enchant", ContextGroupKeys.ANY));
}
}
String id = ItemTypeRegistryModule.getInstance().getNMSKey(itemstack);
if (GriefDefenderPlugin.getGlobalConfig().getConfig().mod.convertBlockId(id)) {
final String itemName = NMSUtil.getInstance().getItemName(itemstack, id);
if (itemName != null) {
if (!itemName.contains(":")) {
final int index = id.indexOf(":");
final String modId = id.substring(0, index);
id = modId + ":" + itemName;
} else {
id = itemName;
}
}
}
if (this.isObjectIdBanned(claim, id, BanType.ITEM)) {
return null;
}
return populateEventSourceTargetContext(contexts, id, isSource);
} else if (obj instanceof DamageCause) {
final DamageCause damageCause = (DamageCause) obj;
String id = damageCause.name().toLowerCase();
return populateEventSourceTargetContext(contexts, id, isSource);
} else if (obj instanceof TeleportCause) {
final TeleportCause teleportCause = (TeleportCause) obj;
String id = teleportCause.name().toLowerCase();
return populateEventSourceTargetContext(contexts, id, isSource);
} else if (obj instanceof SpawnReason) {
return populateEventSourceTargetContext(contexts, "spawnreason:" + ((SpawnReason) obj).name().toLowerCase(), isSource);
} else if (obj instanceof CreatureSpawner) {
final CreatureSpawner spawner = (CreatureSpawner) obj;
return this.getPermissionContexts(claim, spawner.getBlock(), isSource);
} else if (obj instanceof String) {
final String id = obj.toString().toLowerCase();
return populateEventSourceTargetContext(contexts, id, isSource);
}
return contexts;
}
public boolean isObjectIdBanned(GDClaim claim, String id, BanType type) {
if (id.equalsIgnoreCase("player")) {
return false;
}
GDPermissionUser user = null;
if (this.eventSubject != null && this.eventSubject instanceof GDPermissionUser) {
user = (GDPermissionUser) this.eventSubject;
if (user.getInternalPlayerData() != null && user.getInternalPlayerData().canIgnoreClaim(claim)) {
return false;
}
}
final String permission = StringUtils.replace(id, ":", ".");
Component banReason = null;
final BanCategory banCategory = GriefDefenderPlugin.getGlobalConfig().getConfig().bans;
if (type == BanType.BLOCK) {
for (Entry<String, Component> banId : banCategory.getBlockMap().entrySet()) {
if (FilenameUtils.wildcardMatch(id, banId.getKey())) {
banReason = GriefDefenderPlugin.getGlobalConfig().getConfig().bans.getBlockBanReason(banId.getKey());
if (banReason != null && banReason.equals(TextComponent.empty())) {
banReason = MessageStorage.MESSAGE_DATA.getMessage(MessageStorage.PERMISSION_BAN_BLOCK,
ImmutableMap.of("id", TextComponent.of(id, TextColor.GOLD)));
}
break;
}
}
} else if (type == BanType.ITEM) {
for (Entry<String, Component> banId : banCategory.getItemMap().entrySet()) {
if (FilenameUtils.wildcardMatch(id, banId.getKey())) {
banReason = GriefDefenderPlugin.getGlobalConfig().getConfig().bans.getItemBanReason(banId.getKey());
if (banReason != null && banReason.equals(TextComponent.empty())) {
banReason = MessageStorage.MESSAGE_DATA.getMessage(MessageStorage.PERMISSION_BAN_ITEM,
ImmutableMap.of("id", TextComponent.of(id, TextColor.GOLD)));
}
}
}
} else if (type == BanType.ENTITY) {
for (Entry<String, Component> banId : banCategory.getEntityMap().entrySet()) {
if (FilenameUtils.wildcardMatch(id, banId.getKey())) {
banReason = GriefDefenderPlugin.getGlobalConfig().getConfig().bans.getEntityBanReason(banId.getKey());
if (banReason != null && banReason.equals(TextComponent.empty())) {
banReason = MessageStorage.MESSAGE_DATA.getMessage(MessageStorage.PERMISSION_BAN_ENTITY,
ImmutableMap.of("id", TextComponent.of(id, TextColor.GOLD)));
}
}
}
}
if (banReason != null && user != null) {
final Player player = user.getOnlinePlayer();
if (player != null) {
if (banReason.equals(TextComponent.empty())) {
banReason = MessageStorage.MESSAGE_DATA.getMessage(MessageStorage.PERMISSION_BAN_BLOCK,
ImmutableMap.of("id", id));
}
TextAdapter.sendComponent(player, banReason);
this.processResult(claim, permission, "banned", Tristate.FALSE, user);
return true;
}
}
if (banReason != null) {
// Detected ban
this.processResult(claim, permission, "banned", Tristate.FALSE, this.eventSubject);
return true;
}
return false;
}
public void addCustomEntityTypeContexts(Entity targetEntity, String id, Set<Context> contexts, GDEntityType type, boolean isSource) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_ANY);
contexts.add(new Context(ContextKeys.SOURCE, "#" + type.getModId().toLowerCase() + ":any"));
} else {
contexts.add(ContextGroups.TARGET_ANY);
contexts.add(new Context(ContextKeys.TARGET, "#" + type.getModId().toLowerCase() + ":any"));
}
// check vehicle
if (targetEntity instanceof Vehicle) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_VEHICLE);
} else {
contexts.add(ContextGroups.TARGET_VEHICLE);
}
}
// pixelmon
if (targetEntity.getType() != null && targetEntity.getType().name().equalsIgnoreCase("pixelmon_pixelmon") || targetEntity.getType().name().equalsIgnoreCase("pixelmon")) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_PIXELMON);
} else {
contexts.add(ContextGroups.TARGET_PIXELMON);
}
}
// potion
if (targetEntity instanceof ThrownPotion && GriefDefenderPlugin.getGlobalConfig().getConfig().context.potionEffects) {
final ThrownPotion potion = (ThrownPotion) targetEntity;
for (PotionEffect effect : potion.getEffects()) {
contexts.add(new Context("potion_effect", effect.getType().getName().toLowerCase()));
}
if (!potion.getEffects().isEmpty()) {
contexts.add(new Context("potion_effect", ContextGroupKeys.ANY));
}
}
final String creatureType = type.getEnumCreatureTypeId();
if (creatureType == null) {
return;
}
final String modId = type.getModId().toLowerCase();
if (creatureType.contains("animal")) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_ANIMAL);
contexts.add(new Context(ContextKeys.SOURCE, "#" + modId + ":animal"));
} else {
contexts.add(ContextGroups.TARGET_ANIMAL);
contexts.add(new Context(ContextKeys.TARGET, "#" + modId + ":animal"));
}
this.checkPetContext(targetEntity, modId, contexts, isSource);
} else if (creatureType.contains("aquatic")) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_AQUATIC);
contexts.add(new Context(ContextKeys.SOURCE, "#" + modId + ":aquatic"));
} else {
contexts.add(ContextGroups.TARGET_AQUATIC);
contexts.add(new Context(ContextKeys.TARGET, "#" + modId + ":aquatic"));
}
this.checkPetContext(targetEntity, modId, contexts, isSource);
} else if (creatureType.contains("monster")) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_MONSTER);
contexts.add(new Context(ContextKeys.SOURCE, "#" + modId + ":monster"));
} else {
contexts.add(ContextGroups.TARGET_MONSTER);
contexts.add(new Context(ContextKeys.TARGET, "#" + modId + ":monster"));
}
} else if (creatureType.contains("ambient")) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_AMBIENT);
contexts.add(new Context(ContextKeys.SOURCE, "#" + modId + ":ambient"));
} else {
contexts.add(ContextGroups.TARGET_AMBIENT);
contexts.add(new Context(ContextKeys.TARGET, "#" + modId + ":ambient"));
}
this.checkPetContext(targetEntity, modId, contexts, isSource);
} else {
if (isSource) {
contexts.add(ContextGroups.SOURCE_MISC);
contexts.add(new Context(ContextKeys.SOURCE, "#" + modId + ":misc"));
} else {
contexts.add(ContextGroups.TARGET_MISC);
contexts.add(new Context(ContextKeys.TARGET, "#" + modId + ":misc"));
}
}
}
private void checkPetContext(Entity targetEntity, String modId, Set<Context> contexts, boolean isSource) {
if (this.eventSubject != null && this.eventSubject instanceof GDPermissionUser) {
final GDPermissionUser user = (GDPermissionUser) this.eventSubject;
final UUID uuid = NMSUtil.getInstance().getTameableOwnerUUID(targetEntity);
if (uuid != null && uuid.equals(user.getUniqueId())) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_PET);
if (modId != null && !modId.isEmpty()) {
contexts.add(new Context(ContextKeys.SOURCE, "#" + modId + ":pet"));
}
} else {
contexts.add(ContextGroups.TARGET_PET);
if (modId != null && !modId.isEmpty()) {
contexts.add(new Context(ContextKeys.TARGET, "#" + modId + ":pet"));
}
}
}
}
}
private void addPlayerContexts(Player player, Set<Context> contexts, Flag flag) {
Context usedItemContext = null;
for (Context context : contexts) {
if (context.getKey().equals(ContextKeys.USED_ITEM)) {
usedItemContext = context;
break;
}
}
if(usedItemContext == null) {
// special case
if (this.currentEvent instanceof PlayerBucketEvent) {
final PlayerBucketEvent bucketEvent = (PlayerBucketEvent) this.currentEvent;
contexts.add(new Context(ContextKeys.USED_ITEM, "minecraft:" + bucketEvent.getBucket().name().toLowerCase()));
} else {
final ItemStack stack = NMSUtil.getInstance().getActiveItem(player, this.currentEvent);
if (stack != null && stack.getType() != Material.AIR) {
final String stackId = getPermissionIdentifier(stack);
contexts.add(new Context(ContextKeys.USED_ITEM, stackId));
if (stack.getItemMeta() != null && stack.getItemMeta().getDisplayName() != null) {
String itemName = stack.getItemMeta().getDisplayName().replaceAll("[^A-Za-z0-9]", "").toLowerCase();
if (GriefDefenderPlugin.getInstance().getSlimefunProvider() != null) {
final String slimefunId = GriefDefenderPlugin.getInstance().getSlimefunProvider().getSlimeItemDisplayName(stack);
if (slimefunId != null && !slimefunId.isEmpty()) {
itemName = slimefunId;
}
}
if (itemName != null && !itemName.isEmpty()) {
if (!itemName.contains(":")) {
itemName = "minecraft:" + itemName;
}
contexts.add(new Context("item_name", itemName));
}
}
// populate item tag
if (GriefDefenderPlugin.getInstance().getTagProvider() != null) {
final Set<Context> tagContexts = GriefDefenderPlugin.getInstance().getTagProvider().getTagMap().get(stackId);
if (tagContexts != null) {
for (Context context : tagContexts) {
contexts.add(new Context(ContextKeys.USED_ITEM, "#" + context.getKey() + ":" + context.getValue()));
if (context.getKey().equalsIgnoreCase("minecraft")) {
contexts.add(new Context(ContextKeys.USED_ITEM, "#" + context.getValue()));
}
}
}
}
}
}
} else {
// populate item tag
if (GriefDefenderPlugin.getInstance().getTagProvider() != null) {
final Set<Context> tagContexts = GriefDefenderPlugin.getInstance().getTagProvider().getTagMap().get(usedItemContext.getValue());
if (tagContexts != null) {
for (Context context : tagContexts) {
contexts.add(new Context(ContextKeys.USED_ITEM, "#" + context.getKey() + ":" + context.getValue()));
if (context.getKey().equalsIgnoreCase("minecraft")) {
contexts.add(new Context(ContextKeys.USED_ITEM, "#" + context.getValue()));
}
}
}
}
}
if (GriefDefenderPlugin.getGlobalConfig().getConfig().context.playerEquipment) {
final ItemStack helmet = player.getInventory().getHelmet();
final ItemStack chestplate = player.getInventory().getChestplate();
final ItemStack leggings = player.getInventory().getLeggings();
final ItemStack boots = player.getInventory().getBoots();
if (helmet != null) {
contexts.add(new Context("helmet", getPermissionIdentifier(helmet)));
}
if (chestplate != null) {
contexts.add(new Context("chestplate", getPermissionIdentifier(chestplate)));
}
if (leggings != null) {
contexts.add(new Context("leggings", getPermissionIdentifier(leggings)));
}
if (boots != null) {
contexts.add(new Context("boots", getPermissionIdentifier(boots)));
}
}
if (GriefDefenderPlugin.getGlobalConfig().getConfig().context.enchantments) {
// add player item enchantment contexts
final List<String> enchantments = NMSUtil.getInstance().getEnchantmentsItemMainHand(player);
for (String enchantment : enchantments) {
final String[] parts = enchantment.split(",");
for (String part : parts) {
if (part.startsWith("id:")) {
part = part.replace("id:", "");
part = part.replace("\"", "");
part = part.substring(0, part.length() - 1);
if (Character.isDigit(part.charAt(0))) {
part = part.replaceAll("[^0-9]", "");
part = NMSUtil.getInstance().getEnchantmentId(Integer.valueOf(part));
}
contexts.add(new Context("mainhand_enchant", part));
contexts.add(new Context("mainhand_enchant", ContextGroupKeys.ANY));
}
}
enchantment = enchantment.replace("\"", "");
enchantment = enchantment.substring(1, enchantment.length() - 1);
contexts.add(new Context("mainhand_enchant_data", enchantment));
}
if (!enchantments.isEmpty()) {
contexts.add(new Context("mainhand_enchant", ContextGroupKeys.ANY));
}
final List<String> offEnchantments = NMSUtil.getInstance().getEnchantmentsItemOffHand(player);
for (String enchantment : offEnchantments) {
final String[] parts = enchantment.split(",");
for (String part : parts) {
if (part.startsWith("id:")) {
part = part.replace("id:", "");
part = part.replace("\"", "");
part = part.substring(0, part.length() - 1);
if (Character.isDigit(part.charAt(0))) {
part = part.replaceAll("[^0-9]", "");
part = NMSUtil.getInstance().getEnchantmentId(Integer.valueOf(part));
}
contexts.add(new Context("offhand_enchant", part));
}
}
enchantment = enchantment.replace("\"", "");
enchantment = enchantment.substring(1, enchantment.length() - 1);
contexts.add(new Context("offhand_enchant_data", enchantment));
}
if (!offEnchantments.isEmpty()) {
contexts.add(new Context("offhand_enchant", ContextGroupKeys.ANY));
}
}
}
private Set<Context> addBlockContexts(Set<Context> contexts, Block block, boolean isSource) {
Matcher matcher = BLOCKSTATE_PATTERN.matcher(NMSUtil.getInstance().getBlockDataString((Block) block));
if (matcher.find()) {
final String properties[] = matcher.group(0).split(",");
for (String property : properties) {
String prop = property.replace("=", ":");
if (prop.equals("type:invalid")) {
// ignore
continue;
}
contexts.add(new Context(ContextKeys.STATE, prop));
}
}
if (NMSUtil.getInstance().isBlockCrops(block)) {
if (isSource) {
contexts.add(ContextGroups.SOURCE_CROPS);
} else {
contexts.add(ContextGroups.TARGET_CROPS);
}
} else if (NMSUtil.getInstance().isBlockPlant(block)){
if (isSource) {
contexts.add(ContextGroups.SOURCE_PLANTS);
} else {
contexts.add(ContextGroups.TARGET_PLANTS);
}
}
return contexts;
}
public String getIdentifierWithoutMeta(String targetId) {
Matcher m = PATTERN_META.matcher(targetId);
String targetMeta = "";
if (m.find()) {
targetMeta = m.group(0);
targetId = StringUtils.replace(targetId, targetMeta, "");
}
return targetId;
}
private Set<Context> populateEventSourceTargetContext(Set<Context> contexts, String id, boolean isSource) {
if (!id.contains(":")) {
id = "minecraft:" + id;
}
contexts = this.populateTagContextsForId(contexts, id, isSource);
// always add source/target any contexts
contexts.add(ContextGroups.SOURCE_ANY);
contexts.add(ContextGroups.TARGET_ANY);
final String[] parts = id.split(":");
final String modId = parts[0];
if (isSource) {
this.eventSourceId = id.toLowerCase();
contexts.add(new Context("source", this.eventSourceId));
contexts.add(new Context("source", modId + ":any"));
} else {
this.eventTargetId = id.toLowerCase();
contexts.add(new Context("target", this.eventTargetId));
contexts.add(new Context("target", modId + ":any"));
}
return contexts;
}
public Set<Context> populateTagContextsForId(Set<Context> contexts, String id, boolean isSource) {
if (GriefDefenderPlugin.getInstance().getTagProvider() == null) {
return contexts;
}
final Set<Context> tagContexts = GriefDefenderPlugin.getInstance().getTagProvider().getTagMap().get(id);
if (tagContexts == null) {
return contexts;
}
for (Context context : tagContexts) {
if (isSource) {
contexts.add(new Context(ContextKeys.SOURCE, "#" + context.getKey() + ":" + context.getValue()));
if (context.getKey().equalsIgnoreCase("minecraft")) {
contexts.add(new Context(ContextKeys.SOURCE, "#" + context.getValue()));
}
} else {
contexts.add(new Context(ContextKeys.TARGET, "#" + context.getKey() + ":" + context.getValue()));
if (context.getKey().equalsIgnoreCase("minecraft")) {
contexts.add(new Context(ContextKeys.TARGET, "#" + context.getValue()));
}
}
}
return contexts;
}
private String populateEventSourceTarget(String id, boolean isSource) {
if (this.blacklistCheck) {
return id;
}
if (!id.contains(":")) {
id = "minecraft:" + id;
}
String[] parts = id.split(":");
if (parts != null && parts.length == 3) {
if (parts[0].equals(parts[1])) {
id = parts[1] + ":" + parts[2];
}
}
if (isSource) {
this.eventSourceId = id.toLowerCase();
} else {
this.eventTargetId = id.toLowerCase();
}
return id;
}
@Override
public CompletableFuture<PermissionResult> clearAllFlagPermissions(Subject subject) {
CompletableFuture<PermissionResult> result = new CompletableFuture<>();
if (subject == null) {
result.complete(new GDPermissionResult(ResultTypes.SUBJECT_DOES_NOT_EXIST));
return result;
}
GDFlagPermissionEvent.ClearAll event = new GDFlagPermissionEvent.ClearAll(subject);
GriefDefender.getEventManager().post(event);
if (event.cancelled()) {
result.complete(new GDPermissionResult(ResultTypes.EVENT_CANCELLED, event.getMessage().orElse(null)));
return result;
}
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : PermissionUtil.getInstance().getPermanentPermissions((GDPermissionHolder) subject).entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
for (Context context : contextSet) {
if (context.getValue().equals(subject.getIdentifier())) {
PermissionUtil.getInstance().clearPermissions((GDPermissionHolder) subject, context);
}
}
}
result.complete(new GDPermissionResult(ResultTypes.SUCCESS));
return result;
}
@Override
public CompletableFuture<PermissionResult> clearFlagPermissions(Set<Context> contexts) {
return clearFlagPermissions(GriefDefenderPlugin.DEFAULT_HOLDER, contexts);
}
@Override
public CompletableFuture<PermissionResult> clearFlagPermissions(Subject subject, Set<Context> contexts) {
CompletableFuture<PermissionResult> result = new CompletableFuture<>();
if (subject == null) {
result.complete(new GDPermissionResult(ResultTypes.SUBJECT_DOES_NOT_EXIST));
}
GDFlagPermissionEvent.Clear event = new GDFlagPermissionEvent.Clear(subject, contexts);
GriefDefender.getEventManager().post(event);
if (event.cancelled()) {
result.complete(new GDPermissionResult(ResultTypes.EVENT_CANCELLED, event.getMessage().orElse(null)));
return result;
}
PermissionUtil.getInstance().clearPermissions((GDPermissionHolder) subject, contexts);
result.complete(new GDPermissionResult(ResultTypes.SUCCESS));
return result;
}
@Override
public CompletableFuture<PermissionResult> setFlagPermission(Flag flag, Tristate value, Set<Context> contexts) {
return setPermission(GriefDefenderPlugin.DEFAULT_HOLDER, flag, value, contexts);
}
public CompletableFuture<PermissionResult> setPermission(Subject subject, Flag flag, Tristate value, Set<Context> contexts) {
CompletableFuture<PermissionResult> result = new CompletableFuture<>();
GDFlagPermissionEvent.Set event = new GDFlagPermissionEvent.Set(subject, flag, value, contexts);
GriefDefender.getEventManager().post(event);
if (event.cancelled()) {
result.complete(new GDPermissionResult(ResultTypes.EVENT_CANCELLED, event.getMessage().orElse(null)));
return result;
}
return PermissionUtil.getInstance().setPermissionValue((GDPermissionHolder) subject, flag, value, contexts);
}
// internal
public CompletableFuture<PermissionResult> setPermission(Claim claim, GDPermissionHolder subject, Flag flag, String target, Tristate value, Set<Context> contexts) {
if (target.equalsIgnoreCase("any:any")) {
target = "any";
}
CompletableFuture<PermissionResult> result = new CompletableFuture<>();
if (flag != Flags.COMMAND_EXECUTE && flag != Flags.COMMAND_EXECUTE_PVP) {
String[] parts = target.split(":");
if (!target.startsWith("#") && parts.length > 1 && parts[0].equalsIgnoreCase("minecraft")) {
target = parts[1];
}
if (target != null && !GriefDefenderPlugin.ID_MAP.contains(target)) {
result.complete(new GDPermissionResult(ResultTypes.TARGET_NOT_VALID));
return result;
}
}
contexts.add(new Context(ContextKeys.TARGET, target));
GDFlagPermissionEvent.Set event = new GDFlagPermissionEvent.Set(subject, flag, value, contexts);
GriefDefender.getEventManager().post(event);
if (event.cancelled()) {
result.complete(new GDPermissionResult(ResultTypes.EVENT_CANCELLED, event.getMessage().orElse(null)));
return result;
}
final GDPermissionUser user = GDCauseStackManager.getInstance().getCurrentCause().first(GDPermissionUser.class).orElse(null);
CommandSender commandSource = user != null && user.getOnlinePlayer() != null ? user.getOnlinePlayer() : Bukkit.getConsoleSender();
result.complete(CommandHelper.addFlagPermission(commandSource, subject, claim, flag, target, value, contexts));
return result;
}
@Override
public Tristate getFlagPermissionValue(Flag flag, Set<Context> contexts) {
return getPermissionValue(GriefDefenderPlugin.DEFAULT_HOLDER, flag, contexts);
}
public Tristate getPermissionValue(GDPermissionHolder subject, Flag flag, Set<Context> contexts) {
return PermissionUtil.getInstance().getPermissionValue(subject, flag.getPermission(), contexts);
}
@Override
public Map<String, Boolean> getFlagPermissions(Set<Context> contexts) {
return getFlagPermissions(GriefDefenderPlugin.DEFAULT_HOLDER, contexts);
}
@Override
public Map<String, Boolean> getFlagPermissions(Subject subject, Set<Context> contexts) {
if (subject == null) {
return new HashMap<>();
}
return PermissionUtil.getInstance().getPermissions((GDPermissionHolder) subject, contexts);
}
public static GDPermissionManager getInstance() {
return instance;
}
static {
instance = new GDPermissionManager();
}
@Override
public Optional<String> getOptionValue(Option option, Set<Context> contexts) {
return Optional.empty();
}
@Override
public Optional<String> getOptionValue(Subject subject, Option option, Set<Context> contexts) {
return Optional.empty();
}
public <T> T getInternalOptionValue(TypeToken<T> type, OfflinePlayer player, Option<T> option) {
return getInternalOptionValue(type, player, option, (ClaimType) null);
}
public <T> T getInternalOptionValue(TypeToken<T> type, OfflinePlayer player, Option<T> option, Claim claim) {
final GDPermissionHolder holder = PermissionHolderCache.getInstance().getOrCreateHolder(player.getUniqueId().toString());
if (claim != null) {
return this.getInternalOptionValue(type, holder, option, claim, claim.getType(), new HashSet<>());
}
return this.getInternalOptionValue(type, holder, option, (ClaimType) null);
}
public <T> T getInternalOptionValue(TypeToken<T> type, OfflinePlayer player, Option<T> option, ClaimType claimType) {
final GDPermissionHolder holder = PermissionHolderCache.getInstance().getOrCreateHolder(player.getUniqueId().toString());
return this.getInternalOptionValue(type, holder, option, null, claimType, new HashSet<>());
}
public <T> T getInternalOptionValue(TypeToken<T> type, GDPermissionHolder holder, Option<T> option) {
return this.getInternalOptionValue(type, holder, option, (ClaimType) null);
}
public <T> T getInternalOptionValue(TypeToken<T> type, GDPermissionHolder holder, Option<T> option, Claim claim) {
if (claim != null) {
return this.getInternalOptionValue(type, holder, option, claim, claim.getType(), new HashSet<>());
}
return this.getInternalOptionValue(type, holder, option, (ClaimType) null);
}
public <T> T getInternalOptionValue(TypeToken<T> type, GDPermissionHolder holder, Option<T> option, Set<Context> contexts) {
return getInternalOptionValue(type, holder, option, null, null, contexts);
}
public <T> T getInternalOptionValue(TypeToken<T> type, GDPermissionHolder holder, Option<T> option, Claim claim, Set<Context> contexts) {
return getInternalOptionValue(type, holder, option, claim, null, contexts);
}
public <T> T getInternalOptionValue(TypeToken<T> type, GDPermissionHolder holder, Option<T> option, ClaimType claimType) {
return this.getInternalOptionValue(type, holder, option, null, claimType, new HashSet<>());
}
public <T> T getInternalOptionValue(TypeToken<T> type, GDPermissionHolder holder, Option<T> option, Claim claim, ClaimType claimType, Set<Context> contexts) {
if (holder != GriefDefenderPlugin.DEFAULT_HOLDER && holder instanceof GDPermissionUser) {
final GDPermissionUser user = (GDPermissionUser) holder;
final GDPlayerData playerData = (GDPlayerData) user.getPlayerData();
// Prevent world contexts being added when checking for accrued blocks in global mode
if (option != Options.ACCRUED_BLOCKS || GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.useWorldPlayerData()) {
PermissionUtil.getInstance().addActiveContexts(contexts, holder, playerData, claim);
}
}
Set<Context> optionContexts = new HashSet<>(contexts);
if (!option.isGlobal() && (claim != null || claimType != null)) {
// check claim
if (claim != null) {
// check override
if (claim.isAdminClaim()) {
optionContexts.add(ClaimContexts.ADMIN_OVERRIDE_CONTEXT);
} else if (claim.isTown()) {
optionContexts.add(ClaimContexts.TOWN_OVERRIDE_CONTEXT);
} else if (claim.isBasicClaim()) {
optionContexts.add(ClaimContexts.BASIC_OVERRIDE_CONTEXT);
} else if (claim.isWilderness()) {
optionContexts.add(ClaimContexts.WILDERNESS_OVERRIDE_CONTEXT);
}
if (!claim.isWilderness()) {
optionContexts.add(ClaimContexts.USER_OVERRIDE_CONTEXT);
}
optionContexts.add(((GDClaim) claim).getWorldContext());
optionContexts.add(ClaimContexts.GLOBAL_OVERRIDE_CONTEXT);
T value = this.getOptionActualValue(type, holder, option, optionContexts);
if (value != null) {
return value;
}
// check claim owner override
optionContexts = new HashSet<>(contexts);
optionContexts.add(((GDClaim) claim).getWorldContext());
optionContexts.add(claim.getOverrideClaimContext());
value = this.getOptionActualValue(type, holder, option, optionContexts);
if (value != null) {
return value;
}
optionContexts = new HashSet<>(contexts);
optionContexts.add(claim.getContext());
value = this.getOptionActualValue(type, holder, option, optionContexts);
if (value != null) {
return value;
}
}
// check claim type
if (claimType != null) {
optionContexts = new HashSet<>(contexts);
optionContexts.add(claimType.getContext());
final T value = this.getOptionActualValue(type, holder, option, optionContexts);
if (value != null) {
return value;
}
}
}
optionContexts = new HashSet<>(contexts);
// Check only active contexts
T value = this.getOptionActualValue(type, holder, option, optionContexts);
if (value != null) {
return value;
}
if (claim != null) {
optionContexts.add(claim.getDefaultTypeContext());
value = this.getOptionActualValue(type, holder, option, optionContexts);
if (value != null) {
return value;
}
optionContexts.remove(claim.getDefaultTypeContext());
}
optionContexts.add(ClaimContexts.GLOBAL_DEFAULT_CONTEXT);
if (claim != null && !claim.isWilderness()) {
optionContexts.add(ClaimContexts.USER_DEFAULT_CONTEXT);
}
value = this.getOptionActualValue(type, holder, option, optionContexts);
if (value != null) {
return value;
}
// Check default holder
if (holder != GriefDefenderPlugin.DEFAULT_HOLDER) {
return getInternalOptionValue(type, GriefDefenderPlugin.DEFAULT_HOLDER, option, claim, claimType, contexts);
}
return option.getDefaultValue();
}
private <T> T getOptionActualValue(TypeToken<T> type, GDPermissionHolder holder, Option option, Set<Context> contexts) {
if (option.multiValued()) {
List<String> values = PermissionUtil.getInstance().getOptionValueList(holder, option, contexts);
if (values != null && !values.isEmpty()) {
return (T) values;
}
}
String value = PermissionUtil.getInstance().getOptionValue(holder, option, contexts);
if (value != null) {
return this.getOptionTypeValue(type, value);
}
return null;
}
private <T> T getOptionTypeValue(TypeToken<T> type, String value) {
if (type.getRawType().isAssignableFrom(Double.class)) {
return (T) Double.valueOf(value);
}
if (type.getRawType().isAssignableFrom(Integer.class)) {
if (value.equalsIgnoreCase("undefined")) {
return (T) Integer.valueOf(-1);
}
Integer val = null;
try {
val = Integer.valueOf(value);
} catch (NumberFormatException e) {
return (T) Integer.valueOf(-1);
}
return (T) Integer.valueOf(value);
}
if (type.getRawType().isAssignableFrom(String.class)) {
return (T) value;
}
if (type.getRawType().isAssignableFrom(Tristate.class)) {
if (value.equalsIgnoreCase("true")) {
return (T) Tristate.TRUE;
}
if (value.equalsIgnoreCase("false")) {
return (T) Tristate.FALSE;
}
int permValue = 0;
try {
permValue = Integer.parseInt(value);
} catch (NumberFormatException e) {
}
if (permValue == 0) {
return (T) Tristate.UNDEFINED;
}
return (T) (permValue == 1 ? Tristate.TRUE : Tristate.FALSE);
}
if (type.getRawType().isAssignableFrom(CreateModeType.class)) {
if (value.equalsIgnoreCase("undefined")) {
return (T) CreateModeTypes.AREA;
}
if (value.equalsIgnoreCase("volume")) {
return (T) CreateModeTypes.VOLUME;
}
if (value.equalsIgnoreCase("area")) {
return (T) CreateModeTypes.AREA;
}
int permValue = 0;
try {
permValue = Integer.parseInt(value);
} catch (NumberFormatException e) {
}
if (permValue == 0) {
return (T) CreateModeTypes.AREA;
}
return (T) (permValue == 1 ? CreateModeTypes.VOLUME : CreateModeTypes.AREA);
}
if (type.getRawType().isAssignableFrom(WeatherType.class)) {
if (value.equalsIgnoreCase("downfall")) {
return (T) WeatherTypes.DOWNFALL;
}
if (value.equalsIgnoreCase("clear")) {
return (T) WeatherTypes.CLEAR;
}
return (T) WeatherTypes.UNDEFINED;
}
if (type.getRawType().isAssignableFrom(GameModeType.class)) {
if (value.equalsIgnoreCase("adventure")) {
return (T) GameModeTypes.ADVENTURE;
}
if (value.equalsIgnoreCase("creative")) {
return (T) GameModeTypes.CREATIVE;
}
if (value.equalsIgnoreCase("spectator")) {
return (T) GameModeTypes.SPECTATOR;
}
if (value.equalsIgnoreCase("survival")) {
return (T) GameModeTypes.SURVIVAL;
}
return (T) GameModeTypes.UNDEFINED;
}
if (type.getRawType().isAssignableFrom(Boolean.class)) {
return (T) Boolean.valueOf(Boolean.parseBoolean(value));
}
return (T) value;
}
// Uses passed contexts and only adds active contexts
public Double getActualOptionValue(GDPermissionHolder holder, Option option, Claim claim, GDPlayerData playerData, Set<Context> contexts) {
if (holder != GriefDefenderPlugin.DEFAULT_HOLDER) {
if (playerData != null) {
playerData.ignoreActiveContexts = true;
}
PermissionUtil.getInstance().addActiveContexts(contexts, holder, playerData, claim);
}
final String value = PermissionUtil.getInstance().getOptionValue(holder, option, contexts);
if (value != null) {
return this.getDoubleValue(value);
}
return Double.valueOf(option.getDefaultValue().toString());
}
private Double getDoubleValue(String option) {
if (option == null) {
return null;
}
double optionValue = 0.0;
try {
optionValue = Double.parseDouble(option);
} catch (NumberFormatException e) {
}
return optionValue;
}
public Optional<Flag> getFlag(String value) {
if (value == null) {
return Optional.empty();
}
value = value.replace("griefdefender.flag.", "");
String[] parts = value.split("\\.");
if (parts.length > 0) {
value = parts[0];
}
return FlagRegistryModule.getInstance().getById(value);
}
public Optional<Option> getOption(String value) {
if (value == null) {
return Optional.empty();
}
value = value.replace("griefdefender.", "");
String[] parts = value.split("\\.");
if (parts.length > 0) {
value = parts[0];
}
return GriefDefender.getRegistry().getType(Option.class, value);
}
public Component getEventMessage() {
return this.eventMessage;
}
@Override
public CompletableFuture<PermissionResult> clearOptions() {
// TODO Auto-generated method stub
return null;
}
@Override
public CompletableFuture<PermissionResult> clearOptions(Set<Context> contexts) {
// TODO Auto-generated method stub
return null;
}
@Override
public Tristate getFlagPermissionValue(Flag flag, Subject subject, Set<Context> contexts) {
// TODO Auto-generated method stub
return null;
}
@Override
public CompletableFuture<PermissionResult> setFlagPermission(Flag flag, Subject subject, Tristate value,
Set<Context> contexts) {
// TODO Auto-generated method stub
return null;
}
@Override
public CompletableFuture<PermissionResult> setOption(Option option, String value, Set<Context> contexts) {
return PermissionUtil.getInstance().setOptionValue(GriefDefenderPlugin.DEFAULT_HOLDER, option.getPermission(), value, contexts);
}
@Override
public CompletableFuture<PermissionResult> setOption(Option option, Subject subject, String value, Set<Context> contexts) {
return PermissionUtil.getInstance().setOptionValue((GDPermissionHolder) subject, option.getPermission(), value, contexts);
}
@Override
public <T> Optional<T> getOptionValue(TypeToken<T> type, Option<T> option, Set<Context> contexts) {
String value = PermissionUtil.getInstance().getOptionValue(GriefDefenderPlugin.DEFAULT_HOLDER, option, contexts);
if (value != null) {
return Optional.of(this.getOptionTypeValue(type, value));
}
return Optional.empty();
}
@Override
public <T> Optional<T> getOptionValue(TypeToken<T> type, Subject subject, Option<T> option, Set<Context> contexts) {
String value = PermissionUtil.getInstance().getOptionValue((GDPermissionHolder) subject, option, contexts);
if (value != null) {
return Optional.of(this.getOptionTypeValue(type, value));
}
return Optional.empty();
}
@Override
public <T> T getActiveOptionValue(TypeToken<T> type, Option<T> option, Subject subject, Claim claim,
Set<Context> contexts) {
return this.getInternalOptionValue(type, (GDPermissionHolder) subject, option, claim, claim.getType(), contexts);
}
@Override
public CompletableFuture<PermissionResult> setFlagDefinition(Subject subject, FlagDefinition flagDefinition, Tristate value) {
Set<Context> contexts = new HashSet<>(flagDefinition.getContexts());
Set<Context> defaultContexts = new HashSet<>();
Set<Context> overrideContexts = new HashSet<>();
String groupStr = null;
final Iterator<Context> iterator = contexts.iterator();
while (iterator.hasNext()) {
final Context context = iterator.next();
if (context.getKey().equalsIgnoreCase("gd_claim_default")) {
defaultContexts.add(context);
} else if (context.getKey().equalsIgnoreCase("gd_claim_override")) {
if (context.getValue().equalsIgnoreCase("claim")) {
iterator.remove();
continue;
}
overrideContexts.add(context);
} else if (context.getKey().equalsIgnoreCase("group")) {
groupStr = context.getValue();
}
}
GDPermissionHolder holder = GriefDefenderPlugin.DEFAULT_HOLDER;
if (groupStr != null) {
if (PermissionUtil.getInstance().hasGroupSubject(groupStr)) {
holder = PermissionHolderCache.getInstance().getOrCreateGroup(groupStr);
if (holder == null) {
holder = GriefDefenderPlugin.DEFAULT_HOLDER;
}
}
}
CompletableFuture<PermissionResult> result = new CompletableFuture<>();
if (!defaultContexts.isEmpty()) {
result = PermissionUtil.getInstance().setFlagDefinition(holder, flagDefinition, flagDefinition.getDefaultValue(), defaultContexts, true);
}
if (!overrideContexts.isEmpty()) {
result = PermissionUtil.getInstance().setFlagDefinition(holder, flagDefinition, flagDefinition.getDefaultValue(), overrideContexts, false);
}
PermissionUtil.getInstance().save(holder);
return result;
}
}