Changed top ten internally to use islands instead of players as keys (#295)

Added %[gamemode]_top_weighted_value_x% placeholder
https://github.com/BentoBoxWorld/Level/issues/294
This commit is contained in:
tastybento 2023-11-19 18:08:47 -08:00 committed by GitHub
parent 26d4839f6a
commit 9d1a5c7476
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1611 additions and 1674 deletions

View File

@ -32,452 +32,429 @@ import world.bentobox.level.objects.LevelsData;
import world.bentobox.level.objects.TopTenData; import world.bentobox.level.objects.TopTenData;
public class LevelsManager { public class LevelsManager {
private static final String INTOPTEN = "intopten"; private static final String INTOPTEN = "intopten";
private static final TreeMap<BigInteger, String> LEVELS; private static final TreeMap<BigInteger, String> LEVELS;
private static final BigInteger THOUSAND = BigInteger.valueOf(1000); private static final BigInteger THOUSAND = BigInteger.valueOf(1000);
static { static {
LEVELS = new TreeMap<>(); LEVELS = new TreeMap<>();
LEVELS.put(THOUSAND, "k"); LEVELS.put(THOUSAND, "k");
LEVELS.put(THOUSAND.pow(2), "M"); LEVELS.put(THOUSAND.pow(2), "M");
LEVELS.put(THOUSAND.pow(3), "G"); LEVELS.put(THOUSAND.pow(3), "G");
LEVELS.put(THOUSAND.pow(4), "T"); LEVELS.put(THOUSAND.pow(4), "T");
} }
private final Level addon; private final Level addon;
// Database handler for level data // Database handler for level data
private final Database<IslandLevels> handler; private final Database<IslandLevels> handler;
// A cache of island levels. // A cache of island levels.
private final Map<String, IslandLevels> levelsCache; private final Map<String, IslandLevels> levelsCache;
// Top ten lists // Top ten lists
private final Map<World, TopTenData> topTenLists; private final Map<World, TopTenData> topTenLists;
public LevelsManager(Level addon) { public LevelsManager(Level addon) {
this.addon = addon; this.addon = addon;
// Get the BentoBox database // Get the BentoBox database
// Set up the database handler to store and retrieve data // Set up the database handler to store and retrieve data
// Note that these are saved by the BentoBox database // Note that these are saved by the BentoBox database
handler = new Database<>(addon, IslandLevels.class); handler = new Database<>(addon, IslandLevels.class);
// Initialize the cache // Initialize the cache
levelsCache = new HashMap<>(); levelsCache = new HashMap<>();
// Initialize top ten lists // Initialize top ten lists
topTenLists = new ConcurrentHashMap<>(); topTenLists = new ConcurrentHashMap<>();
} }
public void migrate() { public void migrate() {
Database<LevelsData> oldDb = new Database<>(addon, LevelsData.class); Database<LevelsData> oldDb = new Database<>(addon, LevelsData.class);
oldDb.loadObjects().forEach(ld -> { oldDb.loadObjects().forEach(ld -> {
try { try {
UUID owner = UUID.fromString(ld.getUniqueId()); UUID owner = UUID.fromString(ld.getUniqueId());
// Step through each world // Step through each world
ld.getLevels().keySet().stream() ld.getLevels().keySet().stream()
// World // World
.map(Bukkit::getWorld).filter(Objects::nonNull) .map(Bukkit::getWorld).filter(Objects::nonNull)
// Island // Island
.map(w -> addon.getIslands().getIsland(w, owner)).filter(Objects::nonNull).forEach(i -> { .map(w -> addon.getIslands().getIsland(w, owner)).filter(Objects::nonNull).forEach(i -> {
// Make new database entry // Make new database entry
World w = i.getWorld(); World w = i.getWorld();
IslandLevels il = new IslandLevels(i.getUniqueId()); IslandLevels il = new IslandLevels(i.getUniqueId());
il.setInitialLevel(ld.getInitialLevel(w)); il.setInitialLevel(ld.getInitialLevel(w));
il.setLevel(ld.getLevel(w)); il.setLevel(ld.getLevel(w));
il.setMdCount(ld.getMdCount(w)); il.setMdCount(ld.getMdCount(w));
il.setPointsToNextLevel(ld.getPointsToNextLevel(w)); il.setPointsToNextLevel(ld.getPointsToNextLevel(w));
il.setUwCount(ld.getUwCount(w)); il.setUwCount(ld.getUwCount(w));
// Save it // Save it
handler.saveObjectAsync(il); handler.saveObjectAsync(il);
});
// Now delete the old database entry
oldDb.deleteID(ld.getUniqueId());
} catch (Exception e) {
addon.logError("Could not migrate level data database! " + e.getMessage());
e.printStackTrace();
return;
}
});
}
/**
* Add a score to the top players list
*
* @param world - world
* @param targetPlayer - target player
* @param lv - island level
*/
private void addToTopTen(@NonNull World world, @NonNull UUID targetPlayer, long lv) {
// Get top ten
Map<UUID, Long> topTen = topTenLists.computeIfAbsent(world, k -> new TopTenData(world)).getTopTen();
// Remove this player from the top list no matter what (we'll put them back
// later if required)
topTen.remove(targetPlayer);
// Get the island
Island island = addon.getIslands().getIsland(world, targetPlayer);
if (island != null && island.getOwner() != null && hasTopTenPerm(world, island.getOwner())) {
// Insert the owner into the top ten
topTen.put(island.getOwner(), lv);
}
}
/**
* Add an island to a top ten
*
* @param island - island to add
* @param lv - level
* @return true if successful, false if not added
*/
private boolean addToTopTen(Island island, long lv) {
if (island != null && island.getOwner() != null && hasTopTenPerm(island.getWorld(), island.getOwner())) {
topTenLists.computeIfAbsent(island.getWorld(), k -> new TopTenData(island.getWorld())).getTopTen()
.put(island.getOwner(), lv);
return true;
}
return false;
}
/**
* Calculate the island level, set all island member's levels to the result and
* try to add the owner to the top ten
*
* @param targetPlayer - uuid of targeted player - owner or team member
* @param island - island to calculate
* @return completable future with the results of the calculation
*/
public CompletableFuture<Results> calculateLevel(UUID targetPlayer, Island island) {
CompletableFuture<Results> result = new CompletableFuture<>();
// Fire pre-level calc event
IslandPreLevelEvent e = new IslandPreLevelEvent(targetPlayer, island);
Bukkit.getPluginManager().callEvent(e);
if (e.isCancelled()) {
return CompletableFuture.completedFuture(null);
}
// Add island to the pipeline
addon.getPipeliner().addIsland(island).thenAccept(r -> {
// Results are irrelevant because the island is unowned or deleted, or
// IslandLevelCalcEvent is cancelled
if (r == null || fireIslandLevelCalcEvent(targetPlayer, island, r)) {
result.complete(null);
}
// Save result
setIslandResults(island.getWorld(), island.getOwner(), r);
// Save the island scan details
result.complete(r);
});
return result;
}
/**
* Fires the IslandLevelCalculatedEvent and returns true if it is canceled
*
* @param targetPlayer - target player
* @param island - island
* @param results - results set
* @return true if canceled
*/
private boolean fireIslandLevelCalcEvent(UUID targetPlayer, Island island, Results results) {
// Fire post calculation event
IslandLevelCalculatedEvent ilce = new IslandLevelCalculatedEvent(targetPlayer, island, results);
Bukkit.getPluginManager().callEvent(ilce);
if (ilce.isCancelled())
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.setDeathHandicap((int) ilce.getKeyValues().getOrDefault("deathHandicap", results.getDeathHandicap()));
results.setPointsToNextLevel(
(Long) ilce.getKeyValues().getOrDefault("pointsToNextLevel", results.getPointsToNextLevel()));
results.setTotalPoints((Long) ilce.getKeyValues().getOrDefault("totalPoints", results.getTotalPoints()));
return ((Boolean) ilce.getKeyValues().getOrDefault("isCancelled", false));
}
/**
* 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 formatLevel(@Nullable Long lvl) {
if (lvl == null)
return "";
String level = String.valueOf(lvl);
// Asking for the level of another player
if (addon.getSettings().isShorthand()) {
BigInteger levelValue = BigInteger.valueOf(lvl);
Map.Entry<BigInteger, String> 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;
}
/**
* Get the initial level of the island. Used to zero island levels
*
* @param island - island
* @return initial level of island
*/
public long getInitialLevel(Island island) {
return getLevelsData(island).getInitialLevel();
}
/**
* Get level of island from cache for a player.
*
* @param world - world where the island is
* @param targetPlayer - target player UUID
* @return Level of the player's island or zero if player is unknown or UUID is
* null
*/
public long getIslandLevel(@NonNull World world, @Nullable UUID targetPlayer) {
if (targetPlayer == null)
return 0L;
// Get the island
Island island = addon.getIslands().getIsland(world, targetPlayer);
return island == null ? 0L : getLevelsData(island).getLevel();
}
/**
* Get the maximum level ever given to this island
*
* @param world - world where the island is
* @param targetPlayer - target player UUID
* @return Max level of the player's island or zero if player is unknown or UUID
* is null
*/
public long getIslandMaxLevel(@NonNull World world, @Nullable UUID targetPlayer) {
if (targetPlayer == null)
return 0L;
// Get the island
Island island = addon.getIslands().getIsland(world, targetPlayer);
return island == null ? 0L : getLevelsData(island).getMaxLevel();
}
/**
* Returns a formatted string of the target player's island level
*
* @param world - world where the island is
* @param targetPlayer - target player's UUID
* @return Formatted level of player or zero if player is unknown or UUID is
* null
*/
public String getIslandLevelString(@NonNull World world, @Nullable UUID targetPlayer) {
return formatLevel(getIslandLevel(world, targetPlayer));
}
/**
* Load a level data for the island from the cache or database.
*
* @param island - UUID of island
* @return IslandLevels object
*/
@NonNull
public IslandLevels getLevelsData(@NonNull Island island) {
String id = island.getUniqueId();
if (levelsCache.containsKey(id)) {
return levelsCache.get(id);
}
// Get from database if not in cache
if (handler.objectExists(id)) {
IslandLevels ld = handler.loadObject(id);
if (ld != null) {
levelsCache.put(id, ld);
} else {
handler.deleteID(id);
levelsCache.put(id, new IslandLevels(id));
}
} else {
levelsCache.put(id, new IslandLevels(id));
}
// Return cached value
return levelsCache.get(id);
}
/**
* Get the number of points required until the next level since the last level
* calc
*
* @param world - world where the island is
* @param targetPlayer - target player UUID
* @return string with the number required or blank if the player is unknown
*/
public String getPointsToNextString(@NonNull World world, @Nullable UUID targetPlayer) {
if (targetPlayer == null)
return "";
Island island = addon.getIslands().getIsland(world, targetPlayer);
return island == null ? "" : String.valueOf(getLevelsData(island).getPointsToNextLevel());
}
/**
* Get the top ten for this world. Returns offline players or players with the
* intopten permission.
*
* @param world - world requested
* @param size - size of the top ten
* @return sorted top ten map
*/
@NonNull
public Map<UUID, Long> getTopTen(@NonNull World world, int size) {
createAndCleanRankings(world);
// Return the sorted map
return Collections.unmodifiableMap(topTenLists.get(world).getTopTen().entrySet().stream()
.filter(e -> addon.getIslands().hasIsland(world, e.getKey())).filter(l -> l.getValue() > 0)
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).limit(size)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)));
}
void createAndCleanRankings(@NonNull World world) {
topTenLists.computeIfAbsent(world, TopTenData::new);
// Remove player from top ten if they are online and do not have the perm
topTenLists.get(world).getTopTen().keySet().removeIf(u -> !hasTopTenPerm(world, u));
}
/**
* @return the topTenLists
*/
public Map<World, TopTenData> getTopTenLists() {
return topTenLists;
}
/**
* Get the rank of the player in the rankings
*
* @param world - world
* @param uuid - player UUID
* @return rank placing - note - placing of 1 means top ranked
*/
public int getRank(@NonNull World world, UUID uuid) {
createAndCleanRankings(world);
Stream<Entry<UUID, Long>> stream = topTenLists.get(world).getTopTen().entrySet().stream()
.filter(e -> addon.getIslands().hasIsland(world, e.getKey())).filter(l -> l.getValue() > 0)
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
return (int) (stream.takeWhile(x -> !x.getKey().equals(uuid)).map(Map.Entry::getKey).count() + 1);
}
/**
* Checks if player has the correct top ten perm to have their level saved
*
* @param world
* @param targetPlayer
* @return true if player has the perm or the player is offline
*/
boolean hasTopTenPerm(@NonNull World world, @NonNull UUID targetPlayer) {
String permPrefix = addon.getPlugin().getIWM().getPermissionPrefix(world);
return Bukkit.getPlayer(targetPlayer) == null
|| Bukkit.getPlayer(targetPlayer).hasPermission(permPrefix + INTOPTEN);
}
/**
* Loads all the top tens from the database
*/
public void loadTopTens() {
topTenLists.clear();
Bukkit.getScheduler().runTaskAsynchronously(addon.getPlugin(), () -> {
addon.log("Generating rankings");
handler.loadObjects().forEach(il -> {
if (il.getLevel() > 0) {
addon.getIslands().getIslandById(il.getUniqueId())
.ifPresent(i -> this.addToTopTen(i, il.getLevel()));
}
}); });
topTenLists.keySet().forEach(w -> addon.log("Generated rankings for " + w.getName())); // Now delete the old database entry
}); oldDb.deleteID(ld.getUniqueId());
} } catch (Exception e) {
addon.logError("Could not migrate level data database! " + e.getMessage());
e.printStackTrace();
return;
}
});
}
/** /**
* Removes a player from a world's top ten and removes world from player's level * Add an island to a top ten
* data *
* * @param island - island to add
* @param world - world * @param lv - level
* @param uuid - the player's uuid * @return true if successful, false if not added
*/ */
public void removeEntry(World world, UUID uuid) { private boolean addToTopTen(Island island, long lv) {
if (topTenLists.containsKey(world)) { if (island != null && island.getOwner() != null && hasTopTenPerm(island.getWorld(), island.getOwner())) {
topTenLists.get(world).getTopTen().remove(uuid); topTenLists.computeIfAbsent(island.getWorld(), k -> new TopTenData(island.getWorld())).getTopTen()
.put(island.getUniqueId(), lv);
return true;
}
return false;
}
/**
* Calculate the island level, set all island member's levels to the result and
* try to add the owner to the top ten
*
* @param targetPlayer - uuid of targeted player - owner or team member
* @param island - island to calculate
* @return completable future with the results of the calculation
*/
public CompletableFuture<Results> calculateLevel(UUID targetPlayer, Island island) {
CompletableFuture<Results> result = new CompletableFuture<>();
// Fire pre-level calc event
IslandPreLevelEvent e = new IslandPreLevelEvent(targetPlayer, island);
Bukkit.getPluginManager().callEvent(e);
if (e.isCancelled()) {
return CompletableFuture.completedFuture(null);
}
// Add island to the pipeline
addon.getPipeliner().addIsland(island).thenAccept(r -> {
// Results are irrelevant because the island is unowned or deleted, or
// IslandLevelCalcEvent is cancelled
if (r == null || fireIslandLevelCalcEvent(targetPlayer, island, r)) {
result.complete(null);
}
// Save result
setIslandResults(island, r);
// Save the island scan details
result.complete(r);
});
return result;
}
/**
* Fires the IslandLevelCalculatedEvent and returns true if it is canceled
*
* @param targetPlayer - target player
* @param island - island
* @param results - results set
* @return true if canceled
*/
private boolean fireIslandLevelCalcEvent(UUID targetPlayer, Island island, Results results) {
// Fire post calculation event
IslandLevelCalculatedEvent ilce = new IslandLevelCalculatedEvent(targetPlayer, island, results);
Bukkit.getPluginManager().callEvent(ilce);
if (ilce.isCancelled())
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.setDeathHandicap((int) ilce.getKeyValues().getOrDefault("deathHandicap", results.getDeathHandicap()));
results.setPointsToNextLevel(
(Long) ilce.getKeyValues().getOrDefault("pointsToNextLevel", results.getPointsToNextLevel()));
results.setTotalPoints((Long) ilce.getKeyValues().getOrDefault("totalPoints", results.getTotalPoints()));
return ((Boolean) ilce.getKeyValues().getOrDefault("isCancelled", false));
}
/**
* 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 formatLevel(@Nullable Long lvl) {
if (lvl == null)
return "";
String level = String.valueOf(lvl);
// Asking for the level of another player
if (addon.getSettings().isShorthand()) {
BigInteger levelValue = BigInteger.valueOf(lvl);
Map.Entry<BigInteger, String> 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;
}
/**
* Get the initial level of the island. Used to zero island levels
*
* @param island - island
* @return initial level of island
*/
public long getInitialLevel(Island island) {
return getLevelsData(island).getInitialLevel();
}
/**
* Get level of island from cache for a player.
*
* @param world - world where the island is
* @param targetPlayer - target player UUID
* @return Level of the player's island or zero if player is unknown or UUID is
* null
*/
public long getIslandLevel(@NonNull World world, @Nullable UUID targetPlayer) {
if (targetPlayer == null)
return 0L;
// Get the island
Island island = addon.getIslands().getIsland(world, targetPlayer);
return island == null ? 0L : getLevelsData(island).getLevel();
}
/**
* Get the maximum level ever given to this island
*
* @param world - world where the island is
* @param targetPlayer - target player UUID
* @return Max level of the player's island or zero if player is unknown or UUID
* is null
*/
public long getIslandMaxLevel(@NonNull World world, @Nullable UUID targetPlayer) {
if (targetPlayer == null)
return 0L;
// Get the island
Island island = addon.getIslands().getIsland(world, targetPlayer);
return island == null ? 0L : getLevelsData(island).getMaxLevel();
}
/**
* Returns a formatted string of the target player's island level
*
* @param world - world where the island is
* @param targetPlayer - target player's UUID
* @return Formatted level of player or zero if player is unknown or UUID is
* null
*/
public String getIslandLevelString(@NonNull World world, @Nullable UUID targetPlayer) {
return formatLevel(getIslandLevel(world, targetPlayer));
}
/**
* Load a level data for the island from the cache or database.
*
* @param island - UUID of island
* @return IslandLevels object
*/
@NonNull
public IslandLevels getLevelsData(@NonNull Island island) {
String id = island.getUniqueId();
if (levelsCache.containsKey(id)) {
return levelsCache.get(id);
}
// Get from database if not in cache
if (handler.objectExists(id)) {
IslandLevels ld = handler.loadObject(id);
if (ld != null) {
levelsCache.put(id, ld);
} else {
handler.deleteID(id);
levelsCache.put(id, new IslandLevels(id));
}
} else {
levelsCache.put(id, new IslandLevels(id));
}
// Return cached value
return levelsCache.get(id);
}
/**
* Get the number of points required until the next level since the last level
* calc
*
* @param world - world where the island is
* @param targetPlayer - target player UUID
* @return string with the number required or blank if the player is unknown
*/
public String getPointsToNextString(@NonNull World world, @Nullable UUID targetPlayer) {
if (targetPlayer == null)
return "";
Island island = addon.getIslands().getIsland(world, targetPlayer);
return island == null ? "" : String.valueOf(getLevelsData(island).getPointsToNextLevel());
}
/**
* Get the top ten for this world. Returns offline players or players with the
* intopten permission.
*
* @param world - world requested
* @param size - size of the top ten
* @return sorted top ten map. The key is the island unique ID
*/
@NonNull
public Map<String, Long> getTopTen(@NonNull World world, int size) {
createAndCleanRankings(world);
// Return the sorted map
return Collections.unmodifiableMap(topTenLists.get(world).getTopTen().entrySet().stream()
.filter(l -> l.getValue() > 0).sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.limit(size)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)));
}
void createAndCleanRankings(@NonNull World world) {
topTenLists.computeIfAbsent(world, TopTenData::new);
// Remove player from top ten if they are online and do not have the perm
topTenLists.get(world).getTopTen().keySet().removeIf(u -> addon.getIslands().getIslandById(u)
.filter(i -> i.getOwner() == null || !hasTopTenPerm(world, i.getOwner())).isPresent());
}
/**
* @return the topTenLists
*/
public Map<World, TopTenData> getTopTenLists() {
return topTenLists;
}
/**
* Get the rank of the player in the rankings
*
* @param world - world
* @param uuid - player UUID
* @return rank placing - note - placing of 1 means top ranked
*/
public int getRank(@NonNull World world, UUID uuid) {
createAndCleanRankings(world);
Stream<Entry<String, Long>> stream = topTenLists.get(world).getTopTen().entrySet().stream()
.filter(l -> l.getValue() > 0).sorted(Collections.reverseOrder(Map.Entry.comparingByValue()));
// Get player's current island
Island island = addon.getIslands().getIsland(world, uuid);
String id = island == null ? null : island.getUniqueId();
return (int) (stream.takeWhile(x -> !x.getKey().equals(id)).map(Map.Entry::getKey).count() + 1);
}
/**
* Checks if player has the correct top ten perm to have their level saved
*
* @param world
* @param targetPlayer
* @return true if player has the perm or the player is offline
*/
boolean hasTopTenPerm(@NonNull World world, @NonNull UUID targetPlayer) {
String permPrefix = addon.getPlugin().getIWM().getPermissionPrefix(world);
return Bukkit.getPlayer(targetPlayer) == null
|| Bukkit.getPlayer(targetPlayer).hasPermission(permPrefix + INTOPTEN);
}
/**
* Loads all the top tens from the database
*/
public void loadTopTens() {
topTenLists.clear();
Bukkit.getScheduler().runTaskAsynchronously(addon.getPlugin(), () -> {
addon.log("Generating rankings");
handler.loadObjects().forEach(il -> {
if (il.getLevel() > 0) {
addon.getIslands().getIslandById(il.getUniqueId())
.ifPresent(i -> this.addToTopTen(i, il.getLevel()));
} }
});
topTenLists.keySet().forEach(w -> addon.log("Generated rankings for " + w.getName()));
});
}
/**
* Removes an island from a world's top ten
*
* @param world - world
* @param uuid - the island's uuid
*/
public void removeEntry(World world, String uuid) {
if (topTenLists.containsKey(world)) {
topTenLists.get(world).getTopTen().remove(uuid);
} }
/** }
* Set an initial island level
*
* @param island - the island to set. Must have a non-null world
* @param lv - initial island level
*/
public void setInitialIslandLevel(@NonNull Island island, long lv) {
if (island.getWorld() == null)
return;
levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new).setInitialLevel(lv);
handler.saveObjectAsync(levelsCache.get(island.getUniqueId()));
}
/** /**
* Set the island level for the owner of the island that targetPlayer is a * Set an initial island level
* member *
* * @param island - the island to set. Must have a non-null world
* @param world - world * @param lv - initial island level
* @param targetPlayer - player, may be a team member */
* @param lv - level public void setInitialIslandLevel(@NonNull Island island, long lv) {
*/ if (island.getWorld() == null)
public void setIslandLevel(@NonNull World world, @NonNull UUID targetPlayer, long lv) { return;
// Get the island levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new).setInitialLevel(lv);
Island island = addon.getIslands().getIsland(world, targetPlayer); handler.saveObjectAsync(levelsCache.get(island.getUniqueId()));
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);
}
handler.saveObjectAsync(levelsCache.get(id));
// Update TopTen
addToTopTen(world, targetPlayer, levelsCache.get(id).getLevel());
}
/**
* Set the island level for the owner of the island that targetPlayer is a
* member
*
* @param world - world
* @param island - island
* @param lv - level
*/
public void setIslandLevel(@NonNull World world, @NonNull UUID targetPlayer, long lv) {
// Get the island
Island island = addon.getIslands().getIsland(world, targetPlayer);
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);
}
handler.saveObjectAsync(levelsCache.get(id));
// Update TopTen
addToTopTen(island, levelsCache.get(id).getLevel());
} }
}
/** /**
* Set the island level for the owner of the island that targetPlayer is a * Set the island level for the owner of the island that targetPlayer is a
* member * member
* *
* @param world - world * @param world - world
* @param owner - owner of the island * @param owner - owner of the island
* @param r - results of the calculation * @param r - results of the calculation
*/ */
private void setIslandResults(World world, @NonNull UUID owner, Results r) { private void setIslandResults(Island island, Results r) {
// Get the island if (island == null)
Island island = addon.getIslands().getIsland(world, owner); return;
if (island == null) IslandLevels ld = levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new);
return; ld.setLevel(r.getLevel());
IslandLevels ld = levelsCache.computeIfAbsent(island.getUniqueId(), IslandLevels::new); ld.setUwCount(Maps.asMap(r.getUwCount().elementSet(), elem -> r.getUwCount().count(elem)));
ld.setLevel(r.getLevel()); ld.setMdCount(Maps.asMap(r.getMdCount().elementSet(), elem -> r.getMdCount().count(elem)));
ld.setUwCount(Maps.asMap(r.getUwCount().elementSet(), elem -> r.getUwCount().count(elem))); ld.setPointsToNextLevel(r.getPointsToNextLevel());
ld.setMdCount(Maps.asMap(r.getMdCount().elementSet(), elem -> r.getMdCount().count(elem))); ld.setTotalPoints(r.getTotalPoints());
ld.setPointsToNextLevel(r.getPointsToNextLevel()); levelsCache.put(island.getUniqueId(), ld);
ld.setTotalPoints(r.getTotalPoints()); handler.saveObjectAsync(ld);
levelsCache.put(island.getUniqueId(), ld); // Update TopTen
handler.saveObjectAsync(ld); addToTopTen(island, ld.getLevel());
// Update TopTen }
addToTopTen(world, owner, ld.getLevel());
}
/** /**
* Removes island from cache when it is deleted * Removes island from cache when it is deleted
* *
* @param uniqueId - id of island * @param uniqueId - id of island
*/ */
public void deleteIsland(String uniqueId) { public void deleteIsland(String uniqueId) {
levelsCache.remove(uniqueId); levelsCache.remove(uniqueId);
handler.deleteID(uniqueId); handler.deleteID(uniqueId);
} }
} }

View File

@ -2,10 +2,13 @@ package world.bentobox.level;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.bukkit.World; import org.bukkit.World;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.GameModeAddon; import world.bentobox.bentobox.api.addons.GameModeAddon;
@ -18,6 +21,7 @@ import world.bentobox.level.objects.TopTenData;
/** /**
* Handles Level placeholders * Handles Level placeholders
*
* @author tastybento * @author tastybento
* *
*/ */
@ -27,150 +31,180 @@ public class PlaceholderManager {
private final BentoBox plugin; private final BentoBox plugin;
public PlaceholderManager(Level addon) { public PlaceholderManager(Level addon) {
this.addon = addon; this.addon = addon;
this.plugin = addon.getPlugin(); this.plugin = addon.getPlugin();
} }
protected void registerPlaceholders(GameModeAddon gm) { protected void registerPlaceholders(GameModeAddon gm) {
if (plugin.getPlaceholdersManager() == null) return; if (plugin.getPlaceholdersManager() == null)
PlaceholdersManager bpm = plugin.getPlaceholdersManager(); return;
// Island Level PlaceholdersManager bpm = plugin.getPlaceholdersManager();
bpm.registerPlaceholder(addon, // Island Level
gm.getDescription().getName().toLowerCase() + "_island_level", bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_island_level",
user -> addon.getManager().getIslandLevelString(gm.getOverWorld(), user.getUniqueId())); user -> addon.getManager().getIslandLevelString(gm.getOverWorld(), user.getUniqueId()));
bpm.registerPlaceholder(addon, // Unformatted island level
gm.getDescription().getName().toLowerCase() + "_island_level_raw", bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_island_level_raw",
user -> String.valueOf(addon.getManager().getIslandLevel(gm.getOverWorld(), user.getUniqueId()))); user -> String.valueOf(addon.getManager().getIslandLevel(gm.getOverWorld(), user.getUniqueId())));
bpm.registerPlaceholder(addon, // Total number of points counted before applying level formula
gm.getDescription().getName().toLowerCase() + "_island_total_points", bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_island_total_points", user -> {
user -> { IslandLevels data = addon.getManager().getLevelsData(addon.getIslands().getIsland(gm.getOverWorld(), user));
IslandLevels data = addon.getManager().getLevelsData(addon.getIslands().getIsland(gm.getOverWorld(), user)); return data.getTotalPoints() + "";
return data.getTotalPoints()+""; });
}); // Points to the next level for player
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_points_to_next_level",
user -> addon.getManager().getPointsToNextString(gm.getOverWorld(), user.getUniqueId()));
// Maximum level this island has ever been. Current level maybe lower.
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_island_level_max",
user -> String.valueOf(addon.getManager().getIslandMaxLevel(gm.getOverWorld(), user.getUniqueId())));
bpm.registerPlaceholder(addon, // Visited Island Level
gm.getDescription().getName().toLowerCase() + "_points_to_next_level", bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_visited_island_level",
user -> addon.getManager().getPointsToNextString(gm.getOverWorld(), user.getUniqueId())); user -> getVisitedIslandLevel(gm, user));
bpm.registerPlaceholder(addon,
gm.getDescription().getName().toLowerCase() + "_island_level_max",
user -> String.valueOf(addon.getManager().getIslandMaxLevel(gm.getOverWorld(), user.getUniqueId())));
// Visited Island Level // Register Top Ten Placeholders
bpm.registerPlaceholder(addon, for (int i = 1; i < 11; i++) {
gm.getDescription().getName().toLowerCase() + "_visited_island_level", user -> getVisitedIslandLevel(gm, user)); final int rank = i;
// Name
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_name_" + i,
u -> getRankName(gm.getOverWorld(), rank));
// Island Name
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_island_name_" + i,
u -> getRankIslandName(gm.getOverWorld(), rank));
// Members
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_members_" + i,
u -> getRankMembers(gm.getOverWorld(), rank));
// Level
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_value_" + i,
u -> getRankLevel(gm.getOverWorld(), rank));
// Weighted Level (Level / number of members)
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_weighted_value_" + i,
u -> getWeightedRankLevel(gm.getOverWorld(), rank));
}
// Register Top Ten Placeholders // Personal rank
for (int i = 1; i < 11; i++) { bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_rank_value",
final int rank = i; u -> getRankValue(gm.getOverWorld(), u));
// Name
bpm.registerPlaceholder(addon,
gm.getDescription().getName().toLowerCase() + "_top_name_" + i, u -> getRankName(gm.getOverWorld(), rank));
// Island Name
bpm.registerPlaceholder(addon,
gm.getDescription().getName().toLowerCase() + "_top_island_name_" + i, u -> getRankIslandName(gm.getOverWorld(), rank));
// Members
bpm.registerPlaceholder(addon,
gm.getDescription().getName().toLowerCase() + "_top_members_" + i, u -> getRankMembers(gm.getOverWorld(), rank));
// Level
bpm.registerPlaceholder(addon,
gm.getDescription().getName().toLowerCase() + "_top_value_" + i, u -> getRankLevel(gm.getOverWorld(), rank));
}
// Personal rank
bpm.registerPlaceholder(addon,
gm.getDescription().getName().toLowerCase() + "_rank_value", u -> getRankValue(gm.getOverWorld(), u));
} }
/** /**
* Get the name of the player who holds the rank in this world * Get the name of the owner of the island who holds the rank in this world.
*
* @param world world * @param world world
* @param rank rank 1 to 10 * @param rank rank 1 to 10
* @return rank name * @return rank name
*/ */
String getRankName(World world, int rank) { String getRankName(World world, int rank) {
if (rank < 1) rank = 1; // Ensure rank is within bounds
if (rank > Level.TEN) rank = Level.TEN; rank = Math.max(1, Math.min(rank, Level.TEN));
return addon.getPlayers().getName(addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L).findFirst().orElse(null)); @Nullable
UUID owner = addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L)
.findFirst().flatMap(addon.getIslands()::getIslandById).map(Island::getOwner).orElse(null);
return addon.getPlayers().getName(owner);
} }
/** /**
* Get the island name for this rank * Get the island name for this rank
*
* @param world world * @param world world
* @param rank rank 1 to 10 * @param rank rank 1 to 10
* @return name of island or nothing if there isn't one * @return name of island or nothing if there isn't one
*/ */
String getRankIslandName(World world, int rank) { String getRankIslandName(World world, int rank) {
if (rank < 1) rank = 1; // Ensure rank is within bounds
if (rank > Level.TEN) rank = Level.TEN; rank = Math.max(1, Math.min(rank, Level.TEN));
UUID owner = addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L).findFirst().orElse(null); return addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L).findFirst()
if (owner != null) { .flatMap(addon.getIslands()::getIslandById).map(Island::getName).orElse("");
Island island = addon.getIslands().getIsland(world, owner);
if (island != null) {
return island.getName() == null ? "" : island.getName();
}
}
return "";
} }
/** /**
* Gets a comma separated string of island member names * Gets a comma separated string of island member names
*
* @param world world * @param world world
* @param rank rank to request * @param rank rank to request
* @return comma separated string of island member names * @return comma separated string of island member names
*/ */
String getRankMembers(World world, int rank) { String getRankMembers(World world, int rank) {
if (rank < 1) rank = 1; // Ensure rank is within bounds
if (rank > Level.TEN) rank = Level.TEN; rank = Math.max(1, Math.min(rank, Level.TEN));
UUID owner = addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L).findFirst().orElse(null); Optional<Island> island = addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L)
if (owner != null) { .limit(1L).findFirst().flatMap(addon.getIslands()::getIslandById);
Island island = addon.getIslands().getIsland(world, owner);
if (island != null) { if (island.isPresent()) {
// Sort members by rank // Sort members by rank
return island.getMembers().entrySet().stream() return island.get().getMembers().entrySet().stream().filter(e -> e.getValue() >= RanksManager.MEMBER_RANK)
.filter(e -> e.getValue() >= RanksManager.MEMBER_RANK) .sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).map(Map.Entry::getKey)
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) .map(addon.getPlayers()::getName).collect(Collectors.joining(","));
.map(Map.Entry::getKey) }
.map(addon.getPlayers()::getName) return "";
.collect(Collectors.joining(",")); }
}
} /**
return ""; * Gets the weighted level, which is the level / number of players
*
* @param world world
* @param rank level
* @return weighted level
*/
String getWeightedRankLevel(World world, int rank) {
// Ensure rank is within bounds
rank = Math.max(1, Math.min(rank, Level.TEN));
// Retrieve the top ten entries
Map<String, Long> topTen = addon.getManager().getTopTen(world, Level.TEN);
if (topTen.isEmpty()) {
return "";
}
// Find the entry corresponding to the rank
Entry<String, Long> entry = topTen.entrySet().stream().skip(rank - 1).findFirst().orElse(null);
if (entry == null) {
return "";
}
// Calculate the score
Island island = addon.getIslands().getIslandById(entry.getKey()).orElse(null);
if (island == null || island.getMemberSet().isEmpty()) {
return "";
}
double score = (double) entry.getValue() / island.getMemberSet().size();
// Format and return the level
return addon.getManager().formatLevel((long) score);
} }
String getRankLevel(World world, int rank) { String getRankLevel(World world, int rank) {
if (rank < 1) rank = 1; // Ensure rank is within bounds
if (rank > Level.TEN) rank = Level.TEN; rank = Math.max(1, Math.min(rank, Level.TEN));
return addon.getManager() return addon.getManager().formatLevel(addon.getManager().getTopTen(world, Level.TEN).values().stream()
.formatLevel(addon.getManager() .skip(rank - 1L).limit(1L).findFirst().orElse(null));
.getTopTen(world, Level.TEN)
.values()
.stream()
.skip(rank - 1L)
.limit(1L)
.findFirst()
.orElse(null));
} }
/** /**
* Return the rank of the player in a world * Return the rank of the player in a world
*
* @param world world * @param world world
* @param user player * @param user player
* @return rank where 1 is the top rank. * @return rank where 1 is the top rank.
*/ */
private String getRankValue(World world, User user) { private String getRankValue(World world, User user) {
if (user == null) { if (user == null) {
return ""; return "";
} }
// Get the island level for this user // Get the island level for this user
long level = addon.getManager().getIslandLevel(world, user.getUniqueId()); long level = addon.getManager().getIslandLevel(world, user.getUniqueId());
return String.valueOf(addon.getManager().getTopTenLists().getOrDefault(world, new TopTenData(world)).getTopTen().values().stream().filter(l -> l > level).count() + 1); return String.valueOf(addon.getManager().getTopTenLists().getOrDefault(world, new TopTenData(world)).getTopTen()
.values().stream().filter(l -> l > level).count() + 1);
} }
String getVisitedIslandLevel(GameModeAddon gm, User user) { String getVisitedIslandLevel(GameModeAddon gm, User user) {
if (user == null || !gm.inWorld(user.getWorld())) return ""; if (user == null || !gm.inWorld(user.getWorld()))
return addon.getIslands().getIslandAt(user.getLocation()) return "";
.map(island -> addon.getManager().getIslandLevelString(gm.getOverWorld(), island.getOwner())) return addon.getIslands().getIslandAt(user.getLocation())
.orElse("0"); .map(island -> addon.getManager().getIslandLevelString(gm.getOverWorld(), island.getOwner()))
.orElse("0");
} }
} }

View File

@ -6,7 +6,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.bukkit.World; import org.bukkit.World;
@ -19,81 +18,81 @@ import world.bentobox.level.objects.TopTenData;
public class AdminStatsCommand extends CompositeCommand { public class AdminStatsCommand extends CompositeCommand {
private final Level level; private final Level level;
public AdminStatsCommand(Level addon, CompositeCommand parent) { public AdminStatsCommand(Level addon, CompositeCommand parent) {
super(parent, "stats"); super(parent, "stats");
this.level = addon; this.level = addon;
new AdminTopRemoveCommand(addon, this); new AdminTopRemoveCommand(addon, this);
}
@Override
public void setup() {
this.setPermission("admin.stats");
this.setOnlyPlayer(false);
this.setDescription("admin.stats.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
user.sendMessage("admin.stats.title");
Map<World, TopTenData> topTenLists = level.getManager().getTopTenLists();
if (topTenLists.isEmpty()) {
user.sendMessage("admin.stats.no-data");
return false;
} }
for (Entry<World, TopTenData> en : topTenLists.entrySet()) {
user.sendMessage("admin.stats.world", TextVariables.NAME,
level.getPlugin().getIWM().getWorldName(en.getKey()));
Map<String, Long> topTen = en.getValue().getTopTen();
if (topTen.isEmpty()) {
user.sendMessage("admin.stats.no-data");
return false;
}
@Override // Calculating basic statistics
public void setup() { long sum = 0, max = Long.MIN_VALUE, min = Long.MAX_VALUE;
this.setPermission("admin.stats"); Map<Long, Integer> levelFrequency = new HashMap<>();
this.setOnlyPlayer(false);
this.setDescription("admin.stats.description"); for (Long level : topTen.values()) {
sum += level;
max = Math.max(max, level);
min = Math.min(min, level);
levelFrequency.merge(level, 1, Integer::sum);
}
double average = sum / (double) topTen.size();
List<Long> sortedLevels = topTen.values().stream().sorted().collect(Collectors.toList());
long median = sortedLevels.get(sortedLevels.size() / 2);
Long mode = Collections.max(levelFrequency.entrySet(), Map.Entry.comparingByValue()).getKey();
// Logging basic statistics
user.sendMessage("admin.stats.average-level", TextVariables.NUMBER, String.valueOf(average));
user.sendMessage("admin.stats.median-level", TextVariables.NUMBER, String.valueOf(median));
user.sendMessage("admin.stats.mode-level", TextVariables.NUMBER, String.valueOf(mode));
user.sendMessage("admin.stats.highest-level", TextVariables.NUMBER, String.valueOf(max));
user.sendMessage("admin.stats.lowest-level", TextVariables.NUMBER, String.valueOf(min));
// Grouping data for distribution analysis
Map<String, Integer> rangeMap = new TreeMap<>();
for (Long level : topTen.values()) {
String range = getRange(level);
rangeMap.merge(range, 1, Integer::sum);
}
// Logging distribution
user.sendMessage("admin.stats.distribution");
for (Map.Entry<String, Integer> entry : rangeMap.entrySet()) {
user.sendMessage(
entry.getKey() + ": " + entry.getValue() + " " + user.getTranslation("admin.stats.islands"));
}
} }
return true;
}
@Override private static String getRange(long level) {
public boolean execute(User user, String label, List<String> args) { long rangeStart = level / 100 * 100;
user.sendMessage("admin.stats.title"); long rangeEnd = rangeStart + 99;
Map<World, TopTenData> topTenLists = level.getManager().getTopTenLists(); return rangeStart + "-" + rangeEnd;
if (topTenLists.isEmpty()) { }
user.sendMessage("admin.stats.no-data");
return false;
}
for (Entry<World, TopTenData> en : topTenLists.entrySet()) {
user.sendMessage("admin.stats.world", TextVariables.NAME,
level.getPlugin().getIWM().getWorldName(en.getKey()));
Map<UUID, Long> topTen = en.getValue().getTopTen();
if (topTen.isEmpty()) {
user.sendMessage("admin.stats.no-data");
return false;
}
// Calculating basic statistics
long sum = 0, max = Long.MIN_VALUE, min = Long.MAX_VALUE;
Map<Long, Integer> levelFrequency = new HashMap<>();
for (Long level : topTen.values()) {
sum += level;
max = Math.max(max, level);
min = Math.min(min, level);
levelFrequency.merge(level, 1, Integer::sum);
}
double average = sum / (double) topTen.size();
List<Long> sortedLevels = topTen.values().stream().sorted().collect(Collectors.toList());
long median = sortedLevels.get(sortedLevels.size() / 2);
Long mode = Collections.max(levelFrequency.entrySet(), Map.Entry.comparingByValue()).getKey();
// Logging basic statistics
user.sendMessage("admin.stats.average-level", TextVariables.NUMBER, String.valueOf(average));
user.sendMessage("admin.stats.median-level", TextVariables.NUMBER, String.valueOf(median));
user.sendMessage("admin.stats.mode-level", TextVariables.NUMBER, String.valueOf(mode));
user.sendMessage("admin.stats.highest-level", TextVariables.NUMBER, String.valueOf(max));
user.sendMessage("admin.stats.lowest-level", TextVariables.NUMBER, String.valueOf(min));
// Grouping data for distribution analysis
Map<String, Integer> rangeMap = new TreeMap<>();
for (Long level : topTen.values()) {
String range = getRange(level);
rangeMap.merge(range, 1, Integer::sum);
}
// Logging distribution
user.sendMessage("admin.stats.distribution");
for (Map.Entry<String, Integer> entry : rangeMap.entrySet()) {
user.sendMessage(
entry.getKey() + ": " + entry.getValue() + " " + user.getTranslation("admin.stats.islands"));
}
}
return true;
}
private static String getRange(long level) {
long rangeStart = level / 100 * 100;
long rangeEnd = rangeStart + 99;
return rangeStart + "-" + rangeEnd;
}
} }

View File

@ -2,7 +2,7 @@ package world.bentobox.level.commands;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.Optional;
import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
@ -14,36 +14,32 @@ public class AdminTopCommand extends CompositeCommand {
private final Level levelPlugin; private final Level levelPlugin;
public AdminTopCommand(Level addon, CompositeCommand parent) { public AdminTopCommand(Level addon, CompositeCommand parent) {
super(parent, "top", "topten"); super(parent, "top", "topten");
this.levelPlugin = addon; this.levelPlugin = addon;
new AdminTopRemoveCommand(addon, this); new AdminTopRemoveCommand(addon, this);
} }
@Override @Override
public void setup() { public void setup() {
this.setPermission("admin.top"); this.setPermission("admin.top");
this.setOnlyPlayer(false); this.setOnlyPlayer(false);
this.setDescription("admin.top.description"); this.setDescription("admin.top.description");
} }
@Override @Override
public boolean execute(User user, String label, List<String> args) { public boolean execute(User user, String label, List<String> args) {
user.sendMessage("island.top.gui-title"); user.sendMessage("island.top.gui-title");
int rank = 0; int rank = 0;
for (Map.Entry<UUID, Long> topTen : levelPlugin.getManager().getTopTen(getWorld(), Level.TEN).entrySet()) { for (Map.Entry<String, Long> topTen : levelPlugin.getManager().getTopTen(getWorld(), Level.TEN).entrySet()) {
Island island = getPlugin().getIslands().getIsland(getWorld(), topTen.getKey()); Optional<Island> is = getPlugin().getIslands().getIslandById(topTen.getKey());
if (island != null) { if (is.isPresent()) {
rank++; Island island = is.get();
user.sendMessage("admin.top.display", rank++;
"[rank]", user.sendMessage("admin.top.display", "[rank]", String.valueOf(rank), "[name]",
String.valueOf(rank), this.getPlugin().getPlayers().getUser(island.getOwner()).getName(), "[level]",
"[name]", String.valueOf(topTen.getValue()));
this.getPlugin().getPlayers().getUser(island.getOwner()).getName(), }
"[level]", }
String.valueOf(topTen.getValue())); return true;
}
}
return true;
} }
} }

View File

@ -6,10 +6,12 @@ import java.util.Optional;
import world.bentobox.bentobox.api.commands.CompositeCommand; import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.level.Level; import world.bentobox.level.Level;
/** /**
* Removes a player from the top ten * Removes a player from the top ten
*
* @author tastybento * @author tastybento
* *
*/ */
@ -19,46 +21,53 @@ public class AdminTopRemoveCommand extends CompositeCommand {
private User target; private User target;
public AdminTopRemoveCommand(Level addon, CompositeCommand parent) { public AdminTopRemoveCommand(Level addon, CompositeCommand parent) {
super(parent, "remove", "delete"); super(parent, "remove", "delete");
this.addon = addon; this.addon = addon;
} }
@Override @Override
public void setup() { public void setup() {
this.setPermission("admin.top.remove"); this.setPermission("admin.top.remove");
this.setOnlyPlayer(false); this.setOnlyPlayer(false);
this.setParametersHelp("admin.top.remove.parameters"); this.setParametersHelp("admin.top.remove.parameters");
this.setDescription("admin.top.remove.description"); this.setDescription("admin.top.remove.description");
} }
/* (non-Javadoc) /*
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List) * (non-Javadoc)
*
* @see world.bentobox.bentobox.api.commands.BentoBoxCommand#canExecute(world.
* bentobox.bentobox.api.user.User, java.lang.String, java.util.List)
*/ */
@Override @Override
public boolean canExecute(User user, String label, List<String> args) { public boolean canExecute(User user, String label, List<String> args) {
if (args.size() != 1) { if (args.size() != 1) {
this.showHelp(this, user); this.showHelp(this, user);
return false; return false;
} }
target = getPlayers().getUser(args.get(0)); target = getPlayers().getUser(args.get(0));
if (target == null) { if (target == null) {
user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0)); user.sendMessage("general.errors.unknown-player", TextVariables.NAME, args.get(0));
return false; return false;
} }
return true; return true;
} }
@Override @Override
public boolean execute(User user, String label, List<String> args) { public boolean execute(User user, String label, List<String> args) {
addon.getManager().removeEntry(getWorld(), target.getUniqueId()); // Removes islands that this target is an owner of
user.sendMessage("general.success"); getIslands().getIslands(getWorld(), target.getUniqueId()).stream()
return true; .filter(is -> target.getUniqueId().equals(is.getOwner()))
.forEach(island -> addon.getManager().removeEntry(getWorld(), island.getUniqueId()));
user.sendMessage("general.success");
return true;
} }
@Override @Override
public Optional<List<String>> tabComplete(User user, String alias, List<String> args) { public Optional<List<String>> tabComplete(User user, String alias, List<String> args) {
return Optional.of(addon.getManager().getTopTen(getWorld(), Level.TEN).keySet().stream().map(addon.getPlayers()::getName) return Optional.of(addon.getManager().getTopTen(getWorld(), Level.TEN).keySet().stream()
.filter(n -> !n.isEmpty()).toList()); .map(getIslands()::getIslandById).flatMap(Optional::stream).map(Island::getOwner)
.map(addon.getPlayers()::getName).filter(n -> !n.isEmpty()).toList());
} }
} }

View File

@ -1,7 +1,5 @@
package world.bentobox.level.listeners; package world.bentobox.level.listeners;
import java.util.UUID;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@ -21,7 +19,9 @@ import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.level.Level; import world.bentobox.level.Level;
/** /**
* Listens for new islands or ownership changes and sets the level to zero automatically * Listens for new islands or ownership changes and sets the level to zero
* automatically
*
* @author tastybento * @author tastybento
* *
*/ */
@ -33,93 +33,89 @@ public class IslandActivitiesListeners implements Listener {
* @param addon - addon * @param addon - addon
*/ */
public IslandActivitiesListeners(Level addon) { public IslandActivitiesListeners(Level addon) {
this.addon = addon; this.addon = addon;
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onNewIsland(IslandCreatedEvent e) { public void onNewIsland(IslandCreatedEvent e) {
if (addon.getSettings().isZeroNewIslandLevels()) { if (addon.getSettings().isZeroNewIslandLevels()) {
zeroIsland(e.getIsland()); zeroIsland(e.getIsland());
} }
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onNewIsland(IslandResettedEvent e) { public void onNewIsland(IslandResettedEvent e) {
if (addon.getSettings().isZeroNewIslandLevels()) { if (addon.getSettings().isZeroNewIslandLevels()) {
zeroIsland(e.getIsland()); zeroIsland(e.getIsland());
} }
} }
private void zeroIsland(final Island island) { private void zeroIsland(final Island island) {
// Clear the island setting // Clear the island setting
if (island.getOwner() != null && island.getWorld() != null) { if (island.getOwner() != null && island.getWorld() != null) {
addon.getPipeliner().zeroIsland(island).thenAccept(results -> addon.getPipeliner().zeroIsland(island)
addon.getManager().setInitialIslandLevel(island, results.getLevel())); .thenAccept(results -> addon.getManager().setInitialIslandLevel(island, results.getLevel()));
} }
} }
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onIslandDelete(IslandPreclearEvent e) { public void onIslandDelete(IslandPreclearEvent e) {
remove(e.getIsland().getWorld(), e.getIsland().getUniqueId());
// Remove player from the top ten and level
UUID uuid = e.getIsland().getOwner();
World world = e.getIsland().getWorld();
remove(world, uuid);
} }
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onIslandDeleted(IslandDeleteEvent e) { public void onIslandDeleted(IslandDeleteEvent e) {
// Remove island // Remove island
addon.getManager().deleteIsland(e.getIsland().getUniqueId()); addon.getManager().deleteIsland(e.getIsland().getUniqueId());
} }
private void remove(World world, UUID uuid) { private void remove(World world, String uuid) {
if (uuid != null && world != null) { if (uuid != null && world != null) {
addon.getManager().removeEntry(world, uuid); addon.getManager().removeEntry(world, uuid);
} }
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onNewIslandOwner(TeamSetownerEvent e) { public void onNewIslandOwner(TeamSetownerEvent e) {
// Remove player from the top ten and level // Remove island from the top ten and level
remove(e.getIsland().getWorld(), e.getIsland().getOwner()); remove(e.getIsland().getWorld(), e.getIsland().getUniqueId());
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIsland(TeamJoinedEvent e) { public void onIsland(TeamJoinedEvent e) {
// TODO: anything to do here?
// Remove player from the top ten and level // Remove player from the top ten and level
remove(e.getIsland().getWorld(), e.getPlayerUUID()); // remove(e.getIsland().getWorld(), e.getPlayerUUID());
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIsland(IslandUnregisteredEvent e) { public void onIsland(IslandUnregisteredEvent e) {
// Remove player from the top ten // Remove island from the top ten
remove(e.getIsland().getWorld(), e.getPlayerUUID()); remove(e.getIsland().getWorld(), e.getIsland().getUniqueId());
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIsland(IslandRegisteredEvent e) { public void onIsland(IslandRegisteredEvent e) {
// TODO: anything to do here?
// Remove player from the top ten // Remove player from the top ten
remove(e.getIsland().getWorld(), e.getPlayerUUID()); // remove(e.getIsland().getWorld(), e.getPlayerUUID());
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIsland(TeamLeaveEvent e) { public void onIsland(TeamLeaveEvent e) {
// TODO: anything to do here?
// Remove player from the top ten and level // Remove player from the top ten and level
remove(e.getIsland().getWorld(), e.getPlayerUUID()); // remove(e.getIsland().getWorld(), e.getPlayerUUID());
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIsland(TeamKickEvent e) { public void onIsland(TeamKickEvent e) {
//// TODO: anything to do here?
// Remove player from the top ten and level // Remove player from the top ten and level
remove(e.getIsland().getWorld(), e.getPlayerUUID()); // remove(e.getIsland().getWorld(), e.getPlayerUUID());
} }
} }

View File

@ -3,56 +3,41 @@ package world.bentobox.level.objects;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import org.bukkit.World; import org.bukkit.World;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.database.objects.Table;
/** /**
* This class stores the top ten. * This class stores the top ten.
*
* @author tastybento * @author tastybento
* *
*/ */
@Table(name = "TopTenData") public class TopTenData {
public class TopTenData implements DataObject {
// UniqueId is the world name // UniqueId is the world name
@Expose @Expose
private String uniqueId = ""; private String uniqueId = "";
@Expose @Expose
private Map<UUID, Long> topTen = new LinkedHashMap<>(); private Map<String, Long> topTen = new LinkedHashMap<>();
public TopTenData(World k) { public TopTenData(World k) {
uniqueId = k.getName().toLowerCase(Locale.ENGLISH); uniqueId = k.getName().toLowerCase(Locale.ENGLISH);
} }
@Override
public String getUniqueId() {
// This is the world name
return uniqueId;
}
@Override
public void setUniqueId(String uniqueId) {
// This is the world name - make it always lowercase
this.uniqueId = uniqueId.toLowerCase(Locale.ENGLISH);
}
/** /**
* @return the topTen * @return the topTen
*/ */
public Map<UUID, Long> getTopTen() { public Map<String, Long> getTopTen() {
return topTen; return topTen;
} }
/** /**
* @param topTen the topTen to set * @param topTen the topTen to set
*/ */
public void setTopTen(Map<UUID, Long> topTen) { public void setTopTen(Map<String, Long> topTen) {
this.topTen = topTen; this.topTen = topTen;
} }
} }

View File

@ -5,10 +5,11 @@
package world.bentobox.level.panels; package world.bentobox.level.panels;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -29,474 +30,390 @@ import world.bentobox.bentobox.managers.RanksManager;
import world.bentobox.level.Level; import world.bentobox.level.Level;
import world.bentobox.level.util.Utils; import world.bentobox.level.util.Utils;
/** /**
* This panel opens top likes panel * This panel opens top likes panel
*/ */
public class TopLevelPanel public class TopLevelPanel {
{
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Internal Constructor // Section: Internal Constructor
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
/** /**
* This is internal constructor. It is used internally in current class to avoid creating objects everywhere. * This is internal constructor. It is used internally in current class to avoid
* creating objects everywhere.
* *
* @param addon Level object. * @param addon Level object.
* @param user User who opens Panel. * @param user User who opens Panel.
* @param world World where gui is opened * @param world World where gui is opened
* @param permissionPrefix Permission Prefix * @param permissionPrefix Permission Prefix
*/ */
private TopLevelPanel(Level addon, User user, World world, String permissionPrefix) private TopLevelPanel(Level addon, User user, World world, String permissionPrefix) {
{ this.addon = addon;
this.addon = addon; this.user = user;
this.user = user; this.world = world;
this.world = world;
this.iconPermission = permissionPrefix + "level.icon"; this.iconPermission = permissionPrefix + "level.icon";
topIslands = new ArrayList<>();
this.topIslands = this.addon.getManager().getTopTen(this.world, 10).entrySet().stream(). for (Map.Entry<String, Long> en : addon.getManager().getTopTen(this.world, Level.TEN).entrySet()) {
map(entry -> { Optional<Island> is = addon.getIslands().getIslandById(en.getKey());
Island island = this.addon.getIslandsManager().getIsland(this.world, entry.getKey()); if (is.isPresent()) {
return new IslandTopRecord(island, entry.getValue()); topIslands.add(new IslandTopRecord(is.get(), en.getValue()));
}). }
collect(Collectors.toList()); }
} }
/** /**
* Build method manages current panel opening. It uses BentoBox PanelAPI that is easy to use and users can get nice * Build method manages current panel opening. It uses BentoBox PanelAPI that is
* panels. * easy to use and users can get nice panels.
*/ */
public void build() public void build() {
{ TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
panelBuilder.user(this.user); panelBuilder.user(this.user);
panelBuilder.world(this.world); panelBuilder.world(this.world);
panelBuilder.template("top_panel", new File(this.addon.getDataFolder(), "panels")); panelBuilder.template("top_panel", new File(this.addon.getDataFolder(), "panels"));
panelBuilder.registerTypeBuilder("VIEW", this::createViewerButton); panelBuilder.registerTypeBuilder("VIEW", this::createViewerButton);
panelBuilder.registerTypeBuilder("TOP", this::createPlayerButton); panelBuilder.registerTypeBuilder("TOP", this::createPlayerButton);
// Register unknown type builder. // Register unknown type builder.
panelBuilder.build(); panelBuilder.build();
} }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Methods // Section: Methods
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
/** /**
* Creates fallback based on template. * Creates fallback based on template.
*
* @param template Template record for fallback button. * @param template Template record for fallback button.
* @param index Place of the fallback. * @param index Place of the fallback.
* @return Fallback panel item. * @return Fallback panel item.
*/ */
private PanelItem createFallback(ItemTemplateRecord template, long index) private PanelItem createFallback(ItemTemplateRecord template, long index) {
{ if (template == null) {
if (template == null) return null;
{ }
return null;
}
PanelItemBuilder builder = new PanelItemBuilder(); PanelItemBuilder builder = new PanelItemBuilder();
if (template.icon() != null) if (template.icon() != null) {
{ builder.icon(template.icon().clone());
builder.icon(template.icon().clone()); }
}
if (template.title() != null) if (template.title() != null) {
{ builder.name(
builder.name(this.user.getTranslation(this.world, template.title(), this.user.getTranslation(this.world, template.title(), TextVariables.NAME, String.valueOf(index)));
TextVariables.NAME, String.valueOf(index))); } else {
} builder.name(this.user.getTranslation(this.world, REFERENCE, TextVariables.NAME, String.valueOf(index)));
else }
{
builder.name(this.user.getTranslation(this.world, REFERENCE,
TextVariables.NAME, String.valueOf(index)));
}
if (template.description() != null) if (template.description() != null) {
{ builder.description(this.user.getTranslation(this.world, template.description(), TextVariables.NUMBER,
builder.description(this.user.getTranslation(this.world, template.description(), String.valueOf(index)));
TextVariables.NUMBER, String.valueOf(index))); }
}
builder.amount(index != 0 ? (int) index : 1); builder.amount(index != 0 ? (int) index : 1);
return builder.build(); return builder.build();
} }
/** /**
* This method creates player icon with warp functionality. * This method creates player icon with warp functionality.
* *
* @return PanelItem for PanelBuilder. * @return PanelItem for PanelBuilder.
*/ */
private PanelItem createPlayerButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot itemSlot) private PanelItem createPlayerButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot itemSlot) {
{ int index = (int) template.dataMap().getOrDefault("index", 0);
int index = (int) template.dataMap().getOrDefault("index", 0);
if (index < 1) if (index < 1) {
{ return this.createFallback(template.fallback(), index);
return this.createFallback(template.fallback(), index); }
}
IslandTopRecord islandTopRecord = this.topIslands.size() < index ? null : this.topIslands.get(index - 1); IslandTopRecord islandTopRecord = this.topIslands.size() < index ? null : this.topIslands.get(index - 1);
if (islandTopRecord == null) if (islandTopRecord == null) {
{ return this.createFallback(template.fallback(), index);
return this.createFallback(template.fallback(), index); }
}
return this.createIslandIcon(template, islandTopRecord, index); return this.createIslandIcon(template, islandTopRecord, index);
} }
/** /**
* This method creates button from template for given island top record. * This method creates button from template for given island top record.
* @param template Icon Template. *
* @param template Icon Template.
* @param islandTopRecord Island Top Record. * @param islandTopRecord Island Top Record.
* @param index Place Index. * @param index Place Index.
* @return PanelItem for PanelBuilder. * @return PanelItem for PanelBuilder.
*/ */
private PanelItem createIslandIcon(ItemTemplateRecord template, IslandTopRecord islandTopRecord, int index) private PanelItem createIslandIcon(ItemTemplateRecord template, IslandTopRecord islandTopRecord, int index) {
{ // Get player island.
// Get player island. Island island = islandTopRecord.island();
Island island = islandTopRecord.island();
if (island == null) if (island == null) {
{ return this.createFallback(template.fallback(), index);
return this.createFallback(template.fallback(), index); }
}
PanelItemBuilder builder = new PanelItemBuilder(); PanelItemBuilder builder = new PanelItemBuilder();
this.populateIslandIcon(builder, template, island); this.populateIslandIcon(builder, template, island);
this.populateIslandTitle(builder, template, island); this.populateIslandTitle(builder, template, island);
this.populateIslandDescription(builder, template, island, islandTopRecord, index); this.populateIslandDescription(builder, template, island, islandTopRecord, index);
builder.amount(index); builder.amount(index);
// Get only possible actions, by removing all inactive ones. // Get only possible actions, by removing all inactive ones.
List<ItemTemplateRecord.ActionRecords> activeActions = new ArrayList<>(template.actions()); List<ItemTemplateRecord.ActionRecords> activeActions = new ArrayList<>(template.actions());
activeActions.removeIf(action -> activeActions.removeIf(action -> {
{ switch (action.actionType().toUpperCase()) {
switch (action.actionType().toUpperCase()) case "WARP" -> {
{ return island.getOwner() == null || this.addon.getWarpHook() == null
case "WARP" -> { || !this.addon.getWarpHook().getWarpSignsManager().hasWarp(this.world, island.getOwner());
return island.getOwner() == null || }
this.addon.getWarpHook() == null || case "VISIT" -> {
!this.addon.getWarpHook().getWarpSignsManager().hasWarp(this.world, island.getOwner()); return island.getOwner() == null || this.addon.getVisitHook() == null
} || !this.addon.getVisitHook().getAddonManager().preprocessTeleportation(this.user, island);
case "VISIT" -> { }
return island.getOwner() == null || case "VIEW" -> {
this.addon.getVisitHook() == null || return island.getOwner() == null
!this.addon.getVisitHook().getAddonManager().preprocessTeleportation(this.user, island); || !island.getMemberSet(RanksManager.MEMBER_RANK).contains(this.user.getUniqueId());
} }
case "VIEW" -> { default -> {
return island.getOwner() == null || return false;
!island.getMemberSet(RanksManager.MEMBER_RANK).contains(this.user.getUniqueId()); }
} }
default -> { });
return false;
}
}
});
// Add Click handler // Add Click handler
builder.clickHandler((panel, user, clickType, i) -> builder.clickHandler((panel, user, clickType, i) -> {
{ for (ItemTemplateRecord.ActionRecords action : activeActions) {
for (ItemTemplateRecord.ActionRecords action : activeActions) if (clickType == action.clickType() || action.clickType() == ClickType.UNKNOWN) {
{ switch (action.actionType().toUpperCase()) {
if (clickType == action.clickType() || action.clickType() == ClickType.UNKNOWN) case "WARP" -> {
{ this.user.closeInventory();
switch (action.actionType().toUpperCase()) this.addon.getWarpHook().getWarpSignsManager().warpPlayer(this.world, this.user,
{ island.getOwner());
case "WARP" -> { }
this.user.closeInventory(); case "VISIT" ->
this.addon.getWarpHook().getWarpSignsManager().warpPlayer(this.world, this.user, island.getOwner()); // The command call implementation solves necessity to check for all visits
} // options,
case "VISIT" -> // like cool down, confirmation and preprocess in single go. Would it be better
// The command call implementation solves necessity to check for all visits options, // to write
// like cool down, confirmation and preprocess in single go. Would it be better to write // all logic here?
// all logic here?
this.addon.getPlugin().getIWM().getAddon(this.world). this.addon.getPlugin().getIWM().getAddon(this.world).flatMap(GameModeAddon::getPlayerCommand)
flatMap(GameModeAddon::getPlayerCommand).ifPresent(command -> .ifPresent(command -> {
{ String mainCommand = this.addon.getVisitHook().getSettings().getPlayerMainCommand();
String mainCommand =
this.addon.getVisitHook().getSettings().getPlayerMainCommand();
if (!mainCommand.isBlank()) if (!mainCommand.isBlank()) {
{ this.user.closeInventory();
this.user.closeInventory(); this.user.performCommand(
this.user.performCommand(command.getTopLabel() + " " + mainCommand + " " + island.getOwner()); command.getTopLabel() + " " + mainCommand + " " + island.getOwner());
} }
}); });
case "VIEW" -> { case "VIEW" -> {
this.user.closeInventory(); this.user.closeInventory();
// Open Detailed GUI. // Open Detailed GUI.
DetailsPanel.openPanel(this.addon, this.world, this.user); DetailsPanel.openPanel(this.addon, this.world, this.user);
} }
// Catch default // Catch default
default -> { default -> {
this.user.closeInventory(); this.user.closeInventory();
addon.logError("Unknown action type " + action.actionType().toUpperCase()); addon.logError("Unknown action type " + action.actionType().toUpperCase());
} }
} }
} }
} }
return true; return true;
}); });
// Collect tooltips. // Collect tooltips.
List<String> tooltips = activeActions.stream(). List<String> tooltips = activeActions.stream().filter(action -> action.tooltip() != null)
filter(action -> action.tooltip() != null). .map(action -> this.user.getTranslation(this.world, action.tooltip())).filter(text -> !text.isBlank())
map(action -> this.user.getTranslation(this.world, action.tooltip())). .collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
filter(text -> !text.isBlank()).
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
// Add tooltips. // Add tooltips.
if (!tooltips.isEmpty()) if (!tooltips.isEmpty()) {
{ // Empty line and tooltips.
// Empty line and tooltips. builder.description("");
builder.description(""); builder.description(tooltips);
builder.description(tooltips); }
}
return builder.build(); return builder.build();
} }
/** /**
* Populate given panel item builder name with values from template and island objects. * Populate given panel item builder name with values from template and island
* objects.
* *
* @param builder the builder * @param builder the builder
* @param template the template * @param template the template
* @param island the island * @param island the island
*/ */
private void populateIslandTitle(PanelItemBuilder builder, private void populateIslandTitle(PanelItemBuilder builder, ItemTemplateRecord template, Island island) {
ItemTemplateRecord template,
Island island)
{
// Get Island Name // Get Island Name
String nameText; String nameText;
if (island.getName() == null || island.getName().isEmpty()) if (island.getName() == null || island.getName().isEmpty()) {
{ nameText = this.user.getTranslation(REFERENCE + "owners-island", PLAYER,
nameText = this.user.getTranslation(REFERENCE + "owners-island", island.getOwner() == null ? this.user.getTranslation(REFERENCE + "unknown")
PLAYER, : this.addon.getPlayers().getName(island.getOwner()));
island.getOwner() == null ? } else {
this.user.getTranslation(REFERENCE + "unknown") : nameText = island.getName();
this.addon.getPlayers().getName(island.getOwner())); }
}
else
{
nameText = island.getName();
}
// Template specific title is always more important than custom one. // Template specific title is always more important than custom one.
if (template.title() != null && !template.title().isBlank()) if (template.title() != null && !template.title().isBlank()) {
{ builder.name(this.user.getTranslation(this.world, template.title(), TextVariables.NAME, nameText));
builder.name(this.user.getTranslation(this.world, template.title(), } else {
TextVariables.NAME, nameText)); builder.name(this.user.getTranslation(REFERENCE + "name", TextVariables.NAME, nameText));
} }
else
{
builder.name(this.user.getTranslation(REFERENCE + "name", TextVariables.NAME, nameText));
}
} }
/** /**
* Populate given panel item builder icon with values from template and island objects. * Populate given panel item builder icon with values from template and island
* objects.
* *
* @param builder the builder * @param builder the builder
* @param template the template * @param template the template
* @param island the island * @param island the island
*/ */
private void populateIslandIcon(PanelItemBuilder builder, private void populateIslandIcon(PanelItemBuilder builder, ItemTemplateRecord template, Island island) {
ItemTemplateRecord template, User owner = island.getOwner() == null ? null : User.getInstance(island.getOwner());
Island island)
{
User owner = island.getOwner() == null ? null : User.getInstance(island.getOwner());
// Get permission or island icon // Get permission or island icon
String permissionIcon = owner == null ? null : String permissionIcon = owner == null ? null : Utils.getPermissionValue(owner, this.iconPermission, null);
Utils.getPermissionValue(owner, this.iconPermission, null);
Material material; Material material;
if (permissionIcon != null && !permissionIcon.equals("*")) if (permissionIcon != null && !permissionIcon.equals("*")) {
{ material = Material.matchMaterial(permissionIcon);
material = Material.matchMaterial(permissionIcon); } else {
} material = null;
else }
{
material = null;
}
if (material != null) if (material != null) {
{ if (!material.equals(Material.PLAYER_HEAD)) {
if (!material.equals(Material.PLAYER_HEAD)) builder.icon(material);
{ } else {
builder.icon(material); builder.icon(owner.getName());
} }
else } else if (template.icon() != null) {
{ builder.icon(template.icon().clone());
builder.icon(owner.getName()); } else if (owner != null) {
} builder.icon(owner.getName());
} } else {
else if (template.icon() != null) builder.icon(Material.PLAYER_HEAD);
{ }
builder.icon(template.icon().clone());
}
else if (owner != null)
{
builder.icon(owner.getName());
}
else
{
builder.icon(Material.PLAYER_HEAD);
}
} }
/** /**
* Populate given panel item builder description with values from template and island objects. * Populate given panel item builder description with values from template and
* island objects.
* *
* @param builder the builder * @param builder the builder
* @param template the template * @param template the template
* @param island the island * @param island the island
* @param islandTopRecord the top record object * @param islandTopRecord the top record object
* @param index place index. * @param index place index.
*/ */
private void populateIslandDescription(PanelItemBuilder builder, private void populateIslandDescription(PanelItemBuilder builder, ItemTemplateRecord template, Island island,
ItemTemplateRecord template, IslandTopRecord islandTopRecord, int index) {
Island island, // Get Owner Name
IslandTopRecord islandTopRecord, String ownerText = this.user.getTranslation(REFERENCE + "owner", PLAYER,
int index) island.getOwner() == null ? this.user.getTranslation(REFERENCE + "unknown")
{ : this.addon.getPlayers().getName(island.getOwner()));
// Get Owner Name
String ownerText = this.user.getTranslation(REFERENCE + "owner",
PLAYER,
island.getOwner() == null ?
this.user.getTranslation(REFERENCE + "unknown") :
this.addon.getPlayers().getName(island.getOwner()));
// Get Members Text // Get Members Text
String memberText; String memberText;
if (island.getMemberSet().size() > 1) if (island.getMemberSet().size() > 1) {
{ StringBuilder memberBuilder = new StringBuilder(
StringBuilder memberBuilder = new StringBuilder( this.user.getTranslationOrNothing(REFERENCE + "members-title"));
this.user.getTranslationOrNothing(REFERENCE + "members-title"));
for (UUID uuid : island.getMemberSet()) for (UUID uuid : island.getMemberSet()) {
{ User member = User.getInstance(uuid);
User member = User.getInstance(uuid);
if (memberBuilder.length() > 0) if (memberBuilder.length() > 0) {
{ memberBuilder.append("\n");
memberBuilder.append("\n"); }
}
memberBuilder.append( memberBuilder.append(this.user.getTranslationOrNothing(REFERENCE + "member", PLAYER, member.getName()));
this.user.getTranslationOrNothing(REFERENCE + "member", }
PLAYER, member.getName()));
}
memberText = memberBuilder.toString(); memberText = memberBuilder.toString();
} } else {
else memberText = "";
{ }
memberText = "";
}
String placeText = this.user.getTranslation(REFERENCE + "place", String placeText = this.user.getTranslation(REFERENCE + "place", TextVariables.NUMBER, String.valueOf(index));
TextVariables.NUMBER, String.valueOf(index));
String levelText = this.user.getTranslation(REFERENCE + "level", String levelText = this.user.getTranslation(REFERENCE + "level", TextVariables.NUMBER,
TextVariables.NUMBER, this.addon.getManager().formatLevel(islandTopRecord.level())); this.addon.getManager().formatLevel(islandTopRecord.level()));
// Template specific description is always more important than custom one. // Template specific description is always more important than custom one.
if (template.description() != null && !template.description().isBlank()) if (template.description() != null && !template.description().isBlank()) {
{ builder.description(this.user
builder.description(this.user.getTranslation(this.world, template.description(), .getTranslation(this.world, template.description(), "[owner]", ownerText, "[members]", memberText,
"[owner]", ownerText, "[level]", levelText, "[place]", placeText)
"[members]", memberText, .replaceAll("(?m)^[ \\t]*\\r?\\n", "").replaceAll("(?<!\\\\)\\|", "\n").replace("\\\\\\|", "|")); // Not
"[level]", levelText, // a
"[place]", placeText). // regex
replaceAll("(?m)^[ \\t]*\\r?\\n", ""). // -
replaceAll("(?<!\\\\)\\|", "\n"). // replace
replace("\\\\\\|", "|")); // Not a regex - replace is more efficient // is
} // more
else // efficient
{ } else {
// Now combine everything. // Now combine everything.
String descriptionText = this.user.getTranslation(REFERENCE + "description", String descriptionText = this.user.getTranslation(REFERENCE + "description", "[owner]", ownerText,
"[owner]", ownerText, "[members]", memberText, "[level]", levelText, "[place]", placeText);
"[members]", memberText,
"[level]", levelText,
"[place]", placeText);
builder.description(descriptionText. builder.description(descriptionText.replaceAll("(?m)^[ \\t]*\\r?\\n", "").replaceAll("(?<!\\\\)\\|", "\n")
replaceAll("(?m)^[ \\t]*\\r?\\n", ""). .replace("\\\\\\|", "|")); // Not a regex - replace is more efficient
replaceAll("(?<!\\\\)\\|", "\n"). }
replace("\\\\\\|", "|")); // Not a regex - replace is more efficient
}
} }
/** /**
* Create viewer button panel item. * Create viewer button panel item.
* *
* @return PanelItem for PanelBuilder. * @return PanelItem for PanelBuilder.
*/ */
private PanelItem createViewerButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot itemSlot) private PanelItem createViewerButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot itemSlot) {
{ Island island = this.addon.getIslands().getIsland(this.world, this.user);
Island island = this.addon.getIslands().getIsland(this.world, this.user);
if (island == null || island.getOwner() == null) if (island == null || island.getOwner() == null) {
{ // Player do not have an island.
// Player do not have an island. return null;
return null; }
}
int place = this.addon.getManager().getRank(this.world, this.user.getUniqueId()); int place = this.addon.getManager().getRank(this.world, this.user.getUniqueId());
long level = this.addon.getIslandLevel(this.world, island.getOwner()); long level = this.addon.getIslandLevel(this.world, island.getOwner());
IslandTopRecord topRecord = new IslandTopRecord(island, level); IslandTopRecord topRecord = new IslandTopRecord(island, level);
return this.createIslandIcon(template, topRecord, place); return this.createIslandIcon(template, topRecord, place);
} }
/** /**
* This method is used to open UserPanel outside this class. It will be much easier to open panel with single method * This method is used to open UserPanel outside this class. It will be much
* call then initializing new object. * easier to open panel with single method call then initializing new object.
* *
* @param addon Level Addon object * @param addon Level Addon object
* @param user User who opens panel * @param user User who opens panel
* @param world World where gui is opened * @param world World where gui is opened
* @param permissionPrefix Permission Prefix * @param permissionPrefix Permission Prefix
*/ */
public static void openPanel(Level addon, User user, World world, String permissionPrefix) public static void openPanel(Level addon, User user, World world, String permissionPrefix) {
{ new TopLevelPanel(addon, user, world, permissionPrefix).build();
new TopLevelPanel(addon, user, world, permissionPrefix).build();
} }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
@ -512,9 +429,12 @@ public class TopLevelPanel
/** /**
* This record is used internally. It converts user -> level to island -> level. * This record is used internally. It converts user -> level to island -> level.
*
* @param island island
* @param level level
*/ */
private record IslandTopRecord(Island island, Long level) {} private record IslandTopRecord(Island island, Long level) {
}
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Section: Variables // Section: Variables

View File

@ -73,60 +73,60 @@ import world.bentobox.level.objects.TopTenData;
@PrepareForTest({ Bukkit.class, BentoBox.class, DatabaseSetup.class, PanelBuilder.class }) @PrepareForTest({ Bukkit.class, BentoBox.class, DatabaseSetup.class, PanelBuilder.class })
public class LevelsManagerTest { public class LevelsManagerTest {
@Mock @Mock
private static AbstractDatabaseHandler<Object> handler; private static AbstractDatabaseHandler<Object> handler;
@Mock @Mock
Level addon; Level addon;
@Mock @Mock
private BentoBox plugin; private BentoBox plugin;
@Mock @Mock
private Settings pluginSettings; private Settings pluginSettings;
// Class under test // Class under test
private LevelsManager lm; private LevelsManager lm;
@Mock @Mock
private Island island; private Island island;
@Mock @Mock
private Pipeliner pipeliner; private Pipeliner pipeliner;
private CompletableFuture<Results> cf; private CompletableFuture<Results> cf;
private UUID uuid; private UUID uuid;
@Mock @Mock
private World world; private World world;
@Mock @Mock
private Player player; private Player player;
@Mock @Mock
private ConfigSettings settings; private ConfigSettings settings;
@Mock @Mock
private User user; private User user;
@Mock @Mock
private PlayersManager pm; private PlayersManager pm;
@Mock @Mock
private Inventory inv; private Inventory inv;
@Mock @Mock
private IslandWorldManager iwm; private IslandWorldManager iwm;
@Mock @Mock
private PluginManager pim; private PluginManager pim;
@Mock @Mock
private IslandLevels levelsData; private IslandLevels levelsData;
@Mock @Mock
private IslandsManager im; private IslandsManager im;
@Mock @Mock
private BukkitScheduler scheduler; private BukkitScheduler scheduler;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@BeforeClass @BeforeClass
public static void beforeClass() { public static void beforeClass() {
// This has to be done beforeClass otherwise the tests will interfere with each // This has to be done beforeClass otherwise the tests will interfere with each
// other // other
handler = mock(AbstractDatabaseHandler.class); handler = mock(AbstractDatabaseHandler.class);
// Database // Database
PowerMockito.mockStatic(DatabaseSetup.class); PowerMockito.mockStatic(DatabaseSetup.class);
DatabaseSetup dbSetup = mock(DatabaseSetup.class); DatabaseSetup dbSetup = mock(DatabaseSetup.class);
when(DatabaseSetup.getDatabase()).thenReturn(dbSetup); when(DatabaseSetup.getDatabase()).thenReturn(dbSetup);
when(dbSetup.getHandler(any())).thenReturn(handler); when(dbSetup.getHandler(any())).thenReturn(handler);
} }
/** /**
* @throws java.lang.Exception * @throws java.lang.Exception
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -160,7 +160,7 @@ public class LevelsManagerTest {
when(island.getMemberSet()).thenReturn(iset); when(island.getMemberSet()).thenReturn(iset);
when(island.getOwner()).thenReturn(uuid); when(island.getOwner()).thenReturn(uuid);
when(island.getWorld()).thenReturn(world); when(island.getWorld()).thenReturn(world);
when(island.getUniqueId()).thenReturn(UUID.randomUUID().toString()); when(island.getUniqueId()).thenReturn(uuid.toString());
// Default to uuid's being island owners // Default to uuid's being island owners
when(im.hasIsland(eq(world), any(UUID.class))).thenReturn(true); when(im.hasIsland(eq(world), any(UUID.class))).thenReturn(true);
when(im.getIsland(world, uuid)).thenReturn(island); when(im.getIsland(world, uuid)).thenReturn(island);
@ -232,229 +232,218 @@ public class LevelsManagerTest {
lm.migrate(); lm.migrate();
} }
/** /**
* @throws java.lang.Exception * @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
deleteAll(new File("database"));
User.clearUsers();
Mockito.framework().clearInlineMocks();
}
private static void deleteAll(File file) throws IOException {
if (file.exists()) {
Files.walk(file.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
}
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#calculateLevel(UUID, world.bentobox.bentobox.database.objects.Island)}.
*/
@Test
public void testCalculateLevel() {
Results results = new Results();
results.setLevel(10000);
results.setInitialLevel(3);
lm.calculateLevel(uuid, island);
// Complete the pipelined completable future
cf.complete(results);
assertEquals(10000L, lm.getLevelsData(island).getLevel());
// Map<UUID, Long> tt = lm.getTopTen(world, 10);
// assertEquals(1, tt.size());
// assertTrue(tt.get(uuid) == 10000);
assertEquals(10000L, lm.getIslandMaxLevel(world, uuid));
results.setLevel(5000);
lm.calculateLevel(uuid, island);
// Complete the pipelined completable future
cf.complete(results);
assertEquals(5000L, lm.getLevelsData(island).getLevel());
// Still should be 10000
assertEquals(10000L, lm.getIslandMaxLevel(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getInitialLevel(world.bentobox.bentobox.database.objects.Island)}.
*/
@Test
public void testGetInitialLevel() {
assertEquals(0, lm.getInitialLevel(island));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getIslandLevel(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testGetIslandLevel() {
assertEquals(-5, lm.getIslandLevel(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getPointsToNextString(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testGetPointsToNextString() {
// No island player
assertEquals("", lm.getPointsToNextString(world, UUID.randomUUID()));
// Player has island
assertEquals("0", lm.getPointsToNextString(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getIslandLevelString(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testGetIslandLevelString() {
assertEquals("-5", lm.getIslandLevelString(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getLevelsData(java.util.UUID)}.
*/
@Test
public void testGetLevelsData() {
assertEquals(levelsData, lm.getLevelsData(island));
}
/**
* Test method for {@link world.bentobox.level.LevelsManager#formatLevel(long)}.
*/
@Test
public void testFormatLevel() {
assertEquals("123456789", lm.formatLevel(123456789L));
when(settings.isShorthand()).thenReturn(true);
assertEquals("123.5M", lm.formatLevel(123456789L));
assertEquals("1.2k", lm.formatLevel(1234L));
assertEquals("123.5G", lm.formatLevel(123456789352L));
assertEquals("1.2T", lm.formatLevel(1234567893524L));
assertEquals("12345.7T", lm.formatLevel(12345678345345349L));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getTopTen(org.bukkit.World, int)}.
*/
@Test
public void testGetTopTenEmpty() {
Map<UUID, Long> tt = lm.getTopTen(world, Level.TEN);
assertTrue(tt.isEmpty());
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getTopTen(org.bukkit.World, int)}.
*/
@Test
public void testGetTopTen() {
testLoadTopTens();
Map<UUID, Long> tt = lm.getTopTen(world, Level.TEN);
assertFalse(tt.isEmpty());
assertEquals(1, tt.size());
assertEquals(1, lm.getTopTen(world, 1).size());
}
/**
* Test method for {@link world.bentobox.level.LevelsManager#getTopTen(org.bukkit.World, int)}.
*/ */
@Test @After
public void testGetTopTenNoOwners() { public void tearDown() throws Exception {
when(im.hasIsland(eq(world), any(UUID.class))).thenReturn(false); deleteAll(new File("database"));
testLoadTopTens(); User.clearUsers();
Map<UUID, Long> tt = lm.getTopTen(world, Level.TEN); Mockito.framework().clearInlineMocks();
assertTrue(tt.isEmpty());
} }
/** private static void deleteAll(File file) throws IOException {
* Test method for if (file.exists()) {
* {@link world.bentobox.level.LevelsManager#hasTopTenPerm(org.bukkit.World, java.util.UUID)}. Files.walk(file.toPath()).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
*/
@Test
public void testHasTopTenPerm() {
assertTrue(lm.hasTopTenPerm(world, uuid));
} }
}
/** /**
* Test method for {@link world.bentobox.level.LevelsManager#loadTopTens()}. * Test method for
*/ * {@link world.bentobox.level.LevelsManager#calculateLevel(UUID, world.bentobox.bentobox.database.objects.Island)}.
@Test */
public void testLoadTopTens() { @Test
ArgumentCaptor<Runnable> task = ArgumentCaptor.forClass(Runnable.class); public void testCalculateLevel() {
lm.loadTopTens(); Results results = new Results();
PowerMockito.verifyStatic(Bukkit.class); // 1 results.setLevel(10000);
Bukkit.getScheduler(); results.setInitialLevel(3);
verify(scheduler).runTaskAsynchronously(eq(plugin), task.capture()); lm.calculateLevel(uuid, island);
task.getValue().run(); // Complete the pipelined completable future
verify(addon).log("Generating rankings"); cf.complete(results);
verify(addon).log("Generated rankings for bskyblock-world");
assertEquals(10000L, lm.getLevelsData(island).getLevel());
// Map<UUID, Long> tt = lm.getTopTen(world, 10);
// assertEquals(1, tt.size());
// assertTrue(tt.get(uuid) == 10000);
assertEquals(10000L, lm.getIslandMaxLevel(world, uuid));
results.setLevel(5000);
lm.calculateLevel(uuid, island);
// Complete the pipelined completable future
cf.complete(results);
assertEquals(5000L, lm.getLevelsData(island).getLevel());
// Still should be 10000
assertEquals(10000L, lm.getIslandMaxLevel(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getInitialLevel(world.bentobox.bentobox.database.objects.Island)}.
*/
@Test
public void testGetInitialLevel() {
assertEquals(0, lm.getInitialLevel(island));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getIslandLevel(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testGetIslandLevel() {
assertEquals(-5, lm.getIslandLevel(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getPointsToNextString(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testGetPointsToNextString() {
// No island player
assertEquals("", lm.getPointsToNextString(world, UUID.randomUUID()));
// Player has island
assertEquals("0", lm.getPointsToNextString(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getIslandLevelString(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testGetIslandLevelString() {
assertEquals("-5", lm.getIslandLevelString(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getLevelsData(java.util.UUID)}.
*/
@Test
public void testGetLevelsData() {
assertEquals(levelsData, lm.getLevelsData(island));
}
/**
* Test method for {@link world.bentobox.level.LevelsManager#formatLevel(long)}.
*/
@Test
public void testFormatLevel() {
assertEquals("123456789", lm.formatLevel(123456789L));
when(settings.isShorthand()).thenReturn(true);
assertEquals("123.5M", lm.formatLevel(123456789L));
assertEquals("1.2k", lm.formatLevel(1234L));
assertEquals("123.5G", lm.formatLevel(123456789352L));
assertEquals("1.2T", lm.formatLevel(1234567893524L));
assertEquals("12345.7T", lm.formatLevel(12345678345345349L));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getTopTen(org.bukkit.World, int)}.
*/
@Test
public void testGetTopTenEmpty() {
Map<String, Long> tt = lm.getTopTen(world, Level.TEN);
assertTrue(tt.isEmpty());
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getTopTen(org.bukkit.World, int)}.
*/
@Test
public void testGetTopTen() {
testLoadTopTens();
Map<String, Long> tt = lm.getTopTen(world, Level.TEN);
assertFalse(tt.isEmpty());
assertEquals(1, tt.size());
assertEquals(1, lm.getTopTen(world, 1).size());
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#hasTopTenPerm(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testHasTopTenPerm() {
assertTrue(lm.hasTopTenPerm(world, uuid));
}
/**
* Test method for {@link world.bentobox.level.LevelsManager#loadTopTens()}.
*/
@Test
public void testLoadTopTens() {
ArgumentCaptor<Runnable> task = ArgumentCaptor.forClass(Runnable.class);
lm.loadTopTens();
PowerMockito.verifyStatic(Bukkit.class); // 1
Bukkit.getScheduler();
verify(scheduler).runTaskAsynchronously(eq(plugin), task.capture());
task.getValue().run();
verify(addon).log("Generating rankings");
verify(addon).log("Generated rankings for bskyblock-world");
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#removeEntry(org.bukkit.World, java.util.UUID)}.
*/
@Test
public void testRemoveEntry() {
testLoadTopTens();
Map<String, Long> tt = lm.getTopTen(world, Level.TEN);
assertTrue(tt.containsKey(uuid.toString()));
lm.removeEntry(world, uuid.toString());
tt = lm.getTopTen(world, Level.TEN);
assertFalse(tt.containsKey(uuid.toString()));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#setInitialIslandLevel(world.bentobox.bentobox.database.objects.Island, long)}.
*/
@Test
public void testSetInitialIslandLevel() {
lm.setInitialIslandLevel(island, Level.TEN);
assertEquals(Level.TEN, lm.getInitialLevel(island));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#setIslandLevel(org.bukkit.World, java.util.UUID, long)}.
*/
@Test
public void testSetIslandLevel() {
lm.setIslandLevel(world, uuid, 1234);
assertEquals(1234, lm.getIslandLevel(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getRank(World, UUID)}
*/
@Test
public void testGetRank() {
lm.createAndCleanRankings(world);
Map<World, TopTenData> ttl = lm.getTopTenLists();
Map<String, Long> tt = ttl.get(world).getTopTen();
for (long i = 100; i < 150; i++) {
tt.put(UUID.randomUUID().toString(), i);
} }
// Put island as lowest rank
/** tt.put(uuid.toString(), 10L);
* Test method for assertEquals(51, lm.getRank(world, uuid));
* {@link world.bentobox.level.LevelsManager#removeEntry(org.bukkit.World, java.util.UUID)}. // Put island as highest rank
*/ tt.put(uuid.toString(), 1000L);
@Test assertEquals(1, lm.getRank(world, uuid));
public void testRemoveEntry() { // Unknown UUID - lowest rank + 1
testLoadTopTens(); assertEquals(52, lm.getRank(world, UUID.randomUUID()));
Map<UUID, Long> tt = lm.getTopTen(world, Level.TEN); }
assertTrue(tt.containsKey(uuid));
lm.removeEntry(world, uuid);
tt = lm.getTopTen(world, Level.TEN);
assertFalse(tt.containsKey(uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#setInitialIslandLevel(world.bentobox.bentobox.database.objects.Island, long)}.
*/
@Test
public void testSetInitialIslandLevel() {
lm.setInitialIslandLevel(island, Level.TEN);
assertEquals(Level.TEN, lm.getInitialLevel(island));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#setIslandLevel(org.bukkit.World, java.util.UUID, long)}.
*/
@Test
public void testSetIslandLevel() {
lm.setIslandLevel(world, uuid, 1234);
assertEquals(1234, lm.getIslandLevel(world, uuid));
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getRank(World, UUID)}
*/
@Test
public void testGetRank() {
lm.createAndCleanRankings(world);
Map<World, TopTenData> ttl = lm.getTopTenLists();
Map<UUID, Long> tt = ttl.get(world).getTopTen();
for (long i = 100; i < 150; i++) {
tt.put(UUID.randomUUID(), i);
}
// Put player as lowest rank
tt.put(uuid, 10L);
assertEquals(51, lm.getRank(world, uuid));
// Put player as highest rank
tt.put(uuid, 1000L);
assertEquals(1, lm.getRank(world, uuid));
// Unknown UUID - lowest rank + 1
assertEquals(52, lm.getRank(world, UUID.randomUUID()));
}
} }

View File

@ -3,6 +3,7 @@ package world.bentobox.level;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@ -10,9 +11,10 @@ import static org.mockito.Mockito.when;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -44,7 +46,7 @@ import world.bentobox.level.objects.IslandLevels;
* *
*/ */
@RunWith(PowerMockRunner.class) @RunWith(PowerMockRunner.class)
@PrepareForTest({BentoBox.class}) @PrepareForTest({ BentoBox.class })
public class PlaceholderManagerTest { public class PlaceholderManagerTest {
@Mock @Mock
@ -54,7 +56,7 @@ public class PlaceholderManagerTest {
@Mock @Mock
private BentoBox plugin; private BentoBox plugin;
private PlaceholderManager pm; private PlaceholderManager phm;
@Mock @Mock
private PlaceholdersManager bpm; private PlaceholdersManager bpm;
@Mock @Mock
@ -67,13 +69,24 @@ public class PlaceholderManagerTest {
private Island island; private Island island;
@Mock @Mock
private User user; private User user;
private Map<UUID, String> names = new HashMap<>(); private static final Map<UUID, String> names = new LinkedHashMap<>();
private static final List<String> NAMES = List.of("tasty", "bento", "fred", "bonne", "cyprien", "mael", "joe", "horacio", "steph", "vicky"); static {
private Map<UUID, Island> islands = new HashMap<>(); names.put(UUID.randomUUID(), "tasty");
private Map<UUID, Long> map = new HashMap<>(); names.put(UUID.randomUUID(), "bento");
names.put(UUID.randomUUID(), "fred");
names.put(UUID.randomUUID(), "bonne");
names.put(UUID.randomUUID(), "cyprien");
names.put(UUID.randomUUID(), "mael");
names.put(UUID.randomUUID(), "joe");
names.put(UUID.randomUUID(), "horacio");
names.put(UUID.randomUUID(), "steph");
names.put(UUID.randomUUID(), "vicky");
}
private Map<String, Island> islands = new HashMap<>();
private Map<String, Long> map = new HashMap<>();
private @NonNull IslandLevels data; private @NonNull IslandLevels data;
@Mock @Mock
private PlayersManager players; private PlayersManager pm;
/** /**
* @throws java.lang.Exception * @throws java.lang.Exception
@ -83,29 +96,31 @@ public class PlaceholderManagerTest {
when(addon.getPlugin()).thenReturn(plugin); when(addon.getPlugin()).thenReturn(plugin);
// Users // Users
when(addon.getPlayers()).thenReturn(players); when(addon.getPlayers()).thenReturn(pm);
// Users // Users
when(user.getWorld()).thenReturn(world); when(user.getWorld()).thenReturn(world);
when(user.getLocation()).thenReturn(mock(Location.class)); when(user.getLocation()).thenReturn(mock(Location.class));
for (int i = 0; i < Level.TEN; i++) { int i = 0;
UUID uuid = UUID.randomUUID(); for (Entry<UUID, String> n : names.entrySet()) {
names.put(uuid, NAMES.get(i)); UUID uuid = UUID.randomUUID(); // Random island ID
map.put(uuid, (long)(100 - i)); map.put(uuid.toString(), (long)(100 - i++)); // level
Island is = new Island(); Island is = new Island();
is.setOwner(uuid); is.setUniqueId(uuid.toString());
is.setName(NAMES.get(i) + "'s island"); is.setOwner(n.getKey());
islands.put(uuid, is); is.setName(n.getValue() + "'s island");
islands.put(uuid.toString(), is);
} }
// Sort // Sort
map = map.entrySet().stream() map = map.entrySet().stream()
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) .sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
.collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new)); .collect(Collectors.toMap( Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
when(players.getName(any())).thenAnswer((Answer<String>) invocation -> names.getOrDefault(invocation.getArgument(0, UUID.class), "unknown")); when(pm.getName(any())).thenAnswer((Answer<String>) invocation -> names.getOrDefault(invocation.getArgument(0, UUID.class), "unknown"));
Map<UUID, Integer> members = new HashMap<>(); Map<UUID, Integer> members = new HashMap<>();
map.forEach((uuid, l) -> members.put(uuid, RanksManager.MEMBER_RANK)); names.forEach((uuid, l) -> members.put(uuid, RanksManager.MEMBER_RANK));
islands.values().forEach(i -> i.setMembers(members)); islands.values().forEach(is -> is.setMembers(members));
// Placeholders manager for plugin // Placeholders manager for plugin
@ -120,7 +135,8 @@ public class PlaceholderManagerTest {
// Islands // Islands
when(im.getIsland(any(World.class), any(User.class))).thenReturn(island); when(im.getIsland(any(World.class), any(User.class))).thenReturn(island);
when(im.getIslandAt(any(Location.class))).thenReturn(Optional.of(island)); when(im.getIslandAt(any(Location.class))).thenReturn(Optional.of(island));
when(im.getIsland(any(World.class), any(UUID.class))).thenAnswer((Answer<Island>) invocation -> islands.get(invocation.getArgument(1, UUID.class))); when(im.getIslandById(anyString())).thenAnswer((Answer<Optional<Island>>) invocation -> Optional.of(islands.get(invocation.getArgument(0, String.class))));
when(im.getIslands(any(), any(UUID.class))).thenReturn(new HashSet<>(islands.values()));
when(addon.getIslands()).thenReturn(im); when(addon.getIslands()).thenReturn(im);
// Levels Manager // Levels Manager
@ -136,127 +152,134 @@ public class PlaceholderManagerTest {
when(lm.getLevelsData(island)).thenReturn(data); when(lm.getLevelsData(island)).thenReturn(data);
when(addon.getManager()).thenReturn(lm); when(addon.getManager()).thenReturn(lm);
pm = new PlaceholderManager(addon); phm = new PlaceholderManager(addon);
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#PlaceholderManager(world.bentobox.level.Level)}. * Test method for
* {@link world.bentobox.level.PlaceholderManager#PlaceholderManager(world.bentobox.level.Level)}.
*/ */
@Test @Test
public void testPlaceholderManager() { public void testPlaceholderManager() {
verify(addon).getPlugin(); verify(addon).getPlugin();
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#registerPlaceholders(world.bentobox.bentobox.api.addons.GameModeAddon)}. * Test method for
* {@link world.bentobox.level.PlaceholderManager#registerPlaceholders(world.bentobox.bentobox.api.addons.GameModeAddon)}.
*/ */
@Test @Test
public void testRegisterPlaceholders() { public void testRegisterPlaceholders() {
pm.registerPlaceholders(gm); phm.registerPlaceholders(gm);
// Island Level // Island Level
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_island_level"), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_island_level"), any());
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_island_level_raw"), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_island_level_raw"), any());
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_island_total_points"), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_island_total_points"), any());
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_points_to_next_level"), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_points_to_next_level"), any());
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_island_level_max"), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_island_level_max"), any());
// Visited Island Level // Visited Island Level
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_visited_island_level"), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_visited_island_level"), any());
// Register Top Ten Placeholders // Register Top Ten Placeholders
for (int i = 1; i < 11; i++) { for (int i = 1; i < 11; i++) {
// Name // Name
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_top_name_" + i), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_top_name_" + i), any());
// Island Name // Island Name
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_top_island_name_" + i), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_top_island_name_" + i), any());
// Members // Members
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_top_members_" + i), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_top_members_" + i), any());
// Level // Level
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_top_value_" + i), any()); verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_top_value_" + i), any());
} }
// Personal rank
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_rank_value"), any());
// Personal rank
verify(bpm).registerPlaceholder(eq(addon), eq("aoneblock_rank_value"), any());
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#getRankName(org.bukkit.World, int)}. * Test method for
* {@link world.bentobox.level.PlaceholderManager#getRankName(org.bukkit.World, int)}.
*/ */
@Test @Test
public void testGetRankName() { public void testGetRankName() {
// Test extremes // Test extremes
assertEquals("tasty", pm.getRankName(world, 0)); assertEquals("tasty", phm.getRankName(world, 0));
assertEquals("vicky", pm.getRankName(world, 100)); assertEquals("vicky", phm.getRankName(world, 100));
// Test the ranks // Test the ranks
int rank = 1; int rank = 1;
for (String name : NAMES) { for (String name : names.values()) {
assertEquals(name, pm.getRankName(world, rank++)); assertEquals(name, phm.getRankName(world, rank++));
} }
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#getRankIslandName(org.bukkit.World, int)}. * Test method for
* {@link world.bentobox.level.PlaceholderManager#getRankIslandName(org.bukkit.World, int)}.
*/ */
@Test @Test
public void testGetRankIslandName() { public void testGetRankIslandName() {
// Test extremes // Test extremes
assertEquals("tasty's island", pm.getRankIslandName(world, 0)); assertEquals("tasty's island", phm.getRankIslandName(world, 0));
assertEquals("vicky's island", pm.getRankIslandName(world, 100)); assertEquals("vicky's island", phm.getRankIslandName(world, 100));
// Test the ranks // Test the ranks
int rank = 1; int rank = 1;
for (String name : NAMES) { for (String name : names.values()) {
assertEquals(name + "'s island", pm.getRankIslandName(world, rank++)); assertEquals(name + "'s island", phm.getRankIslandName(world, rank++));
} }
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#getRankMembers(org.bukkit.World, int)}. * Test method for
* {@link world.bentobox.level.PlaceholderManager#getRankMembers(org.bukkit.World, int)}.
*/ */
@Test @Test
public void testGetRankMembers() { public void testGetRankMembers() {
// Test extremes // Test extremes
check(1, pm.getRankMembers(world, 0)); check(1, phm.getRankMembers(world, 0));
check(2, pm.getRankMembers(world, 100)); check(2, phm.getRankMembers(world, 100));
// Test the ranks // Test the ranks
for (int rank = 1; rank < 11; rank++) { for (int rank = 1; rank < 11; rank++) {
check(3, pm.getRankMembers(world, rank)); check(3, phm.getRankMembers(world, rank));
} }
} }
void check(int indicator, String list) { void check(int indicator, String list) {
for (String n : NAMES) { for (String n : names.values()) {
assertTrue(n + " is missing for twst " + indicator, list.contains(n)); assertTrue(n + " is missing for test " + indicator, list.contains(n));
} }
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#getRankLevel(org.bukkit.World, int)}. * Test method for
* {@link world.bentobox.level.PlaceholderManager#getRankLevel(org.bukkit.World, int)}.
*/ */
@Test @Test
public void testGetRankLevel() { public void testGetRankLevel() {
// Test extremes // Test extremes
assertEquals("100", pm.getRankLevel(world, 0)); assertEquals("100", phm.getRankLevel(world, 0));
assertEquals("91", pm.getRankLevel(world, 100)); assertEquals("91", phm.getRankLevel(world, 100));
// Test the ranks // Test the ranks
for (int rank = 1; rank < 11; rank++) { for (int rank = 1; rank < 11; rank++) {
assertEquals(String.valueOf(101 - rank), pm.getRankLevel(world, rank)); assertEquals(String.valueOf(101 - rank), phm.getRankLevel(world, rank));
} }
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#getVisitedIslandLevel(world.bentobox.bentobox.api.addons.GameModeAddon, world.bentobox.bentobox.api.user.User)}. * Test method for
* {@link world.bentobox.level.PlaceholderManager#getVisitedIslandLevel(world.bentobox.bentobox.api.addons.GameModeAddon, world.bentobox.bentobox.api.user.User)}.
*/ */
@Test @Test
public void testGetVisitedIslandLevelNullUser() { public void testGetVisitedIslandLevelNullUser() {
assertEquals("", pm.getVisitedIslandLevel(gm, null)); assertEquals("", phm.getVisitedIslandLevel(gm, null));
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#getVisitedIslandLevel(world.bentobox.bentobox.api.addons.GameModeAddon, world.bentobox.bentobox.api.user.User)}. * Test method for {@link world.bentobox.level.PlaceholderManager#getVisitedIslandLevel(world.bentobox.bentobox.api.addons.GameModeAddon, world.bentobox.bentobox.api.user.User)}.
*/ */
@ -264,26 +287,27 @@ public class PlaceholderManagerTest {
public void testGetVisitedIslandLevelUserNotInWorld() { public void testGetVisitedIslandLevelUserNotInWorld() {
// Another world // Another world
when(user.getWorld()).thenReturn(mock(World.class)); when(user.getWorld()).thenReturn(mock(World.class));
assertEquals("", pm.getVisitedIslandLevel(gm, user)); assertEquals("", phm.getVisitedIslandLevel(gm, user));
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#getVisitedIslandLevel(world.bentobox.bentobox.api.addons.GameModeAddon, world.bentobox.bentobox.api.user.User)}. * Test method for
* {@link world.bentobox.level.PlaceholderManager#getVisitedIslandLevel(world.bentobox.bentobox.api.addons.GameModeAddon, world.bentobox.bentobox.api.user.User)}.
*/ */
@Test @Test
public void testGetVisitedIslandLevel() { public void testGetVisitedIslandLevel() {
assertEquals("1234567", pm.getVisitedIslandLevel(gm, user)); assertEquals("1234567", phm.getVisitedIslandLevel(gm, user));
} }
/** /**
* Test method for {@link world.bentobox.level.PlaceholderManager#getVisitedIslandLevel(world.bentobox.bentobox.api.addons.GameModeAddon, world.bentobox.bentobox.api.user.User)}. * Test method for {@link world.bentobox.level.PlaceholderManager#getVisitedIslandLevel(world.bentobox.bentobox.api.addons.GameModeAddon, world.bentobox.bentobox.api.user.User)}.
*/ */
@Test @Test
public void testGetVisitedIslandLevelNoIsland() { public void testGetVisitedIslandLevelNoIsland() {
when(im.getIslandAt(any(Location.class))).thenReturn(Optional.empty()); when(im.getIslandAt(any(Location.class))).thenReturn(Optional.empty());
assertEquals("0", pm.getVisitedIslandLevel(gm, user)); assertEquals("0", phm.getVisitedIslandLevel(gm, user));
} }

View File

@ -52,132 +52,132 @@ import world.bentobox.level.objects.TopTenData;
@PrepareForTest({ Bukkit.class, BentoBox.class }) @PrepareForTest({ Bukkit.class, BentoBox.class })
public class AdminStatsCommandTest { public class AdminStatsCommandTest {
@Mock @Mock
private CompositeCommand ic; private CompositeCommand ic;
private UUID uuid; private UUID uuid;
@Mock @Mock
private User user; private User user;
@Mock @Mock
private IslandsManager im; private IslandsManager im;
@Mock @Mock
private Island island; private Island island;
@Mock @Mock
private Level addon; private Level addon;
@Mock @Mock
private World world; private World world;
@Mock @Mock
private IslandWorldManager iwm; private IslandWorldManager iwm;
@Mock @Mock
private GameModeAddon gameModeAddon; private GameModeAddon gameModeAddon;
@Mock @Mock
private Player p; private Player p;
@Mock @Mock
private LocalesManager lm; private LocalesManager lm;
@Mock @Mock
private PlayersManager pm; private PlayersManager pm;
private AdminStatsCommand asc; private AdminStatsCommand asc;
private TopTenData ttd; private TopTenData ttd;
@Mock @Mock
private LevelsManager manager; private LevelsManager manager;
@Mock @Mock
private Server server; private Server server;
@Before @Before
public void setUp() { public void setUp() {
// Set up plugin // Set up plugin
BentoBox plugin = mock(BentoBox.class); BentoBox plugin = mock(BentoBox.class);
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
User.setPlugin(plugin); User.setPlugin(plugin);
when(addon.getPlugin()).thenReturn(plugin); when(addon.getPlugin()).thenReturn(plugin);
// Addon // Addon
when(ic.getAddon()).thenReturn(addon); when(ic.getAddon()).thenReturn(addon);
when(ic.getPermissionPrefix()).thenReturn("bskyblock."); when(ic.getPermissionPrefix()).thenReturn("bskyblock.");
when(ic.getLabel()).thenReturn("island"); when(ic.getLabel()).thenReturn("island");
when(ic.getTopLabel()).thenReturn("island"); when(ic.getTopLabel()).thenReturn("island");
when(ic.getWorld()).thenReturn(world); when(ic.getWorld()).thenReturn(world);
when(ic.getTopLabel()).thenReturn("bsb"); when(ic.getTopLabel()).thenReturn("bsb");
// IWM friendly name // IWM friendly name
when(plugin.getIWM()).thenReturn(iwm); when(plugin.getIWM()).thenReturn(iwm);
when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock"); when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock");
// World // World
when(world.toString()).thenReturn("world"); when(world.toString()).thenReturn("world");
when(world.getName()).thenReturn("BSkyBlock_world"); when(world.getName()).thenReturn("BSkyBlock_world");
// Player manager // Player manager
when(plugin.getPlayers()).thenReturn(pm); when(plugin.getPlayers()).thenReturn(pm);
when(pm.getUser(anyString())).thenReturn(user); when(pm.getUser(anyString())).thenReturn(user);
// topTen // topTen
when(addon.getManager()).thenReturn(manager); when(addon.getManager()).thenReturn(manager);
// User // User
uuid = UUID.randomUUID(); uuid = UUID.randomUUID();
when(user.getUniqueId()).thenReturn(uuid); when(user.getUniqueId()).thenReturn(uuid);
when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class)); when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class));
// Bukkit // Bukkit
PowerMockito.mockStatic(Bukkit.class); PowerMockito.mockStatic(Bukkit.class);
when(Bukkit.getServer()).thenReturn(server); when(Bukkit.getServer()).thenReturn(server);
// Mock item factory (for itemstacks) // Mock item factory (for itemstacks)
ItemFactory itemFactory = mock(ItemFactory.class); ItemFactory itemFactory = mock(ItemFactory.class);
ItemMeta itemMeta = mock(ItemMeta.class); ItemMeta itemMeta = mock(ItemMeta.class);
when(itemFactory.getItemMeta(any())).thenReturn(itemMeta); when(itemFactory.getItemMeta(any())).thenReturn(itemMeta);
when(server.getItemFactory()).thenReturn(itemFactory); when(server.getItemFactory()).thenReturn(itemFactory);
when(Bukkit.getItemFactory()).thenReturn(itemFactory); when(Bukkit.getItemFactory()).thenReturn(itemFactory);
// Top ten // Top ten
ttd = new TopTenData(world); ttd = new TopTenData(world);
Map<UUID, Long> topten = new HashMap<>(); Map<String, Long> topten = new HashMap<>();
Random r = new Random(); Random r = new Random();
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
topten.put(UUID.randomUUID(), r.nextLong(20000)); topten.put(UUID.randomUUID().toString(), r.nextLong(20000));
}
ttd.setTopTen(topten);
asc = new AdminStatsCommand(addon, ic);
} }
ttd.setTopTen(topten);
asc = new AdminStatsCommand(addon, ic);
}
@After @After
public void tearDown() { public void tearDown() {
User.clearUsers(); User.clearUsers();
} }
/** /**
* Test method for * Test method for
* {@link world.bentobox.level.commands.AdminStatsCommand#setup()}. * {@link world.bentobox.level.commands.AdminStatsCommand#setup()}.
*/ */
@Test @Test
public void testSetup() { public void testSetup() {
assertEquals("bskyblock.admin.stats", asc.getPermission()); assertEquals("bskyblock.admin.stats", asc.getPermission());
assertFalse(asc.isOnlyPlayer()); assertFalse(asc.isOnlyPlayer());
assertEquals("admin.stats.description", asc.getDescription()); assertEquals("admin.stats.description", asc.getDescription());
} }
/** /**
* Test method for * Test method for
* {@link world.bentobox.level.commands.AdminStatsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. * {@link world.bentobox.level.commands.AdminStatsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/ */
@Test @Test
public void testExecuteUserStringListOfString() { public void testExecuteUserStringListOfString() {
assertFalse(asc.execute(user, "", List.of())); assertFalse(asc.execute(user, "", List.of()));
verify(user).sendMessage("admin.stats.title"); verify(user).sendMessage("admin.stats.title");
verify(user).sendMessage("admin.stats.no-data"); verify(user).sendMessage("admin.stats.no-data");
} }
/** /**
* Test method for * Test method for
* {@link world.bentobox.level.commands.AdminStatsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. * {@link world.bentobox.level.commands.AdminStatsCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/ */
@Test @Test
public void testExecuteUserStringListOfStringLevels() { public void testExecuteUserStringListOfStringLevels() {
Map<World, TopTenData> map = new HashMap<>(); Map<World, TopTenData> map = new HashMap<>();
map.put(world, ttd); map.put(world, ttd);
when(manager.getTopTenLists()).thenReturn(map); when(manager.getTopTenLists()).thenReturn(map);
assertTrue(asc.execute(user, "", List.of())); assertTrue(asc.execute(user, "", List.of()));
verify(user).sendMessage("admin.stats.title"); verify(user).sendMessage("admin.stats.title");
verify(user, never()).sendMessage("admin.stats.no-data"); verify(user, never()).sendMessage("admin.stats.no-data");
} }
} }

View File

@ -5,12 +5,12 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import java.util.Collections; import java.util.Collections;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -51,122 +51,130 @@ import world.bentobox.level.objects.TopTenData;
@PrepareForTest({ Bukkit.class, BentoBox.class }) @PrepareForTest({ Bukkit.class, BentoBox.class })
public class AdminTopRemoveCommandTest { public class AdminTopRemoveCommandTest {
@Mock @Mock
private CompositeCommand ic; private CompositeCommand ic;
private UUID uuid; private UUID uuid;
@Mock @Mock
private User user; private User user;
@Mock @Mock
private IslandsManager im; private IslandsManager im;
@Mock @Mock
private Island island; private Island island;
@Mock @Mock
private Level addon; private Level addon;
@Mock @Mock
private World world; private World world;
@Mock @Mock
private IslandWorldManager iwm; private IslandWorldManager iwm;
@Mock @Mock
private GameModeAddon gameModeAddon; private GameModeAddon gameModeAddon;
@Mock @Mock
private Player p; private Player p;
@Mock @Mock
private LocalesManager lm; private LocalesManager lm;
@Mock @Mock
private PlayersManager pm; private PlayersManager pm;
private AdminTopRemoveCommand atrc; private AdminTopRemoveCommand atrc;
@Mock @Mock
private TopTenData ttd; private TopTenData ttd;
@Mock @Mock
private LevelsManager manager; private LevelsManager manager;
@Mock @Mock
private Server server; private Server server;
@Before @Before
public void setUp() { public void setUp() {
// Set up plugin // Set up plugin
BentoBox plugin = mock(BentoBox.class); BentoBox plugin = mock(BentoBox.class);
Whitebox.setInternalState(BentoBox.class, "instance", plugin); Whitebox.setInternalState(BentoBox.class, "instance", plugin);
User.setPlugin(plugin); User.setPlugin(plugin);
// Addon
when(ic.getAddon()).thenReturn(addon);
when(ic.getPermissionPrefix()).thenReturn("bskyblock.");
when(ic.getLabel()).thenReturn("island");
when(ic.getTopLabel()).thenReturn("island");
when(ic.getWorld()).thenReturn(world);
when(ic.getTopLabel()).thenReturn("bsb");
// IWM friendly name // Addon
when(plugin.getIWM()).thenReturn(iwm); when(ic.getAddon()).thenReturn(addon);
when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock"); when(ic.getPermissionPrefix()).thenReturn("bskyblock.");
when(ic.getLabel()).thenReturn("island");
when(ic.getTopLabel()).thenReturn("island");
when(ic.getWorld()).thenReturn(world);
when(ic.getTopLabel()).thenReturn("bsb");
// World // IWM friendly name
when(world.toString()).thenReturn("world"); when(plugin.getIWM()).thenReturn(iwm);
when(world.getName()).thenReturn("BSkyBlock_world"); when(iwm.getFriendlyName(any())).thenReturn("BSkyBlock");
// Player manager // World
when(plugin.getPlayers()).thenReturn(pm); when(world.toString()).thenReturn("world");
when(pm.getUser(anyString())).thenReturn(user); when(world.getName()).thenReturn("BSkyBlock_world");
// topTen
when(addon.getManager()).thenReturn(manager);
// User
uuid = UUID.randomUUID();
when(user.getUniqueId()).thenReturn(uuid);
when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class));
// Bukkit // Player manager
PowerMockito.mockStatic(Bukkit.class); when(plugin.getPlayers()).thenReturn(pm);
when(Bukkit.getServer()).thenReturn(server); when(pm.getUser(anyString())).thenReturn(user);
// Mock item factory (for itemstacks) // topTen
ItemFactory itemFactory = mock(ItemFactory.class); when(addon.getManager()).thenReturn(manager);
ItemMeta itemMeta = mock(ItemMeta.class); // User
when(itemFactory.getItemMeta(any())).thenReturn(itemMeta); uuid = UUID.randomUUID();
when(server.getItemFactory()).thenReturn(itemFactory); when(user.getUniqueId()).thenReturn(uuid);
when(Bukkit.getItemFactory()).thenReturn(itemFactory); when(user.getTranslation(any())).thenAnswer(invocation -> invocation.getArgument(0, String.class));
// Island
when(island.getUniqueId()).thenReturn(uuid.toString());
when(island.getOwner()).thenReturn(uuid);
// Island Manager
when(plugin.getIslands()).thenReturn(im);
when(im.getIslands(any(), any(User.class))).thenReturn(Set.of(island));
when(im.getIslands(any(), any(UUID.class))).thenReturn(Set.of(island));
atrc = new AdminTopRemoveCommand(addon, ic); // Bukkit
} PowerMockito.mockStatic(Bukkit.class);
when(Bukkit.getServer()).thenReturn(server);
// Mock item factory (for itemstacks)
ItemFactory itemFactory = mock(ItemFactory.class);
ItemMeta itemMeta = mock(ItemMeta.class);
when(itemFactory.getItemMeta(any())).thenReturn(itemMeta);
when(server.getItemFactory()).thenReturn(itemFactory);
when(Bukkit.getItemFactory()).thenReturn(itemFactory);
@After atrc = new AdminTopRemoveCommand(addon, ic);
public void tearDown() { }
User.clearUsers();
}
/** @After
* Test method for public void tearDown() {
* {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#AdminTopRemoveCommand(world.bentobox.level.Level, world.bentobox.bentobox.api.commands.CompositeCommand)}. User.clearUsers();
*/ }
@Test
public void testAdminTopRemoveCommand() {
assertEquals("remove", atrc.getLabel());
assertEquals("delete", atrc.getAliases().get(0));
}
/** /**
* Test method for * Test method for
* {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#setup()}. * {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#AdminTopRemoveCommand(world.bentobox.level.Level, world.bentobox.bentobox.api.commands.CompositeCommand)}.
*/ */
@Test @Test
public void testSetup() { public void testAdminTopRemoveCommand() {
assertEquals("bskyblock.admin.top.remove", atrc.getPermission()); assertEquals("remove", atrc.getLabel());
assertEquals("admin.top.remove.parameters", atrc.getParameters()); assertEquals("delete", atrc.getAliases().get(0));
assertEquals("admin.top.remove.description", atrc.getDescription()); }
assertFalse(atrc.isOnlyPlayer());
} /**
* Test method for
* {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#setup()}.
*/
@Test
public void testSetup() {
assertEquals("bskyblock.admin.top.remove", atrc.getPermission());
assertEquals("admin.top.remove.parameters", atrc.getParameters());
assertEquals("admin.top.remove.description", atrc.getDescription());
assertFalse(atrc.isOnlyPlayer());
/** }
* Test method for
* {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testCanExecuteWrongArgs() {
assertFalse(atrc.canExecute(user, "delete", Collections.emptyList()));
verify(user).sendMessage("commands.help.header", TextVariables.LABEL, "BSkyBlock");
}
/** /**
* Test method for
* {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/
@Test
public void testCanExecuteWrongArgs() {
assertFalse(atrc.canExecute(user, "delete", Collections.emptyList()));
verify(user).sendMessage("commands.help.header", TextVariables.LABEL, "BSkyBlock");
}
/**
* Test method for {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. * Test method for {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/ */
@Test @Test
@ -176,25 +184,25 @@ public class AdminTopRemoveCommandTest {
verify(user).sendMessage("general.errors.unknown-player", TextVariables.NAME, "tastybento"); verify(user).sendMessage("general.errors.unknown-player", TextVariables.NAME, "tastybento");
} }
/** /**
* Test method for * Test method for
* {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. * {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#canExecute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/ */
@Test @Test
public void testCanExecuteKnown() { public void testCanExecuteKnown() {
assertTrue(atrc.canExecute(user, "delete", Collections.singletonList("tastybento"))); assertTrue(atrc.canExecute(user, "delete", Collections.singletonList("tastybento")));
} }
/** /**
* Test method for * Test method for
* {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}. * {@link world.bentobox.level.commands.admin.AdminTopRemoveCommand#execute(world.bentobox.bentobox.api.user.User, java.lang.String, java.util.List)}.
*/ */
@Test @Test
public void testExecuteUserStringListOfString() { public void testExecuteUserStringListOfString() {
testCanExecuteKnown(); testCanExecuteKnown();
assertTrue(atrc.execute(user, "delete", Collections.singletonList("tastybento"))); assertTrue(atrc.execute(user, "delete", Collections.singletonList("tastybento")));
verify(manager).removeEntry(any(World.class), eq(uuid)); verify(manager).removeEntry(world, uuid.toString());
verify(user).sendMessage("general.success"); verify(user).sendMessage("general.success");
} }
} }