mirror of
https://github.com/BentoBoxWorld/Challenges.git
synced 2025-02-22 23:31:21 +01:00
commit
7935c62738
2
pom.xml
2
pom.xml
@ -44,7 +44,7 @@
|
||||
<!-- More visible way how to change dependency versions -->
|
||||
<spigot.version>1.21.3-R0.1-SNAPSHOT</spigot.version>
|
||||
<spigot-annotations.version>1.2.3-SNAPSHOT</spigot-annotations.version>
|
||||
<bentobox.version>2.7.1-SNAPSHOT</bentobox.version>
|
||||
<bentobox.version>3.2.4-SNAPSHOT</bentobox.version>
|
||||
<level.version>2.6.3</level.version>
|
||||
<vault.version>1.7</vault.version>
|
||||
<panelutils.version>1.2.0</panelutils.version>
|
||||
|
@ -15,8 +15,8 @@ import world.bentobox.bentobox.api.flags.Flag;
|
||||
import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType;
|
||||
import world.bentobox.bentobox.hooks.VaultHook;
|
||||
import world.bentobox.bentobox.managers.RanksManager;
|
||||
import world.bentobox.challenges.commands.ChallengesPlayerCommand;
|
||||
import world.bentobox.challenges.commands.ChallengesGlobalPlayerCommand;
|
||||
import world.bentobox.challenges.commands.ChallengesPlayerCommand;
|
||||
import world.bentobox.challenges.commands.admin.ChallengesAdminCommand;
|
||||
import world.bentobox.challenges.commands.admin.ChallengesGlobalAdminCommand;
|
||||
import world.bentobox.challenges.config.Settings;
|
||||
|
@ -1,7 +1,11 @@
|
||||
package world.bentobox.challenges.database.object;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
@ -1,7 +1,11 @@
|
||||
package world.bentobox.challenges.database.object;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
@ -7,12 +7,20 @@
|
||||
package world.bentobox.challenges.database.object.adapters;
|
||||
|
||||
|
||||
import com.google.gson.*;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
|
||||
|
||||
|
@ -7,9 +7,16 @@
|
||||
package world.bentobox.challenges.database.object.adapters;
|
||||
|
||||
|
||||
import com.google.gson.*;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
import world.bentobox.challenges.database.object.Challenge;
|
||||
|
||||
|
||||
|
@ -7,7 +7,11 @@
|
||||
package world.bentobox.challenges.database.object.requirements;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
@ -7,9 +7,15 @@
|
||||
package world.bentobox.challenges.database.object.requirements;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.bukkit.Fluid;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
@ -26,166 +32,10 @@ public class IslandRequirements extends Requirements
|
||||
/**
|
||||
* Constructor Requirements creates a new Requirements instance.
|
||||
*/
|
||||
public IslandRequirements()
|
||||
{
|
||||
public IslandRequirements() {
|
||||
// Empty constructor for data loader
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Getters and Setters
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#getRequiredBlocks returns the requiredBlocks of this object.
|
||||
*
|
||||
* @return the requiredBlocks (type {@code Map<Material, Integer>}) of this object.
|
||||
*/
|
||||
public Map<Material, Integer> getRequiredBlocks()
|
||||
{
|
||||
return requiredBlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setRequiredBlocks sets new value for the requiredBlocks of this object.
|
||||
* @param requiredBlocks new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setRequiredBlocks(Map<Material, Integer> requiredBlocks)
|
||||
{
|
||||
this.requiredBlocks = requiredBlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#isRemoveBlocks returns the removeBlocks of this object.
|
||||
*
|
||||
* @return the removeBlocks (type boolean) of this object.
|
||||
*/
|
||||
public boolean isRemoveBlocks()
|
||||
{
|
||||
return removeBlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setRemoveBlocks sets new value for the removeBlocks of this object.
|
||||
* @param removeBlocks new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setRemoveBlocks(boolean removeBlocks)
|
||||
{
|
||||
this.removeBlocks = removeBlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#getRequiredEntities returns the requiredEntities of this object.
|
||||
*
|
||||
* @return the requiredEntities (type {@code Map<EntityType, Integer>}) of this object.
|
||||
*/
|
||||
public Map<EntityType, Integer> getRequiredEntities()
|
||||
{
|
||||
return requiredEntities;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setRequiredEntities sets new value for the requiredEntities of this object.
|
||||
* @param requiredEntities new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setRequiredEntities(Map<EntityType, Integer> requiredEntities)
|
||||
{
|
||||
this.requiredEntities = requiredEntities;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#isRemoveEntities returns the removeEntities of this object.
|
||||
*
|
||||
* @return the removeEntities (type boolean) of this object.
|
||||
*/
|
||||
public boolean isRemoveEntities()
|
||||
{
|
||||
return removeEntities;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setRemoveEntities sets new value for the removeEntities of this object.
|
||||
* @param removeEntities new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setRemoveEntities(boolean removeEntities)
|
||||
{
|
||||
this.removeEntities = removeEntities;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#getSearchRadius returns the searchRadius of this object.
|
||||
*
|
||||
* @return the searchRadius (type int) of this object.
|
||||
*/
|
||||
public int getSearchRadius()
|
||||
{
|
||||
return searchRadius;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setSearchRadius sets new value for the searchRadius of this object.
|
||||
* @param searchRadius new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setSearchRadius(int searchRadius)
|
||||
{
|
||||
this.searchRadius = searchRadius;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Other methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Method isValid returns if given requirement data is valid or not.
|
||||
*
|
||||
* @return {@code true} if data is valid, {@code false} otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid()
|
||||
{
|
||||
return super.isValid() &&
|
||||
this.requiredBlocks != null && this.requiredBlocks.keySet().stream().noneMatch(Objects::isNull) &&
|
||||
this.requiredEntities != null && this.requiredEntities.keySet().stream().noneMatch(Objects::isNull);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method Requirements#copy allows copies Requirements object, to avoid changing content when it is necessary
|
||||
* to use it.
|
||||
* @return IslandRequirements copy
|
||||
*/
|
||||
@Override
|
||||
public Requirements copy()
|
||||
{
|
||||
IslandRequirements clone = new IslandRequirements();
|
||||
clone.setRequiredPermissions(new HashSet<>(this.getRequiredPermissions()));
|
||||
|
||||
clone.setRequiredBlocks(new HashMap<>(this.requiredBlocks));
|
||||
clone.setRemoveBlocks(this.removeBlocks);
|
||||
clone.setRequiredEntities(new HashMap<>(this.requiredEntities));
|
||||
clone.setRemoveEntities(this.removeEntities);
|
||||
|
||||
clone.setSearchRadius(this.searchRadius);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Variables
|
||||
// ---------------------------------------------------------------------
|
||||
@ -197,6 +47,13 @@ public class IslandRequirements extends Requirements
|
||||
@Expose
|
||||
private Map<Material, Integer> requiredBlocks = new EnumMap<>(Material.class);
|
||||
|
||||
@Expose
|
||||
private Map<Tag<Material>, Integer> requiredMaterialTags = new HashMap<>();
|
||||
@Expose
|
||||
private Map<Tag<Fluid>, Integer> requiredFluidTags = new HashMap<>();
|
||||
@Expose
|
||||
private Map<Tag<EntityType>, Integer> requiredEntityTypeTags = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Boolean that indicate if blocks should be removed from world after completion.
|
||||
*/
|
||||
@ -221,4 +78,186 @@ public class IslandRequirements extends Requirements
|
||||
*/
|
||||
@Expose
|
||||
private int searchRadius = 10;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Getters and Setters
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#getRequiredBlocks returns the requiredBlocks of this object.
|
||||
*
|
||||
* @return the requiredBlocks (type {@code Map<Material, Integer>}) of this object.
|
||||
*/
|
||||
public Map<Material, Integer> getRequiredBlocks() {
|
||||
return requiredBlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setRequiredBlocks sets new value for the requiredBlocks of this object.
|
||||
* @param requiredBlocks new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setRequiredBlocks(Map<Material, Integer> requiredBlocks) {
|
||||
this.requiredBlocks = requiredBlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#isRemoveBlocks returns the removeBlocks of this object.
|
||||
*
|
||||
* @return the removeBlocks (type boolean) of this object.
|
||||
*/
|
||||
public boolean isRemoveBlocks() {
|
||||
return removeBlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setRemoveBlocks sets new value for the removeBlocks of this object.
|
||||
* @param removeBlocks new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setRemoveBlocks(boolean removeBlocks) {
|
||||
this.removeBlocks = removeBlocks;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#getRequiredEntities returns the requiredEntities of this object.
|
||||
*
|
||||
* @return the requiredEntities (type {@code Map<EntityType, Integer>}) of this object.
|
||||
*/
|
||||
public Map<EntityType, Integer> getRequiredEntities() {
|
||||
return requiredEntities;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setRequiredEntities sets new value for the requiredEntities of this object.
|
||||
* @param requiredEntities new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setRequiredEntities(Map<EntityType, Integer> requiredEntities) {
|
||||
this.requiredEntities = requiredEntities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#isRemoveEntities returns the removeEntities of this object.
|
||||
*
|
||||
* @return the removeEntities (type boolean) of this object.
|
||||
*/
|
||||
public boolean isRemoveEntities() {
|
||||
return removeEntities;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setRemoveEntities sets new value for the removeEntities of this object.
|
||||
* @param removeEntities new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setRemoveEntities(boolean removeEntities) {
|
||||
this.removeEntities = removeEntities;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#getSearchRadius returns the searchRadius of this object.
|
||||
*
|
||||
* @return the searchRadius (type int) of this object.
|
||||
*/
|
||||
public int getSearchRadius() {
|
||||
return searchRadius;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method IslandRequirements#setSearchRadius sets new value for the searchRadius of this object.
|
||||
* @param searchRadius new value for this object.
|
||||
*
|
||||
*/
|
||||
public void setSearchRadius(int searchRadius) {
|
||||
this.searchRadius = searchRadius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method isValid returns if given requirement data is valid or not.
|
||||
*
|
||||
* @return {@code true} if data is valid, {@code false} otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return super.isValid() && this.requiredBlocks != null
|
||||
&& this.requiredBlocks.keySet().stream().noneMatch(Objects::isNull) && this.requiredEntities != null
|
||||
&& this.requiredEntities.keySet().stream().noneMatch(Objects::isNull);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Method Requirements#copy allows copies Requirements object, to avoid changing content when it is necessary
|
||||
* to use it.
|
||||
* @return IslandRequirements copy
|
||||
*/
|
||||
@Override
|
||||
public Requirements copy() {
|
||||
IslandRequirements clone = new IslandRequirements();
|
||||
clone.setRequiredPermissions(new HashSet<>(this.getRequiredPermissions()));
|
||||
clone.setRequiredMaterialTags(new HashMap<>(this.requiredMaterialTags));
|
||||
clone.setRequiredFluidTags(new HashMap<>(this.requiredFluidTags));
|
||||
clone.setRequiredEntityTypeTags(new HashMap<>(this.requiredEntityTypeTags));
|
||||
clone.setRequiredBlocks(new HashMap<>(this.requiredBlocks));
|
||||
clone.setRemoveBlocks(this.removeBlocks);
|
||||
clone.setRequiredEntities(new HashMap<>(this.requiredEntities));
|
||||
clone.setRemoveEntities(this.removeEntities);
|
||||
|
||||
clone.setSearchRadius(this.searchRadius);
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the requiredMaterialTags
|
||||
*/
|
||||
public Map<Tag<Material>, Integer> getRequiredMaterialTags() {
|
||||
return requiredMaterialTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requiredMaterialTags the requiredMaterialTags to set
|
||||
*/
|
||||
public void setRequiredMaterialTags(Map<Tag<Material>, Integer> requiredMaterialTags) {
|
||||
this.requiredMaterialTags = requiredMaterialTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the requiredFluidTags
|
||||
*/
|
||||
public Map<Tag<Fluid>, Integer> getRequiredFluidTags() {
|
||||
return requiredFluidTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requiredFluidTags the requiredFluidTags to set
|
||||
*/
|
||||
public void setRequiredFluidTags(Map<Tag<Fluid>, Integer> requiredFluidTags) {
|
||||
this.requiredFluidTags = requiredFluidTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the requiredEntityTypeTags
|
||||
*/
|
||||
public Map<Tag<EntityType>, Integer> getRequiredEntityTypeTags() {
|
||||
return requiredEntityTypeTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requiredEntityTypeTags the requiredEntityTypeTags to set
|
||||
*/
|
||||
public void setRequiredEntityTypeTags(Map<Tag<EntityType>, Integer> requiredEntityTypeTags) {
|
||||
this.requiredEntityTypeTags = requiredEntityTypeTags;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ public abstract class Requirements
|
||||
|
||||
|
||||
/**
|
||||
* This set contains all permission strings that ir required for player to complete challenge.
|
||||
* This set contains all permission strings that are required for player to complete challenge.
|
||||
*/
|
||||
@Expose
|
||||
private Set<String> requiredPermissions = new HashSet<>();
|
||||
|
@ -7,12 +7,13 @@
|
||||
package world.bentobox.challenges.database.object.requirements;
|
||||
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import com.google.gson.annotations.Expose;
|
||||
|
||||
|
||||
public class StatisticRequirements extends Requirements
|
||||
{
|
||||
|
@ -2,9 +2,10 @@ package world.bentobox.challenges.events;
|
||||
|
||||
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import world.bentobox.bentobox.api.events.BentoBoxEvent;
|
||||
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
package world.bentobox.challenges.events;
|
||||
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import world.bentobox.bentobox.api.events.BentoBoxEvent;
|
||||
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
package world.bentobox.challenges.events;
|
||||
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import world.bentobox.bentobox.api.events.BentoBoxEvent;
|
||||
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
package world.bentobox.challenges.events;
|
||||
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import world.bentobox.bentobox.api.events.BentoBoxEvent;
|
||||
|
||||
|
||||
|
@ -9,7 +9,16 @@ import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
@ -1,7 +1,19 @@
|
||||
package world.bentobox.challenges.managers;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@ -1572,7 +1584,8 @@ public class ChallengesManager
|
||||
|
||||
this.islandWorldManager.getAddon(world).ifPresent(gameMode -> {
|
||||
this.resetAllChallenges(storageID, gameMode.getDescription().getName());
|
||||
this.addLogEntry(storageID, new LogEntry.Builder("RESET_ALL").
|
||||
this.addLogEntry(storageID, new LogEntry.Builder("RESET_ALL")
|
||||
.
|
||||
data(USER_ID, userID.toString()).
|
||||
data(ADMIN_ID, adminID == null ? "ISLAND_RESET" : adminID.toString()).
|
||||
build());
|
||||
|
@ -7,15 +7,15 @@
|
||||
package world.bentobox.challenges.panel;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
@ -103,6 +103,7 @@ public abstract class CommonPagedPanel<T> extends CommonPanel
|
||||
{
|
||||
if (!panelBuilder.slotOccupied(index))
|
||||
{
|
||||
// Show a challenge
|
||||
panelBuilder.item(index, this.createElementButton(objectList.get(objectIndex++)));
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,8 @@ import world.bentobox.challenges.utils.Utils;
|
||||
* This class contains common methods for all panels.
|
||||
*/
|
||||
public abstract class CommonPanel {
|
||||
private static final long MAXSIZE = 10;
|
||||
|
||||
/**
|
||||
* This is default constructor for all classes that extends CommonPanel.
|
||||
*
|
||||
@ -148,7 +150,7 @@ public abstract class CommonPanel {
|
||||
String requirements = isCompletedAll ? "" : this.generateRequirements(challenge, target);
|
||||
// Get rewards in single string
|
||||
String rewards = isCompletedAll ? "" : this.generateRewards(challenge, isCompletedOnce);
|
||||
// Get coolDown in singe string
|
||||
// Get coolDown in single string
|
||||
String coolDown = isCompletedAll || challenge.getTimeout() <= 0 ? "" : this.generateCoolDown(challenge, target);
|
||||
|
||||
if (!description.replaceAll("(?m)^[ \\t]*\\r?\\n", "").isEmpty()) {
|
||||
@ -284,50 +286,47 @@ public abstract class CommonPanel {
|
||||
private String generateIslandChallenge(IslandRequirements requirement) {
|
||||
final String reference = Constants.DESCRIPTIONS + "challenge.requirements.island.";
|
||||
|
||||
String blocks;
|
||||
|
||||
// Required Blocks
|
||||
StringBuilder blocks = new StringBuilder();
|
||||
blocks.append(getBlocksTagsDescription(requirement, reference));
|
||||
if (!requirement.getRequiredBlocks().isEmpty()) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "blocks-title"));
|
||||
requirement.getRequiredBlocks().entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> {
|
||||
builder.append("\n");
|
||||
blocks.append("\n");
|
||||
|
||||
if (entry.getValue() > 1) {
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "blocks-value",
|
||||
blocks.append(this.user.getTranslationOrNothing(reference + "blocks-value",
|
||||
Constants.PARAMETER_NUMBER, String.valueOf(entry.getValue()), Constants.PARAMETER_MATERIAL,
|
||||
Utils.prettifyObject(entry.getKey(), this.user)));
|
||||
} else {
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "block-value",
|
||||
blocks.append(this.user.getTranslationOrNothing(reference + "block-value",
|
||||
Constants.PARAMETER_MATERIAL, Utils.prettifyObject(entry.getKey(), this.user)));
|
||||
}
|
||||
});
|
||||
|
||||
blocks = builder.toString();
|
||||
} else {
|
||||
blocks = "";
|
||||
}
|
||||
// Add title if there is something here
|
||||
if (!blocks.isEmpty()) {
|
||||
blocks.insert(0, this.user.getTranslationOrNothing(reference + "blocks-title"));
|
||||
}
|
||||
|
||||
String entities;
|
||||
|
||||
StringBuilder entities = new StringBuilder();
|
||||
entities.append(getEntityTypeTagsDescription(requirement, reference));
|
||||
if (!requirement.getRequiredEntities().isEmpty()) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "entities-title"));
|
||||
requirement.getRequiredEntities().entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> {
|
||||
builder.append("\n");
|
||||
entities.append("\n");
|
||||
|
||||
if (entry.getValue() > 1) {
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "entities-value",
|
||||
entities.append(this.user.getTranslationOrNothing(reference + "entities-value",
|
||||
Constants.PARAMETER_NUMBER, String.valueOf(entry.getValue()), Constants.PARAMETER_ENTITY,
|
||||
Utils.prettifyObject(entry.getKey(), this.user)));
|
||||
} else {
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "entity-value",
|
||||
entities.append(this.user.getTranslationOrNothing(reference + "entity-value",
|
||||
Constants.PARAMETER_ENTITY, Utils.prettifyObject(entry.getKey(), this.user)));
|
||||
}
|
||||
});
|
||||
|
||||
entities = builder.toString();
|
||||
} else {
|
||||
entities = "";
|
||||
}
|
||||
// Add title if there is something here
|
||||
if (!entities.isEmpty()) {
|
||||
entities.insert(0, this.user.getTranslationOrNothing(reference + "entities-title"));
|
||||
}
|
||||
|
||||
String searchRadius = this.user.getTranslationOrNothing(reference + "search-radius", Constants.PARAMETER_NUMBER,
|
||||
@ -340,10 +339,63 @@ public abstract class CommonPanel {
|
||||
? this.user.getTranslationOrNothing(reference + "warning-entity")
|
||||
: "";
|
||||
|
||||
return this.user.getTranslationOrNothing(reference + "lore", "[blocks]", blocks, "[entities]", entities,
|
||||
return this.user.getTranslationOrNothing(reference + "lore", "[blocks]", blocks.toString(), "[entities]",
|
||||
entities.toString(),
|
||||
"[warning-block]", warningBlocks, "[warning-entity]", warningEntities, "[search-radius]", searchRadius);
|
||||
}
|
||||
|
||||
private String getBlocksTagsDescription(IslandRequirements requirement, String reference) {
|
||||
String tags = "";
|
||||
if (!requirement.getRequiredMaterialTags().isEmpty()) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
requirement.getRequiredMaterialTags().entrySet().stream().limit(MAXSIZE).forEach(entry -> {
|
||||
builder.append("\n");
|
||||
|
||||
if (entry.getValue() > 1) {
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "blocks-value",
|
||||
Constants.PARAMETER_NUMBER, String.valueOf(entry.getValue()), Constants.PARAMETER_MATERIAL,
|
||||
Utils.prettifyObject(entry.getKey(), this.user)));
|
||||
} else {
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "block-value",
|
||||
Constants.PARAMETER_MATERIAL, Utils.prettifyObject(entry.getKey(), this.user)));
|
||||
}
|
||||
});
|
||||
if (requirement.getRequiredMaterialTags().size() > MAXSIZE) {
|
||||
builder.append("...\n");
|
||||
}
|
||||
tags = builder.toString();
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
private String getEntityTypeTagsDescription(IslandRequirements requirement, String reference) {
|
||||
String tags = "";
|
||||
if (!requirement.getRequiredEntityTypeTags().isEmpty()) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
requirement.getRequiredEntityTypeTags().entrySet().stream().limit(MAXSIZE).forEach(entry -> {
|
||||
builder.append("\n");
|
||||
|
||||
if (entry.getValue() > 1) {
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "blocks-value",
|
||||
Constants.PARAMETER_NUMBER, String.valueOf(entry.getValue()), Constants.PARAMETER_MATERIAL,
|
||||
Utils.prettifyObject(entry.getKey(), this.user)));
|
||||
} else {
|
||||
builder.append(this.user.getTranslationOrNothing(reference + "block-value",
|
||||
Constants.PARAMETER_MATERIAL, Utils.prettifyObject(entry.getKey(), this.user)));
|
||||
}
|
||||
});
|
||||
if (requirement.getRequiredEntityTypeTags().size() > MAXSIZE) {
|
||||
builder.append("...\n");
|
||||
}
|
||||
|
||||
tags = builder.toString();
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method generates lore message for inventory requirement.
|
||||
*
|
||||
|
@ -7,16 +7,24 @@
|
||||
package world.bentobox.challenges.panel;
|
||||
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.conversations.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.conversations.ConversationAbandonedListener;
|
||||
import org.bukkit.conversations.ConversationContext;
|
||||
import org.bukkit.conversations.ConversationFactory;
|
||||
import org.bukkit.conversations.MessagePrompt;
|
||||
import org.bukkit.conversations.NumericPrompt;
|
||||
import org.bukkit.conversations.Prompt;
|
||||
import org.bukkit.conversations.StringPrompt;
|
||||
import org.bukkit.conversations.ValidatingPrompt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.challenges.utils.Constants;
|
||||
|
@ -171,11 +171,14 @@ public class EditChallengePanel extends CommonPanel {
|
||||
*/
|
||||
private void buildIslandRequirementsPanel(PanelBuilder panelBuilder) {
|
||||
panelBuilder.item(19, this.createRequirementButton(RequirementButton.REQUIRED_ENTITIES));
|
||||
panelBuilder.item(20, this.createRequirementButton(RequirementButton.REQUIRED_ENTITYTAGS));
|
||||
panelBuilder.item(28, this.createRequirementButton(RequirementButton.REMOVE_ENTITIES));
|
||||
|
||||
panelBuilder.item(21, this.createRequirementButton(RequirementButton.REQUIRED_BLOCKS));
|
||||
panelBuilder.item(22, this.createRequirementButton(RequirementButton.REQUIRED_MATERIALTAGS));
|
||||
panelBuilder.item(30, this.createRequirementButton(RequirementButton.REMOVE_BLOCKS));
|
||||
|
||||
|
||||
panelBuilder.item(23, this.createRequirementButton(RequirementButton.SEARCH_RADIUS));
|
||||
panelBuilder.item(25, this.createRequirementButton(RequirementButton.REQUIRED_PERMISSIONS));
|
||||
}
|
||||
@ -614,7 +617,8 @@ public class EditChallengePanel extends CommonPanel {
|
||||
.build();
|
||||
}
|
||||
// Buttons for Island Requirements
|
||||
case REQUIRED_ENTITIES, REMOVE_ENTITIES, REQUIRED_BLOCKS, REMOVE_BLOCKS, SEARCH_RADIUS -> {
|
||||
case REQUIRED_ENTITIES, REMOVE_ENTITIES, REQUIRED_BLOCKS, REMOVE_BLOCKS, SEARCH_RADIUS,
|
||||
REQUIRED_MATERIALTAGS, REQUIRED_ENTITYTAGS -> {
|
||||
return this.createIslandRequirementButton(button);
|
||||
}
|
||||
// Buttons for Inventory Requirements
|
||||
@ -692,12 +696,56 @@ public class EditChallengePanel extends CommonPanel {
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
|
||||
}
|
||||
|
||||
case REQUIRED_MATERIALTAGS -> {
|
||||
if (requirements.getRequiredMaterialTags().isEmpty()) {
|
||||
description.add(this.user.getTranslation(reference + "none"));
|
||||
} else {
|
||||
description.add(this.user.getTranslation(reference + "title"));
|
||||
// Add Material Tags only
|
||||
requirements.getRequiredMaterialTags()
|
||||
.forEach((block, count) -> description.add(this.user.getTranslation(reference + "list",
|
||||
"[tag]", Utils.prettifyObject(block, this.user), "[number]", String.valueOf(count))));
|
||||
}
|
||||
|
||||
icon = new ItemStack(Material.STONE_BRICKS);
|
||||
clickHandler = (panel, user, clickType, slot) -> {
|
||||
ManageBlockGroupsPanel.open(this, requirements.getRequiredMaterialTags());
|
||||
return true;
|
||||
};
|
||||
glow = false;
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
|
||||
}
|
||||
|
||||
case REQUIRED_ENTITYTAGS -> {
|
||||
if (requirements.getRequiredEntityTypeTags().isEmpty()) {
|
||||
description.add(this.user.getTranslation(reference + "none"));
|
||||
} else {
|
||||
description.add(this.user.getTranslation(reference + "title"));
|
||||
// Add Material Tags only
|
||||
requirements.getRequiredEntityTypeTags()
|
||||
.forEach((block, count) -> description.add(this.user.getTranslation(reference + "list",
|
||||
"[tag]", Utils.prettifyObject(block, this.user), "[number]", String.valueOf(count))));
|
||||
}
|
||||
|
||||
icon = new ItemStack(Material.ZOMBIE_HEAD);
|
||||
clickHandler = (panel, user, clickType, slot) -> {
|
||||
ManageEntityGroupsPanel.open(this, requirements.getRequiredEntityTypeTags());
|
||||
return true;
|
||||
};
|
||||
glow = false;
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
|
||||
}
|
||||
|
||||
case REQUIRED_BLOCKS -> {
|
||||
if (requirements.getRequiredBlocks().isEmpty()) {
|
||||
description.add(this.user.getTranslation(reference + "none"));
|
||||
} else {
|
||||
description.add(this.user.getTranslation(reference + "title"));
|
||||
|
||||
requirements.getRequiredBlocks()
|
||||
.forEach((block, count) -> description.add(this.user.getTranslation(reference + "list",
|
||||
"[block]", Utils.prettifyObject(block, this.user), "[number]", String.valueOf(count))));
|
||||
@ -1754,7 +1802,7 @@ public class EditChallengePanel extends CommonPanel {
|
||||
REQUIRED_ENTITIES, REMOVE_ENTITIES, REQUIRED_BLOCKS, REMOVE_BLOCKS, SEARCH_RADIUS, REQUIRED_PERMISSIONS,
|
||||
REQUIRED_ITEMS, REMOVE_ITEMS, ADD_IGNORED_META, REMOVE_IGNORED_META, REQUIRED_EXPERIENCE, REMOVE_EXPERIENCE,
|
||||
REQUIRED_LEVEL, REQUIRED_MONEY, REMOVE_MONEY, STATISTIC, STATISTIC_BLOCKS, STATISTIC_ITEMS, STATISTIC_ENTITIES,
|
||||
STATISTIC_AMOUNT, REMOVE_STATISTIC,
|
||||
STATISTIC_AMOUNT, REMOVE_STATISTIC, REQUIRED_MATERIALTAGS, REQUIRED_ENTITYTAGS,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
@ -1772,4 +1820,5 @@ public class EditChallengePanel extends CommonPanel {
|
||||
* Variable holds current active menu.
|
||||
*/
|
||||
private MenuType currentMenuType;
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,15 @@
|
||||
package world.bentobox.challenges.panel.admin;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -19,14 +27,14 @@ import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.bentobox.util.Util;
|
||||
import world.bentobox.challenges.ChallengesAddon;
|
||||
import world.bentobox.challenges.managers.ChallengesManager;
|
||||
import world.bentobox.challenges.database.object.Challenge;
|
||||
import world.bentobox.challenges.database.object.ChallengeLevel;
|
||||
import world.bentobox.challenges.managers.ChallengesManager;
|
||||
import world.bentobox.challenges.panel.CommonPagedPanel;
|
||||
import world.bentobox.challenges.panel.CommonPanel;
|
||||
import world.bentobox.challenges.panel.ConversationUtils;
|
||||
import world.bentobox.challenges.panel.util.ItemSelector;
|
||||
import world.bentobox.challenges.panel.util.ChallengeSelector;
|
||||
import world.bentobox.challenges.panel.util.ItemSelector;
|
||||
import world.bentobox.challenges.panel.util.MultiBlockSelector;
|
||||
import world.bentobox.challenges.utils.Constants;
|
||||
import world.bentobox.challenges.utils.Utils;
|
||||
|
@ -1,13 +1,13 @@
|
||||
package world.bentobox.challenges.panel.admin;
|
||||
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
|
||||
import lv.id.bonne.panelutils.PanelUtils;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
|
@ -0,0 +1,321 @@
|
||||
package world.bentobox.challenges.panel.admin;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import lv.id.bonne.panelutils.PanelUtils;
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.challenges.panel.CommonPagedPanel;
|
||||
import world.bentobox.challenges.panel.CommonPanel;
|
||||
import world.bentobox.challenges.panel.ConversationUtils;
|
||||
import world.bentobox.challenges.panel.util.MultiMaterialTagsSelector;
|
||||
import world.bentobox.challenges.utils.Constants;
|
||||
import world.bentobox.challenges.utils.Utils;
|
||||
|
||||
|
||||
/**
|
||||
* This class allows to edit Block Groups that are in required.
|
||||
*/
|
||||
public class ManageBlockGroupsPanel extends CommonPagedPanel<Tag<Material>>
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Enums
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Functional buttons in current GUI.
|
||||
*/
|
||||
private enum Button {
|
||||
ADD_BLOCK_GROUP, REMOVE_BLOCK_GROUP
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Variables
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Contains selected materials.
|
||||
*/
|
||||
private final Set<Tag<Material>> selectedTags;
|
||||
|
||||
/**
|
||||
* List of materials to avoid order issues.
|
||||
*/
|
||||
private final List<Tag<Material>> materialList;
|
||||
|
||||
/**
|
||||
* List of required materials.
|
||||
*/
|
||||
private final Map<Tag<Material>, Integer> tagMap;
|
||||
|
||||
/**
|
||||
* Stores filtered items.
|
||||
*/
|
||||
private List<Tag<Material>> filterElements;
|
||||
|
||||
private ManageBlockGroupsPanel(CommonPanel parentGUI, Map<Tag<Material>, Integer> map)
|
||||
{
|
||||
super(parentGUI);
|
||||
this.tagMap = map;
|
||||
this.materialList = new ArrayList<>(this.tagMap.keySet());
|
||||
|
||||
// Sort tags by their ordinal value.
|
||||
this.materialList.sort(Comparator.comparing(tag -> tag.getKey().getKey()));
|
||||
|
||||
this.selectedTags = new HashSet<>();
|
||||
|
||||
// Init without filters applied.
|
||||
this.filterElements = this.materialList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open the Challenges Admin GUI.
|
||||
*/
|
||||
public static void open(CommonPanel parentGUI, Map<Tag<Material>, Integer> map)
|
||||
{
|
||||
new ManageBlockGroupsPanel(parentGUI, map).build();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* This method is called when filter value is updated.
|
||||
*/
|
||||
@Override
|
||||
protected void updateFilters()
|
||||
{
|
||||
if (this.searchString == null || this.searchString.isBlank())
|
||||
{
|
||||
this.filterElements = this.materialList;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.filterElements = this.materialList.stream().
|
||||
filter(element -> {
|
||||
// If element name is set and name contains search field, then do not filter out.
|
||||
return element.getKey().getKey().toLowerCase(Locale.ENGLISH)
|
||||
.contains(this.searchString.toLowerCase(Locale.ENGLISH));
|
||||
}).
|
||||
distinct().
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method builds all necessary elements in GUI panel.
|
||||
*/
|
||||
@Override
|
||||
protected void build()
|
||||
{
|
||||
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
|
||||
name(this.user.getTranslation(Constants.TITLE + "manage-block-groups"));
|
||||
|
||||
// Create nice border.
|
||||
PanelUtils.fillBorder(panelBuilder);
|
||||
|
||||
panelBuilder.item(3, this.createButton(Button.ADD_BLOCK_GROUP));
|
||||
panelBuilder.item(5, this.createButton(Button.REMOVE_BLOCK_GROUP));
|
||||
// Fill the box with what is selected
|
||||
this.populateElements(panelBuilder, this.filterElements);
|
||||
|
||||
// Add return button.
|
||||
panelBuilder.item(44, this.returnButton);
|
||||
|
||||
panelBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates PanelItem button of requested type.
|
||||
* @param button Button which must be created.
|
||||
* @return new PanelItem with requested functionality.
|
||||
*/
|
||||
private PanelItem createButton(Button button)
|
||||
{
|
||||
final String reference = Constants.BUTTON + button.name().toLowerCase() + ".";
|
||||
|
||||
final String name = this.user.getTranslation(reference + "name");
|
||||
final List<String> description = new ArrayList<>(3);
|
||||
description.add(this.user.getTranslation(reference + "description"));
|
||||
|
||||
ItemStack icon;
|
||||
PanelItem.ClickHandler clickHandler;
|
||||
boolean glow;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case ADD_BLOCK_GROUP -> {
|
||||
icon = new ItemStack(Material.BUCKET);
|
||||
clickHandler = (panel, user1, clickType, slot) ->
|
||||
{
|
||||
MultiMaterialTagsSelector.open(this.user, MultiMaterialTagsSelector.Mode.BLOCKS,
|
||||
new HashSet<>(this.materialList),
|
||||
(status, materials) ->
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
materials.forEach(material ->
|
||||
{
|
||||
this.tagMap.put(material, 1);
|
||||
this.materialList.add(material);
|
||||
});
|
||||
}
|
||||
|
||||
this.build();
|
||||
});
|
||||
return true;
|
||||
};
|
||||
glow = false;
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-add"));
|
||||
}
|
||||
case REMOVE_BLOCK_GROUP -> {
|
||||
|
||||
if (!this.selectedTags.isEmpty())
|
||||
{
|
||||
description.add(this.user.getTranslation(reference + "title"));
|
||||
this.selectedTags.forEach(material ->
|
||||
description.add(this.user.getTranslation(reference + "material",
|
||||
"[material]", Utils.prettifyObject(material, this.user))));
|
||||
}
|
||||
|
||||
icon = new ItemStack(Material.LAVA_BUCKET);
|
||||
|
||||
clickHandler = (panel, user1, clickType, slot) ->
|
||||
{
|
||||
if (!this.selectedTags.isEmpty())
|
||||
{
|
||||
this.tagMap.keySet().removeAll(this.selectedTags);
|
||||
this.materialList.removeAll(this.selectedTags);
|
||||
this.selectedTags.clear();
|
||||
this.build();
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
glow = !this.selectedTags.isEmpty();
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-remove"));
|
||||
}
|
||||
default -> {
|
||||
icon = new ItemStack(Material.PAPER);
|
||||
clickHandler = null;
|
||||
glow = false;
|
||||
}
|
||||
}
|
||||
|
||||
return new PanelItemBuilder().
|
||||
icon(icon).
|
||||
name(name).
|
||||
description(description).
|
||||
clickHandler(clickHandler).
|
||||
glow(glow).
|
||||
build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates button for given material.
|
||||
* @param tag material which button must be created.
|
||||
* @return new Button for material.
|
||||
*/
|
||||
@Override
|
||||
protected PanelItem createElementButton(Tag<Material> tag)
|
||||
{
|
||||
final String reference = Constants.BUTTON + "block-group.";
|
||||
|
||||
List<String> description = new ArrayList<>();
|
||||
|
||||
if (this.selectedTags.contains(tag))
|
||||
{
|
||||
description.add(this.user.getTranslation(reference + "selected"));
|
||||
}
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-choose"));
|
||||
|
||||
if (this.selectedTags.contains(tag))
|
||||
{
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-deselect"));
|
||||
}
|
||||
else
|
||||
{
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-select"));
|
||||
}
|
||||
|
||||
return new PanelItemBuilder().
|
||||
name(this.user.getTranslation(reference + "name", "[tag]",
|
||||
Utils.prettifyObject(tag, this.user))).
|
||||
icon(getIcon(tag, this.tagMap.get(tag))).
|
||||
description(description).
|
||||
clickHandler((panel, user1, clickType, slot) -> {
|
||||
// On right click change which entities are selected for deletion.
|
||||
if (clickType.isRightClick())
|
||||
{
|
||||
if (!this.selectedTags.add(tag))
|
||||
{
|
||||
// Remove material if it is already selected
|
||||
this.selectedTags.remove(tag);
|
||||
}
|
||||
|
||||
this.build();
|
||||
}
|
||||
else
|
||||
{
|
||||
Consumer<Number> numberConsumer = number -> {
|
||||
if (number != null)
|
||||
{
|
||||
this.tagMap.put(tag, number.intValue());
|
||||
}
|
||||
|
||||
// reopen panel
|
||||
this.build();
|
||||
};
|
||||
|
||||
ConversationUtils.createNumericInput(numberConsumer,
|
||||
this.user,
|
||||
this.user.getTranslation(Constants.CONVERSATIONS + "input-number"),
|
||||
1,
|
||||
Integer.MAX_VALUE);
|
||||
}
|
||||
return true;
|
||||
}).
|
||||
glow(this.selectedTags.contains(tag)).
|
||||
build();
|
||||
}
|
||||
|
||||
private @Nullable ItemStack getIcon(Tag<Material> materialTag, Integer quantity) {
|
||||
Material m = MultiMaterialTagsSelector.ICONS.getOrDefault(materialTag, Registry.MATERIAL.stream()
|
||||
.filter(materialTag::isTagged).filter(Material::isItem).findAny().orElse(Material.PAPER));
|
||||
return new ItemStack(m, quantity);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,334 @@
|
||||
package world.bentobox.challenges.panel.admin;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import lv.id.bonne.panelutils.PanelUtils;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.challenges.panel.CommonPagedPanel;
|
||||
import world.bentobox.challenges.panel.CommonPanel;
|
||||
import world.bentobox.challenges.panel.ConversationUtils;
|
||||
import world.bentobox.challenges.panel.util.MultiEntityTypeTagsSelector;
|
||||
import world.bentobox.challenges.utils.Constants;
|
||||
import world.bentobox.challenges.utils.Utils;
|
||||
|
||||
|
||||
/**
|
||||
* This class allows to edit material that are in required material map.
|
||||
*/
|
||||
public class ManageEntityGroupsPanel extends CommonPagedPanel<Tag<EntityType>>
|
||||
{
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Enums
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Functional buttons in current GUI.
|
||||
*/
|
||||
private enum Button {
|
||||
ADD_ENTITY_GROUP, REMOVE_ENTITY_GROUP
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Variables
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Contains selected materials.
|
||||
*/
|
||||
private final Set<Tag<EntityType>> selectedTags;
|
||||
|
||||
/**
|
||||
* List of materials to avoid order issues.
|
||||
*/
|
||||
private final List<Tag<EntityType>> materialList;
|
||||
|
||||
/**
|
||||
* List of required materials.
|
||||
*/
|
||||
private final Map<Tag<EntityType>, Integer> tagMap;
|
||||
|
||||
/**
|
||||
* Stores filtered items.
|
||||
*/
|
||||
private List<Tag<EntityType>> filterElements;
|
||||
|
||||
private ManageEntityGroupsPanel(CommonPanel parentGUI, Map<Tag<EntityType>, Integer> map)
|
||||
{
|
||||
super(parentGUI);
|
||||
this.tagMap = map;
|
||||
this.materialList = new ArrayList<>(this.tagMap.keySet());
|
||||
|
||||
// Sort tags by their ordinal value.
|
||||
this.materialList.sort(Comparator.comparing(tag -> tag.getKey().getKey()));
|
||||
|
||||
this.selectedTags = new HashSet<>();
|
||||
|
||||
// Init without filters applied.
|
||||
this.filterElements = this.materialList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open the Challenges Admin GUI.
|
||||
*/
|
||||
public static void open(CommonPanel parentGUI, Map<Tag<EntityType>, Integer> map)
|
||||
{
|
||||
new ManageEntityGroupsPanel(parentGUI, map).build();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* This method is called when filter value is updated.
|
||||
*/
|
||||
@Override
|
||||
protected void updateFilters()
|
||||
{
|
||||
if (this.searchString == null || this.searchString.isBlank())
|
||||
{
|
||||
this.filterElements = this.materialList;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.filterElements = this.materialList.stream().
|
||||
filter(element -> {
|
||||
// If element name is set and name contains search field, then do not filter out.
|
||||
return element.getKey().getKey().toLowerCase(Locale.ENGLISH)
|
||||
.contains(this.searchString.toLowerCase(Locale.ENGLISH));
|
||||
}).
|
||||
distinct().
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method builds all necessary elements in GUI panel.
|
||||
*/
|
||||
@Override
|
||||
protected void build()
|
||||
{
|
||||
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
|
||||
name(this.user.getTranslation(Constants.TITLE + "manage-entity-groups"));
|
||||
|
||||
// Create nice border.
|
||||
PanelUtils.fillBorder(panelBuilder);
|
||||
|
||||
panelBuilder.item(3, this.createButton(Button.ADD_ENTITY_GROUP));
|
||||
panelBuilder.item(5, this.createButton(Button.REMOVE_ENTITY_GROUP));
|
||||
// Fill the box with what is selected
|
||||
this.populateElements(panelBuilder, this.filterElements);
|
||||
|
||||
// Add return button.
|
||||
panelBuilder.item(44, this.returnButton);
|
||||
|
||||
panelBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates PanelItem button of requested type.
|
||||
* @param button Button which must be created.
|
||||
* @return new PanelItem with requested functionality.
|
||||
*/
|
||||
private PanelItem createButton(Button button)
|
||||
{
|
||||
final String reference = Constants.BUTTON + button.name().toLowerCase() + ".";
|
||||
|
||||
final String name = this.user.getTranslation(reference + "name");
|
||||
final List<String> description = new ArrayList<>(3);
|
||||
description.add(this.user.getTranslation(reference + "description"));
|
||||
|
||||
ItemStack icon;
|
||||
PanelItem.ClickHandler clickHandler;
|
||||
boolean glow;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case ADD_ENTITY_GROUP -> {
|
||||
icon = new ItemStack(Material.BUCKET);
|
||||
clickHandler = (panel, user1, clickType, slot) ->
|
||||
{
|
||||
MultiEntityTypeTagsSelector.open(this.user, MultiEntityTypeTagsSelector.Mode.ENTITY_TYPE,
|
||||
new HashSet<>(this.materialList),
|
||||
(status, materials) ->
|
||||
{
|
||||
if (status)
|
||||
{
|
||||
materials.forEach(material ->
|
||||
{
|
||||
this.tagMap.put(material, 1);
|
||||
this.materialList.add(material);
|
||||
});
|
||||
}
|
||||
|
||||
this.build();
|
||||
});
|
||||
return true;
|
||||
};
|
||||
glow = false;
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-add"));
|
||||
}
|
||||
case REMOVE_ENTITY_GROUP -> {
|
||||
|
||||
if (!this.selectedTags.isEmpty())
|
||||
{
|
||||
description.add(this.user.getTranslation(reference + "title"));
|
||||
this.selectedTags.forEach(material ->
|
||||
description.add(this.user.getTranslation(reference + "entity", "[tag]",
|
||||
Utils.prettifyObject(material, this.user))));
|
||||
}
|
||||
|
||||
icon = new ItemStack(Material.LAVA_BUCKET);
|
||||
|
||||
clickHandler = (panel, user1, clickType, slot) ->
|
||||
{
|
||||
if (!this.selectedTags.isEmpty())
|
||||
{
|
||||
this.tagMap.keySet().removeAll(this.selectedTags);
|
||||
this.materialList.removeAll(this.selectedTags);
|
||||
this.selectedTags.clear();
|
||||
this.build();
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
glow = !this.selectedTags.isEmpty();
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-remove"));
|
||||
}
|
||||
default -> {
|
||||
icon = new ItemStack(Material.PAPER);
|
||||
clickHandler = null;
|
||||
glow = false;
|
||||
}
|
||||
}
|
||||
|
||||
return new PanelItemBuilder().
|
||||
icon(icon).
|
||||
name(name).
|
||||
description(description).
|
||||
clickHandler(clickHandler).
|
||||
glow(glow).
|
||||
build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates button for given material.
|
||||
* @param tag material which button must be created.
|
||||
* @return new Button for material.
|
||||
*/
|
||||
@Override
|
||||
protected PanelItem createElementButton(Tag<EntityType> tag)
|
||||
{
|
||||
final String reference = Constants.BUTTON + "entity-group.";
|
||||
|
||||
List<String> description = new ArrayList<>();
|
||||
|
||||
if (this.selectedTags.contains(tag))
|
||||
{
|
||||
description.add(this.user.getTranslation(reference + "selected"));
|
||||
}
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-choose"));
|
||||
|
||||
if (this.selectedTags.contains(tag))
|
||||
{
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-deselect"));
|
||||
}
|
||||
else
|
||||
{
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-select"));
|
||||
}
|
||||
|
||||
return new PanelItemBuilder().
|
||||
name(this.user.getTranslation(reference + "name", "[tag]",
|
||||
Utils.prettifyObject(tag, this.user))).
|
||||
icon(getIcon(tag, this.tagMap.get(tag))).
|
||||
description(description).
|
||||
clickHandler((panel, user1, clickType, slot) -> {
|
||||
// On right click change which entities are selected for deletion.
|
||||
if (clickType.isRightClick())
|
||||
{
|
||||
if (!this.selectedTags.add(tag))
|
||||
{
|
||||
// Remove material if it is already selected
|
||||
this.selectedTags.remove(tag);
|
||||
}
|
||||
|
||||
this.build();
|
||||
}
|
||||
else
|
||||
{
|
||||
Consumer<Number> numberConsumer = number -> {
|
||||
if (number != null)
|
||||
{
|
||||
this.tagMap.put(tag, number.intValue());
|
||||
}
|
||||
|
||||
// reopen panel
|
||||
this.build();
|
||||
};
|
||||
|
||||
ConversationUtils.createNumericInput(numberConsumer,
|
||||
this.user,
|
||||
this.user.getTranslation(Constants.CONVERSATIONS + "input-number"),
|
||||
1,
|
||||
Integer.MAX_VALUE);
|
||||
}
|
||||
return true;
|
||||
}).
|
||||
glow(this.selectedTags.contains(tag)).
|
||||
build();
|
||||
}
|
||||
|
||||
private @Nullable ItemStack getIcon(Tag<EntityType> entityTag, Integer quantity) {
|
||||
if (entityTag.getKey().getKey().contains("boat")) {
|
||||
return new ItemStack(Material.OAK_PLANKS, quantity); // Boats cannot be stacked
|
||||
}
|
||||
EntityType entType = Registry.ENTITY_TYPE.stream().filter(entityTag::isTagged).findAny().orElse(null);
|
||||
if (entType == null) {
|
||||
return new ItemStack(Material.PAPER, quantity);
|
||||
}
|
||||
String eggName = entType.getKey().getKey().toUpperCase(Locale.ENGLISH) + "_SPAWN_EGG";
|
||||
Material result;
|
||||
try {
|
||||
result = Material.valueOf(eggName);
|
||||
} catch (Exception e) {
|
||||
result = Material.PAPER;
|
||||
}
|
||||
return new ItemStack(result, quantity);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -7,17 +7,18 @@
|
||||
package world.bentobox.challenges.panel.user;
|
||||
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.TemplatedPanel;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
|
@ -7,15 +7,16 @@
|
||||
package world.bentobox.challenges.panel.user;
|
||||
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
import world.bentobox.bentobox.api.addons.GameModeAddon;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.TemplatedPanel;
|
||||
|
@ -7,15 +7,15 @@
|
||||
package world.bentobox.challenges.panel.user;
|
||||
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.TemplatedPanel;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
|
@ -20,7 +20,11 @@ import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.challenges.database.object.Challenge;
|
||||
import world.bentobox.challenges.database.object.requirements.*;
|
||||
import world.bentobox.challenges.database.object.requirements.InventoryRequirements;
|
||||
import world.bentobox.challenges.database.object.requirements.IslandRequirements;
|
||||
import world.bentobox.challenges.database.object.requirements.OtherRequirements;
|
||||
import world.bentobox.challenges.database.object.requirements.Requirements;
|
||||
import world.bentobox.challenges.database.object.requirements.StatisticRequirements;
|
||||
import world.bentobox.challenges.utils.Constants;
|
||||
|
||||
|
||||
|
@ -1,7 +1,11 @@
|
||||
package world.bentobox.challenges.panel.util;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -9,286 +13,108 @@ import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import lv.id.bonne.panelutils.PanelUtils;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.challenges.utils.Constants;
|
||||
import world.bentobox.challenges.utils.Utils;
|
||||
|
||||
|
||||
/**
|
||||
* This class contains all necessary things that allows to select single block from all ingame blocks. Selected
|
||||
* block will be returned via BiConsumer.
|
||||
* This class provides a multi-selector GUI for selecting blocks (i.e. Materials).
|
||||
* It extends the unified multi-selector base class and provides the type-specific
|
||||
* implementations required for block selection.
|
||||
*/
|
||||
public class MultiBlockSelector extends PagedSelector<Material>
|
||||
{
|
||||
private MultiBlockSelector(User user, Mode mode, Set<Material> excluded, BiConsumer<Boolean, Collection<Material>> consumer)
|
||||
{
|
||||
super(user);
|
||||
this.consumer = consumer;
|
||||
public class MultiBlockSelector extends UnifiedMultiSelector<Material> {
|
||||
|
||||
// Current GUI cannot display air blocks. It crashes with null-pointer
|
||||
excluded.add(Material.AIR);
|
||||
excluded.add(Material.CAVE_AIR);
|
||||
excluded.add(Material.VOID_AIR);
|
||||
private final Mode mode;
|
||||
private final Set<Material> excluded;
|
||||
|
||||
// Piston head and moving piston is not necessary. useless.
|
||||
excluded.add(Material.PISTON_HEAD);
|
||||
excluded.add(Material.MOVING_PISTON);
|
||||
|
||||
// Barrier cannot be accessible to user.
|
||||
excluded.add(Material.BARRIER);
|
||||
|
||||
this.selectedElements = new HashSet<>();
|
||||
|
||||
this.elements = Arrays.stream(Material.values()).
|
||||
filter(material -> !excluded.contains(material)).
|
||||
filter(material -> {
|
||||
switch (mode)
|
||||
{
|
||||
case BLOCKS -> {
|
||||
return material.isBlock();
|
||||
public enum Mode {
|
||||
BLOCKS, ITEMS, ANY
|
||||
}
|
||||
case ITEMS -> {
|
||||
return material.isItem();
|
||||
}
|
||||
default -> {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}).
|
||||
// Sort by name
|
||||
sorted(Comparator.comparing(Material::name)).
|
||||
collect(Collectors.toList());
|
||||
// Init without filters applied.
|
||||
this.filterElements = this.elements;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method opens GUI that allows to select challenge type.
|
||||
* Private constructor.
|
||||
*
|
||||
* @param user User who opens GUI.
|
||||
* @param consumer Consumer that allows to get clicked type.
|
||||
* @param user the user opening the selector
|
||||
* @param mode the mode indicating whether to show only blocks, only items, or any
|
||||
* @param excluded a set of Materials to exclude from the list
|
||||
* @param consumer the callback to be invoked when the user confirms or cancels
|
||||
*/
|
||||
public static void open(User user, Mode mode, Set<Material> excluded, BiConsumer<Boolean, Collection<Material>> consumer)
|
||||
{
|
||||
private MultiBlockSelector(User user, Mode mode, Set<Material> excluded,
|
||||
BiConsumer<Boolean, Collection<Material>> consumer) {
|
||||
super(user, consumer);
|
||||
this.mode = mode;
|
||||
if (excluded == null) {
|
||||
excluded = new HashSet<>();
|
||||
}
|
||||
this.excluded = excluded;
|
||||
// Add default exclusions
|
||||
this.excluded.add(Material.AIR);
|
||||
this.excluded.add(Material.CAVE_AIR);
|
||||
this.excluded.add(Material.VOID_AIR);
|
||||
this.excluded.add(Material.PISTON_HEAD);
|
||||
this.excluded.add(Material.MOVING_PISTON);
|
||||
this.excluded.add(Material.BARRIER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the MultiBlockSelector GUI with a specified mode and exclusions.
|
||||
*
|
||||
* @param user the user who opens the GUI
|
||||
* @param mode the mode for filtering (BLOCKS, ITEMS, or ANY)
|
||||
* @param excluded a set of Materials to exclude
|
||||
* @param consumer a callback to receive the result
|
||||
*/
|
||||
public static void open(User user, Mode mode, Set<Material> excluded,
|
||||
BiConsumer<Boolean, Collection<Material>> consumer) {
|
||||
new MultiBlockSelector(user, mode, excluded, consumer).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method opens GUI that allows to select challenge type.
|
||||
* Opens the MultiBlockSelector GUI with default mode (ANY) and no exclusions.
|
||||
*
|
||||
* @param user User who opens GUI.
|
||||
* @param consumer Consumer that allows to get clicked type.
|
||||
* @param user the user who opens the GUI
|
||||
* @param consumer a callback to receive the result
|
||||
*/
|
||||
public static void open(User user, BiConsumer<Boolean, Collection<Material>> consumer)
|
||||
{
|
||||
public static void open(User user, BiConsumer<Boolean, Collection<Material>> consumer) {
|
||||
new MultiBlockSelector(user, Mode.ANY, new HashSet<>(), consumer).build();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* This method builds all necessary elements in GUI panel.
|
||||
*/
|
||||
@Override
|
||||
protected void build()
|
||||
{
|
||||
PanelBuilder panelBuilder = new PanelBuilder().user(this.user);
|
||||
panelBuilder.name(this.user.getTranslation(Constants.TITLE + "block-selector"));
|
||||
|
||||
PanelUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE);
|
||||
|
||||
this.populateElements(panelBuilder, this.filterElements);
|
||||
|
||||
panelBuilder.item(3, this.createButton(Button.ACCEPT_SELECTED));
|
||||
panelBuilder.item(5, this.createButton(Button.CANCEL));
|
||||
|
||||
panelBuilder.build();
|
||||
protected List<Material> getElements() {
|
||||
return Arrays.stream(Material.values()).filter(material -> excluded == null || !excluded.contains(material))
|
||||
.filter(material -> {
|
||||
switch (mode) {
|
||||
case BLOCKS:
|
||||
return material.isBlock();
|
||||
case ITEMS:
|
||||
return material.isItem();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}).sorted(Comparator.comparing(Material::name)).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is called when filter value is updated.
|
||||
*/
|
||||
@Override
|
||||
protected void updateFilters()
|
||||
{
|
||||
if (this.searchString == null || this.searchString.isBlank())
|
||||
{
|
||||
this.filterElements = this.elements;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.filterElements = this.elements.stream().
|
||||
filter(element -> {
|
||||
// If element name is set and name contains search field, then do not filter out.
|
||||
return element.name().toLowerCase().contains(this.searchString.toLowerCase());
|
||||
}).
|
||||
distinct().
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
protected String getTitleKey() {
|
||||
return "block-selector";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates PanelItem button of requested type.
|
||||
* @param button Button which must be created.
|
||||
* @return new PanelItem with requested functionality.
|
||||
*/
|
||||
private PanelItem createButton(Button button)
|
||||
{
|
||||
final String reference = Constants.BUTTON + button.name().toLowerCase() + ".";
|
||||
|
||||
final String name = this.user.getTranslation(reference + "name");
|
||||
final List<String> description = new ArrayList<>(3);
|
||||
description.add(this.user.getTranslation(reference + "description"));
|
||||
|
||||
ItemStack icon;
|
||||
PanelItem.ClickHandler clickHandler;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case ACCEPT_SELECTED -> {
|
||||
if (!this.selectedElements.isEmpty())
|
||||
{
|
||||
description.add(this.user.getTranslation(reference + "title"));
|
||||
this.selectedElements.forEach(material ->
|
||||
description.add(this.user.getTranslation(reference + "element",
|
||||
"[element]", Utils.prettifyObject(material, this.user))));
|
||||
}
|
||||
|
||||
icon = new ItemStack(Material.COMMAND_BLOCK);
|
||||
clickHandler = (panel, user1, clickType, slot) ->
|
||||
{
|
||||
this.consumer.accept(true, this.selectedElements);
|
||||
return true;
|
||||
};
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-save"));
|
||||
}
|
||||
case CANCEL -> {
|
||||
|
||||
icon = new ItemStack(Material.IRON_DOOR);
|
||||
|
||||
clickHandler = (panel, user1, clickType, slot) ->
|
||||
{
|
||||
this.consumer.accept(false, null);
|
||||
return true;
|
||||
};
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel"));
|
||||
}
|
||||
default -> {
|
||||
icon = new ItemStack(Material.PAPER);
|
||||
clickHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
return new PanelItemBuilder().
|
||||
icon(icon).
|
||||
name(name).
|
||||
description(description).
|
||||
clickHandler(clickHandler).
|
||||
build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates button for given material.
|
||||
* @param material material which button must be created.
|
||||
* @return new Button for material.
|
||||
*/
|
||||
@Override
|
||||
protected PanelItem createElementButton(Material material)
|
||||
{
|
||||
final String reference = Constants.BUTTON + "material.";
|
||||
|
||||
List<String> description = new ArrayList<>();
|
||||
description.add(this.user.getTranslation(reference + "description",
|
||||
"[id]", material.name()));
|
||||
|
||||
if (this.selectedElements.contains(material))
|
||||
{
|
||||
description.add(this.user.getTranslation(reference + "selected"));
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-deselect"));
|
||||
}
|
||||
else
|
||||
{
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-select"));
|
||||
protected String getElementKeyPrefix() {
|
||||
return "material.";
|
||||
}
|
||||
|
||||
return new PanelItemBuilder().
|
||||
name(this.user.getTranslation(reference + "name", "[material]",
|
||||
Utils.prettifyObject(material, this.user))).
|
||||
icon(PanelUtils.getMaterialItem(material)).
|
||||
description(description).
|
||||
clickHandler((panel, user1, clickType, slot) -> {
|
||||
// On right click change which entities are selected for deletion.
|
||||
if (!this.selectedElements.add(material))
|
||||
{
|
||||
// Remove material if it is already selected
|
||||
this.selectedElements.remove(material);
|
||||
@Override
|
||||
protected ItemStack getIcon(Material element) {
|
||||
return PanelUtils.getMaterialItem(element);
|
||||
}
|
||||
|
||||
this.build();
|
||||
return true;
|
||||
}).
|
||||
glow(this.selectedElements.contains(material)).
|
||||
build();
|
||||
@Override
|
||||
protected String getElementDisplayName(Material element) {
|
||||
return Utils.prettifyObject(element, this.user);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Functional buttons in current GUI.
|
||||
*/
|
||||
private enum Button
|
||||
{
|
||||
ACCEPT_SELECTED,
|
||||
CANCEL
|
||||
@Override
|
||||
protected String elementToString(Material element) {
|
||||
return element.name();
|
||||
}
|
||||
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
BLOCKS,
|
||||
ITEMS,
|
||||
ANY
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Variables
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* List with elements that will be displayed in current GUI.
|
||||
*/
|
||||
private final List<Material> elements;
|
||||
|
||||
/**
|
||||
* Set that contains selected materials.
|
||||
*/
|
||||
private final Set<Material> selectedElements;
|
||||
|
||||
/**
|
||||
* This variable stores consumer.
|
||||
*/
|
||||
private final BiConsumer<Boolean, Collection<Material>> consumer;
|
||||
|
||||
/**
|
||||
* Stores filtered items.
|
||||
*/
|
||||
private List<Material> filterElements;
|
||||
}
|
||||
|
@ -1,282 +1,129 @@
|
||||
package world.bentobox.challenges.panel.util;
|
||||
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import lv.id.bonne.panelutils.PanelUtils;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.challenges.utils.Constants;
|
||||
import world.bentobox.challenges.utils.Utils;
|
||||
|
||||
|
||||
/**
|
||||
* This class contains all necessary things that allows to select single block from all ingame blocks. Selected
|
||||
* block will be returned via BiConsumer.
|
||||
* This class provides a multi-selector GUI for selecting entities.
|
||||
* It extends the unified multi-selector base class and supplies the
|
||||
* type-specific implementations required for entity selection.
|
||||
*/
|
||||
public class MultiEntitySelector extends PagedSelector<EntityType>
|
||||
{
|
||||
private MultiEntitySelector(User user, boolean asEgg, Mode mode, Set<EntityType> excluded, BiConsumer<Boolean, Collection<EntityType>> consumer)
|
||||
{
|
||||
super(user);
|
||||
|
||||
this.consumer = consumer;
|
||||
this.asEgg = asEgg;
|
||||
this.selectedElements = new HashSet<>();
|
||||
|
||||
this.elements = Arrays.stream(EntityType.values()).
|
||||
filter(entity -> !excluded.contains(entity)).
|
||||
filter(entity -> {
|
||||
if (mode == Mode.ALIVE)
|
||||
{
|
||||
return entity.isAlive();
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}).
|
||||
// Sort by name
|
||||
sorted(Comparator.comparing(EntityType::name)).
|
||||
collect(Collectors.toList());
|
||||
// Init without filters applied.
|
||||
this.filterElements = this.elements;
|
||||
}
|
||||
public class MultiEntitySelector extends UnifiedMultiSelector<EntityType> {
|
||||
|
||||
private final boolean asEgg;
|
||||
private final Mode mode;
|
||||
private final Set<EntityType> excluded;
|
||||
|
||||
/**
|
||||
* This method opens GUI that allows to select challenge type.
|
||||
* Specifies which entities to display.
|
||||
*/
|
||||
public enum Mode {
|
||||
ALIVE, ANY
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
*
|
||||
* @param user User who opens GUI.
|
||||
* @param consumer Consumer that allows to get clicked type.
|
||||
* @param user the user opening the selector
|
||||
* @param asEgg if true, display entities using their spawn egg icon; otherwise, use the entity head
|
||||
* @param mode determines whether to show only living entities (ALIVE) or all (ANY)
|
||||
* @param excluded a set of EntityType values to exclude
|
||||
* @param consumer the callback to be invoked when the user confirms or cancels
|
||||
*/
|
||||
public static void open(User user, boolean asEgg, Mode mode, Set<EntityType> excluded, BiConsumer<Boolean, Collection<EntityType>> consumer)
|
||||
{
|
||||
private MultiEntitySelector(User user, boolean asEgg, Mode mode, Set<EntityType> excluded,
|
||||
java.util.function.BiConsumer<Boolean, Collection<EntityType>> consumer) {
|
||||
super(user, consumer);
|
||||
this.asEgg = asEgg;
|
||||
this.mode = mode;
|
||||
this.excluded = excluded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the MultiEntitySelector GUI with the specified parameters.
|
||||
*
|
||||
* @param user the user who opens the GUI
|
||||
* @param asEgg if true, show the entity spawn egg icon; otherwise, show the entity head
|
||||
* @param mode the filtering mode (ALIVE or ANY)
|
||||
* @param excluded a set of EntityType values to exclude from the list
|
||||
* @param consumer a callback to receive the result
|
||||
*/
|
||||
public static void open(User user, boolean asEgg, Mode mode, Set<EntityType> excluded,
|
||||
java.util.function.BiConsumer<Boolean, Collection<EntityType>> consumer) {
|
||||
new MultiEntitySelector(user, asEgg, mode, excluded, consumer).build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method opens GUI that allows to select challenge type.
|
||||
* Opens the MultiEntitySelector GUI with default parameters (mode ANY and no exclusions).
|
||||
*
|
||||
* @param user User who opens GUI.
|
||||
* @param consumer Consumer that allows to get clicked type.
|
||||
* @param user the user who opens the GUI
|
||||
* @param asEgg if true, show the entity spawn egg icon; otherwise, show the entity head
|
||||
* @param consumer a callback to receive the result
|
||||
*/
|
||||
public static void open(User user, boolean asEgg, BiConsumer<Boolean, Collection<EntityType>> consumer)
|
||||
{
|
||||
public static void open(User user, boolean asEgg,
|
||||
java.util.function.BiConsumer<Boolean, Collection<EntityType>> consumer) {
|
||||
new MultiEntitySelector(user, asEgg, Mode.ANY, new HashSet<>(), consumer).build();
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* This method builds all necessary elements in GUI panel.
|
||||
*/
|
||||
protected void build()
|
||||
{
|
||||
PanelBuilder panelBuilder = new PanelBuilder().user(this.user);
|
||||
panelBuilder.name(this.user.getTranslation(Constants.TITLE + "entity-selector"));
|
||||
|
||||
PanelUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE);
|
||||
|
||||
this.populateElements(panelBuilder, this.filterElements);
|
||||
|
||||
panelBuilder.item(3, this.createButton(Button.ACCEPT_SELECTED));
|
||||
panelBuilder.item(5, this.createButton(Button.CANCEL));
|
||||
|
||||
panelBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is called when filter value is updated.
|
||||
* Returns the list of EntityType values to display, applying the specified exclusions and mode.
|
||||
*/
|
||||
@Override
|
||||
protected void updateFilters()
|
||||
{
|
||||
if (this.searchString == null || this.searchString.isBlank())
|
||||
{
|
||||
this.filterElements = this.elements;
|
||||
protected List<EntityType> getElements() {
|
||||
return Arrays.stream(EntityType.values()).filter(entity -> excluded == null || !excluded.contains(entity))
|
||||
.filter(entity -> mode == Mode.ALIVE ? entity.isAlive() : true)
|
||||
.sorted(Comparator.comparing(EntityType::name)).collect(Collectors.toList());
|
||||
}
|
||||
else
|
||||
{
|
||||
this.filterElements = this.elements.stream().
|
||||
filter(element -> {
|
||||
// If element name is set and name contains search field, then do not filter out.
|
||||
return element.name().toLowerCase().contains(this.searchString.toLowerCase());
|
||||
}).
|
||||
distinct().
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates PanelItem button of requested type.
|
||||
* @param button Button which must be created.
|
||||
* @return new PanelItem with requested functionality.
|
||||
*/
|
||||
private PanelItem createButton(Button button)
|
||||
{
|
||||
final String reference = Constants.BUTTON + button.name().toLowerCase() + ".";
|
||||
|
||||
final String name = this.user.getTranslation(reference + "name");
|
||||
final List<String> description = new ArrayList<>(3);
|
||||
description.add(this.user.getTranslation(reference + "description"));
|
||||
|
||||
ItemStack icon;
|
||||
PanelItem.ClickHandler clickHandler;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case ACCEPT_SELECTED -> {
|
||||
if (!this.selectedElements.isEmpty())
|
||||
{
|
||||
description.add(this.user.getTranslation(reference + "title"));
|
||||
this.selectedElements.forEach(material ->
|
||||
description.add(this.user.getTranslation(reference + "element",
|
||||
"[element]", Utils.prettifyObject(material, this.user))));
|
||||
}
|
||||
|
||||
icon = new ItemStack(Material.COMMAND_BLOCK);
|
||||
clickHandler = (panel, user1, clickType, slot) ->
|
||||
{
|
||||
this.consumer.accept(true, this.selectedElements);
|
||||
return true;
|
||||
};
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-save"));
|
||||
}
|
||||
case CANCEL -> {
|
||||
|
||||
icon = new ItemStack(Material.IRON_DOOR);
|
||||
|
||||
clickHandler = (panel, user1, clickType, slot) ->
|
||||
{
|
||||
this.consumer.accept(false, null);
|
||||
return true;
|
||||
};
|
||||
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel"));
|
||||
}
|
||||
default -> {
|
||||
icon = new ItemStack(Material.PAPER);
|
||||
clickHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
return new PanelItemBuilder().
|
||||
icon(icon).
|
||||
name(name).
|
||||
description(description).
|
||||
clickHandler(clickHandler).
|
||||
build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method creates button for given entity.
|
||||
* @param entity entity which button must be created.
|
||||
* @return new Button for entity.
|
||||
* Returns the title key used to form the GUI title.
|
||||
*/
|
||||
@Override
|
||||
protected PanelItem createElementButton(EntityType entity)
|
||||
{
|
||||
final String reference = Constants.BUTTON + "entity.";
|
||||
|
||||
List<String> description = new ArrayList<>();
|
||||
description.add(this.user.getTranslation(reference + "description",
|
||||
"[id]", entity.name()));
|
||||
|
||||
if (this.selectedElements.contains(entity))
|
||||
{
|
||||
description.add(this.user.getTranslation(reference + "selected"));
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-deselect"));
|
||||
protected String getTitleKey() {
|
||||
return "entity-selector";
|
||||
}
|
||||
else
|
||||
{
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-select"));
|
||||
}
|
||||
|
||||
return new PanelItemBuilder().
|
||||
name(this.user.getTranslation(reference + "name", "[entity]",
|
||||
Utils.prettifyObject(entity, this.user))).
|
||||
icon(this.asEgg ? PanelUtils.getEntityEgg(entity) : PanelUtils.getEntityHead(entity)).
|
||||
description(description).
|
||||
clickHandler((panel, user1, clickType, slot) -> {
|
||||
// On right click change which entities are selected for deletion.
|
||||
if (!this.selectedElements.add(entity))
|
||||
{
|
||||
// Remove entity if it is already selected
|
||||
this.selectedElements.remove(entity);
|
||||
}
|
||||
|
||||
this.build();
|
||||
return true;
|
||||
}).
|
||||
glow(this.selectedElements.contains(entity)).
|
||||
build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Functional buttons in current GUI.
|
||||
* Returns the translation key prefix for element buttons.
|
||||
*/
|
||||
private enum Button
|
||||
{
|
||||
ACCEPT_SELECTED,
|
||||
CANCEL
|
||||
@Override
|
||||
protected String getElementKeyPrefix() {
|
||||
return "entity.";
|
||||
}
|
||||
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
ALIVE,
|
||||
ANY
|
||||
/**
|
||||
* Returns the icon for the given EntityType.
|
||||
* If asEgg is true, an entity spawn egg is returned; otherwise, the entity head is returned.
|
||||
*/
|
||||
@Override
|
||||
protected ItemStack getIcon(EntityType element) {
|
||||
return asEgg ? PanelUtils.getEntityEgg(element) : PanelUtils.getEntityHead(element);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Section: Variables
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* List with elements that will be displayed in current GUI.
|
||||
* Returns the display name for the given EntityType.
|
||||
*/
|
||||
private final List<EntityType> elements;
|
||||
|
||||
/**
|
||||
* Set that contains selected materials.
|
||||
*/
|
||||
private final Set<EntityType> selectedElements;
|
||||
|
||||
/**
|
||||
* This variable stores consumer.
|
||||
*/
|
||||
private final BiConsumer<Boolean, Collection<EntityType>> consumer;
|
||||
|
||||
/**
|
||||
* Indicates that entity must be displayed as egg.
|
||||
*/
|
||||
private final boolean asEgg;
|
||||
|
||||
/**
|
||||
* Stores filtered items.
|
||||
*/
|
||||
private List<EntityType> filterElements;
|
||||
@Override
|
||||
protected String getElementDisplayName(EntityType element) {
|
||||
return Utils.prettifyObject(element, this.user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the given EntityType used for filtering.
|
||||
*/
|
||||
@Override
|
||||
protected String elementToString(EntityType element) {
|
||||
return element.name();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,200 @@
|
||||
package world.bentobox.challenges.panel.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.challenges.utils.Utils;
|
||||
|
||||
/**
|
||||
* This class provides a multi-selector GUI for selecting entity-type tags.
|
||||
* It extends the unified multi-selector base class (UnifiedMultiSelector) and supplies
|
||||
* all tag-specific implementations such as retrieving the tag list, filtering unwanted tags,
|
||||
* and choosing an appropriate icon.
|
||||
*
|
||||
* @see UnifiedMultiSelector
|
||||
*/
|
||||
public class MultiEntityTypeTagsSelector extends UnifiedMultiSelector<Tag<EntityType>> {
|
||||
|
||||
private final Mode mode;
|
||||
private final Set<Tag<EntityType>> excluded;
|
||||
|
||||
/**
|
||||
* Defines filtering modes.
|
||||
*/
|
||||
public enum Mode {
|
||||
ENTITY_TYPE, ANY
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
*
|
||||
* @param user the user opening the selector
|
||||
* @param mode the mode (ENTITY_TYPE or ANY) that might influence filtering behavior
|
||||
* @param excluded a set of tags to be excluded from display
|
||||
* @param consumer a callback to receive the selected tags (or cancellation)
|
||||
*/
|
||||
private MultiEntityTypeTagsSelector(User user, Mode mode, Set<Tag<EntityType>> excluded,
|
||||
BiConsumer<Boolean, java.util.Collection<Tag<EntityType>>> consumer) {
|
||||
super(user, consumer);
|
||||
this.mode = mode; // This is not currently used
|
||||
this.excluded = excluded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the entity-type tag selector GUI with the specified mode and exclusions.
|
||||
*
|
||||
* @param user the user who opens the GUI
|
||||
* @param mode filtering mode (ENTITY_TYPE or ANY)
|
||||
* @param excluded a set of tags to exclude
|
||||
* @param consumer a callback to receive the result
|
||||
*/
|
||||
public static void open(User user, Mode mode, Set<Tag<EntityType>> excluded,
|
||||
BiConsumer<Boolean, java.util.Collection<Tag<EntityType>>> consumer) {
|
||||
new MultiEntityTypeTagsSelector(user, mode, excluded, consumer).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the entity-type tag selector GUI with default parameters (mode ANY and no exclusions).
|
||||
*
|
||||
* @param user the user who opens the GUI
|
||||
* @param consumer a callback to receive the result
|
||||
*/
|
||||
public static void open(User user,
|
||||
BiConsumer<Boolean, java.util.Collection<Tag<EntityType>>> consumer) {
|
||||
new MultiEntityTypeTagsSelector(user, Mode.ANY, new HashSet<>(), consumer).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of available entity-type tags.
|
||||
* <p>
|
||||
* This method uses Bukkit’s tag API to get all tags for "entity_types" (of type EntityType),
|
||||
* sorts them by their key, then removes any that are deemed irrelevant based on their key name
|
||||
* (for example, tags containing "AXOLOTL", "IMMUNE", etc.) and any tags specified in the excluded set.
|
||||
* </p>
|
||||
*
|
||||
* @return a sorted and filtered list of Tag<EntityType>
|
||||
*/
|
||||
@Override
|
||||
protected List<Tag<EntityType>> getElements() {
|
||||
List<Tag<EntityType>> tagList = new ArrayList<>();
|
||||
Iterable<Tag<EntityType>> iterable = Bukkit.getTags("entity_types", EntityType.class);
|
||||
iterable.forEach(tagList::add);
|
||||
tagList.sort(Comparator.comparing(tag -> tag.getKey().getKey()));
|
||||
|
||||
// Remove irrelevant tags based on key contents.
|
||||
tagList.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("AXOLOTL"));
|
||||
tagList.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("IMMUNE"));
|
||||
tagList.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("IGNORES"));
|
||||
tagList.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("FRIEND"));
|
||||
tagList.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("SENSITIVE"));
|
||||
tagList.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("PROJECTILE"));
|
||||
|
||||
// Remove specific known tags.
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_ARROWS);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_BEEHIVE_INHABITORS);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_CAN_TURN_IN_BOATS);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_DISMOUNTS_UNDERWATER);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_FALL_DAMAGE_IMMUNE);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_FREEZE_HURTS_EXTRA_TYPES);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_INVERTED_HEALING_AND_HARM);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_NO_ANGER_FROM_WIND_CHARGE);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_NON_CONTROLLING_RIDER);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_NOT_SCARY_FOR_PUFFERFISH);
|
||||
tagList.remove(org.bukkit.Tag.ENTITY_TYPES_FROG_FOOD);
|
||||
|
||||
// Remove any tags specified in the excluded set.
|
||||
if (excluded != null) {
|
||||
for (Tag<EntityType> ex : excluded) {
|
||||
tagList.removeIf(tag -> tag.equals(ex));
|
||||
}
|
||||
}
|
||||
return tagList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title key used to build the GUI title.
|
||||
*
|
||||
* @return "entity-selector"
|
||||
*/
|
||||
@Override
|
||||
protected String getTitleKey() {
|
||||
return "entity-selector";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the translation key prefix for individual element buttons.
|
||||
*
|
||||
* @return "entity-group."
|
||||
*/
|
||||
@Override
|
||||
protected String getElementKeyPrefix() {
|
||||
return "entity-group.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icon for the given entity-type tag.
|
||||
* <p>
|
||||
* If the tag’s key contains "boat", an oak boat icon is used. Otherwise, the method attempts
|
||||
* to find any EntityType that is tagged by this tag and constructs a spawn egg material name
|
||||
* (e.g. "CREEPER_SPAWN_EGG"). If no matching material is found, a PAPER icon is returned.
|
||||
* </p>
|
||||
*
|
||||
* @param element the Tag<EntityType> for which to determine the icon
|
||||
* @return an ItemStack representing the icon
|
||||
*/
|
||||
@Override
|
||||
protected ItemStack getIcon(Tag<EntityType> element) {
|
||||
Material iconMaterial;
|
||||
if (element.getKey().getKey().contains("boat")) {
|
||||
iconMaterial = Material.OAK_BOAT;
|
||||
} else {
|
||||
EntityType entType = Registry.ENTITY_TYPE.stream().filter(element::isTagged).findAny().orElse(null);
|
||||
if (entType != null) {
|
||||
String eggName = entType.getKey().getKey().toUpperCase(Locale.ENGLISH) + "_SPAWN_EGG";
|
||||
try {
|
||||
iconMaterial = Material.valueOf(eggName);
|
||||
} catch (Exception e) {
|
||||
iconMaterial = Material.PAPER;
|
||||
}
|
||||
} else {
|
||||
iconMaterial = Material.PAPER;
|
||||
}
|
||||
}
|
||||
return new ItemStack(iconMaterial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name for the given tag.
|
||||
*
|
||||
* @param element the Tag<EntityType>
|
||||
* @return a pretty-printed string for display
|
||||
*/
|
||||
@Override
|
||||
protected String getElementDisplayName(Tag<EntityType> element) {
|
||||
return Utils.prettifyObject(element, this.user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the tag used for filtering.
|
||||
*
|
||||
* @param element the Tag<EntityType>
|
||||
* @return the tag’s key (as a string)
|
||||
*/
|
||||
@Override
|
||||
protected String elementToString(Tag<EntityType> element) {
|
||||
return element.getKey().getKey();
|
||||
}
|
||||
}
|
@ -0,0 +1,229 @@
|
||||
package world.bentobox.challenges.panel.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.challenges.utils.Utils;
|
||||
|
||||
/**
|
||||
* This class provides a multi-selector GUI for selecting material tags.
|
||||
* It extends the unified multi-selector base class and supplies the tag‑specific
|
||||
* implementations such as retrieving the tag list, filtering unwanted tags,
|
||||
* selecting an appropriate icon, and generating display names.
|
||||
*
|
||||
* <p>
|
||||
* Two static open methods are provided: one that accepts a filtering mode and an excluded set,
|
||||
* and one that uses default parameters.
|
||||
* </p>
|
||||
*
|
||||
* @see UnifiedMultiSelector
|
||||
*/
|
||||
public class MultiMaterialTagsSelector extends UnifiedMultiSelector<Tag<Material>> {
|
||||
|
||||
/**
|
||||
* A map of specific tags to custom icon materials.
|
||||
*/
|
||||
public static final Map<Tag<Material>, Material> ICONS = Map.of(
|
||||
Tag.AIR, Material.BARRIER, Tag.FIRE, Material.TORCH, Tag.CANDLE_CAKES, Material.CAKE, Tag.PORTALS,
|
||||
Material.MAGENTA_STAINED_GLASS_PANE, Tag.WALL_HANGING_SIGNS, Material.ACACIA_SIGN, Tag.WALL_SIGNS,
|
||||
Material.OAK_SIGN,
|
||||
Tag.WALL_CORALS, Material.BUBBLE_CORAL_FAN, Tag.CAVE_VINES, Material.VINE
|
||||
);
|
||||
|
||||
private final Mode mode;
|
||||
private final Set<Tag<Material>> excluded;
|
||||
|
||||
/**
|
||||
* Modes for filtering material tags.
|
||||
*/
|
||||
public enum Mode {
|
||||
BLOCKS, ITEMS, ANY
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
*
|
||||
* @param user the user opening the selector
|
||||
* @param mode filtering mode (BLOCKS, ITEMS, or ANY)
|
||||
* @param excluded a set of tags to exclude from display
|
||||
* @param consumer the callback to receive the selected tags or cancellation
|
||||
*/
|
||||
private MultiMaterialTagsSelector(User user, Mode mode, Set<Tag<Material>> excluded,
|
||||
BiConsumer<Boolean, Collection<Tag<Material>>> consumer) {
|
||||
super(user, consumer);
|
||||
this.mode = mode; // Not currently used
|
||||
this.excluded = excluded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the material tag selector GUI with a specified mode and exclusions.
|
||||
*
|
||||
* @param user the user who opens the GUI
|
||||
* @param mode the filtering mode (BLOCKS, ITEMS, or ANY)
|
||||
* @param excluded a set of tags to exclude
|
||||
* @param consumer a callback to receive the result
|
||||
*/
|
||||
public static void open(User user, Mode mode, Set<Tag<Material>> excluded,
|
||||
BiConsumer<Boolean, Collection<Tag<Material>>> consumer) {
|
||||
new MultiMaterialTagsSelector(user, mode, excluded, consumer).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the material tag selector GUI with default parameters (mode ANY and no exclusions).
|
||||
*
|
||||
* @param user the user who opens the GUI
|
||||
* @param consumer a callback to receive the result
|
||||
*/
|
||||
public static void open(User user, BiConsumer<Boolean, Collection<Tag<Material>>> consumer) {
|
||||
new MultiMaterialTagsSelector(user, Mode.ANY, new HashSet<>(), consumer).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of available material tags.
|
||||
*
|
||||
* <p>
|
||||
* This method obtains tags using Bukkit’s tag API for the "blocks" category,
|
||||
* sorts them by their key name, applies several removeIf filters to eliminate irrelevant tags,
|
||||
* and then removes any tags provided in the excluded set.
|
||||
* </p>
|
||||
*
|
||||
* @return a sorted and filtered list of Tag<Material>
|
||||
*/
|
||||
@Override
|
||||
protected List<Tag<Material>> getElements() {
|
||||
List<Tag<Material>> list = new ArrayList<>();
|
||||
Iterable<Tag<Material>> iterable = Bukkit.getTags("blocks", Material.class);
|
||||
iterable.forEach(list::add);
|
||||
list.sort(Comparator.comparing(tag -> tag.getKey().getKey()));
|
||||
|
||||
// Remove irrelevant tags based on their key.
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("SPAWNABLE"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("PLACE"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("TEMPT"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("_ON"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("BASE"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("SOUND_BLOCKS"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("DRAGON"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("VALID"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("INCORRECT"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("INFINIBURN"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("MINEABLE"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("TOOL"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("SNIFFER"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("OVERRIDE"));
|
||||
list.removeIf(t -> t.getKey().getKey().toUpperCase(Locale.ENGLISH).contains("OVERWORLD"));
|
||||
|
||||
// Remove specific known tags.
|
||||
list.remove(Tag.BLOCKS_WIND_CHARGE_EXPLOSIONS);
|
||||
list.remove(Tag.CONVERTABLE_TO_MUD);
|
||||
list.remove(Tag.DAMPENS_VIBRATIONS);
|
||||
list.remove(Tag.DOES_NOT_BLOCK_HOPPERS);
|
||||
list.remove(Tag.ENCHANTMENT_POWER_PROVIDER);
|
||||
list.remove(Tag.ENCHANTMENT_POWER_TRANSMITTER);
|
||||
list.remove(Tag.ENDERMAN_HOLDABLE);
|
||||
list.remove(Tag.FEATURES_CANNOT_REPLACE);
|
||||
list.remove(Tag.FALL_DAMAGE_RESETTING);
|
||||
list.remove(Tag.FROG_PREFER_JUMP_TO);
|
||||
list.remove(Tag.MAINTAINS_FARMLAND);
|
||||
list.remove(Tag.MANGROVE_LOGS_CAN_GROW_THROUGH);
|
||||
list.remove(Tag.MANGROVE_ROOTS_CAN_GROW_THROUGH);
|
||||
list.remove(Tag.BEE_GROWABLES);
|
||||
list.remove(Tag.MOB_INTERACTABLE_DOORS);
|
||||
list.remove(Tag.HOGLIN_REPELLENTS);
|
||||
list.remove(Tag.PIGLIN_REPELLENTS);
|
||||
list.remove(Tag.SNAPS_GOAT_HORN);
|
||||
list.remove(Tag.SOUL_SPEED_BLOCKS);
|
||||
list.remove(Tag.STRIDER_WARM_BLOCKS);
|
||||
list.remove(Tag.SWORD_EFFICIENT);
|
||||
list.remove(Tag.UNSTABLE_BOTTOM_CENTER);
|
||||
list.remove(Tag.COMPLETES_FIND_TREE_TUTORIAL);
|
||||
list.remove(Tag.GUARDED_BY_PIGLINS);
|
||||
list.remove(Tag.IMPERMEABLE);
|
||||
list.remove(Tag.PREVENT_MOB_SPAWNING_INSIDE);
|
||||
list.remove(Tag.SMELTS_TO_GLASS);
|
||||
list.remove(Tag.WITHER_IMMUNE);
|
||||
|
||||
// Remove any tags specified in the excluded set.
|
||||
if (excluded != null) {
|
||||
for (Tag<Material> ex : excluded) {
|
||||
list.removeIf(tag -> tag.equals(ex));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the title key used for the GUI.
|
||||
*
|
||||
* @return "block-selector"
|
||||
*/
|
||||
@Override
|
||||
protected String getTitleKey() {
|
||||
return "block-selector";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the translation key prefix for individual element buttons.
|
||||
*
|
||||
* @return "block-group."
|
||||
*/
|
||||
@Override
|
||||
protected String getElementKeyPrefix() {
|
||||
return "block-group.";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icon for the given material tag.
|
||||
*
|
||||
* <p>
|
||||
* This method first checks the ICONS map; if a mapping exists for the tag, that material is used.
|
||||
* Otherwise, it searches through the Bukkit material registry for any material tagged by the given tag
|
||||
* that is also an item. If none is found, it falls back to PAPER.
|
||||
* </p>
|
||||
*
|
||||
* @param element the Tag<Material> for which to determine the icon
|
||||
* @return an ItemStack representing the icon
|
||||
*/
|
||||
@Override
|
||||
protected ItemStack getIcon(Tag<Material> element) {
|
||||
Material iconMaterial = ICONS.getOrDefault(element, Registry.MATERIAL.stream().filter(element::isTagged)
|
||||
.filter(Material::isItem).findAny().orElse(Material.PAPER));
|
||||
return new ItemStack(iconMaterial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name for the given material tag.
|
||||
*
|
||||
* @param element the Tag<Material>
|
||||
* @return a pretty-printed string for display
|
||||
*/
|
||||
@Override
|
||||
protected String getElementDisplayName(Tag<Material> element) {
|
||||
return Utils.prettifyObject(element, this.user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the tag used for filtering.
|
||||
*
|
||||
* @param element the Tag<Material>
|
||||
* @return the tag's key (as a string)
|
||||
*/
|
||||
@Override
|
||||
protected String elementToString(Tag<Material> element) {
|
||||
return element.getKey().getKey();
|
||||
}
|
||||
}
|
@ -7,12 +7,13 @@
|
||||
package world.bentobox.challenges.panel.util;
|
||||
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
|
@ -1,12 +1,18 @@
|
||||
package world.bentobox.challenges.panel.util;
|
||||
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import lv.id.bonne.panelutils.PanelUtils;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
|
@ -1,7 +1,12 @@
|
||||
package world.bentobox.challenges.panel.util;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -1,12 +1,16 @@
|
||||
package world.bentobox.challenges.panel.util;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lv.id.bonne.panelutils.PanelUtils;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
|
@ -0,0 +1,192 @@
|
||||
package world.bentobox.challenges.panel.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import lv.id.bonne.panelutils.PanelUtils;
|
||||
import world.bentobox.bentobox.BentoBox;
|
||||
import world.bentobox.bentobox.api.panels.PanelItem;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelBuilder;
|
||||
import world.bentobox.bentobox.api.panels.builders.PanelItemBuilder;
|
||||
import world.bentobox.bentobox.api.user.User;
|
||||
import world.bentobox.challenges.utils.Constants;
|
||||
|
||||
/**
|
||||
* Unified abstract class for multi‐selector GUIs.
|
||||
* <p>
|
||||
* This class provides the common logic for building the GUI, filtering the list,
|
||||
* and creating the functional buttons. Subclasses must supply the list of available elements
|
||||
* and type‐specific details such as how to obtain an element’s display name, icon, and
|
||||
* string representation for filtering.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> The type of element shown in the GUI (e.g. Material, EntityType, or Tag<Material>, etc.)
|
||||
*/
|
||||
public abstract class UnifiedMultiSelector<T> extends PagedSelector<T> {
|
||||
|
||||
protected final List<T> elements;
|
||||
protected final Set<T> selectedElements;
|
||||
protected final BiConsumer<Boolean, Collection<T>> consumer;
|
||||
protected List<T> filterElements;
|
||||
|
||||
protected UnifiedMultiSelector(User user, BiConsumer<Boolean, Collection<T>> consumer) {
|
||||
super(user);
|
||||
this.consumer = consumer;
|
||||
this.selectedElements = new HashSet<>();
|
||||
// Obtain the complete list of elements from the subclass.
|
||||
this.elements = getElements();
|
||||
// Sort elements using the provided string representation.
|
||||
this.elements.sort(Comparator.comparing(this::elementToString));
|
||||
// Start with the full list as the filtered list.
|
||||
this.filterElements = this.elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must return the complete list of available elements.
|
||||
*/
|
||||
protected abstract List<T> getElements();
|
||||
|
||||
/**
|
||||
* Returns the title key (to be appended to Constants.TITLE)
|
||||
* for this selector (for example, "entity-selector" or "block-selector").
|
||||
*/
|
||||
protected abstract String getTitleKey();
|
||||
|
||||
/**
|
||||
* Returns the translation key prefix used for element buttons
|
||||
* (for example, "entity." or "material.").
|
||||
*/
|
||||
protected abstract String getElementKeyPrefix();
|
||||
|
||||
/**
|
||||
* Returns the icon for the given element.
|
||||
*/
|
||||
protected abstract ItemStack getIcon(T element);
|
||||
|
||||
/**
|
||||
* Returns the display name for the given element.
|
||||
* (For instance, by calling Utils.prettifyObject(element, user)).
|
||||
*/
|
||||
protected abstract String getElementDisplayName(T element);
|
||||
|
||||
/**
|
||||
* Returns a string representation of the element used for filtering.
|
||||
* (For enums you might simply return element.name().)
|
||||
*/
|
||||
protected abstract String elementToString(T element);
|
||||
|
||||
@Override
|
||||
protected void build() {
|
||||
PanelBuilder panelBuilder = new PanelBuilder().user(this.user);
|
||||
panelBuilder.name(this.user.getTranslation(Constants.TITLE + getTitleKey()));
|
||||
|
||||
PanelUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE);
|
||||
|
||||
// Populate the GUI with the filtered list.
|
||||
this.populateElements(panelBuilder, this.filterElements);
|
||||
|
||||
// Add functional buttons.
|
||||
panelBuilder.item(3, createButton(Button.ACCEPT_SELECTED));
|
||||
panelBuilder.item(5, createButton(Button.CANCEL));
|
||||
|
||||
panelBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFilters() {
|
||||
if (this.searchString == null || this.searchString.isBlank()) {
|
||||
this.filterElements = this.elements;
|
||||
} else {
|
||||
this.filterElements = this.elements.stream()
|
||||
.filter(element -> elementToString(element).toLowerCase(Locale.ENGLISH)
|
||||
.contains(this.searchString.toLowerCase(Locale.ENGLISH)))
|
||||
.distinct().collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
private PanelItem createButton(Button button) {
|
||||
final String reference = Constants.BUTTON + button.name().toLowerCase() + ".";
|
||||
final String name = this.user.getTranslation(reference + "name");
|
||||
final List<String> description = new ArrayList<>();
|
||||
description.add(this.user.getTranslation(reference + "description"));
|
||||
|
||||
ItemStack icon;
|
||||
PanelItem.ClickHandler clickHandler;
|
||||
|
||||
switch (button) {
|
||||
case ACCEPT_SELECTED -> {
|
||||
if (!this.selectedElements.isEmpty()) {
|
||||
description.add(this.user.getTranslation(reference + "title"));
|
||||
for (T element : this.selectedElements) {
|
||||
description.add(this.user.getTranslation(reference + "element", "[element]",
|
||||
getElementDisplayName(element)));
|
||||
}
|
||||
}
|
||||
icon = new ItemStack(Material.COMMAND_BLOCK);
|
||||
clickHandler = (panel, user1, clickType, slot) -> {
|
||||
this.consumer.accept(true, this.selectedElements);
|
||||
return true;
|
||||
};
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-save"));
|
||||
}
|
||||
case CANCEL -> {
|
||||
icon = new ItemStack(Material.IRON_DOOR);
|
||||
clickHandler = (panel, user1, clickType, slot) -> {
|
||||
this.consumer.accept(false, null);
|
||||
return true;
|
||||
};
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-cancel"));
|
||||
}
|
||||
default -> {
|
||||
icon = new ItemStack(Material.PAPER);
|
||||
clickHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
return new PanelItemBuilder().icon(icon).name(name).description(description).clickHandler(clickHandler).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PanelItem createElementButton(T element) {
|
||||
final String reference = Constants.BUTTON + getElementKeyPrefix();
|
||||
List<String> description = new ArrayList<>();
|
||||
description.add(this.user.getTranslation(reference + "description", "[id]", elementToString(element)));
|
||||
|
||||
if (this.selectedElements.contains(element)) {
|
||||
description.add(this.user.getTranslation(reference + "selected"));
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-deselect"));
|
||||
} else {
|
||||
description.add("");
|
||||
description.add(this.user.getTranslation(Constants.TIPS + "click-to-select"));
|
||||
}
|
||||
|
||||
return new PanelItemBuilder()
|
||||
.name(this.user.getTranslation(reference + "name", "[id]",
|
||||
getElementDisplayName(element)))
|
||||
.icon(getIcon(element)).description(description).clickHandler((panel, user1, clickType, slot) -> {
|
||||
// Toggle the selection state.
|
||||
if (!this.selectedElements.add(element)) {
|
||||
this.selectedElements.remove(element);
|
||||
}
|
||||
this.build();
|
||||
return true;
|
||||
}).glow(this.selectedElements.contains(element)).build();
|
||||
}
|
||||
|
||||
protected enum Button {
|
||||
ACCEPT_SELECTED, CANCEL
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -11,6 +11,7 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Statistic;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.EntityType;
|
||||
@ -284,6 +285,25 @@ public class Utils
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Prettify the Tag object for user.
|
||||
* @param object a tag, like ALL_HANGING_SIGNS
|
||||
* @param user user
|
||||
* @return prettified tag
|
||||
*/
|
||||
public static String prettifyObject(@Nullable Tag<?> object, User user) {
|
||||
// Nothing to translate
|
||||
if (object == null) {
|
||||
return "";
|
||||
}
|
||||
String translation = user.getTranslationOrNothing(
|
||||
Constants.MATERIALS + object.getKey().getKey().toLowerCase(Locale.ENGLISH) + ".name");
|
||||
String any = user.getTranslationOrNothing(Constants.MATERIALS + "any");
|
||||
// Prettify and remove last s
|
||||
String tag = any + Util.prettifyText(object.getKey().getKey()).replaceAll("s$", "");
|
||||
|
||||
return translation.isEmpty() ? tag : translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prettify Material object for user.
|
||||
|
@ -1,7 +1,7 @@
|
||||
name: Challenges
|
||||
main: world.bentobox.challenges.ChallengesAddon
|
||||
version: ${version}${build.number}
|
||||
api-version: 2.7.1
|
||||
api-version: 3.2.4
|
||||
repository: 'BentoBoxWorld/Challenges'
|
||||
metrics: true
|
||||
|
||||
@ -9,7 +9,7 @@ authors:
|
||||
- tastybento
|
||||
- BONNe
|
||||
|
||||
softdepend: AcidIsland, BSkyBlock, CaveBlock, SkyGrid, Level
|
||||
softdepend: AcidIsland, BSkyBlock, CaveBlock, SkyGrid, Level, Poseidon, Boxed
|
||||
|
||||
permissions:
|
||||
addon.admin.challenges:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,11 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
|
Loading…
Reference in New Issue
Block a user