1.3.2 Update

* Fix tags not being added to contexts.
* Fix interact-entity-secondary using wrong source if item was in hand.
* Fix create limit check on shovel create start.
* Fix spawn-limit crashing server when checking wilderness limits.
* Fix sell signs being broken by non-trusted.
* Fix EntityChangeBlockEvent using owner of monster damage.
* Fix ClassCastException with WildTP.
* (Sponge) Fix schematic NPE on reload.
* Add workaround for VehicleDamageEvent passing null when source is block.
* Add bypass option support for trusted users.
* Optimize getChunks call.
* Cache user perk option lookups.
* Cache user bypass option lookups.
This commit is contained in:
bloodshot 2020-06-07 23:02:24 -04:00
parent 61a9d8efd1
commit fa2b986f26
34 changed files with 399 additions and 239 deletions

View File

@ -142,6 +142,7 @@ public class GDPlayerData implements PlayerData {
private CreateModeType optionClaimCreateMode;
// cached permission values
// admin cache
public boolean canManageAdminClaims = false;
public boolean canManageWilderness = false;
public boolean canManageGlobalOptions = false;
@ -154,6 +155,15 @@ public class GDPlayerData implements PlayerData {
public boolean ignoreBasicClaims = false;
public boolean ignoreTowns = false;
public boolean ignoreWilderness = false;
// user cache
public boolean userOptionPerkFlyOwner = false;
public boolean userOptionPerkFlyAccessor = false;
public boolean userOptionPerkFlyBuilder = false;
public boolean userOptionPerkFlyContainer = false;
public boolean userOptionPerkFlyManager = false;
public boolean userOptionBypassPlayerDenyFlight = false;
public boolean userOptionBypassPlayerDenyGodmode = false;
public boolean userOptionBypassPlayerGamemode = false;
public boolean dataInitialized = false;
public boolean showVisualFillers = true;
@ -195,7 +205,7 @@ public class GDPlayerData implements PlayerData {
final GDPermissionUser subject = this.playerSubject.get();
final Set<Context> activeContexts = new HashSet<>();
PermissionUtil.getInstance().addActiveContexts(activeContexts, subject);
// permissions
// admin permissions
this.bypassBorderCheck = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.BYPASS_BORDER_CHECK, activeContexts).asBoolean();
this.ignoreAdminClaims = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.IGNORE_CLAIMS_ADMIN, activeContexts).asBoolean();
this.ignoreTowns = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.IGNORE_CLAIMS_TOWN, activeContexts).asBoolean();
@ -208,13 +218,16 @@ public class GDPlayerData implements PlayerData {
this.canManageAdminOptions = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.MANAGE_ADMIN_OPTIONS, activeContexts).asBoolean();
this.canManageFlagDefaults = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.MANAGE_FLAG_DEFAULTS, activeContexts).asBoolean();
this.canManageFlagOverrides = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.MANAGE_FLAG_OVERRIDES, activeContexts).asBoolean();
// user permissions
this.userOptionPerkFlyOwner = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_OWNER, activeContexts).asBoolean();
this.userOptionPerkFlyManager = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_MANAGER, activeContexts).asBoolean();
this.userOptionPerkFlyBuilder = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_BUILDER, activeContexts).asBoolean();
this.userOptionPerkFlyContainer = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_CONTAINER, activeContexts).asBoolean();
this.userOptionPerkFlyAccessor = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_ACCESSOR, activeContexts).asBoolean();
this.userOptionBypassPlayerDenyFlight = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_DENY_FLIGHT.getName().toLowerCase(), activeContexts).asBoolean();
this.userOptionBypassPlayerDenyGodmode = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_DENY_GODMODE.getName().toLowerCase(), activeContexts).asBoolean();
this.userOptionBypassPlayerGamemode = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_GAMEMODE.getName().toLowerCase(), activeContexts).asBoolean();
this.playerID = subject.getUniqueId();
/*if (this.optionMaxClaimLevel > 255 || this.optionMaxClaimLevel <= 0 || this.optionMaxClaimLevel < this.optionMinClaimLevel) {
this.optionMaxClaimLevel = 255;
}
if (this.optionMinClaimLevel < 0 || this.optionMinClaimLevel >= 255 || this.optionMinClaimLevel > this.optionMaxClaimLevel) {
this.optionMinClaimLevel = 0;
}*/
this.dataInitialized = true;
this.checkedDimensionHeight = false;
});

View File

@ -195,7 +195,6 @@ import com.griefdefender.permission.flag.GDFlagData;
import com.griefdefender.permission.flag.GDFlagDefinition;
import com.griefdefender.permission.flag.GDFlags;
import com.griefdefender.provider.DynmapProvider;
import com.griefdefender.provider.EssentialsProvider;
import com.griefdefender.provider.LuckPermsProvider;
import com.griefdefender.provider.PermissionProvider;
import com.griefdefender.provider.PlaceholderProvider;
@ -275,7 +274,6 @@ public class GriefDefenderPlugin {
public BaseStorage dataStore;
private DynmapProvider dynmapProvider;
private EssentialsProvider essentialsProvider;
private GDTagProvider tagProvider;
private GDWorldEditProvider worldEditProvider;
private WorldGuardProvider worldGuardProvider;
@ -540,10 +538,6 @@ public class GriefDefenderPlugin {
this.worldGuardProvider = new WorldGuardProvider();
}
if (Bukkit.getPluginManager().getPlugin("Essentials") != null) {
this.essentialsProvider = new EssentialsProvider();
}
if (Bukkit.getPluginManager().getPlugin("dynmap") != null
&& GriefDefenderPlugin.getGlobalConfig().getConfig().dynmap.enabled) {
this.dynmapProvider = new DynmapProvider();
@ -1219,10 +1213,6 @@ public class GriefDefenderPlugin {
return this.dynmapProvider;
}
public EssentialsProvider getEssentialsProvider() {
return this.essentialsProvider;
}
public GDTagProvider getTagProvider() {
return this.tagProvider;
}

View File

@ -52,7 +52,6 @@ import com.griefdefender.api.claim.ShovelTypes;
import com.griefdefender.api.claim.TrustType;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.api.data.ClaimData;
import com.griefdefender.api.data.EconomyData;
import com.griefdefender.api.permission.Context;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.cache.MessageCache;
@ -72,6 +71,8 @@ import com.griefdefender.event.GDSaveClaimEvent;
import com.griefdefender.event.GDTransferClaimEvent;
import com.griefdefender.event.GDUserTrustClaimEvent;
import com.griefdefender.internal.provider.WorldGuardProvider;
import com.griefdefender.internal.registry.GDEntityType;
import com.griefdefender.internal.tracking.chunk.GDChunk;
import com.griefdefender.internal.util.VecHelper;
import com.griefdefender.internal.visual.GDClaimVisual;
import com.griefdefender.permission.GDPermissionHolder;
@ -97,7 +98,6 @@ import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -145,10 +145,11 @@ public class GDClaim implements Claim {
protected IClaimData claimData;
public GDClaim parent = null;
public Set<Claim> children = new HashSet<>();
public GDClaimVisual claimVisual;
public Set<UUID> playersWatching = new HashSet<>();
public Map<String, ClaimSchematic> schematics = new HashMap<>();
public Set<UUID> playersWatching = new HashSet<>();
public Set<Claim> children = new HashSet<>();
public Set<Long> loadedChunkHashes = new HashSet<>();
private GDPlayerData ownerPlayerData;
@ -760,12 +761,27 @@ public class GDClaim implements Claim {
return chunkPositions;
}
public ArrayList<Chunk> getChunks() {
public List<Chunk> getLoadedChunks() {
List<Chunk> chunks = new ArrayList<>();
for (long chunkHash : this.getChunkHashes()) {
final GDChunk gdChunk = this.worldClaimManager.getChunk(chunkHash);
if (gdChunk != null) {
chunks.add(gdChunk.getHandle());
}
}
return chunks;
}
public List<Chunk> getChunks() {
return this.getChunks(false);
}
public ArrayList<Chunk> getChunks(boolean force) {
ArrayList<Chunk> chunks = new ArrayList<Chunk>();
public List<Chunk> getChunks(boolean force) {
if (!force || this.isWilderness()) {
return this.getLoadedChunks();
}
List<Chunk> chunks = new ArrayList<Chunk>();
Chunk lesserChunk = this.world
.getChunkAt(this.getLesserBoundaryCorner().getX() >> 4, this.getLesserBoundaryCorner().getZ() >> 4);
@ -775,9 +791,6 @@ public class GDClaim implements Claim {
if (lesserChunk != null && greaterChunk != null) {
for (int x = lesserChunk.getX(); x <= greaterChunk.getX(); x++) {
for (int z = lesserChunk.getZ(); z <= greaterChunk.getZ(); z++) {
if (!force && !this.world.isChunkLoaded(x, z)) {
continue;
}
final Chunk chunk = this.world.getChunkAt(x, z);
if (chunk != null) {
chunks.add(chunk);
@ -830,20 +843,28 @@ public class GDClaim implements Claim {
@Override
public Set<Long> getChunkHashes() {
return this.getChunkHashes(true);
return this.getChunkHashes(false);
}
public Set<Long> getChunkHashes(boolean refresh) {
if (this.isWilderness()) {
return this.loadedChunkHashes;
}
if (this.chunkHashes == null || refresh) {
this.chunkHashes = new HashSet<Long>();
int smallX = this.lesserBoundaryCorner.getX() >> 4;
int smallZ = this.lesserBoundaryCorner.getZ() >> 4;
int largeX = this.greaterBoundaryCorner.getX() >> 4;
int largeZ = this.greaterBoundaryCorner.getZ() >> 4;
this.loadedChunkHashes.clear();
for (int x = smallX; x <= largeX; x++) {
for (int z = smallZ; z <= largeZ; z++) {
this.chunkHashes.add(BlockUtil.getInstance().asLong(x, z));
final GDChunk gdChunk = this.worldClaimManager.getChunkIfLoaded(x, z);
if (gdChunk != null) {
this.loadedChunkHashes.add(gdChunk.getChunkKey());
}
}
}
}
@ -1974,11 +1995,23 @@ public class GDClaim implements Claim {
return new GDClaimResult(ClaimResultType.SUCCESS);
}
public int countEntities(EntityType type) {
public int getSpawnLimit(Set<Context> contexts) {
final List<Claim> parents = this.getParents(true);
for (Claim claim : parents) {
final int parentSpawnLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), GriefDefenderPlugin.DEFAULT_HOLDER, Options.SPAWN_LIMIT, claim, new HashSet<>(contexts));
if (parentSpawnLimit > -1) {
return parentSpawnLimit;
}
}
return GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), GriefDefenderPlugin.DEFAULT_HOLDER, Options.SPAWN_LIMIT, this, new HashSet<>(contexts));
}
public int countEntities(Entity spawnedEntity) {
int count = 0;
for (Chunk chunk : this.getChunks()) {
for (Entity entity : chunk.getEntities()) {
if (entity.getType() == type) {
if (spawnedEntity.getType() == entity.getType()) {
count++;
}
}

View File

@ -648,16 +648,45 @@ public class GDClaimManager implements ClaimManager {
}
public GDChunk getChunk(Chunk chunk) {
GDChunk gdChunk = this.chunksToGDChunks.get(getChunkKey(chunk));
final long chunkKey = getChunkKey(chunk);
GDChunk gdChunk = this.chunksToGDChunks.get(chunkKey);
if (gdChunk == null) {
gdChunk = new GDChunk(chunk);
this.chunksToGDChunks.put(getChunkKey(chunk), gdChunk);
this.chunksToGDChunks.put(chunkKey, gdChunk);
if (this.chunksToClaimsMap.get(chunkKey) == null) {
this.theWildernessClaim.loadedChunkHashes.add(chunkKey);
}
}
return gdChunk;
}
public void removeChunk(Chunk chunk) {
this.chunksToGDChunks.remove(getChunkKey(chunk));
public GDChunk getChunkIfLoaded(int cx, int cz) {
return this.chunksToGDChunks.get(getChunkKey(cx, cz));
}
public GDChunk getChunk(long key) {
return this.chunksToGDChunks.get(key);
}
public boolean isChunkLoaded(Chunk chunk) {
return this.chunksToGDChunks.get(getChunkKey(chunk)) != null;
}
public boolean isChunkLoaded(int cx, int cz) {
return this.chunksToGDChunks.get(getChunkKey(cx, cz)) != null;
}
public boolean isChunkLoaded(long key) {
return this.chunksToGDChunks.get(key) != null;
}
public void removeChunk(long key) {
this.chunksToGDChunks.remove(key);
this.theWildernessClaim.loadedChunkHashes.remove(key);
}
private long getChunkKey(int cx, int cz) {
return (long) cx & 0xffffffffL | ((long) cz & 0xffffffffL) << 32;
}
private long getChunkKey(Chunk chunk) {

View File

@ -455,9 +455,26 @@ public class CommonEntityEventHandler {
}
final Boolean noFly = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Boolean.class), playerData.getSubject(), Options.PLAYER_DENY_FLIGHT, toClaim);
final boolean adminFly = player.hasPermission(GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_DENY_FLIGHT.getName().toLowerCase());
final boolean ownerFly = toClaim.isBasicClaim() ? player.hasPermission(GDPermissions.USER_OPTION_PERK_OWNER_FLY_BASIC) : toClaim.isTown() ? player.hasPermission(GDPermissions.USER_OPTION_PERK_OWNER_FLY_TOWN) : false;
if (player.getUniqueId().equals(toClaim.getOwnerUniqueId()) && ownerFly) {
final boolean adminFly = playerData.userOptionBypassPlayerDenyFlight;
boolean trustFly = false;
if (toClaim.isBasicClaim() || (toClaim.parent != null && toClaim.parent.isBasicClaim()) || toClaim.isInTown()) {
// check owner
if (playerData.userOptionPerkFlyOwner && toClaim.allowEdit(player) == null) {
trustFly = true;
} else {
if (playerData.userOptionPerkFlyAccessor && toClaim.isUserTrusted(player, TrustTypes.ACCESSOR)) {
trustFly = true;
} else if (playerData.userOptionPerkFlyBuilder && toClaim.isUserTrusted(player, TrustTypes.BUILDER)) {
trustFly = true;
} else if (playerData.userOptionPerkFlyContainer && toClaim.isUserTrusted(player, TrustTypes.CONTAINER)) {
trustFly = true;
} else if (playerData.userOptionPerkFlyManager && toClaim.isUserTrusted(player, TrustTypes.MANAGER)) {
trustFly = true;
}
}
}
if (trustFly) {
return;
}
if (!adminFly && noFly) {
@ -488,7 +505,7 @@ public class CommonEntityEventHandler {
}
final Boolean noGodMode = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Boolean.class), playerData.getSubject(), Options.PLAYER_DENY_GODMODE, toClaim);
final boolean bypassOption = player.hasPermission(GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_DENY_GODMODE.getName().toLowerCase());
final boolean bypassOption = playerData.userOptionBypassPlayerDenyGodmode;
if (!bypassOption && noGodMode) {
player.setInvulnerable(false);
GriefDefenderPlugin.sendMessage(player, MessageCache.getInstance().OPTION_APPLY_PLAYER_DENY_GODMODE);
@ -516,7 +533,7 @@ public class CommonEntityEventHandler {
return;
}
final boolean bypassOption = player.hasPermission(GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_GAMEMODE.getName().toLowerCase());
final boolean bypassOption = playerData.userOptionBypassPlayerGamemode;
if (!bypassOption && gameModeType != null && gameModeType != GameModeTypes.UNDEFINED) {
final GameMode newGameMode = PlayerUtil.GAMEMODE_MAP.get(gameModeType);
if (currentGameMode != newGameMode) {

View File

@ -282,7 +282,8 @@ public class EntityEventHandler implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onVehicleDamage(VehicleDamageEvent event) {
GDTimings.ENTITY_DAMAGE_EVENT.startTiming();
if (protectEntity(event, event.getAttacker(), (Entity) event.getVehicle())) {
final Object source = event.getAttacker() != null ? event.getAttacker() : NMSUtil.getInstance().getBlockDamager();
if (protectEntity(event, source, (Entity) event.getVehicle())) {
event.setCancelled(true);
}
GDTimings.ENTITY_DAMAGE_EVENT.stopTiming();

View File

@ -1,69 +0,0 @@
/*
* 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.listener;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import com.google.common.reflect.TypeToken;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissions;
import net.ess3.api.events.FlyStatusChangeEvent;
public class EssentialsEventHandler implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onFlyStatusChange(FlyStatusChangeEvent event) {
final Player player = event.getAffected().getBase();
final Location location = player.getLocation();
final GameMode gameMode = player.getGameMode();
if (gameMode == GameMode.CREATIVE || gameMode == GameMode.SPECTATOR) {
return;
}
if (event.getValue()) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(location, playerData, true);
final Boolean noFly = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Boolean.class), playerData.getSubject(), Options.PLAYER_DENY_FLIGHT, claim);
final boolean adminFly = player.hasPermission(GDPermissions.BYPASS_OPTION);
final boolean ownerFly = claim.isBasicClaim() ? player.hasPermission(GDPermissions.USER_OPTION_PERK_OWNER_FLY_BASIC) : claim.isTown() ? player.hasPermission(GDPermissions.USER_OPTION_PERK_OWNER_FLY_TOWN) : false;
if (player.getUniqueId().equals(claim.getOwnerUniqueId()) && ownerFly) {
return;
}
if (!adminFly && noFly) {
event.setCancelled(true);
}
}
}
}

View File

@ -610,7 +610,7 @@ public class PlayerEventHandler implements Listener {
}
// Item permission checks passed, check entity
final Object source = activeItem != null && activeItem.getType() != Material.AIR ? activeItem : player;
final Object source = player;
if (GriefDefenderPlugin.isTargetIdBlacklisted(Flags.INTERACT_ENTITY_SECONDARY.getName(), targetEntity, player.getWorld().getUID())) {
return;
}
@ -1152,15 +1152,18 @@ public class PlayerEventHandler implements Listener {
if (!player.hasPermission(GDPermissions.BYPASS_CLAIM_LIMIT)) {
int createClaimLimit = -1;
if (playerData.shovelMode == ShovelTypes.BASIC && (claim.isAdminClaim() || claim.isTown() || claim.isWilderness())) {
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, claim).intValue();
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, type).intValue();
} else if (playerData.shovelMode == ShovelTypes.TOWN && (claim.isAdminClaim() || claim.isWilderness())) {
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, claim).intValue();
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, type).intValue();
} else if (playerData.shovelMode == ShovelTypes.SUBDIVISION && !claim.isWilderness()) {
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, claim).intValue();
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, type).intValue();
}
if (createClaimLimit > 0 && createClaimLimit < (playerData.getClaimTypeCount(type) + 1)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.CREATE_FAILED_CLAIM_LIMIT));
final Component message = GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.CREATE_FAILED_CLAIM_LIMIT, ImmutableMap.of(
"limit", createClaimLimit,
"type", type.getName()));
GriefDefenderPlugin.sendMessage(player, message);
return;
}
}

View File

@ -71,10 +71,10 @@ public class WorldEventHandler implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onChunkLoad(ChunkLoadEvent event) {
final GDClaimManager claimWorldManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(event.getWorld().getUID());
final GDChunk gpChunk = claimWorldManager.getChunk(event.getChunk());
if (gpChunk != null) {
final GDChunk gdChunk = claimWorldManager.getChunk(event.getChunk());
if (gdChunk != null) {
try {
gpChunk.loadChunkTrackingData();
gdChunk.loadChunkTrackingData();
} catch (IOException e) {
e.printStackTrace();
}
@ -84,12 +84,12 @@ public class WorldEventHandler implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onChunkUnload(ChunkUnloadEvent event) {
final GDClaimManager claimWorldManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(event.getWorld().getUID());
final GDChunk gpChunk = claimWorldManager.getChunk(event.getChunk());
if (gpChunk != null) {
if (gpChunk.getTrackedShortPlayerPositions().size() > 0) {
gpChunk.saveChunkTrackingData();
final GDChunk gdChunk = claimWorldManager.getChunk(event.getChunk());
if (gdChunk != null) {
if (gdChunk.getTrackedShortPlayerPositions().size() > 0) {
gdChunk.saveChunkTrackingData();
}
claimWorldManager.removeChunk(event.getChunk());
claimWorldManager.removeChunk(gdChunk.getChunkKey());
}
}
}

View File

@ -216,20 +216,21 @@ public class GDPermissionManager implements PermissionManager {
this.eventPlayerData = playerData;
final String targetPermission = flag.getPermission();
if (flag == Flags.ENTITY_SPAWN && GDOptions.isOptionEnabled(Options.SPAWN_LIMIT)) {
if (flag == Flags.ENTITY_SPAWN && GDOptions.isOptionEnabled(Options.SPAWN_LIMIT) && target instanceof LivingEntity) {
// Check spawn limit
final int spawnLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), GriefDefenderPlugin.DEFAULT_HOLDER, Options.SPAWN_LIMIT, claim, new HashSet<>(contexts));
final GDClaim gdClaim = (GDClaim) claim;
final int spawnLimit = gdClaim.getSpawnLimit(contexts);
if (spawnLimit > -1) {
if (target instanceof Entity) {
final Entity entity = (Entity) target;
final int currentEntityCount = ((GDClaim) claim).countEntities(entity.getType());
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.getName(),
"type", entityType.getId(),
"limit", spawnLimit));
GriefDefenderPlugin.sendMessage(user.getOnlinePlayer(), message);
}
@ -907,6 +908,8 @@ public class GDPermissionManager implements PermissionManager {
}
private Set<Context> populateEventSourceTargetContext(Set<Context> contexts, String id, boolean isSource) {
contexts = this.populateTagContextsForId(contexts, id, isSource);
if (!id.contains(":")) {
id = "minecraft:" + id;
}
@ -922,7 +925,7 @@ public class GDPermissionManager implements PermissionManager {
contexts.add(new Context("target", modId + ":any"));
}
return this.populateTagContextsForId(contexts, modId, isSource);
return contexts;
}
public Set<Context> populateTagContextsForId(Set<Context> contexts, String id, boolean isSource) {
@ -1119,7 +1122,7 @@ public class GDPermissionManager implements PermissionManager {
}
public <T> T getInternalOptionValue(TypeToken<T> type, OfflinePlayer player, Option<T> option) {
return getInternalOptionValue(type, player, option, null);
return getInternalOptionValue(type, player, option, (ClaimType) null);
}
public <T> T getInternalOptionValue(TypeToken<T> type, OfflinePlayer player, Option<T> option, Claim claim) {
@ -1130,6 +1133,11 @@ public class GDPermissionManager implements PermissionManager {
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);
}

View File

@ -113,8 +113,11 @@ public class GDPermissions {
public static final String COMMAND_OPTIONS_CLAIM = "griefdefender.user.claim.command.option.base";
public static final String COMMAND_OPTIONS_PLAYER = "griefdefender.user.claim.command.option.player";
public static final String COMMAND_OPTIONS_GROUP = "griefdefender.user.claim.command.option.group";
public static final String USER_OPTION_PERK_OWNER_FLY_BASIC = "griefdefender.user.option.perk.owner-fly.basic";
public static final String USER_OPTION_PERK_OWNER_FLY_TOWN = "griefdefender.user.option.perk.owner-fly.town";
public static final String USER_OPTION_PERK_FLY_OWNER = "griefdefender.user.option.perk.fly.owner";
public static final String USER_OPTION_PERK_FLY_ACCESSOR = "griefdefender.user.option.perk.fly.accessor";
public static final String USER_OPTION_PERK_FLY_BUILDER = "griefdefender.user.option.perk.fly.builder";
public static final String USER_OPTION_PERK_FLY_CONTAINER = "griefdefender.user.option.perk.fly.container";
public static final String USER_OPTION_PERK_FLY_MANAGER = "griefdefender.user.option.perk.fly.manager";
public static final String OPTION_BASE = "griefdefender";
// Economy

View File

@ -1,37 +0,0 @@
/*
* 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.provider;
import org.bukkit.Bukkit;
import com.griefdefender.GDBootstrap;
import com.griefdefender.listener.EssentialsEventHandler;
public class EssentialsProvider {
public EssentialsProvider() {
Bukkit.getPluginManager().registerEvents(new EssentialsEventHandler(), GDBootstrap.getInstance());
}
}

View File

@ -613,6 +613,14 @@ public class EconomyUtil {
}
public void sellCancelConfirmation(CommandSender src, Claim claim, Sign sign) {
final Player player = (Player) src;
final GDClaim gdClaim = (GDClaim) claim;
// check sell access
if (gdClaim.allowEdit(player) != null) {
GriefDefenderPlugin.sendMessage(player, MessageCache.getInstance().CLAIM_NOT_YOURS);
return;
}
final Component sellCancelConfirmationText = TextComponent.builder()
.append("\n[")
.append(MessageCache.getInstance().LABEL_CONFIRM.color(TextColor.GREEN))

View File

@ -3,9 +3,9 @@
"libraries": [
{
"name": "com.griefdefender:adapter:1.12.2",
"sha1": "d3fb44b19f32ec01395b104fe5770deb23e1b602",
"path": "com/griefdefender/adapter/1.12.2-SNAPSHOT/adapter-1.12.2-20200603.032437-32.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.12.2-SNAPSHOT/adapter-1.12.2-20200603.032437-32.jar"
"sha1": "73421d4599201a371858653a7d31c054eb972949",
"path": "com/griefdefender/adapter/1.12.2-SNAPSHOT/adapter-1.12.2-20200607.224144-34.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.12.2-SNAPSHOT/adapter-1.12.2-20200607.224144-34.jar"
},
{
"name": "com.griefdefender:api:1.0.0",

View File

@ -3,9 +3,9 @@
"libraries": [
{
"name": "com.griefdefender:adapter:1.13.2",
"sha1": "e8720dcbfe285267059ab668871c5d2fb8bd60c8",
"path": "com/griefdefender/adapter/1.13.2-SNAPSHOT/adapter-1.13.2-20200603.032056-31.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.13.2-SNAPSHOT/adapter-1.13.2-20200603.032056-31.jar"
"sha1": "78e6b190a71d1213632ed0c9eacb0017836e9a45",
"path": "com/griefdefender/adapter/1.13.2-SNAPSHOT/adapter-1.13.2-20200607.224012-33.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.13.2-SNAPSHOT/adapter-1.13.2-20200607.224012-33.jar"
},
{
"name": "com.griefdefender:api:1.0.0",

View File

@ -3,9 +3,9 @@
"libraries": [
{
"name": "com.griefdefender:adapter:1.14.2",
"sha1": "616ccfbbb15db415c40f1b01c3c65e196d3fc1d6",
"path": "com/griefdefender/adapter/1.14.2-SNAPSHOT/adapter-1.14.2-20200603.031745-31.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.14.2-SNAPSHOT/adapter-1.14.2-20200603.031745-31.jar"
"sha1": "49837d3d065b2e642d86a43d4106edf5e89c1f42",
"path": "com/griefdefender/adapter/1.14.2-SNAPSHOT/adapter-1.14.2-20200607.223940-33.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.14.2-SNAPSHOT/adapter-1.14.2-20200607.223940-33.jar"
},
{
"name": "com.griefdefender:api:1.0.0",

View File

@ -3,9 +3,9 @@
"libraries": [
{
"name": "com.griefdefender:adapter:1.14.3",
"sha1": "99cf64ac2c71a24aea62aee9e730a3d9c97764f1",
"path": "com/griefdefender/adapter/1.14.3-SNAPSHOT/adapter-1.14.3-20200603.031630-32.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.14.3-SNAPSHOT/adapter-1.14.3-20200603.031630-32.jar"
"sha1": "bc12031edab59cdb998248a9048f225ec5bfbf34",
"path": "com/griefdefender/adapter/1.14.3-SNAPSHOT/adapter-1.14.3-20200607.223828-34.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.14.3-SNAPSHOT/adapter-1.14.3-20200607.223828-34.jar"
},
{
"name": "com.griefdefender:api:1.0.0",

View File

@ -3,9 +3,9 @@
"libraries": [
{
"name": "com.griefdefender:adapter:1.14.4",
"sha1": "0626d2eaf079afa2c8650772c675f78d72c140aa",
"path": "com/griefdefender/adapter/1.14.4-SNAPSHOT/adapter-1.14.4-20200603.031515-30.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.14.4-SNAPSHOT/adapter-1.14.4-20200603.031515-30.jar"
"sha1": "fc030c3b3b95439abd341df479e297b183a2cf13",
"path": "com/griefdefender/adapter/1.14.4-SNAPSHOT/adapter-1.14.4-20200607.223535-32.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.14.4-SNAPSHOT/adapter-1.14.4-20200607.223535-32.jar"
},
{
"name": "com.griefdefender:api:1.0.0",

View File

@ -3,9 +3,9 @@
"libraries": [
{
"name": "com.griefdefender:adapter:1.15.2",
"sha1": "8d31e289fa9ecac8e6a3b61d80f924a6b4b63919",
"path": "com/griefdefender/adapter/1.15.2-SNAPSHOT/adapter-1.15.2-20200603.025720-11.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.15.2-SNAPSHOT/adapter-1.15.2-20200603.025720-11.jar"
"sha1": "2d8a21c18abae4184fb6bc80cad4175fe8cbdda6",
"path": "com/griefdefender/adapter/1.15.2-SNAPSHOT/adapter-1.15.2-20200607.223430-13.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.15.2-SNAPSHOT/adapter-1.15.2-20200607.223430-13.jar"
},
{
"name": "com.griefdefender:api:1.0.0",

View File

@ -3,9 +3,9 @@
"libraries": [
{
"name": "com.griefdefender:adapter:1.15",
"sha1": "ed9bf3b730bf6a5e82ff459c17127782dbac4019",
"path": "com/griefdefender/adapter/1.15-SNAPSHOT/adapter-1.15-20200603.030311-12.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.15-SNAPSHOT/adapter-1.15-20200603.030311-12.jar"
"sha1": "a20a6b8aa707a1e13333078cf10c49b64732e334",
"path": "com/griefdefender/adapter/1.15-SNAPSHOT/adapter-1.15-20200607.223501-14.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.15-SNAPSHOT/adapter-1.15-20200607.223501-14.jar"
},
{
"name": "com.griefdefender:api:1.0.0",

View File

@ -3,9 +3,9 @@
"libraries": [
{
"name": "com.griefdefender:adapter:1.8.8",
"sha1": "de86ea635e3c59eefd331a9661a9523bab441d60",
"path": "com/griefdefender/adapter/1.8.8-SNAPSHOT/adapter-1.8.8-20200603.032651-32.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.8.8-SNAPSHOT/adapter-1.8.8-20200603.032651-32.jar"
"sha1": "0694300ced47831481d1bd01f91bc2a6ad180305",
"path": "com/griefdefender/adapter/1.8.8-SNAPSHOT/adapter-1.8.8-20200607.174827-33.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter/1.8.8-SNAPSHOT/adapter-1.8.8-20200607.174827-33.jar"
},
{
"name": "com.griefdefender:api:1.0.0",

View File

@ -3,5 +3,5 @@ main: com.griefdefender.GDBootstrap
softdepend: [dynmap, PlaceholderAPI, WorldEdit, WorldGuard, Vault]
depend: [LuckPerms]
load: STARTUP
version: '1.3.1'
version: '1.3.2'
api-version: 1.13

View File

@ -2,13 +2,13 @@
name=GriefDefender
group=com.griefdefender
url=https://github.com/bloodmc/GriefDefender
version=1.3.1
version=1.3.2
apiVersion=1.0.0-20200528.202302-24
# Bukkit
adapterVersion=1.15.2-20200603.025720-11
adapterVersion=1.15.2-20200607.223430-13
spigotVersion=1.15.2-R0.1-SNAPSHOT
# Sponge
adapterSpongeVersion=1.12.2-20200603.052230-4
adapterSpongeVersion=1.12.2-20200607.180353-5
commonVersion=1.12.2-7.1.7-SNAPSHOT
minecraftVersion=1.12.2
mcpMappings=snapshot_20180808

View File

@ -144,6 +144,7 @@ public class GDPlayerData implements PlayerData {
private CreateModeType optionClaimCreateMode;
// cached permission values
// admin cache
public boolean canManageAdminClaims = false;
public boolean canManageWilderness = false;
public boolean canManageGlobalOptions = false;
@ -156,6 +157,15 @@ public class GDPlayerData implements PlayerData {
public boolean ignoreBasicClaims = false;
public boolean ignoreTowns = false;
public boolean ignoreWilderness = false;
// user cache
public boolean userOptionPerkFlyOwner = false;
public boolean userOptionPerkFlyAccessor = false;
public boolean userOptionPerkFlyBuilder = false;
public boolean userOptionPerkFlyContainer = false;
public boolean userOptionPerkFlyManager = false;
public boolean userOptionBypassPlayerDenyFlight = false;
public boolean userOptionBypassPlayerDenyGodmode = false;
public boolean userOptionBypassPlayerGamemode = false;
public boolean dataInitialized = false;
public boolean showVisualFillers = true;
@ -196,7 +206,7 @@ public class GDPlayerData implements PlayerData {
final GDPermissionUser subject = this.playerSubject.get();
final Set<Context> activeContexts = new HashSet<>();
PermissionUtil.getInstance().addActiveContexts(activeContexts, subject);
// permissions
// admin permissions
this.bypassBorderCheck = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.BYPASS_BORDER_CHECK, activeContexts).asBoolean();
this.ignoreAdminClaims = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.IGNORE_CLAIMS_ADMIN, activeContexts).asBoolean();
this.ignoreTowns = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.IGNORE_CLAIMS_TOWN, activeContexts).asBoolean();
@ -209,13 +219,16 @@ public class GDPlayerData implements PlayerData {
this.canManageAdminOptions = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.MANAGE_ADMIN_OPTIONS, activeContexts).asBoolean();
this.canManageFlagDefaults = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.MANAGE_FLAG_DEFAULTS, activeContexts).asBoolean();
this.canManageFlagOverrides = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.MANAGE_FLAG_OVERRIDES, activeContexts).asBoolean();
// user permissions
this.userOptionPerkFlyOwner = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_OWNER, activeContexts).asBoolean();
this.userOptionPerkFlyManager = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_MANAGER, activeContexts).asBoolean();
this.userOptionPerkFlyBuilder = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_BUILDER, activeContexts).asBoolean();
this.userOptionPerkFlyContainer = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_CONTAINER, activeContexts).asBoolean();
this.userOptionPerkFlyAccessor = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.USER_OPTION_PERK_FLY_ACCESSOR, activeContexts).asBoolean();
this.userOptionBypassPlayerDenyFlight = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_DENY_FLIGHT.getName().toLowerCase(), activeContexts).asBoolean();
this.userOptionBypassPlayerDenyGodmode = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_DENY_GODMODE.getName().toLowerCase(), activeContexts).asBoolean();
this.userOptionBypassPlayerGamemode = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_GAMEMODE.getName().toLowerCase(), activeContexts).asBoolean();
this.playerID = subject.getUniqueId();
/*if (this.optionMaxClaimLevel > 255 || this.optionMaxClaimLevel <= 0 || this.optionMaxClaimLevel < this.optionMinClaimLevel) {
this.optionMaxClaimLevel = 255;
}
if (this.optionMinClaimLevel < 0 || this.optionMinClaimLevel >= 255 || this.optionMinClaimLevel > this.optionMaxClaimLevel) {
this.optionMinClaimLevel = 0;
}*/
this.dataInitialized = true;
this.checkedDimensionHeight = false;
});

View File

@ -70,6 +70,7 @@ import com.griefdefender.event.GDGroupTrustClaimEvent;
import com.griefdefender.event.GDSaveClaimEvent;
import com.griefdefender.event.GDTransferClaimEvent;
import com.griefdefender.event.GDUserTrustClaimEvent;
import com.griefdefender.internal.tracking.chunk.GDChunk;
import com.griefdefender.internal.util.BlockUtil;
import com.griefdefender.internal.visual.GDClaimVisual;
import com.griefdefender.permission.GDPermissionHolder;
@ -90,7 +91,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.entity.Entity;
import org.spongepowered.api.entity.EntityType;
import org.spongepowered.api.entity.living.player.Player;
import org.spongepowered.api.event.cause.Cause;
import org.spongepowered.api.event.cause.EventContext;
@ -148,14 +148,14 @@ public class GDClaim implements Claim {
protected IClaimData claimData;
public GDClaim parent = null;
public Set<Claim> children = new HashSet<>();
public GDClaimVisual claimVisual;
public Set<UUID> playersWatching = new HashSet<>();
public Map<String, ClaimSchematic> schematics = new HashMap<>();
public Set<UUID> playersWatching = new HashSet<>();
public Set<Claim> children = new HashSet<>();
public Set<Long> loadedChunkHashes = new HashSet<>();
private GDPlayerData ownerPlayerData;
private Account economyAccount;
private static final int MAX_AREA = GriefDefenderPlugin.CLAIM_BLOCK_SYSTEM == ClaimBlockSystem.VOLUME ? 2560000 : 10000;
public GDClaim(World world, Vector3i point1, Vector3i point2, ClaimType type, UUID ownerUniqueId, boolean cuboid) {
this(world, point1, point2, type, ownerUniqueId, cuboid, null);
@ -778,12 +778,27 @@ public class GDClaim implements Claim {
return chunkPositions;
}
public ArrayList<Chunk> getChunks() {
public List<Chunk> getLoadedChunks() {
List<Chunk> chunks = new ArrayList<>();
for (long chunkHash : this.getChunkHashes()) {
final GDChunk gdChunk = this.worldClaimManager.getChunk(chunkHash);
if (gdChunk != null) {
chunks.add(gdChunk.getHandle());
}
}
return chunks;
}
public List<Chunk> getChunks() {
return this.getChunks(false);
}
public ArrayList<Chunk> getChunks(boolean force) {
ArrayList<Chunk> chunks = new ArrayList<Chunk>();
public List<Chunk> getChunks(boolean force) {
if (!force || this.isWilderness()) {
return this.getLoadedChunks();
}
List<Chunk> chunks = new ArrayList<Chunk>();
Chunk lesserChunk = this.world
.getChunk(this.getLesserBoundaryCorner().getX() >> 4, 0, this.getLesserBoundaryCorner().getZ() >> 4).orElse(null);
@ -793,10 +808,7 @@ public class GDClaim implements Claim {
if (lesserChunk != null && greaterChunk != null) {
for (int x = lesserChunk.getPosition().getX(); x <= greaterChunk.getPosition().getX(); x++) {
for (int z = lesserChunk.getPosition().getZ(); z <= greaterChunk.getPosition().getZ(); z++) {
if (!force && !BlockUtil.getInstance().isChunkLoadedAtBlock(this.world, x, z)) {
continue;
}
Chunk chunk = this.world.loadChunk(x, 0, z, true).orElse(null);
final Chunk chunk = this.world.loadChunk(x, 0, z, true).orElse(null);
if (chunk != null) {
chunks.add(chunk);
}
@ -848,20 +860,28 @@ public class GDClaim implements Claim {
@Override
public Set<Long> getChunkHashes() {
return this.getChunkHashes(true);
return this.getChunkHashes(false);
}
public Set<Long> getChunkHashes(boolean refresh) {
if (this.isWilderness()) {
return this.loadedChunkHashes;
}
if (this.chunkHashes == null || refresh) {
this.chunkHashes = new HashSet<Long>();
int smallX = this.lesserBoundaryCorner.getX() >> 4;
int smallZ = this.lesserBoundaryCorner.getZ() >> 4;
int largeX = this.greaterBoundaryCorner.getX() >> 4;
int largeZ = this.greaterBoundaryCorner.getZ() >> 4;
this.loadedChunkHashes.clear();
for (int x = smallX; x <= largeX; x++) {
for (int z = smallZ; z <= largeZ; z++) {
this.chunkHashes.add(BlockUtil.getInstance().asLong(x, z));
final GDChunk gdChunk = this.worldClaimManager.getChunkIfLoaded(x, z);
if (gdChunk != null) {
this.loadedChunkHashes.add(gdChunk.getChunkKey());
}
}
}
}
@ -1999,7 +2019,19 @@ public class GDClaim implements Claim {
return new GDClaimResult(ClaimResultType.SUCCESS);
}
public int countEntities(EntityType type) {
public int getSpawnLimit(Set<Context> contexts) {
final List<Claim> parents = this.getParents(true);
for (Claim claim : parents) {
final int parentSpawnLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), GriefDefenderPlugin.DEFAULT_HOLDER, Options.SPAWN_LIMIT, claim, new HashSet<>(contexts));
if (parentSpawnLimit > -1) {
return parentSpawnLimit;
}
}
return GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), GriefDefenderPlugin.DEFAULT_HOLDER, Options.SPAWN_LIMIT, this, new HashSet<>(contexts));
}
/*public int countEntities(EntityType type) {
int count = 0;
for (Chunk chunk : this.getChunks()) {
for (Entity entity : chunk.getEntities()) {
@ -2009,6 +2041,19 @@ public class GDClaim implements Claim {
}
}
return count;
}*/
public int countEntities(Entity spawnedEntity) {
int count = 0;
for (Chunk chunk : this.getChunks()) {
for (Entity entity : chunk.getEntities()) {
if (spawnedEntity.getType() == entity.getType()) {
count++;
}
}
}
return count;
}
@ -3104,7 +3149,7 @@ public class GDClaim implements Claim {
@Override
public boolean deleteSchematic(String name) {
final Path schematicPath = GriefDefenderPlugin.getInstance().getWorldEditProvider().getSchematicWorldMap().get(this.world.getUniqueId()).resolve(this.id.toString());
final Path schematicPath = GriefDefenderPlugin.getInstance().getSchematicWorldMap().get(this.world.getUniqueId()).resolve(this.id.toString());
try {
Files.createDirectories(schematicPath);
} catch (IOException e1) {

View File

@ -43,7 +43,7 @@ import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.configuration.ClaimDataConfig;
import com.griefdefender.configuration.ClaimStorageData;
import com.griefdefender.event.GDRemoveClaimEvent;
import com.griefdefender.event.GDRemoveClaimEvent.Delete;
import com.griefdefender.internal.tracking.chunk.GDChunk;
import com.griefdefender.internal.util.BlockUtil;
import com.griefdefender.internal.util.VecHelper;
import com.griefdefender.permission.GDPermissionManager;
@ -61,6 +61,7 @@ import org.spongepowered.api.service.economy.EconomyService;
import org.spongepowered.api.service.economy.account.Account;
import org.spongepowered.api.service.economy.account.UniqueAccount;
import org.spongepowered.api.util.Direction;
import org.spongepowered.api.world.Chunk;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;
@ -89,6 +90,7 @@ public class GDClaimManager implements ClaimManager {
private Map<UUID, Claim> claimUniqueIdMap = Maps.newHashMap();
// String -> Claim
private Map<Long, Set<Claim>> chunksToClaimsMap = new Long2ObjectOpenHashMap<>(4096);
private Map<Long, GDChunk> chunksToGDChunks = new Long2ObjectOpenHashMap<>(4096);
private GDClaim theWildernessClaim;
public GDClaimManager(World world) {
@ -640,4 +642,50 @@ public class GDClaimManager implements ClaimManager {
public UUID getWorldId() {
return this.worldUniqueId;
}
public GDChunk getChunk(Chunk chunk) {
final long chunkKey = getChunkKey(chunk);
GDChunk gdChunk = this.chunksToGDChunks.get(chunkKey);
if (gdChunk == null) {
gdChunk = new GDChunk(chunk);
this.chunksToGDChunks.put(chunkKey, gdChunk);
if (this.chunksToClaimsMap.get(chunkKey) == null) {
this.theWildernessClaim.loadedChunkHashes.add(chunkKey);
}
}
return gdChunk;
}
public GDChunk getChunkIfLoaded(int cx, int cz) {
return this.chunksToGDChunks.get(getChunkKey(cx, cz));
}
public GDChunk getChunk(long key) {
return this.chunksToGDChunks.get(key);
}
public boolean isChunkLoaded(Chunk chunk) {
return this.chunksToGDChunks.get(getChunkKey(chunk)) != null;
}
public boolean isChunkLoaded(int cx, int cz) {
return this.chunksToGDChunks.get(getChunkKey(cx, cz)) != null;
}
public boolean isChunkLoaded(long key) {
return this.chunksToGDChunks.get(key) != null;
}
public void removeChunk(long key) {
this.chunksToGDChunks.remove(key);
this.theWildernessClaim.loadedChunkHashes.remove(key);
}
private long getChunkKey(int cx, int cz) {
return (long) cx & 0xffffffffL | ((long) cz & 0xffffffffL) << 32;
}
private long getChunkKey(Chunk chunk) {
return (long) chunk.getPosition().getX() & 0xffffffffL | ((long) chunk.getPosition().getZ() & 0xffffffffL) << 32;
}
}

View File

@ -518,9 +518,26 @@ public class CommonEntityEventHandler {
}
final Boolean noFly = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Boolean.class), playerData.getSubject(), Options.PLAYER_DENY_FLIGHT, toClaim);
final boolean adminFly = player.hasPermission(GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_DENY_FLIGHT.getName().toLowerCase());
final boolean ownerFly = toClaim.isBasicClaim() ? player.hasPermission(GDPermissions.USER_OPTION_PERK_OWNER_FLY_BASIC) : toClaim.isTown() ? player.hasPermission(GDPermissions.USER_OPTION_PERK_OWNER_FLY_TOWN) : false;
if (player.getUniqueId().equals(toClaim.getOwnerUniqueId()) && ownerFly) {
final boolean adminFly = playerData.userOptionBypassPlayerDenyFlight;
boolean trustFly = false;
if (toClaim.isBasicClaim() || (toClaim.parent != null && toClaim.parent.isBasicClaim()) || toClaim.isInTown()) {
// check owner
if (playerData.userOptionPerkFlyOwner && toClaim.allowEdit(player) == null) {
trustFly = true;
} else {
if (playerData.userOptionPerkFlyAccessor && toClaim.isUserTrusted(player, TrustTypes.ACCESSOR)) {
trustFly = true;
} else if (playerData.userOptionPerkFlyBuilder && toClaim.isUserTrusted(player, TrustTypes.BUILDER)) {
trustFly = true;
} else if (playerData.userOptionPerkFlyContainer && toClaim.isUserTrusted(player, TrustTypes.CONTAINER)) {
trustFly = true;
} else if (playerData.userOptionPerkFlyManager && toClaim.isUserTrusted(player, TrustTypes.MANAGER)) {
trustFly = true;
}
}
}
if (trustFly) {
return;
}
if (!adminFly && noFly) {
@ -558,7 +575,7 @@ public class CommonEntityEventHandler {
}
final Boolean noGodMode = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Boolean.class), playerData.getSubject(), Options.PLAYER_DENY_GODMODE, toClaim);
final boolean bypassOption = player.hasPermission(GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_DENY_GODMODE.getName().toLowerCase());
final boolean bypassOption = playerData.userOptionBypassPlayerDenyGodmode;
if (!bypassOption && noGodMode) {
player.offer(Keys.INVULNERABLE, false);
GriefDefenderPlugin.sendMessage(player, MessageCache.getInstance().OPTION_APPLY_PLAYER_DENY_GODMODE);
@ -586,7 +603,7 @@ public class CommonEntityEventHandler {
return;
}
final boolean bypassOption = player.hasPermission(GDPermissions.BYPASS_OPTION + "." + Options.PLAYER_GAMEMODE.getName().toLowerCase());
final boolean bypassOption = playerData.userOptionBypassPlayerGamemode;
if (!bypassOption && gameModeType != null && gameModeType != GameModeTypes.UNDEFINED) {
final GameMode newGameMode = PlayerUtil.GAMEMODE_MAP.get(gameModeType);
if (currentGameMode != newGameMode) {

View File

@ -150,7 +150,7 @@ public class EntityEventHandler {
if (!denySurfaceExplosion) {
denySurfaceExplosion = GriefDefenderPlugin.getActiveConfig(event.getTargetWorld().getUniqueId()).getConfig().claim.explosionEntitySurfaceBlacklist.contains("any");
}
System.out.println("entity size = " + event.getEntities().size());
while (iterator.hasNext()) {
Entity entity = iterator.next();
final Location<World> location = entity.getLocation();

View File

@ -1387,15 +1387,18 @@ public class PlayerEventHandler {
if (!player.hasPermission(GDPermissions.BYPASS_CLAIM_LIMIT)) {
int createClaimLimit = -1;
if (playerData.shovelMode == ShovelTypes.BASIC && (claim.isAdminClaim() || claim.isTown() || claim.isWilderness())) {
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, claim).intValue();
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, type).intValue();
} else if (playerData.shovelMode == ShovelTypes.TOWN && (claim.isAdminClaim() || claim.isWilderness())) {
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, claim).intValue();
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, type).intValue();
} else if (playerData.shovelMode == ShovelTypes.SUBDIVISION && !claim.isWilderness()) {
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, claim).intValue();
createClaimLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), player, Options.CREATE_LIMIT, type).intValue();
}
if (createClaimLimit > 0 && createClaimLimit < (playerData.getClaimTypeCount(type) + 1)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.CREATE_FAILED_CLAIM_LIMIT));
final Component message = GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.CREATE_FAILED_CLAIM_LIMIT, ImmutableMap.of(
"limit", createClaimLimit,
"type", type.getName()));
GriefDefenderPlugin.sendMessage(player, message);
return;
}
}
@ -1425,7 +1428,7 @@ public class PlayerEventHandler {
if ((type == ClaimTypes.BASIC || type == ClaimTypes.TOWN) && GriefDefenderPlugin.getGlobalConfig().getConfig().economy.economyMode) {
// Check current economy mode cost
final Double economyBlockCost = playerData.getInternalEconomyBlockCost();
if (economyBlockCost == null || economyBlockCost <= 0) {
if (economyBlockCost == null || economyBlockCost < 0) {
final Component message = GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.ECONOMY_MODE_BLOCK_COST_NOT_SET,
ImmutableMap.of(
"price", economyBlockCost == null ? "not set" : economyBlockCost));

View File

@ -27,12 +27,15 @@ package com.griefdefender.listener;
import com.griefdefender.GDTimings;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaimManager;
import com.griefdefender.internal.tracking.chunk.GDChunk;
import com.griefdefender.internal.util.NMSUtil;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.Order;
import org.spongepowered.api.event.world.LoadWorldEvent;
import org.spongepowered.api.event.world.SaveWorldEvent;
import org.spongepowered.api.event.world.UnloadWorldEvent;
import org.spongepowered.api.event.world.chunk.LoadChunkEvent;
import org.spongepowered.api.event.world.chunk.UnloadChunkEvent;
import org.spongepowered.common.SpongeImpl;
public class WorldEventHandler {
@ -75,4 +78,19 @@ public class WorldEventHandler {
claimWorldManager.save();
GDTimings.WORLD_SAVE_EVENT.stopTimingIfSync();
}
@Listener(order = Order.EARLY)
public void onChunkLoad(LoadChunkEvent event) {
final GDClaimManager claimWorldManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(event.getTargetChunk().getWorld().getUniqueId());
claimWorldManager.getChunk(event.getTargetChunk());
}
@Listener
public void onChunkUnload(UnloadChunkEvent event) {
final GDClaimManager claimWorldManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(event.getTargetChunk().getWorld().getUniqueId());
final GDChunk gdChunk = claimWorldManager.getChunk(event.getTargetChunk());
if (gdChunk != null) {
claimWorldManager.removeChunk(gdChunk.getChunkKey());
}
}
}

View File

@ -274,13 +274,14 @@ public class GDPermissionManager implements PermissionManager {
this.eventPlayerData = playerData;
final String targetPermission = flag.getPermission();
if (flag == Flags.ENTITY_SPAWN && GDOptions.isOptionEnabled(Options.SPAWN_LIMIT)) {
if (flag == Flags.ENTITY_SPAWN && GDOptions.isOptionEnabled(Options.SPAWN_LIMIT) && target instanceof Living) {
// Check spawn limit
final int spawnLimit = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Integer.class), GriefDefenderPlugin.DEFAULT_HOLDER, Options.SPAWN_LIMIT, claim, new HashSet<>(contexts));
final GDClaim gdClaim = (GDClaim) claim;
final int spawnLimit = gdClaim.getSpawnLimit(contexts);
if (spawnLimit > -1) {
if (target instanceof Entity) {
final Entity entity = (Entity) target;
final int currentEntityCount = ((GDClaim) claim).countEntities(entity .getType());
final int currentEntityCount = gdClaim.countEntities(entity);
if (currentEntityCount >= spawnLimit) {
if (source instanceof Player) {
final Component message = GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.OPTION_APPLY_SPAWN_LIMIT,
@ -1112,7 +1113,7 @@ public class GDPermissionManager implements PermissionManager {
}
public <T> T getInternalOptionValue(TypeToken<T> type, User player, Option<T> option) {
return getInternalOptionValue(type, player, option, null);
return this.getInternalOptionValue(type, player, option, (ClaimType) null);
}
public <T> T getInternalOptionValue(TypeToken<T> type, User player, Option<T> option, Claim claim) {
@ -1123,6 +1124,11 @@ public class GDPermissionManager implements PermissionManager {
return this.getInternalOptionValue(type, holder, option, (ClaimType) null);
}
public <T> T getInternalOptionValue(TypeToken<T> type, User 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);
}

View File

@ -113,8 +113,11 @@ public class GDPermissions {
public static final String COMMAND_OPTIONS_CLAIM = "griefdefender.user.claim.command.option.base";
public static final String COMMAND_OPTIONS_PLAYER = "griefdefender.user.claim.command.option.player";
public static final String COMMAND_OPTIONS_GROUP = "griefdefender.user.claim.command.option.group";
public static final String USER_OPTION_PERK_OWNER_FLY_BASIC = "griefdefender.user.option.perk.owner-fly.basic";
public static final String USER_OPTION_PERK_OWNER_FLY_TOWN = "griefdefender.user.option.perk.owner-fly.town";
public static final String USER_OPTION_PERK_FLY_OWNER = "griefdefender.user.option.perk.fly.owner";
public static final String USER_OPTION_PERK_FLY_ACCESSOR = "griefdefender.user.option.perk.fly.accessor";
public static final String USER_OPTION_PERK_FLY_BUILDER = "griefdefender.user.option.perk.fly.builder";
public static final String USER_OPTION_PERK_FLY_CONTAINER = "griefdefender.user.option.perk.fly.container";
public static final String USER_OPTION_PERK_FLY_MANAGER = "griefdefender.user.option.perk.fly.manager";
public static final String OPTION_BASE = "griefdefender";
// Economy

View File

@ -626,6 +626,14 @@ public class EconomyUtil {
}
public void sellCancelConfirmation(CommandSource src, Claim claim, Sign sign) {
final Player player = (Player) src;
final GDClaim gdClaim = (GDClaim) claim;
// check sell access
if (gdClaim.allowEdit(player) != null) {
GriefDefenderPlugin.sendMessage(player, MessageCache.getInstance().CLAIM_NOT_YOURS);
return;
}
final Component sellCancelConfirmationText = TextComponent.builder()
.append("\n[")
.append(MessageCache.getInstance().LABEL_CONFIRM.color(TextColor.GREEN))

View File

@ -3,9 +3,9 @@
"libraries": [
{
"name": "com.griefdefender:adapter-sponge:1.12.2",
"sha1": "603829ec198b9aa87e5589238256ce2e0888d2f0",
"path": "com/griefdefender/adapter-sponge/1.12.2-SNAPSHOT/adapter-sponge-1.12.2-20200603.052230-4.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter-sponge/1.12.2-SNAPSHOT/adapter-sponge-1.12.2-20200603.052230-4.jar"
"sha1": "0d9a0ef80a8fc7c470053978dc17efd9655f9e4b",
"path": "com/griefdefender/adapter-sponge/1.12.2-SNAPSHOT/adapter-sponge-1.12.2-20200607.180353-5.jar",
"url": "https://repo.glaremasters.me/repository/bloodshot/com/griefdefender/adapter-sponge/1.12.2-SNAPSHOT/adapter-sponge-1.12.2-20200607.180353-5.jar"
},
{
"name": "com.griefdefender:api:1.0.0",