Merge branch 'develop' into 1.17_world_gen

This commit is contained in:
tastybento 2021-12-20 12:21:39 -08:00 committed by GitHub
commit 6e57bfc875
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1217 additions and 475 deletions

View File

@ -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}
@ -1647,6 +1656,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
*/
@ -2198,6 +2218,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)

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,6 +1,5 @@
package world.bentobox.caveblock.generators;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
@ -14,15 +13,17 @@ import org.bukkit.block.data.BlockData;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.generator.WorldInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Class ChunkGeneratorWorld ...
*
* @author BONNe
* Created on 27.01.2019
* @author tastybento
*/
public class ChunkGeneratorWorld extends ChunkGenerator {
private static final int BLOB_SIZE = 1;
private static final Map<Environment, List<Ore>> ORES;
static {

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,96 @@
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.*;
public class NewMaterialPopulator extends BlockPopulator {
private final Map<World.Environment, List<Ore>> ores = new EnumMap<>(World.Environment.class);
public NewMaterialPopulator() {
// 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);
}
@Override
public void populate(WorldInfo worldInfo, Random random, int chunkX, int chunkZ, LimitedRegion limitedRegion) {
for (int y = worldInfo.getMinHeight(); y < worldInfo.getMaxHeight(); 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 blobSize = (int) (((double)random.nextInt(o.blob()) / 3) + 1);
int blobSize = 1;
int offset = random.nextInt(16);
for (int x = Math.max(0, offset - blobSize); x < Math.min(16, offset + blobSize); x++) {
for (int z = Math.max(0, offset - blobSize); z < Math.min(16, offset + blobSize); z++) {
for (int yy = Math.max(worldInfo.getMinHeight(), y - blobSize); yy < Math.min(worldInfo.getMaxHeight(), y + blobSize); 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

@ -93,6 +93,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

@ -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,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: "允许在洞穴的天花板上行走."