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
This commit is contained in:
parent
cc90579f51
commit
47053fde31
2
pom.xml
2
pom.xml
|
@ -61,7 +61,7 @@
|
||||||
<spigot.version>1.16.5-R0.1-SNAPSHOT</spigot.version>
|
<spigot.version>1.16.5-R0.1-SNAPSHOT</spigot.version>
|
||||||
<bentobox.version>1.20.0</bentobox.version>
|
<bentobox.version>1.20.0</bentobox.version>
|
||||||
<!-- Panel Utils version -->
|
<!-- Panel Utils version -->
|
||||||
<panelutils.version>1.0.0</panelutils.version>
|
<panelutils.version>1.1.0</panelutils.version>
|
||||||
<!-- Revision variable removes warning about dynamic version -->
|
<!-- Revision variable removes warning about dynamic version -->
|
||||||
<revision>${build.version}-SNAPSHOT</revision>
|
<revision>${build.version}-SNAPSHOT</revision>
|
||||||
<!-- Do not change unless you want different name for local builds. -->
|
<!-- Do not change unless you want different name for local builds. -->
|
||||||
|
|
|
@ -78,6 +78,7 @@ public class Level extends Addon implements Listener {
|
||||||
// Save existing panels.
|
// Save existing panels.
|
||||||
this.saveResource("panels/top_panel.yml", false);
|
this.saveResource("panels/top_panel.yml", false);
|
||||||
this.saveResource("panels/detail_panel.yml", false);
|
this.saveResource("panels/detail_panel.yml", false);
|
||||||
|
this.saveResource("panels/value_panel.yml", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean loadSettings() {
|
private boolean loadSettings() {
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package world.bentobox.level.commands;
|
package world.bentobox.level.commands;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
@ -8,43 +11,132 @@ import org.bukkit.inventory.PlayerInventory;
|
||||||
|
|
||||||
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
import world.bentobox.bentobox.api.commands.CompositeCommand;
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
|
import world.bentobox.bentobox.util.Util;
|
||||||
import world.bentobox.level.Level;
|
import world.bentobox.level.Level;
|
||||||
|
import world.bentobox.level.panels.ValuePanel;
|
||||||
|
import world.bentobox.level.util.Utils;
|
||||||
|
|
||||||
public class IslandValueCommand extends CompositeCommand {
|
|
||||||
|
public class IslandValueCommand extends CompositeCommand
|
||||||
|
{
|
||||||
private final Level addon;
|
private final Level addon;
|
||||||
|
|
||||||
public IslandValueCommand(Level addon, CompositeCommand parent) {
|
|
||||||
|
public IslandValueCommand(Level addon, CompositeCommand parent)
|
||||||
|
{
|
||||||
super(parent, "value");
|
super(parent, "value");
|
||||||
this.addon = addon;
|
this.addon = addon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setup() {
|
public void setup()
|
||||||
|
{
|
||||||
this.setPermission("island.value");
|
this.setPermission("island.value");
|
||||||
this.setDescription("island.value.description");
|
this.setParametersHelp("level.commands.value.parameters");
|
||||||
|
this.setDescription("level.commands.value.description");
|
||||||
this.setOnlyPlayer(true);
|
this.setOnlyPlayer(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(User user, String label, List<String> args) {
|
public boolean execute(User user, String label, List<String> args)
|
||||||
Player player = user.getPlayer();
|
{
|
||||||
PlayerInventory inventory = player.getInventory();
|
if (args.size() > 1)
|
||||||
if (!inventory.getItemInMainHand().getType().equals(Material.AIR)) {
|
{
|
||||||
Material material = inventory.getItemInMainHand().getType();
|
this.showHelp(this, user);
|
||||||
Integer value = addon.getBlockConfig().getValue(getWorld(), material);
|
return true;
|
||||||
if (value != null) {
|
|
||||||
user.sendMessage("island.value.success", "[value]", String.valueOf(value));
|
|
||||||
double underWater = addon.getSettings().getUnderWaterMultiplier();
|
|
||||||
if (underWater > 1.0) {
|
|
||||||
user.sendMessage("island.value.success-underwater", "[value]", (underWater * value) + "");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
user.sendMessage("island.value.no-value");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
user.sendMessage("island.value.empty-hand");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.isEmpty())
|
||||||
|
{
|
||||||
|
ValuePanel.openPanel(this.addon, this.getWorld(), user);
|
||||||
|
}
|
||||||
|
else if (args.get(0).equalsIgnoreCase("HAND"))
|
||||||
|
{
|
||||||
|
Player player = user.getPlayer();
|
||||||
|
PlayerInventory inventory = player.getInventory();
|
||||||
|
|
||||||
|
if (!inventory.getItemInMainHand().getType().equals(Material.AIR))
|
||||||
|
{
|
||||||
|
this.printValue(user, inventory.getItemInMainHand().getType());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Utils.sendMessage(user, user.getTranslation("level.conversations.empty-hand"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Material material = Material.matchMaterial(args.get(0));
|
||||||
|
|
||||||
|
if (material == null)
|
||||||
|
{
|
||||||
|
Utils.sendMessage(user,
|
||||||
|
user.getTranslation(this.getWorld(), "level.conversations.unknown-item",
|
||||||
|
"[material]", args.get(0)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.printValue(user, material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* This method prints value of the given material in chat.
|
||||||
|
* @param user User who receives the message.
|
||||||
|
* @param material Material value.
|
||||||
|
*/
|
||||||
|
private void printValue(User user, Material material)
|
||||||
|
{
|
||||||
|
Integer value = this.addon.getBlockConfig().getValue(getWorld(), material);
|
||||||
|
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
Utils.sendMessage(user,
|
||||||
|
user.getTranslation(this.getWorld(), "level.conversations.value",
|
||||||
|
"[value]", String.valueOf(value),
|
||||||
|
"[material]", Utils.prettifyObject(material, user)));
|
||||||
|
|
||||||
|
double underWater = this.addon.getSettings().getUnderWaterMultiplier();
|
||||||
|
|
||||||
|
if (underWater > 1.0)
|
||||||
|
{
|
||||||
|
Utils.sendMessage(user,
|
||||||
|
user.getTranslation(this.getWorld(),"level.conversations.success-underwater",
|
||||||
|
"[value]", (underWater * value) + ""),
|
||||||
|
"[material]", Utils.prettifyObject(material, user));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Utils.sendMessage(user,
|
||||||
|
user.getTranslation(this.getWorld(),"level.conversations.no-value"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Optional<List<String>> tabComplete(User user, String alias, List<String> args)
|
||||||
|
{
|
||||||
|
String lastArg = !args.isEmpty() ? args.get(args.size() - 1) : "";
|
||||||
|
|
||||||
|
if (args.isEmpty())
|
||||||
|
{
|
||||||
|
// Don't show every player on the server. Require at least the first letter
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> options = new ArrayList<>(Arrays.stream(Material.values()).
|
||||||
|
filter(Material::isBlock).
|
||||||
|
map(Material::name).toList());
|
||||||
|
|
||||||
|
options.add("HAND");
|
||||||
|
|
||||||
|
return Optional.of(Util.tabLimit(options, lastArg));
|
||||||
|
}
|
||||||
|
}
|
|
@ -165,8 +165,8 @@ public class DetailsPanel
|
||||||
{
|
{
|
||||||
if (o1.getValue().equals(o2.getValue()))
|
if (o1.getValue().equals(o2.getValue()))
|
||||||
{
|
{
|
||||||
String o1Name = DetailsPanel.prettifyObject(o1.getKey(), this.user);
|
String o1Name = Utils.prettifyObject(o1.getKey(), this.user);
|
||||||
String o2Name = DetailsPanel.prettifyObject(o2.getKey(), this.user);
|
String o2Name = Utils.prettifyObject(o2.getKey(), this.user);
|
||||||
|
|
||||||
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
||||||
}
|
}
|
||||||
|
@ -193,8 +193,8 @@ public class DetailsPanel
|
||||||
|
|
||||||
if (o1Value == o2Value)
|
if (o1Value == o2Value)
|
||||||
{
|
{
|
||||||
String o1Name = DetailsPanel.prettifyObject(o1.getKey(), this.user);
|
String o1Name = Utils.prettifyObject(o1.getKey(), this.user);
|
||||||
String o2Name = DetailsPanel.prettifyObject(o2.getKey(), this.user);
|
String o2Name = Utils.prettifyObject(o2.getKey(), this.user);
|
||||||
|
|
||||||
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
||||||
}
|
}
|
||||||
|
@ -208,8 +208,8 @@ public class DetailsPanel
|
||||||
{
|
{
|
||||||
sorter = (o1, o2) ->
|
sorter = (o1, o2) ->
|
||||||
{
|
{
|
||||||
String o1Name = DetailsPanel.prettifyObject(o1.getKey(), this.user);
|
String o1Name = Utils.prettifyObject(o1.getKey(), this.user);
|
||||||
String o2Name = DetailsPanel.prettifyObject(o2.getKey(), this.user);
|
String o2Name = Utils.prettifyObject(o2.getKey(), this.user);
|
||||||
|
|
||||||
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
||||||
};
|
};
|
||||||
|
@ -647,10 +647,10 @@ public class DetailsPanel
|
||||||
{
|
{
|
||||||
builder.name(this.user.getTranslation(this.world, template.title(),
|
builder.name(this.user.getTranslation(this.world, template.title(),
|
||||||
"[number]", String.valueOf(materialCount.getValue()),
|
"[number]", String.valueOf(materialCount.getValue()),
|
||||||
"[material]", DetailsPanel.prettifyObject(materialCount.getKey(), this.user)));
|
"[material]", Utils.prettifyObject(materialCount.getKey(), this.user)));
|
||||||
}
|
}
|
||||||
|
|
||||||
String description = DetailsPanel.prettifyDescription(materialCount.getKey(), this.user);
|
String description = Utils.prettifyDescription(materialCount.getKey(), this.user);
|
||||||
|
|
||||||
final String reference = "level.gui.buttons.material.";
|
final String reference = "level.gui.buttons.material.";
|
||||||
String blockId = this.user.getTranslationOrNothing(reference + "id",
|
String blockId = this.user.getTranslationOrNothing(reference + "id",
|
||||||
|
@ -710,95 +710,6 @@ public class DetailsPanel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prettify Material object for user.
|
|
||||||
* @param object Object that must be pretty.
|
|
||||||
* @param user User who will see the object.
|
|
||||||
* @return Prettified string for Material.
|
|
||||||
*/
|
|
||||||
private static String prettifyObject(Material object, User user)
|
|
||||||
{
|
|
||||||
// Nothing to translate
|
|
||||||
if (object == null)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find addon structure with:
|
|
||||||
// [addon]:
|
|
||||||
// materials:
|
|
||||||
// [material]:
|
|
||||||
// name: [name]
|
|
||||||
String translation = user.getTranslationOrNothing("level.materials." + object.name().toLowerCase() + ".name");
|
|
||||||
|
|
||||||
if (!translation.isEmpty())
|
|
||||||
{
|
|
||||||
// We found our translation.
|
|
||||||
return translation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find addon structure with:
|
|
||||||
// [addon]:
|
|
||||||
// materials:
|
|
||||||
// [material]: [name]
|
|
||||||
|
|
||||||
translation = user.getTranslationOrNothing("level.materials." + object.name().toLowerCase());
|
|
||||||
|
|
||||||
if (!translation.isEmpty())
|
|
||||||
{
|
|
||||||
// We found our translation.
|
|
||||||
return translation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find general structure with:
|
|
||||||
// materials:
|
|
||||||
// [material]: [name]
|
|
||||||
|
|
||||||
translation = user.getTranslationOrNothing("materials." + object.name().toLowerCase());
|
|
||||||
|
|
||||||
if (!translation.isEmpty())
|
|
||||||
{
|
|
||||||
// We found our translation.
|
|
||||||
return translation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use Lang Utils Hook to translate material
|
|
||||||
return LangUtilsHook.getMaterialName(object, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prettify Material object description for user.
|
|
||||||
* @param object Object that must be pretty.
|
|
||||||
* @param user User who will see the object.
|
|
||||||
* @return Prettified description string for Material.
|
|
||||||
*/
|
|
||||||
public static String prettifyDescription(Material object, User user)
|
|
||||||
{
|
|
||||||
// Nothing to translate
|
|
||||||
if (object == null)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find addon structure with:
|
|
||||||
// [addon]:
|
|
||||||
// materials:
|
|
||||||
// [material]:
|
|
||||||
// description: [text]
|
|
||||||
String translation = user.getTranslationOrNothing("level.materials." + object.name().toLowerCase() + ".description");
|
|
||||||
|
|
||||||
if (!translation.isEmpty())
|
|
||||||
{
|
|
||||||
// We found our translation.
|
|
||||||
return translation;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No text to return.
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
// Section: Enums
|
// Section: Enums
|
||||||
// ---------------------------------------------------------------------
|
// ---------------------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,773 @@
|
||||||
|
package world.bentobox.level.panels;
|
||||||
|
|
||||||
|
|
||||||
|
import com.google.common.base.Enums;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import lv.id.bonne.panelutils.PanelUtils;
|
||||||
|
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.hooks.LangUtilsHook;
|
||||||
|
import world.bentobox.bentobox.util.Pair;
|
||||||
|
import world.bentobox.level.Level;
|
||||||
|
import world.bentobox.level.util.ConversationUtils;
|
||||||
|
import world.bentobox.level.util.Utils;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class opens GUI that shows generator view for user.
|
||||||
|
*/
|
||||||
|
public class ValuePanel
|
||||||
|
{
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// 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 ValuePanel(Level addon,
|
||||||
|
World world,
|
||||||
|
User user)
|
||||||
|
{
|
||||||
|
this.addon = addon;
|
||||||
|
this.world = world;
|
||||||
|
this.user = user;
|
||||||
|
|
||||||
|
this.activeFilter = Filter.NAME_ASC;
|
||||||
|
this.materialRecordList = Arrays.stream(Material.values()).
|
||||||
|
filter(Material::isBlock).
|
||||||
|
filter(m -> !m.name().startsWith("LEGACY_")).
|
||||||
|
map(material ->
|
||||||
|
{
|
||||||
|
Integer value = this.addon.getBlockConfig().getValue(this.world, material);
|
||||||
|
Integer limit = this.addon.getBlockConfig().getBlockLimits().get(material);
|
||||||
|
|
||||||
|
return new MaterialRecord(material,
|
||||||
|
value != null ? value : 0,
|
||||||
|
limit != null ? limit : 0);
|
||||||
|
}).
|
||||||
|
collect(Collectors.toList());
|
||||||
|
|
||||||
|
this.elementList = new ArrayList<>(Material.values().length);
|
||||||
|
this.searchText = "";
|
||||||
|
|
||||||
|
this.updateFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method builds this GUI.
|
||||||
|
*/
|
||||||
|
private void build()
|
||||||
|
{
|
||||||
|
// Start building panel.
|
||||||
|
TemplatedPanelBuilder panelBuilder = new TemplatedPanelBuilder();
|
||||||
|
panelBuilder.user(this.user);
|
||||||
|
panelBuilder.world(this.user.getWorld());
|
||||||
|
|
||||||
|
panelBuilder.template("value_panel", new File(this.addon.getDataFolder(), "panels"));
|
||||||
|
|
||||||
|
panelBuilder.registerTypeBuilder("NEXT", this::createNextButton);
|
||||||
|
panelBuilder.registerTypeBuilder("PREVIOUS", this::createPreviousButton);
|
||||||
|
panelBuilder.registerTypeBuilder("BLOCK", this::createMaterialButton);
|
||||||
|
|
||||||
|
panelBuilder.registerTypeBuilder("FILTER", this::createFilterButton);
|
||||||
|
panelBuilder.registerTypeBuilder("SEARCH", this::createSearchButton);
|
||||||
|
|
||||||
|
// Register unknown type builder.
|
||||||
|
panelBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method updates filter of elements based on tabs.
|
||||||
|
*/
|
||||||
|
private void updateFilters()
|
||||||
|
{
|
||||||
|
Comparator<MaterialRecord> sorter;
|
||||||
|
|
||||||
|
switch (this.activeFilter)
|
||||||
|
{
|
||||||
|
case VALUE_ASC ->
|
||||||
|
{
|
||||||
|
sorter = (o1, o2) ->
|
||||||
|
{
|
||||||
|
if (o1.value().equals(o2.value()))
|
||||||
|
{
|
||||||
|
String o1Name = Utils.prettifyObject(o1.material(), this.user);
|
||||||
|
String o2Name = Utils.prettifyObject(o2.material(), this.user);
|
||||||
|
|
||||||
|
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Integer.compare(o1.value(), o2.value());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case VALUE_DESC ->
|
||||||
|
{
|
||||||
|
sorter = (o1, o2) ->
|
||||||
|
{
|
||||||
|
if (o1.value().equals(o2.value()))
|
||||||
|
{
|
||||||
|
String o1Name = Utils.prettifyObject(o1.material(), this.user);
|
||||||
|
String o2Name = Utils.prettifyObject(o2.material(), this.user);
|
||||||
|
|
||||||
|
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Integer.compare(o2.value(), o1.value());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case NAME_DESC ->
|
||||||
|
{
|
||||||
|
sorter = (o1, o2) ->
|
||||||
|
{
|
||||||
|
String o1Name = Utils.prettifyObject(o1.material(), this.user);
|
||||||
|
String o2Name = Utils.prettifyObject(o2.material(), this.user);
|
||||||
|
|
||||||
|
return String.CASE_INSENSITIVE_ORDER.compare(o2Name, o1Name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default ->
|
||||||
|
{
|
||||||
|
sorter = (o1, o2) ->
|
||||||
|
{
|
||||||
|
String o1Name = Utils.prettifyObject(o1.material(), this.user);
|
||||||
|
String o2Name = Utils.prettifyObject(o2.material(), this.user);
|
||||||
|
|
||||||
|
return String.CASE_INSENSITIVE_ORDER.compare(o1Name, o2Name);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.materialRecordList.sort(sorter);
|
||||||
|
|
||||||
|
if (!this.searchText.isBlank())
|
||||||
|
{
|
||||||
|
this.elementList = new ArrayList<>(this.materialRecordList.size());
|
||||||
|
final String text = this.searchText.toLowerCase();
|
||||||
|
|
||||||
|
this.materialRecordList.forEach(record ->
|
||||||
|
{
|
||||||
|
if (record.material.name().toLowerCase().contains(text) ||
|
||||||
|
Utils.prettifyObject(record.material(), this.user).toLowerCase().contains(text))
|
||||||
|
{
|
||||||
|
this.elementList.add(record);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.elementList = this.materialRecordList;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 createSearchButton(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(), "[text]", this.searchText));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (template.description() != null)
|
||||||
|
{
|
||||||
|
// Set description
|
||||||
|
builder.description(this.user.getTranslation(this.world, template.description(), "[text]", this.searchText));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get only possible actions, by removing all inactive ones.
|
||||||
|
List<ItemTemplateRecord.ActionRecords> activeActions = new ArrayList<>(template.actions());
|
||||||
|
|
||||||
|
activeActions.removeIf(action ->
|
||||||
|
"CLEAR".equalsIgnoreCase(action.actionType()) && this.searchText.isBlank());
|
||||||
|
|
||||||
|
// Add Click handler
|
||||||
|
builder.clickHandler((panel, user, clickType, i) ->
|
||||||
|
{
|
||||||
|
for (ItemTemplateRecord.ActionRecords action : activeActions)
|
||||||
|
{
|
||||||
|
if (clickType == action.clickType() || ClickType.UNKNOWN.equals(action.clickType()))
|
||||||
|
{
|
||||||
|
if ("CLEAR".equalsIgnoreCase(action.actionType()))
|
||||||
|
{
|
||||||
|
this.searchText = "";
|
||||||
|
|
||||||
|
// Update filters.
|
||||||
|
this.updateFilters();
|
||||||
|
this.build();
|
||||||
|
}
|
||||||
|
else if ("INPUT".equalsIgnoreCase(action.actionType()))
|
||||||
|
{
|
||||||
|
// Create consumer that process description change
|
||||||
|
Consumer<String> consumer = value ->
|
||||||
|
{
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
this.searchText = value;
|
||||||
|
this.updateFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.build();
|
||||||
|
};
|
||||||
|
|
||||||
|
// start conversation
|
||||||
|
ConversationUtils.createStringInput(consumer,
|
||||||
|
user,
|
||||||
|
user.getTranslation("level.conversations.write-search"),
|
||||||
|
user.getTranslation("level.conversations.search-updated"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.searchText.isBlank());
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
String filterName = String.valueOf(template.dataMap().get("filter"));
|
||||||
|
|
||||||
|
final String reference = "level.gui.buttons.filters.";
|
||||||
|
|
||||||
|
if (template.title() != null)
|
||||||
|
{
|
||||||
|
// Set title
|
||||||
|
builder.name(this.user.getTranslation(this.world, template.title()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.name(this.user.getTranslation(this.world, reference + filterName.toLowerCase() + ".name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (template.description() != null)
|
||||||
|
{
|
||||||
|
// Set description
|
||||||
|
builder.description(this.user.getTranslation(this.world, template.description()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.name(this.user.getTranslation(this.world, reference + filterName.toLowerCase() + ".description"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get only possible actions, by removing all inactive ones.
|
||||||
|
List<ItemTemplateRecord.ActionRecords> activeActions = new ArrayList<>(template.actions());
|
||||||
|
|
||||||
|
activeActions.removeIf(action -> {
|
||||||
|
if (this.activeFilter.name().startsWith(filterName))
|
||||||
|
{
|
||||||
|
return this.activeFilter.name().endsWith("ASC") && "ASC".equalsIgnoreCase(action.actionType()) ||
|
||||||
|
this.activeFilter.name().endsWith("DESC") && "DESC".equalsIgnoreCase(action.actionType());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "DESC".equalsIgnoreCase(action.actionType());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add Click handler
|
||||||
|
builder.clickHandler((panel, user, clickType, i) ->
|
||||||
|
{
|
||||||
|
for (ItemTemplateRecord.ActionRecords action : activeActions)
|
||||||
|
{
|
||||||
|
if (clickType == action.clickType() || ClickType.UNKNOWN.equals(action.clickType()))
|
||||||
|
{
|
||||||
|
if ("ASC".equalsIgnoreCase(action.actionType()))
|
||||||
|
{
|
||||||
|
this.activeFilter = Enums.getIfPresent(Filter.class, filterName + "_ASC").or(Filter.NAME_ASC);
|
||||||
|
|
||||||
|
// Update filters.
|
||||||
|
this.updateFilters();
|
||||||
|
this.build();
|
||||||
|
}
|
||||||
|
else if ("DESC".equalsIgnoreCase(action.actionType()))
|
||||||
|
{
|
||||||
|
this.activeFilter = Enums.getIfPresent(Filter.class, filterName + "_DESC").or(Filter.NAME_DESC);
|
||||||
|
|
||||||
|
// 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.name().startsWith(filterName.toUpperCase()));
|
||||||
|
|
||||||
|
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.elementList.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) 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(),
|
||||||
|
"[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()))
|
||||||
|
{
|
||||||
|
if ("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) 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(),
|
||||||
|
"[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()))
|
||||||
|
{
|
||||||
|
if ("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.elementList.isEmpty())
|
||||||
|
{
|
||||||
|
// Does not contain any generators.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = this.pageIndex * slot.amountMap().getOrDefault("BLOCK", 1) + slot.slot();
|
||||||
|
|
||||||
|
if (index >= this.elementList.size())
|
||||||
|
{
|
||||||
|
// Out of index.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.createMaterialButton(template, this.elementList.get(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates button for material.
|
||||||
|
*
|
||||||
|
* @param template the template of the button
|
||||||
|
* @param materialRecord materialRecord which button must be created.
|
||||||
|
* @return PanelItem for generator tier.
|
||||||
|
*/
|
||||||
|
private PanelItem createMaterialButton(ItemTemplateRecord template,
|
||||||
|
MaterialRecord materialRecord)
|
||||||
|
{
|
||||||
|
PanelItemBuilder builder = new PanelItemBuilder();
|
||||||
|
|
||||||
|
if (template.icon() != null)
|
||||||
|
{
|
||||||
|
builder.icon(template.icon().clone());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.icon(PanelUtils.getMaterialItem(materialRecord.material()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (materialRecord.value() <= 64 && materialRecord.value() > 0)
|
||||||
|
{
|
||||||
|
builder.amount(materialRecord.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (template.title() != null)
|
||||||
|
{
|
||||||
|
builder.name(this.user.getTranslation(this.world, template.title(),
|
||||||
|
"[material]", Utils.prettifyObject(materialRecord.material(), this.user)));
|
||||||
|
}
|
||||||
|
|
||||||
|
String description = Utils.prettifyDescription(materialRecord.material(), this.user);
|
||||||
|
|
||||||
|
final String reference = "level.gui.buttons.material.";
|
||||||
|
String blockId = this.user.getTranslationOrNothing(reference + "id",
|
||||||
|
"[id]", materialRecord.material().name());
|
||||||
|
|
||||||
|
String value = this.user.getTranslationOrNothing(reference + "value",
|
||||||
|
"[number]", String.valueOf(materialRecord.value()));
|
||||||
|
|
||||||
|
String underWater;
|
||||||
|
|
||||||
|
if (this.addon.getSettings().getUnderWaterMultiplier() > 1.0)
|
||||||
|
{
|
||||||
|
underWater = this.user.getTranslationOrNothing(reference + "underwater",
|
||||||
|
"[number]", String.valueOf(materialRecord.value() * this.addon.getSettings().getUnderWaterMultiplier()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
underWater = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
String limit = materialRecord.limit() > 0 ? this.user.getTranslationOrNothing(reference + "limit",
|
||||||
|
"[number]", String.valueOf(materialRecord.limit())) : "";
|
||||||
|
|
||||||
|
if (template.description() != null)
|
||||||
|
{
|
||||||
|
builder.description(this.user.getTranslation(this.world, template.description(),
|
||||||
|
"[description]", description,
|
||||||
|
"[id]", blockId,
|
||||||
|
"[value]", value,
|
||||||
|
"[underwater]", underWater,
|
||||||
|
"[limit]", limit).
|
||||||
|
replaceAll("(?m)^[ \\t]*\\r?\\n", "").
|
||||||
|
replaceAll("(?<!\\\\)\\|", "\n").
|
||||||
|
replaceAll("\\\\\\|", "|"));
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.clickHandler((panel, user1, clickType, i) -> {
|
||||||
|
System.out.println("Material: " + materialRecord.material());
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
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 ValuePanel(addon, world, user).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Section: Enums
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorting order of blocks.
|
||||||
|
*/
|
||||||
|
private enum Filter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* By name asc
|
||||||
|
*/
|
||||||
|
NAME_ASC,
|
||||||
|
/**
|
||||||
|
* By name desc
|
||||||
|
*/
|
||||||
|
NAME_DESC,
|
||||||
|
/**
|
||||||
|
* By value asc
|
||||||
|
*/
|
||||||
|
VALUE_ASC,
|
||||||
|
/**
|
||||||
|
* By value desc
|
||||||
|
*/
|
||||||
|
VALUE_DESC,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private record MaterialRecord(Material material, Integer value, Integer limit)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Section: Variables
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<MaterialRecord> materialRecordList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This variable stores the list of elements to display.
|
||||||
|
*/
|
||||||
|
private List<MaterialRecord> elementList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This variable holds current pageIndex for multi-page generator choosing.
|
||||||
|
*/
|
||||||
|
private int pageIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This variable stores which tab currently is active.
|
||||||
|
*/
|
||||||
|
private String searchText;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This variable stores active filter for items.
|
||||||
|
*/
|
||||||
|
private Filter activeFilter;
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
//
|
||||||
|
// Created by BONNe
|
||||||
|
// Copyright - 2021
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
package world.bentobox.level.util;
|
||||||
|
|
||||||
|
|
||||||
|
import org.bukkit.conversations.*;
|
||||||
|
import org.eclipse.jdt.annotation.NonNull;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import world.bentobox.bentobox.BentoBox;
|
||||||
|
import world.bentobox.bentobox.api.user.User;
|
||||||
|
|
||||||
|
|
||||||
|
public class ConversationUtils
|
||||||
|
{
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
// Section: Conversation API implementation
|
||||||
|
// ---------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method will close opened gui and writes question in chat. After players answers on question in chat, message
|
||||||
|
* will trigger consumer and gui will reopen.
|
||||||
|
*
|
||||||
|
* @param consumer Consumer that accepts player output text.
|
||||||
|
* @param question Message that will be displayed in chat when player triggers conversion.
|
||||||
|
* @param user User who is targeted with current confirmation.
|
||||||
|
*/
|
||||||
|
public static void createStringInput(Consumer<String> consumer,
|
||||||
|
User user,
|
||||||
|
@NonNull String question,
|
||||||
|
@Nullable String successMessage)
|
||||||
|
{
|
||||||
|
// Text input message.
|
||||||
|
StringPrompt stringPrompt = new StringPrompt()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public @NonNull String getPromptText(@NonNull ConversationContext context)
|
||||||
|
{
|
||||||
|
user.closeInventory();
|
||||||
|
return question;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NonNull Prompt acceptInput(@NonNull ConversationContext context, @Nullable String input)
|
||||||
|
{
|
||||||
|
consumer.accept(input);
|
||||||
|
return ConversationUtils.endMessagePrompt(successMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
new ConversationFactory(BentoBox.getInstance()).
|
||||||
|
withPrefix(context -> user.getTranslation("level.conversations.prefix")).
|
||||||
|
withFirstPrompt(stringPrompt).
|
||||||
|
// On cancel conversation will be closed.
|
||||||
|
withLocalEcho(false).
|
||||||
|
withTimeout(90).
|
||||||
|
withEscapeSequence(user.getTranslation("level.conversations.cancel-string")).
|
||||||
|
// Use null value in consumer to detect if user has abandoned conversation.
|
||||||
|
addConversationAbandonedListener(ConversationUtils.getAbandonListener(consumer, user)).
|
||||||
|
buildConversation(user.getPlayer()).
|
||||||
|
begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is just a simple end message prompt that displays requested message.
|
||||||
|
*
|
||||||
|
* @param message Message that will be displayed.
|
||||||
|
* @return MessagePrompt that displays given message and exists from conversation.
|
||||||
|
*/
|
||||||
|
private static MessagePrompt endMessagePrompt(@Nullable String message)
|
||||||
|
{
|
||||||
|
return new MessagePrompt()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public @NonNull String getPromptText(@NonNull ConversationContext context)
|
||||||
|
{
|
||||||
|
return message == null ? "" : message;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @Nullable Prompt getNextPrompt(@NonNull ConversationContext context)
|
||||||
|
{
|
||||||
|
return Prompt.END_OF_CONVERSATION;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method creates and returns abandon listener for every conversation.
|
||||||
|
*
|
||||||
|
* @param consumer Consumer which must return null value.
|
||||||
|
* @param user User who was using conversation.
|
||||||
|
* @return ConversationAbandonedListener instance.
|
||||||
|
*/
|
||||||
|
private static ConversationAbandonedListener getAbandonListener(Consumer<?> consumer, User user)
|
||||||
|
{
|
||||||
|
return abandonedEvent ->
|
||||||
|
{
|
||||||
|
if (!abandonedEvent.gracefulExit())
|
||||||
|
{
|
||||||
|
consumer.accept(null);
|
||||||
|
// send cancell message
|
||||||
|
abandonedEvent.getContext().getForWhom().sendRawMessage(
|
||||||
|
user.getTranslation("level.conversations.prefix") +
|
||||||
|
user.getTranslation("level.conversations.cancelled"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,11 +7,13 @@
|
||||||
package world.bentobox.level.util;
|
package world.bentobox.level.util;
|
||||||
|
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import world.bentobox.bentobox.api.user.User;
|
import world.bentobox.bentobox.api.user.User;
|
||||||
|
import world.bentobox.bentobox.hooks.LangUtilsHook;
|
||||||
|
|
||||||
|
|
||||||
public class Utils
|
public class Utils
|
||||||
|
@ -131,4 +133,93 @@ public class Utils
|
||||||
|
|
||||||
return currentValue;
|
return currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prettify Material object for user.
|
||||||
|
* @param object Object that must be pretty.
|
||||||
|
* @param user User who will see the object.
|
||||||
|
* @return Prettified string for Material.
|
||||||
|
*/
|
||||||
|
public static String prettifyObject(Material object, User user)
|
||||||
|
{
|
||||||
|
// Nothing to translate
|
||||||
|
if (object == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find addon structure with:
|
||||||
|
// [addon]:
|
||||||
|
// materials:
|
||||||
|
// [material]:
|
||||||
|
// name: [name]
|
||||||
|
String translation = user.getTranslationOrNothing("level.materials." + object.name().toLowerCase() + ".name");
|
||||||
|
|
||||||
|
if (!translation.isEmpty())
|
||||||
|
{
|
||||||
|
// We found our translation.
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find addon structure with:
|
||||||
|
// [addon]:
|
||||||
|
// materials:
|
||||||
|
// [material]: [name]
|
||||||
|
|
||||||
|
translation = user.getTranslationOrNothing("level.materials." + object.name().toLowerCase());
|
||||||
|
|
||||||
|
if (!translation.isEmpty())
|
||||||
|
{
|
||||||
|
// We found our translation.
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find general structure with:
|
||||||
|
// materials:
|
||||||
|
// [material]: [name]
|
||||||
|
|
||||||
|
translation = user.getTranslationOrNothing("materials." + object.name().toLowerCase());
|
||||||
|
|
||||||
|
if (!translation.isEmpty())
|
||||||
|
{
|
||||||
|
// We found our translation.
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use Lang Utils Hook to translate material
|
||||||
|
return LangUtilsHook.getMaterialName(object, user);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prettify Material object description for user.
|
||||||
|
* @param object Object that must be pretty.
|
||||||
|
* @param user User who will see the object.
|
||||||
|
* @return Prettified description string for Material.
|
||||||
|
*/
|
||||||
|
public static String prettifyDescription(Material object, User user)
|
||||||
|
{
|
||||||
|
// Nothing to translate
|
||||||
|
if (object == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find addon structure with:
|
||||||
|
// [addon]:
|
||||||
|
// materials:
|
||||||
|
// [material]:
|
||||||
|
// description: [text]
|
||||||
|
String translation = user.getTranslationOrNothing("level.materials." + object.name().toLowerCase() + ".description");
|
||||||
|
|
||||||
|
if (!translation.isEmpty())
|
||||||
|
{
|
||||||
|
// We found our translation.
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No text to return.
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,18 +55,16 @@ island:
|
||||||
syntax: "[name] x [number]"
|
syntax: "[name] x [number]"
|
||||||
hint: "&c Run level to see the block report"
|
hint: "&c Run level to see the block report"
|
||||||
|
|
||||||
value:
|
|
||||||
description: "shows the value of any block"
|
|
||||||
success: "&7 The value of this block is: &e[value]"
|
|
||||||
success-underwater: "&7 The value of this block below sea-level: &e[value]"
|
|
||||||
empty-hand: "&c There are no blocks in your hand"
|
|
||||||
no-value: "&c That item has no value."
|
|
||||||
|
|
||||||
level:
|
level:
|
||||||
|
commands:
|
||||||
|
value:
|
||||||
|
parameters: "[hand|<material>]"
|
||||||
|
description: "shows the value of blocks. Add 'hand' at the end to display value for item in hand."
|
||||||
gui:
|
gui:
|
||||||
titles:
|
titles:
|
||||||
top: "&0&l Top Islands"
|
top: "&0&l Top Islands"
|
||||||
detail-panel: "&0&l [name]'s island"
|
detail-panel: "&0&l [name]'s island"
|
||||||
|
value-panel: "&0&l Block Values"
|
||||||
buttons:
|
buttons:
|
||||||
island:
|
island:
|
||||||
empty: '&f&l [name]. place'
|
empty: '&f&l [name]. place'
|
||||||
|
@ -138,6 +136,18 @@ level:
|
||||||
name: "&f&l Sort by Count"
|
name: "&f&l Sort by Count"
|
||||||
description: |-
|
description: |-
|
||||||
&7 Sort all blocks by their amount.
|
&7 Sort all blocks by their amount.
|
||||||
|
value:
|
||||||
|
name: "&f&l [material]"
|
||||||
|
description: |-
|
||||||
|
[description]
|
||||||
|
[value]
|
||||||
|
[underwater]
|
||||||
|
[limit]
|
||||||
|
[id]
|
||||||
|
id: "&7 Block id: &e [id]"
|
||||||
|
value: "&7 Block value: &e [number]"
|
||||||
|
underwater: "&7 Bellow sea level: &e [number]"
|
||||||
|
limit: "&7 Block limit: &e [number]"
|
||||||
# Button that is used in multi-page GUIs which allows to return to previous page.
|
# Button that is used in multi-page GUIs which allows to return to previous page.
|
||||||
previous:
|
previous:
|
||||||
name: "&f&l Previous Page"
|
name: "&f&l Previous Page"
|
||||||
|
@ -148,6 +158,12 @@ level:
|
||||||
name: "&f&l Next Page"
|
name: "&f&l Next Page"
|
||||||
description: |-
|
description: |-
|
||||||
&7 Switch to [number] page
|
&7 Switch to [number] page
|
||||||
|
search:
|
||||||
|
name: "&f&l Search"
|
||||||
|
description: |-
|
||||||
|
&7 Search for a specific
|
||||||
|
&7 value.
|
||||||
|
search: "&b Value: [value]"
|
||||||
tips:
|
tips:
|
||||||
click-to-view: "&e Click &7 to view."
|
click-to-view: "&e Click &7 to view."
|
||||||
click-to-previous: "&e Click &7 to view previous page."
|
click-to-previous: "&e Click &7 to view previous page."
|
||||||
|
@ -155,7 +171,30 @@ level:
|
||||||
click-to-select: "&e Click &7 to select."
|
click-to-select: "&e Click &7 to select."
|
||||||
left-click-to-cycle-up: "&e Left Click &7 to cycle up."
|
left-click-to-cycle-up: "&e Left Click &7 to cycle up."
|
||||||
right-click-to-cycle-down: "&e Right Click &7 to cycle down."
|
right-click-to-cycle-down: "&e Right Click &7 to cycle down."
|
||||||
|
left-click-to-change: "&e Left Click &7 to edit."
|
||||||
|
right-click-to-clear: "&e Right Click &7 to clear."
|
||||||
|
click-to-asc: "&e Click &7 to sort in increasing order."
|
||||||
|
click-to-desc: "&e Click &7 to sort in decreasing order."
|
||||||
conversations:
|
conversations:
|
||||||
# Prefix for messages that are send from server.
|
# Prefix for messages that are send from server.
|
||||||
prefix: "&l&6 [BentoBox]: &r"
|
prefix: "&l&6 [BentoBox]: &r"
|
||||||
no-data: "&c Run level to see the block report."
|
no-data: "&c Run level to see the block report."
|
||||||
|
# String that allows to cancel conversation. (can be only one)
|
||||||
|
cancel-string: "cancel"
|
||||||
|
# List of strings that allows to exit conversation. (separated with ,)
|
||||||
|
exit-string: "cancel, exit, quit"
|
||||||
|
# Message that asks for search value input.
|
||||||
|
write-search: "&e Please enter a search value. (Write 'cancel' to exit)"
|
||||||
|
# Message that appears after updating search value.
|
||||||
|
search-updated: "&a Search value updated."
|
||||||
|
# Message that is sent to user when conversation is cancelled.
|
||||||
|
cancelled: "&c Conversation cancelled!"
|
||||||
|
# Message that is sent to user when given material does not have any value.
|
||||||
|
no-value: "&c That item has no value."
|
||||||
|
# Message that is sent to user when requested material does not exist.
|
||||||
|
unknown-item: "&c The '[material]' does not exist in game."
|
||||||
|
# Messages that is sent to user when requesting value for a specific material.
|
||||||
|
value: "&7 The value of '[material]' is: &e[value]"
|
||||||
|
value-underwater: "&7 The value of '[material]' below sea-level: &e[value]"
|
||||||
|
# Message that is sent to user when he does not hold any items in hand.
|
||||||
|
empty-hand: "&c There are no blocks in your hand"
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
value_panel:
|
||||||
|
title: level.gui.titles.value-panel
|
||||||
|
type: INVENTORY
|
||||||
|
background:
|
||||||
|
icon: BLACK_STAINED_GLASS_PANE
|
||||||
|
title: "&b&r" # Empty text
|
||||||
|
border:
|
||||||
|
icon: BLACK_STAINED_GLASS_PANE
|
||||||
|
title: "&b&r" # Empty text
|
||||||
|
force-shown: []
|
||||||
|
content:
|
||||||
|
1:
|
||||||
|
4:
|
||||||
|
icon: PAPER
|
||||||
|
title: level.gui.buttons.filters.name.name
|
||||||
|
description: level.gui.buttons.filters.name.description
|
||||||
|
data:
|
||||||
|
type: FILTER
|
||||||
|
# the value of filter button. Suggestion is to leave fist value to name if you use single button.
|
||||||
|
filter: NAME
|
||||||
|
actions:
|
||||||
|
asc:
|
||||||
|
click-type: unknown
|
||||||
|
tooltip: level.gui.tips.click-to-asc
|
||||||
|
desc:
|
||||||
|
click-type: unknown
|
||||||
|
tooltip: level.gui.tips.click-to-desc
|
||||||
|
5:
|
||||||
|
# You can create multiple buttons. By default it is one.
|
||||||
|
icon: MAP
|
||||||
|
title: level.gui.buttons.search.name
|
||||||
|
description: level.gui.buttons.search.description
|
||||||
|
data:
|
||||||
|
type: SEARCH
|
||||||
|
actions:
|
||||||
|
input:
|
||||||
|
click-type: left
|
||||||
|
tooltip: level.gui.tips.left-click-to-change
|
||||||
|
clear:
|
||||||
|
click-type: right
|
||||||
|
tooltip: level.gui.tips.right-click-to-clear
|
||||||
|
6:
|
||||||
|
icon: DIAMOND
|
||||||
|
title: level.gui.buttons.filters.value.name
|
||||||
|
description: level.gui.buttons.filters.value.description
|
||||||
|
data:
|
||||||
|
type: FILTER
|
||||||
|
# the value of filter button. Suggestion is to leave fist value to name if you use single button.
|
||||||
|
filter: VALUE
|
||||||
|
actions:
|
||||||
|
asc:
|
||||||
|
click-type: unknown
|
||||||
|
tooltip: level.gui.tips.click-to-asc
|
||||||
|
desc:
|
||||||
|
click-type: unknown
|
||||||
|
tooltip: level.gui.tips.click-to-desc
|
||||||
|
2:
|
||||||
|
2: material_button
|
||||||
|
3: material_button
|
||||||
|
4: material_button
|
||||||
|
5: material_button
|
||||||
|
6: material_button
|
||||||
|
7: material_button
|
||||||
|
8: material_button
|
||||||
|
3:
|
||||||
|
1:
|
||||||
|
icon: TIPPED_ARROW:INSTANT_HEAL::::1
|
||||||
|
title: level.gui.buttons.previous.name
|
||||||
|
description: level.gui.buttons.previous.description
|
||||||
|
data:
|
||||||
|
type: PREVIOUS
|
||||||
|
indexing: true
|
||||||
|
actions:
|
||||||
|
previous:
|
||||||
|
click-type: unknown
|
||||||
|
tooltip: level.gui.tips.click-to-previous
|
||||||
|
2: material_button
|
||||||
|
3: material_button
|
||||||
|
4: material_button
|
||||||
|
5: material_button
|
||||||
|
6: material_button
|
||||||
|
7: material_button
|
||||||
|
8: material_button
|
||||||
|
9:
|
||||||
|
icon: TIPPED_ARROW:JUMP::::1
|
||||||
|
title: level.gui.buttons.next.name
|
||||||
|
description: level.gui.buttons.next.description
|
||||||
|
data:
|
||||||
|
type: NEXT
|
||||||
|
indexing: true
|
||||||
|
actions:
|
||||||
|
next:
|
||||||
|
click-type: unknown
|
||||||
|
tooltip: level.gui.tips.click-to-next
|
||||||
|
4:
|
||||||
|
2: material_button
|
||||||
|
3: material_button
|
||||||
|
4: material_button
|
||||||
|
5: material_button
|
||||||
|
6: material_button
|
||||||
|
7: material_button
|
||||||
|
8: material_button
|
||||||
|
reusable:
|
||||||
|
material_button:
|
||||||
|
#icon: STONE
|
||||||
|
title: level.gui.buttons.value.name
|
||||||
|
description: level.gui.buttons.value.description
|
||||||
|
data:
|
||||||
|
type: BLOCK
|
Loading…
Reference in New Issue