From 30f7f002d58db93796cf826454ed9f1f9d8d71f4 Mon Sep 17 00:00:00 2001 From: dfsek Date: Sun, 19 Dec 2021 13:48:51 -0700 Subject: [PATCH] warn at out-of-bounds access rather than crash on Bukkit. --- .../dfsek/terra/bukkit/TerraBukkitPlugin.java | 2 +- .../BukkitChunkGeneratorWrapper.java | 8 ++- .../terra/bukkit/world/BukkitProtoWorld.java | 51 +++++++++++++++---- .../world/block/data/BukkitBlockState.java | 2 +- 4 files changed, 49 insertions(+), 14 deletions(-) diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java index 55818a4aa..5ac84f324 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java @@ -208,6 +208,6 @@ public class TerraBukkitPlugin extends JavaPlugin { ConfigPack pack = platform.getConfigRegistry().get(id).orElseThrow( () -> new IllegalArgumentException("No such config pack \"" + id + "\"")); return pack.getGeneratorProvider().newInstance(pack); - }), platform.getRawConfigRegistry().get(id).orElseThrow()); + }), platform.getRawConfigRegistry().get(id).orElseThrow(), platform.getWorldHandle().air()); } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java index 476d193bb..aba15a0fa 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/generator/BukkitChunkGeneratorWrapper.java @@ -17,6 +17,8 @@ package com.dfsek.terra.bukkit.generator; +import com.dfsek.terra.api.block.state.BlockState; + import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.generator.BiomeProvider; @@ -41,12 +43,14 @@ import com.dfsek.terra.bukkit.world.BukkitServerWorld; public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGenerator implements GeneratorWrapper { private final ChunkGenerator delegate; private final ConfigPack pack; + private final BlockState air; private World world; private ServerWorld terraWorld; - public BukkitChunkGeneratorWrapper(ChunkGenerator delegate, ConfigPack pack) { + public BukkitChunkGeneratorWrapper(ChunkGenerator delegate, ConfigPack pack, BlockState air) { this.delegate = delegate; this.pack = pack; + this.air = air; } @Override @@ -71,7 +75,7 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener @Override public void populate(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull LimitedRegion limitedRegion) { - generationStage.populate(new BukkitProtoWorld(limitedRegion)); + generationStage.populate(new BukkitProtoWorld(limitedRegion, air)); } }) .collect(Collectors.toList()); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java index 973b2674e..ebff44019 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/BukkitProtoWorld.java @@ -18,11 +18,22 @@ import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; import com.dfsek.terra.bukkit.world.block.state.BukkitBlockEntity; import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Optional; +import java.util.function.Supplier; + public class BukkitProtoWorld implements ProtoWorld { private final LimitedRegion delegate; + private final BlockState air; + private static final Logger LOGGER = LoggerFactory.getLogger(BukkitProtoWorld.class); - public BukkitProtoWorld(LimitedRegion delegate) { this.delegate = delegate; } + public BukkitProtoWorld(LimitedRegion delegate, BlockState air) { + this.delegate = delegate; + this.air = air; + } @Override public LimitedRegion getHandle() { @@ -31,10 +42,12 @@ public class BukkitProtoWorld implements ProtoWorld { @Override public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { - delegate.setBlockData(x, y, z, BukkitAdapter.adapt(data)); - if(physics) { - delegate.scheduleBlockUpdate(x, y, z); - } + access(x, y, z, () -> { + delegate.setBlockData(x, y, z, BukkitAdapter.adapt(data)); + if(physics) { + delegate.scheduleBlockUpdate(x, y, z); + } + }); } @Override @@ -49,12 +62,12 @@ public class BukkitProtoWorld implements ProtoWorld { @Override public BlockState getBlockState(int x, int y, int z) { - return BukkitBlockState.newInstance(delegate.getBlockData(x, y, z)); + return access(x, y, z, () -> BukkitBlockState.newInstance(delegate.getBlockData(x, y, z))).orElse(air); } @Override public BlockEntity getBlockEntity(int x, int y, int z) { - return BukkitBlockEntity.newInstance(delegate.getBlockState(x, y, z)); + return access(x, y, z, () -> BukkitBlockEntity.newInstance(delegate.getBlockState(x, y, z))).orElse(null); } @Override @@ -64,9 +77,8 @@ public class BukkitProtoWorld implements ProtoWorld { @Override public Entity spawnEntity(double x, double y, double z, EntityType entityType) { - return new BukkitEntity( - delegate.spawnEntity(new Location(delegate.getWorld(), x, y, z), ((BukkitEntityType) entityType).getHandle())); - + return access((int) x, (int) y, (int) z, () -> new BukkitEntity( + delegate.spawnEntity(new Location(delegate.getWorld(), x, y, z), ((BukkitEntityType) entityType).getHandle()))).orElse(null); } @Override @@ -98,4 +110,23 @@ public class BukkitProtoWorld implements ProtoWorld { public ServerWorld getWorld() { return new BukkitServerWorld(delegate.getWorld()); } + + private Optional access(int x, int y, int z, Supplier action) { + if(delegate.isInRegion(x, y, z)) { + return Optional.of(action.get()); + } else { + LOGGER.warn("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z, + delegate.getCenterChunkX(), delegate.getCenterChunkZ()); + return Optional.empty(); + } + } + + private void access(int x, int y, int z, Runnable action) { + if(delegate.isInRegion(x, y, z)) { + action.run(); + } else { + LOGGER.warn("Detected world access at coordinates out of bounds: ({}, {}, {}) accessed for region [{}, {}]", x, y, z, + delegate.getCenterChunkX(), delegate.getCenterChunkZ()); + } + } } diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java index 176e8bf21..b4cf0b988 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/world/block/data/BukkitBlockState.java @@ -32,7 +32,7 @@ public class BukkitBlockState implements BlockState { this.delegate = delegate; } - public static BukkitBlockState newInstance(org.bukkit.block.data.BlockData bukkitData) { + public static BlockState newInstance(org.bukkit.block.data.BlockData bukkitData) { return new BukkitBlockState(bukkitData); }