From f6c1bc7d7fe03bcd13634f8e18ec65aa21530f34 Mon Sep 17 00:00:00 2001 From: tastybento Date: Fri, 1 Feb 2019 12:29:28 -0800 Subject: [PATCH] Makes chunk population more efficient Adds locale text. --- .../world/bentobox/caveblock/CaveBlock.java | 352 ++++++------- .../populators/EntitiesPopulator.java | 481 +++++++++--------- .../populators/MaterialPopulator.java | 323 ++++++------ src/main/resources/locales/en-US.yml | 224 ++++++++ 4 files changed, 822 insertions(+), 558 deletions(-) diff --git a/src/main/java/world/bentobox/caveblock/CaveBlock.java b/src/main/java/world/bentobox/caveblock/CaveBlock.java index b18dd1a..1fe9685 100644 --- a/src/main/java/world/bentobox/caveblock/CaveBlock.java +++ b/src/main/java/world/bentobox/caveblock/CaveBlock.java @@ -17,218 +17,218 @@ import world.bentobox.caveblock.generators.ChunkGeneratorWorld; public class CaveBlock extends GameModeAddon { - /** - * Executes code when loading the addon. This is called before {@link #onEnable()}. This should preferably - * be used to setup configuration and worlds. - */ - @Override - public void onLoad() - { - super.onLoad(); + /** + * Executes code when loading the addon. This is called before {@link #onEnable()}. This should preferably + * be used to setup configuration and worlds. + */ + @Override + public void onLoad() + { + super.onLoad(); - this.saveDefaultConfig(); - this.loadSettings(); - } + this.saveDefaultConfig(); + this.loadSettings(); + } - /** - * Executes code when enabling the addon. This is called after {@link #onLoad()}. - */ - @Override - public void onEnable() - { - this.playerCommand = new IslandCommand(this); - this.adminCommand = new AdminCommand(this); - } + /** + * Executes code when enabling the addon. This is called after {@link #onLoad()}. + */ + @Override + public void onEnable() + { + this.playerCommand = new IslandCommand(this); + this.adminCommand = new AdminCommand(this); + } - /** - * Executes code when reloading the addon. - */ - @Override - public void onReload() - { - super.onReload(); - this.loadSettings(); - } + /** + * Executes code when reloading the addon. + */ + @Override + public void onReload() + { + super.onReload(); + this.loadSettings(); + } - /** - * Executes code when disabling the addon. - */ - @Override - public void onDisable() - { - if (this.settings != null) - { - new Config<>(this, Settings.class).saveConfigObject(this.settings); - } - } + /** + * Executes code when disabling the addon. + */ + @Override + public void onDisable() + { + if (this.settings != null) + { + new Config<>(this, Settings.class).saveConfigObject(this.settings); + } + } - /** - * This method loads CaveBlock settings - */ - private void loadSettings() - { - this.settings = new Config<>(this, Settings.class).loadConfigObject(); + /** + * This method loads CaveBlock settings + */ + private void loadSettings() + { + this.settings = new Config<>(this, Settings.class).loadConfigObject(); - if (this.settings == null) - { - // Disable - this.logError("CaveBlock settings could not load! Addon disabled."); - this.setState(State.DISABLED); - } - } + if (this.settings == null) + { + // Disable + this.logError("CaveBlock settings could not load! Addon disabled."); + this.setState(State.DISABLED); + } + } -// --------------------------------------------------------------------- -// Section: World generators -// --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Section: World generators + // --------------------------------------------------------------------- - /** - * Make the worlds for this GameMode in this method. BentoBox will call it after onLoad() and before - * onEnable(). {@link #islandWorld} must be created and assigned, {@link #netherWorld} and {@link - * #endWorld} are optional and may be null. - */ - @Override - public void createWorlds() - { - String worldName = this.settings.getWorldName(); + /** + * Make the worlds for this GameMode in this method. BentoBox will call it after onLoad() and before + * onEnable(). {@link #islandWorld} must be created and assigned, {@link #netherWorld} and {@link + * #endWorld} are optional and may be null. + */ + @Override + public void createWorlds() + { + String worldName = this.settings.getWorldName(); - if (this.getServer().getWorld(worldName) == null) - { - this.getLogger().info("Creating CaveBlock world ..."); - } + if (this.getServer().getWorld(worldName) == null) + { + this.getLogger().info("Creating CaveBlock world ..."); + } - this.chunkGenerator = new ChunkGeneratorWorld(this); + this.chunkGenerator = new ChunkGeneratorWorld(this); - // Create the world if it does not exist - this.islandWorld = WorldCreator.name(worldName). - type(WorldType.FLAT). - environment(World.Environment.NORMAL). - generator(new ChunkGeneratorWorld(this)). - createWorld(); + // Create the world if it does not exist + this.islandWorld = WorldCreator.name(worldName). + type(WorldType.FLAT). + environment(World.Environment.NORMAL). + generator(this.chunkGenerator). + createWorld(); - // Make the nether if it does not exist - if (this.settings.isNetherGenerate()) - { - if (this.getServer().getWorld(worldName + NETHER) == null) - { - this.log("Creating CaveBlock's Nether..."); - } + // Make the nether if it does not exist + if (this.settings.isNetherGenerate()) + { + if (this.getServer().getWorld(worldName + NETHER) == null) + { + this.log("Creating CaveBlock's Nether..."); + } - if (!this.settings.isNetherIslands()) - { - this.netherWorld = WorldCreator.name(worldName + NETHER). - type(WorldType.NORMAL). - environment(World.Environment.NETHER). - createWorld(); - } - else - { - this.netherWorld = WorldCreator.name(worldName + NETHER). - type(WorldType.FLAT). - generator(new ChunkGeneratorWorld(this)). - environment(World.Environment.NETHER). - createWorld(); - } - } + if (!this.settings.isNetherIslands()) + { + this.netherWorld = WorldCreator.name(worldName + NETHER). + type(WorldType.NORMAL). + environment(World.Environment.NETHER). + createWorld(); + } + else + { + this.netherWorld = WorldCreator.name(worldName + NETHER). + type(WorldType.FLAT). + generator(this.chunkGenerator). + environment(World.Environment.NETHER). + createWorld(); + } + } - // Make the end if it does not exist - if (this.settings.isEndGenerate()) - { - if (this.getServer().getWorld(worldName + THE_END) == null) - { - this.log("Creating CaveBlock's End World..."); - } - if (!this.settings.isEndIslands()) - { - this.endWorld = WorldCreator.name(worldName + THE_END). - type(WorldType.NORMAL). - environment(World.Environment.THE_END). - createWorld(); - } - else - { - this.endWorld = WorldCreator.name(worldName + THE_END). - type(WorldType.FLAT). - generator(new ChunkGeneratorWorld(this)). - environment(World.Environment.THE_END). - createWorld(); - } - } - } + // Make the end if it does not exist + if (this.settings.isEndGenerate()) + { + if (this.getServer().getWorld(worldName + THE_END) == null) + { + this.log("Creating CaveBlock's End World..."); + } + if (!this.settings.isEndIslands()) + { + this.endWorld = WorldCreator.name(worldName + THE_END). + type(WorldType.NORMAL). + environment(World.Environment.THE_END). + createWorld(); + } + else + { + this.endWorld = WorldCreator.name(worldName + THE_END). + type(WorldType.FLAT). + generator(this.chunkGenerator). + environment(World.Environment.THE_END). + createWorld(); + } + } + } - /** - * Defines the world generator for this game mode - * - * @param worldName - name of world that this applies to - * @param id - id if any - * @return Chunk generator - * @since 1.2.0 - */ - @Override - public @NonNull ChunkGenerator getDefaultWorldGenerator(String worldName, String id) - { - return this.chunkGenerator; - } + /** + * Defines the world generator for this game mode + * + * @param worldName - name of world that this applies to + * @param id - id if any + * @return Chunk generator + * @since 1.2.0 + */ + @Override + public @NonNull ChunkGenerator getDefaultWorldGenerator(String worldName, String id) + { + return this.chunkGenerator; + } -// --------------------------------------------------------------------- -// Section: Getters -// --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Section: Getters + // --------------------------------------------------------------------- - /** - * @return WorldSettings for this GameMode - */ - @Override - public WorldSettings getWorldSettings() - { - return this.settings; - } + /** + * @return WorldSettings for this GameMode + */ + @Override + public WorldSettings getWorldSettings() + { + return this.settings; + } - /** - * @return Settings for this GameMode - */ - public Settings getSettings() - { - return this.settings; - } + /** + * @return Settings for this GameMode + */ + public Settings getSettings() + { + return this.settings; + } -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- - /** - * This stores CaveBlock addon settings. - */ - private Settings settings; + /** + * This stores CaveBlock addon settings. + */ + private Settings settings; - /** - * This stores CaveBlock addon WorldGenerator. - */ - private ChunkGeneratorWorld chunkGenerator; + /** + * This stores CaveBlock addon WorldGenerator. + */ + private ChunkGeneratorWorld chunkGenerator; -// --------------------------------------------------------------------- -// Section: Constants -// --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Section: Constants + // --------------------------------------------------------------------- - /** - * String for nether world. - */ - private static final String NETHER = "_nether"; + /** + * String for nether world. + */ + private static final String NETHER = "_nether"; - /** - * String for the end world. - */ - private static final String THE_END = "_the_end"; + /** + * String for the end world. + */ + private static final String THE_END = "_the_end"; } diff --git a/src/main/java/world/bentobox/caveblock/generators/populators/EntitiesPopulator.java b/src/main/java/world/bentobox/caveblock/generators/populators/EntitiesPopulator.java index 2a8db24..6b0c08f 100644 --- a/src/main/java/world/bentobox/caveblock/generators/populators/EntitiesPopulator.java +++ b/src/main/java/world/bentobox/caveblock/generators/populators/EntitiesPopulator.java @@ -1,14 +1,20 @@ package world.bentobox.caveblock.generators.populators; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.stream.Collectors; + import org.bukkit.Chunk; import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.World.Environment; import org.bukkit.block.Block; import org.bukkit.entity.EntityType; import org.bukkit.generator.BlockPopulator; -import java.util.*; -import java.util.stream.Collectors; import world.bentobox.bentobox.util.Pair; import world.bentobox.caveblock.CaveBlock; @@ -20,250 +26,267 @@ import world.bentobox.caveblock.Settings; */ public class EntitiesPopulator extends BlockPopulator { - /** - * This is default constructor - * @param addon CaveBlock addon. - */ - public EntitiesPopulator(CaveBlock addon) - { - this.addon = addon; - this.settings = addon.getSettings(); - } + + private Map chances; + + private final int generationTry; + + private int worldHeight; - /** - * This method populates chunk with entities. - * @param world World where population must be. - * @param random Randomness - * @param chunk Chunk were populator operates. - */ - @Override - public void populate(World world, Random random, Chunk chunk) - { - Map> entityChanceMap; - Material mainMaterial; - - if (world.getEnvironment().equals(World.Environment.NETHER)) - { - entityChanceMap = this.getEntityMap(this.settings.getNetherBlocks()); - mainMaterial = this.settings.getNetherMainBlock(); - } - else if (world.getEnvironment().equals(World.Environment.THE_END)) - { - entityChanceMap = this.getEntityMap(this.settings.getEndBlocks()); - mainMaterial = this.settings.getEndMainBlock(); - } - else - { - entityChanceMap = this.getEntityMap(this.settings.getNormalBlocks()); - mainMaterial = this.settings.getNormalMainBlock(); - } - - final int generationTry = this.settings.getNumberOfBlockGenerationTries(); - final int worldHeight = this.settings.getWorldDepth() - 1; - - for (Map.Entry> entry : entityChanceMap.entrySet()) - { - for (int subY = 0; subY < worldHeight; subY += 16) - { - for (int tries = 0; tries < generationTry; tries++) - { - if (random.nextInt(100) < entry.getValue().x) - { - int x = random.nextInt(15); - 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, mainMaterial); - } - } - } - } - } + /** + * This is default constructor + * @param addon CaveBlock addon. + */ + public EntitiesPopulator(CaveBlock addon) + { + this.addon = addon; + this.settings = addon.getSettings(); + // Set up chances + chances = new HashMap<>(); + // Normal + chances.put(Environment.NORMAL, new Chances(this.getEntityMap(this.settings.getNormalBlocks()), this.settings.getNormalMainBlock())); + // Nether + chances.put(Environment.NETHER, new Chances(this.getEntityMap(this.settings.getNetherBlocks()), this.settings.getNetherMainBlock())); + // End + chances.put(Environment.THE_END, new Chances(this.getEntityMap(this.settings.getEndBlocks()), this.settings.getEndMainBlock())); + // Other settings + generationTry = this.settings.getNumberOfBlockGenerationTries(); + worldHeight = this.settings.getWorldDepth() - 1; + } - /** - * This method returns Entity frequently and pack size map. - * @param objectList List with objects that contains data. - * @return Map that contains entity, its rarity and pack size. - */ - private Map> getEntityMap(List objectList) - { - Map> entityMap = new HashMap<>(objectList.size()); + /** + * This method populates chunk with entities. + * @param world World where population must be. + * @param random Randomness + * @param chunk Chunk were populator operates. + */ + @Override + public void populate(World world, Random random, Chunk chunk) + { + for (Map.Entry> entry : chances.get(world.getEnvironment()).entityChanceMap.entrySet()) + { + for (int subY = 0; subY < worldHeight; subY += 16) + { + for (int tries = 0; tries < generationTry; tries++) + { + if (random.nextInt(100) < entry.getValue().x) + { + int x = random.nextInt(15); + int z = random.nextInt(15); + int y = Math.min(worldHeight - 2, subY + random.nextInt(15)); - Map entityTypeMap = Arrays.stream(EntityType.values()). - collect(Collectors.toMap(Enum::name, - entityType -> entityType, - (a, b) -> b, - () -> new HashMap<>(EntityType.values().length))); - - // wrong material object. - objectList.stream(). - filter(object -> object.startsWith("ENTITY")). - map(object -> object.split(":")). - filter(splitString -> splitString.length == 4). - forEach(splitString -> { - EntityType entity = entityTypeMap.getOrDefault(splitString[1], null); - - if (entity != null) - { - entityMap.put(entity, - new Pair<>(Integer.parseInt(splitString[2]), Integer.parseInt(splitString[3]))); - } - }); - - return entityMap; - } + this.tryToPlaceEntity(world, chunk.getBlock(x, y, z), entry.getKey(), x, z, chances.get(world.getEnvironment()).mainMaterial); + } + } + } + } + } - /** - * 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 Entity frequently and pack size map. + * @param objectList List with objects that contains data. + * @return Map that contains entity, its rarity and pack size. + */ + private Map> getEntityMap(List objectList) + { + Map> entityMap = new HashMap<>(objectList.size()); + + Map entityTypeMap = Arrays.stream(EntityType.values()). + collect(Collectors.toMap(Enum::name, + entityType -> entityType, + (a, b) -> b, + () -> new HashMap<>(EntityType.values().length))); + + // wrong material object. + objectList.stream(). + filter(object -> object.startsWith("ENTITY")). + map(object -> object.split(":")). + filter(splitString -> splitString.length == 4). + forEach(splitString -> { + EntityType entity = entityTypeMap.getOrDefault(splitString[1], null); + + if (entity != null) + { + entityMap.put(entity, + new Pair<>(Integer.parseInt(splitString[2]), Integer.parseInt(splitString[3]))); + } + }); + + return entityMap; + } - /** - * 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 block - Block that was choosed by random. - * @param entity - Entity that must be spawned. - * @param x - ChunkX coordinate. - * @param z - ChunkY coordinate. - * @param originalMaterial - replacement manterial. - */ - private void tryToPlaceEntity(World world, Block block, EntityType entity, int x, int z, Material originalMaterial) - { - if (this.isValidBlock(world, block, x, z) && block.getType().equals(originalMaterial)) - { - if (entity.isAlive()) - { - int height = 0; - int width = 0; - int length = 0; - boolean water = false; + /** + * 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); + } - 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; - } - Block otherBlock = world.getBlockAt(block.getX(), block.getY() + 1, block.getZ()); + /** + * 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 block - Block that was choosed by random. + * @param entity - Entity that must be spawned. + * @param x - ChunkX coordinate. + * @param z - ChunkY coordinate. + * @param originalMaterial - replacement manterial. + */ + private void tryToPlaceEntity(World world, Block block, EntityType entity, int x, int z, Material originalMaterial) + { + if (this.isValidBlock(world, block, x, z) && block.getType().equals(originalMaterial)) + { + if (entity.isAlive()) + { + int height = 0; + int width = 0; + int length = 0; + boolean water = false; - if (!otherBlock.getType().equals(originalMaterial)) - { - otherBlock = world.getBlockAt(block.getX(), block.getY() - 1, block.getZ()); - } + 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; + } - if (otherBlock.getType().equals(originalMaterial)) - { - block.setType(Material.CAVE_AIR); - otherBlock.setType(Material.CAVE_AIR); + Block otherBlock = world.getBlockAt(block.getX(), block.getY() + 1, block.getZ()); - if (otherBlock.getY() < block.getY()) - { - world.spawnEntity(otherBlock.getLocation(), entity); - } - else - { - world.spawnEntity(block.getLocation(), entity); - } - } - } - else - { - block.setType(Material.CAVE_AIR); - world.spawnEntity(block.getLocation(), entity); - } - } - } + 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 + { + block.setType(Material.CAVE_AIR); + world.spawnEntity(block.getLocation(), entity); + } + } + } -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- - /** - * CaveBlock addon. - */ - private CaveBlock addon; + /** + * CaveBlock addon. + */ + private CaveBlock addon; - /** - * CaveBlock settings. - */ - private Settings settings; + /** + * CaveBlock settings. + */ + private Settings settings; + + /** + * Chances class to store chances for environments and main material + * + */ + private class Chances { + final Map> entityChanceMap; + final Material mainMaterial; + + /** + * @param materialChanceMap + * @param mainMaterial + */ + public Chances(Map> entityChanceMap, Material mainMaterial) { + this.entityChanceMap = entityChanceMap; + this.mainMaterial = mainMaterial; + } + } } diff --git a/src/main/java/world/bentobox/caveblock/generators/populators/MaterialPopulator.java b/src/main/java/world/bentobox/caveblock/generators/populators/MaterialPopulator.java index b0b26ee..855ce75 100644 --- a/src/main/java/world/bentobox/caveblock/generators/populators/MaterialPopulator.java +++ b/src/main/java/world/bentobox/caveblock/generators/populators/MaterialPopulator.java @@ -2,16 +2,18 @@ package world.bentobox.caveblock.generators.populators; -import org.bukkit.Chunk; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.generator.BlockPopulator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.World.Environment; +import org.bukkit.block.Block; +import org.bukkit.generator.BlockPopulator; + import world.bentobox.bentobox.util.Pair; import world.bentobox.caveblock.CaveBlock; import world.bentobox.caveblock.Settings; @@ -22,173 +24,188 @@ import world.bentobox.caveblock.Settings; */ public class MaterialPopulator extends BlockPopulator { - /** - * This is default constructor - * @param addon CaveBlock addon. - */ - public MaterialPopulator(CaveBlock addon) - { - this.addon = addon; - this.settings = addon.getSettings(); - } + private Map chances; + + private final int generationTry; + + private int worldHeight; + + /** + * This is default constructor + * @param addon CaveBlock addon. + */ + public MaterialPopulator(CaveBlock addon) + { + this.addon = addon; + this.settings = addon.getSettings(); + // Set up chances + chances = new HashMap<>(); + // Normal + chances.put(Environment.NORMAL, new Chances(this.getMaterialMap(this.settings.getNormalBlocks()), this.settings.getNormalMainBlock())); + // Nether + chances.put(Environment.NETHER, new Chances(this.getMaterialMap(this.settings.getNetherBlocks()), this.settings.getNetherMainBlock())); + // End + chances.put(Environment.THE_END, new Chances(this.getMaterialMap(this.settings.getEndBlocks()), this.settings.getEndMainBlock())); + // Other settings + generationTry = this.settings.getNumberOfBlockGenerationTries(); + worldHeight = this.settings.getWorldDepth() - 1; + + } - /** - * This method populates chunk with blocks. - * @param world World where population must be. - * @param random Randomness - * @param chunk Chunk were populator operates. - */ - @Override - public void populate(World world, Random random, Chunk chunk) - { - Map> materialChanceMap; - Material mainMaterial; + /** + * This method populates chunk with blocks. + * @param world World where population must be. + * @param random Randomness + * @param chunk Chunk were populator operates. + */ + @Override + public void populate(World world, Random random, Chunk chunk) + { + for (Map.Entry> entry : chances.get(world.getEnvironment()).materialChanceMap.entrySet()) + { + for (int subY = 0; subY < worldHeight; subY += 16) + { + for (int tries = 0; tries < generationTry; tries++) + { + if (random.nextInt(100) < entry.getValue().x) + { + int x = random.nextInt(15); + int z = random.nextInt(15); + int y = Math.min(worldHeight - 2, subY + random.nextInt(15)); - if (world.getEnvironment().equals(World.Environment.NETHER)) - { - materialChanceMap = this.getMaterialMap(this.settings.getNetherBlocks()); - mainMaterial = this.settings.getNetherMainBlock(); - } - else if (world.getEnvironment().equals(World.Environment.THE_END)) - { - materialChanceMap = this.getMaterialMap(this.settings.getEndBlocks()); - mainMaterial = this.settings.getEndMainBlock(); - } - else - { - materialChanceMap = this.getMaterialMap(this.settings.getNormalBlocks()); - mainMaterial = this.settings.getNormalMainBlock(); - } + Block block = chunk.getBlock(x, y, z); - final int generationTry = this.settings.getNumberOfBlockGenerationTries(); - final int worldHeight = this.settings.getWorldDepth() - 1; + if (block.getType().equals(chances.get(world.getEnvironment()).mainMaterial) && + this.isValidBlock(world, block, x, z)) + { + int packSize = random.nextInt(entry.getValue().z); - for (Map.Entry> entry : materialChanceMap.entrySet()) - { - for (int subY = 0; subY < worldHeight; subY += 16) - { - for (int tries = 0; tries < generationTry; tries++) - { - if (random.nextInt(100) < entry.getValue().x) - { - int x = random.nextInt(15); - int z = random.nextInt(15); - int y = Math.min(worldHeight - 2, subY + random.nextInt(15)); + boolean continuePlacing = true; - Block block = chunk.getBlock(x, y, z); + while (continuePlacing) + { + if (!block.getType().equals(entry.getKey())) + { + block.setType(entry.getKey()); + packSize--; + } - if (block.getType().equals(mainMaterial) && - this.isValidBlock(world, block, x, z)) - { - int packSize = random.nextInt(entry.getValue().z); + // 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; + } - boolean continuePlacing = true; + block = chunk.getBlock(x, y, z); - while (continuePlacing) - { - if (!block.getType().equals(entry.getKey())) - { - 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(mainMaterial) || - block.getType().equals(entry.getKey())); - } - } - } - } - } - } - } + continuePlacing = this.isValidBlock(world, block, x, z) && + packSize > 0 && + (block.getType().equals(chances.get(world.getEnvironment()).mainMaterial) || + block.getType().equals(entry.getKey())); + } + } + } + } + } + } + } - /** - * 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 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. - * @param objectList List with objects that contains data. - * @return Map that contains material, its rarity and pack size. - */ - private Map> getMaterialMap(List objectList) - { - Map> materialMap = new HashMap<>(objectList.size()); + /** + * This method returns material frequently and pack size map. + * @param objectList List with objects that contains data. + * @return Map that contains material, its rarity and pack size. + */ + private Map> getMaterialMap(List objectList) + { + Map> materialMap = new HashMap<>(objectList.size()); - // wrong material object. - objectList.stream(). - filter(object -> object.startsWith("MATERIAL")). - map(object -> object.split(":")). - filter(splitString -> splitString.length == 4). - forEach(splitString -> { - Material material = Material.getMaterial(splitString[1]); + // wrong material object. + objectList.stream(). + filter(object -> object.startsWith("MATERIAL")). + map(object -> object.split(":")). + filter(splitString -> splitString.length == 4). + forEach(splitString -> { + Material material = Material.getMaterial(splitString[1]); - if (material != null) - { - materialMap.put(material, - new Pair<>(Integer.parseInt(splitString[2]), Integer.parseInt(splitString[3]))); - } - }); + if (material != null) + { + materialMap.put(material, + new Pair<>(Integer.parseInt(splitString[2]), Integer.parseInt(splitString[3]))); + } + }); - return materialMap; - } + return materialMap; + } -// --------------------------------------------------------------------- -// Section: Variables -// --------------------------------------------------------------------- + // --------------------------------------------------------------------- + // Section: Variables + // --------------------------------------------------------------------- - /** - * CaveBlock addon. - */ - private CaveBlock addon; + /** + * CaveBlock addon. + */ + private CaveBlock addon; - /** - * CaveBlock settings. - */ - private Settings settings; + /** + * CaveBlock settings. + */ + private Settings settings; + + + /** + * Chances class to store chances for environments and main material + * + */ + private class Chances { + final Map> materialChanceMap; + final Material mainMaterial; + + /** + * @param materialChanceMap + * @param mainMaterial + */ + public Chances(Map> materialChanceMap, Material mainMaterial) { + this.materialChanceMap = materialChanceMap; + this.mainMaterial = mainMaterial; + } + } } diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index 098b998..982cf85 100644 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -9,4 +9,228 @@ caveblock: line1: "Welcome!" line2: "[name]" line3: "Start digging! &c<3" + # Override BentoBox default command strings + # General strings + general: + errors: + no-island: "&cYou do not have a cave!" + player-has-island: "&cPlayer already has a cave!" + player-has-no-island: "&cThat player has no cave!" + already-have-island: "&cYou already have a cave!" + no-safe-location: "&cNo safe location found!" + not-owner: "&cYou are not the owner of your team!" + commands: + # Override BentoBox default island command strings + island: + info: + description: "display info about your cave or the player's cave" + go: + description: "teleport you to your cave" + teleport: "&aTeleporting you to your cave." + create: + description: "create a cave, using optional schem (requires permission)" + too-many-islands: "&cThere are too many caves in this world: there isn't enough room for yours to be created." + unable-create-island: "&cYour cave could not be generated, please contact an administrator." + creating-island: "&aCreating your cave, please wait a moment..." + reset: + description: "restart your cave from scratch" + parameters: "" + must-remove-members: "&cYou must remove all team players before you can restart (/[label] team kick )." + sethome: + must-be-on-your-island: "&cYou must be in your cave to set home!" + home-set: "&6Your home has been set to your current location." + setname: + description: "set a name for your cave" + resetname: + description: "reset your cave name" + team: + coop: + description: "make a player coop rank" + uncoop: + you-are-no-longer-a-coop-member: "&cYou are no longer a coop member of [name]'s cave" + all-members-logged-off: "&cAll team members logged off so you are no longer a coop member of [name]'s cave" + trust: + description: "give a player trusted rank" + invite: + description: "invite a player to join your team" + name-has-invited-you: "&a[name] has invited you to join their team." + to-accept-or-reject: "&aDo /[label] team accept to accept, or /[label] team reject to reject" + you-will-lose-your-island: "&cWARNING! You will lose your our cave if you accept!" + errors: + island-is-full: "&cYour team is full, you can't invite anyone else." + accept: + you-joined-island: "&aYou joined a team! Use /[label] team info to see the other members." + name-joined-your-island: "&a[name] joined your team!" + confirmation: |- + &cAre you sure you want to accept this invite? + &c&lThis will &nDESTORY &r&c&lyour current cave! + reject: + you-rejected-invite: "&aYou rejected the invitation to join a team." + name-rejected-your-invite: "&c[name] rejected your invite!" + cancel: + description: "cancel the pending invite to join your team" + leave: + description: "leave your team" + left-your-island: "&c[name] &cleft your team" + kick: + description: "remove a team member" + owner-kicked: "&cThe owner kicked you from the team!" + demote: + description: "demote a player one rank" + promote: + description: "promote a player one rank" + setowner: + description: "transfer team ownership to a member" + errors: + target-is-not-member: "&cThat player is not part of your team!" + name-is-the-owner: "&a[name] is now the cave owner!" + you-are-the-owner: "&aYou are now the cave owner!" + ban: + description: "ban a player from your cave" + cannot-ban-more-players: "&cYou reached the ban limit, you cannot ban any more players." + owner-banned-you: "&b[name]&c banned you from their cave!" + you-are-banned: "&bYou are banned from this cave!" + unban: + description: "unban a player from your cave" + you-are-unbanned: "&b[name]&a unbanned you from their cave!" + banlist: + noone: "&aNo one is banned on this cave" + settings: + description: "display cave settings" + # Admin commands + admin: + team: + add: + name-has-island: "&c[name] has a cave. Unregister or delete them first!" + setowner: + description: "transfers cave ownership to the player" + already-owner: "&cPlayer is already the owner of this cave!" + range: + description: "Admin cave range command" + display: + description: "Show/hide cave range indicators" + hint: |- + &cRed Barrier icons &fshow the current protected range limit. + &7Gray Particles &fshow the max limit. + &aGreen Particles &fshow the default protected range if the protection range differs from it. + set: + description: "Sets the cave protected range" + reset: + description: "Resets the protected range to the world default" + register: + parameters: "" + description: "register player to unowned cave you are in" + registered-island: "&aRegistered player to cave at [xyz]." + already-owned: "&ccave is already owned by another player!" + no-island-here: "&cThere is no player cave here. Confirm to make one." + in-deletion: "&cThis space is currently being regenerated. Try later." + unregister: + description: "unregister owner from a cave, but keep cave blocks as-is" + unregistered-island: "&aUnregistered player from cave at [xyz]." + info: + parameters: "" + description: "get info on where you are or on player" + no-island: "&cYou are not in a registered cave right now..." + title: "========== Cave Info ============" + owner: "Owner: [owner] ([uuid])" + last-login: "Last login: [date]" + deaths: "Deaths: [number]" + resets-left: "Resets: [number] (Max: [total])" + team-members-title: "Team members:" + team-owner-format: "&a[name] [rank]" + team-member-format: "&b[name] [rank]" + island-location: "Cave location: [xyz]" + island-coords: "Cave coordinates: [xz1] to [xz2]" + protection-range: "Protection range: [range]" + max-protection-range: "Largest historical protection range: [range]" + protection-coords: "Protection coordinates: [xz1] to [xz2]" + is-spawn: "Cave is a spawn cave" + banned-players: "Banned players:" + banned-format: "&c[name]" + unowned: "&cUnowned" + setrange: + description: "set the range of player's cave" + range-updated: "Cave range updated to [number]" + tp: + parameters: "" + description: "teleport to a player's cave" + getrank: + description: "get a player's rank in their cave" + rank-is: "&aRank is [rank] in their cave." + setrank: + description: "set a player's rank in their cave" + setspawn: + description: "set a cave as spawn for this world" + already-spawn: "&cThis cave is already a spawn!" + no-island-here: "&cThere is no registered cave here." + confirmation: "&cAre you sure you want to set this cave as the spawn for this world?" + delete: + parameters: "" + description: "deletes a player and regenerates their cave" + cannot-delete-owner: "&cAll team members must be kicked before deleting." + deleted-island: "&aCave at &e[xyz] &ahas been successfully regenerated." + + protection: + flags: + ELYTRA: + description: "Toggle use" + ENDERMAN_GRIEFING: + description: |- + &aEndermen can remove + &ablocks + ENTER_EXIT_MESSAGES: + description: "Display entry and exit messages" + island: "[name]'s protected cave" + name: "Enter/Exit messages" + now-entering: "&bNow entering [name]" + now-leaving: "&bNow leaving [name]" + GEO_LIMIT_MOBS: + description: |- + &aRemove mobs that go + &aoutside protected + &aplayer space + name: "&eLimit mobs to player cave" + ISLAND_RESPAWN: + description: |- + &aPlayers respawn + &ain their cave + name: "Cave respawn" + LOCK: + name: "Lock player cave" + OFFLINE_REDSTONE: + description: |- + &aWhen disabled, redstone + &awill not operate in caves + &awhere all members are offline. + &aMay help reduce lag. + PISTON_PUSH: + description: |- + &aAllow pistons to push + &ablocks outside a player's cave + PVP_OVERWORLD: + description: |- + &cEnable/Disable PVP + &cin protected cave. + REMOVE_MOBS: + description: |- + &aRemove monsters when + &ateleporting to a cave + PREVENT_TELEPORT_WHEN_FALLING: + description: |- + &aPrevent players from teleporting + &aif they are falling. + hint: "&cYou cannot teleport while you are falling!" + locked: "&cThis cave is locked!" + protected: "&ccave protected: [description]" + + panel: + PROTECTION: + title: "&6Protection" + description: |- + &aProtection settings + &afor this cave + SETTING: + description: |- + &aGeneral settings + &afor this cave \ No newline at end of file