diff --git a/pom.xml b/pom.xml
index 7f7501e..77f934b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,13 +59,13 @@
2.0.9
1.20.4-R0.1-SNAPSHOT
- 2.0.0-SNAPSHOT
+ 2.5.0-SNAPSHOT
${build.version}-SNAPSHOT
-LOCAL
- 1.18.2
+ 1.19.0
BentoBoxWorld_AcidIsland
bentobox-world
diff --git a/src/main/java/world/bentobox/acidisland/AISettings.java b/src/main/java/world/bentobox/acidisland/AISettings.java
index b3ac824..2dc9988 100644
--- a/src/main/java/world/bentobox/acidisland/AISettings.java
+++ b/src/main/java/world/bentobox/acidisland/AISettings.java
@@ -11,6 +11,7 @@
import com.google.common.base.Enums;
+import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.configuration.ConfigComment;
import world.bentobox.bentobox.api.configuration.ConfigEntry;
import world.bentobox.bentobox.api.configuration.StoreAt;
@@ -201,6 +202,15 @@ public class AISettings implements WorldSettings {
@ConfigEntry(path = "world.island-height")
private int islandHeight = 50;
+ @ConfigComment("The number of concurrent islands a player can have in the world")
+ @ConfigComment("A value of 0 will use the BentoBox config.yml default")
+ @ConfigEntry(path = "world.concurrent-islands")
+ private int concurrentIslands = 0;
+
+ @ConfigComment("Disallow players to have other islands if they are in a team.")
+ @ConfigEntry(path = "world.disallow-team-member-islands")
+ boolean disallowTeamMemberIslands = true;
+
@ConfigComment("Use your own world generator for this world.")
@ConfigComment("In this case, the plugin will not generate anything.")
@ConfigEntry(path = "world.use-own-generator", experimental = true)
@@ -220,6 +230,21 @@ public class AISettings implements WorldSettings {
@ConfigEntry(path = "world.ocean-floor", needsReset = true)
private boolean oceanFloor = false;
+ @ConfigComment("Structures")
+ @ConfigComment("This creates an vanilla structures in the worlds.")
+ @ConfigEntry(path = "world.make-structures", needsReset = true)
+ private boolean makeStructures = false;
+
+ @ConfigComment("Caves")
+ @ConfigComment("This creates an vanilla caves in the worlds.")
+ @ConfigEntry(path = "world.make-caves", needsReset = true)
+ private boolean makeCaves = false;
+
+ @ConfigComment("Decorations")
+ @ConfigComment("This creates an vanilla decorations in the worlds.")
+ @ConfigEntry(path = "world.make-decorations", needsReset = true)
+ private boolean makeDecorations = true;
+
@ConfigComment("Maximum number of islands in the world. Set to -1 or 0 for unlimited. ")
@ConfigComment("If the number of islands is greater than this number, no new island will be created.")
@ConfigEntry(path = "world.max-islands")
@@ -2024,4 +2049,79 @@ public boolean isOceanFloor() {
public void setOceanFloor(boolean oceanFloor) {
this.oceanFloor = oceanFloor;
}
+
+ /**
+ * @return the makeStructures
+ */
+ public boolean isMakeStructures() {
+ return makeStructures;
+ }
+
+ /**
+ * @param makeStructures the makeStructures to set
+ */
+ public void setMakeStructures(boolean makeStructures) {
+ this.makeStructures = makeStructures;
+ }
+
+ /**
+ * @return the makeCaves
+ */
+ public boolean isMakeCaves() {
+ return makeCaves;
+ }
+
+ /**
+ * @param makeCaves the makeCaves to set
+ */
+ public void setMakeCaves(boolean makeCaves) {
+ this.makeCaves = makeCaves;
+ }
+
+ /**
+ * @return the makeDecorations
+ */
+ public boolean isMakeDecorations() {
+ return makeDecorations;
+ }
+
+ /**
+ * @param makeDecorations the makeDecorations to set
+ */
+ public void setMakeDecorations(boolean makeDecorations) {
+ this.makeDecorations = makeDecorations;
+ }
+
+ /**
+ * @return the disallowTeamMemberIslands
+ */
+ @Override
+ public boolean isDisallowTeamMemberIslands() {
+ return disallowTeamMemberIslands;
+ }
+
+ /**
+ * @param disallowTeamMemberIslands the disallowTeamMemberIslands to set
+ */
+ public void setDisallowTeamMemberIslands(boolean disallowTeamMemberIslands) {
+ this.disallowTeamMemberIslands = disallowTeamMemberIslands;
+ }
+
+ /**
+ * @return the concurrentIslands
+ */
+ @Override
+ public int getConcurrentIslands() {
+ if (concurrentIslands <= 0) {
+ return BentoBox.getInstance().getSettings().getIslandNumber();
+ }
+ return concurrentIslands;
+ }
+
+ /**
+ * @param concurrentIslands the concurrentIslands to set
+ */
+ public void setConcurrentIslands(int concurrentIslands) {
+ this.concurrentIslands = concurrentIslands;
+ }
}
diff --git a/src/main/java/world/bentobox/acidisland/AcidIslandPladdon.java b/src/main/java/world/bentobox/acidisland/AcidIslandPladdon.java
index a54acd5..f345450 100644
--- a/src/main/java/world/bentobox/acidisland/AcidIslandPladdon.java
+++ b/src/main/java/world/bentobox/acidisland/AcidIslandPladdon.java
@@ -2,12 +2,18 @@
import world.bentobox.bentobox.api.addons.Addon;
+import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.addons.Pladdon;
public class AcidIslandPladdon extends Pladdon {
+ private GameModeAddon addon;
+
@Override
public Addon getAddon() {
- return new AcidIsland();
+ if (addon == null) {
+ addon = new AcidIsland();
+ }
+ return addon;
}
}
diff --git a/src/main/java/world/bentobox/acidisland/events/EntityDamageByAcidEvent.java b/src/main/java/world/bentobox/acidisland/events/EntityDamageByAcidEvent.java
index cdeb4f6..e041c02 100644
--- a/src/main/java/world/bentobox/acidisland/events/EntityDamageByAcidEvent.java
+++ b/src/main/java/world/bentobox/acidisland/events/EntityDamageByAcidEvent.java
@@ -1,21 +1,23 @@
package world.bentobox.acidisland.events;
import org.bukkit.entity.Entity;
+import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
/**
* Fired when an entity (items excluded) receives damage from acid
- * @author Poslovitch
+ * @author Poslovitch, tastybento
* @since 1.0
*/
-public class EntityDamageByAcidEvent extends Event {
+public class EntityDamageByAcidEvent extends Event implements Cancellable {
private final Entity entity;
private double damage;
public enum Acid { RAIN, WATER }
private final Acid cause;
+ private boolean cancelled;
private static final HandlerList handlers = new HandlerList();
@Override
@@ -64,4 +66,15 @@ public void setDamage(double damage) {
public Acid getCause() {
return cause;
}
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancel) {
+ this.cancelled = cancel;
+
+ }
}
diff --git a/src/main/java/world/bentobox/acidisland/listeners/AcidEffect.java b/src/main/java/world/bentobox/acidisland/listeners/AcidEffect.java
index 887454a..c0f0806 100644
--- a/src/main/java/world/bentobox/acidisland/listeners/AcidEffect.java
+++ b/src/main/java/world/bentobox/acidisland/listeners/AcidEffect.java
@@ -178,7 +178,14 @@ protected boolean checkForRain(Player player) {
// Check they are still in this world
} else if (wetPlayers.containsKey(player) && wetPlayers.get(player) < System.currentTimeMillis()) {
double protection = addon.getSettings().getAcidRainDamage() * getDamageReduced(player);
- double totalDamage = Math.max(0, addon.getSettings().getAcidRainDamage() - protection);
+
+ User user = User.getInstance(player);
+ // Get the percentage reduction and ensure the value is between 0 and 100
+ double percent = (100
+ - Math.max(0, Math.min(100, user.getPermissionValue("acidisland.protection.rain", 0)))) / 100D;
+
+ double totalDamage = Math.max(0, addon.getSettings().getAcidRainDamage() - protection) * percent;
+
AcidRainEvent event = new AcidRainEvent(player, totalDamage, protection,
addon.getSettings().getAcidRainEffects());
Bukkit.getPluginManager().callEvent(event);
@@ -187,11 +194,13 @@ protected boolean checkForRain(Player player) {
.addPotionEffect(new PotionEffect(t, addon.getSettings().getRainEffectDuation() * 20, 1)));
// Apply damage if there is any
if (event.getRainDamage() > 0D) {
- player.damage(event.getRainDamage());
- player.getWorld().playSound(player.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 3F, 3F);
EntityDamageByAcidEvent e = new EntityDamageByAcidEvent(player, event.getRainDamage(), Acid.RAIN);
// Fire event
Bukkit.getPluginManager().callEvent(e);
+ if (!e.isCancelled()) {
+ player.damage(event.getRainDamage());
+ player.getWorld().playSound(player.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 3F, 3F);
+ }
}
}
}
@@ -204,19 +213,28 @@ protected boolean continuouslyHurtPlayer(Player player) {
return true;
} else if (burningPlayers.containsKey(player) && burningPlayers.get(player) < System.currentTimeMillis()) {
double protection = addon.getSettings().getAcidDamage() * getDamageReduced(player);
- double totalDamage = Math.max(0, addon.getSettings().getAcidDamage() - protection);
+
+ User user = User.getInstance(player);
+ // Get the percentage reduction and ensure the value is between 0 and 100
+ double percent = (100
+ - Math.max(0, Math.min(100, user.getPermissionValue("acidisland.protection.acid", 0)))) / 100D;
+
+ double totalDamage = Math.max(0, addon.getSettings().getAcidDamage() - protection) * percent;
+
AcidEvent event = new AcidEvent(player, totalDamage, protection, addon.getSettings().getAcidEffects());
addon.getServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
event.getPotionEffects().stream().filter(EFFECTS::contains).forEach(t -> player
.addPotionEffect(new PotionEffect(t, addon.getSettings().getAcidEffectDuation() * 20, 1)));
// Apply damage if there is any
- if (event.getTotalDamage() > 0D) {
- player.damage(event.getTotalDamage());
- player.getWorld().playSound(player.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 3F, 3F);
+ if (event.getTotalDamage() > 0D) {
EntityDamageByAcidEvent e = new EntityDamageByAcidEvent(player, event.getTotalDamage(), Acid.WATER);
// Fire event
Bukkit.getPluginManager().callEvent(e);
+ if (!e.isCancelled()) {
+ player.damage(event.getTotalDamage());
+ player.getWorld().playSound(player.getLocation(), Sound.ENTITY_CREEPER_PRIMED, 3F, 3F);
+ }
}
}
}
@@ -230,9 +248,10 @@ protected boolean continuouslyHurtPlayer(Player player) {
*/
private boolean isSafeFromRain(Player player) {
if (isEssentialsGodMode(player) || player.getWorld().getEnvironment().equals(Environment.NETHER)
+ || player.getGameMode() != GameMode.SURVIVAL
|| player.getWorld().getEnvironment().equals(Environment.THE_END)
|| (addon.getSettings().isHelmetProtection() && (player.getInventory().getHelmet() != null
- && player.getInventory().getHelmet().getType().name().contains("HELMET")))
+ && player.getInventory().getHelmet().getType().name().contains("HELMET")))
|| (!addon.getSettings().isAcidDamageSnow() && player.getLocation().getBlock().getTemperature() < 0.1) // snow falls
|| player.getLocation().getBlock().getHumidity() == 0 // dry
|| (player.getActivePotionEffects().stream().map(PotionEffect::getType)
@@ -260,7 +279,7 @@ private boolean isSafeFromRain(Player player) {
*/
boolean isSafeFromAcid(Player player) {
// Check for GodMode
- if (isEssentialsGodMode(player)
+ if (isEssentialsGodMode(player) || player.getGameMode() != GameMode.SURVIVAL
// Protect visitors
|| (addon.getPlugin().getIWM().getIvSettings(player.getWorld()).contains(DamageCause.CUSTOM.name())
&& !addon.getIslands().userIsOnIsland(player.getWorld(), User.getInstance(player)))) {
diff --git a/src/main/java/world/bentobox/acidisland/world/AcidTask.java b/src/main/java/world/bentobox/acidisland/world/AcidTask.java
index 1e9dab2..fd2a416 100644
--- a/src/main/java/world/bentobox/acidisland/world/AcidTask.java
+++ b/src/main/java/world/bentobox/acidisland/world/AcidTask.java
@@ -37,6 +37,8 @@ public class AcidTask {
i.add(EntityType.POLAR_BEAR);
i.add(EntityType.TURTLE);
i.add(EntityType.DROWNED);
+ i.add(EntityType.GUARDIAN);
+ i.add(EntityType.ELDER_GUARDIAN);
Enums.getIfPresent(EntityType.class, "AXOLOTL").toJavaUtil().ifPresent(i::add);
IMMUNE = Collections.unmodifiableList(i);
}
@@ -86,10 +88,12 @@ void findEntities() {
void applyDamage(Entity e, long damage) {
if (e instanceof LivingEntity) {
double actualDamage = Math.max(0, damage - damage * AcidEffect.getDamageReduced((LivingEntity)e));
- ((LivingEntity)e).damage(actualDamage);
EntityDamageByAcidEvent event = new EntityDamageByAcidEvent(e, actualDamage, Acid.WATER);
// Fire event
Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ ((LivingEntity)e).damage(actualDamage);
+ }
} else if (addon.getSettings().getAcidDestroyItemTime() > 0 && e instanceof Item){
// Item
if (e.getLocation().getBlock().getType().equals(Material.WATER)) {
diff --git a/src/main/java/world/bentobox/acidisland/world/ChunkGeneratorWorld.java b/src/main/java/world/bentobox/acidisland/world/ChunkGeneratorWorld.java
index fbbbe56..748c0c0 100644
--- a/src/main/java/world/bentobox/acidisland/world/ChunkGeneratorWorld.java
+++ b/src/main/java/world/bentobox/acidisland/world/ChunkGeneratorWorld.java
@@ -27,10 +27,17 @@
*/
public class ChunkGeneratorWorld extends ChunkGenerator {
+ private record FloorMats(Material base, Material top) {
+ }
+
private final AcidIsland addon;
private final Random rand = new Random();
private final Map seaHeight = new EnumMap<>(Environment.class);
private final Map roofChunk = new HashMap<>();
+ private static final Map floorMats = Map.of(Environment.NETHER,
+ new FloorMats(Material.NETHERRACK, Material.SOUL_SAND), Environment.NORMAL,
+ new FloorMats(Material.SANDSTONE, Material.SAND), Environment.THE_END,
+ new FloorMats(Material.END_STONE, Material.END_STONE));
private PerlinOctaveGenerator gen;
private record WorldConfig(int seaHeight, Material waterBlock) {}
@@ -72,7 +79,8 @@ private void addNoise(@NonNull WorldInfo worldInfo, int chunkX, int chunkZ, @Non
for (int z = 0; z < 16; z++) {
int n = (int)(25 * gen.noise((chunkX << 4) + (double)x, (chunkZ << 4) + (double)z, 0.5, 0.5, true));
for (int y = worldInfo.getMinHeight(); y < 25 + n; y++) {
- chunkData.setBlock(x, y, z, rand.nextBoolean() ? Material.SAND : Material.SANDSTONE);
+ chunkData.setBlock(x, y, z, rand.nextBoolean() ? floorMats.get(worldInfo.getEnvironment()).top()
+ : floorMats.get(worldInfo.getEnvironment()).base());
}
}
}
@@ -90,11 +98,11 @@ public boolean shouldGenerateSurface() {
}
@Override
public boolean shouldGenerateCaves() {
- return addon.getSettings().isOceanFloor();
+ return addon.getSettings().isMakeCaves();
}
@Override
public boolean shouldGenerateDecorations() {
- return addon.getSettings().isOceanFloor();
+ return addon.getSettings().isMakeDecorations();
}
@Override
public boolean shouldGenerateMobs() {
@@ -102,7 +110,7 @@ public boolean shouldGenerateMobs() {
}
@Override
public boolean shouldGenerateStructures() {
- return addon.getSettings().isOceanFloor();
+ return addon.getSettings().isMakeStructures();
}
@Override
diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml
index ffff1f8..ec1e131 100755
--- a/src/main/resources/addon.yml
+++ b/src/main/resources/addon.yml
@@ -1,7 +1,7 @@
name: AcidIsland
main: world.bentobox.acidisland.AcidIsland
version: ${version}${build.number}
-api-version: 1.22.1
+api-version: 2.4.0
metrics: true
repository: "BentoBoxWorld/AcidIsland"
icon: "OAK_BOAT"
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index ce2df30..984485e 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -125,6 +125,11 @@ world:
# Island height - Lowest is 5.
# It is the y coordinate of the bedrock block in the schem.
island-height: 60
+ # The number of concurrent islands a player can have in the world
+ # A value of 0 will use the BentoBox config.yml default
+ concurrent-islands: 1
+ # Disallow players to have other islands if they are in a team.
+ disallow-team-member-islands: true
# Use your own world generator for this world.
# In this case, the plugin will not generate anything.
# /!\ This feature is experimental and might not work as expected or might not work at all.
@@ -139,6 +144,18 @@ world:
# This creates an ocean floor environment, with vanilla elements.
# /!\ 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.
ocean-floor: true
+ # Structures
+ # This creates an vanilla structures in the worlds.
+ # /!\ 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.
+ make-structures: false
+ # Caves
+ # This creates an vanilla caves in the worlds.
+ # /!\ 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.
+ make-caves: false
+ # Decorations
+ # This creates an vanilla decorations in the worlds.
+ # /!\ 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.
+ make-decorations: true
# 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
@@ -211,10 +228,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:
- - ZOMBIE_VILLAGER
- ENDERMAN
- - ZOMBIFIED_PIGLIN
+ - ZOMBIE_VILLAGER
- WITHER
+ - ZOMBIFIED_PIGLIN
# World flags. These are boolean settings for various flags for this world
flags:
CREEPER_DAMAGE: true
@@ -228,27 +245,33 @@ world:
PREVENT_TELEPORT_WHEN_FALLING: false
NATURAL_SPAWNING_OUTSIDE_RANGE: true
ENTER_EXIT_MESSAGES: true
+ ALLOW_MOVE_BOX: true
ENDERMAN_DEATH_DROP: true
+ LIQUIDS_FLOWING_OUT: false
OFFLINE_REDSTONE: true
REMOVE_END_EXIT_ISLAND: true
OFFLINE_GROWTH: true
REMOVE_MOBS: true
ENDER_CHEST: false
ITEM_FRAME_DAMAGE: false
+ TREES_GROWING_OUTSIDE_RANGE: 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
+ LOOM: 500
DRAGON_EGG: 500
REDSTONE: 500
BUCKET: 500
LOCK: 0
ENDER_PEARL: 500
+ BELL_RINGING: 500
DOOR: 500
BREAK_HOPPERS: 500
FURNACE: 500
+ HURT_TAMED_ANIMALS: 500
ANVIL: 500
MINECART: 500
FISH_SCOOPING: 500
@@ -256,6 +279,8 @@ world:
END_PORTAL: 500
BREEDING: 500
HURT_VILLAGERS: 500
+ BOOKSHELF: 500
+ HARVEST: 500
TURTLE_EGGS: 500
FROST_WALKER: 500
COLLECT_LAVA: 500
@@ -268,6 +293,7 @@ world:
NAME_TAG: 500
ARMOR_STAND: 500
CHANGE_SETTINGS: 1000
+ SIGN_EDITING: 500
TRADING: 0
EGGS: 500
ITEM_DROP: 0
@@ -278,15 +304,19 @@ world:
SCULK_SENSOR: 500
LECTERN: 500
SHULKER_BOX: 500
+ GRINDSTONE: 500
ITEM_PICKUP: 0
CROP_TRAMPLE: 500
DROPPER: 500
BREWING: 500
+ MOVE_BOX: 1000
TNT_PRIMING: 500
+ PARKOUR_CREATIVE: 500
COLLECT_WATER: 500
AXOLOTL_SCOOPING: 500
BUTTON: 500
COMPOSTER: 500
+ STONECUTTING: 500
FIRE_EXTINGUISH: 500
COMMAND_RANKS: 500
BEACON: 500
@@ -298,6 +328,7 @@ world:
HIVE: 500
ITEM_FRAME: 500
PLACE_BLOCKS: 500
+ CROP_PLANTING: 500
CRAFTING: 0
SHEARING: 500
ENCHANTING: 0
@@ -309,8 +340,10 @@ world:
DISPENSER: 500
SCULK_SHRIEKER: 500
GATE: 0
+ SMITHING: 500
EXPERIENCE_PICKUP: 500
HOPPER: 500
+ CANDLES: 500
LEASH: 500
MOUNT_INVENTORY: 500
BREAK_BLOCKS: 500
@@ -320,13 +353,16 @@ world:
POTION_THROWING: 500
BARREL: 500
COLLECT_POWDERED_SNOW: 500
+ CARTOGRAPHY: 500
# These are the default settings for new islands
default-island-settings:
PVP_END: false
PVP_NETHER: false
LEAF_DECAY: true
+ ENDERMAN_TELEPORT: true
ANIMAL_NATURAL_SPAWN: true
MONSTER_NATURAL_SPAWN: true
+ SHULKER_TELEPORT: true
FIRE_SPREAD: true
FIRE_BURNING: true
PVP_OVERWORLD: false
@@ -551,4 +587,3 @@ protection:
do-not-edit-these-settings:
# These settings should not be edited
reset-epoch: 0
-
diff --git a/src/main/resources/locales/hr.yml b/src/main/resources/locales/hr.yml
new file mode 100644
index 0000000..5332d57
--- /dev/null
+++ b/src/main/resources/locales/hr.yml
@@ -0,0 +1,7 @@
+---
+acidisland:
+ sign:
+ line0: "&1Otok kiseline"
+ line1: "[Ime]"
+ line2: Voda je kiselina!
+ line3: Budi oprezan! &c<3