From e449910af5855b69b04024234272a9176ead7eea Mon Sep 17 00:00:00 2001 From: Jordan Date: Mon, 12 Jun 2023 10:27:07 +0100 Subject: [PATCH] feat: prevent edits outside +/- 30,000,000 blocks (#2285) * feat: prevent edits outside +/- 30,000,000 blocks * Remove import --- .../sk89q/worldedit/bukkit/BukkitWorld.java | 52 +++++++++++++++++++ .../fastasyncworldedit/core/FaweCache.java | 5 ++ .../core/configuration/Settings.java | 6 +++ .../internal/exception/FaweException.java | 1 + .../SingleThreadQueueExtent.java | 4 +- .../preloader/AsyncPreloader.java | 8 +++ .../src/main/resources/lang/strings.json | 1 + 7 files changed, 76 insertions(+), 1 deletion(-) diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 769bcbd03..7afe0aaff 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -21,6 +21,8 @@ package com.sk89q.worldedit.bukkit; import com.fastasyncworldedit.bukkit.util.WorldUnloadedException; 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.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; @@ -242,6 +244,9 @@ public class BukkitWorld extends AbstractWorld { @Override public int getBlockLightLevel(BlockVector3 pt) { + //FAWE start - safe edit region + testCoords(pt); + //FAWE end return getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).getLightLevel(); } @@ -265,6 +270,9 @@ public class BukkitWorld extends AbstractWorld { @Override public boolean clearContainerBlockContents(BlockVector3 pt) { checkNotNull(pt); + //FAWE start - safe edit region + testCoords(pt); + //FAWE end BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); if (adapter != null) { try { @@ -337,6 +345,7 @@ public class BukkitWorld extends AbstractWorld { @Override public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 pt) { //FAWE start - allow tree commands to be undone and obey region restrictions + testCoords(pt); return WorldEditPlugin.getInstance().getBukkitImplAdapter().generateTree(type, editSession, pt, getWorld()); //FAWE end } @@ -349,6 +358,9 @@ public class BukkitWorld extends AbstractWorld { @Override public void checkLoadedChunk(BlockVector3 pt) { + //FAWE start - safe edit region + testCoords(pt); + //FAWE end World world = getWorld(); //FAWE start int X = pt.getBlockX() >> 4; @@ -480,6 +492,9 @@ public class BukkitWorld extends AbstractWorld { @Override public void simulateBlockMine(BlockVector3 pt) { + //FAWE start - safe edit region + testCoords(pt); + //FAWE end getWorld().getBlockAt(pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()).breakNaturally(); } @@ -493,6 +508,9 @@ public class BukkitWorld extends AbstractWorld { @Override 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(); if (adapter != null) { return adapter.canPlaceAt(getWorld(), position, blockState); @@ -505,6 +523,9 @@ public class BukkitWorld extends AbstractWorld { @Override public com.sk89q.worldedit.world.block.BlockState getBlock(BlockVector3 position) { + //FAWE start - safe edit region + testCoords(position); + //FAWE end BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); if (adapter != null) { try { @@ -526,6 +547,9 @@ public class BukkitWorld extends AbstractWorld { @Override public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) { + //FAWE start - safe edit region + testCoords(position); + //FAWE end if (worldNativeAccess != null) { try { return worldNativeAccess.setBlock(position, block, sideEffects); @@ -545,6 +569,9 @@ public class BukkitWorld extends AbstractWorld { @Override public BaseBlock getFullBlock(BlockVector3 position) { + //FAWE start - safe edit region + testCoords(position); + //FAWE end BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); if (adapter != null) { 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 public Set applySideEffects( BlockVector3 position, com.sk89q.worldedit.world.block.BlockState previousType, SideEffectSet sideEffectSet ) { + //FAWE start - safe edit region + testCoords(position); + //FAWE end if (worldNativeAccess != null) { worldNativeAccess.applySideEffects(position, previousType, sideEffectSet); return Sets.intersection( @@ -571,6 +612,9 @@ public class BukkitWorld extends AbstractWorld { @Override public boolean useItem(BlockVector3 position, BaseItem item, Direction face) { + //FAWE start - safe edit region + testCoords(position); + //FAWE end BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter(); if (adapter != null) { return adapter.simulateItemUse(getWorld(), position, item, face); @@ -588,6 +632,9 @@ public class BukkitWorld extends AbstractWorld { @SuppressWarnings("deprecation") @Override public BiomeType getBiome(BlockVector3 position) { + //FAWE start - safe edit region + testCoords(position); + //FAWE end if (HAS_3D_BIOMES) { return BukkitAdapter.adapt(getWorld().getBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ())); } else { @@ -598,6 +645,9 @@ public class BukkitWorld extends AbstractWorld { @SuppressWarnings("deprecation") @Override public boolean setBiome(BlockVector3 position, BiomeType biome) { + //FAWE start - safe edit region + testCoords(position); + //FAWE end if (HAS_3D_BIOMES) { getWorld().setBiome(position.getBlockX(), position.getBlockY(), position.getBlockZ(), BukkitAdapter.adapt(biome)); } else { @@ -626,11 +676,13 @@ public class BukkitWorld extends AbstractWorld { @Override public void refreshChunk(int chunkX, int chunkZ) { + testCoords(BlockVector3.at(chunkX << 16, 0, chunkZ << 16)); getWorld().refreshChunk(chunkX, chunkZ); } @Override public IChunkGet get(int chunkX, int chunkZ) { + testCoords(BlockVector3.at(chunkX << 16, 0, chunkZ << 16)); return WorldEditPlugin.getInstance().getBukkitImplAdapter().get(getWorldChecked(), chunkX, chunkZ); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java index a6d035155..b66b4ef06 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java @@ -182,6 +182,11 @@ public enum FaweCache implements Trimable { "fawe.cancel.reason.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( Caption.of("fawe.cancel.reason.max" + ".checks"), Type.MAX_CHECKS diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java index 5eba1f01f..90ed792fa 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/configuration/Settings.java @@ -312,6 +312,12 @@ public class Settings extends Config { " - Any blacklist regions are likely to override any internal allowed regions." }) 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; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/exception/FaweException.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/exception/FaweException.java index ff1d7913d..f59de907c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/exception/FaweException.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/internal/exception/FaweException.java @@ -80,6 +80,7 @@ public class FaweException extends RuntimeException { MANUAL, NO_REGION, OUTSIDE_REGION, + OUTSIDE_SAFE_REGION, MAX_CHECKS, MAX_CHANGES, LOW_MEMORY, diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java index a41d8786b..59427c8ef 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java @@ -293,7 +293,9 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen if (pair == lastPair) { 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; lastChunk = NullChunk.getInstance(); return NullChunk.getInstance(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/preloader/AsyncPreloader.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/preloader/AsyncPreloader.java index 29e82790d..7a74ed8ac 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/preloader/AsyncPreloader.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/preloader/AsyncPreloader.java @@ -110,6 +110,14 @@ public class AsyncPreloader implements Preloader, Runnable { Iterator chunksIter = chunks.iterator(); while (chunksIter.hasNext() && pair.getValue() == chunks) { // Ensure the queued load is still valid 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); } } diff --git a/worldedit-core/src/main/resources/lang/strings.json b/worldedit-core/src/main/resources/lang/strings.json index ac3c2d3ac..46445a2d9 100644 --- a/worldedit-core/src/main/resources/lang/strings.json +++ b/worldedit-core/src/main/resources/lang/strings.json @@ -149,6 +149,7 @@ "fawe.cancel.reason.max.iterations": "Max iterations", "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.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.reason": "No allowed region: {0}", "fawe.cancel.reason.no.region.plot.noworldeditflag": "Plot flag NoWorldeditFlag set",