From c64baf0baa70d373c05ced1317f33126f4458751 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 5 Dec 2021 13:50:15 -0500 Subject: [PATCH] Sanitize claim depth on extend/resize (#1598) Closes #312 --- .../GriefPrevention/DataStore.java | 71 ++++++++++++++----- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/src/main/java/me/ryanhamshire/GriefPrevention/DataStore.java b/src/main/java/me/ryanhamshire/GriefPrevention/DataStore.java index 05a70a5..2104219 100644 --- a/src/main/java/me/ryanhamshire/GriefPrevention/DataStore.java +++ b/src/main/java/me/ryanhamshire/GriefPrevention/DataStore.java @@ -61,6 +61,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Pattern; +import java.util.stream.Stream; //singleton class which manages all GriefPrevention data (except for config options) public abstract class DataStore @@ -925,6 +926,7 @@ public abstract class DataStore result.claim = parent; return result; } + smally = sanitizeClaimDepth(parent, smally); } //creative mode claims always go to bedrock @@ -1067,31 +1069,62 @@ public abstract class DataStore //respects the max depth config variable synchronized public void extendClaim(Claim claim, int newDepth) { - newDepth = Math.max( - Objects.requireNonNull(claim.getLesserBoundaryCorner().getWorld()).getMinHeight(), - Math.max( - newDepth, - GriefPrevention.instance.config_claims_maxDepth)); - if (claim.parent != null) claim = claim.parent; + newDepth = sanitizeClaimDepth(claim, newDepth); + //call event and return if event got cancelled ClaimExtendEvent event = new ClaimExtendEvent(claim, newDepth); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) return; //adjust to new depth - claim.lesserBoundaryCorner.setY(newDepth); - claim.greaterBoundaryCorner.setY(newDepth); - for (Claim subdivision : claim.children) - { - subdivision.lesserBoundaryCorner.setY(newDepth); - subdivision.greaterBoundaryCorner.setY(newDepth); - this.saveClaim(subdivision); - } + setNewDepth(claim, event.getNewDepth()); + } - //save changes - this.saveClaim(claim); + /** + * Helper method for sanitizing claim depth to find the minimum expected value. + * + * @param claim the claim + * @param newDepth the new depth + * @return the sanitized new depth + */ + private int sanitizeClaimDepth(Claim claim, int newDepth) { + if (claim.parent != null) claim = claim.parent; + + // Get the old depth including the depth of the lowest subdivision. + int oldDepth = Math.min( + claim.getLesserBoundaryCorner().getBlockY(), + claim.children.stream().mapToInt(child -> child.getLesserBoundaryCorner().getBlockY()) + .min().orElse(Integer.MAX_VALUE)); + + // Use the lowest of the old and new depths. + newDepth = Math.min(newDepth, oldDepth); + // Cap depth to maximum depth allowed by the configuration. + newDepth = Math.max(newDepth, GriefPrevention.instance.config_claims_maxDepth); + // Cap the depth to the world's minimum height. + World world = Objects.requireNonNull(claim.getLesserBoundaryCorner().getWorld()); + newDepth = Math.max(newDepth, world.getMinHeight()); + + return newDepth; + } + + /** + * Helper method for sanitizing and setting claim depth. Saves affected claims. + * + * @param claim the claim + * @param newDepth the new depth + */ + private void setNewDepth(Claim claim, int newDepth) { + if (claim.parent != null) claim = claim.parent; + + final int depth = sanitizeClaimDepth(claim, newDepth); + + Stream.concat(Stream.of(claim), claim.children.stream()).forEach(localClaim -> { + localClaim.lesserBoundaryCorner.setY(depth); + localClaim.greaterBoundaryCorner.setY(Math.max(localClaim.greaterBoundaryCorner.getBlockY(), depth)); + this.saveClaim(localClaim); + }); } //starts a siege on a claim @@ -1350,11 +1383,11 @@ public abstract class DataStore // copy the boundary from the claim created in the dry run of createClaim() to our existing claim claim.lesserBoundaryCorner = result.claim.lesserBoundaryCorner; claim.greaterBoundaryCorner = result.claim.greaterBoundaryCorner; + // Sanitize claim depth, expanding parent down to the lowest subdivision and subdivisions down to parent. + // Also saves affected claims. + setNewDepth(claim, claim.getLesserBoundaryCorner().getBlockY()); result.claim = claim; addToChunkClaimMap(claim); // add the new boundary to the chunk cache - - //save those changes - this.saveClaim(result.claim); } return result;