diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/DelayedRegionOverlapAssociation.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/DelayedRegionOverlapAssociation.java index e71d0e0b..4a5f0d1e 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/DelayedRegionOverlapAssociation.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/DelayedRegionOverlapAssociation.java @@ -75,10 +75,19 @@ public Association getAssociation(List regions) { if (source == null) { ApplicableRegionSet result = query.getApplicableRegions(location); source = result.getRegions(); - if (useMaxPriorityAssociation) - maxPriority = source.stream().mapToInt(ProtectedRegion::getPriority).max().orElse(0); - } + assert source != null; + if (useMaxPriorityAssociation) { + int best = 0; + for (ProtectedRegion region : source) { + int priority = region.getPriority(); + if (priority > best) { + best = priority; + } + } + maxPriority = best; + } + } for (ProtectedRegion region : regions) { if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty())) { @@ -88,7 +97,9 @@ public Association getAssociation(List regions) { if (source.contains(region)) { if (useMaxPriorityAssociation) { int priority = region.getPriority(); - if (priority == maxPriority) return Association.OWNER; + if (priority == maxPriority) { + return Association.OWNER; + } } else { return Association.OWNER; } diff --git a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/association/RegionOverlapAssociation.java b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/association/RegionOverlapAssociation.java index 89c608f2..04fc2c19 100644 --- a/worldguard-core/src/main/java/com/sk89q/worldguard/protection/association/RegionOverlapAssociation.java +++ b/worldguard-core/src/main/java/com/sk89q/worldguard/protection/association/RegionOverlapAssociation.java @@ -34,6 +34,8 @@ public class RegionOverlapAssociation implements RegionAssociable { private final Set source; + private boolean useMaxPriorityAssociation; + private int maxPriority; // only used for useMaxPriorityAssociation /** * Create a new instance. @@ -41,16 +43,46 @@ public class RegionOverlapAssociation implements RegionAssociable { * @param source set of regions that input regions must be contained within */ public RegionOverlapAssociation(Set source) { + this(source, false); + } + + /** + * Create a new instance. + * + * @param source set of regions that input regions must be contained within + * @param useMaxPriorityAssociation whether to use the max priority from regions to determine association + */ + public RegionOverlapAssociation(Set source, boolean useMaxPriorityAssociation) { checkNotNull(source); this.source = source; + this.useMaxPriorityAssociation = useMaxPriorityAssociation; + int best = 0; + for (ProtectedRegion region : source) { + int priority = region.getPriority(); + if (priority > best) { + best = priority; + } + } + this.maxPriority = best; } @Override public Association getAssociation(List regions) { for (ProtectedRegion region : regions) { - if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty()) || source.contains(region)) { + if ((region.getId().equals(ProtectedRegion.GLOBAL_REGION) && source.isEmpty())) { return Association.OWNER; } + + if (source.contains(region)) { + if (useMaxPriorityAssociation) { + int priority = region.getPriority(); + if (priority == maxPriority) { + return Association.OWNER; + } + } else { + return Association.OWNER; + } + } } return Association.NON_MEMBER; diff --git a/worldguard-core/src/test/java/com/sk89q/worldguard/protection/RegionOverlapTest.java b/worldguard-core/src/test/java/com/sk89q/worldguard/protection/RegionOverlapTest.java index 7bfbeddb..44d0eec8 100644 --- a/worldguard-core/src/test/java/com/sk89q/worldguard/protection/RegionOverlapTest.java +++ b/worldguard-core/src/test/java/com/sk89q/worldguard/protection/RegionOverlapTest.java @@ -38,10 +38,14 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; +@RunWith(Parameterized.class) public abstract class RegionOverlapTest { static String COURTYARD_ID = "courtyard"; static String FOUNTAIN_ID = "fountain"; @@ -60,6 +64,14 @@ public abstract class RegionOverlapTest { TestPlayer player1; TestPlayer player2; + @Parameterized.Parameters(name = "{index}: useMaxPrio = {0}") + public static Iterable params() { + return Arrays.asList(new Object[][]{{true}, {false}}); + } + + @Parameterized.Parameter + public boolean useMaxPriorityAssociation; + protected FlagRegistry getFlagRegistry() { return WorldGuard.getInstance().getFlagRegistry(); } @@ -105,6 +117,7 @@ void setUpCourtyardRegion() { ProtectedRegion region = new ProtectedPolygonalRegion(COURTYARD_ID, points, 0, 10); region.setOwners(domain); + region.setPriority(5); manager.addRegion(region); courtyard = region; @@ -117,6 +130,7 @@ void setUpFountainRegion() throws Exception { ProtectedRegion region = new ProtectedCuboidRegion(FOUNTAIN_ID, BlockVector3.ZERO, BlockVector3.at(5, 5, 5)); region.setMembers(domain); + region.setPriority(10); manager.addRegion(region); fountain = region; @@ -186,7 +200,7 @@ public void testNonPlayerBuildAccessInOneRegion() { HashSet source = new HashSet<>(); source.add(courtyard); - RegionOverlapAssociation assoc = new RegionOverlapAssociation(source); + RegionOverlapAssociation assoc = new RegionOverlapAssociation(source, useMaxPriorityAssociation); // Outside appl = manager.getApplicableRegions(outside); @@ -206,14 +220,14 @@ public void testNonPlayerBuildAccessInBothRegions() { HashSet source = new HashSet<>(); source.add(fountain); source.add(courtyard); - RegionOverlapAssociation assoc = new RegionOverlapAssociation(source); + RegionOverlapAssociation assoc = new RegionOverlapAssociation(source, useMaxPriorityAssociation); // Outside appl = manager.getApplicableRegions(outside); assertTrue(appl.testState(assoc, Flags.BUILD)); // Inside courtyard appl = manager.getApplicableRegions(inCourtyard); - assertTrue(appl.testState(assoc, Flags.BUILD)); + assertTrue(useMaxPriorityAssociation ^ appl.testState(assoc, Flags.BUILD)); // Inside fountain appl = manager.getApplicableRegions(inFountain); assertTrue(appl.testState(assoc, Flags.BUILD)); @@ -224,7 +238,7 @@ public void testNonPlayerBuildAccessInNoRegions() { ApplicableRegionSet appl; HashSet source = new HashSet<>(); - RegionOverlapAssociation assoc = new RegionOverlapAssociation(source); + RegionOverlapAssociation assoc = new RegionOverlapAssociation(source, useMaxPriorityAssociation); // Outside appl = manager.getApplicableRegions(outside);