diff --git a/pom.xml b/pom.xml
index 16055c7..cebdfea 100644
--- a/pom.xml
+++ b/pom.xml
@@ -67,7 +67,7 @@
-LOCAL
- 2.19.3
+ 2.20.0BentoBoxWorld_Levelbentobox-worldhttps://sonarcloud.io
diff --git a/src/main/java/world/bentobox/level/Level.java b/src/main/java/world/bentobox/level/Level.java
index d1b1d36..0ba0c1b 100644
--- a/src/main/java/world/bentobox/level/Level.java
+++ b/src/main/java/world/bentobox/level/Level.java
@@ -339,12 +339,13 @@ public long getIslandLevel(World world, @Nullable UUID targetPlayer) {
}
/**
- * Sets the player's level to a value
- *
- * @param world - world
- * @param targetPlayer - target player
- * @param level - level
- */
+ * Sets the player's level to a value. This will only last until the player reruns the level command
+ *
+ * @param world - world
+ * @param targetPlayer - target player
+ * @param level - level
+ * @deprecated This is a useless method.
+ */
public void setIslandLevel(World world, UUID targetPlayer, long level) {
getManager().setIslandLevel(world, targetPlayer, level);
}
@@ -355,19 +356,31 @@ public void setIslandLevel(World world, UUID targetPlayer, long level) {
* @param island - island
* @param level - initial calculated island level
*/
- public void setInitialIslandLevel(@NonNull Island island, long level) {
- getManager().setInitialIslandLevel(island, level);
- }
+ /* TODO
+ public void setInitialIslandLevel(@NonNull Island island, long level) {
+ getManager().setInitialIslandLevel(island, level);
+ }
+
+ /**
+ * Get the initial island level
+ *
+ * @param island - island
+ * @return level or 0 by default
+ */
+ /* TODO
+ public long getInitialIslandLevel(@NonNull Island island) {
+ return getManager().getInitialLevel(island);
+ }*/
- /**
- * Get the initial island level
- *
- * @param island - island
- * @return level or 0 by default
- */
- public long getInitialIslandLevel(@NonNull Island island) {
- return getManager().getInitialLevel(island);
- }
+ /**
+ * Get the initial island count
+ *
+ * @param island - island
+ * @return count or 0 by default
+ */
+ public long getInitialIslandCount(@NonNull Island island) {
+ return getManager().getInitialCount(island);
+ }
/**
* Calculates a user's island
@@ -392,21 +405,22 @@ public void calculateIslandLevel(World world, @Nullable User user, @NonNull UUID
* @return LevelsData object or null if not found. Only island levels are set!
* @deprecated Do not use this anymore. Use {@link #getIslandLevel(World, UUID)}
*/
- @Deprecated(since = "2.3.0", forRemoval = true)
- public LevelsData getLevelsData(UUID targetPlayer) {
- LevelsData ld = new LevelsData(targetPlayer);
- getPlugin().getAddonsManager().getGameModeAddons().stream()
- .filter(gm -> !settings.getGameModes().contains(gm.getDescription().getName())).forEach(gm -> {
- if (getSettings().isZeroNewIslandLevels()) {
- Island island = getIslands().getIsland(gm.getOverWorld(), targetPlayer);
- if (island != null) {
- ld.setInitialLevel(gm.getOverWorld(), this.getInitialIslandLevel(island));
- }
- }
- ld.setLevel(gm.getOverWorld(), this.getIslandLevel(gm.getOverWorld(), targetPlayer));
- });
- return ld;
- }
+ /*
+ @Deprecated(since = "2.3.0", forRemoval = true)
+ public LevelsData getLevelsData(UUID targetPlayer) {
+ LevelsData ld = new LevelsData(targetPlayer);
+ getPlugin().getAddonsManager().getGameModeAddons().stream()
+ .filter(gm -> !settings.getGameModes().contains(gm.getDescription().getName())).forEach(gm -> {
+ if (getSettings().isZeroNewIslandLevels()) {
+ Island island = getIslands().getIsland(gm.getOverWorld(), targetPlayer);
+ if (island != null) {
+ ld.setInitialLevel(gm.getOverWorld(), this.getInitialIslandLevel(island));
+ }
+ }
+ ld.setLevel(gm.getOverWorld(), this.getIslandLevel(gm.getOverWorld(), targetPlayer));
+ });
+ return ld;
+ }*/
/**
* @return the registeredGameModes
diff --git a/src/main/java/world/bentobox/level/LevelsManager.java b/src/main/java/world/bentobox/level/LevelsManager.java
index 61cb122..ac9c46b 100644
--- a/src/main/java/world/bentobox/level/LevelsManager.java
+++ b/src/main/java/world/bentobox/level/LevelsManager.java
@@ -1,7 +1,9 @@
package world.bentobox.level;
+import java.io.IOException;
import java.math.BigInteger;
import java.text.DecimalFormat;
+import java.text.ParseException;
import java.time.Instant;
import java.util.AbstractMap;
import java.util.Collections;
@@ -26,6 +28,7 @@
import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.objects.Island;
+import world.bentobox.level.calculators.EquationEvaluator;
import world.bentobox.level.calculators.Results;
import world.bentobox.level.events.IslandLevelCalculatedEvent;
import world.bentobox.level.events.IslandPreLevelEvent;
@@ -130,7 +133,7 @@ private boolean fireIslandLevelCalcEvent(UUID targetPlayer, Island island, Resul
return true;
// Set the values if they were altered
results.setLevel((Long) ilce.getKeyValues().getOrDefault("level", results.getLevel()));
- results.setInitialLevel((Long) ilce.getKeyValues().getOrDefault("initialLevel", results.getInitialLevel()));
+ results.setInitialCount((Long) ilce.getKeyValues().getOrDefault("initialCount", results.getInitialCount()));
results.setDeathHandicap((int) ilce.getKeyValues().getOrDefault("deathHandicap", results.getDeathHandicap()));
results.setPointsToNextLevel(
(Long) ilce.getKeyValues().getOrDefault("pointsToNextLevel", results.getPointsToNextLevel()));
@@ -168,13 +171,65 @@ public String formatLevel(@Nullable Long lvl) {
}
/**
- * Get the initial level of the island. Used to zero island levels
+ * Get the initial count of the island. Used to zero island levels
*
* @param island - island
- * @return initial level of island
+ * @return initial count of island
*/
- public long getInitialLevel(Island island) {
- return getLevelsData(island).getInitialLevel();
+ @SuppressWarnings("deprecation")
+ public long getInitialCount(Island island) {
+ Long initialLevel = getLevelsData(island).getInitialLevel(); // Backward compatibility check. For all new islands, this should be null.
+ Long initialCount = getLevelsData(island).getInitialCount();
+ if (initialLevel != null) {
+ // Initial level exists so convert it
+ if (initialCount == null) { // If initialCount is not null, then this is an edge case and initialCount will be used and initialLevel discarded
+ // Convert from level to count
+ initialCount = 0L;
+ try {
+ initialCount = getNumBlocks(initialLevel);
+ } catch (Exception e) {
+ addon.logError("Could not convert legacy initial level to count, so it will be set to 0. Error is: "
+ + e.getLocalizedMessage());
+ initialCount = 0L;
+ }
+ }
+ // Null out the old initial level and save
+ getLevelsData(island).setInitialLevel(null);
+ // Save
+ this.setInitialIslandCount(island, initialCount);
+ }
+ // If initialCount doesn't exist, set it to 0L
+ if (initialCount == null) {
+ initialCount = 0L;
+ getLevelsData(island).setInitialCount(0L);
+ }
+ return initialCount;
+ }
+
+ /**
+ * Runs the level calculation using the current formula until the level matches the initial value, or fails.
+ * @param initialLevel - the old initial level
+ * @return block count to obtain this level now
+ * @throws ParseException if the formula for level calc is bugged
+ * @throws IOException if the number of blocks cannot be found for this level
+ */
+ private long getNumBlocks(final long initialLevel) throws ParseException, IOException {
+ String calcString = addon.getSettings().getLevelCalc();
+ int result = -1;
+ long calculatedLevel = 0;
+ String withCost = calcString.replace("level_cost", String.valueOf(this.addon.getSettings().getLevelCost()));
+ long time = System.currentTimeMillis() + 10 * 1000; // 10 seconds
+ do {
+ result++;
+ if (System.currentTimeMillis() > time) {
+ throw new IOException("Timeout: Blocks cannot be found to create this initial level");
+ }
+ // Paste in the values to the formula
+ String withValues = withCost.replace("blocks", String.valueOf(result));
+ // Try and evaluate it
+ calculatedLevel = (long) EquationEvaluator.eval(withValues);
+ } while (calculatedLevel != initialLevel);
+ return result;
}
/**
@@ -422,15 +477,13 @@ public void removeEntry(World world, String uuid) {
}
/**
- * Set an initial island level
+ * Set an initial island count
*
- * @param island - the island to set. Must have a non-null world
- * @param lv - initial island level
+ * @param island - the island to set.
+ * @param lv - initial island count
*/
- public void setInitialIslandLevel(@NonNull Island island, long lv) {
- if (island.getWorld() == null)
- return;
- levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new).setInitialLevel(lv);
+ public void setInitialIslandCount(@NonNull Island island, long lv) {
+ levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new).setInitialCount(lv);
handler.saveObjectAsync(levelsCache.get(island.getUniqueId()));
}
@@ -448,12 +501,7 @@ public void setIslandLevel(@NonNull World world, @NonNull UUID targetPlayer, lon
if (island != null) {
String id = island.getUniqueId();
IslandLevels il = levelsCache.computeIfAbsent(id, IslandLevels::new);
- // Remove the initial level
- if (addon.getSettings().isZeroNewIslandLevels()) {
- il.setLevel(lv - il.getInitialLevel());
- } else {
- il.setLevel(lv);
- }
+ il.setLevel(lv);
handler.saveObjectAsync(levelsCache.get(id));
// Update TopTen
addToTopTen(island, levelsCache.get(id).getLevel());
diff --git a/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java b/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java
index 9188594..da71e57 100644
--- a/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java
+++ b/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java
@@ -93,7 +93,8 @@ public IslandLevelCalculator(Level addon, Island island, CompletableFuture();
// Get the initial island level
- results.initialLevel.set(addon.getInitialIslandLevel(island));
+ // TODO: results.initialLevel.set(addon.getInitialIslandLevel(island));
+ results.setInitialCount(addon.getInitialIslandCount(island));
// Set up the worlds
worlds.put(Environment.NORMAL, Util.getWorld(island.getWorld()));
// Nether
@@ -117,19 +118,22 @@ public IslandLevelCalculator(Level addon, Island island, CompletableFuture getReport() {
reportLines.add("Formula to calculate island level: " + addon.getSettings().getLevelCalc());
reportLines.add("Level cost = " + addon.getSettings().getLevelCost());
reportLines.add("Deaths handicap = " + results.deathHandicap.get());
+ /*
if (addon.getSettings().isZeroNewIslandLevels()) {
reportLines.add("Initial island level = " + (0L - addon.getManager().getInitialLevel(island)));
+ }*/
+ if (addon.getSettings().isZeroNewIslandLevels()) {
+ reportLines.add("Initial island count = " + (0L - addon.getManager().getInitialCount(island)));
}
reportLines.add("Previous level = " + addon.getManager().getIslandLevel(island.getWorld(), island.getOwner()));
reportLines.add("New level = " + results.getLevel());
diff --git a/src/main/java/world/bentobox/level/calculators/Results.java b/src/main/java/world/bentobox/level/calculators/Results.java
index b744046..6dbd2a5 100644
--- a/src/main/java/world/bentobox/level/calculators/Results.java
+++ b/src/main/java/world/bentobox/level/calculators/Results.java
@@ -7,6 +7,9 @@
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
+/**
+ * Where results are stored
+ */
public class Results {
public enum Result {
/**
@@ -23,9 +26,21 @@ public enum Result {
TIMEOUT
}
List report;
+ /**
+ * MaterialData count anything above sea level
+ */
final Multiset