Merge branch 'IntellectualSites:main' into main

This commit is contained in:
Telesphoreo 2023-06-14 15:46:43 -05:00 committed by GitHub
commit c609aa97ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 233 additions and 154 deletions

View File

@ -8,7 +8,7 @@ body:
value: | value: |
Thanks for taking the time to fill out this bug report for FastAsyncWorldEdit! Fill out the following form to your best ability to help us fix the problem. Thanks for taking the time to fill out this bug report for FastAsyncWorldEdit! Fill out the following form to your best ability to help us fix the problem.
Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/intellectualsites) or [the wiki](https://intellectualsites.github.io/fastasyncworldedit-documentation/). Only use this if you're absolutely sure that you found a bug and can reproduce it. For anything else, use: [our Discord server](https://discord.gg/intellectualsites) or [the wiki](https://intellectualsites.github.io/fastasyncworldedit-documentation/).
Do NOT use the public issue tracker to report security vulnerabilities! They are disclosed using [this](https://forms.gle/btgdRn9yhGtzEiGW8) form! Do NOT use the public issue tracker to report security vulnerabilities! They are disclosed using [this](https://github.com/IntellectualSites/FastAsyncWorldEdit/security/policy) GitHub form!
- type: dropdown - type: dropdown
attributes: attributes:

View File

@ -34,7 +34,7 @@ logger.lifecycle("""
******************************************* *******************************************
""") """)
var rootVersion by extra("2.6.3") var rootVersion by extra("2.6.4")
var snapshot by extra("SNAPSHOT") var snapshot by extra("SNAPSHOT")
var revision: String by extra("") var revision: String by extra("")
var buildNumber by extra("") var buildNumber by extra("")

View File

@ -202,8 +202,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
try { try {
// Non-Paper // Non-Paper
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField("entityManager"); SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "P"));
LEVEL_CHUNK_ENTITIES.setAccessible(true); SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
} catch (NoSuchFieldException ignored) { } catch (NoSuchFieldException ignored) {
} }
POST_CHUNK_REWRITE = chunkRewrite; POST_CHUNK_REWRITE = chunkRewrite;

View File

@ -199,8 +199,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
try { try {
// Non-Paper // Non-Paper
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField("entityManager"); SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "P"));
LEVEL_CHUNK_ENTITIES.setAccessible(true); SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
} catch (NoSuchFieldException ignored) { } catch (NoSuchFieldException ignored) {
} }
POST_CHUNK_REWRITE = chunkRewrite; POST_CHUNK_REWRITE = chunkRewrite;

View File

@ -204,8 +204,8 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
} }
try { try {
// Non-Paper // Non-Paper
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField("entityManager"); SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "L"));
LEVEL_CHUNK_ENTITIES.setAccessible(true); SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
} catch (NoSuchFieldException ignored) { } catch (NoSuchFieldException ignored) {
} }
POST_CHUNK_REWRITE = chunkRewrite; POST_CHUNK_REWRITE = chunkRewrite;

View File

@ -182,8 +182,8 @@ public final class PaperweightAdapter implements BukkitImplAdapter<net.minecraft
CraftServer.class.cast(Bukkit.getServer()); CraftServer.class.cast(Bukkit.getServer());
int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion(); int dataVersion = CraftMagicNumbers.INSTANCE.getDataVersion();
if (dataVersion != 3463) { if (dataVersion != 3463 && dataVersion != 3465) {
throw new UnsupportedClassVersionError("Not 1.20!"); throw new UnsupportedClassVersionError("Not 1.20(.1)!");
} }
serverWorldsField = CraftServer.class.getDeclaredField("worlds"); serverWorldsField = CraftServer.class.getDeclaredField("worlds");

View File

@ -211,7 +211,7 @@ public final class PaperweightPlatformAdapter extends NMSAdapter {
try { try {
// Non-Paper // Non-Paper
SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "M")); SERVER_LEVEL_ENTITY_MANAGER = ServerLevel.class.getDeclaredField(Refraction.pickName("entityManager", "M"));
LEVEL_CHUNK_ENTITIES.setAccessible(true); SERVER_LEVEL_ENTITY_MANAGER.setAccessible(true);
} catch (NoSuchFieldException ignored) { } catch (NoSuchFieldException ignored) {
} }
POST_CHUNK_REWRITE = chunkRewrite; POST_CHUNK_REWRITE = chunkRewrite;

View File

@ -2,9 +2,7 @@ package com.fastasyncworldedit.bukkit.regions;
import com.fastasyncworldedit.core.regions.FaweMask; import com.fastasyncworldedit.core.regions.FaweMask;
import com.palmergames.bukkit.towny.Towny; import com.palmergames.bukkit.towny.Towny;
import com.palmergames.bukkit.towny.TownyUniverse; import com.palmergames.bukkit.towny.TownyAPI;
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
import com.palmergames.bukkit.towny.object.PlayerCache;
import com.palmergames.bukkit.towny.object.Resident; import com.palmergames.bukkit.towny.object.Resident;
import com.palmergames.bukkit.towny.object.Town; import com.palmergames.bukkit.towny.object.Town;
import com.palmergames.bukkit.towny.object.TownBlock; import com.palmergames.bukkit.towny.object.TownBlock;
@ -36,31 +34,27 @@ public class TownyFeature extends BukkitMaskManager implements Listener {
if (block == null) { if (block == null) {
return false; return false;
} }
Resident resident; Resident resident = TownyAPI.getInstance().getResident(player);
try { if (resident == null) {
resident = TownyUniverse.getInstance().getResident(player.getName()); return false;
try { }
if (block.getResident().equals(resident)) { if (block.hasResident(resident) || block.hasTrustedResident(resident)) {
return true; return true;
} }
} catch (NotRegisteredException ignored) { Town town = block.getTownOrNull(); // Will not be null, because block is not null.
} if (town.isMayor(resident) || town.hasTrustedResident(resident)) {
Town town = block.getTown(); return true;
if (town.isMayor(resident)) { }
if (!town.hasResident(resident)) {
return false;
}
if (player.hasPermission("fawe.towny.*")) {
return true;
}
for (String rank : resident.getTownRanks()) {
if (player.hasPermission("fawe.towny." + rank)) {
return true; return true;
} }
if (!town.hasResident(resident)) {
return false;
}
if (player.hasPermission("fawe.towny.*")) {
return true;
}
for (String rank : resident.getTownRanks()) {
if (player.hasPermission("fawe.towny." + rank)) {
return true;
}
}
} catch (NotRegisteredException ignored) {
} }
return false; return false;
} }
@ -69,32 +63,23 @@ public class TownyFeature extends BukkitMaskManager implements Listener {
public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, MaskType type, boolean isWhitelist) { public FaweMask getMask(final com.sk89q.worldedit.entity.Player wePlayer, MaskType type, boolean isWhitelist) {
final Player player = BukkitAdapter.adapt(wePlayer); final Player player = BukkitAdapter.adapt(wePlayer);
final Location location = player.getLocation(); final Location location = player.getLocation();
try { final WorldCoord mycoord = WorldCoord.parseWorldCoord(location);
final PlayerCache cache = ((Towny) this.towny).getCache(player); if (mycoord.isWilderness()) {
final WorldCoord mycoord = cache.getLastTownBlock(); return null;
if (mycoord == null) { }
return null; final TownBlock myplot = mycoord.getTownBlockOrNull(); // Will not be null, because of the isWilderness() test above.
} boolean isMember = isAllowed(player, myplot);
final TownBlock myplot = mycoord.getTownBlock(); if (isMember) {
if (myplot == null) { final Location loc1 = mycoord.getLowerMostCornerLocation();
return null; final Location loc2 = mycoord.getUpperMostCornerLocation();
} final BlockVector3 pos1 = BlockVector3.at(loc1.getX(), loc1.getY(), loc1.getZ());
boolean isMember = isAllowed(player, myplot); final BlockVector3 pos2 = BlockVector3.at(loc2.getX(), loc2.getY(), loc2.getZ());
if (isMember) { return new FaweMask(new CuboidRegion(pos1, pos2)) {
final Chunk chunk = location.getChunk(); @Override
final BlockVector3 pos1 = BlockVector3 public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) {
.at(chunk.getX() * 16, 0, chunk.getZ() * 16); return isAllowed(BukkitAdapter.adapt(player), myplot);
final BlockVector3 pos2 = BlockVector3.at( }
chunk.getX() * 16 + 15, 156, chunk.getZ() * 16 };
+ 15);
return new FaweMask(new CuboidRegion(pos1, pos2)) {
@Override
public boolean isValid(com.sk89q.worldedit.entity.Player player, MaskType type) {
return isAllowed(BukkitAdapter.adapt(player), myplot);
}
};
}
} catch (Exception ignored) {
} }
return null; return null;
} }

View File

@ -21,6 +21,8 @@ package com.sk89q.worldedit.bukkit;
import com.fastasyncworldedit.bukkit.util.WorldUnloadedException; import com.fastasyncworldedit.bukkit.util.WorldUnloadedException;
import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.internal.exception.FaweException;
import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.IChunkGet;
import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket;
@ -242,6 +244,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public int getBlockLightLevel(BlockVector3 pt) { public int getBlockLightLevel(BlockVector3 pt) {
//FAWE start - safe edit region
testCoords(pt);
//FAWE end
return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel(); return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel();
} }
@ -265,6 +270,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public boolean clearContainerBlockContents(BlockVector3 pt) { public boolean clearContainerBlockContents(BlockVector3 pt) {
checkNotNull(pt); checkNotNull(pt);
//FAWE start - safe edit region
testCoords(pt);
//FAWE end
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) { if (adapter != null) {
try { try {
@ -337,6 +345,7 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 pt) { public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 pt) {
//FAWE start - allow tree commands to be undone and obey region restrictions //FAWE start - allow tree commands to be undone and obey region restrictions
testCoords(pt);
return WorldEditPlugin.getInstance().getBukkitImplAdapter().generateTree(type, editSession, pt, getWorld()); return WorldEditPlugin.getInstance().getBukkitImplAdapter().generateTree(type, editSession, pt, getWorld());
//FAWE end //FAWE end
} }
@ -349,6 +358,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public void checkLoadedChunk(BlockVector3 pt) { public void checkLoadedChunk(BlockVector3 pt) {
//FAWE start - safe edit region
testCoords(pt);
//FAWE end
World world = getWorld(); World world = getWorld();
//FAWE start //FAWE start
int X = pt.getBlockX() >> 4; int X = pt.getBlockX() >> 4;
@ -480,6 +492,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public void simulateBlockMine(BlockVector3 pt) { public void simulateBlockMine(BlockVector3 pt) {
//FAWE start - safe edit region
testCoords(pt);
//FAWE end
getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally(); getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally();
} }
@ -493,6 +508,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public boolean canPlaceAt(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState blockState) { public boolean canPlaceAt(BlockVector3 position, com.sk89q.worldedit.world.block.BlockState blockState) {
//FAWE start - safe edit region
testCoords(position);
//FAWE end
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) { if (adapter != null) {
return adapter.canPlaceAt(getWorld(), position, blockState); return adapter.canPlaceAt(getWorld(), position, blockState);
@ -505,6 +523,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public com.sk89q.worldedit.world.block.BlockState getBlock(BlockVector3 position) { public com.sk89q.worldedit.world.block.BlockState getBlock(BlockVector3 position) {
//FAWE start - safe edit region
testCoords(position);
//FAWE end
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) { if (adapter != null) {
try { try {
@ -526,6 +547,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) { public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) {
//FAWE start - safe edit region
testCoords(position);
//FAWE end
if (worldNativeAccess != null) { if (worldNativeAccess != null) {
try { try {
return worldNativeAccess.setBlock(position, block, sideEffects); return worldNativeAccess.setBlock(position, block, sideEffects);
@ -545,6 +569,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public BaseBlock getFullBlock(BlockVector3 position) { public BaseBlock getFullBlock(BlockVector3 position) {
//FAWE start - safe edit region
testCoords(position);
//FAWE end
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) { if (adapter != null) {
return adapter.getFullBlock(BukkitAdapter.adapt(getWorld(), position)); return adapter.getFullBlock(BukkitAdapter.adapt(getWorld(), position));
@ -553,11 +580,25 @@ public class BukkitWorld extends AbstractWorld {
} }
} }
private void testCoords(BlockVector3 position) throws FaweException {
if (!Settings.settings().REGION_RESTRICTIONS_OPTIONS.RESTRICT_TO_SAFE_RANGE) {
return;
}
int x = position.getX();
int z = position.getZ();
if (x > 30000000 || z > 30000000 || x < -30000000 || z < -30000000) {
throw FaweCache.OUTSIDE_SAFE_REGION;
}
}
@Override @Override
public Set<SideEffect> applySideEffects( public Set<SideEffect> applySideEffects(
BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType, BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType,
SideEffectSet sideEffectSet SideEffectSet sideEffectSet
) { ) {
//FAWE start - safe edit region
testCoords(position);
//FAWE end
if (worldNativeAccess != null) { if (worldNativeAccess != null) {
worldNativeAccess.applySideEffects(position, previousType, sideEffectSet); worldNativeAccess.applySideEffects(position, previousType, sideEffectSet);
return Sets.intersection( return Sets.intersection(
@ -571,6 +612,9 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { public boolean useItem(BlockVector3 position, BaseItem item, Direction face) {
//FAWE start - safe edit region
testCoords(position);
//FAWE end
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) { if (adapter != null) {
return adapter.simulateItemUse(getWorld(), position, item, face); return adapter.simulateItemUse(getWorld(), position, item, face);
@ -588,6 +632,9 @@ public class BukkitWorld extends AbstractWorld {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override @Override
public BiomeType getBiome(BlockVector3 position) { public BiomeType getBiome(BlockVector3 position) {
//FAWE start - safe edit region
testCoords(position);
//FAWE end
if (HAS_3D_BIOMES) { if (HAS_3D_BIOMES) {
return BukkitAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ())); return BukkitAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ()));
} else { } else {
@ -598,6 +645,9 @@ public class BukkitWorld extends AbstractWorld {
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@Override @Override
public boolean setBiome(BlockVector3 position, BiomeType biome) { public boolean setBiome(BlockVector3 position, BiomeType biome) {
//FAWE start - safe edit region
testCoords(position);
//FAWE end
if (HAS_3D_BIOMES) { if (HAS_3D_BIOMES) {
getWorld().setBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ(), BukkitAdapter.adapt(biome)); getWorld().setBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ(), BukkitAdapter.adapt(biome));
} else { } else {
@ -626,11 +676,13 @@ public class BukkitWorld extends AbstractWorld {
@Override @Override
public void refreshChunk(int chunkX, int chunkZ) { public void refreshChunk(int chunkX, int chunkZ) {
testCoords(BlockVector3.at(chunkX << 4, 0, chunkZ << 4));
getWorld().refreshChunk(chunkX, chunkZ); getWorld().refreshChunk(chunkX, chunkZ);
} }
@Override @Override
public IChunkGet get(int chunkX, int chunkZ) { public IChunkGet get(int chunkX, int chunkZ) {
testCoords(BlockVector3.at(chunkX << 4, 0, chunkZ << 4));
return WorldEditPlugin.getInstance().getBukkitImplAdapter().get(getWorldChecked(), chunkX, chunkZ); return WorldEditPlugin.getInstance().getBukkitImplAdapter().get(getWorldChecked(), chunkX, chunkZ);
} }

View File

@ -171,52 +171,68 @@ public enum FaweCache implements Trimable {
public static final FaweBlockBagException BLOCK_BAG = new FaweBlockBagException(); public static final FaweBlockBagException BLOCK_BAG = new FaweBlockBagException();
public static final FaweException MANUAL = new FaweException( public static final FaweException MANUAL = new FaweException(
Caption.of("fawe.cancel.reason.manual"), Caption.of("fawe.cancel.reason.manual"),
Type.MANUAL Type.MANUAL,
false
); );
public static final FaweException NO_REGION = new FaweException( public static final FaweException NO_REGION = new FaweException(
Caption.of("fawe.cancel.reason.no.region"), Caption.of("fawe.cancel.reason.no.region"),
Type.NO_REGION Type.NO_REGION,
false
); );
public static final FaweException OUTSIDE_REGION = new FaweException( public static final FaweException OUTSIDE_REGION = new FaweException(
Caption.of( Caption.of(
"fawe.cancel.reason.outside.region"), "fawe.cancel.reason.outside.region"),
Type.OUTSIDE_REGION,
true
);
public static final FaweException OUTSIDE_SAFE_REGION = new FaweException(
Caption.of(
"fawe.cancel.reason.outside.safe.region"),
Type.OUTSIDE_REGION Type.OUTSIDE_REGION
); );
public static final FaweException MAX_CHECKS = new FaweException( public static final FaweException MAX_CHECKS = new FaweException(
Caption.of("fawe.cancel.reason.max" + ".checks"), Caption.of("fawe.cancel.reason.max" + ".checks"),
Type.MAX_CHECKS Type.MAX_CHECKS,
true
); );
public static final FaweException MAX_CHANGES = new FaweException( public static final FaweException MAX_CHANGES = new FaweException(
Caption.of("fawe.cancel.reason.max" + ".changes"), Caption.of("fawe.cancel.reason.max" + ".changes"),
Type.MAX_CHANGES Type.MAX_CHANGES,
false
); );
public static final FaweException LOW_MEMORY = new FaweException( public static final FaweException LOW_MEMORY = new FaweException(
Caption.of("fawe.cancel.reason.low" + ".memory"), Caption.of("fawe.cancel.reason.low" + ".memory"),
Type.LOW_MEMORY Type.LOW_MEMORY,
false
); );
public static final FaweException MAX_ENTITIES = new FaweException( public static final FaweException MAX_ENTITIES = new FaweException(
Caption.of( Caption.of(
"fawe.cancel.reason.max.entities"), "fawe.cancel.reason.max.entities"),
Type.MAX_ENTITIES Type.MAX_ENTITIES,
true
); );
public static final FaweException MAX_TILES = new FaweException(Caption.of( public static final FaweException MAX_TILES = new FaweException(Caption.of(
"fawe.cancel.reason.max.tiles", "fawe.cancel.reason.max.tiles",
Type.MAX_TILES Type.MAX_TILES,
true
)); ));
public static final FaweException MAX_ITERATIONS = new FaweException( public static final FaweException MAX_ITERATIONS = new FaweException(
Caption.of( Caption.of(
"fawe.cancel.reason.max.iterations"), "fawe.cancel.reason.max.iterations"),
Type.MAX_ITERATIONS Type.MAX_ITERATIONS,
true
); );
public static final FaweException PLAYER_ONLY = new FaweException( public static final FaweException PLAYER_ONLY = new FaweException(
Caption.of( Caption.of(
"fawe.cancel.reason.player-only"), "fawe.cancel.reason.player-only"),
Type.PLAYER_ONLY Type.PLAYER_ONLY,
false
); );
public static final FaweException ACTOR_REQUIRED = new FaweException( public static final FaweException ACTOR_REQUIRED = new FaweException(
Caption.of( Caption.of(
"fawe.cancel.reason.actor-required"), "fawe.cancel.reason.actor-required"),
Type.ACTOR_REQUIRED Type.ACTOR_REQUIRED,
false
); );
/* /*

View File

@ -312,6 +312,12 @@ public class Settings extends Config {
" - Any blacklist regions are likely to override any internal allowed regions." " - Any blacklist regions are likely to override any internal allowed regions."
}) })
public boolean WORLDGUARD_REGION_BLACKLIST = false; public boolean WORLDGUARD_REGION_BLACKLIST = false;
@Comment({
"Restrict all edits to within the safe chunk limits of +/- 30 million blocks",
" - Edits outside this range may induce crashing",
" - Forcefully prevents any edit outside this range"
})
public boolean RESTRICT_TO_SAFE_RANGE = true;
} }

View File

@ -20,6 +20,7 @@ import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Countable; import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -34,19 +35,46 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
public class LimitExtent extends AbstractDelegateExtent { public class LimitExtent extends AbstractDelegateExtent {
private final FaweLimit limit; private final FaweLimit limit;
private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length];
private final Consumer<Component> onErrorMessage;
/** /**
* Create a new instance. * Create a new instance.
* *
* @param extent the extent * @param extent the extent
* @param limit the limit
*/ */
public LimitExtent(Extent extent, FaweLimit limit) { public LimitExtent(Extent extent, FaweLimit limit) {
this(extent, limit, c -> {
});
}
/**
* Create a new instance.
*
* @param extent the extent
* @param limit the limit
* @param onErrorMessage consumer to handle a component generated by exceptions
*/
public LimitExtent(Extent extent, FaweLimit limit, Consumer<Component> onErrorMessage) {
super(extent); super(extent);
this.limit = limit; this.limit = limit;
this.onErrorMessage = onErrorMessage;
}
private void handleException(FaweException e) {
if (e.ignorable() || !limit.MAX_FAILS()) {
throw e;
}
if (!faweExceptionReasonsUsed[e.getType().ordinal()]) {
faweExceptionReasonsUsed[e.getType().ordinal()] = true;
onErrorMessage.accept(e.getComponent());
}
} }
@Override @Override
@ -55,9 +83,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getEntities(region); return super.getEntities(region);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return Collections.emptyList(); return Collections.emptyList();
} }
} }
@ -68,9 +94,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getEntities(); return super.getEntities();
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return Collections.emptyList(); return Collections.emptyList();
} }
} }
@ -83,9 +107,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.createEntity(location, entity); return super.createEntity(location, entity);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return null; return null;
} }
} }
@ -98,9 +120,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.createEntity(location, entity, uuid); return super.createEntity(location, entity, uuid);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return null; return null;
} }
} }
@ -112,9 +132,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
super.removeEntity(x, y, z, uuid); super.removeEntity(x, y, z, uuid);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
} }
} }
@ -124,9 +142,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.regenerateChunk(x, z, type, seed); return super.regenerateChunk(x, z, type, seed);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return false; return false;
} }
} }
@ -137,9 +153,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getHighestTerrainBlock(x, z, minY, maxY); return super.getHighestTerrainBlock(x, z, minY, maxY);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return minY; return minY;
} }
} }
@ -150,9 +164,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getHighestTerrainBlock(x, z, minY, maxY, filter); return super.getHighestTerrainBlock(x, z, minY, maxY, filter);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return minY; return minY;
} }
} }
@ -163,9 +175,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getNearestSurfaceLayer(x, z, y, minY, maxY); return super.getNearestSurfaceLayer(x, z, y, minY, maxY);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return minY; return minY;
} }
} }
@ -176,9 +186,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir); return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return minY; return minY;
} }
} }
@ -189,9 +197,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY); return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return minY; return minY;
} }
} }
@ -202,9 +208,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax); return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return minY; return minY;
} }
} }
@ -215,9 +219,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask); return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return minY; return minY;
} }
} }
@ -237,9 +239,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir); return super.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return minY; return minY;
} }
} }
@ -386,9 +386,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
filter.applyBlock(block.init(pos)); filter.applyBlock(block.init(pos));
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
} }
} }
return filter; return filter;
@ -404,9 +402,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getBlock(position); return super.getBlock(position);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return BlockTypes.AIR.getDefaultState(); return BlockTypes.AIR.getDefaultState();
} }
} }
@ -417,9 +413,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getBlock(x, y, z); return super.getBlock(x, y, z);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return BlockTypes.AIR.getDefaultState(); return BlockTypes.AIR.getDefaultState();
} }
} }
@ -430,9 +424,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getFullBlock(position); return super.getFullBlock(position);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return BlockTypes.AIR.getDefaultState().toBaseBlock(); return BlockTypes.AIR.getDefaultState().toBaseBlock();
} }
} }
@ -443,9 +435,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getFullBlock(x, y, z); return super.getFullBlock(x, y, z);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return BlockTypes.AIR.getDefaultState().toBaseBlock(); return BlockTypes.AIR.getDefaultState().toBaseBlock();
} }
} }
@ -456,9 +446,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getBiome(position); return super.getBiome(position);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return BiomeTypes.FOREST; return BiomeTypes.FOREST;
} }
} }
@ -469,9 +457,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.getBiomeType(x, y, z); return super.getBiomeType(x, y, z);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return BiomeTypes.FOREST; return BiomeTypes.FOREST;
} }
} }
@ -486,9 +472,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.setBlock(position, block); return super.setBlock(position, block);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return false; return false;
} }
} }
@ -502,9 +486,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.setBlock(x, y, z, block); return super.setBlock(x, y, z, block);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return false; return false;
} }
} }
@ -516,9 +498,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.setTile(x, y, z, tile); return super.setTile(x, y, z, tile);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return false; return false;
} }
} }
@ -529,9 +509,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.setBiome(position, biome); return super.setBiome(position, biome);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return false; return false;
} }
} }
@ -542,9 +520,7 @@ public class LimitExtent extends AbstractDelegateExtent {
try { try {
return super.setBiome(x, y, z, biome); return super.setBiome(x, y, z, biome);
} catch (FaweException e) { } catch (FaweException e) {
if (e.getType() == FaweException.Type.MANUAL || !limit.MAX_FAILS()) { handleException(e);
throw e;
}
return false; return false;
} }
} }

View File

@ -14,6 +14,7 @@ public class FaweException extends RuntimeException {
private final Component message; private final Component message;
private final Type type; private final Type type;
private final boolean ignorable;
/** /**
* New instance. Defaults to {@link FaweException.Type#OTHER}. * New instance. Defaults to {@link FaweException.Type#OTHER}.
@ -33,8 +34,19 @@ public class FaweException extends RuntimeException {
* New instance of a given {@link FaweException.Type} * New instance of a given {@link FaweException.Type}
*/ */
public FaweException(Component reason, Type type) { public FaweException(Component reason, Type type) {
this(reason, type, false);
}
/**
* New instance of a given {@link FaweException.Type}
*
* @param ignorable if an edit can continue if this exception is caught, e.g. by {@link com.fastasyncworldedit.core.extent.LimitExtent}
* @since TODO
*/
public FaweException(Component reason, Type type, boolean ignorable) {
this.message = reason; this.message = reason;
this.type = type; this.type = type;
this.ignorable = ignorable;
} }
@Override @Override
@ -55,6 +67,15 @@ public class FaweException extends RuntimeException {
return type; return type;
} }
/**
* If an edit can continue if this exception is caught, e.g. by {@link com.fastasyncworldedit.core.extent.LimitExtent}
*
* @since TODO
*/
public boolean ignorable() {
return ignorable;
}
public static FaweException get(Throwable e) { public static FaweException get(Throwable e) {
if (e instanceof FaweException) { if (e instanceof FaweException) {
return (FaweException) e; return (FaweException) e;
@ -80,6 +101,7 @@ public class FaweException extends RuntimeException {
MANUAL, MANUAL,
NO_REGION, NO_REGION,
OUTSIDE_REGION, OUTSIDE_REGION,
OUTSIDE_SAFE_REGION,
MAX_CHECKS, MAX_CHECKS,
MAX_CHANGES, MAX_CHANGES,
LOW_MEMORY, LOW_MEMORY,

View File

@ -293,7 +293,9 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
if (pair == lastPair) { if (pair == lastPair) {
return lastChunk; return lastChunk;
} }
if (!processGet(x, z)) { if (!processGet(x, z) || (Settings.settings().REGION_RESTRICTIONS_OPTIONS.RESTRICT_TO_SAFE_RANGE
// if any chunk coord is outside 30 million blocks
&& (x > 1875000 || z > 1875000 || x < -1875000 || z < -1875000))) {
lastPair = pair; lastPair = pair;
lastChunk = NullChunk.getInstance(); lastChunk = NullChunk.getInstance();
return NullChunk.getInstance(); return NullChunk.getInstance();

View File

@ -110,6 +110,14 @@ public class AsyncPreloader implements Preloader, Runnable {
Iterator<BlockVector2> chunksIter = chunks.iterator(); Iterator<BlockVector2> chunksIter = chunks.iterator();
while (chunksIter.hasNext() && pair.getValue() == chunks) { // Ensure the queued load is still valid while (chunksIter.hasNext() && pair.getValue() == chunks) { // Ensure the queued load is still valid
BlockVector2 chunk = chunksIter.next(); BlockVector2 chunk = chunksIter.next();
if (Settings.settings().REGION_RESTRICTIONS_OPTIONS.RESTRICT_TO_SAFE_RANGE) {
int x = chunk.getX();
int z = chunk.getZ();
// if any chunk coord is outside 30 million blocks
if (x > 1875000 || z > 1875000 || x < -1875000 || z < -1875000) {
continue;
}
}
queueLoad(world, chunk); queueLoad(world, chunk);
} }
} }

View File

@ -65,16 +65,19 @@ import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Identifiable; import com.sk89q.worldedit.util.Identifiable;
import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent; import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Consumer;
/** /**
* A builder-style factory for {@link EditSession EditSessions}. * A builder-style factory for {@link EditSession EditSessions}.
@ -590,10 +593,17 @@ public final class EditSessionBuilder {
} else { } else {
relighter = NullRelighter.INSTANCE; relighter = NullRelighter.INSTANCE;
} }
Consumer<Component> onErrorMessage;
if (getActor() != null) {
onErrorMessage = c -> getActor().print(Caption.of("fawe.error.occurred-continuing", c));
} else {
onErrorMessage = c -> {
};
}
if (limit != null && !limit.isUnlimited() && regionExtent != null) { if (limit != null && !limit.isUnlimited() && regionExtent != null) {
this.extent = new LimitExtent(regionExtent, limit); this.extent = new LimitExtent(regionExtent, limit, onErrorMessage);
} else if (limit != null && !limit.isUnlimited()) { } else if (limit != null && !limit.isUnlimited()) {
this.extent = new LimitExtent(this.extent, limit); this.extent = new LimitExtent(this.extent, limit, onErrorMessage);
} else if (regionExtent != null) { } else if (regionExtent != null) {
this.extent = regionExtent; this.extent = regionExtent;
} }

View File

@ -134,6 +134,7 @@
"fawe.error.limit.disallowed-block": "Your limit disallows use of block '{0}'", "fawe.error.limit.disallowed-block": "Your limit disallows use of block '{0}'",
"fawe.error.limit.disallowed-property": "Your limit disallows use of property '{0}'", "fawe.error.limit.disallowed-property": "Your limit disallows use of property '{0}'",
"fawe.error.region-mask-invalid": "Invalid region mask: {0}", "fawe.error.region-mask-invalid": "Invalid region mask: {0}",
"fawe.error.occurred-continuing": "Ignorable error occurred during edit: {0}",
"fawe.cancel.count": "Cancelled {0} edits.", "fawe.cancel.count": "Cancelled {0} edits.",
"fawe.cancel.reason.confirm": "Use //confirm to execute {0}", "fawe.cancel.reason.confirm": "Use //confirm to execute {0}",
"fawe.cancel.reason.confirm.region": "Your selection is large ({0} -> {1}, containing {3} blocks). Use //confirm to execute {2}", "fawe.cancel.reason.confirm.region": "Your selection is large ({0} -> {1}, containing {3} blocks). Use //confirm to execute {2}",
@ -149,6 +150,7 @@
"fawe.cancel.reason.max.iterations": "Max iterations", "fawe.cancel.reason.max.iterations": "Max iterations",
"fawe.cancel.reason.outside.level": "Outside world", "fawe.cancel.reason.outside.level": "Outside world",
"fawe.cancel.reason.outside.region": "Outside allowed region (bypass with /wea, or disable `region-restrictions` in config.yml)", "fawe.cancel.reason.outside.region": "Outside allowed region (bypass with /wea, or disable `region-restrictions` in config.yml)",
"fawe.cancel.reason.outside.safe.region": "Outside safe edit region of +/- 30,000,000 blocks.",
"fawe.cancel.reason.no.region": "No allowed region (bypass with /wea, or disable `region-restrictions` in config.yml)", "fawe.cancel.reason.no.region": "No allowed region (bypass with /wea, or disable `region-restrictions` in config.yml)",
"fawe.cancel.reason.no.region.reason": "No allowed region: {0}", "fawe.cancel.reason.no.region.reason": "No allowed region: {0}",
"fawe.cancel.reason.no.region.plot.noworldeditflag": "Plot flag NoWorldeditFlag set", "fawe.cancel.reason.no.region.plot.noworldeditflag": "Plot flag NoWorldeditFlag set",