diff --git a/pom.xml b/pom.xml index 4adb4dd..a24e216 100644 --- a/pom.xml +++ b/pom.xml @@ -59,7 +59,7 @@ 2.0.9 1.20.4-R0.1-SNAPSHOT - 2.0.0-SNAPSHOT + 2.4.0-SNAPSHOT 1.12.0 @@ -71,7 +71,7 @@ -LOCAL - 2.13.0 + 2.14.0 BentoBoxWorld_Level bentobox-world https://sonarcloud.io diff --git a/src/main/java/world/bentobox/level/LevelsManager.java b/src/main/java/world/bentobox/level/LevelsManager.java index f0680c5..46d47b3 100644 --- a/src/main/java/world/bentobox/level/LevelsManager.java +++ b/src/main/java/world/bentobox/level/LevelsManager.java @@ -39,12 +39,12 @@ public class LevelsManager { private static final TreeMap LEVELS; private static final BigInteger THOUSAND = BigInteger.valueOf(1000); static { - LEVELS = new TreeMap<>(); + LEVELS = new TreeMap<>(); - LEVELS.put(THOUSAND, "k"); - LEVELS.put(THOUSAND.pow(2), "M"); - LEVELS.put(THOUSAND.pow(3), "G"); - LEVELS.put(THOUSAND.pow(4), "T"); + LEVELS.put(THOUSAND, "k"); + LEVELS.put(THOUSAND.pow(2), "M"); + LEVELS.put(THOUSAND.pow(3), "G"); + LEVELS.put(THOUSAND.pow(4), "T"); } private final Level addon; @@ -58,15 +58,15 @@ public class LevelsManager { private Map cache = new HashMap<>(); public LevelsManager(Level addon) { - this.addon = addon; - // Get the BentoBox database - // Set up the database handler to store and retrieve data - // Note that these are saved by the BentoBox database - handler = new Database<>(addon, IslandLevels.class); - // Initialize the cache - levelsCache = new HashMap<>(); - // Initialize top ten lists - topTenLists = new ConcurrentHashMap<>(); + this.addon = addon; + // Get the BentoBox database + // Set up the database handler to store and retrieve data + // Note that these are saved by the BentoBox database + handler = new Database<>(addon, IslandLevels.class); + // Initialize the cache + levelsCache = new HashMap<>(); + // Initialize top ten lists + topTenLists = new ConcurrentHashMap<>(); } public void migrate() { @@ -208,7 +208,7 @@ public String formatLevel(@Nullable Long lvl) { * @return initial level of island */ public long getInitialLevel(Island island) { - return getLevelsData(island).getInitialLevel(); + return getLevelsData(island).getInitialLevel(); } /** @@ -252,7 +252,7 @@ public long getIslandMaxLevel(@NonNull World world, @Nullable UUID targetPlayer) * null */ public String getIslandLevelString(@NonNull World world, @Nullable UUID targetPlayer) { - return formatLevel(getIslandLevel(world, targetPlayer)); + return formatLevel(getIslandLevel(world, targetPlayer)); } /** @@ -263,24 +263,24 @@ public String getIslandLevelString(@NonNull World world, @Nullable UUID targetPl */ @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); + 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); } /** @@ -414,7 +414,8 @@ public void loadTopTens() { addon.log("Generating rankings"); handler.loadObjects().forEach(il -> { if (il.getLevel() > 0) { - addon.getIslands().getIslandById(il.getUniqueId()) + // Load islands, but don't cache them + addon.getIslands().getIslandById(il.getUniqueId(), false) .ifPresent(i -> this.addToTopTen(i, il.getLevel())); } }); @@ -429,7 +430,7 @@ public void loadTopTens() { * @param uuid - the island's uuid */ public void removeEntry(World world, String uuid) { - if (topTenLists.containsKey(world)) { + if (topTenLists.containsKey(world)) { topTenLists.get(world).getTopTen().remove(uuid); // Invalidate the cache because of this deletion cache.remove(world); @@ -504,8 +505,8 @@ private void setIslandResults(Island island, Results r) { * @param uniqueId - id of island */ public void deleteIsland(String uniqueId) { - levelsCache.remove(uniqueId); - handler.deleteID(uniqueId); + levelsCache.remove(uniqueId); + handler.deleteID(uniqueId); } } diff --git a/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java b/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java index 8904cdf..025381a 100644 --- a/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java +++ b/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java @@ -89,34 +89,34 @@ public class IslandLevelCalculator { * @param zeroIsland - true if the calculation is due to an island zeroing */ public IslandLevelCalculator(Level addon, Island island, CompletableFuture r, boolean zeroIsland) { - this.addon = addon; - this.island = island; - this.r = r; - this.zeroIsland = zeroIsland; - results = new Results(); - duration = System.currentTimeMillis(); - chunksToCheck = getChunksToScan(island); - this.limitCount = new EnumMap<>(addon.getBlockConfig().getBlockLimits()); - // Get the initial island level - results.initialLevel.set(addon.getInitialIslandLevel(island)); - // Set up the worlds - worlds.put(Environment.NORMAL, Util.getWorld(island.getWorld())); - // Nether - if (addon.getSettings().isNether()) { - World nether = addon.getPlugin().getIWM().getNetherWorld(island.getWorld()); - if (nether != null) { - worlds.put(Environment.NETHER, nether); - } - } - // End - if (addon.getSettings().isEnd()) { - World end = addon.getPlugin().getIWM().getEndWorld(island.getWorld()); - if (end != null) { - worlds.put(Environment.THE_END, end); - } - } - // Sea Height - seaHeight = addon.getPlugin().getIWM().getSeaHeight(island.getWorld()); + this.addon = addon; + this.island = island; + this.r = r; + this.zeroIsland = zeroIsland; + results = new Results(); + duration = System.currentTimeMillis(); + chunksToCheck = getChunksToScan(island); + this.limitCount = new EnumMap<>(addon.getBlockConfig().getBlockLimits()); + // Get the initial island level + results.initialLevel.set(addon.getInitialIslandLevel(island)); + // Set up the worlds + worlds.put(Environment.NORMAL, Util.getWorld(island.getWorld())); + // Nether + if (addon.getSettings().isNether()) { + World nether = addon.getPlugin().getIWM().getNetherWorld(island.getWorld()); + if (nether != null) { + worlds.put(Environment.NETHER, nether); + } + } + // End + if (addon.getSettings().isEnd()) { + World end = addon.getPlugin().getIWM().getEndWorld(island.getWorld()); + if (end != null) { + worlds.put(Environment.THE_END, end); + } + } + // Sea Height + seaHeight = addon.getPlugin().getIWM().getSeaHeight(island.getWorld()); } /** @@ -148,14 +148,14 @@ private long calculateLevel(long blockAndDeathPoints) { * @param belowSeaLevel - true if below sea level */ private void checkBlock(Material mat, boolean belowSeaLevel) { - int count = limitCount(mat); - if (belowSeaLevel) { - results.underWaterBlockCount.addAndGet(count); - results.uwCount.add(mat); - } else { - results.rawBlockCount.addAndGet(count); - results.mdCount.add(mat); - } + int count = limitCount(mat); + if (belowSeaLevel) { + results.underWaterBlockCount.addAndGet(count); + results.uwCount.add(mat); + } else { + results.rawBlockCount.addAndGet(count); + results.mdCount.add(mat); + } } /** @@ -180,7 +180,7 @@ private Queue> getChunksToScan(Island island) { * @return the island */ public Island getIsland() { - return island; + return island; } /** @@ -189,7 +189,7 @@ public Island getIsland() { * @return the r */ public CompletableFuture getR() { - return r; + return r; } /** @@ -258,7 +258,7 @@ private List getReport() { * @return the results */ public Results getResults() { - return results; + return results; } /** @@ -268,13 +268,13 @@ public Results getResults() { * @return value of a material */ private int getValue(Material md) { - Integer value = addon.getBlockConfig().getValue(island.getWorld(), md); - if (value == null) { - // Not in config - results.ncCount.add(md); - return 0; - } - return value; + Integer value = addon.getBlockConfig().getValue(island.getWorld(), md); + if (value == null) { + // Not in config + results.ncCount.add(md); + return 0; + } + return value; } /** @@ -286,44 +286,44 @@ private int getValue(Material md) { * there is no island nether */ private CompletableFuture> getWorldChunk(Environment env, Queue> pairList) { - if (worlds.containsKey(env)) { - CompletableFuture> r2 = new CompletableFuture<>(); - List chunkList = new ArrayList<>(); - World world = worlds.get(env); - // Get the chunk, and then coincidentally check the RoseStacker - loadChunks(r2, world, pairList, chunkList); - return r2; - } - return CompletableFuture.completedFuture(Collections.emptyList()); + if (worlds.containsKey(env)) { + CompletableFuture> r2 = new CompletableFuture<>(); + List chunkList = new ArrayList<>(); + World world = worlds.get(env); + // Get the chunk, and then coincidentally check the RoseStacker + loadChunks(r2, world, pairList, chunkList); + return r2; + } + return CompletableFuture.completedFuture(Collections.emptyList()); } private void loadChunks(CompletableFuture> r2, World world, Queue> pairList, - List chunkList) { - if (pairList.isEmpty()) { - r2.complete(chunkList); - return; - } - Pair p = pairList.poll(); - Util.getChunkAtAsync(world, p.x, p.z, world.getEnvironment().equals(Environment.NETHER)).thenAccept(chunk -> { - if (chunk != null) { - chunkList.add(chunk); - roseStackerCheck(chunk); - } - loadChunks(r2, world, pairList, chunkList); // Iteration - }); + List chunkList) { + if (pairList.isEmpty()) { + r2.complete(chunkList); + return; + } + Pair p = pairList.poll(); + Util.getChunkAtAsync(world, p.x, p.z, world.getEnvironment().equals(Environment.NETHER)).thenAccept(chunk -> { + if (chunk != null) { + chunkList.add(chunk); + roseStackerCheck(chunk); + } + loadChunks(r2, world, pairList, chunkList); // Iteration + }); } private void roseStackerCheck(Chunk chunk) { - if (addon.isRoseStackersEnabled()) { - RoseStackerAPI.getInstance().getStackedBlocks(Collections.singletonList(chunk)).forEach(e -> { - // Blocks below sea level can be scored differently - boolean belowSeaLevel = seaHeight > 0 && e.getLocation().getY() <= seaHeight; - // Check block once because the base block will be counted in the chunk snapshot - for (int _x = 0; _x < e.getStackSize() - 1; _x++) { - checkBlock(e.getBlock().getType(), belowSeaLevel); - } - }); - } + if (addon.isRoseStackersEnabled()) { + RoseStackerAPI.getInstance().getStackedBlocks(Collections.singletonList(chunk)).forEach(e -> { + // Blocks below sea level can be scored differently + boolean belowSeaLevel = seaHeight > 0 && e.getLocation().getY() <= seaHeight; + // Check block once because the base block will be counted in the chunk snapshot + for (int _x = 0; _x < e.getStackSize() - 1; _x++) { + checkBlock(e.getBlock().getType(), belowSeaLevel); + } + }); + } } /** @@ -334,17 +334,17 @@ private void roseStackerCheck(Chunk chunk) { * @return value of the block if can be counted */ private int limitCount(Material md) { - if (limitCount.containsKey(md)) { - int count = limitCount.get(md); - if (count > 0) { - limitCount.put(md, --count); - return getValue(md); - } else { - results.ofCount.add(md); - return 0; - } - } - return getValue(md); + if (limitCount.containsKey(md)) { + int count = limitCount.get(md); + if (count > 0) { + limitCount.put(md, --count); + return getValue(md); + } else { + results.ofCount.add(md); + return 0; + } + } + return getValue(md); } /** @@ -579,7 +579,7 @@ public void tidyUp() { * @return the zeroIsland */ boolean isNotZeroIsland() { - return !zeroIsland; + return !zeroIsland; } public void scanIsland(Pipeliner pipeliner) { @@ -608,57 +608,52 @@ public void scanIsland(Pipeliner pipeliner) { // Done pipeliner.getInProcessQueue().remove(this); // Chunk finished - // This was the last chunk - handleStackedBlocks(); - handleChests(); - long checkTime = System.currentTimeMillis(); - finishTask = Bukkit.getScheduler().runTaskTimer(addon.getPlugin(), () -> { - // Check every half second if all the chests and stacks have been cleared - if ((chestBlocks.isEmpty() && stackedBlocks.isEmpty()) - || System.currentTimeMillis() - checkTime > MAX_AMOUNT) { - this.tidyUp(); - this.getR().complete(getResults()); - finishTask.cancel(); - } - }, 0, 10L); - + // This was the last chunk. Handle stacked blocks, then chests and exit + handleStackedBlocks().thenCompose(v -> handleChests()).thenRun(() -> { + this.tidyUp(); + this.getR().complete(getResults()); + }); } }); } - private void handleChests() { - Iterator it = chestBlocks.iterator(); - while (it.hasNext()) { - Chunk v = it.next(); - Util.getChunkAtAsync(v.getWorld(), v.getX(), v.getZ()).thenAccept(c -> { + private CompletableFuture handleChests() { + List> futures = new ArrayList<>(); + for (Chunk v : chestBlocks) { + CompletableFuture future = Util.getChunkAtAsync(v.getWorld(), v.getX(), v.getZ()).thenAccept(c -> { scanChests(c); - it.remove(); }); + futures.add(future); } + // Return a CompletableFuture that completes when all futures are done + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); } - private void handleStackedBlocks() { - // Deal with any stacked blocks - Iterator it = stackedBlocks.iterator(); - while (it.hasNext()) { - Location v = it.next(); - Util.getChunkAtAsync(v).thenAccept(c -> { - Block stackedBlock = v.getBlock(); - boolean belowSeaLevel = seaHeight > 0 && v.getBlockY() <= seaHeight; - if (WildStackerAPI.getWildStacker().getSystemManager().isStackedBarrel(stackedBlock)) { - StackedBarrel barrel = WildStackerAPI.getStackedBarrel(stackedBlock); - int barrelAmt = WildStackerAPI.getBarrelAmount(stackedBlock); - for (int _x = 0; _x < barrelAmt; _x++) { - checkBlock(barrel.getType(), belowSeaLevel); - } - } else if (WildStackerAPI.getWildStacker().getSystemManager().isStackedSpawner(stackedBlock)) { - int spawnerAmt = WildStackerAPI.getSpawnersAmount((CreatureSpawner) stackedBlock.getState()); - for (int _x = 0; _x < spawnerAmt; _x++) { - checkBlock(stackedBlock.getType(), belowSeaLevel); - } - } - it.remove(); - }); - } + private CompletableFuture handleStackedBlocks() { + // Deal with any stacked blocks + List> futures = new ArrayList<>(); + for (Location v : stackedBlocks) { + CompletableFuture future = Util.getChunkAtAsync(v).thenAccept(c -> { + Block stackedBlock = v.getBlock(); + boolean belowSeaLevel = seaHeight > 0 && v.getBlockY() <= seaHeight; + if (WildStackerAPI.getWildStacker().getSystemManager().isStackedBarrel(stackedBlock)) { + StackedBarrel barrel = WildStackerAPI.getStackedBarrel(stackedBlock); + int barrelAmt = WildStackerAPI.getBarrelAmount(stackedBlock); + for (int _x = 0; _x < barrelAmt; _x++) { + checkBlock(barrel.getType(), belowSeaLevel); + } + } else if (WildStackerAPI.getWildStacker().getSystemManager().isStackedSpawner(stackedBlock)) { + int spawnerAmt = WildStackerAPI.getSpawnersAmount((CreatureSpawner) stackedBlock.getState()); + for (int _x = 0; _x < spawnerAmt; _x++) { + checkBlock(stackedBlock.getType(), belowSeaLevel); + } + } + }); + futures.add(future); + } + // Return a CompletableFuture that completes when all futures are done + return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); + } + } diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml index d7e5b6d..9edbf7d 100755 --- a/src/main/resources/addon.yml +++ b/src/main/resources/addon.yml @@ -2,7 +2,7 @@ name: Level main: world.bentobox.level.Level version: ${version}${build.number} icon: DIAMOND -api-version: 1.16.5 +api-version: 2.4.0 authors: tastybento diff --git a/src/main/resources/locales/zh-CN.yml b/src/main/resources/locales/zh-CN.yml old mode 100755 new mode 100644 index d015525..e9283e0 --- a/src/main/resources/locales/zh-CN.yml +++ b/src/main/resources/locales/zh-CN.yml @@ -1,79 +1,93 @@ ---- admin: level: - parameters: "" + parameters: description: 计算指定玩家的岛屿等级 sethandicap: - parameters: " " - description: 设置偏差值,通常用于抵消初始岛屿等级,来保证岛屿等级从零开始。实际岛屿等级 - = 最终的岛屿等级 - changed: "&a 岛屿的偏差值从 [number] 更改为 [new_number]" - invalid-level: "&c 偏差值无效,请使用整数" + parameters: + description: 设置偏差值, 通常用于抵消初始岛屿等级, 来保证岛屿等级从零开始. 实际岛屿等级 - = 最终的岛屿等级 + changed: '&a岛屿的偏差值从[number]更改为[new_number]' + invalid-level: '&c偏差值无效, 请使用整数' levelstatus: description: 显示等级计算队列中的岛屿 - islands-in-queue: "&a 列队中的岛屿:[number]" + islands-in-queue: '&a列队中的岛屿: [number]' top: description: 显示前十名 - unknown-world: "&c 未知的世界!" - display: "&f[rank]. &a[name] &7- &b[level]" + unknown-world: '&c未知的世界!' + display: '&f[rank]. &a[name] &7- &b[level]' remove: description: 将玩家移出前十名 - parameters: "" + parameters: + stats: + description: 显示该服务器上岛屿的统计数据 + title: 服务器岛屿数据 + world: '&a[name]' + no-data: '&c没有数据.' + average-level: '平均岛屿等级: [number]' + median-level: '中位数岛屿等级: [number]' + mode-level: '众数岛屿等级: [number]' + highest-level: '最高岛屿等级: [number]' + lowest-level: '最低岛屿等级: [number]' + distribution: '岛屿等级分布:' + islands: 个岛屿 island: level: - parameters: "[player]" - description: 计算你或指定玩家 [player] 的岛屿等级 - calculating: "&a 等级计算中..." - estimated-wait: "&a 预计等待时间:[number] 秒" - in-queue: "&a 你处于队列中第 [number] 个" - island-level-is: "&a 岛屿等级为 &b[level]" - required-points-to-next-level: "&a 还需 [points] 点数才能到达下一级" - deaths: "&c([number] 次死亡)" - cooldown: "&c 还需等待 &b[time] &c秒才能再次使用该指令" - in-progress: "&6 岛级等级正在计算中..." - time-out: "&c 等级计算超时。请稍后再试" + parameters: '[player]' + description: 计算你或指定玩家[player]的岛屿等级 + calculating: '&a等级计算中...' + estimated-wait: '&a预计等待时间: [number]秒' + in-queue: '&a你处于队列中第[number]个' + island-level-is: '&a岛屿等级为: &b[level]' + required-points-to-next-level: '&a还需[points]点数才能到达下一级' + deaths: '&c([number]次死亡)' + cooldown: '&c还需等待&b[time]&c秒才能再次使用该指令' + in-progress: '&6岛屿等级正在计算中...' + time-out: '&c等级计算超时, 请稍后再试' + top: description: 显示前十名 - gui-title: "&a 前十" - gui-heading: "&6[name]: &B[rank]" - island-level: "&b 等级 [level]" - warp-to: "&a 正在传送到 [name] 的岛屿" + gui-title: '&a前十' + gui-heading: '&6[name]: &B[rank]' + island-level: '&b等级: [level]' + warp-to: '&a正在传送到[name]的岛屿' + level-details: above-sea-level-blocks: 海平面以上的方块 spawners: 刷怪笼 underwater-blocks: 水下的方块 all-blocks: 所有方块 - no-island: "&c 没有岛屿!" - names-island: "[name] 的岛屿" - syntax: "[name] x [number]" - hint: "&c 运行level指令查看方块报告" + no-island: '&c没有岛屿!' + names-island: '[name]的岛屿' + syntax: '[name] x [number]' + hint: '&c运行level指令查看方块报告' + level: commands: value: - parameters: "[hand|]" - description: 显示方块的价值。在末尾添加 'hand' 可显示手中方块的价值 + parameters: '[hand|]' + description: 显示方块的价值. 在末尾添加'hand'可显示手中方块的价值 gui: titles: - top: "&0&l 岛屿排行榜" - detail-panel: "&0&l [name] 的岛屿" - value-panel: "&0&l 方块价值" + top: '&0&l岛屿排行榜' + detail-panel: '&0&l[name]的岛屿' + value-panel: '&0&l方块价值' buttons: island: - empty: "&f&l 第 [name] 名" - name: "&f&l [name]" + empty: '&f&l第[name]名' + name: '&f&l[name]' description: |- [owner] [members] [place] [level] - owners-island: "[player] 的岛屿" - owner: "&7&l 岛主:&r&b [player]" - members-title: "&7&l 成员:" - member: "&b - [player]" + owners-island: '[player]的岛屿' + owner: '&7&l岛主: &r&b[player]' + members-title: '&7&l成员: ' + member: '&b- [player]' unknown: 未知 - place: "&7第 &7&o[number] &r&7名" - level: "&7 等级: &o [number]" + place: '&7第&7&o[number]&r&7名' + level: '&7等级: &o[number]' material: - name: "&f&l [number] x [material]" + name: '&f&l [number] x [material]' description: |- [description] [count] @@ -81,83 +95,79 @@ level: [calculated] [limit] [id] - id: "&7 方块ID:&e [id]" - value: "&7 方块价值:&e [number]" - limit: "&7 方块限制:&e [number]" - count: "&7 方块数量:&e [number]" - calculated: "&7 计算值:&e [number]" + id: '&7方块ID: &e[id]' + value: '&7方块价值: &e[number]' + limit: '&7方块限制: &e[number]' + count: '&7方块数量: &e[number]' + calculated: '&7计算值: &e[number]' all_blocks: - name: "&f&l 所有方块" - description: "&7 显示岛屿上所有的方块" + name: '&f&l所有方块' + description: '&7显示岛屿上所有的方块' above_sea_level: - name: "&f&l 海平面以上的方块" - description: |- - &7 只显示所有 - &7 海平面以上的方块 + name: '&f&l海平面以上的方块' + description: '&7只显示所有海平面以上的方块' underwater: - name: "&f&l 海平面以下的方块" - description: |- - &7 只显示所有 - &7 海平面以下的方块 + name: '&f&l海平面以下的方块' + description: 只显示所有海平面以下的方块 spawner: - name: "&f&l 刷怪笼" - description: "&7 只显示刷怪笼" + name: '&f&l刷怪笼' + description: '&7只显示刷怪笼' filters: name: - name: "&f&l 按名称排序" - description: "&7 通过名称排序所有的方块" + name: '&f&l按名称排序' + description: '&7通过名称排序所有的方块' value: - name: "&f&l 按价值排序" - description: "&7 通过价值排序所有的方块" + name: '&f&l按价值排序' + description: '&7通过价值排序所有的方块' count: - name: "&f&l 按数量排序" - description: "&7 通过数量排序所有方块" + name: '&f&l按数量排序' + description: '&7通过数量排序所有方块' value: - name: "&f&l [material]" + name: '&f&l[material]' description: |- [description] [value] [underwater] [limit] [id] - id: "&7 方块ID:&e [id]" - value: "&7 方块价值:&e [number]" - underwater: "&7 海平面以下方块的价值:&e [number]" - limit: "&7 方块限制:&e [number]" + id: '&7方块ID: &e[id]' + value: '&7方块价值: &e[number]' + underwater: '&7海平面以下方块的价值: &e[number]' + limit: '&7方块限制: &e[number]' previous: - name: "&f&l 上一页" - description: "&7 切换到第 [number] 页" + name: '&f&l上一页' + description: '&7切换到第[number]页' next: - name: "&f&l 下一页" - description: "&7 切换到第 [number] 页" + name: '&f&l下一页' + description: '&7切换到第[number]页' search: - name: "&f&l 搜索" - description: "&7 搜索特定的内容" - search: "&b 搜索值:[value]" + name: '&f&l搜索' + description: '&7搜索特定的内容' + search: '&b搜索值: [value]' tips: - click-to-view: "&e 点击 &7 查看" - click-to-previous: "&e 点击 &7 查看上一页" - click-to-next: "&e 点击 &7 查看下一页" - click-to-select: "&e 点击 &7 选择" - left-click-to-cycle-up: "&e 左键点击 &7 向上循环" - right-click-to-cycle-down: "&e 右键点击 &7 向下循环" - left-click-to-change: "&e 左键点击 &7 编辑" - right-click-to-clear: "&e 右键点击 &7 清除" - click-to-asc: "&e 点击 &7 以升序排序" - click-to-desc: "&e 点击 &7 以降序排序" - click-to-warp: "&e 点击 &7 去岛屿传送点" - click-to-visit: "&e 点击 &7 参观" - right-click-to-visit: "&e 右键点击 &7 查看" + click-to-view: '&e点击 &7查看' + click-to-previous: '&e点击 &7查看上一页' + click-to-next: '&e点击 &7查看下一页' + click-to-select: '&e点击 &7选择' + left-click-to-cycle-up: '&e左键 &7向上循环' + right-click-to-cycle-down: '&e右键 &7向下循环' + left-click-to-change: '&e左键 &7编辑' + right-click-to-clear: '&e右键 &7清除' + click-to-asc: '&e点击 &7以升序排序' + click-to-desc: '&e点击 &7以降序排序' + click-to-warp: '&e点击 &7去岛屿传送点' + click-to-visit: '&e点击 &7参观' + right-click-to-visit: '&e右键 &7查看' conversations: - prefix: "&l&6 [BentoBox]: &r" - no-data: "&c 运行level指令查看方块报告" + prefix: '&l&6[BentoBox]: &r' + no-data: '&c运行level指令查看方块报告' cancel-string: cancel exit-string: cancel, exit, quit - write-search: "&e 请输入要搜索的值. (输入 'cancel' 退出)" - search-updated: "&a 搜索值已更新" - cancelled: "&c 对话已取消!" - no-value: "&c 这件物品一文不值" - unknown-item: "&c 物品 '[material]' 在游戏中不存在" - value: "&7 物品 '[material]' 的价值:&e[value]" - value-underwater: "&7 物品 '[material]' 在海平面以下的价值:&e[value]" - empty-hand: "&c 你的手中没有拿着方块" + write-search: '&e请输入要搜索的值. (输入''cancel''退出)' + search-updated: '&a搜索值已更新' + cancelled: '&c对话已取消' + no-value: '&c这件物品一文不值' + unknown-item: '&c物品''[material]''在游戏中不存在' + value: '&7物品''[material]''的价值: &e[value]' + value-underwater: '&7物品''[material]''在海平面以下的价值: &e[value]' + empty-hand: '&c你的手中没有拿着方块' diff --git a/src/test/java/world/bentobox/level/LevelTest.java b/src/test/java/world/bentobox/level/LevelTest.java index 5f8074a..7da610f 100644 --- a/src/test/java/world/bentobox/level/LevelTest.java +++ b/src/test/java/world/bentobox/level/LevelTest.java @@ -61,6 +61,7 @@ import world.bentobox.bentobox.managers.IslandWorldManager; import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.PlaceholdersManager; +import world.bentobox.bentobox.util.Util; import world.bentobox.level.config.BlockConfig; import world.bentobox.level.config.ConfigSettings; import world.bentobox.level.listeners.IslandActivitiesListeners; @@ -72,7 +73,7 @@ */ @SuppressWarnings("deprecation") @RunWith(PowerMockRunner.class) -@PrepareForTest({ Bukkit.class, BentoBox.class, User.class }) +@PrepareForTest({ Bukkit.class, BentoBox.class, User.class, Util.class }) public class LevelTest { private static File jFile; @@ -144,7 +145,7 @@ public static void beforeClass() throws IOException { /** * @throws java.lang.Exception */ - @Before + @Before public void setUp() throws Exception { // Set up plugin Whitebox.setInternalState(BentoBox.class, "instance", plugin); @@ -189,6 +190,11 @@ public void setUp() throws Exception { when(Bukkit.getServer()).thenReturn(server); when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger()); when(Bukkit.getPluginManager()).thenReturn(mock(PluginManager.class)); + when(Bukkit.getBukkitVersion()).thenReturn(""); + + // Util + PowerMockito.mockStatic(Util.class, Mockito.RETURNS_MOCKS); + when(Util.inTest()).thenReturn(true); // Addon addon = new Level(); @@ -221,7 +227,6 @@ public void setUp() throws Exception { when(fm.getFlags()).thenReturn(Collections.emptyList()); // Bukkit - PowerMockito.mockStatic(Bukkit.class); when(Bukkit.getScheduler()).thenReturn(scheduler); ItemMeta meta = mock(ItemMeta.class); ItemFactory itemFactory = mock(ItemFactory.class); diff --git a/src/test/java/world/bentobox/level/LevelsManagerTest.java b/src/test/java/world/bentobox/level/LevelsManagerTest.java index 551c573..c0be60c 100644 --- a/src/test/java/world/bentobox/level/LevelsManagerTest.java +++ b/src/test/java/world/bentobox/level/LevelsManagerTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -165,6 +166,7 @@ public void setUp() throws Exception { when(im.hasIsland(eq(world), any(UUID.class))).thenReturn(true); when(im.getIsland(world, uuid)).thenReturn(island); when(im.getIslandById(anyString())).thenReturn(Optional.of(island)); + when(im.getIslandById(anyString(), eq(false))).thenReturn(Optional.of(island)); // Player when(player.getUniqueId()).thenReturn(uuid); @@ -395,8 +397,8 @@ public void testLoadTopTens() { lm.loadTopTens(); PowerMockito.verifyStatic(Bukkit.class); // 1 Bukkit.getScheduler(); - verify(scheduler).runTaskAsynchronously(eq(plugin), task.capture()); - task.getValue().run(); + verify(scheduler).runTaskAsynchronously(eq(plugin), task.capture()); // Capture the task in the scheduler + task.getValue().run(); // run it verify(addon).log("Generating rankings"); verify(addon).log("Generated rankings for bskyblock-world"); diff --git a/src/test/java/world/bentobox/level/PlaceholderManagerTest.java b/src/test/java/world/bentobox/level/PlaceholderManagerTest.java index 56f0a1d..10bf0d0 100644 --- a/src/test/java/world/bentobox/level/PlaceholderManagerTest.java +++ b/src/test/java/world/bentobox/level/PlaceholderManagerTest.java @@ -9,9 +9,9 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; @@ -138,7 +138,7 @@ public void setUp() throws Exception { when(im.getIsland(any(World.class), any(User.class))).thenReturn(island); when(im.getIslandAt(any(Location.class))).thenReturn(Optional.of(island)); when(im.getIslandById(anyString())).thenAnswer((Answer>) invocation -> Optional.of(islands.get(invocation.getArgument(0, String.class)))); - when(im.getIslands(any(), any(UUID.class))).thenReturn(new HashSet<>(islands.values())); + when(im.getIslands(any(), any(UUID.class))).thenReturn(new ArrayList<>(islands.values())); when(addon.getIslands()).thenReturn(im); // Levels Manager diff --git a/src/test/java/world/bentobox/level/commands/AdminTopRemoveCommandTest.java b/src/test/java/world/bentobox/level/commands/AdminTopRemoveCommandTest.java index 9e82384..8a49c25 100644 --- a/src/test/java/world/bentobox/level/commands/AdminTopRemoveCommandTest.java +++ b/src/test/java/world/bentobox/level/commands/AdminTopRemoveCommandTest.java @@ -10,7 +10,7 @@ import static org.mockito.Mockito.when; import java.util.Collections; -import java.util.Set; +import java.util.List; import java.util.UUID; import org.bukkit.Bukkit; @@ -120,8 +120,8 @@ public void setUp() { 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)); + when(im.getIslands(any(), any(User.class))).thenReturn(List.of(island)); + when(im.getIslands(any(), any(UUID.class))).thenReturn(List.of(island)); // Bukkit PowerMockito.mockStatic(Bukkit.class);