diff --git a/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java b/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java index 6eb1f5bc..76260805 100644 --- a/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java +++ b/src/main/java/com/sk89q/worldguard/bukkit/listener/RegionProtectionListener.java @@ -31,6 +31,7 @@ import com.sk89q.worldguard.bukkit.event.entity.DestroyEntityEvent; import com.sk89q.worldguard.bukkit.event.entity.SpawnEntityEvent; import com.sk89q.worldguard.bukkit.event.entity.UseEntityEvent; +import com.sk89q.worldguard.bukkit.util.DelayedRegionOverlapAssociation; import com.sk89q.worldguard.bukkit.util.Entities; import com.sk89q.worldguard.bukkit.util.Materials; import com.sk89q.worldguard.domains.Association; @@ -114,12 +115,10 @@ private RegionAssociable createRegionAssociable(Cause cause) { return getPlugin().wrapPlayer((Player) rootCause); } else if (rootCause instanceof Entity) { RegionQuery query = getPlugin().getRegionContainer().createQuery(); - ApplicableRegionSet source = query.getApplicableRegions(((Entity) rootCause).getLocation()); - return new RegionOverlapAssociation(source.getRegions()); + return new DelayedRegionOverlapAssociation(query, ((Entity) rootCause).getLocation()); } else if (rootCause instanceof Block) { RegionQuery query = getPlugin().getRegionContainer().createQuery(); - ApplicableRegionSet source = query.getApplicableRegions(((Block) rootCause).getLocation()); - return new RegionOverlapAssociation(source.getRegions()); + return new DelayedRegionOverlapAssociation(query, ((Block) rootCause).getLocation()); } else { return Associables.constant(Association.NON_MEMBER); } diff --git a/src/main/java/com/sk89q/worldguard/bukkit/util/DelayedRegionOverlapAssociation.java b/src/main/java/com/sk89q/worldguard/bukkit/util/DelayedRegionOverlapAssociation.java new file mode 100644 index 00000000..85a30a19 --- /dev/null +++ b/src/main/java/com/sk89q/worldguard/bukkit/util/DelayedRegionOverlapAssociation.java @@ -0,0 +1,75 @@ +/* + * WorldGuard, a suite of tools for Minecraft + * Copyright (C) sk89q + * Copyright (C) WorldGuard team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldguard.bukkit.util; + +import com.sk89q.worldguard.bukkit.RegionQuery; +import com.sk89q.worldguard.domains.Association; +import com.sk89q.worldguard.protection.ApplicableRegionSet; +import com.sk89q.worldguard.protection.association.RegionAssociable; +import com.sk89q.worldguard.protection.regions.ProtectedRegion; +import org.bukkit.Location; + +import javax.annotation.Nullable; +import java.util.Set; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Determines that the association to a region is {@code OWNER} if the input + * region is in a set of source regions. + * + *

This class only performs a spatial query if its + * {@link #getAssociation(ProtectedRegion)} method is called.

+ */ +public class DelayedRegionOverlapAssociation implements RegionAssociable { + + private final RegionQuery query; + private final Location location; + @Nullable + private Set source; + + /** + * Create a new instance. + * + * @param query the query + * @param location the location + */ + public DelayedRegionOverlapAssociation(RegionQuery query, Location location) { + checkNotNull(query); + checkNotNull(location); + this.query = query; + this.location = location; + } + + @Override + public Association getAssociation(ProtectedRegion region) { + if (source == null) { + ApplicableRegionSet result = query.getApplicableRegions(location); + source = result.getRegions(); + } + + if (source.contains(region)) { + return Association.OWNER; + } else { + return Association.NON_MEMBER; + } + } + +}