mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-04 03:56:41 +00:00
Implement region blacklisting
This commit is contained in:
@ -86,6 +86,7 @@ public final class EditSessionBuilder {
|
||||
private FaweLimit limit;
|
||||
private AbstractChangeSet changeSet;
|
||||
private Region[] allowedRegions;
|
||||
private Region[] disallowedRegions;
|
||||
private Boolean fastMode;
|
||||
private Boolean checkMemory;
|
||||
private Boolean combineStages;
|
||||
@ -341,6 +342,34 @@ public final class EditSessionBuilder {
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the regions the edit is allowed to operate in. Set to null for the regions to be calculated based on the actor if
|
||||
* present
|
||||
*/
|
||||
public EditSessionBuilder disallowedRegions(@Nullable Region[] disallowedRegions) {
|
||||
this.disallowedRegions = disallowedRegions;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the regions the edit is allowed to operate in. Set to null for the regions to be calculated based on the actor if
|
||||
* present
|
||||
*/
|
||||
@Deprecated
|
||||
public EditSessionBuilder disallowedRegions(@Nullable RegionWrapper[] disallowedRegions) {
|
||||
this.disallowedRegions = disallowedRegions;
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the region the edit is allowed to operate in. Set to null for the regions to be calculated based on the actor if
|
||||
* present
|
||||
*/
|
||||
public EditSessionBuilder disallowedRegions(@Nullable RegionWrapper disallowedRegion) {
|
||||
this.disallowedRegions = disallowedRegion == null ? null : disallowedRegion.toArray();
|
||||
return setDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the edit to be allowed to edit everywhere
|
||||
*/
|
||||
@ -511,23 +540,33 @@ public final class EditSessionBuilder {
|
||||
if (actor != null && !actor.hasPermission("fawe.bypass") && !actor.hasPermission("fawe.bypass.regions")) {
|
||||
if (actor instanceof Player) {
|
||||
Player player = (Player) actor;
|
||||
allowedRegions = player.getCurrentRegions();
|
||||
allowedRegions = player.getAllowedRegions();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (disallowedRegions == null && Settings.IMP.REGION_RESTRICTIONS && Settings.IMP.REGION_RESTRICTIONS_OPTIONS.ALLOW_BLACKLISTS) {
|
||||
if (actor != null && !actor.hasPermission("fawe.bypass") && !actor.hasPermission("fawe.bypass.regions")) {
|
||||
if (actor instanceof Player) {
|
||||
Player player = (Player) actor;
|
||||
disallowedRegions = player.getDisallowedRegions();
|
||||
}
|
||||
}
|
||||
}
|
||||
FaweRegionExtent regionExtent = null;
|
||||
if (allowedRegions != null) {
|
||||
if (disallowedRegions != null) { // Always use MultiRegionExtent if we have blacklist regions
|
||||
regionExtent = new MultiRegionExtent(this.extent, this.limit, allowedRegions, disallowedRegions);
|
||||
} else if (allowedRegions == null) {
|
||||
allowedRegions = new Region[]{RegionWrapper.GLOBAL()};
|
||||
} else {
|
||||
if (allowedRegions.length == 0) {
|
||||
regionExtent = new NullExtent(this.extent, FaweCache.NO_REGION);
|
||||
} else {
|
||||
if (allowedRegions.length == 1) {
|
||||
regionExtent = new SingleRegionExtent(this.extent, this.limit, allowedRegions[0]);
|
||||
} else {
|
||||
regionExtent = new MultiRegionExtent(this.extent, this.limit, allowedRegions);
|
||||
regionExtent = new MultiRegionExtent(this.extent, this.limit, allowedRegions, disallowedRegions);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
allowedRegions = new Region[]{RegionWrapper.GLOBAL()};
|
||||
}
|
||||
// There's no need to do lighting (and it'll also just be a pain to implement) if we're not placing chunks
|
||||
if (placeChunks) {
|
||||
|
@ -348,12 +348,46 @@ public interface Player extends Entity, Actor {
|
||||
<B extends BlockStateHolder<B>> void sendFakeBlock(BlockVector3 pos, @Nullable B block);
|
||||
|
||||
//FAWE start
|
||||
Region[] getCurrentRegions();
|
||||
/**
|
||||
* Get the player's current allowed WorldEdit regions.
|
||||
*
|
||||
* @return an array of allowed regions
|
||||
*/
|
||||
Region[] getAllowedRegions();
|
||||
|
||||
Region[] getCurrentRegions(FaweMaskManager.MaskType type);
|
||||
/**
|
||||
* Get the player's current allowed WorldEdit regions.
|
||||
*
|
||||
* @param type Mask type; whether to check if the player is an owner of a member of the regions
|
||||
* @return an array of allowed regions
|
||||
*/
|
||||
Region[] getAllowedRegions(FaweMaskManager.MaskType type);
|
||||
|
||||
/**
|
||||
* Get the player's current disallowed WorldEdit regions. Effectively a blacklist.
|
||||
*
|
||||
* @return an array of disallowed regions
|
||||
*/
|
||||
Region[] getDisallowedRegions();
|
||||
|
||||
/**
|
||||
* Get the player's current disallowed WorldEdit regions. Effectively a blacklist.
|
||||
*
|
||||
* @param type Mask type; whether to check if the player is an owner of a member of the regions
|
||||
* @return an array of disallowed regions
|
||||
*/
|
||||
Region[] getDisallowedRegions(FaweMaskManager.MaskType type);
|
||||
|
||||
/**
|
||||
* Get the largest region in the player's allowed WorldEdit region.
|
||||
*/
|
||||
Region getLargestRegion();
|
||||
|
||||
/**
|
||||
* Set a players selection and selector type to the given region
|
||||
*/
|
||||
void setSelection(Region region);
|
||||
|
||||
/**
|
||||
* Get the player's selection region. If the selection is defined in
|
||||
* a different world, the {@code IncompleteRegionException}
|
||||
@ -366,8 +400,6 @@ public interface Player extends Entity, Actor {
|
||||
return getSession().getSelection(getWorld());
|
||||
}
|
||||
|
||||
void setSelection(Region region);
|
||||
|
||||
/**
|
||||
* Set the player's WorldEdit selection.
|
||||
*
|
||||
|
@ -483,27 +483,31 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
|
||||
}
|
||||
|
||||
//FAWE start
|
||||
|
||||
/**
|
||||
* Get the player's current allowed WorldEdit regions.
|
||||
*
|
||||
* @return an array of allowed regions
|
||||
*/
|
||||
public Region[] getCurrentRegions() {
|
||||
return getCurrentRegions(FaweMaskManager.MaskType.MEMBER);
|
||||
@Override
|
||||
public Region[] getAllowedRegions() {
|
||||
return getAllowedRegions(FaweMaskManager.MaskType.getDefaultMaskType());
|
||||
}
|
||||
|
||||
public Region[] getCurrentRegions(FaweMaskManager.MaskType type) {
|
||||
return WEManager.IMP.getMask(this, type);
|
||||
@Override
|
||||
public Region[] getAllowedRegions(FaweMaskManager.MaskType type) {
|
||||
return WEManager.IMP.getMask(this, type, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the largest region in the player's allowed WorldEdit region.
|
||||
*/
|
||||
@Override
|
||||
public Region[] getDisallowedRegions() {
|
||||
return getDisallowedRegions(FaweMaskManager.MaskType.getDefaultMaskType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region[] getDisallowedRegions(FaweMaskManager.MaskType type) {
|
||||
return WEManager.IMP.getMask(this, type, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Region getLargestRegion() {
|
||||
long area = 0;
|
||||
Region max = null;
|
||||
for (Region region : this.getCurrentRegions()) {
|
||||
for (Region region : this.getAllowedRegions()) {
|
||||
final long tmp = region.getVolume();
|
||||
if (tmp > area) {
|
||||
area = tmp;
|
||||
@ -513,6 +517,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
|
||||
return max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelection(Region region) {
|
||||
RegionSelector selector;
|
||||
if (region instanceof ConvexPolyhedralRegion) {
|
||||
|
@ -748,13 +748,13 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
if (minY <= set.getMinSectionPosition() << 4 && maxY >= (set.getMaxSectionPosition() << 4) + 15) {
|
||||
return set;
|
||||
}
|
||||
trimY(set, minY, maxY);
|
||||
trimY(set, minY, maxY, true);
|
||||
trimNBT(set, this::contains);
|
||||
return set;
|
||||
}
|
||||
if (tx >= minX && bx <= maxX && tz >= minZ && bz <= maxZ) {
|
||||
if (minY > set.getMinSectionPosition() << 4 || maxY < (set.getMaxSectionPosition() << 4) + 15) {
|
||||
trimY(set, minY, maxY);
|
||||
trimY(set, minY, maxY, true);
|
||||
}
|
||||
final int lowerX = Math.max(0, minX - bx);
|
||||
final int upperX = Math.min(15, 15 + maxX - tx);
|
||||
@ -769,51 +769,128 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
||||
boolean trimZ = lowerZ != 0 || upperZ != 15;
|
||||
|
||||
for (int layer = get.getMinSectionPosition(); layer < get.getMaxSectionPosition(); layer++) {
|
||||
if (set.hasSection(layer)) {
|
||||
char[] arr = Objects.requireNonNull(set.loadIfPresent(layer)); // This shouldn't be null if above is true
|
||||
if (trimX || trimZ) {
|
||||
int indexY = 0;
|
||||
for (int y = 0; y < 16; y++, indexY += 256) { // For each y layer within a chunk section
|
||||
int index;
|
||||
if (trimZ) {
|
||||
index = indexY;
|
||||
for (int z = 0; z < lowerZ; z++) {
|
||||
// null the z values
|
||||
for (int x = 0; x < 16; x++, index++) {
|
||||
arr[index] = 0;
|
||||
}
|
||||
}
|
||||
index = indexY + upperZi;
|
||||
for (int z = upperZ + 1; z < 16; z++) {
|
||||
// null the z values
|
||||
for (int x = 0; x < 16; x++, index++) {
|
||||
arr[index] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trimX) {
|
||||
index = indexY + lowerZi;
|
||||
for (int z = lowerZ; z <= upperZ; z++, index += 16) {
|
||||
for (int x = 0; x < lowerX; x++) {
|
||||
// null the x values
|
||||
arr[index + x] = 0;
|
||||
}
|
||||
for (int x = upperX + 1; x < 16; x++) {
|
||||
// null the x values
|
||||
arr[index + x] = 0;
|
||||
}
|
||||
}
|
||||
if (!set.hasSection(layer)) {
|
||||
continue;
|
||||
}
|
||||
char[] arr = Objects.requireNonNull(set.loadIfPresent(layer)); // This shouldn't be null if above is true
|
||||
if (!(trimX || trimZ)) {
|
||||
continue;
|
||||
}
|
||||
int indexY = 0;
|
||||
for (int y = 0; y < 16; y++, indexY += 256) { // For each y layer within a chunk section
|
||||
int index;
|
||||
if (trimZ) {
|
||||
index = indexY;
|
||||
for (int z = 0; z < lowerZ; z++) {
|
||||
// null the z values
|
||||
for (int x = 0; x < 16; x++, index++) {
|
||||
arr[index] = 0;
|
||||
}
|
||||
}
|
||||
index = indexY + upperZi;
|
||||
for (int z = upperZ + 1; z < 16; z++) {
|
||||
// null the z values
|
||||
for (int x = 0; x < 16; x++, index++) {
|
||||
arr[index] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trimX) {
|
||||
index = indexY + lowerZi; // Skip blocks already removed by trimZ
|
||||
for (int z = lowerZ; z <= upperZ; z++, index += 16) {
|
||||
for (int x = 0; x < lowerX; x++) {
|
||||
// null the x values
|
||||
arr[index + x] = 0;
|
||||
}
|
||||
for (int x = upperX + 1; x < 16; x++) {
|
||||
// null the x values
|
||||
arr[index + x] = 0;
|
||||
}
|
||||
}
|
||||
set.setBlocks(layer, arr);
|
||||
}
|
||||
}
|
||||
set.setBlocks(layer, arr);
|
||||
}
|
||||
|
||||
trimNBT(set, this::contains);
|
||||
return set;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set, boolean asBlacklist) {
|
||||
if (!asBlacklist) {
|
||||
return processSet(chunk, get, set);
|
||||
}
|
||||
int bx = chunk.getX() << 4;
|
||||
int bz = chunk.getZ() << 4;
|
||||
int tx = bx + 15;
|
||||
int tz = bz + 15;
|
||||
|
||||
if (bx >= minX && tx <= maxX && bz >= minZ && tz <= maxZ) {
|
||||
// contains all X/Z
|
||||
int sMaxY = (set.getMaxSectionPosition() << 4) + 15;
|
||||
int sMinY = set.getMinSectionPosition() << 4;
|
||||
if (minY <= sMinY && maxY >= sMaxY) {
|
||||
return null;
|
||||
}
|
||||
trimY(set, minY, maxY, false);
|
||||
trimNBT(set, this::contains);
|
||||
return set;
|
||||
}
|
||||
if (tx >= minX && bx <= maxX && tz >= minZ && bz <= maxZ) {
|
||||
if (minY > set.getMinSectionPosition() << 4 || maxY < (set.getMaxSectionPosition() << 4) + 15) {
|
||||
trimY(set, minY, maxY, false);
|
||||
}
|
||||
final int lowerX = Math.max(0, minX - bx);
|
||||
final int upperX = Math.min(15, 15 + maxX - tx);
|
||||
|
||||
final int lowerZ = Math.max(0, minZ - bz);
|
||||
final int upperZ = Math.min(15, 15 + maxZ - tz);
|
||||
|
||||
final int lowerZi = (lowerZ << 4);
|
||||
|
||||
boolean trimX = lowerX != 0 || upperX != 15;
|
||||
boolean trimZ = lowerZ != 0 || upperZ != 15;
|
||||
|
||||
for (int layer = get.getMinSectionPosition(); layer < get.getMaxSectionPosition(); layer++) {
|
||||
if (!set.hasSection(layer)) {
|
||||
continue;
|
||||
}
|
||||
char[] arr = Objects.requireNonNull(set.loadIfPresent(layer)); // This shouldn't be null if above is true
|
||||
if (!(trimX || trimZ)) {
|
||||
continue;
|
||||
}
|
||||
int indexY = 0;
|
||||
for (int y = 0; y < 16; y++, indexY += 256) { // For each y layer within a chunk section
|
||||
int index;
|
||||
if (trimZ) {
|
||||
index = indexY;
|
||||
for (int z = lowerZ; z <= upperZ; z++) {
|
||||
// null the z values
|
||||
for (int x = 0; x < 16; x++, index++) {
|
||||
arr[index] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trimX) {
|
||||
index = indexY + lowerZi; // Skip blocks already removed by trimZ
|
||||
for (int z = lowerZ; z <= upperZ; z++, index += 16) {
|
||||
for (int x = lowerX; x <= upperX; x++) {
|
||||
// null the x values
|
||||
arr[index + x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
set.setBlocks(layer, arr);
|
||||
}
|
||||
trimNBT(set, bv3 -> !this.contains(bv3));
|
||||
return set;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
//FAWE end
|
||||
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldedit.regions;
|
||||
|
||||
import com.fastasyncworldedit.core.FaweCache;
|
||||
import com.fastasyncworldedit.core.extent.SingleRegionExtent;
|
||||
import com.fastasyncworldedit.core.extent.filter.block.ChunkFilterBlock;
|
||||
import com.fastasyncworldedit.core.extent.processor.ProcessorScope;
|
||||
@ -366,6 +367,7 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
||||
return tx >= min.getX() && bx <= max.getX() && tz >= min.getZ() && bz <= max.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
default IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
int bx = chunk.getX() << 4;
|
||||
int bz = chunk.getZ() << 4;
|
||||
@ -377,12 +379,10 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
||||
if (tx >= min.getX() && bx <= max.getX() && tz >= min.getZ() && bz <= max.getZ()) {
|
||||
// contains some
|
||||
boolean processExtra = false;
|
||||
for (int layer = 0; layer < 16; layer++) {
|
||||
for (int layer = getMinimumY() >> 4; layer <= getMaximumY() >> 4; layer++) {
|
||||
int by = layer << 4;
|
||||
int ty = by + 15;
|
||||
if (containsEntireCuboid(bx, tx, by, ty, bz, tz)) {
|
||||
continue;
|
||||
} else {
|
||||
if (!containsEntireCuboid(bx, tx, by, ty, bz, tz)) {
|
||||
processExtra = true;
|
||||
char[] arr = set.load(layer);
|
||||
for (int y = 0, index = 0; y < 16; y++) {
|
||||
@ -406,6 +406,58 @@ public interface Region extends Iterable<BlockVector3>, Cloneable, IBatchProcess
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the chunk, with the option to process as if the region is a blacklisted region, and thus any contained blocks
|
||||
* should be removed, rather than uncontained blocks being removed.
|
||||
*
|
||||
* @param asBlacklist If any blocks contained by the region should be removed
|
||||
*/
|
||||
default IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set, boolean asBlacklist) {
|
||||
if (!asBlacklist) {
|
||||
return processSet(chunk, get, set);
|
||||
}
|
||||
int bx = chunk.getX() << 4;
|
||||
int bz = chunk.getZ() << 4;
|
||||
int tx = bx + 15;
|
||||
int tz = bz + 15;
|
||||
|
||||
BlockVector3 min = getMinimumPoint();
|
||||
BlockVector3 max = getMaximumPoint();
|
||||
if (tx >= min.getX() && bx <= max.getX() && tz >= min.getZ() && bz <= max.getZ()) {
|
||||
// contains some
|
||||
boolean processExtra = false;
|
||||
for (int layer = getMinimumY() >> 4; layer <= getMaximumY() >> 4; layer++) {
|
||||
int by = layer << 4;
|
||||
int ty = by + 15;
|
||||
if (containsEntireCuboid(bx, tx, by, ty, bz, tz)) {
|
||||
set.setBlocks(layer, FaweCache.IMP.EMPTY_CHAR_4096);
|
||||
processExtra = true;
|
||||
continue;
|
||||
}
|
||||
char[] arr = set.load(layer);
|
||||
for (int y = 0, index = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++, index++) {
|
||||
if (arr[index] != 0 && contains(x, y, z)) {
|
||||
arr[index] = 0;
|
||||
processExtra = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (processExtra) {
|
||||
set.setBlocks(layer, arr);
|
||||
}
|
||||
}
|
||||
if (processExtra) {
|
||||
trimNBT(set, bv3 -> !this.contains(bv3));
|
||||
}
|
||||
return set;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
default Future<IChunkSet> postProcessSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
// Doesn't need to do anything
|
||||
|
@ -30,12 +30,11 @@ import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@ -58,7 +57,7 @@ public class RegionIntersection extends AbstractRegion {
|
||||
*
|
||||
* @param regions a list of regions, which is copied
|
||||
*/
|
||||
public RegionIntersection(List<Region> regions) {
|
||||
public RegionIntersection(Collection<Region> regions) {
|
||||
this(null, regions);
|
||||
}
|
||||
|
||||
@ -77,7 +76,7 @@ public class RegionIntersection extends AbstractRegion {
|
||||
* @param world the world
|
||||
* @param regions a list of regions, which is copied
|
||||
*/
|
||||
public RegionIntersection(World world, List<Region> regions) {
|
||||
public RegionIntersection(World world, Collection<Region> regions) {
|
||||
super(world);
|
||||
checkNotNull(regions);
|
||||
checkArgument(!regions.isEmpty(), "empty region list is not supported");
|
||||
@ -174,9 +173,22 @@ public class RegionIntersection extends AbstractRegion {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<IChunkSet> postProcessSet(IChunk chunk, IChunkGet get, IChunkSet set) {
|
||||
// Doesn't need to do anything
|
||||
return CompletableFuture.completedFuture(set);
|
||||
public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set, boolean asBlacklist) {
|
||||
if (!asBlacklist) {
|
||||
return processSet(chunk, get, set);
|
||||
}
|
||||
int bx = chunk.getX() << 4;
|
||||
int bz = chunk.getZ() << 4;
|
||||
int tx = bx + 15;
|
||||
int tz = bz + 15;
|
||||
for (Region region : regions) {
|
||||
BlockVector3 regMin = region.getMinimumPoint();
|
||||
BlockVector3 regMax = region.getMaximumPoint();
|
||||
if (tx >= regMin.getX() && bx <= regMax.getX() && tz >= regMin.getZ() && bz <= regMax.getZ()) {
|
||||
return region.processSet(chunk, get, set, true);
|
||||
}
|
||||
}
|
||||
return set; // default return set as no "blacklist" regions contained the chunk
|
||||
}
|
||||
|
||||
public List<Region> getRegions() {
|
||||
|
Reference in New Issue
Block a user