addon-level/src/main/java/world/bentobox/level/panels/DetailsPanel.java

805 lines
25 KiB
Java
Raw Normal View History

Version 2.10.0 (#283) * Version 2.7.1 * Version 2.7.2 * Use Java 9's takeWhile * Added placeholder %Level_[gamemode]_rank_value Fixes https://github.com/BentoBoxWorld/Level/issues/228 * No save on disable (#231) * Release 2.6.4 * Remove saving to database on disable. https://github.com/BentoBoxWorld/Level/issues/229 First, the top ten tables are never actually used or loaded. They are created in memory by loading the island levels. So there is no reason to keep saving them. Second, the island level data is saved every time it is changed, so there is no need to save all of the cache on exit. * Fixes tests * Rosestacker (#232) * Add support for RoseStacker 1.3.0 * Made plugin a Pladdon. * Version 2.8.0 * Added new placeholders %Level_%gamemode%_top_island_name_%rank% - lists the island name %Level_%gamemode%_top_island_members_%rank% - a comma separated list of team members https://github.com/BentoBoxWorld/Level/issues/224 https://github.com/BentoBoxWorld/Level/issues/211 https://github.com/BentoBoxWorld/Level/issues/132 https://github.com/BentoBoxWorld/Level/issues/107 https://github.com/BentoBoxWorld/Level/issues/105 * Update to BentoBox API 1.18 * Open up modules for testing access. * Back support for BentoBox 1.16.5. * Version 2.8.1 * Speeds up level calculation by doing more chunk scans async. If chests are scanned, then it will take longer because these have to be done sync. https://github.com/BentoBoxWorld/Level/issues/243 * add Vietnamese (#240) * Raw island level placeholder (#241) * Changed IslandLevelCalculator minHeight to world minHeight for negative blocks height support since 1.18. (#246) * Version 2.9.0 * Chinese Translation (#249) * Translate zh-CN.yml via GitLocalize * Translate zh-CN.yml via GitLocalize Co-authored-by: mt-gitlocalize <mt@gitlocalize.com> Co-authored-by: 织梦 <493733933@qq.com> * Translate id.yml via GitLocalize (#250) Co-authored-by: Nathan Adhitya <nathanadhitya@outlook.com> * Translate fr.yml via GitLocalize (#251) Co-authored-by: organizatsiya <organizatsiya.wildguns@gmail.com> * Korean translation (#252) * Translate ko.yml via GitLocalize * Translate ko.yml via GitLocalize Co-authored-by: chickiyeah <ruddls030@naver.com> Co-authored-by: mt-gitlocalize <mt@gitlocalize.com> * German Translation (#253) * Translate de.yml via GitLocalize * Update de.yml Co-authored-by: Rikamo045 <rik.amos.krajinovic@gmail.com> Co-authored-by: tastybento <tastybento@users.noreply.github.com> * Translate hu.yml via GitLocalize (#254) Co-authored-by: András Marczinkó <marczinkoandris@gmail.com> * Version 2.9.1 * Attempt to handle WildStacker spawners * Fix error lon loading id locale * Avoid async chunk snapshotting. Fixes https://github.com/BentoBoxWorld/Level/issues/256 * Update to BentoBox API 1.20. Replace plugin.yml with spigot-annotations. Implement customizable TopLevelPanel. * Fixes some small issues with TopLevelPanel Add Utils class that contains some useful things. * Implement customizable DetailsPanel. Remove old DetailsGUITab due to new implementation. * Fix failing test. * Remove blank file * Added repo for maven plugin snapshots * Implement feature that allows to sort items in detail panel. (#259) Apparently, because it is 2 years old request, it got in a state -> implement or drop. Fixes #192 * Implement calculated value for blocks. (#260) It is ~ value, as calculation formula cannot be applied per block. At least I think so. Part of #192 * Update es.yml (#261) * Implement customizable Values GUI. (#262) This GUI shows value to all items in game. It also shows max limit of blocks, if it is set. Fixes of #192 * Support for AdvancedChests was updated. (#266) * Implements visit/warp actions in top gui Add 2 new actions for island buttons in TOP GUI: - Visit -> allows to visit island, but it requires Visit Addon - Warp -> allows to warp to island, but it requires Warp Addon Requested via Discord. * Fixes a Level addon crash on startup. Level addon crashed at the startup if Visit or Warps addon were not installed. It happened because Level addon main class were implementing Listener interface. To avoid it and fix the crash, I moved migration listener to a separate class. Fixes #2012 * Translate pl.yml via GitLocalize (#269) Co-authored-by: wiktorm12 <wiktorm12@gmail.com> * Translate fr.yml via GitLocalize (#272) Co-authored-by: organizatsiya <organizatsiya.wildguns@gmail.com> * Update to Java 17 * Update Github workflow to Java 17 * Adds %Level_[gamemode]_island_level_max% placeholder This records the lifetime maximum level the island has ever had. Addresses #271 * Only shows Members or higher in the top members placeholder Fixes #267 * Add natural log to level-calc formula parsing Relates to #274 * feat: add island total points + placeholder (#264) * feat: add island total points + placeholder * Update IslandLevels.java * Fix JavaDoc * Translate zh-CN.yml via GitLocalize (#276) Co-authored-by: dawnTak <lanlongxiaode@outlook.com> * Translate nl.yml via GitLocalize (#277) Co-authored-by: DevSolaris <solaris.dev.2002@gmail.com> * Add ${argLine} to get jacoco coverage * Updated Jacoco POM * Add shulker to in chest count (#275) * Sonar Cloud code smell clean up (#278) * Refactor placeholders (#279) * Update ReadMe * Fix Jacoco * Remove unused imports * Remove placeholders from main class Created a separate class for cleaner code and added a test class. * Remove dependency * Add UltimateStacker hook for stacked blocks (#281) * Create plugin.yml (#282) * Create plugin.yml The annotations do not provide the option to define the version dynamically from maven. This should fix that. * Remove Spigot Plugin Annotations * Remove plugin-annotation repo * Updated dependencies --------- Co-authored-by: Huynh Tien <huynhqtienvtag@gmail.com> Co-authored-by: Rubén <44579213+Rubenicos@users.noreply.github.com> Co-authored-by: Pierre Dedrie <Pirgosth74@gmail.com> Co-authored-by: gitlocalize-app[bot] <55277160+gitlocalize-app[bot]@users.noreply.github.com> Co-authored-by: mt-gitlocalize <mt@gitlocalize.com> Co-authored-by: 织梦 <493733933@qq.com> Co-authored-by: Nathan Adhitya <nathanadhitya@outlook.com> Co-authored-by: organizatsiya <organizatsiya.wildguns@gmail.com> Co-authored-by: chickiyeah <ruddls030@naver.com> Co-authored-by: Rikamo045 <rik.amos.krajinovic@gmail.com> Co-authored-by: András Marczinkó <marczinkoandris@gmail.com> Co-authored-by: BONNe <bonne@bonne.id.lv> Co-authored-by: KrazyxWolf <68208993+KrazyxWolf@users.noreply.github.com> Co-authored-by: DeadSilenceIV <Barreto-h2@hotmail.com> Co-authored-by: wiktorm12 <wiktorm12@gmail.com> Co-authored-by: evlad <emmanuelvlad@gmail.com> Co-authored-by: dawnTak <lanlongxiaode@outlook.com> Co-authored-by: DevSolaris <solaris.dev.2002@gmail.com> Co-authored-by: DevSolaris <105156235+DevSolaris@users.noreply.github.com> Co-authored-by: ceze88 <dev.ceze@gmail.com>
2023-04-16 01:44:33 +02:00
package world.bentobox.level.panels;
import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import com.google.common.base.Enums;
import lv.id.bonne.panelutils.PanelUtils;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.TemplatedPanel;
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
import world.bentobox.bentobox.api.panels.builders.TemplatedPanelBuilder;
import world.bentobox.bentobox.api.panels.reader.ItemTemplateRecord;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.util.Pair;
import world.bentobox.level.Level;
import world.bentobox.level.objects.IslandLevels;
import world.bentobox.level.util.Utils;
/**
* This class opens GUI that shows generator view for user.
*/
public class DetailsPanel
{
// ---------------------------------------------------------------------
// Section: Internal Constructor
// ---------------------------------------------------------------------
/**
* This is internal constructor. It is used internally in current class to avoid creating objects everywhere.
*
* @param addon Level object
* @param world World where user is operating
* @param user User who opens panel
*/
private DetailsPanel(Level addon,
World world,
User user)
{
this.addon = addon;
this.world = world;
this.user = user;
this.island = this.addon.getIslands().getIsland(world, user);
if (this.island != null)
{
this.levelsData = this.addon.getManager().getLevelsData(this.island);
}
else
{
this.levelsData = null;
}
// By default no-filters are active.
this.activeTab = Tab.ALL_BLOCKS;
this.activeFilter = Filter.NAME;
this.materialCountList = new ArrayList<>(Material.values().length);
this.updateFilters();
}
/**
* This method builds this GUI.
*/
private void build()
{
if (this.island == null || this.levelsData == null)
{
// Nothing to see.
Utils.sendMessage(this.user, this.user.getTranslation("general.errors.no-island"));
return;
}
if (this.levelsData.getMdCount().isEmpty() && this.levelsData.getUwCount().isEmpty())
{
// Nothing to see.
Utils.sendMessage(this.user, this.user.getTranslation("level.conversations.no-data"));
return;
}
// Start building panel.
TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
panelBuilder.user(this.user);
panelBuilder.world(this.user.getWorld());
panelBuilder.template("detail_panel", new File(this.addon.getDataFolder(), "panels"));
panelBuilder.parameters("[name]", this.user.getName());
panelBuilder.registerTypeBuilder("NEXT", this::createNextButton);
panelBuilder.registerTypeBuilder("PREVIOUS", this::createPreviousButton);
panelBuilder.registerTypeBuilder("BLOCK", this::createMaterialButton);
panelBuilder.registerTypeBuilder("FILTER", this::createFilterButton);
// Register tabs
panelBuilder.registerTypeBuilder("TAB", this::createTabButton);
// Register unknown type builder.
panelBuilder.build();
}
/**
* This method updates filter of elements based on tabs.
*/
private void updateFilters()
{
this.materialCountList.clear();
switch (this.activeTab)
{
case ALL_BLOCKS -> {
Map<Material, Integer> materialCountMap = new EnumMap<>(Material.class);
materialCountMap.putAll(this.levelsData.getMdCount());
// Add underwater blocks.
this.levelsData.getUwCount().forEach((material, count) -> materialCountMap.put(material,
materialCountMap.computeIfAbsent(material, key -> 0) + count));
materialCountMap.entrySet().stream().sorted((Map.Entry.comparingByKey())).
forEachOrdered(entry ->
this.materialCountList.add(new Pair<>(entry.getKey(), entry.getValue())));
}
case ABOVE_SEA_LEVEL -> this.levelsData.getMdCount().entrySet().stream().sorted((Map.Entry.comparingByKey()))
.forEachOrdered(entry -> this.materialCountList.add(new Pair<>(entry.getKey(), entry.getValue())));
case UNDERWATER -> this.levelsData.getUwCount().entrySet().stream().sorted((Map.Entry.comparingByKey()))
.forEachOrdered(entry -> this.materialCountList.add(new Pair<>(entry.getKey(), entry.getValue())));
case SPAWNER -> {
int aboveWater = this.levelsData.getMdCount().getOrDefault(Material.SPAWNER, 0);
int underWater = this.levelsData.getUwCount().getOrDefault(Material.SPAWNER, 0);
// TODO: spawners need some touch...
this.materialCountList.add(new Pair<>(Material.SPAWNER, underWater + aboveWater));
}
}
Comparator<Pair<Material, Integer>> sorter;
switch (this.activeFilter)
{
case COUNT ->
{
sorter = (o1, o2) ->
{
if (o1.getValue().equals(o2.getValue()))
{
String o1Name = Utils.prettifyObject(o1.getKey(), this.user);
String o2Name = Utils.prettifyObject(o2.getKey(), this.user);
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
}
else
{
return Integer.compare(o2.getValue(), o1.getValue());
}
};
}
case VALUE ->
{
sorter = (o1, o2) ->
{
int blockLimit = this.addon.getBlockConfig().getBlockLimits().getOrDefault(o1.getKey(), 0);
int o1Count = blockLimit > 0 ? Math.min(o1.getValue(), blockLimit) : o1.getValue();
blockLimit = this.addon.getBlockConfig().getBlockLimits().getOrDefault(o2.getKey(), 0);
int o2Count = blockLimit > 0 ? Math.min(o2.getValue(), blockLimit) : o2.getValue();
long o1Value = (long) o1Count *
this.addon.getBlockConfig().getBlockValues().getOrDefault(o1.getKey(), 0);
long o2Value = (long) o2Count *
this.addon.getBlockConfig().getBlockValues().getOrDefault(o2.getKey(), 0);
if (o1Value == o2Value)
{
String o1Name = Utils.prettifyObject(o1.getKey(), this.user);
String o2Name = Utils.prettifyObject(o2.getKey(), this.user);
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
}
else
{
return Long.compare(o2Value, o1Value);
}
};
}
default ->
{
sorter = (o1, o2) ->
{
String o1Name = Utils.prettifyObject(o1.getKey(), this.user);
String o2Name = Utils.prettifyObject(o2.getKey(), this.user);
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
};
}
}
this.materialCountList.sort(sorter);
this.pageIndex = 0;
}
// ---------------------------------------------------------------------
// Section: Tab Button Type
// ---------------------------------------------------------------------
/**
* Create tab button panel item.
*
* @param template the template
* @param slot the slot
* @return the panel item
*/
private PanelItem createTabButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
{
PanelItemBuilder builder = new PanelItemBuilder();
if (template.icon() != null)
{
// Set icon
builder.icon(template.icon().clone());
}
if (template.title() != null)
{
// Set title
builder.name(this.user.getTranslation(this.world, template.title()));
}
if (template.description() != null)
{
// Set description
builder.description(this.user.getTranslation(this.world, template.description()));
}
Tab tab = Enums.getIfPresent(Tab.class, String.valueOf(template.dataMap().get("tab"))).or(Tab.ALL_BLOCKS);
// Get only possible actions, by removing all inactive ones.
List<ItemTemplateRecord.ActionRecords> activeActions = new ArrayList<>(template.actions());
activeActions.removeIf(action ->
"VIEW".equalsIgnoreCase(action.actionType()) && this.activeTab == tab);
// Add Click handler
builder.clickHandler((panel, user, clickType, i) ->
{
for (ItemTemplateRecord.ActionRecords action : activeActions)
{
if ((clickType == action.clickType() || ClickType.UNKNOWN.equals(action.clickType()))
&& "VIEW".equalsIgnoreCase(action.actionType()))
{
this.activeTab = tab;
// Update filters.
this.updateFilters();
this.build();
}
}
return true;
});
// Collect tooltips.
List<String> tooltips = activeActions.stream().
filter(action -> action.tooltip() != null).
map(action -> this.user.getTranslation(this.world, action.tooltip())).
filter(text -> !text.isBlank()).
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
// Add tooltips.
if (!tooltips.isEmpty())
{
// Empty line and tooltips.
builder.description("");
builder.description(tooltips);
}
builder.glow(this.activeTab == tab);
return builder.build();
}
/**
* Create next button panel item.
*
* @param template the template
* @param slot the slot
* @return the panel item
*/
private PanelItem createFilterButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
{
PanelItemBuilder builder = new PanelItemBuilder();
if (template.icon() != null)
{
// Set icon
builder.icon(template.icon().clone());
}
Filter filter;
if (slot.amountMap().getOrDefault("FILTER", 0) > 1)
{
filter = Enums.getIfPresent(Filter.class, String.valueOf(template.dataMap().get("filter"))).or(Filter.NAME);
}
else
{
filter = this.activeFilter;
}
final String reference = "level.gui.buttons.filters.";
if (template.title() != null)
{
// Set title
builder.name(this.user.getTranslation(this.world, template.title().replace("[filter]", filter.name().toLowerCase())));
}
else
{
builder.name(this.user.getTranslation(this.world, reference + filter.name().toLowerCase() + ".name"));
}
if (template.description() != null)
{
// Set description
builder.description(this.user.getTranslation(this.world, template.description().replace("[filter]", filter.name().toLowerCase())));
}
else
{
builder.name(this.user.getTranslation(this.world, reference + filter.name().toLowerCase() + ".description"));
}
// Get only possible actions, by removing all inactive ones.
List<ItemTemplateRecord.ActionRecords> activeActions = new ArrayList<>(template.actions());
// Add Click handler
builder.clickHandler((panel, user, clickType, i) ->
{
for (ItemTemplateRecord.ActionRecords action : activeActions)
{
if (clickType == action.clickType() || ClickType.UNKNOWN.equals(action.clickType()))
{
if ("UP".equalsIgnoreCase(action.actionType()))
{
this.activeFilter = Utils.getNextValue(Filter.values(), filter);
// Update filters.
this.updateFilters();
this.build();
}
else if ("DOWN".equalsIgnoreCase(action.actionType()))
{
this.activeFilter = Utils.getPreviousValue(Filter.values(), filter);
// Update filters.
this.updateFilters();
this.build();
}
else if ("SELECT".equalsIgnoreCase(action.actionType()))
{
this.activeFilter = filter;
// Update filters.
this.updateFilters();
this.build();
}
}
}
return true;
});
// Collect tooltips.
List<String> tooltips = activeActions.stream().
filter(action -> action.tooltip() != null).
map(action -> this.user.getTranslation(this.world, action.tooltip())).
filter(text -> !text.isBlank()).
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
// Add tooltips.
if (!tooltips.isEmpty())
{
// Empty line and tooltips.
builder.description("");
builder.description(tooltips);
}
builder.glow(this.activeFilter == filter);
return builder.build();
}
// ---------------------------------------------------------------------
// Section: Create common buttons
// ---------------------------------------------------------------------
/**
* Create next button panel item.
*
* @param template the template
* @param slot the slot
* @return the panel item
*/
private PanelItem createNextButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
{
long size = this.materialCountList.size();
if (size <= slot.amountMap().getOrDefault("BLOCK", 1) ||
1.0 * size / slot.amountMap().getOrDefault("BLOCK", 1) <= this.pageIndex + 1)
{
// There are no next elements
return null;
}
int nextPageIndex = this.pageIndex + 2;
PanelItemBuilder builder = new PanelItemBuilder();
if (template.icon() != null)
{
ItemStack clone = template.icon().clone();
if (Boolean.TRUE.equals(template.dataMap().getOrDefault("indexing", false)))
{
clone.setAmount(nextPageIndex);
}
builder.icon(clone);
}
if (template.title() != null)
{
builder.name(this.user.getTranslation(this.world, template.title()));
}
if (template.description() != null)
{
builder.description(this.user.getTranslation(this.world, template.description(),
TextVariables.NUMBER, String.valueOf(nextPageIndex)));
}
// Add ClickHandler
builder.clickHandler((panel, user, clickType, i) ->
{
for (ItemTemplateRecord.ActionRecords action : template.actions())
{
if ((clickType == action.clickType() || ClickType.UNKNOWN.equals(action.clickType())) &&
"NEXT".equalsIgnoreCase(action.actionType()))
{
this.pageIndex++;
this.build();
}
}
// Always return true.
return true;
});
// Collect tooltips.
List<String> tooltips = template.actions().stream().
filter(action -> action.tooltip() != null).
map(action -> this.user.getTranslation(this.world, action.tooltip())).
filter(text -> !text.isBlank()).
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
// Add tooltips.
if (!tooltips.isEmpty())
{
// Empty line and tooltips.
builder.description("");
builder.description(tooltips);
}
return builder.build();
}
/**
* Create previous button panel item.
*
* @param template the template
* @param slot the slot
* @return the panel item
*/
private PanelItem createPreviousButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
{
if (this.pageIndex == 0)
{
// There are no next elements
return null;
}
int previousPageIndex = this.pageIndex;
PanelItemBuilder builder = new PanelItemBuilder();
if (template.icon() != null)
{
ItemStack clone = template.icon().clone();
if (Boolean.TRUE.equals(template.dataMap().getOrDefault("indexing", false)))
{
clone.setAmount(previousPageIndex);
}
builder.icon(clone);
}
if (template.title() != null)
{
builder.name(this.user.getTranslation(this.world, template.title()));
}
if (template.description() != null)
{
builder.description(this.user.getTranslation(this.world, template.description(),
TextVariables.NUMBER, String.valueOf(previousPageIndex)));
}
// Add ClickHandler
builder.clickHandler((panel, user, clickType, i) ->
{
for (ItemTemplateRecord.ActionRecords action : template.actions())
{
if ((clickType == action.clickType() || ClickType.UNKNOWN.equals(action.clickType()))
&& "PREVIOUS".equalsIgnoreCase(action.actionType()))
{
this.pageIndex--;
this.build();
}
}
// Always return true.
return true;
});
// Collect tooltips.
List<String> tooltips = template.actions().stream().
filter(action -> action.tooltip() != null).
map(action -> this.user.getTranslation(this.world, action.tooltip())).
filter(text -> !text.isBlank()).
collect(Collectors.toCollection(() -> new ArrayList<>(template.actions().size())));
// Add tooltips.
if (!tooltips.isEmpty())
{
// Empty line and tooltips.
builder.description("");
builder.description(tooltips);
}
return builder.build();
}
// ---------------------------------------------------------------------
// Section: Create Material Button
// ---------------------------------------------------------------------
/**
* Create material button panel item.
*
* @param template the template
* @param slot the slot
* @return the panel item
*/
private PanelItem createMaterialButton(ItemTemplateRecord template, TemplatedPanel.ItemSlot slot)
{
if (this.materialCountList.isEmpty())
{
// Does not contain any generators.
return null;
}
int index = this.pageIndex * slot.amountMap().getOrDefault("BLOCK", 1) + slot.slot();
if (index >= this.materialCountList.size())
{
// Out of index.
return null;
}
return this.createMaterialButton(template, this.materialCountList.get(index));
}
/**
* This method creates button for material.
*
* @param template the template of the button
* @param materialCount materialCount which button must be created.
* @return PanelItem for generator tier.
*/
private PanelItem createMaterialButton(ItemTemplateRecord template,
Pair<Material, Integer> materialCount)
{
PanelItemBuilder builder = new PanelItemBuilder();
if (template.icon() != null)
{
builder.icon(template.icon().clone());
}
else
{
builder.icon(PanelUtils.getMaterialItem(materialCount.getKey()));
}
if (materialCount.getValue() < 64)
{
builder.amount(materialCount.getValue());
}
if (template.title() != null)
{
builder.name(this.user.getTranslation(this.world, template.title(),
TextVariables.NUMBER, String.valueOf(materialCount.getValue()),
"[material]", Utils.prettifyObject(materialCount.getKey(), this.user)));
}
String description = Utils.prettifyDescription(materialCount.getKey(), this.user);
final String reference = "level.gui.buttons.material.";
String blockId = this.user.getTranslationOrNothing(reference + "id",
"[id]", materialCount.getKey().name());
int blockValue = this.addon.getBlockConfig().getBlockValues().getOrDefault(materialCount.getKey(), 0);
String value = blockValue > 0 ? this.user.getTranslationOrNothing(reference + "value",
TextVariables.NUMBER, String.valueOf(blockValue)) : "";
int blockLimit = this.addon.getBlockConfig().getBlockLimits().getOrDefault(materialCount.getKey(), 0);
String limit = blockLimit > 0 ? this.user.getTranslationOrNothing(reference + "limit",
TextVariables.NUMBER, String.valueOf(blockLimit)) : "";
String count = this.user.getTranslationOrNothing(reference + "count",
TextVariables.NUMBER, String.valueOf(materialCount.getValue()));
long calculatedValue = (long) Math.min(blockLimit > 0 ? blockLimit : Integer.MAX_VALUE, materialCount.getValue()) * blockValue;
String valueText = calculatedValue > 0 ? this.user.getTranslationOrNothing(reference + "calculated",
TextVariables.NUMBER, String.valueOf(calculatedValue)) : "";
if (template.description() != null)
{
builder.description(this.user.getTranslation(this.world, template.description(),
"[description]", description,
"[id]", blockId,
"[value]", value,
"[calculated]", valueText,
"[limit]", limit,
"[count]", count).
replaceAll("(?m)^[ \\t]*\\r?\\n", "").
replaceAll("(?<!\\\\)\\|", "\n").
replace("\\\\\\|", "|"));
}
return builder.build();
}
// ---------------------------------------------------------------------
// Section: Other Methods
// ---------------------------------------------------------------------
/**
* This method is used to open UserPanel outside this class. It will be much easier to open panel with single method
* call then initializing new object.
*
* @param addon Level object
* @param world World where user is operating
* @param user User who opens panel
*/
public static void openPanel(Level addon,
World world,
User user)
{
new DetailsPanel(addon, world, user).build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum holds possible tabs for current gui.
*/
private enum Tab
{
/**
* All block Tab
*/
ALL_BLOCKS,
/**
* Above Sea level Tab.
*/
ABOVE_SEA_LEVEL,
/**
* Underwater Tab.
*/
UNDERWATER,
/**
* Spawner Tab.
*/
SPAWNER
}
/**
* Sorting order of blocks.
*/
private enum Filter
{
/**
* By name
*/
NAME,
/**
* By value
*/
VALUE,
/**
* By number
*/
COUNT
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable holds targeted island.
*/
private final Island island;
/**
* This variable holds targeted island level data.
*/
private final IslandLevels levelsData;
/**
* This variable allows to access addon object.
*/
private final Level addon;
/**
* This variable holds user who opens panel. Without it panel cannot be opened.
*/
private final User user;
/**
* This variable holds a world to which gui referee.
*/
private final World world;
/**
* This variable stores the list of elements to display.
*/
private final List<Pair<Material, Integer>> materialCountList;
/**
* This variable holds current pageIndex for multi-page generator choosing.
*/
private int pageIndex;
/**
* This variable stores which tab currently is active.
*/
private Tab activeTab;
/**
* This variable stores active filter for items.
*/
private Filter activeFilter;
}