feat: improve (region) fawe mask handling (#2312)

* feat: improve fawe mask handling
 - Actually cache masks, even if the player has left the region
 - Fix P2 isValid test for single plots
 - Fixes #1946

* Fix incorrect delegated method
This commit is contained in:
Jordan 2023-06-28 09:24:20 +01:00 committed by GitHub
parent 0554b31f11
commit 24325d91ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 112 additions and 74 deletions

View File

@ -225,7 +225,7 @@ public class FaweBukkit implements IFawe, Listener {
final Plugin residencePlugin = Bukkit.getServer().getPluginManager().getPlugin("Residence"); final Plugin residencePlugin = Bukkit.getServer().getPluginManager().getPlugin("Residence");
if (residencePlugin != null && residencePlugin.isEnabled()) { if (residencePlugin != null && residencePlugin.isEnabled()) {
try { try {
managers.add(new ResidenceFeature(residencePlugin, this)); managers.add(new ResidenceFeature(residencePlugin));
LOGGER.info("Attempting to use plugin 'Residence'"); LOGGER.info("Attempting to use plugin 'Residence'");
} catch (Throwable ignored) { } catch (Throwable ignored) {
} }

View File

@ -2,10 +2,7 @@ package com.fastasyncworldedit.bukkit.regions;
import com.fastasyncworldedit.core.regions.FaweMask; import com.fastasyncworldedit.core.regions.FaweMask;
import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.TaskManager;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;

View File

@ -3,7 +3,6 @@ package com.fastasyncworldedit.bukkit.regions;
import com.bekvon.bukkit.residence.Residence; import com.bekvon.bukkit.residence.Residence;
import com.bekvon.bukkit.residence.protection.ClaimedResidence; import com.bekvon.bukkit.residence.protection.ClaimedResidence;
import com.bekvon.bukkit.residence.protection.CuboidArea; import com.bekvon.bukkit.residence.protection.CuboidArea;
import com.fastasyncworldedit.bukkit.FaweBukkit;
import com.fastasyncworldedit.core.regions.FaweMask; import com.fastasyncworldedit.core.regions.FaweMask;
import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.TaskManager;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
@ -19,13 +18,8 @@ public class ResidenceFeature extends BukkitMaskManager implements Listener {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
private final FaweBukkit plugin; public ResidenceFeature(final Plugin residencePlugin) {
private final Plugin residence;
public ResidenceFeature(final Plugin residencePlugin, final FaweBukkit p3) {
super(residencePlugin.getName()); super(residencePlugin.getName());
this.residence = residencePlugin;
this.plugin = p3;
LOGGER.info("Plugin 'Residence' found. Using it now."); LOGGER.info("Plugin 'Residence' found. Using it now.");
} }

View File

@ -67,28 +67,32 @@ public class PlotSquaredFeature extends FaweMaskManager {
* @param plot the {@link Plot} * @param plot the {@link Plot}
* @param type the {@link MaskType} * @param type the {@link MaskType}
* @return {@code true} if the player is the plot owner, trusted, has the permission fawe.plotsquared.member * @return {@code true} if the player is the plot owner, trusted, has the permission fawe.plotsquared.member
* or fawe.plotsquared.admin and the NoWorldeditFlag is not set; otherwise {@code false} * or fawe.plotsquared.admin and the NoWorldeditFlag is not set; otherwise {@code false}
*/ */
public boolean isAllowed(Player player, Plot plot, MaskType type) { public boolean isAllowed(Player player, Plot plot, MaskType type, boolean notify) {
if (plot == null) { if (plot == null) {
return false; return false;
} }
UUID uid = player.getUniqueId(); UUID uid = player.getUniqueId();
if (plot.getFlag(NoWorldeditFlag.class)) { if (plot.getFlag(NoWorldeditFlag.class)) {
player.print(Caption.of( if (notify) {
"fawe.cancel.reason.no.region.reason", player.print(Caption.of(
Caption.of("fawe.cancel.reason.no.region.plot.noworldeditflag") "fawe.cancel.reason.no.region.reason",
)); Caption.of("fawe.cancel.reason.no.region.plot.noworldeditflag")
));
}
return false; return false;
} }
if (plot.isOwner(uid) || player.hasPermission("fawe.plotsquared.admin")) { if (plot.isOwner(uid) || player.hasPermission("fawe.plotsquared.admin")) {
return true; return true;
} }
if (type != MaskType.MEMBER) { if (type != MaskType.MEMBER) {
player.print(Caption.of( if (notify) {
"fawe.cancel.reason.no.region.reason", player.print(Caption.of(
Caption.of("fawe.cancel.reason.no.region.plot.owner.only") "fawe.cancel.reason.no.region.reason",
)); Caption.of("fawe.cancel.reason.no.region.plot.owner.only")
));
}
return false; return false;
} }
if (plot.getTrusted().contains(uid) || plot.getTrusted().contains(DBFunc.EVERYONE)) { if (plot.getTrusted().contains(uid) || plot.getTrusted().contains(DBFunc.EVERYONE)) {
@ -96,26 +100,32 @@ public class PlotSquaredFeature extends FaweMaskManager {
} }
if (plot.getMembers().contains(uid) || plot.getMembers().contains(DBFunc.EVERYONE)) { if (plot.getMembers().contains(uid) || plot.getMembers().contains(DBFunc.EVERYONE)) {
if (!player.hasPermission("fawe.plotsquared.member")) { if (!player.hasPermission("fawe.plotsquared.member")) {
player.print(Caption.of( if (notify) {
"fawe.cancel.reason.no.region.reason", player.print(Caption.of(
Caption.of("fawe.error.no-perm", "fawe.plotsquared.member") "fawe.cancel.reason.no.region.reason",
)); Caption.of("fawe.error.no-perm", "fawe.plotsquared.member")
));
}
return false; return false;
} }
if (!plot.getOwners().isEmpty() && plot.getOwners().stream().anyMatch(this::playerOnline)) { if (!plot.getOwners().isEmpty() && plot.getOwners().stream().anyMatch(this::playerOnline)) {
return true; return true;
} else { } else {
player.print(Caption.of( if (notify) {
"fawe.cancel.reason.no.region.reason", player.print(Caption.of(
Caption.of("fawe.cancel.reason.no.region.plot.owner.offline") "fawe.cancel.reason.no.region.reason",
)); Caption.of("fawe.cancel.reason.no.region.plot.owner.offline")
));
}
return false; return false;
} }
} }
player.print(Caption.of( if (notify) {
"fawe.cancel.reason.no.region.reason", player.print(Caption.of(
Caption.of("fawe.cancel.reason.no.region.not.added") "fawe.cancel.reason.no.region.reason",
)); Caption.of("fawe.cancel.reason.no.region.not.added")
));
}
return false; return false;
} }
@ -128,14 +138,19 @@ public class PlotSquaredFeature extends FaweMaskManager {
} }
@Override @Override
public FaweMask getMask(Player player, MaskType type, boolean isWhitelist) { public FaweMask getMask(final Player player, final MaskType type, final boolean isWhitelist) {
return getMask(player, type, isWhitelist, true);
}
@Override
public FaweMask getMask(Player player, MaskType type, boolean isWhitelist, boolean notify) {
final PlotPlayer<org.bukkit.entity.Player> pp = PlotPlayer.from(BukkitAdapter.adapt(player)); final PlotPlayer<org.bukkit.entity.Player> pp = PlotPlayer.from(BukkitAdapter.adapt(player));
if (pp == null) { if (pp == null) {
return null; return null;
} }
final Set<CuboidRegion> regions; final Set<CuboidRegion> regions;
Plot plot = pp.getCurrentPlot(); Plot plot = pp.getCurrentPlot();
if (isAllowed(player, plot, type)) { if (isAllowed(player, plot, type, notify)) {
regions = plot.getRegions(); regions = plot.getRegions();
} else { } else {
plot = null; plot = null;
@ -184,19 +199,23 @@ public class PlotSquaredFeature extends FaweMaskManager {
private final Plot plot; private final Plot plot;
private final WeakReference<Set<Plot>> connectedPlots; private final WeakReference<Set<Plot>> connectedPlots;
private final boolean singlePlot;
private PlotSquaredMask(Region region, Plot plot) { private PlotSquaredMask(Region region, Plot plot) {
super(region); super(region);
this.plot = plot; this.plot = plot;
connectedPlots = new WeakReference<>(plot.getConnectedPlots()); Set<Plot> connected = plot.getConnectedPlots();
connectedPlots = new WeakReference<>(connected);
singlePlot = connected.size() == 1;
} }
@Override @Override
public boolean isValid(Player player, MaskType type) { public boolean isValid(Player player, MaskType type, boolean notify) {
if (!connectedPlots.refersTo(plot.getConnectedPlots()) || (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(plot))) { if ((!connectedPlots.refersTo(plot.getConnectedPlots()) && !singlePlot) || (Settings.Done.RESTRICT_BUILDING && DoneFlag.isDone(
plot))) {
return false; return false;
} }
return isAllowed(player, plot, type); return isAllowed(player, plot, type, notify);
} }
} }

View File

@ -17,10 +17,30 @@ public class FaweMask implements IDelegateRegion {
return region; return region;
} }
/**
* Test if the mask is still valid
*
* @param player player to test
* @param type type of mask
* @return if still valid
*/
public boolean isValid(Player player, FaweMaskManager.MaskType type) { public boolean isValid(Player player, FaweMaskManager.MaskType type) {
return false; return false;
} }
/**
* Test if the mask is still valid
*
* @param player player to test
* @param type type of mask
* @param notify if the player should be notified
* @return if still valid
* @since TODO
*/
public boolean isValid(Player player, FaweMaskManager.MaskType type, boolean notify) {
return isValid(player, type);
}
@Override @Override
public Region clone() { public Region clone() {
throw new UnsupportedOperationException("Clone not supported"); throw new UnsupportedOperationException("Clone not supported");

View File

@ -1,7 +1,6 @@
package com.fastasyncworldedit.core.regions; package com.fastasyncworldedit.core.regions;
import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.regions.filter.RegionFilter;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import java.util.Locale; import java.util.Locale;
@ -28,6 +27,15 @@ public abstract class FaweMaskManager {
*/ */
public abstract FaweMask getMask(final Player player, MaskType type, boolean isWhitelist); public abstract FaweMask getMask(final Player player, MaskType type, boolean isWhitelist);
/**
* Get a {@link FaweMask} for the given player and {@link MaskType}. If isWhitelist is false, will return a "blacklist" mask.
*
* @since TODO
*/
public FaweMask getMask(final Player player, MaskType type, boolean isWhitelist, boolean notify) {
return getMask(player, type, isWhitelist);
}
public boolean isExclusive() { public boolean isExclusive() {
return Settings.settings().REGION_RESTRICTIONS_OPTIONS.EXCLUSIVE_MANAGERS.contains(this.key); return Settings.settings().REGION_RESTRICTIONS_OPTIONS.EXCLUSIVE_MANAGERS.contains(this.key);
} }

View File

@ -108,27 +108,22 @@ public class WEManager {
} }
player.setMeta("lastMaskWorld", world); player.setMeta("lastMaskWorld", world);
Set<FaweMask> masks = player.getMeta("lastMask"); Set<FaweMask> masks = player.getMeta("lastMask");
Set<Region> backupRegions = new HashSet<>();
Set<Region> regions = new HashSet<>(); Set<Region> regions = new HashSet<>();
if (masks == null || !isWhitelist) { if (masks == null || !isWhitelist) {
masks = new HashSet<>(); masks = new HashSet<>();
} else { } else {
synchronized (masks) { synchronized (masks) {
boolean removed = false; boolean removed = false;
boolean inMask = false;
if (!masks.isEmpty()) { if (!masks.isEmpty()) {
Iterator<FaweMask> iterator = masks.iterator(); Iterator<FaweMask> iterator = masks.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
FaweMask mask = iterator.next(); FaweMask mask = iterator.next();
if (mask.isValid(player, type)) { if (mask.isValid(player, type, false)) {
Region region = mask.getRegion(); Region region = mask.getRegion();
if (region.contains(loc.toBlockPoint())) { inMask |= region.contains(loc.toBlockPoint());
regions.add(region); regions.add(region);
} else {
removed = true;
backupRegions.add(region);
}
} else { } else {
if (Settings.settings().ENABLED_COMPONENTS.DEBUG) { if (Settings.settings().ENABLED_COMPONENTS.DEBUG) {
player.printDebug(Caption.of("fawe.error.region-mask-invalid", mask.getClass().getSimpleName())); player.printDebug(Caption.of("fawe.error.region-mask-invalid", mask.getClass().getSimpleName()));
@ -138,39 +133,44 @@ public class WEManager {
} }
} }
} }
if (!removed) { if (!removed && inMask) {
return regions.toArray(new Region[0]); return regions.toArray(new Region[0]);
} }
masks.clear();
} }
} }
for (FaweMaskManager manager : managers) { synchronized (masks) {
if (player.hasPermission("fawe." + manager.getKey())) { for (FaweMaskManager manager : managers) {
try { if (player.hasPermission("fawe." + manager.getKey())) {
if (manager.isExclusive() && !masks.isEmpty()) { try {
continue; if (manager.isExclusive() && !masks.isEmpty()) {
} continue;
final FaweMask mask = manager.getMask(player, FaweMaskManager.MaskType.getDefaultMaskType(), isWhitelist);
if (mask != null) {
regions.add(mask.getRegion());
masks.add(mask);
if (manager.isExclusive()) {
break;
} }
final FaweMask mask = manager.getMask(
player,
FaweMaskManager.MaskType.getDefaultMaskType(),
isWhitelist,
masks.isEmpty()
);
if (mask != null) {
regions.add(mask.getRegion());
masks.add(mask);
if (manager.isExclusive()) {
break;
}
}
} catch (Throwable e) {
e.printStackTrace();
} }
} catch (Throwable e) { } else {
e.printStackTrace(); player.printError(TextComponent.of("Missing permission " + "fawe." + manager.getKey()));
} }
} else {
player.printError(TextComponent.of("Missing permission " + "fawe." + manager.getKey()));
} }
} if (isWhitelist) {
if (isWhitelist) { if (!masks.isEmpty()) {
regions.addAll(backupRegions); player.setMeta("lastMask", masks);
if (!masks.isEmpty()) { } else {
player.setMeta("lastMask", masks); player.deleteMeta("lastMask");
} else { }
player.deleteMeta("lastMask");
} }
} }
return regions.toArray(new Region[0]); return regions.toArray(new Region[0]);