Merge branch 'develop' into master

# Conflicts:
#	pom.xml
#	src/main/java/world/bentobox/caveblock/generators/populators/EntitiesPopulator.java
This commit is contained in:
BONNe 2022-01-28 12:56:18 +02:00
commit e6e3c97f80
23 changed files with 2682 additions and 1697 deletions

2
.gitignore vendored
View File

@ -26,3 +26,5 @@ hs_err_pid*
/.classpath
/.project
/.settings/
/.idea/
/CaveBlock.iml

View File

@ -7,8 +7,8 @@ CaveBlock is an addon for BentoBox, so to run CaveBlock, you must have BentoBox
## Translation
As most of BentoBox projects, CaveBlock Addon is translatable in any language. Everyone can contribute, and translate some parts of the addon in their language via [GitLocalize](https://gitlocalize.com/repo/2968).
If your language is not in the list, please contact to developers via Discord and it will be added there.
Like most BentoBox projects, the CaveBlock Addon is translatable into any language. Everyone can contribute, and translate some parts of the addon into their language via [GitLocalize](https://gitlocalize.com/repo/2968).
If your language is not in the list, please contact the developers via Discord, and it will be added.
## Installation
@ -16,7 +16,7 @@ If your language is not in the list, please contact to developers via Discord an
1. Place this jar in the addons folder of the BentoBox plugin.
2. Restart the server.
3. The addon will create worlds and a data folder and inside the folder will be a config.yml.
4. Stop the server .
4. Stop the server.
5. Edit the config.yml how you want.
6. Delete any worlds that were created by default if you made changes that would affect them.
7. Restart the server.
@ -24,10 +24,7 @@ If your language is not in the list, please contact to developers via Discord an
## Config.yml
The config.yml is similar to BSkyblock and AcidIsalnd but *not the same*. It has some additional or changed parameters, like,
instead of wrold-height it has world-depth.
It also has option to choose main block for each world, and blocks that will be occasionally replace main block, f.e. diamond ore or shulker.
It also allows to specifiy if roof and floor for each world must be generated from bedrock.
instead of world-height it has world-depth.
### Other Add-ons

17
pom.xml
View File

@ -43,14 +43,14 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<java.version>16</java.version>
<!-- More visible way how to change dependency versions -->
<spigot.version>1.16.4-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>1.16.0</bentobox.version>
<spigot.version>1.18.1-R0.1-SNAPSHOT</spigot.version>
<bentobox.version>1.19.0</bentobox.version>
<!-- Revision variable removes warning about dynamic version -->
<revision>${build.version}-SNAPSHOT</revision>
<!-- This allows to change between versions and snapshots. -->
<build.version>1.14.5</build.version>
<build.version>1.15.0</build.version>
<build.number>-LOCAL</build.number>
<sonar.organization>bentobox-world</sonar.organization>
<sonar.host.url>https://sonarcloud.io</sonar.host.url>
@ -114,6 +114,12 @@
<version>${spigot.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>plugin-annotations</artifactId>
<version>1.2.3-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>world.bentobox</groupId>
<artifactId>bentobox</artifactId>
@ -170,8 +176,7 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<release>${java.version}</release>
</configuration>
</plugin>
<plugin>

View File

@ -24,7 +24,7 @@ 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.
* be used to set up configuration and worlds.
*/
@Override
public void onLoad()
@ -76,7 +76,6 @@ public class CaveBlock extends GameModeAddon
{
super.onReload();
this.loadSettings();
this.chunkGenerator.reload();
}
@ -122,8 +121,8 @@ public class CaveBlock extends GameModeAddon
/**
* 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.
* onEnable(). {@code islandWorld} must be created and assigned, {@code netherWorld} and {@code
* endWorld} are optional and may be null.
*/
@Override
public void createWorlds()
@ -137,7 +136,6 @@ public class CaveBlock extends GameModeAddon
// Create the world if it does not exist
this.islandWorld = WorldCreator.name(worldName).
type(WorldType.FLAT).
environment(World.Environment.NORMAL).
generator(this.chunkGenerator).
createWorld();
@ -316,6 +314,4 @@ public class CaveBlock extends GameModeAddon
* String for the end world.
*/
private static final String THE_END = "_the_end";
}

View File

@ -0,0 +1,20 @@
package world.bentobox.caveblock;
import org.bukkit.plugin.java.annotation.dependency.Dependency;
import org.bukkit.plugin.java.annotation.plugin.ApiVersion;
import org.bukkit.plugin.java.annotation.plugin.Plugin;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.Pladdon;
@Plugin(name = "Pladdon", version = "1.0")
@ApiVersion(ApiVersion.Target.v1_18)
@Dependency(value = "BentoBox")
public class CaveBlockPladdon extends Pladdon {
@Override
public Addon getAddon() {
return new CaveBlock();
}
}

View File

@ -166,13 +166,13 @@ public class Settings implements WorldSettings
/**
* This method returns the useOwnGenerator object.
* @return the useOwnGenerator object.
* This is not an option in Caveblock
* @return false
*/
@Override
public boolean isUseOwnGenerator()
{
return useOwnGenerator;
return false;
}
@ -812,6 +812,15 @@ public class Settings implements WorldSettings
return numberOfBlockGenerationTries;
}
/**
* This method returns the newMaterialGenerator value.
* @return the value of newMaterialGenerator.
*/
public boolean isNewMaterialGenerator()
{
return newMaterialGenerator;
}
/**
* {@inheritDoc}
@ -1022,16 +1031,6 @@ public class Settings implements WorldSettings
}
/**
* This method sets the useOwnGenerator object value.
* @param useOwnGenerator the useOwnGenerator object new value.
*
*/
public void setUseOwnGenerator(boolean useOwnGenerator)
{
this.useOwnGenerator = useOwnGenerator;
}
/**
* This method sets the maxIslands object value.
* @param maxIslands the maxIslands object new value.
@ -1647,6 +1646,17 @@ public class Settings implements WorldSettings
}
/**
* This method sets the newMaterialGenerator value.
* @param newMaterialGenerator the numberOfBlockGenerationTries new value.
*
*/
public void setNewMaterialGenerator(boolean newMaterialGenerator)
{
this.newMaterialGenerator = newMaterialGenerator;
}
/**
* @return the debug
*/
@ -1687,6 +1697,7 @@ public class Settings implements WorldSettings
/**
* @return the onJoinCommands
*/
@NonNull
@Override
public List<String> getOnJoinCommands() {
return onJoinCommands;
@ -1704,6 +1715,7 @@ public class Settings implements WorldSettings
/**
* @return the onLeaveCommands
*/
@NonNull
@Override
public List<String> getOnLeaveCommands() {
return onLeaveCommands;
@ -2163,11 +2175,6 @@ public class Settings implements WorldSettings
@ConfigEntry(path = "world.cave-height")
private int islandHeight = 60;
@ConfigComment("Use your own world generator for this world.")
@ConfigComment("In this case, the plugin will not generate anything.")
@ConfigEntry(path = "world.use-own-generator", experimental = true)
private boolean useOwnGenerator = true;
@ConfigComment("Maximum number of caves in the world. Set to -1 or 0 for unlimited.")
@ConfigComment("If the number of caves is greater than this number, it will stop players from creating caves.")
@ConfigEntry(path = "world.max-caves")
@ -2180,7 +2187,7 @@ public class Settings implements WorldSettings
@ConfigComment("The default biome for the overworld")
@ConfigEntry(path = "world.default-biome")
private Biome defaultBiome = Biome.MOUNTAINS;
private Biome defaultBiome = Enums.getIfPresent(Biome.class, "DRIPSTONE_CAVES").or(Biome.THE_VOID);
@ConfigComment("The maximum number of players a player can ban at any one time in this game mode.")
@ConfigComment("The permission caveblock.ban.maxlimit.X where X is a number can also be used per player")
@ -2198,6 +2205,12 @@ public class Settings implements WorldSettings
@ConfigEntry(path = "world.generation-tries", needsReset = true)
private int numberOfBlockGenerationTries = 1;
@ConfigComment("Should we use the new material generator ?")
@ConfigComment("This will generate ores and blocks similar to how vanilla does,")
@ConfigComment("but it will override the blocks settings of each world.")
@ConfigEntry(path = "world.use-new-material-generator", needsReset = true)
private boolean newMaterialGenerator = false;
@ConfigComment("")
@ConfigComment("Make over world roof of bedrock, if false, it will be made from stone")
@ConfigEntry(path = "world.normal.roof", needsReset = true)
@ -2238,7 +2251,7 @@ public class Settings implements WorldSettings
@ConfigComment("The default biome for the nether world (this may affect what mobs can spawn)")
@ConfigEntry(path = "world.nether.biome", since = "1.14.0")
private Biome defaultNetherBiome = Enums.getIfPresent(Biome.class, "NETHER").or(Enums.getIfPresent(Biome.class, "NETHER_WASTES").or(Biome.BADLANDS));
private Biome defaultNetherBiome = Enums.getIfPresent(Biome.class, "NETHER_WASTES").or(Biome.THE_VOID);
@ConfigComment("Nether spawn protection radius - this is the distance around the nether spawn")
@ConfigComment("that will be protected from player interaction (breaking blocks, pouring lava etc.)")
@ -2286,7 +2299,7 @@ public class Settings implements WorldSettings
@ConfigComment("The default biome for the end world (this may affect what mobs can spawn)")
@ConfigEntry(path = "world.end.biome", since = "1.14.0")
private Biome defaultTheEndBiome = Biome.THE_END;
private Biome defaultTheEndBiome = Enums.getIfPresent(Biome.class, "THE_END").or(Biome.THE_VOID);
@ConfigEntry(path = "world.end.dragon-spawn", experimental = true)
private boolean dragonSpawn = false;

View File

@ -0,0 +1,20 @@
package world.bentobox.caveblock;
import org.bukkit.Location;
public class Utils {
/**
* Convert chunk location to world location
*
* @param x the x coordinate of the chunk location
* @param y the y coordinate
* @param z the z coordinate of the chunk location
* @param chunkX the x coordinate of the chunk
* @param chunkZ the z coordinate of the chunk
* @return the world location
*/
public static Location getLocationFromChunkLocation(int x, int y, int z, int chunkX, int chunkZ) {
return new Location(null, x + (chunkX * 16D), y, z + (chunkZ * 16D));
}
}

View File

@ -1,251 +1,160 @@
package world.bentobox.caveblock.generators;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.WorldInfo;
import world.bentobox.caveblock.CaveBlock;
import world.bentobox.caveblock.Settings;
import world.bentobox.caveblock.generators.populators.EntitiesPopulator;
import world.bentobox.caveblock.generators.populators.FlatBiomeProvider;
import world.bentobox.caveblock.generators.populators.MaterialPopulator;
import world.bentobox.caveblock.generators.populators.NewMaterialPopulator;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import world.bentobox.caveblock.CaveBlock;
import world.bentobox.caveblock.Settings;
import world.bentobox.caveblock.generators.populators.EntitiesPopulator;
import world.bentobox.caveblock.generators.populators.MaterialPopulator;
/**
* Class ChunkGeneratorWorld ...
*
* @author BONNe
* Created on 27.01.2019
*/
public class ChunkGeneratorWorld extends ChunkGenerator
{
public class ChunkGeneratorWorld extends ChunkGenerator {
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
private final CaveBlock addon;
private final Settings settings;
private final List<BlockPopulator> blockPopulators;
private BiomeProvider biomeProvider;
private boolean isNewGenerator;
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* @param addon - CaveBlock object
*/
public ChunkGeneratorWorld(CaveBlock addon)
{
super();
public ChunkGeneratorWorld(CaveBlock addon) {
this.addon = addon;
this.settings = addon.getSettings();
this.blockPopulators = new ArrayList<>(2);
reload();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
private Material getGroundCeilMaterial(World.Environment environment) {
return switch (environment) {
case NETHER -> this.settings.isNetherRoof() ? Material.BEDROCK : this.settings.getNetherMainBlock();
case THE_END -> this.settings.isEndFloor() ? Material.BEDROCK : this.settings.getEndMainBlock();
default -> this.settings.isNormalFloor() ? Material.BEDROCK : this.settings.getNormalMainBlock();
};
}
private Material getBaseMaterial(World.Environment environment) {
return switch (environment) {
case NETHER -> this.settings.getNetherMainBlock();
case THE_END -> this.settings.getEndMainBlock();
default -> this.settings.getNormalMainBlock();
};
}
/**
* This method sets if given coordinates can be set as spawn location
*/
@Override
public boolean canSpawn(World world, int x, int z)
{
public void generateBedrock(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, ChunkData chunkData) {
final int minHeight = worldInfo.getMinHeight();
Material material = getGroundCeilMaterial(worldInfo.getEnvironment());
chunkData.setRegion(0, minHeight, 0, 16, minHeight + 1, 16, material);
}
@Override
public void generateSurface(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, ChunkData chunkData) {
final int worldHeight = Math.min(worldInfo.getMaxHeight(), this.settings.getWorldDepth());
Material material = getGroundCeilMaterial(worldInfo.getEnvironment());
chunkData.setRegion(0, worldHeight - 1, 0, 16, worldHeight, 16, material);
}
@Override
public void generateNoise(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, ChunkData chunkData) {
final int minHeight = worldInfo.getMinHeight();
final int worldHeight = Math.min(worldInfo.getMaxHeight(), this.settings.getWorldDepth());
final World.Environment environment = worldInfo.getEnvironment();
if (isNewGenerator) {
switch (environment) {
case NETHER:
if (worldHeight + 1 > 34) {
chunkData.setRegion(0, minHeight + 1, 0, 16, 34, 16, Material.SOUL_SAND);
chunkData.setRegion(0, 34, 0, 16, worldHeight - 1, 16, Material.NETHERRACK);
} else {
chunkData.setRegion(0, minHeight + 1, 0, 16, worldHeight - 1, 16, Material.NETHERRACK);
}
break;
case THE_END:
chunkData.setRegion(0, minHeight + 1, 0, 16, worldHeight - 1, 16, Material.END_STONE);
break;
default:
if (worldHeight + 1 > 7) {
chunkData.setRegion(0, minHeight + 1, 0, 16, 7, 16, Material.DEEPSLATE);
chunkData.setRegion(0, 7, 0, 16, worldHeight - 1, 16, Material.STONE);
} else {
chunkData.setRegion(0, minHeight + 1, 0, 16, worldHeight - 1, 16, Material.STONE);
}
break;
}
} else {
Material material = getBaseMaterial(environment);
chunkData.setRegion(0, minHeight + 1, 0, 16, worldHeight - 1, 16, material);
}
}
@Override
public List<BlockPopulator> getDefaultPopulators(final World world) {
return this.blockPopulators;
}
@Override
public BiomeProvider getDefaultBiomeProvider(WorldInfo worldInfo) {
return biomeProvider;
}
@Override
public boolean shouldGenerateSurface() {
return true;
}
/**
* This method generates given chunk.
* @param world World where chunk must be generated.
* @param random Random that allows define object randomness.
* @param chunkX Chunk X coordinate.
* @param chunkZ Chunk Z coordinate.
* @param biomeGrid BiomeGrid that contains biomes.
* @return new ChunkData for given chunk.
*/
@Override
public ChunkData generateChunkData(World world,
Random random,
int chunkX,
int chunkZ,
ChunkGenerator.BiomeGrid biomeGrid)
{
ChunkData result = this.createChunkData(world);
// Populate chunk with necessary information
if (world.getEnvironment().equals(World.Environment.NETHER))
{
this.populateNetherChunk(world, result, biomeGrid);
}
else if (world.getEnvironment().equals(World.Environment.THE_END))
{
this.populateTheEndChunk(world, result, biomeGrid);
}
else
{
this.populateOverWorldChunk(world, result, biomeGrid);
}
return result;
public boolean shouldGenerateBedrock() {
return true;
}
/**
* This method populates The End world chunk data.
* @param world world where chunks are generated.
* @param chunkData ChunkData that must be populated.
* @param biomeGrid BiomeGrid for this chunk.
*/
private void populateTheEndChunk(World world, ChunkData chunkData, BiomeGrid biomeGrid)
{
// because everything starts at 0 and ends at 255
final int worldHeight = this.settings.getWorldDepth();
// Fill all blocks
chunkData.setRegion(0, 1, 0,
16, worldHeight - 1, 16,
this.settings.getEndMainBlock());
// Generate ground and ceiling.
chunkData.setRegion(0, 0, 0,
16, 1, 16,
this.settings.isEndFloor() ? Material.BEDROCK : this.settings.getEndMainBlock());
chunkData.setRegion(0, worldHeight - 1, 0,
16, worldHeight, 16,
this.settings.isEndRoof() ? Material.BEDROCK : this.settings.getEndMainBlock());
// Set biome
for (int x = 0; x < 16; x += 4)
{
for (int y = 0; y < world.getMaxHeight(); y += 4)
{
for (int z = 0; z < 16; z += 4)
{
biomeGrid.setBiome(x, y, z, this.settings.getDefaultTheEndBiome());
}
}
}
}
/**
* This method populates nether world chunk data.
* @param world world where chunks are generated.
* @param chunkData ChunkData that must be populated.
* @param biomeGrid BiomeGrid for this chunk.
*/
private void populateNetherChunk(World world, ChunkData chunkData, BiomeGrid biomeGrid)
{
// because everything starts at 0 and ends at 255
final int worldHeight = this.settings.getWorldDepth();
// Fill all blocks
chunkData.setRegion(0, 1, 0,
16, worldHeight - 1, 16,
this.settings.getNetherMainBlock());
// Generate ground and ceiling.
chunkData.setRegion(0, 0, 0,
16, 1, 16,
this.settings.isNetherFloor() ? Material.BEDROCK : this.settings.getNetherMainBlock());
chunkData.setRegion(0, worldHeight - 1, 0,
16, worldHeight, 16,
this.settings.isNetherRoof() ? Material.BEDROCK : this.settings.getNetherMainBlock());
// Set biome
for (int x = 0; x < 16; x += 4)
{
for (int y = 0; y < world.getMaxHeight(); y += 4)
{
for (int z = 0; z < 16; z += 4)
{
biomeGrid.setBiome(x, y, z, this.settings.getDefaultNetherBiome());
}
}
}
}
/**
* This method populates Over world chunk data.
* @param world world where chunks are generated.
* @param chunkData ChunkData that must be populated.
* @param biomeGrid BiomeGrid for this chunk.
*/
private void populateOverWorldChunk(World world, ChunkData chunkData, BiomeGrid biomeGrid)
{
// because everything starts at 0 and ends at 255
final int worldHeight = this.settings.getWorldDepth();
// Fill all blocks
chunkData.setRegion(0, 1, 0,
16, worldHeight - 1, 16,
this.settings.getNormalMainBlock());
// Generate ground and ceiling.
chunkData.setRegion(0, 0, 0,
16, 1, 16,
this.settings.isNormalFloor() ? Material.BEDROCK : this.settings.getNormalMainBlock());
chunkData.setRegion(0, worldHeight - 1, 0,
16, worldHeight, 16,
this.settings.isNormalRoof() ? Material.BEDROCK : this.settings.getNormalMainBlock());
// Set biome
for (int x = 0; x < 16; x += 4)
{
for (int y = 0; y < world.getMaxHeight(); y += 4)
{
for (int z = 0; z < 16; z += 4)
{
biomeGrid.setBiome(x, y, z, this.settings.getDefaultBiome());
}
}
}
}
/**
* This method set world block populators.
* @param world World where this must apply.
* @return List with block populators.
*/
@Override
public List<BlockPopulator> getDefaultPopulators(final World world)
{
return this.blockPopulators;
public boolean shouldGenerateCaves() {
return this.isNewGenerator;
}
/**
* 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));
this.blockPopulators.clear();
this.isNewGenerator = this.settings.isNewMaterialGenerator();
if (this.isNewGenerator) {
this.blockPopulators.add(new NewMaterialPopulator(this.settings.getWorldDepth()));
this.biomeProvider = null;
} else {
this.blockPopulators.add(new MaterialPopulator(this.addon));
this.blockPopulators.add(new EntitiesPopulator(this.addon));
this.biomeProvider = new FlatBiomeProvider(this.addon);
}
}
// ---------------------------------------------------------------------
// 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;
}

View File

@ -0,0 +1,15 @@
package world.bentobox.caveblock.generators;
import org.bukkit.Material;
/**
* @author tastybento
* @param minY minimum Y level this ore should appear
* @param material Material
* @param chance chance
* @param blob maximum size of blob to generate
* @param cont whether the generator should continue to try to make other ores at this level after making this one
*/
public record Ore (int minY, int maxY, Material material, int chance, int blob, boolean cont){
}

View File

@ -1,52 +1,80 @@
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.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.LimitedRegion;
import org.bukkit.generator.WorldInfo;
import org.bukkit.util.BoundingBox;
import world.bentobox.bentobox.util.Pair;
import world.bentobox.caveblock.CaveBlock;
import world.bentobox.caveblock.Utils;
import java.util.*;
import java.util.stream.Collectors;
/**
* This class populates generated chunk with entites by random chance.
* This class populates generated chunk with entities by random chance.
*/
public class EntitiesPopulator extends BlockPopulator
{
public class EntitiesPopulator extends BlockPopulator {
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Water entities
*/
private static final List<EntityType> WATER_ENTITIES = Arrays.asList(EntityType.GUARDIAN,
EntityType.SQUID,
EntityType.COD,
EntityType.SALMON,
EntityType.PUFFERFISH,
EntityType.TROPICAL_FISH,
EntityType.DROWNED,
EntityType.DOLPHIN);
/**
* CaveBlock addon.
*/
private final CaveBlock addon;
/**
* Map that contains chances for spawning per environment.
*/
private Map<Environment, Chances> chances;
/**
* World height
*/
private int worldHeight;
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* This is default constructor
*
* @param addon CaveBlock addon.
*/
public EntitiesPopulator(CaveBlock addon)
{
public EntitiesPopulator(CaveBlock addon) {
this.addon = addon;
this.loadSettings();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method load chances per environment.
*/
private void loadSettings() {
// Set up chances
chances = new HashMap<>();
chances = new EnumMap<>(Environment.class);
// Normal
chances.put(Environment.NORMAL, new Chances(this.getEntityMap(addon.getSettings().getNormalBlocks()), addon.getSettings().getNormalMainBlock()));
// Nether
@ -54,43 +82,49 @@ public class EntitiesPopulator extends BlockPopulator
// End
chances.put(Environment.THE_END, new Chances(this.getEntityMap(addon.getSettings().getEndBlocks()), addon.getSettings().getEndMainBlock()));
// Other settings
worldHeight = addon.getSettings().getWorldDepth() - 1;
worldHeight = addon.getSettings().getWorldDepth();
}
/**
* This method populates chunk with entities.
* @param world World where population must be.
* @param random Randomness
* @param chunk Chunk were populator operates.
*
* @param worldInfo World where population must be.
* @param random Randomness
* @param chunkX X coordinate of chunk
* @param chunkZ Z coordinate of chunk
* @param limitedRegion Region where population operates.
*/
@Override
public void populate(World world, Random random, Chunk chunk)
{
for (Map.Entry<EntityType, Pair<Double, Integer>> entry : chances.get(world.getEnvironment()).entityChanceMap.entrySet())
{
for (int subY = 0; subY < worldHeight; subY += 16)
{
public void populate(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, LimitedRegion limitedRegion) {
int minHeight = worldInfo.getMinHeight();
int height = Math.min(worldInfo.getMaxHeight(), worldHeight) - 1;
for (Map.Entry<EntityType, Pair<Pair<Double, Integer>, Boolean>> entry : chances.get(worldInfo.getEnvironment()).entityChanceMap.entrySet()) {
Pair<Double, Integer> value = entry.getValue().x;
boolean hasAI = entry.getValue().z;
for (int subY = minHeight; subY < height; subY += 16) {
// Use double so chance can be < 1
if (random.nextDouble() * 100 < entry.getValue().x)
{
int y = Math.min(worldHeight - 2, subY + random.nextInt(15));
if (random.nextDouble() * 100 < value.x) {
int y = Math.min(height - 2, subY + random.nextInt(15));
// Spawn only in middle of chunk because bounding box will grow out from here
this.tryToPlaceEntity(world, chunk.getBlock(7, y, 7), entry.getKey(), chances.get(world.getEnvironment()).mainMaterial);
this.tryToPlaceEntity(
worldInfo, Utils.getLocationFromChunkLocation(7, y, 7, chunkX, chunkZ), limitedRegion,
entry.getKey(), hasAI,
chances.get(worldInfo.getEnvironment()).mainMaterial
);
}
}
}
}
/**
* 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<EntityType, Pair<Double, Integer>> getEntityMap(List<String> objectList)
{
Map<EntityType, Pair<Double, Integer>> entityMap = new HashMap<>(objectList.size());
private Map<EntityType, Pair<Pair<Double, Integer>, Boolean>> getEntityMap(List<String> objectList) {
Map<EntityType, Pair<Pair<Double, Integer>, Boolean>> entityMap = new EnumMap<>(EntityType.class);
Map<String, EntityType> entityTypeMap = Arrays.stream(EntityType.values()).
collect(Collectors.toMap(Enum::name,
@ -100,128 +134,86 @@ public class EntitiesPopulator extends BlockPopulator
// 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);
filter(object -> object.startsWith("ENTITY")).
map(object -> object.split(":")).
filter(splitString -> splitString.length >= 4).
forEach(splitString -> {
EntityType entity = entityTypeMap.getOrDefault(splitString[1], null);
boolean hasAI = splitString.length <= 4 || Boolean.parseBoolean(splitString[4]);
if (entity != null)
{
entityMap.put(entity,
new Pair<>(Double.parseDouble(splitString[2]), Integer.parseInt(splitString[3])));
}
});
if (entity != null) {
entityMap.put(entity,
new Pair<>(
new Pair<>(Double.parseDouble(splitString[2]), Integer.parseInt(splitString[3])),
hasAI
)
);
}
});
return entityMap;
}
/**
* Places entities if there is room for them.
* @param world - World were mob must be spawned.
* @param block - Block that was chosen by random.
* @param entity - Entity that must be spawned.
*
* @param worldInfo - World were mob must be spawned.
* @param location - Location that was chosen by random.
* @param limitedRegion - Region where entity must be spawned.
* @param entityType - Entity that must be spawned.
* @param hasAI - If entity has AI.
* @param originalMaterial - replacement material.
*/
private void tryToPlaceEntity(World world, Block block, EntityType entity, Material originalMaterial)
{
if (block.getType().equals(originalMaterial)) {
// Spawn entity
Entity e = world.spawnEntity(block.getLocation().add(0.5, 0, 0.5), entity);
if (e instanceof LivingEntity) {
// Do not despawn
((LivingEntity)e).setRemoveWhenFarAway(false);
}
// Make space for entity based on the entity's size
BoundingBox bb = e.getBoundingBox();
private void tryToPlaceEntity(WorldInfo worldInfo, Location location, LimitedRegion limitedRegion, EntityType entityType, boolean hasAI, Material originalMaterial) {
if (!limitedRegion.isInRegion(location)) return;
if (!limitedRegion.getType(location).equals(originalMaterial)) return;
for (int x = (int) Math.floor(bb.getMinX()); x < bb.getMaxX(); x++) {
for (int z = (int) Math.floor(bb.getMinZ()); z < bb.getMaxZ(); z++) {
int y = (int) Math.floor(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.AIR);
Entity entity = limitedRegion.spawnEntity(location, entityType);
if (entity instanceof LivingEntity livingEntity) {
livingEntity.setAI(hasAI);
livingEntity.setRemoveWhenFarAway(false);
}
BoundingBox bb = entity.getBoundingBox();
for (int x = (int) Math.floor(bb.getMinX()); x < bb.getMaxX(); x++) {
for (int z = (int) Math.floor(bb.getMinZ()); z < bb.getMaxZ(); z++) {
int y = (int) Math.floor(bb.getMinY());
if (!limitedRegion.isInRegion(x, y, z)) {
entity.remove();
return;
}
for (; y <= bb.getMaxY(); y++) {
if (addon.getSettings().isDebug()) {
addon.log("DEBUG: Entity spawn: " + worldInfo.getName() + " " + x + " " + y + " " + z + " " + entity.getType());
}
// 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);
if (!limitedRegion.isInRegion(x, y, z) || !limitedRegion.getType(x, y, z).equals(originalMaterial)) {
// Cannot place entity
entity.remove();
return;
}
limitedRegion.setType(x, y, z, WATER_ENTITIES.contains(entityType) ? Material.WATER : Material.AIR);
}
// Add air block on top for all water entities (required for dolphin, okay for others)
if (WATER_ENTITIES.contains(entityType) && limitedRegion.isInRegion(x, y, z) && limitedRegion.getType(x, y, z).equals(originalMaterial)) {
limitedRegion.setType(x, y, z, Material.CAVE_AIR);
}
}
}
}
// ---------------------------------------------------------------------
// Section: Private Classes
// ---------------------------------------------------------------------
/**
* Chances class to store chances for environments and main material
*
* @param entityChanceMap - contains chances for each entity, and the boolean indicates that entity should have AI.
* @param mainMaterial - material on which entity can replace.
*/
private class Chances
{
/**
* @param entityChanceMap - contains chances for each entity.
* @param mainMaterial - material on which entity can replace.
*/
Chances(Map<EntityType, Pair<Double, Integer>> entityChanceMap, Material mainMaterial)
{
this.entityChanceMap = entityChanceMap;
this.mainMaterial = mainMaterial;
}
/**
* Map that contains chances for entity to spawn.
*/
final Map<EntityType, Pair<Double, Integer>> entityChanceMap;
/**
* Main material that can be replaced.
*/
final Material mainMaterial;
private record Chances(Map<EntityType, Pair<Pair<Double, Integer>, Boolean>> entityChanceMap,
Material mainMaterial) {
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* CaveBlock addon.
*/
private CaveBlock addon;
/**
* Map that contains chances for spawning per environment.
*/
private Map<Environment, Chances> chances;
/**
* World height
*/
private int worldHeight;
/**
* Water entities
*/
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);
}

View File

@ -0,0 +1,48 @@
package world.bentobox.caveblock.generators.populators;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.WorldInfo;
import world.bentobox.caveblock.CaveBlock;
import world.bentobox.caveblock.Settings;
import java.util.Collections;
import java.util.List;
public class FlatBiomeProvider extends BiomeProvider {
private final Settings settings;
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* @param addon - CaveBlock object
*/
public FlatBiomeProvider(CaveBlock addon) {
this.settings = addon.getSettings();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
private Biome getBiome(World.Environment environment) {
return switch (environment) {
case NETHER -> this.settings.getDefaultNetherBiome();
case THE_END -> this.settings.getDefaultTheEndBiome();
default -> this.settings.getDefaultBiome();
};
}
@Override
public Biome getBiome(WorldInfo worldInfo, int x, int y, int z) {
return getBiome(worldInfo.getEnvironment());
}
@Override
public List<Biome> getBiomes(WorldInfo worldInfo) {
return Collections.singletonList(getBiome(worldInfo.getEnvironment()));
}
}

View File

@ -1,47 +1,67 @@
package world.bentobox.caveblock.generators.populators;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World.Environment;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.LimitedRegion;
import org.bukkit.generator.WorldInfo;
import world.bentobox.bentobox.util.Pair;
import world.bentobox.caveblock.CaveBlock;
import world.bentobox.caveblock.Utils;
import java.util.HashMap;
import java.util.EnumMap;
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;
/**
* This class allows to fill given chunk with necessary blocks.
* This class allows filling given chunk with necessary blocks.
*/
public class MaterialPopulator extends BlockPopulator
{
public class MaterialPopulator extends BlockPopulator {
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* CaveBlock addon.
*/
private final CaveBlock addon;
/**
* Map that contains chances for spawning per environment.
*/
private Map<Environment, Chances> chances;
/**
* World height
*/
private int worldHeight;
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* This is default constructor
*
* @param addon CaveBlock addon.
*/
public MaterialPopulator(CaveBlock addon)
{
public MaterialPopulator(CaveBlock addon) {
this.addon = addon;
// Load settings
this.loadSettings();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* Loads chances for Material Populator
*/
private void loadSettings() {
// Set up chances
chances = new HashMap<>();
chances = new EnumMap<>(Environment.class);
// Normal
chances.put(Environment.NORMAL, new Chances(this.getMaterialMap(addon.getSettings().getNormalBlocks()), addon.getSettings().getNormalMainBlock()));
// Nether
@ -49,84 +69,71 @@ public class MaterialPopulator extends BlockPopulator
// End
chances.put(Environment.THE_END, new Chances(this.getMaterialMap(addon.getSettings().getEndBlocks()), addon.getSettings().getEndMainBlock()));
// Other settings
worldHeight = addon.getSettings().getWorldDepth() - 1;
worldHeight = addon.getSettings().getWorldDepth();
}
/**
* This method populates chunk with blocks.
* @param world World where population must be.
* @param random Randomness
* @param chunk Chunk were populator operates.
*
* @param worldInfo World where population must be.
* @param random Randomness
* @param chunkX X coordinate of chunk
* @param chunkZ Z coordinate of chunk
* @param limitedRegion Region were populator operates.
*/
@Override
public void populate(World world, Random random, Chunk chunk)
{
Chances chances = this.chances.get(world.getEnvironment());
public void populate(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, LimitedRegion limitedRegion) {
int minHeight = worldInfo.getMinHeight();
int height = Math.min(worldInfo.getMaxHeight(), worldHeight) - 1;
Chances envChances = this.chances.get(worldInfo.getEnvironment());
for (Map.Entry<Material, Pair<Double, Integer>> entry : envChances.materialChanceMap.entrySet()) {
for (int subY = minHeight + 1; subY < height; subY += 16) {
if (random.nextDouble() * 100 >= entry.getValue().x) {
continue;
}
for (Map.Entry<Material, Pair<Double, Integer>> entry : chances.materialChanceMap.entrySet())
{
for (int subY = 1; subY < worldHeight; subY += 16)
{
if (random.nextDouble() * 100 < entry.getValue().x)
{
// Blocks must be 1 away from edge to avoid adjacent chunk loading
Location location = Utils.getLocationFromChunkLocation(
random.nextInt(13) + 1,
Math.min(height - 2, subY + random.nextInt(15)),
random.nextInt(13) + 1,
chunkX, chunkZ);
// 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());
if (!limitedRegion.isInRegion(location)) {
continue;
}
Material material = limitedRegion.getType(location);
if (!material.equals(envChances.mainMaterial)) {
continue;
}
int packSize = random.nextInt(entry.getValue().z);
boolean continuePlacing = true;
while (continuePlacing) {
if (!material.equals(entry.getKey())) {
limitedRegion.setType(location, entry.getKey());
packSize--;
}
*/
Block block = chunk.getBlock(x, y, z);
if (block.getType().equals(chances.mainMaterial))
{
int packSize = random.nextInt(entry.getValue().z);
boolean continuePlacing = true;
while (continuePlacing)
{
if (!block.getType().equals(entry.getKey()))
{
// Set type without physics is required otherwise server goes into an infinite loop
block.setType(entry.getKey(), false);
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 = packSize > 0 && (block.getType().equals(chances.mainMaterial) ||
block.getType().equals(entry.getKey()));
switch (random.nextInt(6)) {
case 0 -> location.setX(location.getX() + 1);
case 1 -> location.setY(location.getY() + 1);
case 2 -> location.setZ(location.getZ() + 1);
case 3 -> location.setX(location.getX() - 1);
case 4 -> location.setY(location.getY() - 1);
case 5 -> location.setZ(location.getZ() - 1);
default -> {
continuePlacing = false;
continue;
}
}
continuePlacing = packSize > 0 && limitedRegion.isInRegion(location) && location.getY() > minHeight;
if (continuePlacing) {
material = limitedRegion.getType(location);
continuePlacing = material.equals(envChances.mainMaterial) || material.equals(entry.getKey());
}
}
}
}
@ -134,84 +141,42 @@ public class MaterialPopulator extends BlockPopulator
/**
* 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<Material, Pair<Double, Integer>> getMaterialMap(List<String> objectList)
{
Map<Material, Pair<Double, Integer>> materialMap = new HashMap<>(objectList.size());
private Map<Material, Pair<Double, Integer>> getMaterialMap(List<String> objectList) {
Map<Material, Pair<Double, Integer>> materialMap = new EnumMap<>(Material.class);
// 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]);
// Material must be a block otherwise the chunk cannot be populated
if (material != null && material.isBlock())
{
materialMap.put(material,
new Pair<>(Double.parseDouble(splitString[2]), Integer.parseInt(splitString[3])));
} else {
addon.logError("Could not parse MATERIAL in config.yml: " + splitString[1] + " is not a valid block.");
}
});
filter(object -> object.startsWith("MATERIAL")).
map(object -> object.split(":")).
filter(splitString -> splitString.length == 4).
forEach(splitString -> {
Material material = Material.getMaterial(splitString[1]);
// Material must be a block otherwise the chunk cannot be populated
if (material != null && material.isBlock()) {
materialMap.put(material,
new Pair<>(Double.parseDouble(splitString[2]), Integer.parseInt(splitString[3])));
} else {
addon.logError("Could not parse MATERIAL in config.yml: " + splitString[1] + " is not a valid block.");
}
});
return materialMap;
}
// ---------------------------------------------------------------------
// Section: Private Classes
// ---------------------------------------------------------------------
/**
* Chances class to store chances for environments and main material
*
* @param materialChanceMap - contains chances for each material.
* @param mainMaterial - material on which material can replace.
*/
private class Chances
{
/**
* @param materialChanceMap - contains chances for each material.
* @param mainMaterial - material on which material can replace.
*/
Chances(Map<Material, Pair<Double, Integer>> materialChanceMap, Material mainMaterial)
{
this.materialChanceMap = materialChanceMap;
this.mainMaterial = mainMaterial;
}
/**
* Map that contains chances for entity to spawn.
*/
final Map<Material, Pair<Double, Integer>> materialChanceMap;
/**
* Main material that can be replaced.
*/
final Material mainMaterial;
private record Chances(Map<Material, Pair<Double, Integer>> materialChanceMap, Material mainMaterial) {
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* CaveBlock addon.
*/
private CaveBlock addon;
/**
* Map that contains chances for spawning per environment.
*/
private Map<Environment, Chances> chances;
/**
* World height
*/
private int worldHeight;
}

View File

@ -0,0 +1,107 @@
package world.bentobox.caveblock.generators.populators;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.LimitedRegion;
import org.bukkit.generator.WorldInfo;
import world.bentobox.caveblock.Utils;
import world.bentobox.caveblock.generators.Ore;
import java.util.*;
/**
* @author tastybento
*/
public class NewMaterialPopulator extends BlockPopulator {
private static final int BLOB_SIZE = 1;
private static final Map<World.Environment, List<Ore>> ORES;
static {
Map<World.Environment, List<Ore>> ores = new EnumMap<>(World.Environment.class);
// Source https://minecraft.fandom.com/wiki/Blob
List<Ore> worldOres = new ArrayList<>();
worldOres.add(new Ore(-64, 16, Material.DIAMOND_ORE, 1, 10, true));
worldOres.add(new Ore(-64, 64, Material.LAPIS_ORE, 1, 7, true));
worldOres.add(new Ore(-64, 30, Material.GOLD_ORE, 2, 9, true));
worldOres.add(new Ore(0, 16, Material.TUFF, 2, 33, false));
worldOres.add(new Ore(-64, 16, Material.REDSTONE_ORE, 8, 8, true));
worldOres.add(new Ore(0, 16, Material.GRAVEL, 8, 33, false));
worldOres.add(new Ore(0, 79, Material.GRANITE, 5, 33, false));
worldOres.add(new Ore(0, 79, Material.ANDESITE, 5, 33, false));
worldOres.add(new Ore(0, 79, Material.DIORITE, 5, 33, false));
worldOres.add(new Ore(32, 320, Material.EMERALD_ORE, 11, 1, true));
worldOres.add(new Ore(95, 136, Material.COAL_ORE, 20, 17, false));
worldOres.add(new Ore(0, 96, Material.COPPER_ORE, 20, 9, true));
worldOres.add(new Ore(-64, 320, Material.IRON_ORE, 20, 9, true));
worldOres.add(new Ore(-64, 320, Material.CAVE_AIR, 8, 33, false));
ores.put(World.Environment.NORMAL, worldOres);
List<Ore> netherOres = new ArrayList<>();
netherOres.add(new Ore(1, 22, Material.ANCIENT_DEBRIS, 1, 5, true));
netherOres.add(new Ore(-64, 30, Material.NETHER_GOLD_ORE, 2, 9, true));
netherOres.add(new Ore(0, 16, Material.GRAVEL, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.BASALT, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.BLACKSTONE, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.FIRE, 8, 33, false));
netherOres.add(new Ore(200, 320, Material.GLOWSTONE, 8, 33, false));
netherOres.add(new Ore(-64, 320, Material.CAVE_AIR, 8, 33, false));
netherOres.add(new Ore(-64, 320, Material.LAVA, 8, 33, false));
netherOres.add(new Ore(0, 16, Material.MAGMA_BLOCK, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.CRIMSON_FUNGUS, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.WARPED_FUNGUS, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.CRIMSON_NYLIUM, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.WARPED_NYLIUM, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.SHROOMLIGHT, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.CRIMSON_STEM, 8, 33, false));
netherOres.add(new Ore(0, 320, Material.WARPED_STEM, 8, 33, false));
netherOres.add(new Ore(-64, 34, Material.SOUL_SOIL, 20, 17, false));
netherOres.add(new Ore(0, 96, Material.NETHER_QUARTZ_ORE, 20, 9, true));
netherOres.add(new Ore(-64, 320, Material.BONE_BLOCK, 20, 9, true));
ores.put(World.Environment.NETHER, netherOres);
List<Ore> endOres = new ArrayList<>();
endOres.add(new Ore(32, 320, Material.PURPUR_BLOCK, 11, 1, true));
endOres.add(new Ore(95, 136, Material.OBSIDIAN, 20, 17, false));
endOres.add(new Ore(-64, 320, Material.CAVE_AIR, 8, 33, false));
ores.put(World.Environment.THE_END, endOres);
ORES = Collections.unmodifiableMap(ores);
}
private final int worldDepth;
public NewMaterialPopulator(int worldDepth) {
this.worldDepth = worldDepth;
}
@Override
public void populate(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, LimitedRegion limitedRegion) {
final int worldHeight = Math.min(worldInfo.getMaxHeight(), this.worldDepth);
for (int y = worldInfo.getMinHeight(); y < worldHeight - 1; y++) {
for (Ore o : ORES.get(worldInfo.getEnvironment())) {
if (y > o.minY() && y < o.maxY() && random.nextInt(100) <= o.chance()) {
pasteBlob(worldInfo, random, chunkX, chunkZ, limitedRegion, y, o);
if (o.cont()) {
break;
}
}
}
}
}
private void pasteBlob(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, LimitedRegion limitedRegion, int y, Ore o) {
int offset = random.nextInt(16);
for (int x = Math.max(0, offset - BLOB_SIZE); x < Math.min(16, offset + BLOB_SIZE); x++) {
for (int z = Math.max(0, offset - BLOB_SIZE); z < Math.min(16, offset + BLOB_SIZE); z++) {
for (int yy = Math.max(worldInfo.getMinHeight(), y - BLOB_SIZE); yy < Math.min(worldInfo.getMaxHeight(), y + BLOB_SIZE); yy++) {
Location location = Utils.getLocationFromChunkLocation(x, yy, z, chunkX, chunkZ);
if (!limitedRegion.isInRegion(location)) {
continue;
}
if (limitedRegion.getType(location).isSolid() && random.nextBoolean()) {
limitedRegion.setType(location, o.material());
}
}
}
}
}
}

View File

@ -16,14 +16,14 @@ import world.bentobox.caveblock.CaveBlock;
/**
* This listener checks player movement. If enabled, players will be deny to get over world depth limit and
* This listener checks player movement. If enabled, players will be denied to get over world depth limit and
* if alternative teleports is enabled, then falling in void also will be processed.
*/
public class CustomHeightLimitations implements Listener
{
/**
* Simple constructor
* @param addon
* @param addon Addon
*/
public CustomHeightLimitations(CaveBlock addon)
{
@ -53,7 +53,7 @@ public class CustomHeightLimitations implements Listener
// Prevent to get over world height
if (nextY >= this.worldHeight)
{
User.getInstance(player).sendMessage("caveblock.cave-limit-reached");
User.getInstance(player).sendMessage("caveblock.general.errors.cave-limit-reached");
event.setCancelled(true);
}
}
@ -86,7 +86,7 @@ public class CustomHeightLimitations implements Listener
/**
* This method checks and returns if current player movement from location to to location should be
* This method checks and returns if current player movement from location to location should be
* managed by current addon.
* @param nextY NextY location for player.
* @param player Player who makes movement
@ -120,10 +120,10 @@ public class CustomHeightLimitations implements Listener
/**
* CaveBlock addon
*/
private CaveBlock addon;
private final CaveBlock addon;
/**
* This variable store world height.
*/
private int worldHeight;
private final int worldHeight;
}

View File

@ -1,7 +1,7 @@
name: CaveBlock
main: world.bentobox.caveblock.CaveBlock
version: ${version}${build.number}
api-version: 1.13.0
api-version: 1.19.0
metrics: true
repository: "BentoBoxWorld/CaveBlock"
icon: "STONE_PICKAXE"

View File

@ -9,12 +9,12 @@ caveblock:
admin: cbadmin cba
# The default action for new player command call.
# Sub-command of main player command that will be run on first player command call.
# By default it is sub-command 'create'.
# By default, it is the sub-command 'create'.
# Added since 1.13.0.
new-player-action: create
# The default action for player command.
# Sub-command of main player command that will be run on each player command call.
# By default it is sub-command 'go'.
# By default, it is the sub-command 'go'.
# Added since 1.13.0.
default-action: go
world:
@ -69,10 +69,6 @@ world:
# Cave height - Lowest is 5.
# It is the y coordinate of the bedrock block in the schem.
cave-height: 60
# Use your own world generator for this world.
# 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.
use-own-generator: true
# Maximum number of caves in the world. Set to -1 or 0 for unlimited.
# If the number of caves is greater than this number, it will stop players from creating caves.
max-caves: 0
@ -80,7 +76,7 @@ world:
# a new cave for example. Options are SURVIVAL, CREATIVE, ADVENTURE, SPECTATOR
default-game-mode: SURVIVAL
# The default biome for the overworld
default-biome: MOUNTAINS
default-biome: PLAINS
# The maximum number of players a player can ban at any one time in this game mode.
# The permission caveblock.ban.maxlimit.X where X is a number can also be used per player
# -1 = unlimited
@ -93,6 +89,11 @@ world:
# This indicate how many times block should be tried to generate.
# /!\ BentoBox currently does not support changing this value mid-game. If you do need to change it, do a full reset of your databases and worlds.
generation-tries: 2
# Should we use the new material generator ?
# This will generate ores and blocks similar to how vanilla does,
# but it will override the blocks settings of each world.
# /!\ BentoBox currently does not support changing this value mid-game. If you do need to change it, do a full reset of your databases and worlds.
use-new-material-generator: false
normal:
#
# Make over world roof of bedrock, if false, it will be made from stone

View File

@ -24,6 +24,7 @@ caveblock:
already-have-island: "&cYou already have a cave!"
no-safe-location-found: "&cCould not find a safe spot to teleport you to on the cave."
not-owner: "&cYou are not the owner of your cave!"
cave-limit-reached: "&c You have reached the top of your cave. You cannot get higher!"
commands:
# Parameters in <> are required, parameters in [] are optional
admin:
@ -289,6 +290,6 @@ caveblock:
protection:
flags:
SKY_WALKER_FLAG:
description: "&5&oThis allows to enable/disable\n&5&oability to walk on the\n&5&otop of the cave world\n&5&owithout extra permissions."
description: "&5&oEnable/disable\n&5&o the ability to walk on\n&5&o the top of the cave world\n&5&o without extra permissions."
name: "Sky Walker"
hint: "Allows to walk on cave ceiling."
hint: "Allows to walk on the cave roof."

View File

@ -297,4 +297,5 @@ protection:
&5&ola habilidad para caminar en el
&5&otecho del mundo de cuevas
&5&osin permisos extra.
name: Caminante aéreo
hint: Permite caminar en el techo de la cueva

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,301 @@
---
caveblock:
sign:
line0: "&cCaveBlock"
line1: Witaj!
line2: "[name]"
line3: Zacznij kopać! &c<3
informational:
to-nether: Uuu... Pech, wpadłes do Netheru.
to-the-end: To już jest koniec.
to-normal: Powrót do jaskini.
general:
errors:
no-island: "&cNie masz jaskini!"
player-has-island: "&cGracz już posiada jaskinie!"
player-has-no-island: "&cTen gracz nie posiada jaskini!"
already-have-island: "&cJuż masz jaskinie!"
no-safe-location-found: "&cNie można znaleźć bezpiecznego miejsca dla teleportu
do jaskini."
not-owner: "&cTo nie twoja jaskinia!"
commands:
admin:
team:
add:
name-has-island: "&c[name] posiada jaskinie. Pierw wyrejestruj lub usuń!"
success: "&b[name]&a został dodany do jaskini gracza &b[owner]."
kick:
success: "&b[name] &azostał wyrzucony z jaskini gracza &b[owner]."
setowner:
description: przenosi własności jaskini do gracza
already-owner: "&c[name] jest już właścicielem tej jaskini!"
success: "&b name]&a jest teraz właścicielem tej jaskini."
range:
description: Zasięg komendy Jaskinii Admina
display:
description: pokaż/ukryj wskaźniki zasięgu jaskiń
hint: |-
&cCzerwone ikony bariery &fpokazują aktualny limit zasięgu chronionego jaskini.
&7Szare cząsteczki &fpokazują maksymalny limit jaskini.
&aZielone cząsteczki &fpokazują domyślny zasięg ochrony, jeśli zasięg ochrony jaskini różni się od niego.
set:
description: ustawia zasięg ochrony jaskini
success: "&aUstaw zasięg ochrony jaskini na &b[liczba]&a."
reset:
description: resetuje zasięg chroniony jaskini do wartości domyślnych świata
success: "&aZresetuj zasięg ochrony jaskini na &b[numer]&a."
register:
description: zarejestruj gracza w niezarejestrowanej jaskini, w której się
znajdujesz
registered-island: "&aZarejestrowano gracza do jaskini w [xyz]."
already-owned: "&cJaskinia jest już własnością innego gracza!"
no-island-here: "&cTutaj nie ma jaskini. Potwierdź, aby utworzyć."
in-deletion: "&cTo miejsce jaskini jest obecnie usuwane. Spróbuj później."
cannot-make-island: "&cPrzepraszamy, nie można tu umieścić jaskini. Zobacz
konsolę, aby poznać możliwe błędy."
unregister:
description: wyrejestruj właściciela z jaskini, ale zachowaj bloki jaskiniowe
unregistered-island: "&aNiezarejestrowany gracz z jaskini w [xyz]."
info:
description: uzyskaj informacje o tym, gdzie jesteś lub o jaskini gracza
no-island: "&cNie jesteś teraz w jaskini ..."
title: "======== Informacje o jaskini ========"
islands-in-trash: "&dGracz ma jaskinie w koszu."
is-spawn: Wyspa jest jaskinią spawnu
switchto:
description: zmień jaskinię gracza na ponumerowaną znajdującą się w koszu
out-of-range: "&cNumer musi mieścić się w przedziale od 1 do [number]. Użyj
&l[label] trash [player], &r&caby zobaczyć numery jaskiń"
trash:
no-unowned-in-trash: "&cŻadnych bezpańskich jaskiń w śmieciach"
no-islands-in-trash: "&cGracz nie ma jaskiń w koszu"
description: pokaż bezpańskie jaskinie lub jaskinie graczy w śmieciach
title: "&d=========== Jaskinie w koszu ==========="
count: "&l&dJaskinia [number]:"
use-switch: "&aUżyj &l[label] switchto <player> <number>&r&a aby przełączyć
gracza do jaskini w koszu"
emptytrash:
description: Usuń śmieci dla gracza lub wszystkie bezpańskie jaskinie w koszu
setrange:
description: ustaw zasięg jaskini gracza
range-updated: Zasięg jaskiń został zaktualizowany do [number]
tp:
description: teleportuj się do jaskini gracza
getrank:
description: zdobądź rangę gracza w swojej jaskini
rank-is: "&aRank to [range] w ich jaskini."
setrank:
description: ustaw rangę gracza w jego jaskini
setspawn:
description: ustaw jaskinię jako spawn dla tego świata
already-spawn: "&cTa jaskinia już się odradza!"
no-island-here: "&cNie ma tu jaskini."
confirmation: "&cCzy na pewno chcesz ustawić tę jaskinię jako miejsce odrodzenia
tego świata?"
resetflags:
description: Zresetuj wszystkie jaskinie do domyślnych ustawień flag w config.yml
delete:
description: usuwa jaskinię gracza
cannot-delete-owner: "&cWszyscy członkowie jaskini muszą zostać wyrzuceni
z jaskini przed jej usunięciem."
deleted-island: "&aWyspa w &e[xyz] &azostała pomyślnie usunięta."
island:
go:
description: teleportować cię do swojej jaskini
teleport: "&aTeleportuję Cię do Twojej jaskini."
help:
description: Główne dowództwo jaskini
create:
description: stwórz jaskinię, korzystając z opcjonalnego planu (wymaga pozwolenia)
too-many-islands: "&cNa tym świecie jest zbyt wiele jaskiń: nie ma wystarczająco
dużo miejsca, aby stworzyć twoją."
unable-create-island: "&cTwoja jaskinia nie może zostać wygenerowana, skontaktuj
się z administratorem."
creating-island: "&aTworzenie jaskini, proszę chwilę poczekać..."
pick: "&aWybierz jaskinię"
info:
description: wyświetlaj informacje o swojej jaskini lub jaskini gracza
near:
description: pokaż nazwy sąsiednich jaskiń wokół ciebie
the-following-islands: "&aW pobliżu znajdują się następujące jaskinie:"
no-neighbors: "&cNie masz bezpośrednio sąsiadujących jaskiń!"
reset:
description: uruchom ponownie jaskinię i usuń starą
must-remove-members: "&cMusisz usunąć wszystkich członków ze swojej jaskini,
zanim będziesz mógł ją ponownie uruchomić (/island team kick <gracz>)."
sethome:
must-be-on-your-island: "&cMusisz być w swojej jaskini, aby wrócić do domu!"
home-set: "&6Twój dom w jaskini został ustawiony na bieżącą lokalizację."
setname:
description: ustaw nazwę dla swojej jaskini
resetname:
description: zresetuj nazwę jaskini
team:
coop:
description: zrób ranking kooperacyjny gracza w swojej jaskini
uncoop:
you-are-no-longer-a-coop-member: "&cNie jesteś już członkiem współpracy
w jaskini [name]"
all-members-logged-off: "&cWszyscy członkowie jaskini wylogowali się, więc
nie jesteś już członkiem kooperacji w jaskini [name]"
trust:
description: dać graczowi zaufaną rangę w swojej jaskini
invite:
description: zaproś gracza do swojej jaskini
name-has-invited-you: "&a[name] zaprasza Cię do swojej jaskini."
you-will-lose-your-island: "&cOSTRZEŻENIE! Stracisz swoją jaskinię, jeśli
się zgodzisz!"
errors:
island-is-full: "&cTwoja jaskinia jest pełna, nie możesz nikogo zaprosić."
accept:
you-joined-island: "&aDołączyłeś do jaskini! Użyj /[etykieta] informacji
o zespole, aby zobaczyć innych członków."
name-joined-your-island: "&a[name] dołączył do Twojej jaskini!"
confirmation: |-
&cCzy na pewno chcesz przyjąć to zaproszenie?
&c&lZgubisz&n&r &c&lyswoją obecną jaskinię!
reject:
you-rejected-invite: "&aOdrzuciłeś zaproszenie do jaskini."
name-rejected-your-invite: "&c[name] odrzucił Twoje zaproszenie do jaskini!"
cancel:
description: anuluj oczekujące zaproszenie do swojej jaskini
leave:
description: opuść swoją jaskinię
left-your-island: "&c[name] &rozszczep swoją jaskinię"
kick:
description: usuń członka ze swojej jaskini
owner-kicked: "&cWłaściciel wykopał cię z jaskini!"
success: "&b[name] &został wyrzucony z Twojej jaskini."
demote:
description: zdegraduj gracza w swojej jaskini w dół o rangę
promote:
description: awansować gracza w swojej jaskini na wyższą rangę
setowner:
description: przenieść własność jaskini na członka
errors:
target-is-not-member: "&cTen gracz nie jest częścią twojej drużyny jaskiniowej!"
name-is-the-owner: "&a[name] jest teraz właścicielem jaskini!"
you-are-the-owner: "&aJesteś teraz właścicielem jaskini!"
ban:
description: zbanuj gracza ze swojej jaskini
cannot-ban-more-players: "&c Osiągnąłeś limit banów, nie możesz zbanować więcej
graczy ze swojej jaskini."
player-banned: "&b[name]&c jest teraz zablokowany w Twojej jaskini."
owner-banned-you: "&b[name]&c zabronił Ci wstępu do swojej jaskini!"
you-are-banned: "&bNie masz dostępu do tej jaskini!"
unban:
description: odbanuj gracza z twojej jaskini
player-unbanned: "&b[name]&a jest teraz odblokowany w Twojej jaskini."
you-are-unbanned: "&b[name]&a odblokował cię w swojej jaskini!"
banlist:
noone: "&aNikt nie jest zabroniony w tej jaskini."
settings:
description: wyświetl ustawienia jaskini
expel:
description: wyrzuć gracza ze swojej jaskini
not-on-island: "&cTego gracza nie ma w twojej jaskini!"
player-expelled-you: "&b[name]&c wyrzucił cię z jaskini!"
ranks:
owner: Król krasnoludów
sub-owner: Krasnoludzki Rycerz
member: Krasnolud
trusted: Zaufane
coop: Kooperacja
visitor: Człowiek
banned: Ork
protection:
flags:
ENDERMAN_GRIEFING:
description: |-
&aEndermen może usunąć
&blokady z jaskiń
name: Rozpacz Endermana
ENTER_EXIT_MESSAGES:
island: Jaskinia [name]
GEO_LIMIT_MOBS:
description: |-
&aUsuń moby, które idą
&poza chronionym
&ostań w przestrzeni
name: "&eOgranicz moby do jaskini"
ISLAND_RESPAWN:
description: |-
&aGracze odradzają się
&w ich jaskini
name: Odrodzenie w jaskini
LIQUIDS_FLOWING_OUT:
name: Płyny wypływające poza jaskinie
description: |-
&aPrzełącz, czy płyny mogą wypływać na zewnątrz
&a zasięgu ochrony jaskini.
LOCK:
description: Przełącz blokadę
name: Zablokuj jaskinię
NATURAL_SPAWNING_OUTSIDE_RANGE:
name: Naturalne stworzenie odradzające się poza zasięgiem
description: |-
&aPrzełącz czy stworzenia (zwierzęta i
i potwory) mogą naturalnie odradzać się na zewnątrz
&aa zasięg ochrony jaskini.
&cPamiętaj, że nie zapobiega to stworzeniom
&cby odradzać się za pomocą generatora mobów lub spawnu
&ceg.
OFFLINE_GROWTH:
description: |-
&aPo wyłączeniu rośliny
&nie będzie rosnąć w jaskiniach
&kiedy wszyscy członkowie są offline.
&aMoże pomóc zmniejszyć opóźnienia.
name: Rozwój offline
OFFLINE_REDSTONE:
description: |-
&aKiedy wyłączone, czerwony kamień
&nie będzie działać w jaskiniach
&gdzie wszyscy członkowie są offline.
&aMoże pomóc zmniejszyć opóźnienia.
name: Offline Redstone
PISTON_PUSH:
description: |-
&aZezwalaj tłokom na pchanie
&blokuje na zewnątrz jaskini
name: Popychanie tłoka
REMOVE_MOBS:
description: |-
&aUsuń potwory, gdy
&ateleport do jaskini
name: Usuń potwory
TREES_GROWING_OUTSIDE_RANGE:
name: Drzewa rosnące poza zasięgiem
description: |-
&aPrzełącz, czy drzewa mogą rosnąć na zewnątrz i
zakres ochrony &acave, czy nie.
PREVENT_TELEPORT_WHEN_FALLING:
name: Zapobiegaj teleportacji podczas upadku
description: |-
&aZapobiegaj teleportacji graczy
&z powrotem do swojej jaskini za pomocą poleceń
i jeśli spadają.
hint: "&cNie możesz teleportować się z powrotem do swojej jaskini, gdy spadasz."
locked: "&cTa jaskinia jest zamknięta!"
protected: "&cJaskinia chroniona: [description]"
spawn-protected: "&cSpawn chroniony: [description]"
panel:
PROTECTION:
description: |-
&aUstawienia ochrony
&dla tej jaskini
SETTING:
description: |-
&aUstawienia ogólne
&dla tej jaskini
protection:
flags:
SKY_WALKER_FLAG:
description: |-
&5&oPozwala to włączyć/wyłączyć
&5&możliwość chodzenia po
&5&otop świata jaskiń
&5&obez dodatkowych uprawnień.
name: Sky Walker
hint: Pozwala chodzić po suficie jaskini.

View File

@ -0,0 +1,304 @@
---
caveblock:
sign:
line0: "&cCaveBlock"
line1: Добро пожаловать!
line2: "[name]"
line3: Начни копать! &c<3
informational:
to-nether: Так неудачно впасть в ад.
to-the-end: Вы достигли конца.
to-normal: Вернуться к вашей пещере.
general:
errors:
no-island: "&cУ вас нет пещеры!"
player-has-island: "&cУ этого игрока уже есть пещера!"
player-has-no-island: "&cУ этого игрока нет пещеры!"
already-have-island: "&cУ вас уже есть пещера!"
no-safe-location-found: "&cНе удалось найти безопасное место для телепортации
в пещеру."
not-owner: "&cВы не владелец этой пещеры!"
commands:
admin:
team:
add:
name-has-island: "&c[name] имеет пещеру. Сначала отмените регистрацию или
удалите её!"
success: "&b[name]&a был добавлен в пещеру игрока&b [owner]&a."
kick:
success: "&b[name]&a был выгнан из пещеры &b[owner]&a."
setowner:
description: передать владение пещеры игроку
already-owner: "&c[name] уже является владельцем этой пещеры!"
success: "&b[name]&a теперь является владельцем этой пещеры."
range:
description: Пещерный диапазон (Админ-команда)
display:
description: показать/скрыть индикаторы диапазона пещеры
hint: |-
&cКрасные барьеры &f- показывают текущий предел защищенного пещерного диапазона.
&7Серые Частицы &f- показывают максимальный предел пещеры.
&aЗеленные Частицы &f- показывают защищенный диапазон по умолчанию, если диапазон защиты пещеры отличается от него.
set:
description: устанавливает диапазон защиты пещеры
success: "&aУстановить диапазон защиты пещеры до &b[number]&a."
reset:
description: сбрасывает защищенный пещерой диапазон в мир по умолчанию
success: "&aСбросить диапазон защиты пещеры до &b[number]&a."
register:
description: зарегистрировать игрока в неизвестной пещере, в которой вы находитесь
registered-island: "&aЗарегистрирован игрок в пещере [xyz]."
already-owned: "&cПещера уже принадлежит другому игроку!"
no-island-here: "&cИ здесь нет пещеры. Подтвердите, чтобы сделать один."
in-deletion: "&cЭто пещерное пространство в настоящее время удаляется. Попробуй
позже."
cannot-make-island: "&cПещера не может быть размещена здесь, извините. Смотрите
консоль для возможных ошибок."
unregister:
description: не зарегистрирован владелец в пещере, но сохранены пещерные блоки
unregistered-island: "&aНезарегистрированный игрок из пещеры в [xyz]."
info:
description: получить информацию о том, где вы находитесь или пещера игрока
no-island: "&cВы не в пещере сейчас..."
title: "==========Информация о пещере============"
islands-in-trash: "&dИгрок имеет пещеры в мусорном ведре."
is-spawn: Этот остров является спавном.
switchto:
description: переключить пещеру игрока на пронумерованную в мусорном ведре
out-of-range: "&cНомер должен быть от 1 до [number]. Используйте &l[label]
мусорки [player] &r&c, чтобы увидеть номера пещер"
trash:
no-unowned-in-trash: "&cНе принадлежат пещеры в мусоре"
no-islands-in-trash: "&cИгрок не имеет пещер в мусорном ведре"
description: показать неиспользуемые пещеры или пещеры игрока в мусорном ведре
title: "&d===========Пещеры в корзине==========="
count: "&l&dПещера [number]:"
use-switch: "&aИспользуйте &l[label] чтобы поменять на <игрок> <номер> &r&a,
чтобы переключить игрока в пещеру в корзине"
emptytrash:
description: Очистить мусор для игрока, или все ненужные пещеры в мусоре
setrange:
description: установить диапазон пещеры игрока
range-updated: Пещерный диапазон обновлен до [number]
tp:
description: телепортироваться в пещеру игрока
getrank:
description: получить звание игрока в своей пещере
rank-is: "&aРанг - [rank] в этой пещере."
setrank:
description: установить ранг игрока в своей пещере
setspawn:
description: установить пещеру как спавн для этого мира
already-spawn: "&cЭта пещера уже спавн!"
no-island-here: "&cЗдесь нет пещеры."
confirmation: "&сВы уверены, что хотите установить эту пещеру в качестве спавна
для этого мира?"
resetflags:
description: Сброс всех пещер к настройкам флага по умолчанию в config.yml
delete:
description: удаляет пещеру игрока
cannot-delete-owner: "&cВсе члены пещеры должны быть выгнаны из пещеры перед
удалением."
deleted-island: "&aОстров на &e[xyz] &aбыл успешно удален."
island:
go:
description: телепортировать вас в вашу пещеру
teleport: "&aТелепортируем вас в вашу пещеру."
help:
description: Основная пещерная команда
create:
description: создать пещеру, используя необязательный проект (требуется разрешение)
too-many-islands: "&cВ этом мире слишком много пещер: недостаточно места для
создания вашей."
unable-create-island: "&cВашу пещеру не удалось создать, обратитесь к администратору."
creating-island: "&aСоздавается ваша пещера, пожалуйста, подождите..."
pick: "&cВыберите пещеру"
info:
description: отображать информацию о вашей пещере или пещере игрока
near:
description: показать названия соседних пещер вокруг вас
the-following-islands: "&aСледующие пещеры находятся поблизости:"
no-neighbors: "&cУ вас нет ближайших соседних пещер!"
reset:
description: перезапустите свою пещеру и удалите старую
must-remove-members: "&cВы должны удалить всех участников из своей пещеры,
прежде чем сможете ее перезапустить (/ island team kick <player>)."
sethome:
must-be-on-your-island: "&cВы должны быть в своей пещере, чтобы установить
дом!"
home-set: "&6Ваш дом в пещере был настроен на ваше текущее местоположение."
setname:
description: установить имя для вашей пещеры
resetname:
description: сбросить имя пещеры
team:
coop:
description: Добавить игрока в вашу пещеру
uncoop:
you-are-no-longer-a-coop-member: "&cВы больше не являетесь членом кооператива
пещеры [name]"
all-members-logged-off: "&cВсе участники пещеры вышли из системы, так что
вы больше не являетесь членом кооператива пещеры [name]"
trust:
description: дать игроку звание доверенного в вашей пещере
invite:
description: пригласить игрока к вашей пещере
name-has-invited-you: "&a[name] пригласил вас к его пещере."
you-will-lose-your-island: "&сВНИМАНИЕ! Вы потеряете свою пещеру, если вы
примете!"
errors:
island-is-full: "&сВаша пещера заполнена, вы не можете пригласить кого-либо
еще."
accept:
you-joined-island: "&aВы присоединились к пещере! Используйте /[label]
информацию о команде, чтобы увидеть других участников."
name-joined-your-island: "&a[name] присоединилось к вашей пещере!"
confirmation: |-
&cВы уверены, что хотите принять это приглашение?
&c&lВы будете &nУДАЛЕНЫ &r&c с вашей пещеры!
reject:
you-rejected-invite: "&aВы отклонили приглашение присоединиться к пещере."
name-rejected-your-invite: "&c[name] отклонил ваше приглашение в пещеру!"
cancel:
description: отменить ожидающее приглашение присоединиться к вашей пещере
leave:
description: покинуть свою пещеру
left-your-island: "&c[name] вышел с вашей пещеры"
kick:
description: удалить члена из вашей пещеры
owner-kicked: "&cВладелец выгнал вас из пещеры!"
success: "&b[name]&a был изгнан из вашей пещеры."
demote:
description: понизить игрока в вашей пещере по рангу
promote:
description: повысить игрока в вашей пещере до более высокого звания
setowner:
description: передать право собственности на пещеру участнику
errors:
target-is-not-member: "&cЭтот игрок не является частью вашей пещерной
команды!"
name-is-the-owner: "&a[name] теперь является владельцем пещеры!"
you-are-the-owner: "&aТеперь вы владелец пещеры!"
ban:
description: забанить игрока из вашей пещеры
cannot-ban-more-players: "&cВы достигли предела банов, вы не можете забанить
больше игроков из своей пещеры."
player-banned: "&b[name]&c теперь заблокировано в вашей пещере."
owner-banned-you: "&b[name]&c забанили вас из своей пещеры!"
you-are-banned: "&bВы забанены в этой пещере!"
unban:
description: разблокировать игрока из вашей пещеры
player-unbanned: "&b[name]&a теперь не заблокирован в вашей пещере."
you-are-unbanned: "&b[name] &aне пускай тебя в пещеру"
banlist:
noone: "&aНикто не забанен в этой пещере."
settings:
description: настройки отображения пещеры
expel:
description: изгнать игрока из вашей пещеры
not-on-island: "&cэтот игрок не в вашей пещере!"
player-expelled-you: "&b[name]&c выгнал тебя из пещеры!"
ranks:
owner: Король гномов
sub-owner: Гном Рыцарь
member: Гном
trusted: доверенный
coop: КО-ОП
visitor: Человек
banned: Огр
protection:
flags:
ENDERMAN_GRIEFING:
description: |-
&aЭндермен может удалить
&aблоки из пещер
name: Гриферство эндермена
ENTER_EXIT_MESSAGES:
island: пещера [name]
GEO_LIMIT_MOBS:
description: |-
&aУдалиет мобов, которые уходят
&aвне защиты
&aв пещеру
name: "&eЛимит мобов в пещере"
ISLAND_RESPAWN:
description: |-
&aреспаун игрока
&aв его пещере
name: Респавн пещеры
LIQUIDS_FLOWING_OUT:
name: Жидкости текут вне пещер
description: |-
&aВключить, могут ли жидкости вытекать наружу
&aиз диапазона защиты пещеры.
LOCK:
description: Включить/Выключить жидкости
name: Замок пещеры
NATURAL_SPAWNING_OUTSIDE_RANGE:
name: Естественное существо появляется вне пределов досягаемости
description: |-
&aПереключить ли существа (животных и
&aмонстров) могут порождаться естественным путем снаружи
&aДиапазон защиты пещеры.
&cОтметьте, что это не мешает существам
&c порождение через порождения моба или спавна
&cяйца.
OFFLINE_GROWTH:
description: |-
&aКогда выключено, растения
&aне будет расти в пещерах
&aкогда все участники не в сети.
&aМожет помочь уменьшить отставание.
name: Оффлайн Рост
OFFLINE_REDSTONE:
description: |-
&aКогда отключено, Редстоун
&aне будет работать в пещерах
&aкогда все участники не в сети.
&aМожет помочь уменьшить отставание.
name: Оффлайн Редстоун
PISTON_PUSH:
description: |-
&aРазрешить толкать поршни
&aи за пределами пещеры
name: Поршневой толчок
REMOVE_MOBS:
description: |-
&aУдалить монстров, при
&aтелепортации в пещеру
name: Удалить монстров
TREES_GROWING_OUTSIDE_RANGE:
name: Деревья, растущие вне диапазона
description: |-
&aВключить, могут ли деревья расти вне
&aДиапазона защиты пещеры или нет.
PREVENT_TELEPORT_WHEN_FALLING:
name: Предотвратить телепорт при падении
description: |-
&aПредотвращение игроков от &aтелепортации
&aснова в свою пещеру, используя команды
&aесли они падают.
hint: "&cВы не можете телепортироваться обратно в свою пещеру, пока падаете."
locked: "&cЭта пещера заперта!"
protected: "&cПещера защищена: [description]"
spawn-protected: "&cСпавн защищен: [description]"
panel:
PROTECTION:
description: |-
&aнастройки защиты
&aдля этой пещеры
SETTING:
description: |-
&aОбщие настройки
&aдля этой пещеры
protection:
flags:
SKY_WALKER_FLAG:
description: |-
&5&oЭто позволяет включить / отключить
&5&oвозможность ходить по
&5&oверхности из пещерного мира
&5&oбез дополнительных разрешений.
name: Ходящий по небу
hint: Позволяет ходить по пещерному потолку.

View File

@ -0,0 +1,292 @@
###########################################################################################
# This is a YML file. Be careful when editing. Check your edits in a YAML checker like #
# the one at http://yaml-online-parser.appspot.com #
###########################################################################################
caveblock:
sign:
line0: "&cCaveBlock"
line1: "Chào mừng!"
line2: "[name]"
line3: "Đào đi! &c<3"
informational:
to-nether: "Rất tệ khi vào địa ngục."
to-the-end: "Kết thúc rồi."
to-normal: "Về hang của bạn."
# Override BentoBox default command strings
# General strings
general:
errors:
no-island: "&cBạn không có hang!"
player-has-island: "&cNgười chơi đã có hang!"
player-has-no-island: "&cNgười chơi không có hang!"
already-have-island: "&cBạn đã có hang!"
no-safe-location-found: "&cKhông thể tìm thấy vị trí an toàn trong hang."
not-owner: "&cBạn không phải chủ hang!"
commands:
# Parameters in <> are required, parameters in [] are optional
admin:
team:
add:
name-has-island: "&c[name] đã có hang. Huỷ hoặc xoá nó trước!"
success: "&b[name]&a đã được thêm vào hang của &b[owner]&a."
kick:
success: "&b[name] &ađã bị đuổi từ hang của &b[owner]&a."
setowner:
description: "chuyển quyền chủ hang cho người chơi"
already-owner: "&c[name] đã là chủ hang!"
success: "&b[name]&a giờ là chủ hang."
range:
description: "lệnh độ rộng hang của Admin"
display:
description: "hiện/ẩn đánh dấu độ rộng hang"
hint: |-
&cKí tự Rào chặn đỏ &fthể hiện độ rộng vùng bảo vệ của hang.
&7Hạt Xám &fthể hiện giới hạn của hang.
&aHạt Xanh &fthể hiện vùng bảo vệ mặc định nếu vùng bảo vệ của hang khác mặc định.
set:
description: "chỉnh vùng bảo vệ hang"
success: "&aĐã chỉnh vùng bảo vệ hang thành &b[number]&a."
reset:
description: "chỉnh vùng bảo vệ hang về mặc định"
success: "&aĐã chỉnh vùng bảo vệ hang thành &b[number]&a."
register:
description: "đăng kí người chơi vào hang không chủ ở vị trí của bạn"
registered-island: "&aĐã đăng kí người chơi ở hang [xyz]."
already-owned: "&cHang đã có chủ!"
no-island-here: "&cKhông có hang ở đây. Xác nhận để tạo."
in-deletion: "&cHang đang được xoá. Thử lại sau."
cannot-make-island: "&c Hang không thể đặt ở đây. Xem lỗi trên bảng điều khiển."
unregister:
description: "huỷ quyền chủ hang, nhưng giữ lại các khối trong hang"
unregistered-island: "&aĐã huỷ đăng kí người chơi ở hang [xyz]."
info:
description: "lấy thông về nơi bạn ở hoặc hang của người chơi"
no-island: "&cBạn không ở một hang..."
title: "========== Thông tin Hang ============"
islands-in-trash: "&dNgười chơi có hang trong thùng rác."
is-spawn: "Đảo là hang triệu hồi"
switchto:
description: "chuyển hang của người chơi thành một số trong thùng rác"
out-of-range: "&cSố phải từ 1 đến [number]. Dùng &l[label] trash [player] &r&cđể xem số hang"
trash:
no-unowned-in-trash: "&cKhông có hang không chủ trong thùng rác"
no-islands-in-trash: "&cNgười chơi không có hang trong thùng rác"
description: "xem hang không chủ hoặc của người chơi trong thùng rác"
title: "&d=========== Hang trong Thùng Rác ==========="
count: "&l&dHang [number]:"
use-switch: "&aDùng &l[label] switchto <player> <number>&r&a để chuyển người chơi vào hang trong thùng rác"
emptytrash:
description: "Dọn rác cho người chơi, hoặc toàn bộ hang không chủ trong thùng rác"
setrange:
description: "chỉnh độ rộng hang của người chơi"
range-updated: "Đã chỉnh độ rộng của hang thành [number]"
tp:
description: "dịch chuyển đến hang của người chơi"
getrank:
description: "xem cấp độ của người chơi trong hang"
rank-is: "&aCấp độ là [rank] ở hang của họ."
setrank:
description: "chỉnh cấp độ của người chơi ở hang của họ"
setspawn:
description: "chỉnh một hang thành nơi bắt đầu ở thế giới này"
already-spawn: "&cHang này đã là nơi bắt đầu!"
no-island-here: "&cKhông có hang ở đây."
confirmation: "&cBạn có chắc là chọn hang này làm nơi bắt đầu ở thế giới này?"
resetflags:
description: "Đặt lại cờ của các hang về mặc định trong config.yml"
delete:
description: "xoá hang của người chơi"
cannot-delete-owner: "&cThành viên của hang phải bị đuổi trước khi xoá."
deleted-island: "&aĐảo &e[xyz] &ađã được xoá thành công."
island:
go:
description: "dịch chuyển đến hang của bạn"
teleport: "&aĐang dịch chuyển đến hang của bạn."
help:
description: "Lệnh hang chính"
create:
description: "tạo hang, dùng bản vẽ nếu có (cần quyền)"
too-many-islands: "&cQuá nhiều hang ở thế giới này: không đủ khoảng trống cho khu của bạn."
unable-create-island: "&cHang của bạn không được tạo, hãy liên hệ quản trị viên."
creating-island: "&aĐang tạo hang, chờ một chút..."
pick: "&aChọn hang"
info:
description: "xem thông tin hang của bạn hoặc của người chơi"
near:
description: "xem tên của hang kế bên bạn"
the-following-islands: "&aHang kế bên bạn:"
no-neighbors: "&cKhông có hang kế bên bạn!"
reset:
description: "tạo lại hang và xoá hang cũ"
must-remove-members: "&cBạn phải xoá thành viên khỏi hang trước khi xoá (/[label] team kick <player>)."
sethome:
must-be-on-your-island: "&cBạn phải ở hang của bạn để đặt nhà!"
home-set: "&6Nhà của hang đã đặt ở vị trí của bạn."
setname:
description: "đặt tên cho hang"
resetname:
description: "đặt lại tên của hang"
team:
coop:
description: "cho người chơi cấp chơi cùng với hang của bạn"
uncoop:
you-are-no-longer-a-coop-member: '&cBạn không còn chơi cùng với hang của [name].'
all-members-logged-off: '&c Người chơi ở hang đã thoát hết nên bạn không còn chơi cùng với hang của [name].'
trust:
description: "cho người chơi cấp tin tưởng với hang bạn"
invite:
description: "mời người chơi vào hang của bạn"
name-has-invited-you: "&a[name] đã mời bạn vào hang của họ."
you-will-lose-your-island: "&cCHÚ Ý! Bạn sẽ mất hang của bạn nếu chấp nhận lời mời"
errors:
island-is-full: "&cHang đã đầy, bạn không thể mời thêm."
accept:
you-joined-island: "&aBạn đã vào hang! Dùng /[label] team info để xem thành viên khác."
name-joined-your-island: "&a[name] đã vào hang của bạn!"
confirmation: |-
&cBạn có chắc muón chấp nhận lời mời này?
&c&lBạn sẽ &nMẤT&r &c&lhang hiện tại của bạn!
reject:
you-rejected-invite: "&aBạn đã từ chối lời mời vào hang."
name-rejected-your-invite: "&c[name] đã từ chối lời mời của bạn!"
cancel:
description: "huỷ lời mời đang chờ vào hang của bạn"
leave:
description: "rời hang của bạn"
left-your-island: "&c[name] &cđã rời hang của bạn"
kick:
description: "xoá thành viên khỏi hang của bạn"
owner-kicked: "&cChủ hang đã đuổi bạn!"
success: "&b[name] &ađã bị đuổi khỏi hang của bạn."
demote:
description: "hạ cấp của người chơi trong hang"
promote:
description: "nâng cấp của người chơi trong hang"
setowner:
description: "chuyển quyền chủ hang cho người chơi"
errors:
target-is-not-member: "&cNgười chơi đó không ở trong đội của bạn!"
name-is-the-owner: "&a[name] giờ là chủ hang!"
you-are-the-owner: "&aBạn giờ là chủ hang!"
ban:
description: "cấm người chơi khỏi hang của bạn"
cannot-ban-more-players: "&cĐã đạt giới hạn cấm, bạn không thể cấm thêm người."
player-banned: "&b[name]&c đã bị cấm khỏi hang của bạn."
owner-banned-you: "&b[name]&c đã cấm bạn khỏi hang của họ!"
you-are-banned: "&bBạn đã bị cấm ở hang này!"
unban:
description: "bỏ cấm người chơi khỏi hang của bạn"
player-unbanned: "&b[name]&a không còn bị cấm khỏi hang của bạn."
you-are-unbanned: "&b[name]&a huỷ cấm bạn khỏi hang của họ!"
banlist:
noone: "&aKhông ai bị cấm ở hang này."
settings:
description: "xem tuỳ chọn hang"
expel:
description: "trục xuất người chơi khỏi hang của bạn"
not-on-island: "&cNgười chơi đó không ở hang của bạn!"
player-expelled-you: "&b[name]&c đã trục xuất bạn khỏi hang của họ!"
ranks:
owner: "Vua Người Lùn"
sub-owner: "Hiệp Sĩ Người Lùn"
member: "Người Lùn"
trusted: "Tin Tưởng"
coop: "Chơi Cùng"
visitor: "Con Người"
banned: "Orc"
protection:
flags:
ENDERMAN_GRIEFING:
description: |-
&aNgười Ender có thể cướp
&akhối khỏi hang
name: "Trộm bởi Người Ender"
ENTER_EXIT_MESSAGES:
island: "hang của [name]"
GEO_LIMIT_MOBS:
description: |-
&a Xóa các quái đã rời khỏi
&a khu vực bảo vệ trong hang
name: "&eGiới hạn quái trong đảo"
ISLAND_RESPAWN:
description: |-
&aNgười chơi hồi sinh
&aở hang của họ
name: "Hồi sinh tại hang"
LIQUIDS_FLOWING_OUT:
name: "Chất lỏng tràn ra khỏi hang"
description: |-
&aBật/Tắt việc chất lỏng có thể
&atràn ra khỏi khu vực bảo vệ của hang.
LOCK:
description: "Bật/Tắt khóa"
name: "Khoá đảo"
NATURAL_SPAWNING_OUTSIDE_RANGE:
name: "Sinh quái tự nhiên ngoài hang"
description: |-
&aBật/Tắt cho phép con vật (động vật và
&aquái vật) có thể sinh tự nhiên ngoài
&akhu vực bảo vệ của hang.
&cLưu ý là nó không chặn việc sinh quái
&cbằng lồng triệu hồi hoặc trứng.
OFFLINE_GROWTH:
description: |-
&aKhi tắt, cây trồng
&asẽ không mọc lớn trong hang
&anếu tất cả thành viên đều ngoại tuyến.
&aCó thể giúp giảm lag.
name: "Mọc cây khi ngoại tuyến"
OFFLINE_REDSTONE:
description: |-
&aKhi tắt, đá đỏ
&asẽ không hoạt động trong hang
&anếu tất cả thành viên đều ngoại tuyến.
&aCó thể giúp giảm lag.
&aKhông ảnh hưởng đảo triệu hồi.
name: "Đá đỏ khi ngoại tuyến"
PISTON_PUSH:
description: |-
&aCho phép pít tông đẩy
&akhối ra khỏi hang
name: "Pít tông đẩy khối"
REMOVE_MOBS:
description: |-
&aXoá quái khi dịch
&achuyển đến đảo
name: "Xoá quái"
TREES_GROWING_OUTSIDE_RANGE:
name: "Cây mọc ngoài đảo"
description: |-
&aBật/Tắt việc cây có thể mọc ngoài
&akhu vực bảo vệ trong hang.
PREVENT_TELEPORT_WHEN_FALLING:
name: "Chặn dịch chuyển khi đang rời"
description: |-
&aChặn người chơi khỏi việc dịch chuyển
&avề đảo của họ bằng lệnh khi đang rơi.
hint: '&cBạn không thể làm điều đó khi đang rơi.'
locked: "&cHang đã bị khoá!"
protected: "&cĐã bảo vệ hang: [description]"
spawn-protected: "&cĐã bảo vệ nơi bắt đầu: [description]"
panel:
PROTECTION:
description: |-
&aTuỳ chỉnh bảo vệ
&acho hang này
SETTING:
description: |-
&aTuỳ chỉnh tổng quan
&acho hang này
protection:
flags:
SKY_WALKER_FLAG:
description: "&5&oCho phép bật/tắt\n&5&oquyền để đi trên\n&5&ođỉnh của thế giới hang\n&5&omà không cần thêm quyền."
name: "Bước Trên Trời Cao"
hint: "Cho phép đi trên đỉnh hang."

View File

@ -1,286 +1,282 @@
---
caveblock:
sign:
line0: "c方块洞穴"
line1: 欢迎!
line3: 开始挖掘! c <3
line0: "&c洞穴生存"
line1: "欢迎!"
line2: "[name]"
line3: "开始挖掘吧! &c<3"
informational:
to-nether: 真倒霉到地狱了。
to-the-end: 您已经到了末地。
to-normal: 回到你的洞穴。
to-nether: "太不走运了! 掉进了下界."
to-the-end: "您到达了末地."
to-normal: "回到您的洞穴."
general:
errors:
no-island: "c您没有洞穴"
player-has-island: "c玩家已经有一个山洞了"
player-has-no-island: "c该玩家没有洞穴"
already-have-island: "c您已经有一个山洞"
no-safe-location-found: "c在山洞找不到传送您的安全地点。"
not-owner: "c您不是洞穴的所有者"
no-island: "&c您还没有洞穴!"
player-has-island: "&c玩家已有洞穴!"
player-has-no-island: "&c玩家还没有洞穴!"
already-have-island: "&c您已经拥有洞穴!"
no-safe-location-found: "&c无法将您传送到洞穴中, 因为没有找到安全的位置."
not-owner: "&c您不是您洞穴的主人!"
commands:
admin:
team:
add:
name-has-island: "c [name]有一个山洞。首先注销或删除它们!"
success: "b [name]a已添加到b [owner]a的洞穴中。"
name-has-island: "&c[name] 已有洞穴. 请先反注册或删除它们!"
success: "&b[name]&a 已被添加到 &b[owner]&a 的洞穴."
kick:
success: "b [name]ahas被踢出了b [owner]a的山洞。"
success: "&b[name] &a已被 &b[owner]&a 的洞穴移出."
setowner:
description: 将洞穴所有权转移给玩家
already-owner: "c [name]已经是该洞穴的所有者!"
success: "b [name]a现在是这个洞穴的所有者。"
description: "将洞穴的所有权转让给玩家"
already-owner: "&c[name] 玩家已经是此洞穴的主人了!"
success: "&b[name]&a 现在是此洞穴的主人."
range:
description: 管理员洞穴范围命令
description: "管理员洞穴边界命令"
display:
description: 显示/隐藏洞穴范围指示器
description: "显示/隐藏洞穴边界"
hint: |-
c红色屏障图标f显示当前的洞穴保护范围限制。
7灰色粒子f显示最大洞穴极限。
a绿色粒子f如果洞穴保护范围不同于默认保护范围则显示默认保护范围。
&c 红色屏障图标 &f 显示洞穴现在被保护的范围.
&7 灰色粒子 &f 显示最大边界范围.
&a 绿色粒子 &f 显示默认被保护的边界, 如果现在的边界不与其重合的话.
set:
description: 设置洞穴保护范围
success: "a将洞穴保护范围设置为b [number]a。"
description: "设置洞穴被保护的边界范围"
success: "&a洞穴被保护的范围更新至 &b[number]&a."
reset:
description: 将洞穴保护范围重置为世界默认值
success: "a将洞穴保护范围重置为b [number]a。"
description: "重置洞穴被保护的范围到当前世界的默认值"
success: "&a重置洞穴被保护的范围至 &b[number]&a."
register:
description: 注册玩家到您所在的无人洞
registered-island: "a注册玩家到[xyz]洞穴。"
already-owned: "c洞穴已被另一位玩家拥有"
no-island-here: "c这里没有洞穴。确认做一个。"
in-deletion: "c该洞穴空间当前正在被删除。等会再试。"
cannot-make-island: "c抱歉不能在此处放置洞穴。请参阅控制台以获取可能的错误。"
description: "将玩家注册到您所在的未被拥有的洞穴中"
registered-island: "&a在 [xyz] 将玩家注册到洞穴中."
already-owned: "&c此洞穴已被其他玩家所有!"
no-island-here: "&c这里还没有 box. 确认以创建一个."
in-deletion: "&c此区域正在重新生成. 请稍后重试."
cannot-make-island: "&c抱歉, 无法在此处生成洞穴. 从后台查看可能的错误."
unregister:
description: 从山洞中注销所有者,但保留山洞块
unregistered-island: "a来自[xyz]洞穴的未注册玩家。"
description: "反注册洞穴的主人, 同时保留洞穴中的方块"
unregistered-island: "&a在 [xyz] 将玩家从洞穴中反注册."
info:
description: 获取有关您所在位置或玩家洞穴的信息
no-island: "c您现在不在山洞里..."
title: "==========洞穴信息============"
islands-in-trash: "d玩家在垃圾桶中有洞穴。"
is-spawn: 岛是出生点
description: "获取您所在区域或相应玩家洞穴的信息"
no-island: "&c您未在一个洞穴中......"
title: "========== 洞穴信息 ============"
islands-in-trash: "&d玩家拥有废弃的洞穴."
is-spawn: "该区域是主城"
switchto:
description: 将玩家的洞穴切换到垃圾桶中的第一洞
out-of-range: "c数字必须介于1到[number]之间。使用l [label]垃圾[player]rc查看洞穴编号"
description: "将玩家的洞穴切换到废弃的洞穴中的第一位"
out-of-range: "&c数字必须从 1 到 [number]. 输入 &l[label] trash [player] &r&c来查看洞穴数量"
trash:
no-unowned-in-trash: "c垃圾桶中没有无人认领的洞穴"
no-islands-in-trash: "c玩家没有洞穴在垃圾桶中"
description: 在垃圾桶中显示无人洞穴或玩家的洞穴
title: "d ============垃圾洞==========="
no-unowned-in-trash: "&c废弃的洞穴中没有无主人的洞穴"
no-islands-in-trash: "&c玩家没有废弃的洞穴"
description: "在废弃的洞穴中显示无主人的洞穴或玩家的洞穴"
title: "&d=========== 废弃的洞穴 ==========="
count: "&l&d洞穴 [number]:"
use-switch: "a使用l [label]切换到<player> <number>ra将玩家洞穴切换到垃圾桶"
use-switch: "&a输入 &l[label] switchto <player> <number>&r&a 将玩家切换到废弃的洞穴中"
emptytrash:
description: 清除玩家的垃圾桶,或垃圾桶中所有未拥有的洞穴
description: "给玩家清除废弃的洞穴, 或清除所有无主人的废弃的洞穴"
setrange:
description: 设定玩家洞穴的范围
range-updated: 洞穴范围更新为[数字]
description: "设置玩家洞穴的范围"
range-updated: "洞穴范围更新至 [number]"
tp:
description: 传送到玩家的洞穴
description: "传送到玩家的洞穴"
getrank:
description: 在他们的洞穴中获得玩家的排名
rank-is: "aRank在他们的洞穴中[排名]。"
description: "查看玩家在其洞穴中的地位"
rank-is: "&a玩家在其洞穴中的地位是 [rank]."
setrank:
description: 设定玩家在洞穴中的等级
description: "设置玩家在其洞穴中的地位"
setspawn:
description: 为这个世界设置一个洞穴
already-spawn: "c这个洞穴已经是产卵了"
no-island-here: "c这里没有洞穴。"
confirmation: "c您确定要将此洞穴设置为这个世界的生成物吗"
description: "将洞穴设置为当前世界的主城"
already-spawn: "&c此洞穴已经是主城了!"
no-island-here: "&c这里还没有洞穴."
confirmation: "&c确认要将将洞穴设置为当前世界的主城吗?"
resetflags:
description: 将所有洞穴重置为config.yml中的默认标志设置
description: "重置所有洞穴的 flag 值成 config.yml 中的默认值"
delete:
description: 删除玩家的洞穴
cannot-delete-owner: "c删除所有洞穴成员之前必须将其踢出洞穴。"
deleted-island: "e [xyz]ahas中的aIsland已成功删除。"
description: "删除一名玩家的洞穴"
cannot-delete-owner: "&c在删除此洞穴之前, 必须移出此洞穴中的所有成员."
deleted-island: "&a成功删除位于 &e[xyz] &a处的洞穴."
island:
go:
description: 传送你到你的洞穴
teleport: "a将您传送到山洞。"
description: "传送到您的洞穴"
teleport: "&a正在传送到您的洞穴."
help:
description: 主要洞穴命令
description: "洞穴主命令"
create:
description: 使用可选的蓝图创建一个洞穴(需要许可)
too-many-islands: "c这个世界上有太多的洞穴没有足够的空间来创建您的洞穴。"
unable-create-island: "c您的洞穴无法生成请与管理员联系。"
creating-island: "a创建您的洞穴请稍等..."
pick: "a选择一个山洞"
description: "使用模板创建一个新的洞穴 (需要权限)"
too-many-islands: "&c世界中含有太多洞穴了: 没有空间创建您的洞穴."
unable-create-island: "&c生成洞穴失败, 请联系管理员."
creating-island: "&a生成洞穴中, 请稍后..."
pick: "&a选择一个洞穴"
info:
description: 显示有关您的洞穴或玩家洞穴的信息
description: "显示您或相应玩家的洞穴信息"
near:
description: 显示您周围的洞穴名称
the-following-islands: "a附近有以下洞穴"
no-neighbors: "c您没有紧邻的洞穴"
description: "显示周围洞穴的名称"
the-following-islands: "&a周围的洞穴有:"
no-neighbors: "&c您的周围没有其它洞穴!"
reset:
description: 重新启动您的洞穴并删除旧的
must-remove-members: "c您必须先从洞穴中删除所有成员然后才能重新启动洞穴/岛国队踢&lt;player&gt;)。"
description: "删除现有的洞穴并重新开始"
must-remove-members: "&c在您重新开始之前, 您必须移出洞穴中的所有成员 (/island team kick <player>)."
sethome:
must-be-on-your-island: "c您必须在洞穴里才能回家"
home-set: "6您的洞穴之家已设置为您当前的位置。"
must-be-on-your-island: "&c必须在洞穴中才能设置家的位置!"
home-set: "&6洞穴家的位置已设置到您当前位置."
setname:
description: 为你的洞穴命名
description: "设置您洞穴的名称"
resetname:
description: 重设您的洞穴名称
description: "重置您洞穴的名称"
team:
coop:
description: 让玩家在你的洞穴中进行排名
description: "将玩家设置为您洞穴的副 OP"
uncoop:
you-are-no-longer-a-coop-member: "c您不再是[name]的洞穴的鸡舍成员"
all-members-logged-off: "c所有洞穴成员都已注销因此您不再是[name]洞穴的合作伙伴"
you-are-no-longer-a-coop-member: "&c您不再是 [name] 的洞穴的副 OP 了"
all-members-logged-off: "&c洞穴的所有玩家都离线了, 因此您不再是 [name] 的洞穴的副 OP 了"
trust:
description: 给玩家一个值得信赖的等级
description: "将玩家设置为您洞穴的信任者"
invite:
description: 邀请玩家加入你的洞穴
name-has-invited-you: "a [name]邀请您加入他们的洞穴。"
you-will-lose-your-island: "c警告如果您接受您将迷路"
description: "邀请一名玩家到您的洞穴中"
name-has-invited-you: "&a[name] 邀请您加入他(她)的洞穴."
you-will-lose-your-island: "&c注意! 如果接受邀请, 您将失去现有的洞穴!"
errors:
island-is-full: "c您的洞穴已满您不能邀请其他任何人。"
island-is-full: "&c您的洞穴已满, 无法再邀请更多的玩家."
accept:
you-joined-island: "a您加入了一个山洞使用/ [标签]小组信息来查看其他成员。"
name-joined-your-island: "a [name]加入了您的洞穴!"
you-joined-island: "&a您加入了一个洞穴! 输入 /[label] team info 来查看其他成员."
name-joined-your-island: "&a[name] 加入了您的洞穴!"
confirmation: |-
c确定要接受此邀请吗
cl您会nLOSErcly您当前的洞穴
&c确认要接收此邀请?
&c&l您将 &n失去&r &c&l现有的洞穴!
reject:
you-rejected-invite: "a您拒绝了加入洞穴的邀请。"
name-rejected-your-invite: "c [name]拒绝了您的洞穴邀请!"
you-rejected-invite: "&a您拒绝了加入洞穴的邀请."
name-rejected-your-invite: "&c[name] 拒绝了您加入洞穴的邀请!"
cancel:
description: 取消待处理的邀请,加入你的洞穴
description: "取消待接受/拒绝的洞穴加入邀请"
leave:
description: 离开你的洞穴
left-your-island: "c [name]cleft your cave"
description: "退出您的洞穴"
left-your-island: "&c[name] &c退出了您的洞穴"
kick:
description: 从您的洞穴中删除一个成员
owner-kicked: "c主人将您踢出山洞"
success: "b [name]ahas被踢出您的山洞。"
description: "从您的洞穴中移出一名玩家"
owner-kicked: "&c洞穴的主人移出了您!"
success: "&b[name] &a从您的洞穴中被移出."
demote:
description: 将您的玩家降级
description: "降低洞穴中一名玩家的地位"
promote:
description: 提升您的玩家排名
description: "提升洞穴中一名玩家的地位"
setowner:
description: 将您的洞穴所有权转让给成员
description: "将洞穴转让给一名成员"
errors:
target-is-not-member: 该球员不属于您的洞穴团队!
name-is-the-owner: "a [name]现在是洞穴所有者!"
you-are-the-owner: "a您现在是洞穴主人"
target-is-not-member: "&c玩家不在您洞穴的队伍中!"
name-is-the-owner: "&a[name] 现在是洞穴的主人!"
you-are-the-owner: "&a您成为了洞穴的主人!"
ban:
description: 禁止玩家进入您的洞穴
cannot-ban-more-players: "c您已达到禁令限制您不能再从您的洞穴禁赛。"
player-banned: "b [name]c现在被禁止进入您的洞穴。"
owner-banned-you: "b [name]c禁止您进入他们的洞穴"
you-are-banned: "b您被禁止进入这个洞穴"
description: "从洞穴中禁止一名玩家"
cannot-ban-more-players: "&c达到最大禁止玩家的数量, 无法再禁止更多的玩家."
player-banned: "&b[name]&c 被您的洞穴禁止."
owner-banned-you: "&b[name]&c 的洞穴禁止了您!"
you-are-banned: "&b您已被此洞穴禁止!"
unban:
description: 禁止玩家进入您的洞穴
player-unbanned: "b [name]a现在不受您的洞穴限制。"
you-are-unbanned: "b [name]a禁止您进入他们的洞穴"
description: "从洞穴中解封一名玩家"
player-unbanned: "&b[name]&a 被您的洞穴解封."
you-are-unbanned: "&b[name]&a 的洞穴解封了您!"
banlist:
noone: "a没有人被禁止进入这个洞穴。"
noone: "&a没有玩家被此洞穴禁止."
settings:
description: 显示洞穴设置
description: "显示洞穴设置"
expel:
description: 将玩家驱逐出您的洞穴
not-on-island: "c那个玩家不在你的洞穴里"
player-expelled-you: "b [name]c将您赶出了山洞"
description: "从洞穴中请出一名玩家"
not-on-island: "&c该玩家不在您洞穴中!"
player-expelled-you: "&c您被 &b[name]&c 的洞穴请出!"
ranks:
owner: 矮人王
sub-owner: 矮人骑士
member: 侏儒
trusted: 值得信赖
coop: 鸡舍
visitor: 人的
banned: 兽人
owner: "矮人王"
sub-owner: "矮人骑士"
member: "小矮人"
trusted: "信任者"
coop: "副 OP"
visitor: "人类"
banned: "被禁止玩家"
protection:
flags:
ENDERMAN_GRIEFING:
description: |-
aEndermen可以删除
a洞穴
name: 恩德曼悲痛
&a末影人可以
&a移动洞穴中的方块
name: "末影人破坏"
ENTER_EXIT_MESSAGES:
island: "[名字]的洞穴"
island: "[name] 的洞穴"
GEO_LIMIT_MOBS:
description: |-
a删除小怪
&外部保护
&占用空间
name: "e限制小怪进入山洞"
&a移除在洞穴保护
&a范围外的生物
name: "&e将生物限制在洞穴内"
ISLAND_RESPAWN:
description: |-
a玩家重生
和他们的洞穴
name: 洞穴重生
&a玩家在他们的
&a洞穴中重生
name: "洞穴中重生"
LIQUIDS_FLOWING_OUT:
name: 液体在洞穴外流动
name: "流体流出洞穴"
description: |-
a切换液体是否可以流出
a洞穴的保护范围。
&a切换流体是否能
&a流出洞穴保护范围.
LOCK:
description: 拨动锁
name: 锁洞
description: "切换是否禁止访客访问"
name: "锁定洞穴"
NATURAL_SPAWNING_OUTSIDE_RANGE:
name: 自然生物产生范围外
name: "常规生物在保护范围外生成"
description: |-
a切换是否生物动物和
amonsters可以在外面自然产卵
aa洞穴的保护范围。
&a切换常规生物 (动物和
&a怪物) 是否能在洞穴保护
&a范围外生成.
c请注意这不会阻止生物
cto通过暴民生成器或生成器生成
cegg。
&c注意, 此操作不能防止
&c洞穴保护范围外的
&c刷怪笼或刷怪蛋生成生物.
OFFLINE_GROWTH:
description: |-
a禁用时植物
a不会在洞穴中生长
awhen所有成员均处于离线状态。
a可以帮助减少延迟。
name: 离线增长
&a如果禁用, 当洞穴中的所有成员
&a都离线时, 植物将停止生长.
&a或许能减少服务器卡顿.
name: "离线生长"
OFFLINE_REDSTONE:
description: |-
a禁用时红石
a不会在山洞中运作
a所有成员均处于离线状态。
a可以帮助减少延迟。
name: 离线红石
&a如果禁用, 当洞穴中的所有成员
&a都离线时, 红石将停止运作.
&a或许能减少服务器卡顿.
name: "离线红石"
PISTON_PUSH:
description: |-
a允许活塞推动
&在洞穴外面
name: 活塞推
&a允许活塞推动
&a洞穴外的方块
name: "活塞推动"
REMOVE_MOBS:
description: |-
a移除怪物
&前往洞穴
name: 移除怪物
&a传送到洞穴中时,
&a移除洞穴中的所有怪物
name: "Remove monsters"
TREES_GROWING_OUTSIDE_RANGE:
name: 树木生长范围外
name: "树木在洞穴保护范围外生长"
description: |-
a切换树木是否可以在
是否使用acave的保护范围。
&a切换树木是否能长到
&a洞穴保护范围之外.
PREVENT_TELEPORT_WHEN_FALLING:
name: 跌倒时防止传送
name: "掉落时禁止传送"
description: |-
a防止玩家被传送
使用命令返回他们的洞穴
aif他们跌倒了。
hint: "c跌倒时无法传送回洞穴。"
locked: "c这个洞穴被锁了"
protected: "cCave保护[说明]"
spawn-protected: "cSpawn受保护[描述]"
&a当玩家正在掉落时
&a禁止他们通过指令进行传送.
hint: "&c在掉落时不能传送."
locked: "&c该洞穴已禁止访客访问!"
protected: "&c没有权限: [description]"
spawn-protected: "&c没有权限: [description]"
panel:
PROTECTION:
description: |-
a保护设置
a这个洞
&a洞穴的
&a保护设置
SETTING:
description: |-
a常规设置
a这个洞
&a洞穴的
&a一般设置
protection:
flags:
SKY_WALKER_FLAG:
hint: 允许在洞穴顶上行走。
name: 天空行者
description: |-
5o这允许启用/禁用
5o能力继续前进
5otop洞穴世界
5o没有额外的权限。
description: "&5&o这将允许/禁止\n&5&o没有额外权限的玩家\n&5&o在洞穴世界的顶部\n&5&o行走."
name: "天空行者"
hint: "允许在洞穴的天花板上行走."