Merge pull request #8 from BentoBoxWorld/tb-develop

Enables entity setting and config reloading
This commit is contained in:
BONNe 2019-02-02 22:49:59 +02:00 committed by GitHub
commit 7f60f203ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 2239 additions and 2327 deletions

1
.gitignore vendored
View File

@ -21,3 +21,4 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid* hs_err_pid*
/target/

View File

@ -50,6 +50,7 @@ public class CaveBlock extends GameModeAddon
{ {
super.onReload(); super.onReload();
this.loadSettings(); this.loadSettings();
this.chunkGenerator.reload();
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,14 @@
package world.bentobox.caveblock.generators; package world.bentobox.caveblock.generators;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
import java.util.*;
import world.bentobox.caveblock.CaveBlock; import world.bentobox.caveblock.CaveBlock;
import world.bentobox.caveblock.Settings; import world.bentobox.caveblock.Settings;
@ -21,190 +24,199 @@ import world.bentobox.caveblock.generators.populators.MaterialPopulator;
*/ */
public class ChunkGeneratorWorld extends ChunkGenerator public class ChunkGeneratorWorld extends ChunkGenerator
{ {
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Constructor // Section: Constructor
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
/** /**
* @param addon - CaveBlock object * @param addon - CaveBlock object
*/ */
public ChunkGeneratorWorld(CaveBlock addon) public ChunkGeneratorWorld(CaveBlock addon)
{ {
super(); super();
this.addon = addon; this.addon = addon;
this.settings = addon.getSettings(); this.settings = addon.getSettings();
this.blockPopulators = new ArrayList<>(1); reload();
}
this.blockPopulators.add(new MaterialPopulator(this.addon));
this.blockPopulators.add(new EntitiesPopulator(this.addon));
}
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Methods // Section: Methods
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
/** /**
* This method sets if given coordinates can be set as spawn location * This method sets if given coordinates can be set as spawn location
*/ */
@Override @Override
public boolean canSpawn(World world, int x, int z) public boolean canSpawn(World world, int x, int z)
{ {
return true; return true;
} }
/** /**
* This method generates given chunk. * This method generates given chunk.
* @param world World where chunk must be generated. * @param world World where chunk must be generated.
* @param random Random that allows define object randomness. * @param random Random that allows define object randomness.
* @param chunkX Chunk X coordinate. * @param chunkX Chunk X coordinate.
* @param chunkZ Chunk Z coordinate. * @param chunkZ Chunk Z coordinate.
* @param biomeGrid BiomeGrid that contains biomes. * @param biomeGrid BiomeGrid that contains biomes.
* @return new ChunkData for given chunk. * @return new ChunkData for given chunk.
*/ */
@Override @Override
public ChunkData generateChunkData(World world, public ChunkData generateChunkData(World world,
Random random, Random random,
int chunkX, int chunkX,
int chunkZ, int chunkZ,
ChunkGenerator.BiomeGrid biomeGrid) ChunkGenerator.BiomeGrid biomeGrid)
{ {
ChunkData result = this.createChunkData(world); ChunkData result = this.createChunkData(world);
// Populate chunk with necessary information // Populate chunk with necessary information
if (world.getEnvironment().equals(World.Environment.NETHER)) if (world.getEnvironment().equals(World.Environment.NETHER))
{ {
this.populateNetherChunk(result); this.populateNetherChunk(result);
} }
else if (world.getEnvironment().equals(World.Environment.THE_END)) else if (world.getEnvironment().equals(World.Environment.THE_END))
{ {
this.populateTheEndChunk(result); this.populateTheEndChunk(result);
} }
else else
{ {
this.populateOverWorldChunk(result, biomeGrid); this.populateOverWorldChunk(result, biomeGrid);
} }
return result; return result;
} }
/** /**
* This method populates The End world chunk data. * This method populates The End world chunk data.
* @param chunkData ChunkData that must be populated. * @param chunkData ChunkData that must be populated.
*/ */
private void populateTheEndChunk(ChunkData chunkData) private void populateTheEndChunk(ChunkData chunkData)
{ {
// because everything starts at 0 and ends at 255 // because everything starts at 0 and ends at 255
final int worldHeight = this.settings.getWorldDepth(); final int worldHeight = this.settings.getWorldDepth();
// Fill all blocks // Fill all blocks
chunkData.setRegion(0, 1, 0, chunkData.setRegion(0, 1, 0,
16, worldHeight - 1, 16, 16, worldHeight - 1, 16,
this.settings.getEndMainBlock()); this.settings.getEndMainBlock());
// Generate ground and ceiling. // Generate ground and ceiling.
chunkData.setRegion(0, 0, 0, chunkData.setRegion(0, 0, 0,
16, 1, 16, 16, 1, 16,
this.settings.isEndFloor() ? Material.BEDROCK : this.settings.getEndMainBlock()); this.settings.isEndFloor() ? Material.BEDROCK : this.settings.getEndMainBlock());
chunkData.setRegion(0, worldHeight - 1, 0, chunkData.setRegion(0, worldHeight - 1, 0,
16, worldHeight, 16, 16, worldHeight, 16,
this.settings.isEndRoof() ? Material.BEDROCK : this.settings.getEndMainBlock()); this.settings.isEndRoof() ? Material.BEDROCK : this.settings.getEndMainBlock());
} }
/** /**
* This method populates nether world chunk data. * This method populates nether world chunk data.
* @param chunkData ChunkData that must be populated. * @param chunkData ChunkData that must be populated.
*/ */
private void populateNetherChunk(ChunkData chunkData) private void populateNetherChunk(ChunkData chunkData)
{ {
// because everything starts at 0 and ends at 255 // because everything starts at 0 and ends at 255
final int worldHeight = this.settings.getWorldDepth(); final int worldHeight = this.settings.getWorldDepth();
// Fill all blocks // Fill all blocks
chunkData.setRegion(0, 1, 0, chunkData.setRegion(0, 1, 0,
16, worldHeight - 1, 16, 16, worldHeight - 1, 16,
this.settings.getNetherMainBlock()); this.settings.getNetherMainBlock());
// Generate ground and ceiling. // Generate ground and ceiling.
chunkData.setRegion(0, 0, 0, chunkData.setRegion(0, 0, 0,
16, 1, 16, 16, 1, 16,
this.settings.isNetherFloor() ? Material.BEDROCK : this.settings.getNetherMainBlock()); this.settings.isNetherFloor() ? Material.BEDROCK : this.settings.getNetherMainBlock());
chunkData.setRegion(0, worldHeight - 1, 0, chunkData.setRegion(0, worldHeight - 1, 0,
16, worldHeight, 16, 16, worldHeight, 16,
this.settings.isNetherRoof() ? Material.BEDROCK : this.settings.getNetherMainBlock()); this.settings.isNetherRoof() ? Material.BEDROCK : this.settings.getNetherMainBlock());
} }
/** /**
* This method populates Over world chunk data. * This method populates Over world chunk data.
* @param chunkData ChunkData that must be populated. * @param chunkData ChunkData that must be populated.
* @param biomeGrid BiomeGrid for this chunk. * @param biomeGrid BiomeGrid for this chunk.
*/ */
private void populateOverWorldChunk(ChunkData chunkData, BiomeGrid biomeGrid) private void populateOverWorldChunk(ChunkData chunkData, BiomeGrid biomeGrid)
{ {
// because everything starts at 0 and ends at 255 // because everything starts at 0 and ends at 255
final int worldHeight = this.settings.getWorldDepth(); final int worldHeight = this.settings.getWorldDepth();
// Fill all blocks // Fill all blocks
chunkData.setRegion(0, 1, 0, chunkData.setRegion(0, 1, 0,
16, worldHeight - 1, 16, 16, worldHeight - 1, 16,
this.settings.getNormalMainBlock()); this.settings.getNormalMainBlock());
// Generate ground and ceiling. // Generate ground and ceiling.
chunkData.setRegion(0, 0, 0, chunkData.setRegion(0, 0, 0,
16, 1, 16, 16, 1, 16,
this.settings.isNormalFloor() ? Material.BEDROCK : this.settings.getNormalMainBlock()); this.settings.isNormalFloor() ? Material.BEDROCK : this.settings.getNormalMainBlock());
chunkData.setRegion(0, worldHeight - 1, 0, chunkData.setRegion(0, worldHeight - 1, 0,
16, worldHeight, 16, 16, worldHeight, 16,
this.settings.isNormalRoof() ? Material.BEDROCK : this.settings.getNormalMainBlock()); this.settings.isNormalRoof() ? Material.BEDROCK : this.settings.getNormalMainBlock());
// Set biome // Set biome
for (int x = 0; x < 16; x++) for (int x = 0; x < 16; x++)
{ {
for (int z = 0; z < 16; z++) for (int z = 0; z < 16; z++)
{ {
biomeGrid.setBiome(x, z, this.settings.getDefaultBiome()); biomeGrid.setBiome(x, z, this.settings.getDefaultBiome());
} }
} }
} }
/** /**
* This method set world block populators. * This method set world block populators.
* @param world World where this must apply. * @param world World where this must apply.
* @return List with block populators. * @return List with block populators.
*/ */
@Override @Override
public List<BlockPopulator> getDefaultPopulators(final World world) public List<BlockPopulator> getDefaultPopulators(final World world)
{ {
return this.blockPopulators; return this.blockPopulators;
} }
/**
* Called when config is reloaded
*/
public void reload() {
this.blockPopulators = new ArrayList<>(2);
this.blockPopulators.add(new MaterialPopulator(this.addon));
this.blockPopulators.add(new EntitiesPopulator(this.addon));
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
// --------------------------------------------------------------------- /**
// Section: Variables * CaveBlock addon.
// --------------------------------------------------------------------- */
private CaveBlock addon;
/**
* Addon settings.
*/
private Settings settings;
/**
* This list contains block populators that will be applied after chunk is generated.
*/
private List<BlockPopulator> blockPopulators;
/**
* CaveBlock addon.
*/
private CaveBlock addon;
/**
* Addon settings.
*/
private Settings settings;
/**
* This list contains block populators that will be applied after chunk is generated.
*/
private List<BlockPopulator> blockPopulators;
} }

View File

@ -13,27 +13,23 @@ import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.World.Environment; import org.bukkit.World.Environment;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.bukkit.util.BoundingBox;
import world.bentobox.bentobox.util.Pair; import world.bentobox.bentobox.util.Pair;
import world.bentobox.caveblock.CaveBlock; import world.bentobox.caveblock.CaveBlock;
import world.bentobox.caveblock.Settings;
/** /**
* This class populates generated chunk with enitites by random chance. * This class populates generated chunk with entites by random chance.
*/ */
public class EntitiesPopulator extends BlockPopulator public class EntitiesPopulator extends BlockPopulator
{ {
private Map<Environment, Chances> chances;
private final int generationTry;
private int worldHeight;
/** /**
* This is default constructor * This is default constructor
* @param addon CaveBlock addon. * @param addon CaveBlock addon.
@ -41,18 +37,21 @@ public class EntitiesPopulator extends BlockPopulator
public EntitiesPopulator(CaveBlock addon) public EntitiesPopulator(CaveBlock addon)
{ {
this.addon = addon; this.addon = addon;
this.settings = addon.getSettings(); loadSettings();
}
public void loadSettings() {
// Set up chances // Set up chances
chances = new HashMap<>(); chances = new HashMap<>();
// Normal // Normal
chances.put(Environment.NORMAL, new Chances(this.getEntityMap(this.settings.getNormalBlocks()), this.settings.getNormalMainBlock())); chances.put(Environment.NORMAL, new Chances(this.getEntityMap(addon.getSettings().getNormalBlocks()), addon.getSettings().getNormalMainBlock()));
// Nether // Nether
chances.put(Environment.NETHER, new Chances(this.getEntityMap(this.settings.getNetherBlocks()), this.settings.getNetherMainBlock())); chances.put(Environment.NETHER, new Chances(this.getEntityMap(addon.getSettings().getNetherBlocks()), addon.getSettings().getNetherMainBlock()));
// End // End
chances.put(Environment.THE_END, new Chances(this.getEntityMap(this.settings.getEndBlocks()), this.settings.getEndMainBlock())); chances.put(Environment.THE_END, new Chances(this.getEntityMap(addon.getSettings().getEndBlocks()), addon.getSettings().getEndMainBlock()));
// Other settings // Other settings
generationTry = this.settings.getNumberOfBlockGenerationTries(); worldHeight = addon.getSettings().getWorldDepth() - 1;
worldHeight = this.settings.getWorldDepth() - 1;
} }
@ -65,20 +64,16 @@ public class EntitiesPopulator extends BlockPopulator
@Override @Override
public void populate(World world, Random random, Chunk chunk) public void populate(World world, Random random, Chunk chunk)
{ {
for (Map.Entry<EntityType, Pair<Integer, Integer>> entry : chances.get(world.getEnvironment()).entityChanceMap.entrySet()) for (Map.Entry<EntityType, Pair<Double, Integer>> entry : chances.get(world.getEnvironment()).entityChanceMap.entrySet())
{ {
for (int subY = 0; subY < worldHeight; subY += 16) for (int subY = 0; subY < worldHeight; subY += 16)
{ {
for (int tries = 0; tries < generationTry; tries++) // Use double so chance can be < 1
if (random.nextDouble() * 100 < entry.getValue().x)
{ {
if (random.nextInt(100) < entry.getValue().x) int y = Math.min(worldHeight - 2, subY + random.nextInt(15));
{ // Spawn only in middle of chunk because bounding box will grow out from here
int x = random.nextInt(15); this.tryToPlaceEntity(world, chunk.getBlock(7, y, 7), entry.getKey(), chances.get(world.getEnvironment()).mainMaterial);
int z = random.nextInt(15);
int y = Math.min(worldHeight - 2, subY + random.nextInt(15));
this.tryToPlaceEntity(world, chunk.getBlock(x, y, z), entry.getKey(), x, z, chances.get(world.getEnvironment()).mainMaterial);
}
} }
} }
} }
@ -90,9 +85,9 @@ public class EntitiesPopulator extends BlockPopulator
* @param objectList List with objects that contains data. * @param objectList List with objects that contains data.
* @return Map that contains entity, its rarity and pack size. * @return Map that contains entity, its rarity and pack size.
*/ */
private Map<EntityType, Pair<Integer, Integer>> getEntityMap(List<String> objectList) private Map<EntityType, Pair<Double, Integer>> getEntityMap(List<String> objectList)
{ {
Map<EntityType, Pair<Integer, Integer>> entityMap = new HashMap<>(objectList.size()); Map<EntityType, Pair<Double, Integer>> entityMap = new HashMap<>(objectList.size());
Map<String, EntityType> entityTypeMap = Arrays.stream(EntityType.values()). Map<String, EntityType> entityTypeMap = Arrays.stream(EntityType.values()).
collect(Collectors.toMap(Enum::name, collect(Collectors.toMap(Enum::name,
@ -111,147 +106,52 @@ public class EntitiesPopulator extends BlockPopulator
if (entity != null) if (entity != null)
{ {
entityMap.put(entity, entityMap.put(entity,
new Pair<>(Integer.parseInt(splitString[2]), Integer.parseInt(splitString[3]))); new Pair<>(Double.parseDouble(splitString[2]), Integer.parseInt(splitString[3])));
} }
}); });
return entityMap; return entityMap;
} }
/** /**
* This method checks if all chunks around given block is generated. * Places entities if there is room for them.
* @param world World in which block is located
* @param block Block that must be checked.
* @param x Block x-index in chunk
* @param z Block z-index in chunk
* @return true, if all chunks around given block are generated.
*/
private boolean isValidBlock(World world, Block block, int x, int z)
{
return x > 0 && x < 15 && z > 0 && z < 15 ||
world.isChunkGenerated(block.getX() + 1, block.getZ()) &&
world.isChunkGenerated(block.getX() - 1, block.getZ()) &&
world.isChunkGenerated(block.getX(), block.getZ() - 1) &&
world.isChunkGenerated(block.getX(), block.getZ() + 1);
}
/**
* This method is not completed. It must reserve space for entities to spawn, but
* current implementation just allows to spawn 2 high mobs that can be in single
* place.
* @param world - World were mob must be spawned. * @param world - World were mob must be spawned.
* @param block - Block that was choosed by random. * @param block - Block that was chosen by random.
* @param entity - Entity that must be spawned. * @param entity - Entity that must be spawned.
* @param x - ChunkX coordinate. * @param originalMaterial - replacement material.
* @param z - ChunkY coordinate.
* @param originalMaterial - replacement manterial.
*/ */
private void tryToPlaceEntity(World world, Block block, EntityType entity, int x, int z, Material originalMaterial) private void tryToPlaceEntity(World world, Block block, EntityType entity, Material originalMaterial)
{ {
if (this.isValidBlock(world, block, x, z) && block.getType().equals(originalMaterial)) if (block.getType().equals(originalMaterial)) {
{ // Spawn entity
if (entity.isAlive()) Entity e = world.spawnEntity(block.getLocation().add(0.5, 0, 0.5), entity);
{ if (e instanceof LivingEntity) {
int height = 0; // Do not despawn
int width = 0; ((LivingEntity)e).setRemoveWhenFarAway(false);
int length = 0;
boolean water = false;
switch (entity)
{
case SPIDER:
width = 1;
length = 1;
break;
case SLIME:
case ELDER_GUARDIAN:
case GHAST:
case MAGMA_CUBE:
case WITHER:
height = 2;
width = 2;
length = 2;
break;
case ENDERMAN:
case IRON_GOLEM:
height = 2;
break;
case WITHER_SKELETON:
case STRAY:
case HUSK:
case ZOMBIE_VILLAGER:
case EVOKER:
case VINDICATOR:
case ILLUSIONER:
case CREEPER:
case SKELETON:
case ZOMBIE:
case BLAZE:
case SNOWMAN:
case VILLAGER:
case PIG_ZOMBIE:
case WITCH:
case SHULKER:
case SHEEP:
case COW:
case MUSHROOM_COW:
height = 12;
break;
case SKELETON_HORSE:
case ZOMBIE_HORSE:
case DONKEY:
case MULE:
case HORSE:
case POLAR_BEAR:
case LLAMA:
height = 1;
width = 1;
break;
case GUARDIAN:
case SQUID:
case COD:
case SALMON:
case PUFFERFISH:
case TROPICAL_FISH:
water = true;
break;
case DROWNED:
case DOLPHIN:
water = true;
height = 1;
break;
default:
break;
}
Block otherBlock = world.getBlockAt(block.getX(), block.getY() + 1, block.getZ());
if (!otherBlock.getType().equals(originalMaterial))
{
otherBlock = world.getBlockAt(block.getX(), block.getY() - 1, block.getZ());
}
if (otherBlock.getType().equals(originalMaterial))
{
block.setType(Material.CAVE_AIR);
otherBlock.setType(Material.CAVE_AIR);
if (otherBlock.getY() < block.getY())
{
world.spawnEntity(otherBlock.getLocation(), entity);
}
else
{
world.spawnEntity(block.getLocation(), entity);
}
}
} }
else // Make space for entity based on the entity's size
{ BoundingBox bb = e.getBoundingBox();
block.setType(Material.CAVE_AIR); for (int x = (int) bb.getMinX(); x < bb.getMaxX(); x++) {
world.spawnEntity(block.getLocation(), entity); for (int z = (int) bb.getMinZ(); z < bb.getMaxZ(); z++) {
int y = (int) bb.getMinY();
Block b = world.getBlockAt(x, y, z);
for (; y < bb.getMaxY(); y++) {
if (addon.getSettings().isDebug()) {
addon.log("DEBUG: Entity spawn: " + world.getName() + " " + x + " " + y + " " + z + " " + e.getType());
}
b = world.getBlockAt(x, y, z);
if (!b.getType().equals(originalMaterial)) {
// Cannot place entity
e.remove();
return;
}
b.setType(WATER_ENTITIES.contains(entity) ? Material.WATER : Material.CAVE_AIR);
}
// Add air block on top for all water entities (required for dolphin, okay for others)
if (WATER_ENTITIES.contains(entity) && b.getRelative(BlockFace.UP).getType().equals(originalMaterial)) {
b.getRelative(BlockFace.UP).setType(Material.CAVE_AIR);
}
}
} }
} }
} }
@ -267,24 +167,32 @@ public class EntitiesPopulator extends BlockPopulator
*/ */
private CaveBlock addon; private CaveBlock addon;
/** private Map<Environment, Chances> chances;
* CaveBlock settings.
*/ private int worldHeight;
private Settings settings;
private final static List<EntityType> WATER_ENTITIES = Arrays.asList(EntityType.GUARDIAN,
EntityType.SQUID,
EntityType.COD,
EntityType.SALMON,
EntityType.PUFFERFISH,
EntityType.TROPICAL_FISH,
EntityType.DROWNED,
EntityType.DOLPHIN);
/** /**
* Chances class to store chances for environments and main material * Chances class to store chances for environments and main material
* *
*/ */
private class Chances { private class Chances {
final Map<EntityType, Pair<Integer, Integer>> entityChanceMap; final Map<EntityType, Pair<Double, Integer>> entityChanceMap;
final Material mainMaterial; final Material mainMaterial;
/** /**
* @param materialChanceMap * @param materialChanceMap
* @param mainMaterial * @param mainMaterial
*/ */
public Chances(Map<EntityType, Pair<Integer, Integer>> entityChanceMap, Material mainMaterial) { public Chances(Map<EntityType, Pair<Double, Integer>> entityChanceMap, Material mainMaterial) {
this.entityChanceMap = entityChanceMap; this.entityChanceMap = entityChanceMap;
this.mainMaterial = mainMaterial; this.mainMaterial = mainMaterial;
} }

View File

@ -16,7 +16,6 @@ import org.bukkit.generator.BlockPopulator;
import world.bentobox.bentobox.util.Pair; import world.bentobox.bentobox.util.Pair;
import world.bentobox.caveblock.CaveBlock; import world.bentobox.caveblock.CaveBlock;
import world.bentobox.caveblock.Settings;
/** /**
@ -24,11 +23,6 @@ import world.bentobox.caveblock.Settings;
*/ */
public class MaterialPopulator extends BlockPopulator public class MaterialPopulator extends BlockPopulator
{ {
private Map<Environment, Chances> chances;
private final int generationTry;
private int worldHeight;
/** /**
* This is default constructor * This is default constructor
@ -37,19 +31,25 @@ public class MaterialPopulator extends BlockPopulator
public MaterialPopulator(CaveBlock addon) public MaterialPopulator(CaveBlock addon)
{ {
this.addon = addon; this.addon = addon;
this.settings = addon.getSettings(); // Load settings
loadSettings();
}
/**
* Loads chances for Material Populator
*/
public void loadSettings() {
// Set up chances // Set up chances
chances = new HashMap<>(); chances = new HashMap<>();
// Normal // Normal
chances.put(Environment.NORMAL, new Chances(this.getMaterialMap(this.settings.getNormalBlocks()), this.settings.getNormalMainBlock())); chances.put(Environment.NORMAL, new Chances(this.getMaterialMap(addon.getSettings().getNormalBlocks()), addon.getSettings().getNormalMainBlock()));
// Nether // Nether
chances.put(Environment.NETHER, new Chances(this.getMaterialMap(this.settings.getNetherBlocks()), this.settings.getNetherMainBlock())); chances.put(Environment.NETHER, new Chances(this.getMaterialMap(addon.getSettings().getNetherBlocks()), addon.getSettings().getNetherMainBlock()));
// End // End
chances.put(Environment.THE_END, new Chances(this.getMaterialMap(this.settings.getEndBlocks()), this.settings.getEndMainBlock())); chances.put(Environment.THE_END, new Chances(this.getMaterialMap(addon.getSettings().getEndBlocks()), addon.getSettings().getEndMainBlock()));
// Other settings // Other settings
generationTry = this.settings.getNumberOfBlockGenerationTries(); worldHeight = addon.getSettings().getWorldDepth() - 1;
worldHeight = this.settings.getWorldDepth() - 1;
} }
@ -62,65 +62,67 @@ public class MaterialPopulator extends BlockPopulator
@Override @Override
public void populate(World world, Random random, Chunk chunk) public void populate(World world, Random random, Chunk chunk)
{ {
for (Map.Entry<Material, Pair<Integer, Integer>> entry : chances.get(world.getEnvironment()).materialChanceMap.entrySet()) for (Map.Entry<Material, Pair<Double, Integer>> entry : chances.get(world.getEnvironment()).materialChanceMap.entrySet())
{ {
for (int subY = 0; subY < worldHeight; subY += 16) for (int subY = 1; subY < worldHeight; subY += 16)
{ {
for (int tries = 0; tries < generationTry; tries++) if (random.nextDouble() * 100 < entry.getValue().x)
{ {
if (random.nextInt(100) < entry.getValue().x)
// Blocks must be 1 away from edge to avoid adjacent chunk loading
int x = random.nextInt(13) + 1;
int z = random.nextInt(13) + 1;
int y = Math.min(worldHeight - 2, subY + random.nextInt(15));
/*
* TODO: remove
if (addon.getSettings().isDebug()) {
addon.log("DEBUG: Material: " + world.getName() + " " + x + " " + y + " " + z + " " + entry.getKey());
}
*/
Block block = chunk.getBlock(x, y, z);
if (block.getType().equals(chances.get(world.getEnvironment()).mainMaterial))
{ {
int x = random.nextInt(15); int packSize = random.nextInt(entry.getValue().z);
int z = random.nextInt(15);
int y = Math.min(worldHeight - 2, subY + random.nextInt(15));
Block block = chunk.getBlock(x, y, z); boolean continuePlacing = true;
if (block.getType().equals(chances.get(world.getEnvironment()).mainMaterial) && while (continuePlacing)
this.isValidBlock(world, block, x, z))
{ {
int packSize = random.nextInt(entry.getValue().z); if (!block.getType().equals(entry.getKey()))
boolean continuePlacing = true;
while (continuePlacing)
{ {
if (!block.getType().equals(entry.getKey())) block.setType(entry.getKey());
{ packSize--;
block.setType(entry.getKey());
packSize--;
}
// The direction chooser
switch (random.nextInt(5))
{
case 0:
x = Math.min(15, x + 1);
break;
case 1:
y = Math.min(worldHeight - 2, y + 1);
break;
case 2:
z = Math.min(15, z + 1);
break;
case 3:
x = Math.max(0, x - 1);
break;
case 4:
y = Math.max(1, y - 1);
break;
case 5:
z = Math.max(0, z - 1);
break;
}
block = chunk.getBlock(x, y, z);
continuePlacing = this.isValidBlock(world, block, x, z) &&
packSize > 0 &&
(block.getType().equals(chances.get(world.getEnvironment()).mainMaterial) ||
block.getType().equals(entry.getKey()));
} }
// The direction chooser
switch (random.nextInt(5))
{
case 0:
x = Math.min(15, x + 1);
break;
case 1:
y = Math.min(worldHeight - 2, y + 1);
break;
case 2:
z = Math.min(15, z + 1);
break;
case 3:
x = Math.max(0, x - 1);
break;
case 4:
y = Math.max(1, y - 1);
break;
case 5:
z = Math.max(0, z - 1);
break;
}
block = chunk.getBlock(x, y, z);
continuePlacing = packSize > 0 &&
(block.getType().equals(chances.get(world.getEnvironment()).mainMaterial) ||
block.getType().equals(entry.getKey()));
} }
} }
} }
@ -128,33 +130,14 @@ public class MaterialPopulator extends BlockPopulator
} }
} }
/**
* This method checks if all chunks around given block is generated.
* @param world World in which block is located
* @param block Block that must be checked.
* @param x Block x-index in chunk
* @param z Block z-index in chunk
* @return true, if all chunks around given block are generated.
*/
private boolean isValidBlock(World world, Block block, int x, int z)
{
return x > 0 && x < 15 && z > 0 && z < 15 ||
world.isChunkGenerated(block.getX() + 1, block.getZ()) &&
world.isChunkGenerated(block.getX() - 1, block.getZ()) &&
world.isChunkGenerated(block.getX(), block.getZ() - 1) &&
world.isChunkGenerated(block.getX(), block.getZ() + 1);
}
/** /**
* This method returns material frequently and pack size map. * This method returns material frequently and pack size map.
* @param objectList List with objects that contains data. * @param objectList List with objects that contains data.
* @return Map that contains material, its rarity and pack size. * @return Map that contains material, its rarity and pack size.
*/ */
private Map<Material, Pair<Integer, Integer>> getMaterialMap(List<String> objectList) private Map<Material, Pair<Double, Integer>> getMaterialMap(List<String> objectList)
{ {
Map<Material, Pair<Integer, Integer>> materialMap = new HashMap<>(objectList.size()); Map<Material, Pair<Double, Integer>> materialMap = new HashMap<>(objectList.size());
// wrong material object. // wrong material object.
objectList.stream(). objectList.stream().
@ -167,7 +150,7 @@ public class MaterialPopulator extends BlockPopulator
if (material != null) if (material != null)
{ {
materialMap.put(material, materialMap.put(material,
new Pair<>(Integer.parseInt(splitString[2]), Integer.parseInt(splitString[3]))); new Pair<>(Double.parseDouble(splitString[2]), Integer.parseInt(splitString[3])));
} }
}); });
@ -185,25 +168,23 @@ public class MaterialPopulator extends BlockPopulator
*/ */
private CaveBlock addon; private CaveBlock addon;
/** private Map<Environment, Chances> chances;
* CaveBlock settings.
*/
private Settings settings;
private int worldHeight;
/** /**
* Chances class to store chances for environments and main material * Chances class to store chances for environments and main material
* *
*/ */
private class Chances { private class Chances {
final Map<Material, Pair<Integer, Integer>> materialChanceMap; final Map<Material, Pair<Double, Integer>> materialChanceMap;
final Material mainMaterial; final Material mainMaterial;
/** /**
* @param materialChanceMap * @param materialChanceMap
* @param mainMaterial * @param mainMaterial
*/ */
public Chances(Map<Material, Pair<Integer, Integer>> materialChanceMap, Material mainMaterial) { public Chances(Map<Material, Pair<Double, Integer>> materialChanceMap, Material mainMaterial) {
this.materialChanceMap = materialChanceMap; this.materialChanceMap = materialChanceMap;
this.mainMaterial = mainMaterial; this.mainMaterial = mainMaterial;
} }

View File

@ -11,11 +11,11 @@ world:
# World difficulty setting - PEACEFUL, EASY, NORMAL, HARD # World difficulty setting - PEACEFUL, EASY, NORMAL, HARD
# Other plugins may override this setting # Other plugins may override this setting
difficulty: NORMAL difficulty: NORMAL
# Radius of island in blocks. (So distance between islands is twice this) # Radius of cave in blocks. (So distance between caves is twice this)
# Will be rounded up to the nearest 16 blocks. # Will be rounded up to the nearest 16 blocks.
# It is the same for every dimension : Overworld, Nether and End. # 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. # This value cannot be changed mid-game and the plugin will not start if it is different.
distance-between-islands: 64 distance-between-caves: 64
# Default protection range radius in blocks. Cannot be larger than distance. # Default protection range radius in blocks. Cannot be larger than distance.
# Admins can change protection sizes for players individually using /cbadmin range set <player> <new range> # Admins can change protection sizes for players individually using /cbadmin range set <player> <new range>
# or set this permission: caveblock.island.range.<number> # or set this permission: caveblock.island.range.<number>
@ -29,18 +29,13 @@ world:
start-z: 0 start-z: 0
offset-x: 0 offset-x: 0
offset-z: 0 offset-z: 0
# Island height - Lowest is 5. # Cave height - Lowest is 5.
# It is the y coordinate of the bedrock block in the schem. # It is the y coordinate of the bedrock block in the schem.
island-height: 60 cave-height: 60
# Use your own world generator for this world. # Use your own world generator for this world.
# In this case, the plugin will not generate anything. # In this case, the plugin will not generate anything.
# /!\ This feature is experimental and might not work as expected or might not work at all. # /!\ This feature is experimental and might not work as expected or might not work at all.
use-own-generator: true use-own-generator: true
# Sea height (don't changes this mid-game unless you delete the world)
# Minimum is 0, which means you are playing CaveBlock!
# If sea height is less than about 10, then players will drop right through it
# if it exists. Makes for an interesting variation on caveblock.
sea-height: 0
# Maximum number of islands in the world. Set to -1 or 0 for unlimited. # Maximum number of islands in the world. Set to -1 or 0 for unlimited.
# If the number of islands is greater than this number, it will stop players from creating islands. # If the number of islands is greater than this number, it will stop players from creating islands.
max-islands: 0 max-islands: 0
@ -53,14 +48,14 @@ world:
# The permission acidisland.ban.maxlimit.X where X is a number can also be used per player # The permission acidisland.ban.maxlimit.X where X is a number can also be used per player
# -1 = unlimited # -1 = unlimited
ban-limit: -1 ban-limit: -1
# #
# This is cave... no height... only depth. Max 256. # This is cave... no height... only depth. Max 256.
# Should not be less then island height. # Should not be less then island height.
world-depth: 256 world-depth: 256
# This indicate how many times block should be tried to generate. # This indicate how many times block should be tried to generate.
generation-tries: 2 generation-tries: 2
normal: normal:
# #
# Make over world roof of bedrock, if false, it will be made from stone # Make over world roof of bedrock, if false, it will be made from stone
roof: true roof: true
# Make over world floor of bedrock, if false, it will be made from stone # Make over world floor of bedrock, if false, it will be made from stone
@ -74,11 +69,11 @@ world:
# Entities spawned via generator are not protected from despawing. # Entities spawned via generator are not protected from despawing.
# Working only with 2 high mobs currently. # Working only with 2 high mobs currently.
# Example: # Example:
# MATERIAL:DIAMOND:100:5 - means there is 100% chace of spawing diamonds # MATERIAL:DIAMOND_ORE:100:5 - means there is 100% chace of spawing diamonds
# where max amount in pack are 5 per each subchunk! # where max amount in pack are 5 per each subchunk!
blocks: blocks:
- MATERIAL:DIAMOND_ORE:1:3 - MATERIAL:DIAMOND_ORE:1:5
- MATERIAL:GOLD_ORE:5:4 - MATERIAL:GOLD_ORE:1:4
- MATERIAL:IRON_ORE:5:4 - MATERIAL:IRON_ORE:5:4
- MATERIAL:COAL_ORE:10:6 - MATERIAL:COAL_ORE:10:6
- MATERIAL:EMERALD_ORE:1:1 - MATERIAL:EMERALD_ORE:1:1
@ -88,6 +83,9 @@ world:
- MATERIAL:GRANITE:20:10 - MATERIAL:GRANITE:20:10
- MATERIAL:ANDESITE:20:10 - MATERIAL:ANDESITE:20:10
- MATERIAL:DIORITE:30:8 - MATERIAL:DIORITE:30:8
- ENTITY:ZOMBIE:1:1
- ENTITY:DOLPHIN:0.1:1
- ENTITY:CAVE_SPIDER:1:1
nether: nether:
# Generate Nether - if this is false, the nether world will not be made and access to # Generate Nether - if this is false, the nether world will not be made and access to
# the nether will not occur. Other plugins may still enable portal usage. # the nether will not occur. Other plugins may still enable portal usage.
@ -118,14 +116,19 @@ world:
# Entities spawned via generator are not protected from despawing. # Entities spawned via generator are not protected from despawing.
# Working only with 2 high mobs currently. # Working only with 2 high mobs currently.
# Example: # Example:
# MATERIAL:DIAMOND:100:5 - means there is 100% chace of spawing diamonds # MATERIAL:DIAMOND_ORE:100:5 - means there is 100% chace of spawing diamonds
# where max amount in pack are 5 per each subchunk! # where max amount in pack are 5 per each subchunk!
blocks: blocks:
- MATERIAL:QUARTZ_ORE:30:5 - MATERIAL:QUARTZ_ORE:30:5
- MATERIAL:SOUL_SAND:40:10 - MATERIAL:SOUL_SAND:40:10
- MATERIAL:MAGMA_BLOCK:10:3 - MATERIAL:MAGMA_BLOCK:10:3
- MATERIAL:GLOWSTONE:20:8 - MATERIAL:GLOWSTONE:20:8
- MATERIAL:NETHER_BRICK:10:5
- MATERIAL:LAVA:10:1 - MATERIAL:LAVA:10:1
- ENTITY:MAGMA_CUBE:0.5:1
- ENTITY:GHAST:0.1:1
- ENTITY:WITHER_SKELETON:0.1:1
- MATERIAL:FIRE:10:1
end: end:
generate: true generate: true
islands: true islands: true
@ -144,14 +147,16 @@ world:
# Entities spawned via generator are not protected from despawing. # Entities spawned via generator are not protected from despawing.
# Working only with 2 high mobs currently. # Working only with 2 high mobs currently.
# Example: # Example:
# MATERIAL:DIAMOND:100:5 - means there is 100% chace of spawing diamonds # MATERIAL:DIAMOND_ORE:100:5 - means there is 100% chace of spawing diamonds
# where max amount in pack are 5 per each subchunk! # where max amount in pack are 5 per each subchunk!
blocks: blocks:
- ENTITY:SHULKER:1:1 - ENTITY:SHULKER:0.2:1
- MATERIAL:OBSIDIAN:1:1
- MATERIAL:CHORUS_FRUIT:1:3
# Mob white list - these mobs will NOT be removed when logging in or doing /cave # Mob white list - these mobs will NOT be removed when logging in or doing /cave
remove-mobs-whitelist: remove-mobs-whitelist:
- ZOMBIE_VILLAGER
- WITHER - WITHER
- ZOMBIE_VILLAGER
- PIG_ZOMBIE - PIG_ZOMBIE
- ENDERMAN - ENDERMAN
# World flags. These are boolean settings for various flags for this world # World flags. These are boolean settings for various flags for this world
@ -193,8 +198,8 @@ world:
FROST_WALKER: 500 FROST_WALKER: 500
COLLECT_LAVA: 500 COLLECT_LAVA: 500
LEVER: 500 LEVER: 500
HURT_MONSTERS: 0
RIDING: 500 RIDING: 500
HURT_MONSTERS: 0
NAME_TAG: 500 NAME_TAG: 500
ARMOR_STAND: 500 ARMOR_STAND: 500
TRADING: 0 TRADING: 0
@ -202,8 +207,8 @@ world:
ITEM_DROP: 0 ITEM_DROP: 0
NOTE_BLOCK: 0 NOTE_BLOCK: 0
NETHER_PORTAL: 500 NETHER_PORTAL: 500
ITEM_PICKUP: 0
CROP_TRAMPLE: 500 CROP_TRAMPLE: 500
ITEM_PICKUP: 0
BREWING: 500 BREWING: 500
DROPPER: 500 DROPPER: 500
COLLECT_WATER: 500 COLLECT_WATER: 500
@ -215,26 +220,27 @@ world:
PLACE_BLOCKS: 500 PLACE_BLOCKS: 500
ITEM_FRAME: 500 ITEM_FRAME: 500
CRAFTING: 0 CRAFTING: 0
SHEARING: 500
ENCHANTING: 0 ENCHANTING: 0
SPAWN_EGGS: 500 SHEARING: 500
BED: 500 BED: 500
SPAWN_EGGS: 500
MILKING: 0 MILKING: 0
DISPENSER: 500 DISPENSER: 500
GATE: 0 GATE: 0
EXPERIENCE_PICKUP: 500 EXPERIENCE_PICKUP: 500
HOPPER: 500 HOPPER: 500
LEASH: 500 LEASH: 500
MOUNT_INVENTORY: 500
BREAK_BLOCKS: 500 BREAK_BLOCKS: 500
MOUNT_INVENTORY: 500
CHORUS_FRUIT: 500 CHORUS_FRUIT: 500
CONTAINER: 500 CONTAINER: 500
POTION_THROWING: 500
JUKEBOX: 500 JUKEBOX: 500
# These are the default settings for new islands # These are the default settings for new islands
default-island-settings: default-island-settings:
PVP_END: false PVP_END: false
ANIMAL_SPAWN: true
PVP_NETHER: false PVP_NETHER: false
ANIMAL_SPAWN: true
MONSTER_SPAWN: true MONSTER_SPAWN: true
FIRE_SPREAD: true FIRE_SPREAD: true
PVP_OVERWORLD: false PVP_OVERWORLD: false
@ -247,7 +253,7 @@ world:
- spawnmob - spawnmob
island: island:
# Default max team size # Default max team size
# Permission size cannot be less than the default below. # Permission size cannot be less than the default below.
max-team-size: 4 max-team-size: 4
# Default maximum number of homes a player can have. Min = 1 # Default maximum number of homes a player can have. Min = 1
# Accessed via /cave sethome <number> or /cave go <number> # Accessed via /cave sethome <number> or /cave go <number>
@ -350,4 +356,5 @@ panel:
do-not-edit-these-settings: do-not-edit-these-settings:
# These settings should not be edited # These settings should not be edited
reset-epoch: 0 reset-epoch: 0
debug: false
uniqueId: config uniqueId: config