diff --git a/pom.xml b/pom.xml
index c76d008..88003e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,13 +6,24 @@
world.bentobox
level
- 1.5.0
+ ${revision}
Level
Level is an add-on for BentoBox, an expandable Minecraft Bukkit plugin for island-type games like SkyBlock or AcidIsland.
https://github.com/BentoBoxWorld/Level
2017
+
+
+ tastybento
+ tastybento@bentobox.world
+ -8
+
+ Lead Developer
+
+
+
+
scm:git:https://github.com/BentoBoxWorld/Level.git
scm:git:git@github.com:BentoBoxWorld/Level.git
@@ -41,12 +52,59 @@
- UTF-8
- UTF-8
- 1.8
- 1.7.4
+ UTF-8
+ UTF-8
+ 1.8
+
+ 2.0.2
+
+ 1.13.2-R0.1-SNAPSHOT
+ 1.6.0-SNAPSHOT
+
+ ${build.version}-SNAPSHOT
+
+ -LOCAL
+
+ 1.6.0
+
+
+
+
+
+ ci
+
+
+ env.BUILD_NUMBER
+
+
+
+
+ -b${env.BUILD_NUMBER}
+
+
+
+
+
+
+
+ master
+
+
+ env.GIT_BRANCH
+ origin/master
+
+
+
+
+ ${build.version}
+
+
+
+
+
+
spigot-repo
@@ -62,40 +120,50 @@
-
-
- org.spigotmc
- spigot-api
- 1.14.1-R0.1-SNAPSHOT
- provided
-
-
- org.mockito
- mockito-all
- 1.10.19
- test
-
-
- org.powermock
- powermock-module-junit4
- ${powermock.version}
- test
-
-
- org.powermock
- powermock-api-mockito
- ${powermock.version}
- test
-
-
- world.bentobox
- bentobox
- 1.5.0
- provided
-
-
+
+
+
+ org.spigotmc
+ spigot-api
+ ${spigot.version}
+ provided
+
+
+
+ org.mockito
+ mockito-core
+ 3.0.0
+ test
+
+
+ org.powermock
+ powermock-module-junit4
+ ${powermock.version}
+ test
+
+
+ org.powermock
+ powermock-api-mockito2
+ ${powermock.version}
+ test
+
+
+ world.bentobox
+ bentobox
+ ${bentobox.version}
+ provided
+
+
+
+
+
+
+
+
+ ${project.name}-${revision}${build.number}
+
clean package
diff --git a/src/main/java/world/bentobox/level/Level.java b/src/main/java/world/bentobox/level/Level.java
index 127c3f0..181faf5 100644
--- a/src/main/java/world/bentobox/level/Level.java
+++ b/src/main/java/world/bentobox/level/Level.java
@@ -5,6 +5,7 @@ import java.util.Map;
import java.util.UUID;
import org.bukkit.World;
+import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.user.User;
@@ -46,7 +47,7 @@ public class Level extends Addon {
private TopTen topTen;
// Level calculator
- private LevelPresenter levelCalc;
+ private LevelPresenter levelPresenter;
/**
* Calculates a user's island
@@ -54,8 +55,8 @@ public class Level extends Addon {
* @param user - the user who is asking, or null if none
* @param playerUUID - the target island member's UUID
*/
- public void calculateIslandLevel(World world, User user, UUID playerUUID) {
- levelCalc.calculateIslandLevel(world, user, playerUUID);
+ public void calculateIslandLevel(World world, @Nullable User user, UUID playerUUID) {
+ levelPresenter.calculateIslandLevel(world, user, playerUUID);
}
/**
@@ -85,7 +86,7 @@ public class Level extends Addon {
/**
* @return the settings
*/
- public final Settings getSettings() {
+ public Settings getSettings() {
return settings;
}
@@ -93,6 +94,13 @@ public class Level extends Addon {
return topTen;
}
+ /**
+ * @return the levelPresenter
+ */
+ public LevelPresenter getLevelPresenter() {
+ return levelPresenter;
+ }
+
@Override
public void onDisable(){
// Save the cache
@@ -115,7 +123,7 @@ public class Level extends Addon {
// Initialize the cache
levelsCache = new HashMap<>();
// Load the calculator
- levelCalc = new LevelPresenter(this, this.getPlugin());
+ levelPresenter = new LevelPresenter(this, this.getPlugin());
// Start the top ten and register it for clicks
topTen = new TopTen(this);
registerListener(topTen);
@@ -208,7 +216,7 @@ public class Level extends Addon {
public long getInitialIslandLevel(Island island) {
return levelsCache.containsKey(island.getOwner()) ? levelsCache.get(island.getOwner()).getInitialLevel(island.getWorld()) : 0L;
}
-
+
public Database getHandler() {
return handler;
}
diff --git a/src/main/java/world/bentobox/level/LevelPresenter.java b/src/main/java/world/bentobox/level/LevelPresenter.java
index 8edc82d..c4a5bd3 100644
--- a/src/main/java/world/bentobox/level/LevelPresenter.java
+++ b/src/main/java/world/bentobox/level/LevelPresenter.java
@@ -1,7 +1,11 @@
package world.bentobox.level;
+import java.math.BigInteger;
+import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
import java.util.UUID;
import org.bukkit.World;
@@ -10,7 +14,18 @@ import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.level.calculators.PlayerLevel;
-class LevelPresenter {
+public class LevelPresenter {
+
+ private static final BigInteger THOUSAND = BigInteger.valueOf(1000);
+ private static final TreeMap LEVELS;
+ static {
+ LEVELS = new TreeMap<>();
+
+ LEVELS.put(THOUSAND, "k");
+ LEVELS.put(THOUSAND.pow(2), "M");
+ LEVELS.put(THOUSAND.pow(3), "G");
+ LEVELS.put(THOUSAND.pow(4), "T");
+ }
private int levelWait;
private final Level addon;
@@ -41,16 +56,18 @@ class LevelPresenter {
targetPlayer = plugin.getIslands().getOwner(world, targetPlayer);
inTeam = true;
} else {
- sender.sendMessage("general.errors.player-has-no-island");
+ if (sender != null) sender.sendMessage("general.errors.player-has-no-island");
return;
}
}
// Player asking for their own island calc
- if (inTeam || !sender.isPlayer() || sender.getUniqueId().equals(targetPlayer) || sender.isOp() || sender.hasPermission(permPrefix + "mod.info")) {
+ if (sender == null || inTeam || !sender.isPlayer() || sender.getUniqueId().equals(targetPlayer) || sender.isOp() || sender.hasPermission(permPrefix + "mod.info")) {
// Newer better system - uses chunks
- if (!onLevelWaitTime(sender) || levelWait <= 0 || sender.isOp() || sender.hasPermission(permPrefix + "mod.info")) {
- sender.sendMessage("island.level.calculating");
- setLevelWaitTime(sender);
+ if (sender == null || !onLevelWaitTime(sender) || levelWait <= 0 || sender.isOp() || sender.hasPermission(permPrefix + "mod.info")) {
+ if (sender != null) {
+ sender.sendMessage("island.level.calculating");
+ setLevelWaitTime(sender);
+ }
new PlayerLevel(addon, plugin.getIslands().getIsland(world, targetPlayer), targetPlayer, sender);
} else {
// Cooldown
@@ -58,11 +75,36 @@ class LevelPresenter {
}
} else {
- // Asking for the level of another player
- sender.sendMessage("island.level.island-level-is","[level]", String.valueOf(addon.getIslandLevel(world, targetPlayer)));
+ long lvl = addon.getIslandLevel(world, targetPlayer);
+
+ sender.sendMessage("island.level.island-level-is","[level]", getLevelString(lvl));
}
}
+ /**
+ * Get the string representation of the level. May be converted to shorthand notation, e.g., 104556 -> 10.5k
+ * @param lvl - long value to represent
+ * @return string of the level.
+ */
+ public String getLevelString(long lvl) {
+ String level = String.valueOf(lvl);
+ // Asking for the level of another player
+ if(addon.getSettings().isShortHand()) {
+ BigInteger levelValue = BigInteger.valueOf(lvl);
+
+ Map.Entry stage = LEVELS.floorEntry(levelValue);
+
+ if (stage != null) { // level > 1000
+ // 1 052 -> 1.0k
+ // 1 527 314 -> 1.5M
+ // 3 874 130 021 -> 3.8G
+ // 4 002 317 889 -> 4.0T
+ level = new DecimalFormat("#.#").format(levelValue.divide(stage.getKey().divide(THOUSAND)).doubleValue()/1000.0) + stage.getValue();
+ }
+ }
+ return level;
+ }
+
/**
* Sets cool down for the level command
*
diff --git a/src/main/java/world/bentobox/level/TopTen.java b/src/main/java/world/bentobox/level/TopTen.java
index 24b1576..157375b 100644
--- a/src/main/java/world/bentobox/level/TopTen.java
+++ b/src/main/java/world/bentobox/level/TopTen.java
@@ -28,11 +28,11 @@ import world.bentobox.level.objects.TopTenData;
*
*/
public class TopTen implements Listener {
- private final Level addon;
+ private Level addon;
// Top ten list of players
private Map topTenList;
private final int[] SLOTS = new int[] {4, 12, 14, 19, 20, 21, 22, 23, 24, 25};
- private final Database handler;
+ private Database handler;
public TopTen(Level addon) {
this.addon = addon;
@@ -42,6 +42,21 @@ public class TopTen implements Listener {
loadTopTen();
}
+ /**
+ * Loads all the top tens from the database
+ */
+ private void loadTopTen() {
+ topTenList = new HashMap<>();
+ handler.loadObjects().forEach(tt -> {
+ World world = Bukkit.getWorld(tt.getUniqueId());
+ if (world != null) {
+ topTenList.put(world, tt);
+ } else {
+ addon.logError("TopTen world " + tt.getUniqueId() + " is not known on server. Skipping...");
+ }
+ });
+ }
+
/**
* Adds a player to the top ten, if the level is good enough
*
@@ -58,8 +73,8 @@ public class TopTen implements Listener {
topTenList.get(world).setUniqueId(world.getName());
// Try and see if the player is online
- Player player = addon.getServer().getPlayer(ownerUUID);
- if (player != null && !player.hasPermission(addon.getPlugin().getIWM().getPermissionPrefix(world) + ".intopten")) {
+ Player player = Bukkit.getServer().getPlayer(ownerUUID);
+ if (player != null && !player.hasPermission(addon.getPlugin().getIWM().getPermissionPrefix(world) + "intopten")) {
topTenList.get(world).remove(ownerUUID);
return;
}
@@ -86,7 +101,7 @@ public class TopTen implements Listener {
Map.Entry m = it.next();
UUID topTenUUID = m.getKey();
// Remove from TopTen if the player is online and has the permission
- Player entry = addon.getServer().getPlayer(topTenUUID);
+ Player entry = Bukkit.getServer().getPlayer(topTenUUID);
boolean show = true;
if (entry != null) {
if (!entry.hasPermission(permPrefix + "intopten")) {
@@ -110,12 +125,12 @@ public class TopTen implements Listener {
* @param asker - the asker of the top ten
* @return PanelItem
*/
- private PanelItem getHead(int rank, Long level, UUID playerUUID, User asker, World world) {
+ private PanelItem getHead(int rank, long level, UUID playerUUID, User asker, World world) {
final String name = addon.getPlayers().getName(playerUUID);
List description = new ArrayList<>();
if (name != null) {
description.add(asker.getTranslation("island.top.gui-heading", "[name]", name, "[rank]", String.valueOf(rank)));
- description.add(asker.getTranslation("island.top.island-level","[level]", String.valueOf(level)));
+ description.add(asker.getTranslation("island.top.island-level","[level]", addon.getLevelPresenter().getLevelString(level)));
if (addon.getIslands().inTeam(world, playerUUID)) {
List memberList = new ArrayList<>();
for (UUID members : addon.getIslands().getMembers(world, playerUUID)) {
@@ -131,16 +146,14 @@ public class TopTen implements Listener {
return builder.build();
}
- public TopTenData getTopTenList(World world) {
- return topTenList.get(world);
- }
-
/**
- * Loads all the top tens from the database
+ * Get the top ten list for this world
+ * @param world - world
+ * @return top ten data object
*/
- private void loadTopTen() {
- topTenList = new HashMap<>();
- handler.loadObjects().forEach(tt -> topTenList.put(Bukkit.getWorld(tt.getUniqueId()), tt));
+ public TopTenData getTopTenList(World world) {
+ topTenList.putIfAbsent(world, new TopTenData());
+ return topTenList.get(world);
}
/**
diff --git a/src/main/java/world/bentobox/level/calculators/CalcIslandLevel.java b/src/main/java/world/bentobox/level/calculators/CalcIslandLevel.java
index a18ecef..a1b060b 100644
--- a/src/main/java/world/bentobox/level/calculators/CalcIslandLevel.java
+++ b/src/main/java/world/bentobox/level/calculators/CalcIslandLevel.java
@@ -12,7 +12,10 @@ import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChunkSnapshot;
import org.bukkit.Material;
+import org.bukkit.Tag;
import org.bukkit.World;
+import org.bukkit.block.data.BlockData;
+import org.bukkit.block.data.type.Slab;
import org.bukkit.scheduler.BukkitTask;
import com.google.common.collect.HashMultiset;
@@ -28,8 +31,8 @@ import world.bentobox.level.Level;
public class CalcIslandLevel {
- private static final int MAX_CHUNKS = 200;
- private static final long SPEED = 1;
+ private final int MAX_CHUNKS;
+ private final long SPEED;
private static final String LINE_BREAK = "==================================";
private boolean checking;
private final BukkitTask task;
@@ -38,12 +41,13 @@ public class CalcIslandLevel {
private final Set> chunksToScan;
private final Island island;
- private final World world;
private final Results result;
private final Runnable onExit;
// Copy the limits hash map
private final HashMap limitCount;
+ private final World world;
+ private final List worlds;
/**
@@ -56,7 +60,17 @@ public class CalcIslandLevel {
public CalcIslandLevel(final Level addon, final Island island, final Runnable onExit) {
this.addon = addon;
this.island = island;
- this.world = island.getCenter().getWorld();
+ this.world = island.getWorld();
+ this.worlds = new ArrayList<>();
+ this.worlds.add(world);
+ if (addon.getSettings().isNether()) {
+ World netherWorld = addon.getPlugin().getIWM().getNetherWorld(world);
+ if (netherWorld != null) this.worlds.add(netherWorld);
+ }
+ if (addon.getSettings().isEnd()) {
+ World endWorld = addon.getPlugin().getIWM().getEndWorld(world);
+ if (endWorld != null) this.worlds.add(endWorld);
+ }
this.limitCount = new HashMap<>(addon.getSettings().getBlockLimits());
this.onExit = onExit;
@@ -66,6 +80,9 @@ public class CalcIslandLevel {
// Set the initial island handicap
result.initialLevel = addon.getInitialIslandLevel(island);
+ SPEED = addon.getSettings().getUpdateTickDelay();
+ MAX_CHUNKS = addon.getSettings().getChunksPerTick();
+
// Get chunks to scan
chunksToScan = getChunksToScan(island);
@@ -85,12 +102,14 @@ public class CalcIslandLevel {
// Add chunk snapshots to the list
while (it.hasNext() && chunkSnapshot.size() < MAX_CHUNKS) {
Pair pair = it.next();
- if (!world.isChunkLoaded(pair.x, pair.z)) {
- world.loadChunk(pair.x, pair.z);
- chunkSnapshot.add(world.getChunkAt(pair.x, pair.z).getChunkSnapshot());
- world.unloadChunk(pair.x, pair.z);
- } else {
- chunkSnapshot.add(world.getChunkAt(pair.x, pair.z).getChunkSnapshot());
+ for (World world : worlds) {
+ if (!world.isChunkLoaded(pair.x, pair.z)) {
+ world.loadChunk(pair.x, pair.z);
+ chunkSnapshot.add(world.getChunkAt(pair.x, pair.z).getChunkSnapshot());
+ world.unloadChunk(pair.x, pair.z);
+ } else {
+ chunkSnapshot.add(world.getChunkAt(pair.x, pair.z).getChunkSnapshot());
+ }
}
it.remove();
}
@@ -114,6 +133,10 @@ public class CalcIslandLevel {
}
private void scanChunk(ChunkSnapshot chunk) {
+ World chunkWorld = Bukkit.getWorld(chunk.getWorldName());
+ if (chunkWorld == null) return;
+ int maxHeight = chunkWorld.getMaxHeight();
+
for (int x = 0; x< 16; x++) {
// Check if the block coordinate is inside the protection zone and if not, don't count it
if (chunk.getX() * 16 + x < island.getMinProtectedX() || chunk.getX() * 16 + x >= island.getMinProtectedX() + island.getProtectionRange() * 2) {
@@ -125,27 +148,31 @@ public class CalcIslandLevel {
continue;
}
- for (int y = 0; y < island.getCenter().getWorld().getMaxHeight(); y++) {
- Material blockData = chunk.getBlockType(x, y, z);
- int seaHeight = addon.getPlugin().getIWM().getSeaHeight(world);
+ for (int y = 0; y < maxHeight; y++) {
+ BlockData blockData = chunk.getBlockData(x, y, z);
+ int seaHeight = addon.getPlugin().getIWM().getSeaHeight(chunkWorld);
boolean belowSeaLevel = seaHeight > 0 && y <= seaHeight;
- // Air is free
- if (!blockData.equals(Material.AIR)) {
- checkBlock(blockData, belowSeaLevel);
+ // Slabs can be doubled, so check them twice
+ if (Tag.SLABS.isTagged(blockData.getMaterial())) {
+ Slab slab = (Slab)blockData;
+ if (slab.getType().equals(Slab.Type.DOUBLE)) {
+ checkBlock(blockData, belowSeaLevel);
+ }
}
+ checkBlock(blockData, belowSeaLevel);
}
}
}
}
- private void checkBlock(Material md, boolean belowSeaLevel) {
- int count = limitCount(md);
+ private void checkBlock(BlockData bd, boolean belowSeaLevel) {
+ int count = limitCount(bd.getMaterial());
if (belowSeaLevel) {
result.underWaterBlockCount += count;
- result.uwCount.add(md);
+ result.uwCount.add(bd.getMaterial());
} else {
result.rawBlockCount += count;
- result.mdCount.add(md);
+ result.mdCount.add(bd.getMaterial());
}
}
@@ -194,8 +221,7 @@ public class CalcIslandLevel {
Set> chunkSnapshot = new HashSet<>();
for (int x = island.getMinProtectedX(); x < (island.getMinProtectedX() + island.getProtectionRange() * 2 + 16); x += 16) {
for (int z = island.getMinProtectedZ(); z < (island.getMinProtectedZ() + island.getProtectionRange() * 2 + 16); z += 16) {
- Pair pair = new Pair<>(world.getBlockAt(x, 0, z).getChunk().getX(), world.getBlockAt(x, 0, z).getChunk().getZ());
- chunkSnapshot.add(pair);
+ chunkSnapshot.add(new Pair<>(x >> 4, z >> 4));
}
}
return chunkSnapshot;
@@ -222,9 +248,6 @@ public class CalcIslandLevel {
this.addon.getPlayers().getDeaths(this.world, this.island.getOwner());
}
- // Just lazy check for min death count.
- this.result.deathHandicap = Math.min(this.result.deathHandicap, this.addon.getSettings().getMaxDeaths());
-
long blockAndDeathPoints = this.result.rawBlockCount;
if (this.addon.getSettings().getDeathPenalty() > 0)
@@ -308,10 +331,11 @@ public class CalcIslandLevel {
if (addon.getSettings().getBlockValues().containsKey(type)) {
// Specific
value = addon.getSettings().getBlockValues().get(type);
+
+ r.add(type.toString() + ":"
+ + String.format("%,d", en.getCount()) + " blocks x " + value + " = " + (value * en.getCount()));
+ total += (value * en.getCount());
}
- r.add(type.toString() + ":"
- + String.format("%,d", en.getCount()) + " blocks x " + value + " = " + (value * en.getCount()));
- total += (value * en.getCount());
}
r.add("Subtotal = " + total);
r.add(LINE_BREAK);
diff --git a/src/main/java/world/bentobox/level/calculators/PlayerLevel.java b/src/main/java/world/bentobox/level/calculators/PlayerLevel.java
index dee9e5a..68a71e4 100644
--- a/src/main/java/world/bentobox/level/calculators/PlayerLevel.java
+++ b/src/main/java/world/bentobox/level/calculators/PlayerLevel.java
@@ -5,6 +5,7 @@ import java.util.Map;
import java.util.UUID;
import org.bukkit.World;
+import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.events.addon.AddonEvent;
import world.bentobox.bentobox.api.user.User;
@@ -34,7 +35,7 @@ public class PlayerLevel {
private CalcIslandLevel calc;
- public PlayerLevel(final Level addon, final Island island, final UUID targetPlayer, final User asker) {
+ public PlayerLevel(final Level addon, final Island island, final UUID targetPlayer, @Nullable final User asker) {
this.addon = addon;
this.island = island;
this.world = island.getCenter().getWorld();
@@ -70,7 +71,7 @@ public class PlayerLevel {
// Save the results
island.getMemberSet().forEach(m -> addon.setIslandLevel(world, m, results.getLevel()));
// Display result if event is not cancelled
- if (!ilce.isCancelled()) {
+ if (!ilce.isCancelled() && asker != null) {
informPlayers(results);
}
}
diff --git a/src/main/java/world/bentobox/level/commands/admin/AdminLevelCommand.java b/src/main/java/world/bentobox/level/commands/admin/AdminLevelCommand.java
index a532acf..4840a04 100644
--- a/src/main/java/world/bentobox/level/commands/admin/AdminLevelCommand.java
+++ b/src/main/java/world/bentobox/level/commands/admin/AdminLevelCommand.java
@@ -6,17 +6,18 @@ import java.util.Optional;
import java.util.UUID;
import world.bentobox.bentobox.api.commands.CompositeCommand;
+import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
import world.bentobox.level.Level;
public class AdminLevelCommand extends CompositeCommand {
- private final Level levelPlugin;
+ private final Level addon;
- public AdminLevelCommand(Level levelPlugin, CompositeCommand parent) {
+ public AdminLevelCommand(Level addon, CompositeCommand parent) {
super(parent, "level");
- this.levelPlugin = levelPlugin;
+ this.addon = addon;
}
@Override
@@ -34,10 +35,10 @@ public class AdminLevelCommand extends CompositeCommand {
// Convert name to a UUID
final UUID playerUUID = getPlugin().getPlayers().getUUID(args.get(0));
if (playerUUID == null) {
- user.sendMessage("general.errors.unknown-player");
+ user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
return true;
} else {
- levelPlugin.calculateIslandLevel(getWorld(), user, playerUUID);
+ addon.calculateIslandLevel(getWorld(), user, playerUUID);
}
return true;
} else {
@@ -45,7 +46,7 @@ public class AdminLevelCommand extends CompositeCommand {
return false;
}
}
-
+
@Override
public Optional> tabComplete(User user, String alias, List args) {
String lastArg = !args.isEmpty() ? args.get(args.size()-1) : "";
diff --git a/src/main/java/world/bentobox/level/commands/island/IslandLevelCommand.java b/src/main/java/world/bentobox/level/commands/island/IslandLevelCommand.java
index 48314f9..58ada94 100644
--- a/src/main/java/world/bentobox/level/commands/island/IslandLevelCommand.java
+++ b/src/main/java/world/bentobox/level/commands/island/IslandLevelCommand.java
@@ -4,6 +4,7 @@ import java.util.List;
import java.util.UUID;
import world.bentobox.bentobox.api.commands.CompositeCommand;
+import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.level.Level;
@@ -31,7 +32,7 @@ public class IslandLevelCommand extends CompositeCommand {
// Convert name to a UUID
final UUID playerUUID = getPlugin().getPlayers().getUUID(args.get(0));
if (playerUUID == null) {
- user.sendMessage("general.errors.unknown-player");
+ user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
return true;
} else if (user.getUniqueId().equals(playerUUID) ) {
return this.calculateLevel(user);
diff --git a/src/main/java/world/bentobox/level/config/Settings.java b/src/main/java/world/bentobox/level/config/Settings.java
index e0f49dd..0c63609 100644
--- a/src/main/java/world/bentobox/level/config/Settings.java
+++ b/src/main/java/world/bentobox/level/config/Settings.java
@@ -1,6 +1,5 @@
package world.bentobox.level.config;
-import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -14,6 +13,7 @@ import world.bentobox.level.Level;
public class Settings {
+ private Level level;
private boolean sumTeamDeaths;
private Map blockLimits = new HashMap<>();
private Map blockValues = new HashMap<>();
@@ -22,27 +22,49 @@ public class Settings {
private int deathpenalty;
private long levelCost;
private int levelWait;
- private int maxDeaths;
- private boolean islandResetDeathReset;
- private boolean teamJoinDeathReset;
- private List gameModes = new ArrayList<>();
+
+ /**
+ * Stores number of chunks that can be updated in single tick.
+ */
+ private int chunksPerTick;
+
+ /**
+ * Stores number of tick delay between each chunk loading.
+ */
+ private long updateTickDelay;
+
+ private List gameModes;
+
public Settings(Level level) {
-
+ this.level = level;
level.saveDefaultConfig();
// GameModes
gameModes = level.getConfig().getStringList("game-modes");
+ // Level calculation chunk load speed
+ this.setUpdateTickDelay(level.getConfig().getLong("updatetickdelay", 1));
+
+ if (this.getUpdateTickDelay() <= 0)
+ {
+ this.setUpdateTickDelay(1);
+ }
+
+ // Level calculation chunk count per update
+ this.setChunksPerTick(level.getConfig().getInt("chunkspertick", 200));
+
+ if (this.getChunksPerTick() <= 0)
+ {
+ this.setChunksPerTick(200);
+ }
+
setLevelWait(level.getConfig().getInt("levelwait", 60));
if (getLevelWait() < 0) {
setLevelWait(0);
}
setDeathpenalty(level.getConfig().getInt("deathpenalty", 0));
setSumTeamDeaths(level.getConfig().getBoolean("sumteamdeaths"));
- setMaxDeaths(level.getConfig().getInt("maxdeaths", 10));
- setIslandResetDeathReset(level.getConfig().getBoolean("islandresetdeathreset", true));
- setTeamJoinDeathReset(level.getConfig().getBoolean("teamjoindeathreset", true));
setUnderWaterMultiplier(level.getConfig().getDouble("underwater", 1D));
setLevelCost(level.getConfig().getInt("levelcost", 100));
if (getLevelCost() < 1) {
@@ -91,7 +113,7 @@ public class Settings {
worldBlockValues.put(bWorld, values);
}
} else {
- level.getLogger().severe(() -> "Level Addon: No such world : " + world);
+ level.getLogger().severe(() -> "Level Addon: No such world in config.yml : " + world);
}
}
}
@@ -182,44 +204,6 @@ public class Settings {
private void setLevelWait(int levelWait) {
this.levelWait = levelWait;
}
- /**
- * TODO: Use max deaths
- * @return the maxDeaths
- */
- public final int getMaxDeaths() {
- return maxDeaths;
- }
- /**
- * @param maxDeaths the maxDeaths to set
- */
- private void setMaxDeaths(int maxDeaths) {
- this.maxDeaths = maxDeaths;
- }
- /**
- * @return the islandResetDeathReset
- */
- public final boolean isIslandResetDeathReset() {
- return islandResetDeathReset;
- }
- /**
- * @param islandResetDeathReset the islandResetDeathReset to set
- */
- private void setIslandResetDeathReset(boolean islandResetDeathReset) {
- this.islandResetDeathReset = islandResetDeathReset;
- }
- /**
- * @return the teamJoinDeathReset
- */
- public final boolean isTeamJoinDeathReset() {
- return teamJoinDeathReset;
- }
- /**
- * @param teamJoinDeathReset the teamJoinDeathReset to set
- */
- private void setTeamJoinDeathReset(boolean teamJoinDeathReset) {
- this.teamJoinDeathReset = teamJoinDeathReset;
- }
-
/**
* @return the worldBlockValues
*/
@@ -234,4 +218,73 @@ public class Settings {
return gameModes;
}
+ /**
+ * @return if the nether island should be included in the level calc or not
+ */
+ public boolean isNether() {
+ return level.getConfig().getBoolean("nether");
+ }
+
+ /**
+ * @return if the end island should be included in the level calc or not
+ */
+ public boolean isEnd() {
+ return level.getConfig().getBoolean("end");
+ }
+
+ /**
+ * @return true if level should be calculated on login
+ */
+ public boolean isLogin() {
+ return level.getConfig().getBoolean("login");
+ }
+
+ /**
+ * @return true if levels should be shown in shorthand notation, e.g., 10,234 -> 10k
+ */
+ public boolean isShortHand() {
+ return level.getConfig().getBoolean("shorthand");
+ }
+
+
+ /**
+ * This method returns the number of chunks that can be processed at single tick.
+ * @return the value of chunksPerTick.
+ */
+ public int getChunksPerTick()
+ {
+ return this.chunksPerTick;
+ }
+
+
+ /**
+ * This method sets the chunksPerTick value.
+ * @param chunksPerTick the chunksPerTick new value.
+ *
+ */
+ public void setChunksPerTick(int chunksPerTick)
+ {
+ this.chunksPerTick = chunksPerTick;
+ }
+
+
+ /**
+ * This method returns the delay between each update call.
+ * @return the value of updateTickDelay.
+ */
+ public long getUpdateTickDelay()
+ {
+ return this.updateTickDelay;
+ }
+
+
+ /**
+ * This method sets the updateTickDelay value.
+ * @param updateTickDelay the updateTickDelay new value.
+ *
+ */
+ public void setUpdateTickDelay(long updateTickDelay)
+ {
+ this.updateTickDelay = updateTickDelay;
+ }
}
diff --git a/src/main/java/world/bentobox/level/listeners/IslandTeamListeners.java b/src/main/java/world/bentobox/level/listeners/IslandTeamListeners.java
index dfe923e..047c0f6 100644
--- a/src/main/java/world/bentobox/level/listeners/IslandTeamListeners.java
+++ b/src/main/java/world/bentobox/level/listeners/IslandTeamListeners.java
@@ -100,6 +100,13 @@ public class IslandTeamListeners implements Listener {
private void zeroLevel(Island island) {
if (cil.containsKey(island)) {
long level = cil.get(island).getResult().getLevel();
+ // Get deaths
+ int deaths = addon.getPlayers().getDeaths(island.getWorld(), island.getOwner());
+ // Death penalty calculation.
+ if (addon.getSettings().getLevelCost() != 0) {
+ // Add the deaths because this makes the original island that much "bigger"
+ level += deaths * addon.getSettings().getDeathPenalty() / addon.getSettings().getLevelCost();
+ }
addon.setInitialIslandLevel(island, level);
cil.remove(island);
}
diff --git a/src/main/java/world/bentobox/level/listeners/JoinLeaveListener.java b/src/main/java/world/bentobox/level/listeners/JoinLeaveListener.java
index 217c0cd..3323ae0 100644
--- a/src/main/java/world/bentobox/level/listeners/JoinLeaveListener.java
+++ b/src/main/java/world/bentobox/level/listeners/JoinLeaveListener.java
@@ -28,6 +28,14 @@ public class JoinLeaveListener implements Listener {
public void onPlayerJoin(PlayerJoinEvent e) {
// Load player into cache
addon.getLevelsData(e.getPlayer().getUniqueId());
+ // If level calc on login is enabled, run through all the worlds and calculate the level
+ if (addon.getSettings().isLogin()) {
+ addon.getPlugin().getAddonsManager().getGameModeAddons().stream()
+ .filter(gm -> addon.getSettings().getGameModes().contains(gm.getDescription().getName()))
+ .forEach(gm -> {
+ addon.calculateIslandLevel(gm.getOverWorld(), null, e.getPlayer().getUniqueId());
+ });
+ }
}
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
diff --git a/src/main/java/world/bentobox/level/objects/LevelsData.java b/src/main/java/world/bentobox/level/objects/LevelsData.java
index 45c4876..4e251a1 100644
--- a/src/main/java/world/bentobox/level/objects/LevelsData.java
+++ b/src/main/java/world/bentobox/level/objects/LevelsData.java
@@ -1,7 +1,7 @@
package world.bentobox.level.objects;
-import java.util.HashMap;
import java.util.Map;
+import java.util.TreeMap;
import java.util.UUID;
import org.bukkit.World;
@@ -20,12 +20,12 @@ public class LevelsData implements DataObject {
* Map of world name and island level
*/
@Expose
- private Map levels = new HashMap<>();
+ private Map levels = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
/**
* Map of world name to island initial level
*/
@Expose
- private Map initialLevel = new HashMap<>();
+ private Map initialLevel = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
public LevelsData() {} // For Bean loading
@@ -89,7 +89,7 @@ public class LevelsData implements DataObject {
* @param level - level
*/
public void setInitialLevel(World world, long level) {
- this.initialLevel.put(world.getName(), level);
+ this.initialLevel.put(world.getName(), level);
}
/**
diff --git a/src/main/java/world/bentobox/level/objects/TopTenData.java b/src/main/java/world/bentobox/level/objects/TopTenData.java
index 4ad4648..832c90f 100644
--- a/src/main/java/world/bentobox/level/objects/TopTenData.java
+++ b/src/main/java/world/bentobox/level/objects/TopTenData.java
@@ -24,6 +24,8 @@ public class TopTenData implements DataObject {
private Map topTen = new LinkedHashMap<>();
public Map getTopTen() {
+ // Remove any entries that have level values less than 1
+ topTen.values().removeIf(l -> l < 1);
return topTen.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).limit(10)
.collect(Collectors.toMap(
@@ -36,12 +38,14 @@ public class TopTenData implements DataObject {
@Override
public String getUniqueId() {
+ // This is the world name
return uniqueId;
}
@Override
public void setUniqueId(String uniqueId) {
- this.uniqueId = uniqueId;
+ // This is the world name - make it always lowercase
+ this.uniqueId = uniqueId.toLowerCase();
}
/**
diff --git a/src/main/java/world/bentobox/level/placeholders/LevelPlaceholder.java b/src/main/java/world/bentobox/level/placeholders/LevelPlaceholder.java
index da61bf0..4bf27ee 100644
--- a/src/main/java/world/bentobox/level/placeholders/LevelPlaceholder.java
+++ b/src/main/java/world/bentobox/level/placeholders/LevelPlaceholder.java
@@ -1,6 +1,3 @@
-/**
- *
- */
package world.bentobox.level.placeholders;
import world.bentobox.bentobox.api.addons.GameModeAddon;
@@ -32,7 +29,7 @@ public class LevelPlaceholder implements PlaceholderReplacer {
*/
@Override
public String onReplace(User user) {
- return String.valueOf(addon.getIslandLevel(gm.getOverWorld(), user.getUniqueId()));
+ return addon.getLevelPresenter().getLevelString(addon.getIslandLevel(gm.getOverWorld(), user.getUniqueId()));
}
}
diff --git a/src/main/java/world/bentobox/level/placeholders/TopTenNamePlaceholder.java b/src/main/java/world/bentobox/level/placeholders/TopTenNamePlaceholder.java
index 593b18d..b0e7c67 100644
--- a/src/main/java/world/bentobox/level/placeholders/TopTenNamePlaceholder.java
+++ b/src/main/java/world/bentobox/level/placeholders/TopTenNamePlaceholder.java
@@ -1,6 +1,3 @@
-/**
- *
- */
package world.bentobox.level.placeholders;
import java.util.Collection;
diff --git a/src/main/java/world/bentobox/level/placeholders/TopTenPlaceholder.java b/src/main/java/world/bentobox/level/placeholders/TopTenPlaceholder.java
index 27849e4..0da18d3 100644
--- a/src/main/java/world/bentobox/level/placeholders/TopTenPlaceholder.java
+++ b/src/main/java/world/bentobox/level/placeholders/TopTenPlaceholder.java
@@ -1,6 +1,3 @@
-/**
- *
- */
package world.bentobox.level.placeholders;
import java.util.Collection;
diff --git a/src/main/java/world/bentobox/level/requests/TopTenRequestHandler.java b/src/main/java/world/bentobox/level/requests/TopTenRequestHandler.java
index d947717..bc32b52 100644
--- a/src/main/java/world/bentobox/level/requests/TopTenRequestHandler.java
+++ b/src/main/java/world/bentobox/level/requests/TopTenRequestHandler.java
@@ -16,26 +16,26 @@ import world.bentobox.level.objects.TopTenData;
*/
public class TopTenRequestHandler extends AddonRequestHandler {
- /**
- * The level addon field.
- */
- private Level addon;
+ /**
+ * The level addon field.
+ */
+ private Level addon;
- /**
- * This constructor creates a new TopTenRequestHandler instance.
- *
- * @param addon of type Level
- */
- public TopTenRequestHandler(Level addon) {
- super("top-ten-level");
- this.addon = addon;
- }
+ /**
+ * This constructor creates a new TopTenRequestHandler instance.
+ *
+ * @param addon of type Level
+ */
+ public TopTenRequestHandler(Level addon) {
+ super("top-ten-level");
+ this.addon = addon;
+ }
- /**
- * @see AddonRequestHandler#handle(Map)
- */
- @Override
- public Object handle(Map map) {
+ /**
+ * @see {@link AddonRequestHandler#handle(Map)}
+ */
+ @Override
+ public Object handle(Map map) {
/*
What we need in the map:
@@ -47,14 +47,14 @@ public class TopTenRequestHandler extends AddonRequestHandler {
- the map of top ten player UUIDs and their island levels. Can be less then 10.
*/
- if (map == null || map.isEmpty()
- || map.get("world-name") == null || !(map.get("world-name") instanceof String)
- || Bukkit.getWorld((String) map.get("world-name")) == null) {
- return Collections.emptyMap();
- }
+ if (map == null || map.isEmpty()
+ || map.get("world-name") == null || !(map.get("world-name") instanceof String)
+ || Bukkit.getWorld((String) map.get("world-name")) == null) {
+ return Collections.emptyMap();
+ }
- // Null-point check.
- TopTenData data = addon.getTopTen().getTopTenList(Bukkit.getWorld((String) map.get("world-name")));
- return data != null ? data.getTopTen() : Collections.emptyMap();
- }
+ // Null-point check.
+ TopTenData data = addon.getTopTen().getTopTenList(Bukkit.getWorld((String) map.get("world-name")));
+ return data != null ? data.getTopTen() : Collections.emptyMap();
+ }
}
diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml
index be3b9a9..6035359 100755
--- a/src/main/resources/addon.yml
+++ b/src/main/resources/addon.yml
@@ -1,6 +1,6 @@
name: Level
main: world.bentobox.level.Level
-version: ${version}
+version: ${version}${build.number}
softdepend: AcidIsland, BSkyBlock
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 834ab05..0891dc9 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -14,6 +14,21 @@ game-modes:
# Players with the permission askyblock.island.multiplier.# will have their blocks
# multiplied in value by that amount.
+# Calculate island level on login
+# This silently calculates the player's island level when they login
+# This applies to all islands the player has on the server, e.g., BSkyBlock, AcidIsland
+login: false
+
+# Include nether island in level calculations.
+# Warning: Enabling this mid-game will give players with an island a jump in
+# island level. New islands will be correctly zeroed.
+nether: false
+
+# Include end island in level calculations
+# Warning: Enabling this mid-game will give players with an island a jump in
+# island level. New islands will be correctly zeroed.
+end: false
+
# Underwater block multiplier
# If blocks are below sea-level, they can have a higher value. e.g. 2x
# Promotes under-water development if there is a sea. Value can be fractional.
@@ -25,6 +40,14 @@ levelcost: 100
# Cooldown between level requests in seconds
levelwait: 60
+# Delay between each task that loads chunks for calculating island level.
+# Increasing this will increase time to calculate island level.
+updatetickdelay: 1
+
+# Number of chunks that will be processed at the same tick.
+# Decreasing this will increase time to calculate island level.
+chunkspertick: 200
+
# Death penalty
# How many block values a player will lose per death.
# Default value of 100 means that for every death, the player will lose 1 level (if levelcost is 100)
@@ -33,15 +56,11 @@ deathpenalty: 100
# Sum team deaths - if true, all the teams deaths are summed
# If false, only the leader's deaths counts
sumteamdeaths: false
-# Max deaths
-# If player dies more than this, it doesn't count anymore
-# Stops players from getting into an impossible situation
-maxdeaths: 10
-# Reset deaths on island reset
-islandresetdeathreset: true
-# Reset deaths on team join
-teamjoindeathreset: true
+# For other death related settings, see the GameModeAddon's config.yml settings.
+# Shorthand island level
+# Shows large level values rounded down, e.g., 10,345 -> 10k
+shorthand: false
# This section lists the limits for any particular block. Blocks over this amount
# are not counted.
@@ -651,7 +670,7 @@ blocks:
# If a block is not listed, the default value will be used
# Prefix with world name
worlds:
- AcidIsland_world:
+ acidisland_world:
SAND: 0
SANDSTONE: 0
ICE: 0
diff --git a/src/main/resources/locales/fr-FR.yml b/src/main/resources/locales/fr-FR.yml
new file mode 100644
index 0000000..740436c
--- /dev/null
+++ b/src/main/resources/locales/fr-FR.yml
@@ -0,0 +1,41 @@
+###########################################################################################
+# 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 #
+###########################################################################################
+
+meta:
+ authors:
+ - plagoutte
+
+admin:
+ level:
+ parameters: ""
+ description: "calcule le niveau d'île d'un joueur"
+ top:
+ description: "affiche le top 10 des îles"
+ unknown-world: "&cMonde inconnu."
+ display: "&f[rank]. &a[name] &7- &b[level]"
+
+island:
+ level:
+ parameters: "[joueur]"
+ description: "calcule le niveau de votre île ou affiche le niveau d'un [joueur]"
+ calculating: "&aCalcul du niveau en cours..."
+ island-level-is: "&aLe niveau d'île est &b[level]"
+ required-points-to-next-level: "&a[points] points avant le prochain niveau"
+ deaths: "&c([number] morts)"
+ cooldown: "&cVous devez attendre &b[time] &csecondes avant de pouvoir re-faire cette action"
+
+ top:
+ description: "affiche le top 10"
+ gui-title: "&aTop 10"
+ gui-heading: "&6[name]: &B[rank]"
+ island-level: "&BNiveau [level]"
+ warp-to: "&ATéléportation vers l'île de [name]"
+
+ value:
+ description: "affiche la valeur d'un bloc"
+ success: "§7Valeur de ce bloc : §e[value]"
+ success-underwater: "§7Valeur de ce bloc en dessous du niveau de la mer : §e[value]"
+ empty-hand: "§cIl n'y a aucun bloc dans votre main"
+ no-value: "§cCet objet n'a pas de valeur."
diff --git a/src/main/resources/locales/lv-LV.yml b/src/main/resources/locales/lv-LV.yml
new file mode 100644
index 0000000..08b3621
--- /dev/null
+++ b/src/main/resources/locales/lv-LV.yml
@@ -0,0 +1,37 @@
+###########################################################################################
+# 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 #
+###########################################################################################
+
+admin:
+ level:
+ parameters: ""
+ description: "aprēķina spēlētāja salas līmeni"
+ top:
+ description: "rādīt labākās 10 salas"
+ unknown-world: "&cNezināma pasaule!"
+ display: "&f[rank]. &a[name] &7- &b[level]"
+
+island:
+ level:
+ parameters: "[player]"
+ description: "aprēķina tavas salas līmeni, vai parāda spēlētāja [player] līmeni"
+ calculating: "&aAprēķina līmeni..."
+ island-level-is: "&aSalas līmenis ir &b[level]"
+ required-points-to-next-level: "&aNepieciešami [points] punkti, lai sasniegtu nākošo līmeni"
+ deaths: "&c([number] nāves)"
+ cooldown: "&cTev ir jāuzgaida &b[time]&c sekundes, lai vēlreiz aprēķinātu salas līmeni!"
+
+ top:
+ description: "rādīt labākos 10"
+ gui-title: "&aLabākie 10"
+ gui-heading: "&6[name]: &B[rank]"
+ island-level: "&BLīmenis [level]"
+ warp-to: "&APārvietoties uz [name] salu."
+
+ value:
+ description: "rādīt vērtību jebkuram blokam"
+ success: "&7Vērtība šim blokam ir: &e[value]"
+ success-underwater: "&7Vērtība šim blokam zem jūras līmeņa: &e[value]"
+ empty-hand: "&cTev nav bloks rokās."
+ no-value: "&cŠim blokam/priekšmetam nav vērtības."
diff --git a/src/main/resources/locales/tr-TR.yml b/src/main/resources/locales/tr-TR.yml
new file mode 100644
index 0000000..1089c4f
--- /dev/null
+++ b/src/main/resources/locales/tr-TR.yml
@@ -0,0 +1,37 @@
+###########################################################################################
+# 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 #
+###########################################################################################
+
+admin:
+ level:
+ parameters: ""
+ description: "Bir oyuncunun ada seviyesini hesapla"
+ top:
+ description: "Ilk 10 adayı sırala"
+ unknown-world: "&cBilinmeyen kelime"
+ display: "&f[rank]. &a[name] &7- &b[level]"
+
+island:
+ level:
+ parameters: "[player]"
+ description: "&7Kendi ada seviyeni hesapla veya başka oyuncunun ada seviyesini öğren"
+ calculating: "&aLevel hesaplanıyor..."
+ island-level-is: "&7Ada seviyesi &b[level]"
+ required-points-to-next-level: "&7Adayı yükseltmek için &a[points] &7Puan gerekiyor"
+ deaths: "&c(Ölümler: [number])"
+ cooldown: "&7Bunu tekrar yapmak için &b[time] &7beklemelisin"
+
+ top:
+ description: "Ilk 10 adayı sırala"
+ gui-title: "&aIlk 10 Ada"
+ gui-heading: "&6Sıralama: &3[rank]"
+ island-level: "&7Seviye: &a[level]"
+ warp-to: "&a[name] &7oyuncusunun adasına ışınlanıyor"
+
+ value:
+ description: "Herhangi bir bloğun değerini gösterir"
+ success: "&7Bu bloğun değeri: &e[value]"
+ success-underwater: "&7Deniz seviyesinin altındaki bu bloğun değeri: &e[value]"
+ empty-hand: "&cElinde hiç blok yok"
+ no-value: "&cBu eşyanın bir değeri yok."
diff --git a/src/test/java/world/bentobox/level/LevelPresenterTest.java b/src/test/java/world/bentobox/level/LevelPresenterTest.java
index 51293e5..01e33e6 100644
--- a/src/test/java/world/bentobox/level/LevelPresenterTest.java
+++ b/src/test/java/world/bentobox/level/LevelPresenterTest.java
@@ -1,5 +1,6 @@
package world.bentobox.level;
+import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -10,6 +11,7 @@ import org.bukkit.World;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
@@ -20,6 +22,7 @@ import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.managers.IslandWorldManager;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.level.calculators.PlayerLevel;
+import world.bentobox.level.config.Settings;
/**
* @author tastybento
@@ -29,14 +32,17 @@ import world.bentobox.level.calculators.PlayerLevel;
@PrepareForTest({Bukkit.class, LevelPresenter.class})
public class LevelPresenterTest {
+ @Mock
private BentoBox plugin;
+ @Mock
private Level addon;
+ @Mock
private PlayerLevel pl;
+ @Mock
+ private Settings settings;
@Before
public void setUp() throws Exception {
- plugin = mock(BentoBox.class);
- addon = mock(Level.class);
IslandWorldManager iwm = mock(IslandWorldManager.class);
when(plugin.getIWM()).thenReturn(iwm);
when(iwm.getPermissionPrefix(Mockito.any())).thenReturn("world");
@@ -48,10 +54,12 @@ public class LevelPresenterTest {
when(im.inTeam(Mockito.any(), Mockito.any())).thenReturn(true);
// team leader
when(im.getOwner(Mockito.any(), Mockito.any())).thenReturn(UUID.randomUUID());
-
- pl = mock(PlayerLevel.class);
+
+ // Player level
PowerMockito.whenNew(PlayerLevel.class).withAnyArguments().thenReturn(pl);
+ // Settings
+ when(addon.getSettings()).thenReturn(settings);
}
/**
@@ -72,10 +80,32 @@ public class LevelPresenterTest {
User sender = mock(User.class);
UUID targetPlayer = UUID.randomUUID();
lp.calculateIslandLevel(world, sender, targetPlayer);
-
+
Mockito.verify(sender).sendMessage("island.level.calculating");
- // Verify PlayerLevel was called
- Mockito.verify(pl);
}
+ /**
+ * Test method for {@link LevelPresenter#getLevelString(long)}.
+ */
+ @Test
+ public void testGetLevelStringLong() {
+ LevelPresenter lp = new LevelPresenter(addon, plugin);
+ assertEquals("123456789", lp.getLevelString(123456789L));
+
+ }
+
+ /**
+ * Test method for {@link LevelPresenter#getLevelString(long)}.
+ */
+ @Test
+ public void testGetLevelStringLongShorthand() {
+ when(settings.isShortHand()).thenReturn(true);
+ LevelPresenter lp = new LevelPresenter(addon, plugin);
+ assertEquals("123.5M", lp.getLevelString(123456789L));
+ assertEquals("1.2k", lp.getLevelString(1234L));
+ assertEquals("123.5G", lp.getLevelString(123456789352L));
+ assertEquals("1.2T", lp.getLevelString(1234567893524L));
+ assertEquals("12345.7T", lp.getLevelString(12345678345345349L));
+
+ }
}
diff --git a/src/test/java/world/bentobox/level/TopTenTest.java b/src/test/java/world/bentobox/level/TopTenTest.java
new file mode 100644
index 0000000..8dd3807
--- /dev/null
+++ b/src/test/java/world/bentobox/level/TopTenTest.java
@@ -0,0 +1,280 @@
+package world.bentobox.level;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Server;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemFactory;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import world.bentobox.bentobox.BentoBox;
+import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
+import world.bentobox.bentobox.api.user.User;
+import world.bentobox.bentobox.database.AbstractDatabaseHandler;
+import world.bentobox.bentobox.database.DatabaseSetup;
+import world.bentobox.bentobox.managers.IslandWorldManager;
+import world.bentobox.bentobox.managers.IslandsManager;
+import world.bentobox.bentobox.managers.PlayersManager;
+import world.bentobox.level.config.Settings;
+import world.bentobox.level.objects.TopTenData;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({Bukkit.class, BentoBox.class, DatabaseSetup.class, PanelBuilder.class})
+public class TopTenTest {
+
+ @Mock
+ private Level addon;
+ @Mock
+ private World world;
+ @Mock
+ private BentoBox plugin;
+ @Mock
+ private static AbstractDatabaseHandler