feat: prevent edits outside +/- 30,000,000 blocks (#2285)

* feat: prevent edits outside +/- 30,000,000 blocks

* Remove import
This commit is contained in:
Jordan 2023-06-12 10:27:07 +01:00 committed by GitHub
parent ca4080eea7
commit e449910af5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 76 additions and 1 deletions

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 << 16, 0, chunkZ << 16));
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 << 16, 0, chunkZ << 16));
return WorldEditPlugin.getInstance().getBukkitImplAdapter().get(getWorldChecked(), chunkX, chunkZ); return WorldEditPlugin.getInstance().getBukkitImplAdapter().get(getWorldChecked(), chunkX, chunkZ);
} }

View File

@ -182,6 +182,11 @@ public enum FaweCache implements Trimable {
"fawe.cancel.reason.outside.region"), "fawe.cancel.reason.outside.region"),
Type.OUTSIDE_REGION Type.OUTSIDE_REGION
); );
public static final FaweException OUTSIDE_SAFE_REGION = new FaweException(
Caption.of(
"fawe.cancel.reason.outside.safe.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

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

@ -80,6 +80,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

@ -149,6 +149,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",