WIP - redesign to use new world gen API

Work still to do - handle island deletion (may not be supported) and
test with multiple players. Clean up config.
This commit is contained in:
tastybento 2022-11-25 17:13:03 -08:00
parent 049ec51e04
commit 7d66ff19a2
16 changed files with 728 additions and 427 deletions

14
pom.xml
View File

@ -54,18 +54,18 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>16</java.version>
<java.version>17</java.version>
<!-- Non-minecraft related dependencies -->
<powermock.version>2.0.9</powermock.version>
<!-- More visible way how to change dependency versions -->
<spigot.version>1.17.1-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>1.18.0-SNAPSHOT</bentobox.version>
<spigot.version>1.19.2-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>1.22.0-SNAPSHOT</bentobox.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- Do not change unless you want different name for local builds. -->
<build.number>-LOCAL</build.number>
<!-- This allows to change between versions. -->
<build.version>1.2.2</build.version>
<build.version>2.0.2</build.version>
<sonar.projectKey>BentoBoxWorld_Boxed</sonar.projectKey>
<sonar.organization>bentobox-world</sonar.organization>
@ -162,12 +162,6 @@
<version>${bentobox.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>nl.rutgerkok</groupId>
<artifactId>worldgeneratorapi</artifactId>
<version>1.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>

View File

@ -2,11 +2,13 @@ package world.bentobox.boxed;
import java.util.Collections;
import org.bukkit.Difficulty;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.WorldCreator;
import org.bukkit.entity.SpawnCategory;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.ChunkGenerator;
import org.eclipse.jdt.annotation.Nullable;
@ -19,7 +21,9 @@ import world.bentobox.bentobox.api.flags.Flag;
import world.bentobox.bentobox.api.flags.Flag.Mode;
import world.bentobox.bentobox.api.flags.Flag.Type;
import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.boxed.generators.CopyGenerator;
import world.bentobox.boxed.generators.BoxedBiomeGenerator;
import world.bentobox.boxed.generators.BoxedChunkGenerator;
import world.bentobox.boxed.generators.BoxedSeedChunkGenerator;
import world.bentobox.boxed.listeners.AdvancementListener;
import world.bentobox.boxed.listeners.EnderPearlListener;
@ -45,11 +49,12 @@ public class Boxed extends GameModeAddon {
// Settings
private Settings settings;
private ChunkGenerator chunkGenerator;
private BoxedChunkGenerator chunkGenerator;
private final Config<Settings> configObject = new Config<>(this, Settings.class);
private AdvancementsManager advManager;
private ChunkGenerator netherChunkGenerator;
private World seedWorld;
private BiomeProvider boxedBiomeProvider;
@Override
public void onLoad() {
@ -74,6 +79,8 @@ public class Boxed extends GameModeAddon {
setState(State.DISABLED);
return false;
}
// Initialize the Generator because createWorlds will be run after onLoad
this.chunkGenerator = new BoxedChunkGenerator(this);
return true;
}
@ -102,6 +109,7 @@ public class Boxed extends GameModeAddon {
// Register listeners
this.registerListener(new AdvancementListener(this));
this.registerListener(new EnderPearlListener(this));
//this.registerListener(new DebugListener(this));
// Register placeholders
PlaceholdersManager phManager = new PlaceholdersManager(this);
@ -133,19 +141,32 @@ public class Boxed extends GameModeAddon {
@Override
public void createWorlds() {
// Create seed world
log("Creating Boxed Seed world ...");
seedWorld = WorldCreator
.name("seed")
.generator(new BoxedSeedChunkGenerator())
.environment(Environment.NORMAL)
.generateStructures(false)
.seed(getSettings().getSeed())
.createWorld();
saveChunks(seedWorld);
String worldName = settings.getWorldName().toLowerCase();
/*
if (getServer().getWorld(worldName) == null) {
log("Creating Boxed Seed world ...");
}
seedWorld = WorldCreator.name(worldName + "_bak").seed(settings.getSeed()).createWorld();
seedWorld.setDifficulty(Difficulty.PEACEFUL); // No damage wanted in this world.
*/
if (getServer().getWorld(worldName) == null) {
log("Creating Boxed world ...");
}
// Create the world if it does not exist
islandWorld = getWorld(worldName, World.Environment.NORMAL);
/*
// Make the nether if it does not exist
if (settings.isNetherGenerate()) {
if (getServer().getWorld(worldName + NETHER) == null) {
@ -160,6 +181,32 @@ public class Boxed extends GameModeAddon {
}
endWorld = settings.isEndIslands() ? getWorld(worldName, World.Environment.THE_END) : getWorld(worldName, World.Environment.THE_END);
}
*/
}
private void saveChunks(World seedWorld) {
int size = this.getSettings().getIslandDistance();
double percent = size * 4 * size;
int count = 0;
for (int x = -size; x < size; x ++) {
for (int z = -size; z < size; z++) {
ChunkSnapshot chunk = seedWorld.getChunkAt(x, z).getChunkSnapshot(true, true, false);
this.chunkGenerator.setChunk(chunk);
count++;
int p = (int) (count / percent * 100);
if (p % 10 == 0) {
this.log("Storing seed chunks. " + p + "% done");
}
}
}
}
/**
* @return the chunkGenerator
*/
public BoxedChunkGenerator getChunkGenerator() {
return chunkGenerator;
}
/**
@ -172,7 +219,13 @@ public class Boxed extends GameModeAddon {
// Set world name
worldName2 = env.equals(World.Environment.NETHER) ? worldName2 + NETHER : worldName2;
worldName2 = env.equals(World.Environment.THE_END) ? worldName2 + THE_END : worldName2;
World w = WorldCreator.name(worldName2).environment(env).seed(settings.getSeed()).createWorld();
boxedBiomeProvider = new BoxedBiomeGenerator(this);
World w = WorldCreator
.name(worldName2)
.generator(chunkGenerator)
.environment(env)
.seed(seedWorld.getSeed()) // For development
.createWorld();
// Set spawn rates
if (w != null) {
setSpawnRates(w);
@ -181,24 +234,31 @@ public class Boxed extends GameModeAddon {
}
/**
* @return the boxedBiomeProvider
*/
public BiomeProvider getBoxedBiomeProvider() {
return boxedBiomeProvider;
}
private void setSpawnRates(World w) {
if (getSettings().getSpawnLimitMonsters() > 0) {
w.setMonsterSpawnLimit(getSettings().getSpawnLimitMonsters());
w.setSpawnLimit(SpawnCategory.MONSTER, getSettings().getSpawnLimitMonsters());
}
if (getSettings().getSpawnLimitAmbient() > 0) {
w.setAmbientSpawnLimit(getSettings().getSpawnLimitAmbient());
w.setSpawnLimit(SpawnCategory.AMBIENT, getSettings().getSpawnLimitAmbient());
}
if (getSettings().getSpawnLimitAnimals() > 0) {
w.setAnimalSpawnLimit(getSettings().getSpawnLimitAnimals());
w.setSpawnLimit(SpawnCategory.ANIMAL, getSettings().getSpawnLimitAnimals());
}
if (getSettings().getSpawnLimitWaterAnimals() > 0) {
w.setWaterAnimalSpawnLimit(getSettings().getSpawnLimitWaterAnimals());
w.setSpawnLimit(SpawnCategory.WATER_ANIMAL, getSettings().getSpawnLimitWaterAnimals());
}
if (getSettings().getTicksPerAnimalSpawns() > 0) {
w.setTicksPerAnimalSpawns(getSettings().getTicksPerAnimalSpawns());
w.setTicksPerSpawns(SpawnCategory.ANIMAL, getSettings().getTicksPerAnimalSpawns());
}
if (getSettings().getTicksPerMonsterSpawns() > 0) {
w.setTicksPerMonsterSpawns(getSettings().getTicksPerMonsterSpawns());
w.setTicksPerSpawns(SpawnCategory.MONSTER, getSettings().getTicksPerMonsterSpawns());
}
}

View File

@ -0,0 +1,40 @@
package world.bentobox.boxed;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import world.bentobox.bentobox.BentoBox;
/**
* @author tastybento
*
*/
public class DebugListener implements Listener {
private final Boxed addon;
private int size;
/**
* @param addon
*/
public DebugListener(Boxed addon) {
this.addon = addon;
this.size = addon.getSettings().getIslandDistance();
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onMove(PlayerMoveEvent e) {
if (e.getTo().getBlockX() != e.getFrom().getBlockX() || e.getTo().getBlockZ() != e.getFrom().getBlockZ()) {
int chunkX = e.getTo().getChunk().getX();
int chunkZ = e.getTo().getChunk().getZ();
int xx = Math.floorMod(chunkX, size);
int zz = Math.floorMod(chunkZ, size);
BentoBox.getInstance().logDebug("x = " + e.getTo().getBlockX() + " z = " + e.getTo().getBlockZ());
BentoBox.getInstance().logDebug("ChunkX = " + chunkX + " ChunkZ = " + chunkZ);
BentoBox.getInstance().logDebug("CalcChunk X = " + xx + " Calc ChunkZ = " + zz + " should loop");
}
}
}

View File

@ -77,15 +77,31 @@ public class Settings implements WorldSettings {
@ConfigEntry(path = "world.difficulty")
private Difficulty difficulty = Difficulty.NORMAL;
@ConfigComment("Generate surface")
@ConfigEntry(path = "world.generate-surface", needsRestart = true)
private boolean generateSurface = true;
@ConfigComment("Generate bedrock")
@ConfigEntry(path = "world.generate-bedrock", needsRestart = true)
private boolean generateBedrock = true;
@ConfigComment("Generate caves")
@ConfigEntry(path = "world.generate-caves", needsRestart = true)
private boolean generateCaves = true;
@ConfigComment("Generate Decorations")
@ConfigEntry(path = "world.generate-decorations", needsRestart = true)
private boolean generateDecorations = true;
@ConfigComment("Generate mobs")
@ConfigEntry(path = "world.generate-mobs", needsRestart = true)
private boolean generateMobs = true;
@ConfigComment("Allow surface structures - villages, shipwrecks, broken portals, etc.")
@ConfigComment("These will be randomly placed, so may not be available for every player.")
@ConfigEntry(path = "world.allow-structures", needsRestart = true)
private boolean allowStructures = true;
@ConfigComment("Allow strongholds.")
@ConfigComment("These will be randomly placed, so may not be available for every player.")
@ConfigEntry(path = "world.allow-strongholds", experimental = true, needsRestart = true)
private boolean allowStrongholds = true;
@ConfigComment("Spawn limits. These override the limits set in bukkit.yml")
@ConfigComment("If set to a negative number, the server defaults will be used")
@ -106,11 +122,11 @@ public class Settings implements WorldSettings {
@ConfigEntry(path = "world.spawn-limits.ticks-per-monster-spawns")
private int ticksPerMonsterSpawns = -1;
@ConfigComment("Radius of player areas. (So distance between player starting spots is twice this)")
@ConfigComment("Radius of player area in chunks. (So distance between player starting spots is twice this)")
@ConfigComment("It is the same for every dimension : Overworld, Nether and End.")
@ConfigComment("This value cannot be changed mid-game and the plugin will not start if it is different.")
@ConfigEntry(path = "world.area-radius", needsReset = true)
private int islandDistance = 400;
@ConfigEntry(path = "world.chunk-radius", needsReset = true)
private int islandDistance = 10;
@ConfigComment("Starting size of boxed spaces. This is a radius so 1 = a 2x2 area.")
@ConfigComment("Admins can adjust via the /boxadmin range set <player> <new range> command")
@ -1654,20 +1670,6 @@ public class Settings implements WorldSettings {
this.allowStructures = allowStructures;
}
/**
* @return the allowStrongholds
*/
public boolean isAllowStrongholds() {
return allowStrongholds;
}
/**
* @param allowStrongholds the allowStrongholds to set
*/
public void setAllowStrongholds(boolean allowStrongholds) {
this.allowStrongholds = allowStrongholds;
}
/**
* @return the onJoinResetAdvancements
*/
@ -1753,4 +1755,74 @@ public class Settings implements WorldSettings {
public void setBroadcastAdvancements(boolean broadcastAdvancements) {
this.broadcastAdvancements = broadcastAdvancements;
}
/**
* @return the generateSurface
*/
public boolean isGenerateSurface() {
return generateSurface;
}
/**
* @param generateSurface the generateSurface to set
*/
public void setGenerateSurface(boolean generateSurface) {
this.generateSurface = generateSurface;
}
/**
* @return the generateBedrock
*/
public boolean isGenerateBedrock() {
return generateBedrock;
}
/**
* @param generateBedrock the generateBedrock to set
*/
public void setGenerateBedrock(boolean generateBedrock) {
this.generateBedrock = generateBedrock;
}
/**
* @return the generateCaves
*/
public boolean isGenerateCaves() {
return generateCaves;
}
/**
* @param generateCaves the generateCaves to set
*/
public void setGenerateCaves(boolean generateCaves) {
this.generateCaves = generateCaves;
}
/**
* @return the generateDecorations
*/
public boolean isGenerateDecorations() {
return generateDecorations;
}
/**
* @param generateDecorations the generateDecorations to set
*/
public void setGenerateDecorations(boolean generateDecorations) {
this.generateDecorations = generateDecorations;
}
/**
* @return the generateMobs
*/
public boolean isGenerateMobs() {
return generateMobs;
}
/**
* @param generateMobs the generateMobs to set
*/
public void setGenerateMobs(boolean generateMobs) {
this.generateMobs = generateMobs;
}
}

View File

@ -1,33 +1,38 @@
package world.bentobox.boxed.generators;
import java.io.File;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import org.apache.commons.lang.math.NumberUtils;
import org.bukkit.ChunkSnapshot;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import org.bukkit.block.BlockFace;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.WorldInfo;
import org.bukkit.util.Vector;
import com.google.common.base.Enums;
import nl.rutgerkok.worldgeneratorapi.BiomeGenerator;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.boxed.Boxed;
/**
* @author tastybento
*
*/
abstract class AbstractBoxedBiomeGenerator implements BiomeGenerator {
public abstract class AbstractBoxedBiomeProvider extends BiomeProvider {
private static final Map<Environment, String> ENV_MAP;
static {
Map<Environment, String> e = new EnumMap<>(Environment.class);
e.put(Environment.NORMAL, "distribution.overworld");
@ -36,23 +41,25 @@ abstract class AbstractBoxedBiomeGenerator implements BiomeGenerator {
ENV_MAP = Collections.unmodifiableMap(e);
}
protected final Map<BlockFace, SortedMap<Double, Biome>> quadrants;
private final Boxed addon;
protected final int dist;
private final int offsetX;
private final int offsetZ;
private final Biome defaultBiome;
protected final int dist;
protected AbstractBoxedBiomeGenerator(Boxed boxed, Environment env, Biome defaultBiome) {
private final int offsetX;
private final int offsetZ;
protected final Map<BlockFace, SortedMap<Double, Biome>> quadrants;
protected AbstractBoxedBiomeProvider(Boxed boxed, Environment env, Biome defaultBiome) {
this.addon = boxed;
this.defaultBiome = defaultBiome;
dist = addon.getSettings().getIslandDistance();
dist = addon.getSettings().getIslandDistance() * 16; // Distance is in chunks
offsetX = addon.getSettings().getIslandXOffset();
offsetZ = addon.getSettings().getIslandZOffset();
// Load the config
File biomeFile = new File(addon.getDataFolder(), "biomes.yml");
// Check if it exists and if not, save it from the jar
if (!biomeFile.exists()) {
addon.saveResource("biomes.yml", true);
}
@ -69,6 +76,71 @@ abstract class AbstractBoxedBiomeGenerator implements BiomeGenerator {
quadrants.put(BlockFace.SOUTH_WEST, southWest);
}
private Biome getBiome(BlockFace dir, double d) {
Entry<Double, Biome> en = ((TreeMap<Double, Biome>) quadrants.get(dir)).ceilingEntry(d);
return en == null ? defaultBiome : en.getValue();
}
@Override
public Biome getBiome(WorldInfo worldInfo, int x, int y, int z) {
int chunkX = (int)((double)x/16);
int chunkZ = (int)((double)z/16);
int size = addon.getSettings().getIslandDistance();
chunkX = Math.floorMod(chunkX, chunkX < 0 ? -size: size);
chunkZ = Math.floorMod(chunkZ, chunkZ < 0 ? -size : size);
ChunkSnapshot c = addon.getChunkGenerator().getChunk(chunkX, chunkZ);
if (c != null) {
int xx = Math.floorMod(x, 16);
int zz = Math.floorMod(z, 16);
int yy = Math.max(Math.min(y * 4, worldInfo.getMaxHeight()), worldInfo.getMinHeight()); // To handle bug in Spigot
Biome b = c.getBiome(xx, yy, zz);
// Some biomes should stay from the seed world. These are mostly underground biomes.
if (!b.equals(Biome.CUSTOM) && (b.equals(Biome.DRIPSTONE_CAVES) || b.equals(Biome.LUSH_CAVES)
|| b.equals(Biome.RIVER) || b.equals(Biome.DEEP_DARK))) {
return b;
} else {
// Return the mapped biome
return getMappedBiome(x,z);
}
} else {
return getMappedBiome(x,z);
}
}
private Biome getMappedBiome(int x, int z) {
/*
* Biomes go around the island centers
*
*/
Vector s = new Vector(x, 0, z);
Vector l = getClosestIsland(s);
double dis = l.distanceSquared(s);
double d = dis / (dist * dist);
Vector direction = s.subtract(l);
if (direction.getBlockX() <= 0 && direction.getBlockZ() <= 0) {
return getBiome(BlockFace.NORTH_WEST, d);
} else if (direction.getBlockX() > 0 && direction.getBlockZ() <= 0) {
return getBiome(BlockFace.NORTH_EAST, d);
} else if (direction.getBlockX() <= 0 && direction.getBlockZ() > 0) {
return getBiome(BlockFace.SOUTH_WEST, d);
}
return getBiome(BlockFace.SOUTH_EAST, d);
}
@Override
public List<Biome> getBiomes(WorldInfo worldInfo) {
// Return all of them for now!
return Arrays.stream(Biome.values()).filter(b -> !b.equals(Biome.CUSTOM)).toList();
}
private Vector getClosestIsland(Vector v) {
int d = dist * 2;
long x = Math.round((double) v.getBlockX() / d) * d + offsetX;
long z = Math.round((double) v.getBlockZ() / d) * d + offsetZ;
return new Vector(x, 0, z);
}
private SortedMap<Double, Biome> loadQuad(YamlConfiguration config, String string) {
SortedMap<Double, Biome> result = new TreeMap<>();
@ -77,7 +149,7 @@ abstract class AbstractBoxedBiomeGenerator implements BiomeGenerator {
}
for (String ring : config.getStringList(string)) {
String[] split = ring.split(":");
if (split.length == 2 && NumberUtils.isNumber(split[0])) {
if (split.length == 2) {
try {
double d = Double.parseDouble(split[0]);
Biome biome = Enums.getIfPresent(Biome.class, split[1].toUpperCase(Locale.ENGLISH)).orNull();
@ -96,41 +168,4 @@ abstract class AbstractBoxedBiomeGenerator implements BiomeGenerator {
return result;
}
@Override
public Biome getZoomedOutBiome(int x, int y, int z) {
/*
* The given x, y and z coordinates are scaled down by a factor of 4. So when Minecraft
* wants to know the biome at x=112, it will ask the biome generator for a biome at x=112/4=28.
*/
/*
* Biomes go around the island centers
*
*/
Vector s = new Vector(x * 4, 0, z * 4);
Vector l = getClosestIsland(s);
double dis = l.distanceSquared(s);
double d = dis / (dist * dist);
Vector direction = s.subtract(l);
if (direction.getBlockX() <= 0 && direction.getBlockZ() <= 0) {
return getBiome(BlockFace.NORTH_WEST, d);
} else if (direction.getBlockX() > 0 && direction.getBlockZ() <= 0) {
return getBiome(BlockFace.NORTH_EAST, d);
} else if (direction.getBlockX() <= 0 && direction.getBlockZ() > 0) {
return getBiome(BlockFace.SOUTH_WEST, d);
}
return getBiome(BlockFace.SOUTH_EAST, d);
}
private Biome getBiome(BlockFace dir, double d) {
Entry<Double, Biome> en = ((TreeMap<Double, Biome>) quadrants.get(dir)).ceilingEntry(d);
return en == null ? defaultBiome : en.getValue();
}
private Vector getClosestIsland(Vector v) {
int d = dist * 2;
long x = Math.round((double) v.getBlockX() / d) * d + offsetX;
long z = Math.round((double) v.getBlockZ() / d) * d + offsetZ;
return new Vector(x, 0, z);
}
}

View File

@ -9,10 +9,10 @@ import world.bentobox.boxed.Boxed;
* @author tastybento
*
*/
public class BoxedBiomeGenerator extends AbstractBoxedBiomeGenerator {
public class BoxedBiomeGenerator extends AbstractBoxedBiomeProvider {
public BoxedBiomeGenerator(Boxed boxed) {
super(boxed, Environment.NORMAL, Biome.OCEAN);
}
}
}

View File

@ -0,0 +1,66 @@
package world.bentobox.boxed.generators;
import java.util.Arrays;
import java.util.List;
import org.bukkit.ChunkSnapshot;
import org.bukkit.block.Biome;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.WorldInfo;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.boxed.Boxed;
/**
* @author tastybento
*
*/
public class BoxedBiomeProvider extends BiomeProvider {
private final Boxed addon;
public BoxedBiomeProvider(Boxed boxed) {
addon = boxed;
}
@Override
public Biome getBiome(WorldInfo worldInfo, int x, int y, int z) {
if (!worldInfo.getName().equals(addon.getSettings().getWorldName())) {
BentoBox.getInstance().logDebug("Wrong world biome ask.");
return Biome.OLD_GROWTH_SPRUCE_TAIGA;
}
int chunkX = (int)((double)x/16);
int chunkZ = (int)((double)z/16);
ChunkSnapshot c = addon.getChunkGenerator().getChunk(chunkX, chunkZ);
if (c == null) {
//BentoBox.getInstance().logDebug("No chunk snapshot for " + (int)((double)x/16) + "," + (int)((double)z/16));
return Biome.OLD_GROWTH_SPRUCE_TAIGA;
}
int xx = Math.floorMod(x, 16);
int zz = Math.floorMod(z, 16);
int yy = Math.max(Math.min(y * 4, worldInfo.getMaxHeight()), worldInfo.getMinHeight()); // To handle bug in Spigot
Biome b = c.getBiome(xx, yy, zz);
if (b != Biome.CUSTOM) {
/*
if (chunkX == 0 && chunkZ == 0) {
BentoBox.getInstance().logDebug("Chunk thinks its coords are x=" + c.getX() + " z=" + c.getZ());
BentoBox.getInstance().logDebug("World min = " + worldInfo.getMinHeight() + " world max = " + worldInfo.getMaxHeight());
BentoBox.getInstance().logDebug("Biome found and coord = " + b + " " + x + "," + y + "," + z);
BentoBox.getInstance().logDebug("Chunk = " + chunkX + "," + chunkZ);
BentoBox.getInstance().logDebug("Pos in chunk " + xx + "," + yy + "," + zz);
}
*/
return b;
} else {
return Biome.OLD_GROWTH_BIRCH_FOREST;
}
}
@Override
public List<Biome> getBiomes(WorldInfo worldInfo) {
// Return all of them for now!
return Arrays.stream(Biome.values()).filter(b -> !b.equals(Biome.CUSTOM)).toList();
//return overWorld.getBiomeProvider().getBiomes(overWorld);
}
}

View File

@ -1,15 +1,17 @@
package world.bentobox.boxed.generators;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.WorldInfo;
import org.bukkit.util.noise.SimplexNoiseGenerator;
import world.bentobox.bentobox.util.Pair;
import world.bentobox.boxed.Boxed;
/**
@ -18,30 +20,269 @@ import world.bentobox.boxed.Boxed;
*/
public class BoxedChunkGenerator extends ChunkGenerator {
//private final WorldRef wordRef;
private final Boxed addon;
private FileConfiguration config;
private SimplexNoiseGenerator generator;
private final int dist;
private final int size;
private Map<Pair<Integer, Integer>, ChunkSnapshot> chunks = new HashMap<>();
//private final WorldRef wordRefNether;
public BoxedChunkGenerator(Boxed addon) {
this.addon = addon;
this.config = addon.getConfig();
this.generator = new SimplexNoiseGenerator(new Random(addon.getSettings().getSeed()));
this.dist = addon.getSettings().getIslandDistance();
//wordRef = WorldRef.ofName(addon.getSettings().getWorldName());
//wordRefNether = WorldRef.ofName(addon.getSettings().getWorldName() + "_nether");
size = addon.getSettings().getIslandDistance();
}
@Override
public BiomeProvider getDefaultBiomeProvider(WorldInfo worldInfo) {
return addon.getBoxedBiomeProvider();
}
/**
* @param chunk the chunk to set
*/
public void setChunk(ChunkSnapshot chunk) {
chunks.putIfAbsent(new Pair<>(chunk.getX(), chunk.getZ()), chunk);
}
/**
* @param x chunk x
* @param z chunk z
* @return chunk snapshot or null if there is none
*/
public ChunkSnapshot getChunk(int x, int z) {
int xx = Math.floorMod(x, size);
int zz = Math.floorMod(z, size);
return chunks.get(new Pair<>(xx, zz));
}
/**
* @param chunk the chunk to set
*/
public void setChunks(Map<Pair<Integer, Integer>, ChunkSnapshot> chunks) {
this.chunks = chunks;
}
@Override
public boolean canSpawn(World world, int x, int z)
{
return true;
}
@Override
public void generateNoise(WorldInfo worldInfo, Random r, int chunkX, int chunkZ, ChunkData cd) {
int height = worldInfo.getMaxHeight();
int minY = worldInfo.getMinHeight();
// Repeat islands
int xx = Math.floorMod(chunkX, chunkX < 0 ? -size: size);
int zz = Math.floorMod(chunkZ, chunkZ < 0 ? -size : size);
Pair<Integer, Integer> coords = new Pair<>(xx, zz);
if (!chunks.containsKey(coords)) {
// This should never be needed because islands should abut each other
//BentoBox.getInstance().logDebug("Water chunk: " + chunkX + "," + chunkZ);
cd.setRegion(0, minY, 0, 16, 0, 16, Material.WATER);
return;
}
//BentoBox.getInstance().logDebug("Copying chunk: " + xx + "," + zz);
ChunkSnapshot chunk = chunks.get(coords);
for (int x = 0; x < 16; x ++) {
for (int z = 0; z < 16; z++) {
for (int y = minY; y < height; y++) {
Material m = chunk.getBlockType(x, y, z);
switch (m) {
case WATER:
case LAVA:
case NETHERRACK:
cd.setBlock(x, y, z, m);
break;
default:
cd.setBlock(x, y, z, isGround(m) ? Material.STONE: Material.AIR);
}
}
}
}
}
/**
* @return the chunks
*/
public Map<Pair<Integer, Integer>, ChunkSnapshot> getChunks() {
return chunks;
}
private static boolean isGround(Material m) {
if (m.isAir() || m.isBurnable() || !m.isSolid()) return false;
switch (m) {
case ANDESITE:
case BEDROCK:
case CALCITE:
case CLAY:
case COAL_ORE:
case COARSE_DIRT:
case COBBLESTONE:
case COPPER_ORE:
case DEEPSLATE:
case DEEPSLATE_COAL_ORE:
case DEEPSLATE_COPPER_ORE:
case DEEPSLATE_DIAMOND_ORE:
case DEEPSLATE_EMERALD_ORE:
case DEEPSLATE_GOLD_ORE:
case DEEPSLATE_IRON_ORE:
case DEEPSLATE_LAPIS_ORE:
case DEEPSLATE_REDSTONE_ORE:
case DIAMOND_ORE:
case DIORITE:
case DIRT:
case DIRT_PATH:
case DRIPSTONE_BLOCK:
case EMERALD_ORE:
case END_STONE:
case FARMLAND:
case GLOWSTONE:
case GOLD_ORE:
case GRANITE:
case GRASS_BLOCK:
case IRON_ORE:
case MAGMA_BLOCK:
case MYCELIUM:
case NETHERITE_BLOCK:
case NETHERRACK:
case RED_SAND:
case RED_SANDSTONE:
case ROOTED_DIRT:
case SAND:
case SANDSTONE:
case SOUL_SAND:
case SOUL_SOIL:
case STONE:
case TERRACOTTA:
case AMETHYST_BLOCK:
case AMETHYST_CLUSTER:
case AMETHYST_SHARD:
case BASALT:
case BLACKSTONE:
case BLACK_CONCRETE:
case BLACK_GLAZED_TERRACOTTA:
case BLACK_TERRACOTTA:
case BLUE_CONCRETE:
case BLUE_GLAZED_TERRACOTTA:
case BLUE_TERRACOTTA:
case BONE_BLOCK:
case BROWN_CONCRETE:
case BROWN_GLAZED_TERRACOTTA:
case BROWN_TERRACOTTA:
case BUDDING_AMETHYST:
case CHISELED_DEEPSLATE:
case CHISELED_NETHER_BRICKS:
case CHISELED_POLISHED_BLACKSTONE:
case CHISELED_QUARTZ_BLOCK:
case CHISELED_RED_SANDSTONE:
case CHISELED_SANDSTONE:
case CHISELED_STONE_BRICKS:
case COAL_BLOCK:
case COBBLED_DEEPSLATE:
case CRYING_OBSIDIAN:
case CUT_RED_SANDSTONE:
case CUT_RED_SANDSTONE_SLAB:
case CUT_SANDSTONE:
case CUT_SANDSTONE_SLAB:
case CYAN_CONCRETE:
case CYAN_GLAZED_TERRACOTTA:
case CYAN_TERRACOTTA:
case DEEPSLATE_BRICKS:
case DIAMOND_BLOCK:
case ECHO_SHARD:
case EMERALD_BLOCK:
case GOLD_BLOCK:
case GRAVEL:
case GRAY_CONCRETE:
case GRAY_GLAZED_TERRACOTTA:
case GRAY_TERRACOTTA:
case GREEN_CONCRETE:
case GREEN_GLAZED_TERRACOTTA:
case GREEN_TERRACOTTA:
case INFESTED_CHISELED_STONE_BRICKS:
case INFESTED_COBBLESTONE:
case INFESTED_CRACKED_STONE_BRICKS:
case INFESTED_DEEPSLATE:
case INFESTED_MOSSY_STONE_BRICKS:
case INFESTED_STONE:
case INFESTED_STONE_BRICKS:
case LAPIS_ORE:
case LARGE_AMETHYST_BUD:
case LIGHT_BLUE_CONCRETE:
case LIGHT_BLUE_GLAZED_TERRACOTTA:
case LIGHT_BLUE_TERRACOTTA:
case LIGHT_GRAY_CONCRETE:
case LIGHT_GRAY_GLAZED_TERRACOTTA:
case LIGHT_GRAY_TERRACOTTA:
case LIME_CONCRETE:
case LIME_GLAZED_TERRACOTTA:
case LIME_TERRACOTTA:
case MAGENTA_CONCRETE:
case MAGENTA_GLAZED_TERRACOTTA:
case MAGENTA_TERRACOTTA:
case MOSSY_COBBLESTONE:
case MUD:
case NETHERITE_SCRAP:
case NETHER_GOLD_ORE:
case NETHER_QUARTZ_ORE:
case OBSIDIAN:
case ORANGE_CONCRETE:
case ORANGE_GLAZED_TERRACOTTA:
case ORANGE_TERRACOTTA:
case PACKED_MUD:
case PINK_CONCRETE:
case PINK_GLAZED_TERRACOTTA:
case PINK_TERRACOTTA:
case PODZOL:
case POLISHED_ANDESITE:
case POLISHED_BASALT:
case POLISHED_BLACKSTONE:
case POLISHED_DEEPSLATE:
case POLISHED_DIORITE:
case POLISHED_GRANITE:
case PURPLE_CONCRETE:
case PURPLE_GLAZED_TERRACOTTA:
case PURPLE_TERRACOTTA:
case PURPUR_BLOCK:
case QUARTZ_BLOCK:
case RAW_COPPER_BLOCK:
case RAW_GOLD_BLOCK:
case RAW_IRON_BLOCK:
case REDSTONE_BLOCK:
case REDSTONE_ORE:
case RED_CONCRETE:
case RED_GLAZED_TERRACOTTA:
case RED_TERRACOTTA:
case SMOOTH_BASALT:
case SMOOTH_QUARTZ:
case SMOOTH_RED_SANDSTONE:
case SMOOTH_SANDSTONE:
case SMOOTH_STONE:
case WARPED_HYPHAE:
case WARPED_NYLIUM:
case WHITE_CONCRETE:
case WHITE_GLAZED_TERRACOTTA:
case WHITE_TERRACOTTA:
case YELLOW_CONCRETE:
case YELLOW_GLAZED_TERRACOTTA:
case YELLOW_TERRACOTTA:
return true;
default:
return false;
}
}
@Override
public boolean shouldGenerateNoise() {
return false;
@ -49,72 +290,42 @@ public class BoxedChunkGenerator extends ChunkGenerator {
@Override
public boolean shouldGenerateSurface() {
return true;
return this.addon.getSettings().isGenerateSurface();
}
@Override
public boolean shouldGenerateBedrock() {
return true;
return this.addon.getSettings().isGenerateBedrock();
}
@Override
public boolean shouldGenerateCaves() {
return true;
return this.addon.getSettings().isGenerateCaves();
}
@Override
public boolean shouldGenerateDecorations() {
return true;
return this.addon.getSettings().isGenerateDecorations();
}
@Override
public boolean shouldGenerateMobs() {
return true;
return this.addon.getSettings().isGenerateMobs();
}
@Override
public boolean shouldGenerateStructures() {
return true;
return this.addon.getSettings().isAllowStructures();
}
public ChunkSnapshot getChunkFromXZ(int x, int z) {
int chunkX = (int)((double)x/16);
int chunkZ = (int)((double)z/16);
return this.getChunk(chunkX, chunkZ);
}
@Override
public void generateNoise(WorldInfo worldInfo, Random r, int chunkX, int chunkZ, ChunkData cd) {
// Biome scale
Biome biome = Biome.PLAINS;
double noiseScaleHorizontal = config.getDouble("biomes." + biome.name() + ".scale", 8D) / 1000D;
//generator.setScale(noiseScaleHorizontal);
// Biome height
double biomeHeight = config.getDouble("biomes." + biome.name() + ".height", 8D);
Material material;
if (worldInfo.getEnvironment() == World.Environment.NORMAL) {
material = Material.STONE;
} else {
material = Material.NETHERRACK;
}
int worldX = ((chunkX * 16) % dist) + dist;
int worldZ = ((chunkZ * 16) % dist) + dist;
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
double noise = generator.noise(worldX + x, worldZ + z) / noiseScaleHorizontal;
int height = (int) (noise * 40);
height += 50;
height += biomeHeight;
if (height > cd.getMaxHeight()) {
height = cd.getMaxHeight();
}
if (height < cd.getMinHeight()) {
height = cd.getMinHeight();
}
for (int y = 0; y < height; y++) {
cd.setBlock(x, y, z, material);
}
}
}
}
}

View File

@ -0,0 +1,45 @@
package world.bentobox.boxed.generators;
import org.bukkit.generator.ChunkGenerator;
/**
* @author tastybento
*
*/
public class BoxedSeedChunkGenerator extends ChunkGenerator {
@Override
public boolean shouldGenerateNoise() {
return true;
}
@Override
public boolean shouldGenerateSurface() {
return true;
}
@Override
public boolean shouldGenerateBedrock() {
return false;
}
@Override
public boolean shouldGenerateCaves() {
return true;
}
@Override
public boolean shouldGenerateDecorations() {
return true;
}
@Override
public boolean shouldGenerateMobs() {
return false;
}
@Override
public boolean shouldGenerateStructures() {
return false;
}
}

View File

@ -1,44 +0,0 @@
package world.bentobox.boxed.generators;
import java.util.Random;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.WorldInfo;
import world.bentobox.boxed.Boxed;
/**
* @author tastybento
*
*/
public class CopyGenerator extends ChunkGenerator {
private final int distChunks;
private final World world;
/**
* @param addon addon
*/
public CopyGenerator(Boxed addon, World world) {
this.world = world;
this.distChunks = addon.getSettings().getIslandDistance() / 16;
}
@Override
public void generateSurface(WorldInfo worldInfo, Random random, int x, int z, ChunkData chunkData) {
int worldX = (x % distChunks);
int worldZ = (z % distChunks);
// Load the chunk from the back world
Chunk chunk = world.getChunkAt(worldX, worldZ);
for (int xx = 0; xx < 16; xx++) {
for (int y = worldInfo.getMinHeight(); y < worldInfo.getMaxHeight(); y++) {
for (int zz = 0; zz < 16; zz++) {
chunkData.setBlock(xx, y, zz, chunk.getBlock(xx, y, zz).getBlockData());
}
}
}
}
}

View File

@ -1,18 +0,0 @@
package world.bentobox.boxed.generators;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import world.bentobox.boxed.Boxed;
/**
* @author tastybento
*
*/
public class NetherBiomeGenerator extends AbstractBoxedBiomeGenerator {
public NetherBiomeGenerator(Boxed boxed) {
super(boxed, Environment.NETHER, Biome.NETHER_WASTES);
}
}

View File

@ -1,105 +0,0 @@
package world.bentobox.boxed.generators;
import java.io.File;
import java.util.EnumMap;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.util.noise.NoiseGenerator;
import org.bukkit.util.noise.SimplexNoiseGenerator;
import com.google.common.base.Enums;
import nl.rutgerkok.worldgeneratorapi.BaseNoiseGenerator;
import nl.rutgerkok.worldgeneratorapi.BiomeGenerator;
import world.bentobox.boxed.Boxed;
/**
* Generates the Nether
* @author tastybento
*
*/
public class NetherGenerator implements BaseNoiseGenerator {
private static final String NETHER_BIOMES = "nether.biomes";
private final BiomeNoise defaultNoise = new BiomeNoise(10D, 0D, 2D);
private final NoiseGenerator mainNoiseGenerator;
private final Boxed addon;
private final Map<Biome, BiomeNoise> biomeNoiseMap;
public NetherGenerator(Boxed addon, long seed) {
this.addon = addon;
// Initialize the noise generator based on the world seed
this.mainNoiseGenerator = new SimplexNoiseGenerator(seed);
// Load the config
File biomeFile = new File(addon.getDataFolder(), "biomes.yml");
if (!biomeFile.exists()) {
addon.saveResource("biomes.yml", true);
}
YamlConfiguration config = YamlConfiguration.loadConfiguration(biomeFile);
biomeNoiseMap = new EnumMap<>(Biome.class);
if (config.isConfigurationSection(NETHER_BIOMES)) {
for (String key : config.getConfigurationSection(NETHER_BIOMES).getKeys(false)) {
double noiseScaleHorizontal = config.getDouble(NETHER_BIOMES + "." + key + ".scale", 10D);
double height = config.getDouble(NETHER_BIOMES + "." + key + ".height", 0D);
double noiseScaleVertical = config.getDouble(NETHER_BIOMES + "." + key + ".vscale", 2D);
Enums.getIfPresent(Biome.class, key).toJavaUtil()
.ifPresent(biome -> biomeNoiseMap.put(biome, new BiomeNoise(noiseScaleHorizontal, height, noiseScaleVertical)));
}
}
}
static class BiomeNoise {
double noiseScaleHorizontal = 10D;
double height = 0D;
double noiseScaleVertical = 2D;
/**
* @param noiseScaleHorizontal horizontal noise scale
* @param height height
* @param noiseScaleVertical vertical noise scale
*/
public BiomeNoise(double noiseScaleHorizontal, double height, double noiseScaleVertical) {
this.noiseScaleHorizontal = noiseScaleHorizontal;
this.height = height;
this.noiseScaleVertical = noiseScaleVertical;
}
@Override
public String toString() {
return "BiomeNoise [noiseScaleHorizontal=" + noiseScaleHorizontal + ", height=" + height
+ ", noiseScaleVertical=" + noiseScaleVertical + "]";
}
}
@Override
public TerrainSettings getTerrainSettings() {
TerrainSettings ts = new TerrainSettings();
ts.stoneBlock = Material.NETHERRACK.createBlockData();
ts.waterBlock = Material.LAVA.createBlockData();
return ts;
}
@Override
public void getNoise(BiomeGenerator biomeGenerator, double[] buffer, int scaledX, int scaledZ) {
// Repeat on an island boundary
int dist = addon.getSettings().getIslandDistance();
Biome biome = biomeGenerator.getZoomedOutBiome(scaledX, scaledZ);
if (biome == null) {
// edge of island
biome = Biome.NETHER_WASTES;
}
BiomeNoise bm = this.biomeNoiseMap.getOrDefault(biome, defaultNoise);
double x = ((((double)scaledX*4) % dist) / 4) / bm.noiseScaleHorizontal;
double z = ((((double)scaledZ*4) % dist) / 4) / bm.noiseScaleHorizontal;
for (int y = 0; y < 16; y++) {
double noise = this.mainNoiseGenerator.noise(x, y / Math.max(0.5, bm.noiseScaleVertical), z);
double heightOffset = y < 12 && bm.height != 0 ? bm.height - y : 0;
buffer[y] = noise + heightOffset;
}
}
}

View File

@ -1,67 +0,0 @@
package world.bentobox.boxed.generators;
import java.io.File;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.WorldInfo;
import org.bukkit.util.noise.SimplexNoiseGenerator;
import nl.rutgerkok.worldgeneratorapi.BaseNoiseProvider;
import world.bentobox.boxed.Boxed;
/**
* @author tastybento
*
*/
public class OverWorldGenerator implements BaseNoiseProvider {
private final SimplexNoiseGenerator mainNoiseGenerator;
private final Boxed addon;
private final YamlConfiguration config;
public OverWorldGenerator(Boxed addon, long seed) {
this.addon = addon;
// Initialize the noise generator based on the world seed
this.mainNoiseGenerator = new SimplexNoiseGenerator(seed);
// Load the config
File biomeFile = new File(addon.getDataFolder(), "biomes.yml");
if (!biomeFile.exists()) {
addon.saveResource("biomes.yml", true);
}
config = YamlConfiguration.loadConfiguration(biomeFile);
}
@Override
public TerrainConfig getTerrainSettings() {
TerrainConfig ts = new TerrainConfig();
ts.stoneBlock = Material.STONE.createBlockData();
ts.waterBlock = Material.WATER.createBlockData();
return ts;
}
@Override
public void getNoise(WorldInfo worldInfo, double[] buffer, int scaledX, int scaledZ) {
BiomeProvider bp = addon.getPlugin().getDefaultBiomeProvider(worldInfo.getName(), "");
// Repeat on an island boundary
int dist = addon.getSettings().getIslandDistance();
int blockX = scaledX * 4;
int blockZ = scaledZ * 4;
Biome biome = bp.getBiome(worldInfo, blockX, 63, blockZ);
double noiseScaleHorizontal = config.getDouble("biomes." + biome.name() + ".scale", 10D);
double height = config.getDouble("biomes." + biome.name() + ".height", 8D);
double x = ((((double)blockX) % dist) / 4) / noiseScaleHorizontal;
double z = ((((double)blockZ) % dist) / 4) / noiseScaleHorizontal;
for (int y = 0; y < buffer.length; y++) {
double noise = this.mainNoiseGenerator.noise(x, y, z);
double heightOffset = height - y;
buffer[y] = noise + heightOffset;
}
}
}

View File

@ -23,13 +23,13 @@ public class SimpleBiomeProvider extends BiomeProvider {
if (generator.noise(x, z, 1, 1, true) < 0) {
return Biome.OCEAN;
} else {
return Biome.MOUNTAINS;
return Biome.DESERT;
}
}
@NonNull
@Override
public List<Biome> getBiomes(@NonNull WorldInfo worldInfo) {
return Lists.newArrayList(Biome.OCEAN, Biome.MOUNTAINS);
return Lists.newArrayList(Biome.OCEAN, Biome.DESERT);
}
}

View File

@ -5,12 +5,8 @@ distribution:
- 0.05:PLAINS
- 0.1:DESERT
- 0.2:SAVANNA
- 0.4:JUNGLE_EDGE
- 0.5:JUNGLE
- 0.6:JUNGLE_HILLS
- 0.75:BAMBOO_JUNGLE_HILLS
- 0.8:BAMBOO_JUNGLE
- 0.9:BADLANDS_PLATEAU
- 1.0:BADLANDS
- 1.1:LUKEWARM_OCEAN
- 20.0:WARM_OCEAN
@ -20,12 +16,11 @@ distribution:
- 0.2:FLOWER_FOREST
- 0.3:SAVANNA
- 0.4:DESERT
- 0.5:SHATTERED_SAVANNA
- 0.65:DESERT_HILLS
- 0.7:GRAVELLY_MOUNTAINS
- 0.9:BADLANDS_PLATEAU
- 0.5:WINDSWEPT_SAVANNA
- 0.7:STONY_PEAKS
- 0.9:WINDSWEPT_GRAVELLY_HILLS
- 1.0:ERODED_BADLANDS
- 1.1:MUSHROOM_FIELD_SHORE
- 1.1:MUSHROOM_FIELDS
- 20.0:WARM_OCEAN
north-west:
- 0.05:PLAINS
@ -33,9 +28,7 @@ distribution:
- 0.3:FLOWER_FOREST
- 0.4:DARK_FOREST
- 0.5:SNOWY_TAIGA
- 0.65:SNOWY_TAIGA_HILLS
- 0.7:SNOWY_MOUNTAINS
- 0.9:MOUNTAIN_EDGE
- 0.7:STONY_PEAKS
- 1.1:BEACH
- 20.0:COLD_OCEAN
south-west:
@ -44,9 +37,7 @@ distribution:
- 0.3:FOREST
- 0.4:DARK_FOREST
- 0.5:SNOWY_TAIGA
- 0.65:SNOWY_TAIGA_HILLS
- 0.7:SNOWY_MOUNTAINS
- 0.9:MOUNTAIN_EDGE
- 0.7:SNOWY_SLOPES
- 1.1:ICE_SPIKES
- 20.0:COLD_OCEAN
nether:

View File

@ -1,4 +1,4 @@
# Boxed Configuration {$version}
# Boxed Configuration 2.0.2-SNAPSHOT-LOCAL
boxed:
command:
# Player Command. What command users will run to access their area.
@ -27,10 +27,29 @@ world:
# World seed.
# If you change this, stop the server and delete the worlds made.
# /!\ BentoBox currently does not support changing this value mid-game. If you do need to change it, do a full reset of your databases and worlds.
seed: 978573758696
seed: 602103456450
# World difficulty setting - PEACEFUL, EASY, NORMAL, HARD
# Other plugins may override this setting
difficulty: NORMAL
# Generate surface
# /!\ In order to apply the changes made to this option, you must restart your server. Reloading BentoBox or the server won't work.
generate-surface: true
# Generate bedrock
# /!\ In order to apply the changes made to this option, you must restart your server. Reloading BentoBox or the server won't work.
generate-bedrock: true
# Generate caves
# /!\ In order to apply the changes made to this option, you must restart your server. Reloading BentoBox or the server won't work.
generate-caves: false
# Generate Decorations
# /!\ In order to apply the changes made to this option, you must restart your server. Reloading BentoBox or the server won't work.
generate-decorations: true
# Generate mobs
# /!\ In order to apply the changes made to this option, you must restart your server. Reloading BentoBox or the server won't work.
generate-mobs: true
# Allow surface structures - villages, shipwrecks, broken portals, etc.
# These will be randomly placed, so may not be available for every player.
# /!\ In order to apply the changes made to this option, you must restart your server. Reloading BentoBox or the server won't work.
allow-structures: true
spawn-limits:
# Spawn limits. These override the limits set in bukkit.yml
# If set to a negative number, the server defaults will be used
@ -44,11 +63,11 @@ world:
# Setting to 0 will disable monster spawns, but this is not recommended. Minecraft default is 400.
# A negative value uses the server default
ticks-per-monster-spawns: -1
# Radius of player areas. (So distance between player starting spots is twice this)
# Radius of player area in chunks. (So distance between player starting spots is twice this)
# It is the same for every dimension : Overworld, Nether and End.
# This value cannot be changed mid-game and the plugin will not start if it is different.
# /!\ BentoBox currently does not support changing this value mid-game. If you do need to change it, do a full reset of your databases and worlds.
area-radius: 1000
chunk-radius: 20
# Starting size of boxed spaces. This is a radius so 1 = a 2x2 area.
# Admins can adjust via the /boxadmin range set <player> <new range> command
starting-protection-range: 1
@ -61,7 +80,7 @@ world:
start-z: 0
# Area height - Lowest is 5.
# It is the y coordinate of the bedrock block in the blueprint.
area-height: 5
area-height: 8
# Maximum number of player areas in the world. Set to -1 or 0 for unlimited.
# If the number of areas is greater than this number, it will stop players from joining the world.
max-areas: -1
@ -78,21 +97,21 @@ world:
# Note: Some default challenges will not be possible if there is no nether.
# Note that with a standard nether all players arrive at the same portal and entering a
# portal will return them back to their areas.
generate: true
generate: false
# Nether spawn protection radius - this is the distance around the nether spawn
# that will be protected from player interaction (breaking blocks, pouring lava etc.)
# that will be public from player interaction (breaking blocks, pouring lava etc.)
# Minimum is 0 (not recommended), maximum is 100. Default is 25.
# Only applies to vanilla nether
spawn-radius: 32
# This option indicates if nether portals should be linked via dimensions.
# Option will simulate vanilla portal mechanics that links portals together or creates a new portal,
# if there is not a portal in other dimension.
# Added since 1.0.3
# Option will simulate vanilla portal mechanics that links portals together
# or creates a new portal, if there is not a portal in that dimension.
# Added since 1.0.3.
create-and-link-portals: true
end:
# End Nether - if this is false, the end world will not be made and access to
# the end will not occur. Other plugins may still enable portal usage.
generate: true
generate: false
# Mob white list - these mobs will NOT be removed when logging in or doing /boxed
remove-mobs-whitelist: []
# World flags. These are boolean settings for various flags for this world
@ -102,6 +121,7 @@ world:
ISLAND_RESPAWN: true
REDSTONE: true
CREEPER_GRIEFING: true
VISITOR_KEEP_INVENTORY: false
BUCKET: false
ENDER_PEARL: false
DOOR: true
@ -179,6 +199,7 @@ world:
WORLD_TNT_DAMAGE: true
HOPPER: false
LEASH: false
ALLOW_MOVE_BOX: true
BREAK_BLOCKS: false
MOUNT_INVENTORY: false
OFFLINE_REDSTONE: true
@ -208,10 +229,10 @@ world:
BREAK_HOPPERS: 500
FURNACE: 500
MONSTER_SPAWNERS_SPAWN: 500
ANVIL: 500
MINECART: 500
FISH_SCOOPING: 500
ANVIL: 500
FIRE_IGNITE: 500
FISH_SCOOPING: 500
END_PORTAL: 500
BREEDING: 500
HURT_VILLAGERS: 500
@ -221,9 +242,9 @@ world:
BREAK_SPAWNERS: 500
LEVER: 0
ELYTRA: 0
CAKE: 500
RIDING: 500
HURT_MONSTERS: 0
RIDING: 500
CAKE: 500
NAME_TAG: 500
ARMOR_STAND: 500
TRADING: 0
@ -235,8 +256,8 @@ world:
LECTERN: 500
CROP_TRAMPLE: 500
ITEM_PICKUP: 0
DROPPER: 500
BREWING: 500
DROPPER: 500
TNT_PRIMING: 500
COLLECT_WATER: 500
BUTTON: 0
@ -244,18 +265,18 @@ world:
COMMAND_RANKS: 500
BEACON: 500
TRAPDOOR: 500
PRESSURE_PLATE: 0
EXPERIENCE_BOTTLE_THROWING: 500
PRESSURE_PLATE: 0
DYE: 500
PLACE_BLOCKS: 500
ITEM_FRAME: 500
PLACE_BLOCKS: 500
CRAFTING: 0
SHEARING: 500
ENCHANTING: 500
SHEARING: 500
ANIMAL_SPAWNERS_SPAWN: 500
BOAT: 0
BED: 500
SPAWN_EGGS: 500
BED: 500
MILKING: 500
DISPENSER: 500
GATE: 0
@ -279,8 +300,8 @@ world:
MONSTER_NATURAL_SPAWN: true
FIRE_IGNITE: true
FIRE_SPREAD: true
FIRE_BURNING: true
ANIMAL_SPAWNERS_SPAWN: true
FIRE_BURNING: true
PVP_OVERWORLD: false
# These settings/flags are hidden from users
# Ops can toggle hiding in-game using SHIFT-LEFT-CLICK on flags in settings
@ -350,11 +371,11 @@ area:
exp: true
# Reset Ender Chest - if true, the player's Ender Chest will be cleared.
ender-chest: false
# Reset advancements
# Reset advancements.
reset-advancements: true
# Grant these advancements
grant-advancements:
- minecraft:story/root
- minecraft:story/root
on-leave:
# What the plugin should reset when the player leaves or is kicked from an area
# Reset Money - if this is true, will reset the player's money to the starting money
@ -373,7 +394,7 @@ area:
exp: false
# Reset Ender Chest - if true, the player's Ender Chest will be cleared.
ender-chest: false
# Reset advancements
# Reset advancements.
reset-advancements: false
# Grant these advancements
grant-advancements: []
@ -442,17 +463,17 @@ area:
#
# Note that player-executed commands might not work, as these commands can be run with said player being offline.
on-leave: []
# Returns a list of commands that should be executed when the player respawns after death if Flags.ISLAND_RESPAWN is true.
# List of commands that should be executed when the player respawns after death if Flags.ISLAND_RESPAWN is true.
# These commands are run by the console, unless otherwise stated using the [SUDO] prefix,
# in which case they are executed by the player.
#
#
# Available placeholders for the commands are the following:
# * [name]: name of the player
#
#
# Here are some examples of valid commands to execute:
# * '[SUDO] bbox version'
# * 'bsbadmin deaths set [player] 0'
#
#
# Note that player-executed commands might not work, as these commands can be run with said player being offline.
# Added since 1.14.0.
on-respawn: []