|
1 | 1 | package world.bentobox.level; |
2 | 2 |
|
| 3 | +import java.io.IOException; |
3 | 4 | import java.math.BigInteger; |
4 | 5 | import java.text.DecimalFormat; |
| 6 | +import java.text.ParseException; |
5 | 7 | import java.time.Instant; |
6 | 8 | import java.util.AbstractMap; |
7 | 9 | import java.util.Collections; |
|
26 | 28 |
|
27 | 29 | import world.bentobox.bentobox.database.Database; |
28 | 30 | import world.bentobox.bentobox.database.objects.Island; |
| 31 | +import world.bentobox.level.calculators.EquationEvaluator; |
29 | 32 | import world.bentobox.level.calculators.Results; |
30 | 33 | import world.bentobox.level.events.IslandLevelCalculatedEvent; |
31 | 34 | import world.bentobox.level.events.IslandPreLevelEvent; |
@@ -130,7 +133,6 @@ private boolean fireIslandLevelCalcEvent(UUID targetPlayer, Island island, Resul |
130 | 133 | return true; |
131 | 134 | // Set the values if they were altered |
132 | 135 | results.setLevel((Long) ilce.getKeyValues().getOrDefault("level", results.getLevel())); |
133 | | - // TODO: results.setInitialLevel((Long) ilce.getKeyValues().getOrDefault("initialLevel", results.getInitialLevel())); |
134 | 136 | results.setInitialCount((Long) ilce.getKeyValues().getOrDefault("initialCount", results.getInitialCount())); |
135 | 137 | results.setDeathHandicap((int) ilce.getKeyValues().getOrDefault("deathHandicap", results.getDeathHandicap())); |
136 | 138 | results.setPointsToNextLevel( |
@@ -168,25 +170,66 @@ public String formatLevel(@Nullable Long lvl) { |
168 | 170 | return level; |
169 | 171 | } |
170 | 172 |
|
171 | | - /** |
172 | | - * Get the initial level of the island. Used to zero island levels |
173 | | - * |
174 | | - * @param island - island |
175 | | - * @return initial level of island |
176 | | - */ |
177 | | - /*TODO |
178 | | - public long getInitialLevel(Island island) { |
179 | | - return getLevelsData(island).getInitialLevel(); |
180 | | - }*/ |
181 | | - |
182 | 173 | /** |
183 | 174 | * Get the initial count of the island. Used to zero island levels |
184 | 175 | * |
185 | 176 | * @param island - island |
186 | 177 | * @return initial count of island |
187 | 178 | */ |
| 179 | + @SuppressWarnings("deprecation") |
188 | 180 | public long getInitialCount(Island island) { |
189 | | - return getLevelsData(island).getInitialCount(); |
| 181 | + Long initialLevel = getLevelsData(island).getInitialLevel(); // Backward compatibility check. For all new islands, this should be null. |
| 182 | + Long initialCount = getLevelsData(island).getInitialCount(); |
| 183 | + if (initialLevel != null) { |
| 184 | + // Initial level exists so convert it |
| 185 | + if (initialCount == null) { // If initialCount is not null, then this is an edge case and initialCount will be used and initialLevel discarded |
| 186 | + // Convert from level to count |
| 187 | + initialCount = 0L; |
| 188 | + try { |
| 189 | + initialCount = getNumBlocks(initialLevel); |
| 190 | + } catch (Exception e) { |
| 191 | + addon.logError("Could not convert legacy initial level to count, so it will be set to 0. Error is: " |
| 192 | + + e.getLocalizedMessage()); |
| 193 | + initialCount = 0L; |
| 194 | + } |
| 195 | + } |
| 196 | + // Null out the old initial level and save |
| 197 | + getLevelsData(island).setInitialLevel(null); |
| 198 | + // Save |
| 199 | + this.setInitialIslandCount(island, initialCount); |
| 200 | + } |
| 201 | + // If initialCount doesn't exist, set it to 0L |
| 202 | + if (initialCount == null) { |
| 203 | + initialCount = 0L; |
| 204 | + getLevelsData(island).setInitialCount(0L); |
| 205 | + } |
| 206 | + return initialCount; |
| 207 | + } |
| 208 | + |
| 209 | + /** |
| 210 | + * Runs the level calculation using the current formula until the level matches the initial value, or fails. |
| 211 | + * @param initialLevel - the old initial level |
| 212 | + * @return block count to obtain this level now |
| 213 | + * @throws ParseException if the formula for level calc is bugged |
| 214 | + * @throws IOException if the number of blocks cannot be found for this level |
| 215 | + */ |
| 216 | + private long getNumBlocks(final long initialLevel) throws ParseException, IOException { |
| 217 | + String calcString = addon.getSettings().getLevelCalc(); |
| 218 | + int result = -1; |
| 219 | + long calculatedLevel = 0; |
| 220 | + String withCost = calcString.replace("level_cost", String.valueOf(this.addon.getSettings().getLevelCost())); |
| 221 | + long time = System.currentTimeMillis() + 10 * 1000; // 10 seconds |
| 222 | + do { |
| 223 | + result++; |
| 224 | + if (System.currentTimeMillis() > time) { |
| 225 | + throw new IOException("Timeout: Blocks cannot be found to create this initial level"); |
| 226 | + } |
| 227 | + // Paste in the values to the formula |
| 228 | + String withValues = withCost.replace("blocks", String.valueOf(result)); |
| 229 | + // Try and evaluate it |
| 230 | + calculatedLevel = (long) EquationEvaluator.eval(withValues); |
| 231 | + } while (calculatedLevel != initialLevel); |
| 232 | + return result; |
190 | 233 | } |
191 | 234 |
|
192 | 235 | /** |
@@ -433,23 +476,6 @@ public void removeEntry(World world, String uuid) { |
433 | 476 | } |
434 | 477 | } |
435 | 478 |
|
436 | | - /** |
437 | | - * Set an initial island level |
438 | | - * |
439 | | - * @param island - the island to set. Must have a non-null world |
440 | | - * @param lv - initial island level |
441 | | - * @deprecated Use {@link #setInitialIslandCount(Island, long)} |
442 | | - */ |
443 | | - /* |
444 | | - @Deprecated |
445 | | - public void setInitialIslandLevel(@NonNull Island island, long lv) { |
446 | | - // TODO convert to a count |
447 | | - if (island.getWorld() == null) |
448 | | - return; |
449 | | - levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new).setInitialLevel(lv); |
450 | | - handler.saveObjectAsync(levelsCache.get(island.getUniqueId())); |
451 | | - } |
452 | | - */ |
453 | 479 | /** |
454 | 480 | * Set an initial island count |
455 | 481 | * |
|
0 commit comments