Initial Nether implementation.

This commit is contained in:
tastybento 2021-03-23 21:45:52 -07:00
parent 769d4af4bd
commit 7b345253c7
12 changed files with 275 additions and 71 deletions

View File

@ -1,2 +1,3 @@
/org.eclipse.core.resources.prefs
/org.eclipse.jdt.core.prefs
/org.eclipse.m2e.core.prefs

View File

@ -51,6 +51,7 @@ public class Boxed extends GameModeAddon {
private Config<Settings> configObject = new Config<>(this, Settings.class);
private AdvancementsManager advManager;
private DeleteGen delChunks;
private ChunkGenerator netherChunkGenerator;
@Override
public void onLoad() {
@ -69,6 +70,7 @@ public class Boxed extends GameModeAddon {
}
// Chunk generator
chunkGenerator = new BoxedChunkGenerator(this).getGenerator();
netherChunkGenerator = new BoxedChunkGenerator(this).getNetherGenerator();
// Register commands
playerCommand = new DefaultPlayerCommand(this) {};
@ -163,7 +165,7 @@ public class Boxed extends GameModeAddon {
if (getServer().getWorld(worldName + NETHER) == null) {
log("Creating Boxed's Nether...");
}
netherWorld = settings.isNetherIslands() ? getWorld(worldName, World.Environment.NETHER, chunkGenerator) : getWorld(worldName, World.Environment.NETHER, null);
netherWorld = settings.isNetherIslands() ? getWorld(worldName, World.Environment.NETHER, netherChunkGenerator) : getWorld(worldName, World.Environment.NETHER, null);
}
// Make the end if it does not exist
if (settings.isEndGenerate()) {
@ -187,9 +189,7 @@ public class Boxed extends GameModeAddon {
worldName2 = env.equals(World.Environment.THE_END) ? worldName2 + THE_END : worldName2;
World w = WorldCreator.name(worldName2).type(WorldType.FLAT).environment(env).generator(chunkGenerator2).createWorld();
// Backup world
if (env.equals(Environment.NORMAL)) {
WorldCreator.name(worldName2 + "_bak").type(WorldType.FLAT).environment(env).generator(chunkGenerator2).createWorld();
}
WorldCreator.name(worldName2 + "_bak").type(WorldType.FLAT).environment(env).generator(chunkGenerator2).createWorld();
// Set spawn rates
if (w != null) {
setSpawnRates(w);
@ -216,7 +216,7 @@ public class Boxed extends GameModeAddon {
}
if (getSettings().getTicksPerMonsterSpawns() > 0) {
w.setTicksPerMonsterSpawns(getSettings().getTicksPerMonsterSpawns());
}
}
}
@Override
@ -229,7 +229,7 @@ public class Boxed extends GameModeAddon {
if (id != null && id.equals("delete")) {
return delChunks;
}
return chunkGenerator;
return worldName.endsWith("_nether") ? netherChunkGenerator : chunkGenerator;
}
@Override

View File

@ -146,16 +146,6 @@ public class Settings implements WorldSettings {
@ConfigEntry(path = "world.default-game-mode")
private GameMode defaultGameMode = GameMode.SURVIVAL;
@ConfigComment("The default biome for the overworld")
@ConfigEntry(path = "world.default-biome")
private Biome defaultBiome = Biome.PLAINS;
@ConfigComment("The default biome for the nether world (this may affect what mobs can spawn)")
@ConfigEntry(path = "world.default-nether-biome")
private Biome defaultNetherBiome = Enums.getIfPresent(Biome.class, "NETHER").or(Enums.getIfPresent(Biome.class, "NETHER_WASTES").or(Biome.BADLANDS));
@ConfigComment("The default biome for the end world (this may affect what mobs can spawn)")
@ConfigEntry(path = "world.default-end-biome")
private Biome defaultEndBiome = Biome.THE_END;
@ConfigComment("The maximum number of players a player can ban at any one time in this game mode.")
@ConfigComment("The permission boxed.ban.maxlimit.X where X is a number can also be used per player")
@ConfigComment("-1 = unlimited")
@ -624,7 +614,7 @@ public class Settings implements WorldSettings {
*/
@Override
public boolean isNetherIslands() {
return false;
return true;
}
/**
@ -1243,20 +1233,6 @@ public class Settings implements WorldSettings {
return false;
}
/**
* @return default biome
*/
public Biome getDefaultBiome() {
return defaultBiome;
}
/**
* @param defaultBiome the defaultBiome to set
*/
public void setDefaultBiome(Biome defaultBiome) {
this.defaultBiome = defaultBiome;
}
/**
* @return the banLimit
*/
@ -1647,34 +1623,6 @@ public class Settings implements WorldSettings {
this.mobLimitSettings = mobLimitSettings;
}
/**
* @return the defaultNetherBiome
*/
public Biome getDefaultNetherBiome() {
return defaultNetherBiome;
}
/**
* @param defaultNetherBiome the defaultNetherBiome to set
*/
public void setDefaultNetherBiome(Biome defaultNetherBiome) {
this.defaultNetherBiome = defaultNetherBiome;
}
/**
* @return the defaultEndBiome
*/
public Biome getDefaultEndBiome() {
return defaultEndBiome;
}
/**
* @param defaultEndBiome the defaultEndBiome to set
*/
public void setDefaultEndBiome(Biome defaultEndBiome) {
this.defaultEndBiome = defaultEndBiome;
}
/**
* @return the seed
*/

View File

@ -15,10 +15,14 @@ public class BoxedChunkGenerator {
private final WorldRef wordRef;
private final Boxed addon;
private WorldRef wordRefNether;
private WorldRef wordRefEnd;
public BoxedChunkGenerator(Boxed addon) {
this.addon = addon;
wordRef = WorldRef.ofName(addon.getSettings().getWorldName());
wordRefNether = WorldRef.ofName(addon.getSettings().getWorldName() + "_nether");
wordRefEnd = WorldRef.ofName(addon.getSettings().getWorldName() + "_end");
}
public ChunkGenerator getGenerator() {
@ -26,7 +30,7 @@ public class BoxedChunkGenerator {
.getInstance(addon.getPlugin(), 0, 5)
.createCustomGenerator(wordRef, generator -> {
// Set the noise generator
generator.setBaseNoiseGenerator(new BasicWorldGenerator(addon, addon.getSettings().getSeed()));
generator.setBaseNoiseGenerator(new OverWorldGenerator(addon, addon.getSettings().getSeed()));
if (addon.getSettings().isAllowStructures()) {
generator.getWorldDecorator().withoutDefaultDecorations(DecorationType.SURFACE_STRUCTURES);
}
@ -37,4 +41,20 @@ public class BoxedChunkGenerator {
});
}
public ChunkGenerator getNetherGenerator() {
return WorldGeneratorApi
.getInstance(addon.getPlugin(), 0, 5)
.createCustomGenerator(wordRefNether, generator -> {
// Set the noise generator
generator.setBaseNoiseGenerator(new NetherGenerator(addon, addon.getSettings().getSeed()));
if (addon.getSettings().isAllowStructures()) {
generator.getWorldDecorator().withoutDefaultDecorations(DecorationType.SURFACE_STRUCTURES);
}
if (addon.getSettings().isAllowStrongholds()) {
generator.getWorldDecorator().withoutDefaultDecorations(DecorationType.STRONGHOLDS);
}
generator.setBiomeGenerator(new NetherBiomeGenerator(addon));
});
}
}

View File

@ -0,0 +1,145 @@
package world.bentobox.boxed.generators;
import java.util.Collections;
import java.util.EnumMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.SortedMap;
import java.util.TreeMap;
import org.bukkit.block.Biome;
import org.bukkit.block.BlockFace;
import org.bukkit.util.Vector;
import nl.rutgerkok.worldgeneratorapi.BiomeGenerator;
import world.bentobox.boxed.Boxed;
/**
* @author tastybento
*
*/
public class NetherBiomeGenerator implements BiomeGenerator {
private static final double ONE = 0.05;
private static final double TWO = 0.25;
private static final double THREE = 0.5;
private static final double FOUR = 0.75;
private static final double FIVE = 1.0;
private static final double SIX = 1.25;
private static final double SEVEN = 1.50;
private static final double EIGHT = 1.75;
private static final double LAST = 2.0;
private static final TreeMap<Double, Biome> NORTH_EAST = new TreeMap<>();
static {
NORTH_EAST.put(ONE, Biome.BASALT_DELTAS);
NORTH_EAST.put(TWO, Biome.CRIMSON_FOREST);
NORTH_EAST.put(THREE, Biome.SOUL_SAND_VALLEY);
NORTH_EAST.put(FOUR, Biome.WARPED_FOREST);
NORTH_EAST.put(FIVE, Biome.BASALT_DELTAS);
NORTH_EAST.put(SIX, Biome.CRIMSON_FOREST);
NORTH_EAST.put(SEVEN, Biome.SOUL_SAND_VALLEY);
NORTH_EAST.put(EIGHT, Biome.WARPED_FOREST);
NORTH_EAST.put(LAST, Biome.NETHER_WASTES);
}
private static final TreeMap<Double, Biome> SOUTH_EAST = new TreeMap<>();
static {
SOUTH_EAST.put(ONE, Biome.NETHER_WASTES);
SOUTH_EAST.put(TWO, Biome.BASALT_DELTAS);
SOUTH_EAST.put(THREE, Biome.SOUL_SAND_VALLEY);
SOUTH_EAST.put(FOUR, Biome.WARPED_FOREST);
SOUTH_EAST.put(FIVE, Biome.NETHER_WASTES);
SOUTH_EAST.put(SIX, Biome.BASALT_DELTAS);
SOUTH_EAST.put(SEVEN, Biome.SOUL_SAND_VALLEY);
SOUTH_EAST.put(EIGHT, Biome.WARPED_FOREST);
SOUTH_EAST.put(LAST, Biome.CRIMSON_FOREST);
}
private static final TreeMap<Double, Biome> NORTH_WEST = new TreeMap<>();
static {
NORTH_WEST.put(ONE, Biome.NETHER_WASTES);
NORTH_WEST.put(TWO, Biome.NETHER_WASTES);
NORTH_WEST.put(THREE, Biome.SOUL_SAND_VALLEY);
NORTH_WEST.put(FOUR, Biome.WARPED_FOREST);
NORTH_WEST.put(FIVE, Biome.BASALT_DELTAS);
NORTH_WEST.put(SIX, Biome.CRIMSON_FOREST);
NORTH_WEST.put(SEVEN, Biome.SOUL_SAND_VALLEY);
NORTH_WEST.put(EIGHT, Biome.WARPED_FOREST);
NORTH_WEST.put(LAST, Biome.NETHER_WASTES);
}
private static final TreeMap<Double, Biome> SOUTH_WEST = new TreeMap<>();
static {
SOUTH_WEST.put(ONE, Biome.NETHER_WASTES);
SOUTH_WEST.put(TWO, Biome.SOUL_SAND_VALLEY);
SOUTH_WEST.put(THREE, Biome.WARPED_FOREST);
SOUTH_WEST.put(FOUR, Biome.SOUL_SAND_VALLEY);
SOUTH_WEST.put(FIVE, Biome.BASALT_DELTAS);
SOUTH_WEST.put(SIX, Biome.CRIMSON_FOREST);
SOUTH_WEST.put(SEVEN, Biome.WARPED_FOREST);
SOUTH_WEST.put(EIGHT, Biome.SOUL_SAND_VALLEY);
SOUTH_WEST.put(LAST, Biome.NETHER_WASTES);
}
private static final Map<BlockFace, SortedMap<Double, Biome>> QUADRANTS;
static {
Map<BlockFace, SortedMap<Double, Biome>> q = new EnumMap<>(BlockFace.class);
q.put(BlockFace.NORTH_EAST, NORTH_EAST);
q.put(BlockFace.NORTH_WEST, NORTH_WEST);
q.put(BlockFace.SOUTH_EAST, SOUTH_EAST);
q.put(BlockFace.SOUTH_WEST, SOUTH_WEST);
QUADRANTS = Collections.unmodifiableMap(q);
}
private final Boxed addon;
private final int dist;
private final int offsetX;
private final int offsetZ;
public NetherBiomeGenerator(Boxed boxed) {
this.addon = boxed;
dist = addon.getSettings().getIslandDistance();
offsetX = addon.getSettings().getIslandXOffset();
offsetZ = addon.getSettings().getIslandZOffset();
}
@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 ? Biome.NETHER_WASTES : en.getValue();
}
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

@ -0,0 +1,79 @@
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.util.noise.PerlinNoiseGenerator;
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 final PerlinNoiseGenerator mainNoiseGenerator;
private final Boxed addon;
private final YamlConfiguration config;
public NetherGenerator(Boxed addon, long seed) {
this.addon = addon;
// Initialize the noise generator based on the world seed
this.mainNoiseGenerator = new PerlinNoiseGenerator(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 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();
double noiseScaleHorizontal = 10D;
double height = 8D;
Biome biome = biomeGenerator.getZoomedOutBiome(scaledX, scaledZ);
if (biome == null) {
// edge of island
biome = Biome.NETHER_WASTES;
height = 6;
} else {
noiseScaleHorizontal = config.getDouble("nether.biomes." + biome.name() + ".scale", 10D);
height = config.getDouble("nether.biomes." + biome.name() + ".height", 8D);
}
double x = ((((double)scaledX*4) % dist) / 4) / noiseScaleHorizontal;
double z = ((((double)scaledZ*4) % 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;
}
// Ceiling
x = ((((double)scaledX*4) % dist) / 4);
z = ((((double)scaledZ*4) % dist) / 4);
for (int y = 15; y > height + 2; y--) {
double noise = this.mainNoiseGenerator.noise(x, y, z);
double heightOffset = y - height;
buffer[y] = noise + heightOffset;
}
}
}

View File

@ -14,14 +14,14 @@ import world.bentobox.boxed.Boxed;
* @author tastybento
*
*/
public class BasicWorldGenerator implements BaseNoiseGenerator {
public class OverWorldGenerator implements BaseNoiseGenerator {
private final SimplexNoiseGenerator mainNoiseGenerator;
private final Boxed addon;
private final YamlConfiguration config;
public BasicWorldGenerator(Boxed addon, long seed) {
public OverWorldGenerator(Boxed addon, long seed) {
this.addon = addon;
// Initialize the noise generator based on the world seed
this.mainNoiseGenerator = new SimplexNoiseGenerator(seed);

View File

@ -1,3 +1,20 @@
nether:
biomes:
NETHER_WASTES:
height: 8
scale: 5
BASALT_DELTAS:
height: 8
scale: 1
CRIMSON_FOREST:
height: 9
scale: 10
SOUL_SAND_VALLEY:
height: 9
scale: 16
WARPED_FOREST:
height: 10
scale: 10
biomes:
BADLANDS_PLATEAU:
height: 9

View File

@ -3,12 +3,12 @@
"icon": "PAPER",
"displayName": "Default bundle",
"description": [
"§bDefault bundle of blueprints"
"Boxed Starter Blocks"
],
"requirePermission": false,
"blueprints": {
"NORMAL": "island",
"NETHER": "bedrock",
"NETHER": "nether",
"THE_END": "bedrock"
},
"slot": 0

Binary file not shown.

View File

@ -68,12 +68,6 @@ world:
# The default game mode for this world. Players will be set to this mode when they create
# a new area for example. Options are SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR
default-game-mode: SURVIVAL
# The default biome for the overworld
default-biome: PLAINS
# The default biome for the nether world (this may affect what mobs can spawn)
default-nether-biome: NETHER_WASTES
# The default biome for the end world (this may affect what mobs can spawn)
default-end-biome: THE_END
# The maximum number of players a player can ban at any one time in this game mode.
# The permission boxed.ban.maxlimit.X where X is a number can also be used per player
# -1 = unlimited
@ -94,7 +88,7 @@ world:
# 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
create-and-link-portals: false
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.