diff --git a/.travis.yml b/.travis.yml index 774b42c..af3496c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,7 @@ sudo: false addons: sonarcloud: organization: "bentobox-world" - token: - secure: $SONAR_TOKEN + jdk: - openjdk8 diff --git a/pom.xml b/pom.xml index 76a506c..b98962c 100644 --- a/pom.xml +++ b/pom.xml @@ -56,16 +56,16 @@ UTF-8 1.8 - 2.0.2 + 2.0.4 1.14.4-R0.1-SNAPSHOT - 1.8.0 + 1.9.0-SNAPSHOT ${build.version}-SNAPSHOT -LOCAL - 1.8.0 + 1.9.0 diff --git a/src/main/java/world/bentobox/acidisland/AISettings.java b/src/main/java/world/bentobox/acidisland/AISettings.java index d7de204..ec847cc 100644 --- a/src/main/java/world/bentobox/acidisland/AISettings.java +++ b/src/main/java/world/bentobox/acidisland/AISettings.java @@ -257,6 +257,11 @@ public class AISettings implements WorldSettings { @ConfigEntry(path = "world.visitor-banned-commands") private List visitorBannedCommands = new ArrayList<>(); + @ConfigComment("Falling banned commands - players cannot use these commands when falling") + @ConfigComment("if the PREVENT_TELEPORT_WHEN_FALLING world setting flag is active") + @ConfigEntry(path = "world.falling-banned-commands") + private List fallingBannedCommands = new ArrayList<>(); + // --------------------------------------------- /* ISLAND */ @@ -272,18 +277,8 @@ public class AISettings implements WorldSettings { @ConfigEntry(path = "island.max-homes") private int maxHomes = 5; - @ConfigComment("Island naming") - @ConfigComment("Only players with the TODO can name their island") - @ConfigComment("It is displayed in the top ten and enter and exit announcements") - @ConfigComment("It replaces the owner's name. Players can use & for color coding if they have the TODO permission") - @ConfigComment("These set the minimum and maximum size of a name.") - @ConfigEntry(path = "island.name.min-length") - private int nameMinLength = 4; - @ConfigEntry(path = "island.name.max-length") - private int nameMaxLength = 20; - // Reset - @ConfigComment("How many resets a player is allowed (override with /acid clearresets )") + @ConfigComment("How many resets a player is allowed (manage with /acid reset add/remove/reset/set command)") @ConfigComment("Value of -1 means unlimited, 0 means hardcore - no resets.") @ConfigComment("Example, 2 resets means they get 2 resets or 3 islands lifetime") @ConfigEntry(path = "island.reset.reset-limit") @@ -360,6 +355,43 @@ public class AISettings implements WorldSettings { @ConfigEntry(path = "island.reset.on-leave.ender-chest") private boolean onLeaveResetEnderChest = false; + @ConfigComment("Toggles the automatic island creation upon the player's first login on your server.") + @ConfigComment("If set to true,") + @ConfigComment(" * Upon connecting to your server for the first time, the player will be told that") + @ConfigComment(" an island will be created for him.") + @ConfigComment(" * Make sure you have a Blueprint Bundle called \"default\": this is the one that will") + @ConfigComment(" be used to create the island.") + @ConfigComment(" * An island will be created for the player without needing him to run the create command.") + @ConfigComment("If set to false, this will disable this feature entirely.") + @ConfigComment("Warning:") + @ConfigComment(" * If you are running multiple gamemodes on your server, and all of them have") + @ConfigComment(" this feature enabled, an island in all the gamemodes will be created simultaneously.") + @ConfigComment(" However, it is impossible to know on which island the player will be teleported to afterwards.") + @ConfigComment(" * Island creation can be resource-intensive, please consider the options below to help mitigate") + @ConfigComment(" the potential issues, especially if you expect a lot of players to connect to your server") + @ConfigComment(" in a limited period of time.") + @ConfigEntry(path = "island.create-island-on-first-login.enable") + private boolean createIslandOnFirstLoginEnabled; + + @ConfigComment("Time in seconds after the player logged in, before his island gets created.") + @ConfigComment("If set to 0 or less, the island will be created directly upon the player's login.") + @ConfigComment("It is recommended to keep this value under a minute's time.") + @ConfigEntry(path = "island.create-island-on-first-login.delay") + private int createIslandOnFirstLoginDelay = 5; + + @ConfigComment("Toggles whether the island creation should be aborted if the player logged off while the") + @ConfigComment("delay (see the option above) has not worn off yet.") + @ConfigComment("If set to true,") + @ConfigComment(" * If the player has logged off the server while the delay (see the option above) has not") + @ConfigComment(" worn off yet, this will cancel the island creation.") + @ConfigComment(" * If the player relogs afterward, since he will not be recognized as a new player, no island") + @ConfigComment(" would be created for him.") + @ConfigComment(" * If the island creation started before the player logged off, it will continue.") + @ConfigComment("If set to false, the player's island will be created even if he went offline in the meantime.") + @ConfigComment("Note this option has no effect if the delay (see the option above) is set to 0 or less.") + @ConfigEntry(path = "island.create-island-on-first-login.abort-on-logout") + private boolean createIslandOnFirstLoginAbortOnLogout = true; + // Commands @ConfigComment("List of commands to run when a player joins.") @ConfigEntry(path = "island.commands.on-join") @@ -623,18 +655,6 @@ public class AISettings implements WorldSettings { public int getMaxTeamSize() { return maxTeamSize; } - /** - * @return the nameMaxLength - */ - public int getNameMaxLength() { - return nameMaxLength; - } - /** - * @return the nameMinLength - */ - public int getNameMinLength() { - return nameMinLength; - } /** * @return the netherSeaHeight */ @@ -691,6 +711,15 @@ public class AISettings implements WorldSettings { public List getVisitorBannedCommands() { return visitorBannedCommands; } + + /** + * @return the fallingBannedCommands + */ + @Override + public List getFallingBannedCommands() { + return fallingBannedCommands; + } + /** * @return the worldFlags */ @@ -777,6 +806,44 @@ public class AISettings implements WorldSettings { public boolean isKickedKeepInventory() { return kickedKeepInventory; } + + + /** + * This method returns the createIslandOnFirstLoginEnabled boolean value. + * @return the createIslandOnFirstLoginEnabled value + * @since 1.9.0 + */ + @Override + public boolean isCreateIslandOnFirstLoginEnabled() + { + return createIslandOnFirstLoginEnabled; + } + + + /** + * This method returns the createIslandOnFirstLoginDelay int value. + * @return the createIslandOnFirstLoginDelay value + * @since 1.9.0 + */ + @Override + public int getCreateIslandOnFirstLoginDelay() + { + return createIslandOnFirstLoginDelay; + } + + + /** + * This method returns the createIslandOnFirstLoginAbortOnLogout boolean value. + * @return the createIslandOnFirstLoginAbortOnLogout value + * @since 1.9.0 + */ + @Override + public boolean isCreateIslandOnFirstLoginAbortOnLogout() + { + return createIslandOnFirstLoginAbortOnLogout; + } + + /** * @return the leaversLoseReset */ @@ -1129,19 +1196,6 @@ public class AISettings implements WorldSettings { public void setMaxTeamSize(int maxTeamSize) { this.maxTeamSize = maxTeamSize; } - /** - * @param nameMaxLength the nameMaxLength to set - */ - public void setNameMaxLength(int nameMaxLength) { - this.nameMaxLength = nameMaxLength; - } - /** - * @param nameMinLength the nameMinLength to set - */ - public void setNameMinLength(int nameMinLength) { - this.nameMinLength = nameMinLength; - } - /** * @param netherGenerate the netherGenerate to set */ @@ -1280,6 +1334,13 @@ public class AISettings implements WorldSettings { this.visitorBannedCommands = visitorBannedCommands; } + /** + * @param fallingBannedCommands the fallingBannedCommands to set + */ + public void setFallingBannedCommands(List fallingBannedCommands) { + this.fallingBannedCommands = fallingBannedCommands; + } + /** * @param worldFlags the worldFlags to set */ @@ -1423,4 +1484,27 @@ public class AISettings implements WorldSettings { this.onLeaveResetXP = onLeaveResetXP; } + /** + * @param createIslandOnFirstLoginEnabled the createIslandOnFirstLoginEnabled to set + */ + public void setCreateIslandOnFirstLoginEnabled(boolean createIslandOnFirstLoginEnabled) + { + this.createIslandOnFirstLoginEnabled = createIslandOnFirstLoginEnabled; + } + + /** + * @param createIslandOnFirstLoginDelay the createIslandOnFirstLoginDelay to set + */ + public void setCreateIslandOnFirstLoginDelay(int createIslandOnFirstLoginDelay) + { + this.createIslandOnFirstLoginDelay = createIslandOnFirstLoginDelay; + } + + /** + * @param createIslandOnFirstLoginAbortOnLogout the createIslandOnFirstLoginAbortOnLogout to set + */ + public void setCreateIslandOnFirstLoginAbortOnLogout(boolean createIslandOnFirstLoginAbortOnLogout) + { + this.createIslandOnFirstLoginAbortOnLogout = createIslandOnFirstLoginAbortOnLogout; + } } diff --git a/src/main/java/world/bentobox/acidisland/AcidIsland.java b/src/main/java/world/bentobox/acidisland/AcidIsland.java index 427c729..73a25d9 100644 --- a/src/main/java/world/bentobox/acidisland/AcidIsland.java +++ b/src/main/java/world/bentobox/acidisland/AcidIsland.java @@ -5,6 +5,7 @@ import org.bukkit.WorldCreator; import org.bukkit.WorldType; import org.bukkit.generator.ChunkGenerator; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import world.bentobox.acidisland.commands.AcidCommand; import world.bentobox.acidisland.commands.AiCommand; @@ -24,9 +25,9 @@ import world.bentobox.bentobox.lists.Flags; */ public class AcidIsland extends GameModeAddon { - private AISettings settings; - private AcidTask acidTask; - private @NonNull ChunkGenerator chunkGenerator; + private @Nullable AISettings settings; + private @Nullable AcidTask acidTask; + private @Nullable ChunkGenerator chunkGenerator; private Config config = new Config<>(this, AISettings.class); private static final String NETHER = "_nether"; @@ -78,10 +79,11 @@ public class AcidIsland extends GameModeAddon { } @Override - public void onDisable(){ - acidTask.cancelTasks(); + public void onDisable() { + if (acidTask != null) acidTask.cancelTasks(); } + @Nullable public AISettings getSettings() { return settings; } diff --git a/src/main/java/world/bentobox/acidisland/commands/AcidCommand.java b/src/main/java/world/bentobox/acidisland/commands/AcidCommand.java index d1cf37a..ba1facd 100644 --- a/src/main/java/world/bentobox/acidisland/commands/AcidCommand.java +++ b/src/main/java/world/bentobox/acidisland/commands/AcidCommand.java @@ -25,7 +25,7 @@ import world.bentobox.bentobox.api.commands.admin.blueprints.AdminBlueprintComma import world.bentobox.bentobox.api.commands.admin.deaths.AdminDeathsCommand; import world.bentobox.bentobox.api.commands.admin.purge.AdminPurgeCommand; import world.bentobox.bentobox.api.commands.admin.range.AdminRangeCommand; -import world.bentobox.bentobox.api.commands.admin.resets.AdminResetsResetCommand; +import world.bentobox.bentobox.api.commands.admin.resets.AdminResetsCommand; import world.bentobox.bentobox.api.commands.admin.team.AdminTeamAddCommand; import world.bentobox.bentobox.api.commands.admin.team.AdminTeamDisbandCommand; import world.bentobox.bentobox.api.commands.admin.team.AdminTeamKickCommand; @@ -67,8 +67,7 @@ public class AcidCommand extends CompositeCommand { // Range new AdminRangeCommand(this); // Resets - new AdminResetsResetCommand(this); - // TODO new AdminClearresetsallCommand(this); + new AdminResetsCommand(this); // Delete new AdminDeleteCommand(this); // Why diff --git a/src/main/java/world/bentobox/acidisland/world/ChunkGeneratorWorld.java b/src/main/java/world/bentobox/acidisland/world/ChunkGeneratorWorld.java index 68fd06b..8d678c6 100644 --- a/src/main/java/world/bentobox/acidisland/world/ChunkGeneratorWorld.java +++ b/src/main/java/world/bentobox/acidisland/world/ChunkGeneratorWorld.java @@ -1,14 +1,19 @@ package world.bentobox.acidisland.world; -import java.util.Arrays; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Random; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.World.Environment; +import org.bukkit.block.Biome; import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.ChunkGenerator; +import org.bukkit.util.Vector; import org.bukkit.util.noise.PerlinOctaveGenerator; import world.bentobox.acidisland.AcidIsland; @@ -22,6 +27,8 @@ public class ChunkGeneratorWorld extends ChunkGenerator { private final AcidIsland addon; private final Random rand = new Random(); + private Map seaHeight = new EnumMap<>(Environment.class); + private Map roofChunk = new HashMap<>(); /** * @param addon - addon @@ -29,29 +36,38 @@ public class ChunkGeneratorWorld extends ChunkGenerator { public ChunkGeneratorWorld(AcidIsland addon) { super(); this.addon = addon; + seaHeight.put(Environment.NORMAL, addon.getSettings().getSeaHeight()); + seaHeight.put(Environment.NETHER, addon.getSettings().getNetherSeaHeight()); + seaHeight.put(Environment.THE_END, addon.getSettings().getEndSeaHeight()); + makeNetherRoof(); + } + + public ChunkData generateChunks(World world) { + ChunkData result = createChunkData(world); + int sh = seaHeight.getOrDefault(world.getEnvironment(), 0); + if (sh > 0) { + result.setRegion(0, 0, 0, 16, sh + 1, 16, Material.WATER); + } + if (world.getEnvironment().equals(Environment.NETHER) && addon.getSettings().isNetherRoof()) { + roofChunk.forEach((k,v) -> result.setBlock(k.getBlockX(), world.getMaxHeight() + k.getBlockY(), k.getBlockZ(), v)); + } + return result; } @Override - public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, ChunkGenerator.BiomeGrid biomeGrid) { - if (world.getEnvironment().equals(World.Environment.NETHER)) { - return generateNetherChunks(world, random, chunkX, chunkZ, biomeGrid); - } - int seaHeight = world.getEnvironment().equals(World.Environment.NORMAL) ? addon.getSettings().getSeaHeight() : addon.getSettings().getEndSeaHeight(); - ChunkData result = createChunkData(world); - if (seaHeight != 0) { - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - if (world.getEnvironment().equals(Environment.NORMAL)) { - biomeGrid.setBiome(x, z, addon.getSettings().getDefaultBiome()); - } - for (int y = 0; y <= seaHeight; y++) { - result.setBlock(x, y, z, Material.WATER); - } - } - } + public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) { + if (world.getEnvironment().equals(Environment.NORMAL)) setBiome(biomeGrid); + return generateChunks(world); + } + private void setBiome(BiomeGrid biomeGrid) { + Biome biome = addon.getSettings().getDefaultBiome(); + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + biomeGrid.setBiome(x, z, biome); + } } - return result; + } // This needs to be set to return true to override minecraft's default @@ -63,95 +79,81 @@ public class ChunkGeneratorWorld extends ChunkGenerator { @Override public List getDefaultPopulators(final World world) { - return Arrays.asList(new BlockPopulator[0]); + return Collections.emptyList(); } /* * Nether Section */ - private ChunkData generateNetherChunks(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) { - ChunkData result = createChunkData(world); - rand.setSeed(world.getSeed()); - PerlinOctaveGenerator gen = new PerlinOctaveGenerator((long) (random.nextLong() * random.nextGaussian()), 8); - // This is a nether generator - if (!world.getEnvironment().equals(Environment.NETHER)) { - return result; - } - if (addon.getSettings().getSeaHeight() != 0) { - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - for (int y = 0; y <= addon.getSettings().getNetherSeaHeight(); y++) { - result.setBlock(x, y, z, Material.WATER); + private void makeNetherRoof() { + rand.setSeed(System.currentTimeMillis()); + PerlinOctaveGenerator gen = new PerlinOctaveGenerator((long) (rand.nextLong() * rand.nextGaussian()), 8); + + // Make the roof - common across the world + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + // Do the ceiling + setBlock(x, -1, z, Material.BEDROCK); + // Next three layers are a mix of bedrock and netherrack + for (int y = 2; y < 5; y++) { + double r = gen.noise(x, - y, z, 0.5, 0.5); + if (r > 0D) { + setBlock(x, - y, z, Material.BEDROCK); } } - } - - } - if (addon.getSettings().isNetherRoof()) { - // Make the roof - common across the world - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - // Do the ceiling - int maxHeight = world.getMaxHeight(); - result.setBlock(x, (maxHeight - 1), z, Material.BEDROCK); - // Next three layers are a mix of bedrock and netherrack - for (int y = 2; y < 5; y++) { - double r = gen.noise(x, (maxHeight - y), z, 0.5, 0.5); - if (r > 0D) { - result.setBlock(x, (maxHeight - y), z, Material.BEDROCK); - } + // Next three layers are a mix of netherrack and air + for (int y = 5; y < 8; y++) { + double r = gen.noise(x, - y, z, 0.5, 0.5); + if (r > 0D) { + setBlock(x, -y, z, Material.NETHERRACK); + } else { + setBlock(x, -y, z, Material.AIR); } - // Next three layers are a mix of netherrack and air - for (int y = 5; y < 8; y++) { - double r = gen.noise(x, (double)maxHeight - y, z, 0.5, 0.5); - if (r > 0D) { - result.setBlock(x, (maxHeight - y), z, Material.NETHERRACK); - } else { - result.setBlock(x, (maxHeight - y), z, Material.AIR); + } + // Layer 8 may be glowstone + double r = gen.noise(x, - 8, z, rand.nextFloat(), rand.nextFloat()); + if (r > 0.5D) { + // Have blobs of glowstone + switch (rand.nextInt(4)) { + case 1: + // Single block + setBlock(x, -8, z, Material.GLOWSTONE); + if (x < 14 && z < 14) { + setBlock(x + 1, -8, z + 1, Material.GLOWSTONE); + setBlock(x + 2, -8, z + 2, Material.GLOWSTONE); + setBlock(x + 1, -8, z + 2, Material.GLOWSTONE); + setBlock(x + 1, -8, z + 2, Material.GLOWSTONE); } - } - // Layer 8 may be glowstone - double r = gen.noise(x, (double)maxHeight - 8, z, random.nextFloat(), random.nextFloat()); - if (r > 0.5D) { - // Have blobs of glowstone - switch (random.nextInt(4)) { - case 1: - // Single block - result.setBlock(x, (maxHeight - 8), z, Material.GLOWSTONE); - if (x < 14 && z < 14) { - result.setBlock(x + 1, (maxHeight - 8), z + 1, Material.GLOWSTONE); - result.setBlock(x + 2, (maxHeight - 8), z + 2, Material.GLOWSTONE); - result.setBlock(x + 1, (maxHeight - 8), z + 2, Material.GLOWSTONE); - result.setBlock(x + 1, (maxHeight - 8), z + 2, Material.GLOWSTONE); - } - break; - case 2: - // Stalatite - for (int i = 0; i < random.nextInt(10); i++) { - result.setBlock(x, (maxHeight - 8 - i), z, Material.GLOWSTONE); - } - break; - case 3: - result.setBlock(x, (maxHeight - 8), z, Material.GLOWSTONE); - if (x > 3 && z > 3) { - for (int xx = 0; xx < 3; xx++) { - for (int zz = 0; zz < 3; zz++) { - result.setBlock(x - xx, (maxHeight - 8 - random.nextInt(2)), z - xx, Material.GLOWSTONE); - } + break; + case 2: + // Stalatite + for (int i = 0; i < rand.nextInt(10); i++) { + setBlock(x, - 8 - i, z, Material.GLOWSTONE); + } + break; + case 3: + setBlock(x, -8, z, Material.GLOWSTONE); + if (x > 3 && z > 3) { + for (int xx = 0; xx < 3; xx++) { + for (int zz = 0; zz < 3; zz++) { + setBlock(x - xx, - 8 - rand.nextInt(2), z - xx, Material.GLOWSTONE); } } - break; - default: - result.setBlock(x, (maxHeight - 8), z, Material.GLOWSTONE); } - result.setBlock(x, (maxHeight - 8), z, Material.GLOWSTONE); - } else { - result.setBlock(x, (maxHeight - 8), z, Material.AIR); + break; + default: + setBlock(x, -8, z, Material.GLOWSTONE); } + setBlock(x, -8, z, Material.GLOWSTONE); + } else { + setBlock(x, -8, z, Material.AIR); } } - } - return result; + } + } + + private void setBlock(int x, int y, int z, Material m) { + roofChunk.put(new Vector(x, y, z), m); } } \ No newline at end of file diff --git a/src/main/resources/blueprints/temple.blu b/src/main/resources/blueprints/temple.blu index 0a07dea..324465d 100644 Binary files a/src/main/resources/blueprints/temple.blu and b/src/main/resources/blueprints/temple.blu differ diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ed2d16e..cecf934 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -21,11 +21,16 @@ acid: item: 0 # Damage from acid rain rain: 1 + # Damage from acid snow + snow: false + # Delay before acid or acid rain starts burning + # This can give time for conduit power to kick in + delay: 2 # Portion effects from going into acid water # You can list multiple effects effects: - - CONFUSION - - BLINDNESS + - CONFUSION + - BLINDNESS protection: # If player wears a helmet then they will not suffer from acid rain helmet: false @@ -33,9 +38,11 @@ acid: full-armor: false world: # Friendly name for this world. Used in admin commands. Must be a single word + # /!\ 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. friendly-name: AcidIsland # Name of the world - if it does not exist then it will be generated. # It acts like a prefix for nether and end (e.g. acidisland_world, acidisland_world_nether, acidisland_world_end) + # /!\ 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. world-name: acidisland_world # World difficulty setting - PEACEFUL, EASY, NORMAL, HARD # Other plugins may override this setting @@ -44,6 +51,7 @@ world: # Will be rounded up to the nearest 16 blocks. # It is the same for every dimension : Overworld, Nether and End. # This value cannot be changed mid-game and the plugin will not start if it is different. + # /!\ 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. distance-between-islands: 64 # Default protection range radius in blocks. Cannot be larger than distance. # Admins can change protection sizes for players individually using /acid range set @@ -54,7 +62,9 @@ world: # calculate the closest location on the grid. Islands develop around this location # both positively and negatively in a square grid. # If none of this makes sense, leave it at 0,0. + # /!\ 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. start-x: 0 + # /!\ 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. start-z: 0 offset-x: 0 offset-z: 0 @@ -68,7 +78,7 @@ world: # Sea height (don't changes this mid-game unless you delete the world) # Minimum is 0, which means you are playing Skyblock! sea-height: 54 - # Maximum number of islands in the world. Set to -1 or 0 for unlimited. + # Maximum number of islands in the world. Set to -1 or 0 for unlimited. # If the number of islands is greater than this number, no new island will be created. max-islands: 0 # The default game mode for this world. Players will be set to this mode when they create @@ -88,13 +98,12 @@ world: # portal will return them back to their islands. generate: true # Islands in Nether. Change to false for standard vanilla nether. + # /!\ 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. islands: true # Sea height in Nether. Only operates if nether islands is true. # Changing mid-game will cause problems! + # /!\ 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. sea-height: 54 - # Nether trees are made if a player grows a tree in the nether (gravel and glowstone) - # Applies to both vanilla and islands Nether - trees: true # Make the nether roof, if false, there is nothing up there # Change to false if lag is a problem from the generation # Only applies to islands Nether @@ -109,9 +118,11 @@ world: # the end will not occur. Other plugins may still enable portal usage. generate: true # Islands in The End. Change to false for standard vanilla end. + # /!\ 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. islands: true # Sea height in The End. Only operates if end islands is true. # Changing mid-game will cause problems! + # /!\ 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. sea-height: 54 # /!\ This feature is experimental and might not work as expected or might not work at all. dragon-spawn: false @@ -120,10 +131,10 @@ world: # This setting is toggled in world flags and set by the settings GUI. # Mob white list - these mobs will NOT be removed when logging in or doing /island remove-mobs-whitelist: - - ENDERMAN - - ZOMBIE_VILLAGER - - PIG_ZOMBIE - - WITHER + - ZOMBIE_VILLAGER + - WITHER + - PIG_ZOMBIE + - ENDERMAN # World flags. These are boolean settings for various flags for this world flags: CREEPER_DAMAGE: true @@ -134,17 +145,22 @@ world: ENDERMAN_GRIEFING: true CLEAN_SUPER_FLAT: false CHEST_DAMAGE: false + PREVENT_TELEPORT_WHEN_FALLING: false + NATURAL_SPAWNING_OUTSIDE_RANGE: true ENTER_EXIT_MESSAGES: true ENDERMAN_DEATH_DROP: true OFFLINE_REDSTONE: true + OFFLINE_GROWTH: true REMOVE_MOBS: true ENDER_CHEST: false ITEM_FRAME_DAMAGE: false + BOAT: true # These are the default protection settings for new islands. # The value is the minimum island rank required allowed to do the action # Ranks are: Visitor = 0, Member = 900, Owner = 1000 default-island-flags: HURT_ANIMALS: 500 + DRAGON_EGG: 500 REDSTONE: 500 BUCKET: 500 LOCK: 0 @@ -152,42 +168,49 @@ world: DOOR: 500 FURNACE: 500 ANVIL: 500 - FIRE: 500 + MINECART: 500 FISH_SCOOPING: 500 END_PORTAL: 500 BREEDING: 500 HURT_VILLAGERS: 500 - TNT: 500 TURTLE_EGGS: 500 FROST_WALKER: 500 COLLECT_LAVA: 500 LEVER: 500 - HURT_MONSTERS: 0 + ELYTRA: 0 RIDING: 500 - NAME_TAG: 500 + HURT_MONSTERS: 0 + CAKE: 500 ARMOR_STAND: 500 + NAME_TAG: 500 TRADING: 0 EGGS: 500 ITEM_DROP: 0 NOTE_BLOCK: 0 + FLINT_AND_STEEL: 500 NETHER_PORTAL: 500 CROP_TRAMPLE: 500 ITEM_PICKUP: 0 - DROPPER: 500 BREWING: 500 + DROPPER: 500 + TNT_PRIMING: 500 COLLECT_WATER: 500 BUTTON: 500 FIRE_EXTINGUISH: 500 + COMMAND_RANKS: 500 BEACON: 500 TRAPDOOR: 500 + EXPERIENCE_BOTTLE_THROWING: 500 PRESSURE_PLATE: 0 - PLACE_BLOCKS: 500 + DYE: 500 ITEM_FRAME: 500 + PLACE_BLOCKS: 500 CRAFTING: 0 - SHEARING: 500 ENCHANTING: 0 - BED: 500 + SHEARING: 500 + BOAT: 500 SPAWN_EGGS: 500 + BED: 500 MILKING: 0 DISPENSER: 500 GATE: 0 @@ -199,21 +222,31 @@ world: CHORUS_FRUIT: 500 CONTAINER: 500 JUKEBOX: 500 + POTION_THROWING: 500 # These are the default settings for new islands default-island-settings: PVP_END: false ANIMAL_SPAWN: true PVP_NETHER: false + LEAF_DECAY: true + TNT_DAMAGE: true + FIRE_IGNITE: true MONSTER_SPAWN: true FIRE_SPREAD: true + FIRE_BURNING: true PVP_OVERWORLD: false # These settings/flags are hidden from users # Ops can toggle hiding in-game using SHIFT-LEFT-CLICK on flags in settings hidden-flags: [] # Visitor banned commands - Visitors to islands cannot use these commands in this world visitor-banned-commands: - - spawner - - spawnmob + - spawner + - spawnmob + # Falling banned commands - players cannot use these commands when falling + # if the PREVENT_TELEPORT_WHEN_FALLING world setting flag is active + falling-banned-commands: + - warp + - spawn island: # Default max team size # Use this permission to set for specific user groups: acidisland.team.maxsize. @@ -223,14 +256,6 @@ island: # Accessed via /ai sethome or /ai go # Use this permission to set for specific user groups: acidisland.island.maxhomes. max-homes: 1 - name: - # Island naming - # Only players with the TODO can name their island - # It is displayed in the top ten and enter and exit announcements - # It replaces the owner's name. Players can use & for color coding if they have the TODO permission - # These set the minimum and maximum size of a name. - min-length: 4 - max-length: 20 reset: # How many resets a player is allowed (override with /acid clearresets ) # Value of -1 means unlimited, 0 means hardcore - no resets. @@ -246,7 +271,7 @@ island: # Overrides the on-leave inventory reset for kicked players. kicked-keep-inventory: false on-join: - # What the addon should reset when the player joins or creates an island + # What the plugin should reset when the player joins or creates an island # Reset Money - if this is true, will reset the player's money to the starting money # Recommendation is that this is set to true, but if you run multi-worlds # make sure your economy handles multi-worlds too. @@ -281,10 +306,42 @@ island: exp: false # Reset Ender Chest - if true, the player's Ender Chest will be cleared. ender-chest: false + create-island-on-first-login: + # Toggles the automatic island creation upon the player's first login on your server. + # If set to true, + # * Upon connecting to your server for the first time, the player will be told that + # an island will be created for him. + # * Make sure you have a Blueprint Bundle called "default": this is the one that will + # be used to create the island. + # * An island will be created for the player without needing him to run the create command. + # If set to false, this will disable this feature entirely. + # Warning: + # * If you are running multiple gamemodes on your server, and all of them have + # this feature enabled, an island in all the gamemodes will be created simultaneously. + # However, it is impossible to know on which island the player will be teleported to afterwards. + # * Island creation can be resource-intensive, please consider the options below to help mitigate + # the potential issues, especially if you expect a lot of players to connect to your server + # in a limited period of time. + enable: false + # Time in seconds after the player logged in, before his island gets created. + # If set to 0 or less, the island will be created directly upon the player's login. + # It is recommended to keep this value under a minute's time. + delay: 5 + # Toggles whether the island creation should be aborted if the player logged off while the + # delay (see the option above) has not worn off yet. + # If set to true, + # * If the player has logged off the server while the delay (see the option above) has not + # worn off yet, this will cancel the island creation. + # * If the player relogs afterward, since he will not be recognized as a new player, no island + # would be created for him. + # * If the island creation started before the player logged off, it will continue. + # If set to false, the player's island will be created even if he went offline in the meantime. + # Note this option has no effect if the delay (see the option above) is set to 0 or less. + abort-on-logout: true commands: # List of commands to run when a player joins. on-join: [] - # List of commands to run when a player leaves. + # list of commands to run when a player leaves. on-leave: [] sethome: nether: @@ -310,31 +367,30 @@ protection: # Invincible visitors. List of damages that will not affect visitors. # Make list blank if visitors should receive all damages invincible-visitors: - - BLOCK_EXPLOSION - - CONTACT - - CUSTOM - - DROWNING - - ENTITY_ATTACK - - ENTITY_EXPLOSION - - FALL - - FALLING_BLOCK - - FIRE - - FIRE_TICK - - LAVA - - LIGHTNING - - MAGIC - - POISON - - PROJECTILE - - STARVATION - - SUFFOCATION - - THORNS - - WITHER - - DRAGON_BREATH - - FLY_INTO_WALL - - HOT_FLOOR - - CRAMMING - - VOID + - BLOCK_EXPLOSION + - CONTACT + - CUSTOM + - DROWNING + - ENTITY_ATTACK + - ENTITY_EXPLOSION + - FALL + - FALLING_BLOCK + - FIRE + - FIRE_TICK + - LAVA + - LIGHTNING + - MAGIC + - POISON + - PROJECTILE + - STARVATION + - SUFFOCATION + - THORNS + - WITHER + - DRAGON_BREATH + - FLY_INTO_WALL + - HOT_FLOOR + - CRAMMING + - VOID do-not-edit-these-settings: # These settings should not be edited reset-epoch: 0 -uniqueId: config diff --git a/src/main/resources/locales/hu.yml b/src/main/resources/locales/hu.yml new file mode 100644 index 0000000..e4551c9 --- /dev/null +++ b/src/main/resources/locales/hu.yml @@ -0,0 +1,12 @@ +########################################################################################### +# 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 # +########################################################################################### + +acidisland: + sign: + line0: "&2SavSziget" + line1: "[name]" + line2: "A víz savas!" + line3: "Légy óvatos! &d<3" + diff --git a/src/main/resources/locales/pl.yml b/src/main/resources/locales/pl.yml new file mode 100644 index 0000000..a760e9b --- /dev/null +++ b/src/main/resources/locales/pl.yml @@ -0,0 +1,7 @@ +--- +acidisland: + sign: + line0: "&1AcidIsland" + line1: "[name]" + line3: 'Bądź ostrożny! ' + line2: Woda jest kwaśna! diff --git a/src/test/java/world/bentobox/acidisland/world/ChunkGeneratorWorldTest.java b/src/test/java/world/bentobox/acidisland/world/ChunkGeneratorWorldTest.java new file mode 100644 index 0000000..79e2846 --- /dev/null +++ b/src/test/java/world/bentobox/acidisland/world/ChunkGeneratorWorldTest.java @@ -0,0 +1,192 @@ +package world.bentobox.acidisland.world; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Random; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.generator.ChunkGenerator.BiomeGrid; +import org.bukkit.generator.ChunkGenerator.ChunkData; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import world.bentobox.acidisland.AcidIsland; +import world.bentobox.acidisland.AISettings; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({Bukkit.class}) +public class ChunkGeneratorWorldTest { + + @Mock + private AcidIsland addon; + private ChunkGeneratorWorld cg; + @Mock + private World world; + private final Random random = new Random(); + @Mock + private BiomeGrid biomeGrid; + @Mock + private AISettings settings; + @Mock + private ChunkData data; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + // Bukkit + PowerMockito.mockStatic(Bukkit.class); + Server server = mock(Server.class); + when(server.createChunkData(any())).thenReturn(data); + when(Bukkit.getServer()).thenReturn(server); + // World + when(world.getEnvironment()).thenReturn(World.Environment.NORMAL); + // Settings + when(addon.getSettings()).thenReturn(settings); + when(settings.getSeaHeight()).thenReturn(0); + when(settings.isNetherRoof()).thenReturn(true); + + // Instance + cg = new ChunkGeneratorWorld(addon); + } + + /** + * @throws java.lang.Exception + */ + @After + public void tearDown() throws Exception { + } + + /** + * Test method for {@link world.bentobox.bskyblock.generators.ChunkGeneratorWorld#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)}. + */ + @Test + public void testGenerateChunkDataWorldRandomIntIntBiomeGridOverworldVoid() { + ChunkData cd = cg.generateChunkData(world, random, 0 , 0 , biomeGrid); + assertEquals(data, cd); + // Verifications + // Default biome + verify(settings).getDefaultBiome(); + verify(biomeGrid, times(16 * 16)).setBiome(anyInt(), anyInt(), any()); + // Sea height + verify(settings).getSeaHeight(); + // Void + verify(cd, never()).setRegion(anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), any(Material.class)); + } + + /** + * Test method for {@link world.bentobox.bskyblock.generators.ChunkGeneratorWorld#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)}. + */ + @Test + public void testGenerateChunkDataWorldRandomIntIntBiomeGridOverworldSea() { + // Set sea height + when(settings.getSeaHeight()).thenReturn(10); + // new instance + cg = new ChunkGeneratorWorld(addon); + ChunkData cd = cg.generateChunkData(world, random, 0 , 0 , biomeGrid); + assertEquals(data, cd); + // Verifications + // Default biome + verify(settings).getDefaultBiome(); + verify(biomeGrid, times(16 * 16)).setBiome(anyInt(), anyInt(), any()); + // Sea height + verify(settings, times(2)).getSeaHeight(); + // Water. Blocks = 16 x 16 x 11 because block 0 + verify(cd).setRegion(0, 0, 0, 16, 11, 16, Material.WATER); + } + + /** + * Test method for {@link world.bentobox.bskyblock.generators.ChunkGeneratorWorld#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)}. + */ + @Test + public void testGenerateChunkDataWorldRandomIntIntBiomeGridEnd() { + when(world.getEnvironment()).thenReturn(World.Environment.THE_END); + ChunkData cd = cg.generateChunkData(world, random, 0 , 0 , biomeGrid); + assertEquals(data, cd); + // Verifications + // Default biome + verify(settings, never()).getDefaultBiome(); + // Never set biome in end + verify(biomeGrid, never()).setBiome(anyInt(), anyInt(), any()); + // Sea height + verify(settings).getSeaHeight(); + // Void + verify(cd, never()).setRegion(anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), anyInt(), any(Material.class)); + } + + /** + * Test method for {@link world.bentobox.bskyblock.generators.ChunkGeneratorWorld#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)}. + */ + @Test + public void testGenerateChunkDataWorldRandomIntIntBiomeGridNetherWithRoof() { + when(world.getEnvironment()).thenReturn(World.Environment.NETHER); + ChunkData cd = cg.generateChunkData(world, random, 0 , 0 , biomeGrid); + assertEquals(data, cd); + // Verifications + // Nether roof check + verify(settings).isNetherRoof(); + // Never set biome in nether + verify(biomeGrid, never()).setBiome(anyInt(), anyInt(), any()); + // Nether roof - at least bedrock layer + verify(cd, atLeast(16 * 16)).setBlock(anyInt(), anyInt(), anyInt(), eq(Material.BEDROCK)); + } + + /** + * Test method for {@link world.bentobox.bskyblock.generators.ChunkGeneratorWorld#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)}. + */ + @Test + public void testGenerateChunkDataWorldRandomIntIntBiomeGridNetherNoRoof() { + when(settings.isNetherRoof()).thenReturn(false); + when(world.getEnvironment()).thenReturn(World.Environment.NETHER); + ChunkData cd = cg.generateChunkData(world, random, 0 , 0 , biomeGrid); + assertEquals(data, cd); + // Verifications + // Nether roof check + verify(settings).isNetherRoof(); + // Never set biome in nether + verify(biomeGrid, never()).setBiome(anyInt(), anyInt(), any()); + // Nether roof - at least bedrock layer + verify(cd, never()).setBlock(anyInt(), anyInt(), anyInt(), any(Material.class)); + } + + /** + * Test method for {@link world.bentobox.bskyblock.generators.ChunkGeneratorWorld#canSpawn(org.bukkit.World, int, int)}. + */ + @Test + public void testCanSpawnWorldIntInt() { + assertTrue(cg.canSpawn(mock(World.class), 0, 1)); + } + + /** + * Test method for {@link world.bentobox.bskyblock.generators.ChunkGeneratorWorld#getDefaultPopulators(org.bukkit.World)}. + */ + @Test + public void testGetDefaultPopulatorsWorld() { + assertTrue(cg.getDefaultPopulators(mock(World.class)).isEmpty()); + } + +}