From 85cd89bdf71c47dff29e1de453ed775fb244c719 Mon Sep 17 00:00:00 2001 From: tastybento Date: Sat, 4 Jul 2020 18:13:02 -0700 Subject: [PATCH] Added timings, fixed bugs. --- .../world/bentobox/level/LevelsManager.java | 28 +++++----- .../calculators/IslandLevelCalculator.java | 12 +++-- .../bentobox/level/calculators/Pipeliner.java | 26 ++++++++- .../level/commands/IslandLevelCommand.java | 3 +- .../listeners/IslandActivitiesListeners.java | 12 +++++ .../bentobox/level/objects/LevelsData.java | 15 +++++- .../bentobox/level/panels/DetailsGUITab.java | 54 +++++++++++-------- src/main/resources/addon.yml | 12 +++++ src/main/resources/locales/en-US.yml | 13 ++++- 9 files changed, 132 insertions(+), 43 deletions(-) diff --git a/src/main/java/world/bentobox/level/LevelsManager.java b/src/main/java/world/bentobox/level/LevelsManager.java index f4cec12..c6e620d 100644 --- a/src/main/java/world/bentobox/level/LevelsManager.java +++ b/src/main/java/world/bentobox/level/LevelsManager.java @@ -21,8 +21,7 @@ import org.bukkit.World; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; -import com.google.common.collect.Multiset; - +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.events.addon.AddonBaseEvent; import world.bentobox.bentobox.api.events.addon.AddonEvent; import world.bentobox.bentobox.api.panels.PanelItem; @@ -128,7 +127,7 @@ public class LevelsManager { } // Save result addon.logWarning("Saving results"); - setIslandResults(island.getWorld(), island.getOwner(), r.getLevel(), r.getUwCount(), r.getMdCount()); + setIslandResults(island.getWorld(), island.getOwner(), r); // Save top ten addon.logWarning("Saving top ten"); addon.getManager().saveTopTen(island.getWorld()); @@ -307,7 +306,7 @@ public class LevelsManager { } /** - * Load a level data for the island owner from the cache or database. Only island onwers are stored. + * Load a level data for the island owner from the cache or database. Only island owners are stored. * @param islandOwner - UUID of island owner * @return LevelsData object or null if not found */ @@ -399,6 +398,9 @@ public class LevelsManager { * @param uuid - the player's uuid */ public void removeEntry(World world, UUID uuid) { + // Load the user if they haven't yet done anything to put them in the cache + this.getLevelsData(uuid); + // Remove them if (levelsCache.containsKey(uuid)) { levelsCache.get(uuid).remove(world); // Save @@ -433,7 +435,9 @@ public class LevelsManager { * @param lv - initial island level */ public void setInitialIslandLevel(@NonNull Island island, long lv) { + BentoBox.getInstance().logDebug("Setting initial island level " + island +" " + lv); if (island.getOwner() == null || island.getWorld() == null) return; + BentoBox.getInstance().logDebug("saving"); levelsCache.computeIfAbsent(island.getOwner(), LevelsData::new).setInitialLevel(island.getWorld(), lv); handler.saveObjectAsync(levelsCache.get(island.getOwner())); } @@ -454,17 +458,15 @@ public class LevelsManager { /** * Set the island level for the owner of the island that targetPlayer is a member * @param world - world - * @param owner - * @param level - * @param uwCount - * @param mdCount + * @param owner - owner of the island + * @param r - results of the calculation */ - private void setIslandResults(World world, @Nullable UUID owner, long level, Multiset uwCount, - Multiset mdCount) { + private void setIslandResults(World world, @Nullable UUID owner, Results r) { LevelsData ld = levelsCache.computeIfAbsent(owner, LevelsData::new); - ld.setLevel(world, level); - ld.setUwCount(world, uwCount); - ld.setMdCount(world, mdCount); + ld.setLevel(world, r.getLevel()); + ld.setUwCount(world, r.getUwCount()); + ld.setMdCount(world, r.getMdCount()); + ld.setPointsToNextLevel(world, r.getPointsToNextLevel()); levelsCache.put(owner, ld); handler.saveObjectAsync(ld); // Update TopTen diff --git a/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java b/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java index d054e4e..8b076d5 100644 --- a/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java +++ b/src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java @@ -146,18 +146,20 @@ public class IslandLevelCalculator { private final Results results; + private long duration; /** * Constructor to get the level for an island * @param addon - Level addon * @param island - the island to scan - * @param r - completeable result that will be completed when the calculation is complete + * @param r - completable result that will be completed when the calculation is complete */ public IslandLevelCalculator(Level addon, Island island, CompletableFuture r) { this.addon = addon; this.island = island; this.r = r; results = new Results(); + duration = System.currentTimeMillis(); chunksToCheck = getChunksToScan(island); this.limitCount = new HashMap<>(addon.getBlockConfig().getBlockLimits()); } @@ -310,7 +312,7 @@ public class IslandLevelCalculator { if (addon.getSettings().isNether()) { World nether = addon.getPlugin().getIWM().getNetherWorld(island.getWorld()); if (nether != null) { - return Util.getChunkAtAsync(nether, x, z, false); + return Util.getChunkAtAsync(nether, x, z, true); } } // There is no chunk to scan, so return a null chunk @@ -319,13 +321,13 @@ public class IslandLevelCalculator { if (addon.getSettings().isEnd()) { World end = addon.getPlugin().getIWM().getEndWorld(island.getWorld()); if (end != null) { - return Util.getChunkAtAsync(end, x, z, false); + return Util.getChunkAtAsync(end, x, z, true); } } // There is no chunk to scan, so return a null chunk return CompletableFuture.completedFuture(null); default: - return Util.getChunkAtAsync(world, x, z, false); + return Util.getChunkAtAsync(world, x, z, true); } } @@ -530,6 +532,8 @@ public class IslandLevelCalculator { // Report results.report = getReport(); + // Set the duration + addon.getPipeliner().setTime(System.currentTimeMillis() - duration); // All done. } } diff --git a/src/main/java/world/bentobox/level/calculators/Pipeliner.java b/src/main/java/world/bentobox/level/calculators/Pipeliner.java index bd89d35..11e08ba 100644 --- a/src/main/java/world/bentobox/level/calculators/Pipeliner.java +++ b/src/main/java/world/bentobox/level/calculators/Pipeliner.java @@ -18,10 +18,13 @@ import world.bentobox.level.Level; */ public class Pipeliner { + private static final int START_DURATION = 10; // 10 seconds private final Queue processQueue; private final BukkitTask task; private boolean inProcess; private final Level addon; + private long time; + private long count; /** * Construct the pipeliner @@ -53,8 +56,11 @@ public class Pipeliner { task.cancel(); } + /** + * @return number of islands currently in the queue or in process + */ public int getIslandsInQueue() { - return processQueue.size(); + return inProcess ? processQueue.size() + 1 : processQueue.size(); } /** @@ -95,8 +101,26 @@ public class Pipeliner { public CompletableFuture addIsland(Island island) { CompletableFuture r = new CompletableFuture<>(); processQueue.add(new IslandLevelCalculator(addon, island, r)); + count++; return r; } + /** + * Get the average time it takes to run a level check + * @return the average time in seconds + */ + public int getTime() { + return time == 0 || count == 0 ? START_DURATION : (int)((double)time/count/1000); + } + + /** + * Submit how long a level check took + * @param time the time to set + */ + public void setTime(long time) { + // Running average + this.time += time; + } + } diff --git a/src/main/java/world/bentobox/level/commands/IslandLevelCommand.java b/src/main/java/world/bentobox/level/commands/IslandLevelCommand.java index a371080..e616b4b 100644 --- a/src/main/java/world/bentobox/level/commands/IslandLevelCommand.java +++ b/src/main/java/world/bentobox/level/commands/IslandLevelCommand.java @@ -78,8 +78,9 @@ public class IslandLevelCommand extends CompositeCommand { return false; } - user.sendMessage("island.level.calculating"); int inQueue = addon.getPipeliner().getIslandsInQueue(); + user.sendMessage("island.level.calculating"); + user.sendMessage("island.level.estimated-wait", TextVariables.NUMBER, String.valueOf(addon.getPipeliner().getTime() * (inQueue + 1))); if (inQueue > 1) { user.sendMessage("island.level.in-queue", TextVariables.NUMBER, String.valueOf(inQueue + 1)); } diff --git a/src/main/java/world/bentobox/level/listeners/IslandActivitiesListeners.java b/src/main/java/world/bentobox/level/listeners/IslandActivitiesListeners.java index 9c5445d..f7a1c40 100644 --- a/src/main/java/world/bentobox/level/listeners/IslandActivitiesListeners.java +++ b/src/main/java/world/bentobox/level/listeners/IslandActivitiesListeners.java @@ -7,6 +7,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.events.island.IslandEvent.IslandCreatedEvent; import world.bentobox.bentobox.api.events.island.IslandEvent.IslandPreclearEvent; import world.bentobox.bentobox.api.events.island.IslandEvent.IslandRegisteredEvent; @@ -38,17 +39,20 @@ public class IslandActivitiesListeners implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onNewIsland(IslandCreatedEvent e) { + BentoBox.getInstance().logDebug(e.getEventName()); zeroIsland(e.getIsland()); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onNewIsland(IslandResettedEvent e) { + BentoBox.getInstance().logDebug(e.getEventName()); zeroIsland(e.getIsland()); } private void zeroIsland(final Island island) { // Clear the island setting if (island.getOwner() != null && island.getWorld() != null) { + BentoBox.getInstance().logDebug("Zeroing island"); addon.getPipeliner().addIsland(island).thenAccept(results -> addon.getManager().setInitialIslandLevel(island, results.getLevel())); } @@ -56,9 +60,11 @@ public class IslandActivitiesListeners implements Listener { @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onIslandDelete(IslandPreclearEvent e) { + BentoBox.getInstance().logDebug(e.getEventName()); // Remove player from the top ten and level UUID uuid = e.getIsland().getOwner(); World world = e.getIsland().getWorld(); + BentoBox.getInstance().logDebug(uuid + " " + world); remove(world, uuid); } @@ -70,36 +76,42 @@ public class IslandActivitiesListeners implements Listener { @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onNewIslandOwner(TeamSetownerEvent e) { + BentoBox.getInstance().logDebug(e.getEventName()); // Remove player from the top ten and level remove(e.getIsland().getWorld(), e.getIsland().getOwner()); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onIsland(TeamJoinedEvent e) { + BentoBox.getInstance().logDebug(e.getEventName()); // Remove player from the top ten and level remove(e.getIsland().getWorld(), e.getPlayerUUID()); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onIsland(IslandUnregisteredEvent e) { + BentoBox.getInstance().logDebug(e.getEventName()); // Remove player from the top ten and level remove(e.getIsland().getWorld(), e.getPlayerUUID()); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onIsland(IslandRegisteredEvent e) { + BentoBox.getInstance().logDebug(e.getEventName()); // Remove player from the top ten and level remove(e.getIsland().getWorld(), e.getPlayerUUID()); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onIsland(TeamLeaveEvent e) { + BentoBox.getInstance().logDebug(e.getEventName()); // Remove player from the top ten and level remove(e.getIsland().getWorld(), e.getPlayerUUID()); } @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) public void onIsland(TeamKickEvent e) { + BentoBox.getInstance().logDebug(e.getEventName()); // Remove player from the top ten and level remove(e.getIsland().getWorld(), e.getPlayerUUID()); } diff --git a/src/main/java/world/bentobox/level/objects/LevelsData.java b/src/main/java/world/bentobox/level/objects/LevelsData.java index 53869cf..53adecd 100644 --- a/src/main/java/world/bentobox/level/objects/LevelsData.java +++ b/src/main/java/world/bentobox/level/objects/LevelsData.java @@ -13,6 +13,7 @@ import org.bukkit.World; import com.google.common.collect.Multiset; import com.google.gson.annotations.Expose; +import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.database.objects.DataObject; import world.bentobox.bentobox.database.objects.Table; @@ -141,8 +142,12 @@ public class LevelsData implements DataObject { * @param world - world to remove */ public void remove(World world) { - levels.remove(world.getName().toLowerCase(Locale.ENGLISH)); - initialLevel.remove(world.getName().toLowerCase(Locale.ENGLISH)); + BentoBox.getInstance().logDebug("Removing world"); + this.levels.remove(world.getName().toLowerCase(Locale.ENGLISH)); + this.initialLevel.remove(world.getName().toLowerCase(Locale.ENGLISH)); + this.pointsToNextLevel.remove(world.getName().toLowerCase(Locale.ENGLISH)); + this.mdCount.remove(world.getName().toLowerCase(Locale.ENGLISH)); + this.uwCount.remove(world.getName().toLowerCase(Locale.ENGLISH)); } /** @@ -211,6 +216,9 @@ public class LevelsData implements DataObject { * @return the uwCount */ public Map getUwCount(World world) { + if (this.uwCount == null) { + this.uwCount = new HashMap<>(); + } return uwCount.getOrDefault(world.getName(), Collections.emptyMap()); } @@ -219,6 +227,9 @@ public class LevelsData implements DataObject { * @return the mdCount */ public Map getMdCount(World world) { + if (this.mdCount == null) { + this.mdCount = new HashMap<>(); + } return mdCount.getOrDefault(world.getName(), Collections.emptyMap()); } diff --git a/src/main/java/world/bentobox/level/panels/DetailsGUITab.java b/src/main/java/world/bentobox/level/panels/DetailsGUITab.java index 3ad510d..0c7eef9 100644 --- a/src/main/java/world/bentobox/level/panels/DetailsGUITab.java +++ b/src/main/java/world/bentobox/level/panels/DetailsGUITab.java @@ -17,6 +17,7 @@ import org.eclipse.jdt.annotation.Nullable; import com.google.common.base.Enums; +import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.panels.Panel; import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler; @@ -41,6 +42,9 @@ public class DetailsGUITab implements Tab, ClickHandler { UNDERWATER_BLOCKS } + /** + * Converts block materials to item materials + */ private static final Map M2I; static { Map m2i = new HashMap<>(); @@ -72,6 +76,7 @@ public class DetailsGUITab implements Tab, ClickHandler { m2i.put(Material.BUBBLE_COLUMN, Material.WATER_BUCKET); m2i.put(Material.SWEET_BERRY_BUSH, Material.SWEET_BERRIES); m2i.put(Material.BAMBOO_SAPLING, Material.BAMBOO); + m2i.put(Material.FIRE, Material.FLINT_AND_STEEL); // 1.16.1 if (Enums.getIfPresent(Material.class, "WEEPING_VINES_PLANT").isPresent()) { m2i.put(Material.WEEPING_VINES_PLANT, Material.WEEPING_VINES); @@ -104,19 +109,22 @@ public class DetailsGUITab implements Tab, ClickHandler { // Convert walls m = Enums.getIfPresent(Material.class, m.name().replace("WALL_", "")).or(m); // Tags - if (Tag.FIRE.isTagged(m)) { - items.add(new PanelItemBuilder() - .icon(Material.CAMPFIRE) - .name(Util.prettifyText(m.name()) + " x " + count) - .build()); - return; + if (Enums.getIfPresent(Material.class, "SOUL_CAMPFIRE").isPresent()) { + if (Tag.FIRE.isTagged(m)) { + items.add(new PanelItemBuilder() + .icon(Material.CAMPFIRE) + .name(Util.prettifyText(m.name()) + " x " + count) + .build()); + return; + } } if (Tag.FLOWER_POTS.isTagged(m)) { m = Enums.getIfPresent(Material.class, m.name().replace("POTTED_", "")).or(m); } items.add(new PanelItemBuilder() .icon(M2I.getOrDefault(m, m)) - .name(Util.prettifyText(m.name()) + " x " + count) + .name(user.getTranslation("island.level-details.syntax", TextVariables.NAME, + Util.prettifyText(m.name()), TextVariables.NUMBER, String.valueOf(count))) .build()); } @@ -141,30 +149,35 @@ public class DetailsGUITab implements Tab, ClickHandler { default: sumTotal.forEach(this::createItem); break; - } - + if (type.equals(DetailsType.ALL_BLOCKS) && items.isEmpty()) { + // Nothing here - looks like they need to run level + items.add(new PanelItemBuilder() + .name(user.getTranslation("island.level-details.hint")).icon(Material.WRITTEN_BOOK) + .build()); + } } @Override public PanelItem getIcon() { switch(type) { case ABOVE_SEA_LEVEL_BLOCKS: - return new PanelItemBuilder().icon(Material.GRASS_BLOCK).name("Above Sea Level Blocks").build(); + return new PanelItemBuilder().icon(Material.GRASS_BLOCK).name(user.getTranslation("island.level-details.above-sea-level-blocks")).build(); case SPAWNERS: - return new PanelItemBuilder().icon(Material.SPAWNER).name("Spawners").build(); + return new PanelItemBuilder().icon(Material.SPAWNER).name(user.getTranslation("island.level-details.spawners")).build(); case UNDERWATER_BLOCKS: - return new PanelItemBuilder().icon(Material.WATER_BUCKET).name("Underwater Blocks").build(); + return new PanelItemBuilder().icon(Material.WATER_BUCKET).name(user.getTranslation("island.level-details.underwater-blocks")).build(); default: - return new PanelItemBuilder().icon(Material.GRASS_BLOCK).name("All Blocks").build(); + return new PanelItemBuilder().icon(Material.GRASS_BLOCK).name(user.getTranslation("island.level-details.all-blocks")).build(); } } @Override public String getName() { - String name = "&c No island!"; + String name = user.getTranslation("island.level-details.no-island"); if (island.getOwner() != null) { - name = island.getName() != null ? island.getName() : addon.getPlayers().getName(island.getOwner()) + "'s island"; + name = island.getName() != null ? island.getName() : + user.getTranslation("island.level-details.names-island", TextVariables.NAME, addon.getPlayers().getName(island.getOwner())); } return name; } @@ -176,17 +189,16 @@ public class DetailsGUITab implements Tab, ClickHandler { @Override public String getPermission() { + String permPrefix = addon.getPlugin().getIWM().getPermissionPrefix(world); switch(type) { case ABOVE_SEA_LEVEL_BLOCKS: - return ""; - case ALL_BLOCKS: - return ""; + return permPrefix + "island.level.details.above-sea-level"; case SPAWNERS: - return ""; + return permPrefix + "island.level.details.spawners"; case UNDERWATER_BLOCKS: - return ""; + return permPrefix + "island.level.details.underwater"; default: - return ""; + return permPrefix + "island.level.details.blocks"; } } diff --git a/src/main/resources/addon.yml b/src/main/resources/addon.yml index 001787c..40ca788 100755 --- a/src/main/resources/addon.yml +++ b/src/main/resources/addon.yml @@ -19,6 +19,18 @@ permissions: '[gamemode].island.value': description: Player can use value command default: true + '[gamemode].island.level.details.blocks': + description: Player see the level details + default: true + '[gamemode].island.level.details.spawners': + description: Player can see the spawners tab in the level details + default: false + '[gamemode].island.level.details.underwater': + description: Player can see the underwater tab in the level details + default: false + '[gamemode].island.level.details.above-sea-level': + description: Player can see the above sea level tab in the level details + default: false '[gamemode].admin.level': description: Player can use admin level command default: op diff --git a/src/main/resources/locales/en-US.yml b/src/main/resources/locales/en-US.yml index b6c86d0..b9e4f99 100755 --- a/src/main/resources/locales/en-US.yml +++ b/src/main/resources/locales/en-US.yml @@ -22,7 +22,8 @@ island: level: parameters: "[player]" description: "calculate your island level or show the level of [player]" - calculating: "&a Calculating level..." + calculating: "&a Calculating level..." + estimated-wait: "&a Estimated wait: [number] seconds" in-queue: "&a You are number [number] in the queue" island-level-is: "&a Island level is &b[level]" required-points-to-next-level: "&a [points] points required until the next level" @@ -35,6 +36,16 @@ island: gui-heading: "&6[name]: &B[rank]" island-level: "&b Level [level]" warp-to: "&A Warping to [name]'s island" + + level-details: + above-sea-level-blocks: "Above Sea Level Blocks" + spawners: "Spawners" + underwater-blocks: "Underwater Blocks" + all-blocks: "All Blocks" + no-island: "&c No island!" + names-island: "[name]'s island" + syntax: "[name] x [number]" + hint: "&c Run level to see the block report" value: description: "shows the value of any block"