Added timings, fixed bugs.

This commit is contained in:
tastybento 2020-07-04 18:13:02 -07:00
parent 7f75caab36
commit 85cd89bdf7
9 changed files with 132 additions and 43 deletions

View File

@ -21,8 +21,7 @@ import org.bukkit.World;
import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable; 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.AddonBaseEvent;
import world.bentobox.bentobox.api.events.addon.AddonEvent; import world.bentobox.bentobox.api.events.addon.AddonEvent;
import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.PanelItem;
@ -128,7 +127,7 @@ public class LevelsManager {
} }
// Save result // Save result
addon.logWarning("Saving results"); addon.logWarning("Saving results");
setIslandResults(island.getWorld(), island.getOwner(), r.getLevel(), r.getUwCount(), r.getMdCount()); setIslandResults(island.getWorld(), island.getOwner(), r);
// Save top ten // Save top ten
addon.logWarning("Saving top ten"); addon.logWarning("Saving top ten");
addon.getManager().saveTopTen(island.getWorld()); 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 * @param islandOwner - UUID of island owner
* @return LevelsData object or null if not found * @return LevelsData object or null if not found
*/ */
@ -399,6 +398,9 @@ public class LevelsManager {
* @param uuid - the player's uuid * @param uuid - the player's uuid
*/ */
public void removeEntry(World world, UUID 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)) { if (levelsCache.containsKey(uuid)) {
levelsCache.get(uuid).remove(world); levelsCache.get(uuid).remove(world);
// Save // Save
@ -433,7 +435,9 @@ public class LevelsManager {
* @param lv - initial island level * @param lv - initial island level
*/ */
public void setInitialIslandLevel(@NonNull Island island, long lv) { 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; if (island.getOwner() == null || island.getWorld() == null) return;
BentoBox.getInstance().logDebug("saving");
levelsCache.computeIfAbsent(island.getOwner(), LevelsData::new).setInitialLevel(island.getWorld(), lv); levelsCache.computeIfAbsent(island.getOwner(), LevelsData::new).setInitialLevel(island.getWorld(), lv);
handler.saveObjectAsync(levelsCache.get(island.getOwner())); 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 * Set the island level for the owner of the island that targetPlayer is a member
* @param world - world * @param world - world
* @param owner * @param owner - owner of the island
* @param level * @param r - results of the calculation
* @param uwCount
* @param mdCount
*/ */
private void setIslandResults(World world, @Nullable UUID owner, long level, Multiset<Material> uwCount, private void setIslandResults(World world, @Nullable UUID owner, Results r) {
Multiset<Material> mdCount) {
LevelsData ld = levelsCache.computeIfAbsent(owner, LevelsData::new); LevelsData ld = levelsCache.computeIfAbsent(owner, LevelsData::new);
ld.setLevel(world, level); ld.setLevel(world, r.getLevel());
ld.setUwCount(world, uwCount); ld.setUwCount(world, r.getUwCount());
ld.setMdCount(world, mdCount); ld.setMdCount(world, r.getMdCount());
ld.setPointsToNextLevel(world, r.getPointsToNextLevel());
levelsCache.put(owner, ld); levelsCache.put(owner, ld);
handler.saveObjectAsync(ld); handler.saveObjectAsync(ld);
// Update TopTen // Update TopTen

View File

@ -146,18 +146,20 @@ public class IslandLevelCalculator {
private final Results results; private final Results results;
private long duration;
/** /**
* Constructor to get the level for an island * Constructor to get the level for an island
* @param addon - Level addon * @param addon - Level addon
* @param island - the island to scan * @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<Results> r) { public IslandLevelCalculator(Level addon, Island island, CompletableFuture<Results> r) {
this.addon = addon; this.addon = addon;
this.island = island; this.island = island;
this.r = r; this.r = r;
results = new Results(); results = new Results();
duration = System.currentTimeMillis();
chunksToCheck = getChunksToScan(island); chunksToCheck = getChunksToScan(island);
this.limitCount = new HashMap<>(addon.getBlockConfig().getBlockLimits()); this.limitCount = new HashMap<>(addon.getBlockConfig().getBlockLimits());
} }
@ -310,7 +312,7 @@ public class IslandLevelCalculator {
if (addon.getSettings().isNether()) { if (addon.getSettings().isNether()) {
World nether = addon.getPlugin().getIWM().getNetherWorld(island.getWorld()); World nether = addon.getPlugin().getIWM().getNetherWorld(island.getWorld());
if (nether != null) { 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 // There is no chunk to scan, so return a null chunk
@ -319,13 +321,13 @@ public class IslandLevelCalculator {
if (addon.getSettings().isEnd()) { if (addon.getSettings().isEnd()) {
World end = addon.getPlugin().getIWM().getEndWorld(island.getWorld()); World end = addon.getPlugin().getIWM().getEndWorld(island.getWorld());
if (end != null) { 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 // There is no chunk to scan, so return a null chunk
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
default: default:
return Util.getChunkAtAsync(world, x, z, false); return Util.getChunkAtAsync(world, x, z, true);
} }
} }
@ -530,6 +532,8 @@ public class IslandLevelCalculator {
// Report // Report
results.report = getReport(); results.report = getReport();
// Set the duration
addon.getPipeliner().setTime(System.currentTimeMillis() - duration);
// All done. // All done.
} }
} }

View File

@ -18,10 +18,13 @@ import world.bentobox.level.Level;
*/ */
public class Pipeliner { public class Pipeliner {
private static final int START_DURATION = 10; // 10 seconds
private final Queue<IslandLevelCalculator> processQueue; private final Queue<IslandLevelCalculator> processQueue;
private final BukkitTask task; private final BukkitTask task;
private boolean inProcess; private boolean inProcess;
private final Level addon; private final Level addon;
private long time;
private long count;
/** /**
* Construct the pipeliner * Construct the pipeliner
@ -53,8 +56,11 @@ public class Pipeliner {
task.cancel(); task.cancel();
} }
/**
* @return number of islands currently in the queue or in process
*/
public int getIslandsInQueue() { public int getIslandsInQueue() {
return processQueue.size(); return inProcess ? processQueue.size() + 1 : processQueue.size();
} }
/** /**
@ -95,8 +101,26 @@ public class Pipeliner {
public CompletableFuture<Results> addIsland(Island island) { public CompletableFuture<Results> addIsland(Island island) {
CompletableFuture<Results> r = new CompletableFuture<>(); CompletableFuture<Results> r = new CompletableFuture<>();
processQueue.add(new IslandLevelCalculator(addon, island, r)); processQueue.add(new IslandLevelCalculator(addon, island, r));
count++;
return r; 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;
}
} }

View File

@ -78,8 +78,9 @@ public class IslandLevelCommand extends CompositeCommand {
return false; return false;
} }
user.sendMessage("island.level.calculating");
int inQueue = addon.getPipeliner().getIslandsInQueue(); 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) { if (inQueue > 1) {
user.sendMessage("island.level.in-queue", TextVariables.NUMBER, String.valueOf(inQueue + 1)); user.sendMessage("island.level.in-queue", TextVariables.NUMBER, String.valueOf(inQueue + 1));
} }

View File

@ -7,6 +7,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; 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.IslandCreatedEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent.IslandPreclearEvent; import world.bentobox.bentobox.api.events.island.IslandEvent.IslandPreclearEvent;
import world.bentobox.bentobox.api.events.island.IslandEvent.IslandRegisteredEvent; import world.bentobox.bentobox.api.events.island.IslandEvent.IslandRegisteredEvent;
@ -38,17 +39,20 @@ public class IslandActivitiesListeners implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onNewIsland(IslandCreatedEvent e) { public void onNewIsland(IslandCreatedEvent e) {
BentoBox.getInstance().logDebug(e.getEventName());
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) {
BentoBox.getInstance().logDebug(e.getEventName());
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) {
BentoBox.getInstance().logDebug("Zeroing island");
addon.getPipeliner().addIsland(island).thenAccept(results -> addon.getPipeliner().addIsland(island).thenAccept(results ->
addon.getManager().setInitialIslandLevel(island, results.getLevel())); addon.getManager().setInitialIslandLevel(island, results.getLevel()));
} }
@ -56,9 +60,11 @@ public class IslandActivitiesListeners implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onIslandDelete(IslandPreclearEvent e) { public void onIslandDelete(IslandPreclearEvent e) {
BentoBox.getInstance().logDebug(e.getEventName());
// Remove player from the top ten and level // Remove player from the top ten and level
UUID uuid = e.getIsland().getOwner(); UUID uuid = e.getIsland().getOwner();
World world = e.getIsland().getWorld(); World world = e.getIsland().getWorld();
BentoBox.getInstance().logDebug(uuid + " " + world);
remove(world, uuid); remove(world, uuid);
} }
@ -70,36 +76,42 @@ public class IslandActivitiesListeners implements Listener {
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onNewIslandOwner(TeamSetownerEvent e) { public void onNewIslandOwner(TeamSetownerEvent e) {
BentoBox.getInstance().logDebug(e.getEventName());
// Remove player from the top ten and level // Remove player from the top ten and level
remove(e.getIsland().getWorld(), e.getIsland().getOwner()); remove(e.getIsland().getWorld(), e.getIsland().getOwner());
} }
@EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
public void onIsland(TeamJoinedEvent e) { public void onIsland(TeamJoinedEvent e) {
BentoBox.getInstance().logDebug(e.getEventName());
// 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) {
BentoBox.getInstance().logDebug(e.getEventName());
// 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(IslandRegisteredEvent e) { public void onIsland(IslandRegisteredEvent e) {
BentoBox.getInstance().logDebug(e.getEventName());
// 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(TeamLeaveEvent e) { public void onIsland(TeamLeaveEvent e) {
BentoBox.getInstance().logDebug(e.getEventName());
// 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) {
BentoBox.getInstance().logDebug(e.getEventName());
// 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

@ -13,6 +13,7 @@ import org.bukkit.World;
import com.google.common.collect.Multiset; import com.google.common.collect.Multiset;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.database.objects.DataObject; import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.database.objects.Table; import world.bentobox.bentobox.database.objects.Table;
@ -141,8 +142,12 @@ public class LevelsData implements DataObject {
* @param world - world to remove * @param world - world to remove
*/ */
public void remove(World world) { public void remove(World world) {
levels.remove(world.getName().toLowerCase(Locale.ENGLISH)); BentoBox.getInstance().logDebug("Removing world");
initialLevel.remove(world.getName().toLowerCase(Locale.ENGLISH)); 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 * @return the uwCount
*/ */
public Map<Material, Integer> getUwCount(World world) { public Map<Material, Integer> getUwCount(World world) {
if (this.uwCount == null) {
this.uwCount = new HashMap<>();
}
return uwCount.getOrDefault(world.getName(), Collections.emptyMap()); return uwCount.getOrDefault(world.getName(), Collections.emptyMap());
} }
@ -219,6 +227,9 @@ public class LevelsData implements DataObject {
* @return the mdCount * @return the mdCount
*/ */
public Map<Material, Integer> getMdCount(World world) { public Map<Material, Integer> getMdCount(World world) {
if (this.mdCount == null) {
this.mdCount = new HashMap<>();
}
return mdCount.getOrDefault(world.getName(), Collections.emptyMap()); return mdCount.getOrDefault(world.getName(), Collections.emptyMap());
} }

View File

@ -17,6 +17,7 @@ import org.eclipse.jdt.annotation.Nullable;
import com.google.common.base.Enums; 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.Panel;
import world.bentobox.bentobox.api.panels.PanelItem; import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler; import world.bentobox.bentobox.api.panels.PanelItem.ClickHandler;
@ -41,6 +42,9 @@ public class DetailsGUITab implements Tab, ClickHandler {
UNDERWATER_BLOCKS UNDERWATER_BLOCKS
} }
/**
* Converts block materials to item materials
*/
private static final Map<Material, Material> M2I; private static final Map<Material, Material> M2I;
static { static {
Map<Material, Material> m2i = new HashMap<>(); Map<Material, Material> m2i = new HashMap<>();
@ -72,6 +76,7 @@ public class DetailsGUITab implements Tab, ClickHandler {
m2i.put(Material.BUBBLE_COLUMN, Material.WATER_BUCKET); m2i.put(Material.BUBBLE_COLUMN, Material.WATER_BUCKET);
m2i.put(Material.SWEET_BERRY_BUSH, Material.SWEET_BERRIES); m2i.put(Material.SWEET_BERRY_BUSH, Material.SWEET_BERRIES);
m2i.put(Material.BAMBOO_SAPLING, Material.BAMBOO); m2i.put(Material.BAMBOO_SAPLING, Material.BAMBOO);
m2i.put(Material.FIRE, Material.FLINT_AND_STEEL);
// 1.16.1 // 1.16.1
if (Enums.getIfPresent(Material.class, "WEEPING_VINES_PLANT").isPresent()) { if (Enums.getIfPresent(Material.class, "WEEPING_VINES_PLANT").isPresent()) {
m2i.put(Material.WEEPING_VINES_PLANT, Material.WEEPING_VINES); m2i.put(Material.WEEPING_VINES_PLANT, Material.WEEPING_VINES);
@ -104,6 +109,7 @@ public class DetailsGUITab implements Tab, ClickHandler {
// Convert walls // Convert walls
m = Enums.getIfPresent(Material.class, m.name().replace("WALL_", "")).or(m); m = Enums.getIfPresent(Material.class, m.name().replace("WALL_", "")).or(m);
// Tags // Tags
if (Enums.getIfPresent(Material.class, "SOUL_CAMPFIRE").isPresent()) {
if (Tag.FIRE.isTagged(m)) { if (Tag.FIRE.isTagged(m)) {
items.add(new PanelItemBuilder() items.add(new PanelItemBuilder()
.icon(Material.CAMPFIRE) .icon(Material.CAMPFIRE)
@ -111,12 +117,14 @@ public class DetailsGUITab implements Tab, ClickHandler {
.build()); .build());
return; return;
} }
}
if (Tag.FLOWER_POTS.isTagged(m)) { if (Tag.FLOWER_POTS.isTagged(m)) {
m = Enums.getIfPresent(Material.class, m.name().replace("POTTED_", "")).or(m); m = Enums.getIfPresent(Material.class, m.name().replace("POTTED_", "")).or(m);
} }
items.add(new PanelItemBuilder() items.add(new PanelItemBuilder()
.icon(M2I.getOrDefault(m, m)) .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()); .build());
} }
@ -141,30 +149,35 @@ public class DetailsGUITab implements Tab, ClickHandler {
default: default:
sumTotal.forEach(this::createItem); sumTotal.forEach(this::createItem);
break; 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 @Override
public PanelItem getIcon() { public PanelItem getIcon() {
switch(type) { switch(type) {
case ABOVE_SEA_LEVEL_BLOCKS: 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: 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: 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: 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 @Override
public String getName() { public String getName() {
String name = "&c No island!"; String name = user.getTranslation("island.level-details.no-island");
if (island.getOwner() != null) { 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; return name;
} }
@ -176,17 +189,16 @@ public class DetailsGUITab implements Tab, ClickHandler {
@Override @Override
public String getPermission() { public String getPermission() {
String permPrefix = addon.getPlugin().getIWM().getPermissionPrefix(world);
switch(type) { switch(type) {
case ABOVE_SEA_LEVEL_BLOCKS: case ABOVE_SEA_LEVEL_BLOCKS:
return ""; return permPrefix + "island.level.details.above-sea-level";
case ALL_BLOCKS:
return "";
case SPAWNERS: case SPAWNERS:
return ""; return permPrefix + "island.level.details.spawners";
case UNDERWATER_BLOCKS: case UNDERWATER_BLOCKS:
return ""; return permPrefix + "island.level.details.underwater";
default: default:
return ""; return permPrefix + "island.level.details.blocks";
} }
} }

View File

@ -19,6 +19,18 @@ permissions:
'[gamemode].island.value': '[gamemode].island.value':
description: Player can use value command description: Player can use value command
default: true 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': '[gamemode].admin.level':
description: Player can use admin level command description: Player can use admin level command
default: op default: op

View File

@ -23,6 +23,7 @@ island:
parameters: "[player]" parameters: "[player]"
description: "calculate your island level or show the level of [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" in-queue: "&a You are number [number] in the queue"
island-level-is: "&a Island level is &b[level]" island-level-is: "&a Island level is &b[level]"
required-points-to-next-level: "&a [points] points required until the next level" required-points-to-next-level: "&a [points] points required until the next level"
@ -36,6 +37,16 @@ island:
island-level: "&b Level [level]" island-level: "&b Level [level]"
warp-to: "&A Warping to [name]'s island" 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: value:
description: "shows the value of any block" description: "shows the value of any block"
success: "&7 The value of this block is: &e[value]" success: "&7 The value of this block is: &e[value]"