warn at out-of-bounds access rather than crash on Bukkit.

This commit is contained in:
dfsek
2021-12-19 13:48:51 -07:00
parent 77d341ebab
commit 30f7f002d5
4 changed files with 49 additions and 14 deletions
@@ -208,6 +208,6 @@ public class TerraBukkitPlugin extends JavaPlugin {
ConfigPack pack = platform.getConfigRegistry().get(id).orElseThrow( ConfigPack pack = platform.getConfigRegistry().get(id).orElseThrow(
() -> new IllegalArgumentException("No such config pack \"" + id + "\"")); () -> new IllegalArgumentException("No such config pack \"" + id + "\""));
return pack.getGeneratorProvider().newInstance(pack); return pack.getGeneratorProvider().newInstance(pack);
}), platform.getRawConfigRegistry().get(id).orElseThrow()); }), platform.getRawConfigRegistry().get(id).orElseThrow(), platform.getWorldHandle().air());
} }
} }
@@ -17,6 +17,8 @@
package com.dfsek.terra.bukkit.generator; package com.dfsek.terra.bukkit.generator;
import com.dfsek.terra.api.block.state.BlockState;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.generator.BiomeProvider; 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 { public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGenerator implements GeneratorWrapper {
private final ChunkGenerator delegate; private final ChunkGenerator delegate;
private final ConfigPack pack; private final ConfigPack pack;
private final BlockState air;
private World world; private World world;
private ServerWorld terraWorld; private ServerWorld terraWorld;
public BukkitChunkGeneratorWrapper(ChunkGenerator delegate, ConfigPack pack) { public BukkitChunkGeneratorWrapper(ChunkGenerator delegate, ConfigPack pack, BlockState air) {
this.delegate = delegate; this.delegate = delegate;
this.pack = pack; this.pack = pack;
this.air = air;
} }
@Override @Override
@@ -71,7 +75,7 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener
@Override @Override
public void populate(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, public void populate(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z,
@NotNull LimitedRegion limitedRegion) { @NotNull LimitedRegion limitedRegion) {
generationStage.populate(new BukkitProtoWorld(limitedRegion)); generationStage.populate(new BukkitProtoWorld(limitedRegion, air));
} }
}) })
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -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.block.state.BukkitBlockEntity;
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; 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 { public class BukkitProtoWorld implements ProtoWorld {
private final LimitedRegion delegate; 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 @Override
public LimitedRegion getHandle() { public LimitedRegion getHandle() {
@@ -31,10 +42,12 @@ public class BukkitProtoWorld implements ProtoWorld {
@Override @Override
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) { public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
delegate.setBlockData(x, y, z, BukkitAdapter.adapt(data)); access(x, y, z, () -> {
if(physics) { delegate.setBlockData(x, y, z, BukkitAdapter.adapt(data));
delegate.scheduleBlockUpdate(x, y, z); if(physics) {
} delegate.scheduleBlockUpdate(x, y, z);
}
});
} }
@Override @Override
@@ -49,12 +62,12 @@ public class BukkitProtoWorld implements ProtoWorld {
@Override @Override
public BlockState getBlockState(int x, int y, int z) { 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 @Override
public BlockEntity getBlockEntity(int x, int y, int z) { 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 @Override
@@ -64,9 +77,8 @@ public class BukkitProtoWorld implements ProtoWorld {
@Override @Override
public Entity spawnEntity(double x, double y, double z, EntityType entityType) { public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
return new BukkitEntity( return access((int) x, (int) y, (int) z, () -> new BukkitEntity(
delegate.spawnEntity(new Location(delegate.getWorld(), x, y, z), ((BukkitEntityType) entityType).getHandle())); delegate.spawnEntity(new Location(delegate.getWorld(), x, y, z), ((BukkitEntityType) entityType).getHandle()))).orElse(null);
} }
@Override @Override
@@ -98,4 +110,23 @@ public class BukkitProtoWorld implements ProtoWorld {
public ServerWorld getWorld() { public ServerWorld getWorld() {
return new BukkitServerWorld(delegate.getWorld()); return new BukkitServerWorld(delegate.getWorld());
} }
private <T> Optional<T> access(int x, int y, int z, Supplier<T> 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());
}
}
} }
@@ -32,7 +32,7 @@ public class BukkitBlockState implements BlockState {
this.delegate = delegate; 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); return new BukkitBlockState(bukkitData);
} }