Update all admin panels.

Admin panels will not contain better locales codding and easier-to-improve design.

Remove old and unused GUIs.
This commit is contained in:
BONNe 2021-09-18 12:56:44 +03:00
parent 09a30f00db
commit 3ee89af5df
30 changed files with 6233 additions and 8746 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
//
// Created by BONNe
// Copyright - 2021
//
package world.bentobox.challenges.panel;
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.Function;
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.ChallengesAddon;
import world.bentobox.challenges.utils.Constants;
/**
* This panel implements common things for Paged pages.
*/
public abstract class CommonPagedPanel extends CommonPanel
{
/**
* Instantiates a new Common paged panel.
*
* @param addon the addon
* @param user the user
* @param world the world
* @param topLabel the top label
* @param permissionPrefix the permission prefix
*/
protected CommonPagedPanel(ChallengesAddon addon,
User user,
World world, String topLabel, String permissionPrefix)
{
super(addon, user, world, topLabel, permissionPrefix);
}
/**
* Instantiates a new Common paged panel.
*
* @param parentPanel the parent panel
*/
protected CommonPagedPanel(@NonNull CommonPanel parentPanel)
{
super(parentPanel);
}
/**
* Populate elements.
*
* @param panelBuilder the panel builder
* @param objectList the object list
* @param buttonBuilder the button builder
*/
protected void populateElements(PanelBuilder panelBuilder,
List<?> objectList,
Function<Object, PanelItem> buttonBuilder)
{
final int MAX_ELEMENTS = 21;
final int size = objectList.size();
if (this.pageIndex < 0)
{
this.pageIndex = size / MAX_ELEMENTS;
}
else if (this.pageIndex > (size / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int objectIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (objectIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
objectIndex < size &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, buttonBuilder.apply(objectList.get(objectIndex++)));
}
index++;
}
if (size > MAX_ELEMENTS && !(1.0 * size / MAX_ELEMENTS <= this.pageIndex + 1))
{
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
if (this.pageIndex > 0)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
}
}
/**
* This method returns PanelItem that represents given Button.
* @param button Button that must be returned.
* @return PanelItem with requested functionality.
*/
protected PanelItem getButton(CommonButtons button)
{
final String reference = Constants.BUTTON + button.name().toLowerCase() + ".";
final String name = this.user.getTranslation(reference + "name");
final List<String> description = new ArrayList<>(3);
ItemStack icon;
PanelItem.ClickHandler clickHandler;
if (button == CommonButtons.NEXT)
{
description.add(this.user.getTranslation(reference + "description",
Constants.NUMBER, String.valueOf(this.pageIndex + 2)));
icon = new ItemStack(Material.OAK_SIGN, this.pageIndex + 2);
clickHandler = (panel, user, clickType, slot) ->
{
this.pageIndex++;
this.build();
return true;
};
}
else if (button == CommonButtons.PREVIOUS)
{
description.add(this.user.getTranslation(reference + "description",
Constants.NUMBER, String.valueOf(this.pageIndex)));
icon = new ItemStack(Material.OAK_SIGN, Math.max(1, this.pageIndex));
clickHandler = (panel, user, clickType, slot) ->
{
this.pageIndex--;
this.build();
return true;
};
}
else
{
icon = new ItemStack(Material.PAPER);
clickHandler = null;
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(description).
clickHandler(clickHandler).
build();
}
/**
* Next and Previous Buttons.
*/
private enum CommonButtons
{
NEXT,
PREVIOUS
}
/**
* Current page index.
*/
private int pageIndex;
}

View File

@ -0,0 +1,558 @@
//
// Created by BONNe
// Copyright - 2020
//
package world.bentobox.challenges.panel;
import org.apache.commons.lang.ArrayUtils;
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.List;
import java.util.function.Consumer;
import java.util.function.Function;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.Utils;
public class ConversationUtils
{
// ---------------------------------------------------------------------
// Section: Conversation API implementation
// ---------------------------------------------------------------------
/**
* This method will close opened gui and writes question in chat. After players answers on question in chat, message
* will trigger consumer and gui will reopen. Success and fail messages can be implemented like that, as user's chat
* options are disabled while it is in conversation.
*
* @param consumer Consumer that accepts player output text.
* @param question Message that will be displayed in chat when player triggers conversion.
* @param successMessage Message that will be displayed on successful operation.
* @param user User who is targeted with current confirmation.
*/
public static void createConfirmation(Consumer<Boolean> consumer,
User user,
@NotNull String question,
@Nullable String successMessage)
{
ValidatingPrompt confirmationPrompt = new ValidatingPrompt()
{
/**
* Is input valid boolean.
*
* @param context the context
* @param input the input
* @return the boolean
*/
@Override
protected boolean isInputValid(@NotNull ConversationContext context, @NotNull String input)
{
// Get valid strings from translations
String validEntry = user.getTranslation(Constants.CONVERSATIONS + "confirm-string") +
"," + user.getTranslation(Constants.CONVERSATIONS + "deny-string") +
"," + user.getTranslation(Constants.CONVERSATIONS + "exit-string") +
"," + user.getTranslation(Constants.CONVERSATIONS + "cancel-string");
// Split and check if they exist in valid entries.
String[] accepted = validEntry.toLowerCase().replaceAll("\\s", "").split(",");
return ArrayUtils.contains(accepted, input.toLowerCase());
}
/**
* Accept validated input prompt.
*
* @param context the context
* @param input the input
* @return the prompt
*/
@Override
@Nullable
protected Prompt acceptValidatedInput(@NotNull ConversationContext context, @NotNull String input)
{
String validEntry = user.getTranslation(Constants.CONVERSATIONS + "confirm-string").toLowerCase();
if (ArrayUtils.contains(validEntry.replaceAll("\\s", "").split(","), input.toLowerCase()))
{
// Add answer to consumer.
consumer.accept(true);
// Return message about success.
return ConversationUtils.endMessagePrompt(successMessage);
}
else
{
// Add answer to consumer.
consumer.accept(false);
// Return message about failed operation.
return ConversationUtils.endMessagePrompt(
user.getTranslation(Constants.CONVERSATIONS + "cancelled"));
}
}
/**
* @see Prompt#getPromptText(ConversationContext)
*/
@Override
public @NotNull String getPromptText(@NotNull ConversationContext conversationContext)
{
// Close input GUI.
user.closeInventory();
// There are no editable message. Just return question.
return question;
}
};
new ConversationFactory(BentoBox.getInstance()).
withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")).
withFirstPrompt(confirmationPrompt).
withLocalEcho(false).
withTimeout(90).
buildConversation(user.getPlayer()).
begin();
}
/**
* This method will close opened gui and writes question in chat. After players answers on question in chat, message
* will trigger consumer and gui will reopen. Be aware, consumer does not return (and validate) sanitized value,
* while sanitization is done in failure for better informing. Proper implementation would be with adding new
* consumer for failure message.
*
* @param consumer Consumer that accepts player output text.
* @param validation Function that validates if input value is acceptable.
* @param question Message that will be displayed in chat when player triggers conversion.
* @param failTranslationLocation Message that will be displayed on failed operation.
* @param user User who is targeted with current confirmation.
*/
public static void createIDStringInput(Consumer<String> consumer,
Function<String, Boolean> validation,
User user,
@NotNull String question,
@Nullable String successMessage,
@Nullable String failTranslationLocation)
{
ValidatingPrompt validatingPrompt = new ValidatingPrompt()
{
/**
* Gets the text to display to the user when
* this prompt is first presented.
*
* @param context Context information about the
* conversation.
* @return The text to display.
*/
@Override
public String getPromptText(ConversationContext context)
{
// Close input GUI.
user.closeInventory();
// There are no editable message. Just return question.
return question;
}
/**
* Override this method to check the validity of
* the player's input.
*
* @param context Context information about the
* conversation.
* @param input The player's raw console input.
* @return True or false depending on the
* validity of the input.
*/
@Override
protected boolean isInputValid(ConversationContext context, String input)
{
return validation.apply(input);
}
/**
* Optionally override this method to
* display an additional message if the
* user enters an invalid input.
*
* @param context Context information
* about the conversation.
* @param invalidInput The invalid input
* provided by the user.
* @return A message explaining how to
* correct the input.
*/
@Override
protected String getFailedValidationText(ConversationContext context,
String invalidInput)
{
return user.getTranslation(failTranslationLocation,
Constants.ID,
Utils.sanitizeInput(invalidInput));
}
/**
* Override this method to accept and processes
* the validated input from the user. Using the
* input, the next Prompt in the prompt graph
* should be returned.
*
* @param context Context information about the
* conversation.
* @param input The validated input text from
* the user.
* @return The next Prompt in the prompt graph.
*/
@Override
protected Prompt acceptValidatedInput(ConversationContext context, String input)
{
// Add answer to consumer.
consumer.accept(input);
// Send message that it is accepted.
return ConversationUtils.endMessagePrompt(successMessage);
}
};
new ConversationFactory(BentoBox.getInstance()).
withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")).
withFirstPrompt(validatingPrompt).
withLocalEcho(false).
withTimeout(90).
// On cancel conversation will be closed.
withEscapeSequence(user.getTranslation(Constants.CONVERSATIONS + "cancel-string")).
// Use null value in consumer to detect if user has abandoned conversation.
addConversationAbandonedListener(ConversationUtils.getAbandonListener(consumer, user)).
buildConversation(user.getPlayer()).
begin();
}
/**
* This method will close opened gui and writes inputText in chat. After players answers on inputText in chat,
* message will trigger consumer and gui will reopen.
*
* @param consumer Consumer that accepts player output text.
* @param question Message that will be displayed in chat when player triggers conversion.
*/
public static void createNumericInput(Consumer<Number> consumer,
@NotNull User user,
@NotNull String question,
Number minValue,
Number maxValue)
{
// Create NumericPromt instance that will validate and process input.
NumericPrompt numberPrompt = new NumericPrompt()
{
/**
* Override this method to perform some action
* with the user's integer response.
*
* @param context Context information about the
* conversation.
* @param input The user's response as a {@link
* Number}.
* @return The next {@link Prompt} in the prompt
* graph.
*/
@Override
protected Prompt acceptValidatedInput(ConversationContext context, Number input)
{
// Add answer to consumer.
consumer.accept(input);
// End conversation
return Prompt.END_OF_CONVERSATION;
}
/**
* Override this method to do further validation on the numeric player
* input after the input has been determined to actually be a number.
*
* @param context Context information about the conversation.
* @param input The number the player provided.
* @return The validity of the player's input.
*/
@Override
protected boolean isNumberValid(ConversationContext context, Number input)
{
return input.doubleValue() >= minValue.doubleValue() &&
input.doubleValue() <= maxValue.doubleValue();
}
/**
* Optionally override this method to display an additional message if the
* user enters an invalid number.
*
* @param context Context information about the conversation.
* @param invalidInput The invalid input provided by the user.
* @return A message explaining how to correct the input.
*/
@Override
protected String getInputNotNumericText(ConversationContext context, String invalidInput)
{
return user.getTranslation(Constants.CONVERSATIONS + "numeric-only", Constants.VALUE, invalidInput);
}
/**
* Optionally override this method to display an additional message if the
* user enters an invalid numeric input.
*
* @param context Context information about the conversation.
* @param invalidInput The invalid input provided by the user.
* @return A message explaining how to correct the input.
*/
@Override
protected String getFailedValidationText(ConversationContext context, Number invalidInput)
{
return user.getTranslation(Constants.CONVERSATIONS + "not-valid-value",
Constants.VALUE, invalidInput.toString(),
Constants.MIN, Double.toString(minValue.doubleValue()),
Constants.MAX, Double.toString(maxValue.doubleValue()));
}
/**
* @see Prompt#getPromptText(ConversationContext)
*/
@Override
public String getPromptText(ConversationContext conversationContext)
{
// Close input GUI.
user.closeInventory();
// There are no editable message. Just return question.
return question;
}
};
// Init conversation api.
new ConversationFactory(BentoBox.getInstance()).
withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")).
withFirstPrompt(numberPrompt).
withLocalEcho(false).
withTimeout(90).
withEscapeSequence(user.getTranslation(Constants.CONVERSATIONS + "cancel-string")).
// Use null value in consumer to detect if user has abandoned conversation.
addConversationAbandonedListener(ConversationUtils.getAbandonListener(consumer, user)).
buildConversation(user.getPlayer()).
begin();
}
/**
* This method will close opened gui and writes question in chat. After players answers on question in chat, message
* will trigger consumer and gui will reopen. Be aware, consumer does not return (and validate) sanitized value,
* while sanitization is done in failure for better informing. Proper implementation would be with adding new
* consumer for failure message.
*
* @param consumer Consumer that accepts player output text.
* @param question Message that will be displayed in chat when player triggers conversion.
* @param user User who is targeted with current confirmation.
*/
public static void createStringListInput(Consumer<List<String>> consumer,
User user,
@NotNull String question,
@NotNull String successMessage)
{
final String SESSION_CONSTANT = Constants.CONVERSATIONS + user.getUniqueId();
// Successful message about completing.
MessagePrompt messagePrompt = new MessagePrompt()
{
@Override
public @NotNull String getPromptText(@NotNull ConversationContext context)
{
List<String> description = (List<String>) context.getSessionData(SESSION_CONSTANT);
if (description != null)
{
consumer.accept(description);
return successMessage;
}
else
{
return user.getTranslation(Constants.CONVERSATIONS + "cancelled");
}
}
@Override
protected @Nullable Prompt getNextPrompt(@NotNull ConversationContext context)
{
return Prompt.END_OF_CONVERSATION;
}
};
// Text input message.
StringPrompt stringPrompt = new StringPrompt()
{
@Override
public @NotNull String getPromptText(@NotNull ConversationContext context)
{
user.closeInventory();
if (context.getSessionData(SESSION_CONSTANT) != null)
{
StringBuilder sb = new StringBuilder();
sb.append(user.getTranslation(Constants.CONVERSATIONS + "written-text"));
sb.append(System.getProperty("line.separator"));
for (String line : ((List<String>) context.getSessionData(SESSION_CONSTANT)))
{
sb.append(line);
sb.append(System.getProperty("line.separator"));
}
return sb.toString();
}
return question;
}
@Override
public @Nullable Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input)
{
String[] exit = user.getTranslation(Constants.CONVERSATIONS + "exit-string").
toLowerCase().replaceAll("\\s", "").
split(",");
if (input != null && ArrayUtils.contains(exit, input.toLowerCase()))
{
return messagePrompt;
}
List<String> desc = new ArrayList<>();
if (context.getSessionData(SESSION_CONSTANT) != null)
{
desc = ((List<String>) context.getSessionData(SESSION_CONSTANT));
}
if (input != null) {
desc.add(ChatColor.translateAlternateColorCodes('&', input));
}
context.setSessionData(SESSION_CONSTANT, desc);
return this;
}
};
new ConversationFactory(BentoBox.getInstance()).
withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")).
withFirstPrompt(stringPrompt).
withModality(true).
withLocalEcho(false).
withTimeout(90).
withEscapeSequence(user.getTranslation(Constants.CONVERSATIONS + "cancel-string")).
addConversationAbandonedListener(ConversationUtils.getAbandonListener(consumer, user)).
buildConversation(user.getPlayer()).
begin();
}
/**
* This method will close opened gui and writes question in chat. After players answers on question in chat, message
* will trigger consumer and gui will reopen.
*
* @param consumer Consumer that accepts player output text.
* @param question Message that will be displayed in chat when player triggers conversion.
* @param user User who is targeted with current confirmation.
*/
public static void createStringInput(Consumer<String> consumer,
User user,
@NotNull String question,
@Nullable String successMessage)
{
// Text input message.
StringPrompt stringPrompt = new StringPrompt()
{
@Override
public @NotNull String getPromptText(@NotNull ConversationContext context)
{
user.closeInventory();
return question;
}
@Override
public @NotNull Prompt acceptInput(@NotNull ConversationContext context, @Nullable String input)
{
consumer.accept(input);
return ConversationUtils.endMessagePrompt(successMessage);
}
};
new ConversationFactory(BentoBox.getInstance()).
withPrefix(context -> user.getTranslation(Constants.CONVERSATIONS + "prefix")).
withFirstPrompt(stringPrompt).
// On cancel conversation will be closed.
withLocalEcho(false).
withTimeout(90).
withEscapeSequence(user.getTranslation(Constants.CONVERSATIONS + "cancel-string")).
// Use null value in consumer to detect if user has abandoned conversation.
addConversationAbandonedListener(ConversationUtils.getAbandonListener(consumer, user)).
buildConversation(user.getPlayer()).
begin();
}
/**
* This is just a simple end message prompt that displays requested message.
*
* @param message Message that will be displayed.
* @return MessagePrompt that displays given message and exists from conversation.
*/
private static MessagePrompt endMessagePrompt(@Nullable String message)
{
return new MessagePrompt()
{
@Override
public @NotNull String getPromptText(@NotNull ConversationContext context)
{
return message == null ? "" : message;
}
@Override
protected @Nullable Prompt getNextPrompt(@NotNull ConversationContext context)
{
return Prompt.END_OF_CONVERSATION;
}
};
}
/**
* This method creates and returns abandon listener for every conversation.
*
* @param consumer Consumer which must return null value.
* @param user User who was using conversation.
* @return ConversationAbandonedListener instance.
*/
private static ConversationAbandonedListener getAbandonListener(Consumer<?> consumer, User user)
{
return abandonedEvent ->
{
if (!abandonedEvent.gracefulExit())
{
consumer.accept(null);
// send cancell message
abandonedEvent.getContext().getForWhom().sendRawMessage(
user.getTranslation(Constants.CONVERSATIONS + "prefix") +
user.getTranslation(Constants.CONVERSATIONS + "cancelled"));
}
};
}
}

View File

@ -1,143 +0,0 @@
package world.bentobox.challenges.panel;
import java.util.List;
import java.util.Optional;
import org.bukkit.Material;
import org.bukkit.World;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.commands.CompositeCommand;
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.ChallengesAddon;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class process GameModeGui opening.
*/
public class GameModesGUI extends CommonGUI
{
/**
* @param adminMode - boolean that indicate if Gui is in admin mode.
* @param gameModeAddons - List with GameModes where Challenges addon is integrated.
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
public GameModesGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix,
boolean adminMode,
List<GameModeAddon> gameModeAddons)
{
super(addon, world, user, topLabel, permissionPrefix);
this.adminMode = adminMode;
this.gameModeAddons = gameModeAddons;
}
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name("challenges.gui.title.game-modes");
GuiUtils.fillBorder(panelBuilder, this.adminMode ?
Material.BLACK_STAINED_GLASS_PANE :
Material.BLUE_STAINED_GLASS_PANE);
int elementIndex;
if (this.gameModeAddons.size() < 8)
{
if (this.gameModeAddons.size() == 7)
{
elementIndex = 19;
}
else
{
elementIndex = 22 - this.gameModeAddons.size() / 2;
}
}
else
{
elementIndex = 10;
}
for (GameModeAddon gameModeAddon : this.gameModeAddons)
{
if (!panelBuilder.slotOccupied(elementIndex))
{
panelBuilder.item(elementIndex++, this.createGameModeIcon(gameModeAddon));
}
else
{
// Find first open slot
while (panelBuilder.slotOccupied(elementIndex))
{
elementIndex++;
}
}
}
panelBuilder.build();
}
/**
* This method creates icon that will display given GameMode addon.
* @param gameModeAddon GameMode addon.
* @return PanelItem that acts as icon for given GameMode.
*/
private PanelItem createGameModeIcon(GameModeAddon gameModeAddon)
{
return new PanelItemBuilder().
name(gameModeAddon.getDescription().getName()).
description(gameModeAddon.getDescription().getDescription()).
icon(Material.PAPER).
clickHandler((panel, user, clickType, slot) -> {
Optional<CompositeCommand> command;
if (this.adminMode)
{
command = gameModeAddon.getAdminCommand();
}
else
{
command = gameModeAddon.getPlayerCommand();
}
command.ifPresent(compositeCommand ->
user.performCommand(compositeCommand.getTopLabel() + " challenges"));
return true;
}).
build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with game mode addons which must be showed in current GUI.
*/
private List<GameModeAddon> gameModeAddons;
/**
* Stores if current GUI is in Admin Mode or not.
*/
private boolean adminMode;
}

View File

@ -1,736 +0,0 @@
package world.bentobox.challenges.panel.admin;
import java.util.Locale;
import java.util.function.Consumer;
import java.util.function.Function;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.conversations.*;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
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.ChallengesAddon;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.ChallengeTypeGUI;
import world.bentobox.challenges.panel.util.ConfirmationGUI;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
import world.bentobox.challenges.web.WebManager;
/**
* This class contains Main
*/
public class AdminGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This boolean holds if import should overwrite existing challenges.
*/
private boolean overwriteMode;
/**
* This indicate if Reset Challenges must work as reset all.
*/
private boolean resetAllMode;
/**
* This indicate if wipe button should clear all data, or only challenges.
*/
private boolean wipeAll;
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum contains all button variations. Just for cleaner code.
*/
private enum Button
{
COMPLETE_USER_CHALLENGES,
RESET_USER_CHALLENGES,
ADD_CHALLENGE,
ADD_LEVEL,
EDIT_CHALLENGE,
EDIT_LEVEL,
DELETE_CHALLENGE,
DELETE_LEVEL,
EDIT_SETTINGS,
DEFAULT_IMPORT_CHALLENGES,
DEFAULT_EXPORT_CHALLENGES,
/**
* Allows to remove whole database
*/
COMPLETE_WIPE,
/**
* Allows to remove only challenges and levels
*/
CHALLENGE_WIPE,
/**
* Allows to remove only players data
*/
USER_WIPE,
/**
* Allows to access Web Library
*/
LIBRARY
}
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
public AdminGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
super(addon, world, user, topLabel, permissionPrefix);
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.gui-title"));
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(10, this.createButton(Button.COMPLETE_USER_CHALLENGES));
panelBuilder.item(19, this.createButton(Button.RESET_USER_CHALLENGES));
// Add All Player Data removal.
panelBuilder.item(28, this.createButton(Button.USER_WIPE));
// Add Challenges
panelBuilder.item(12, this.createButton(Button.ADD_CHALLENGE));
panelBuilder.item(13, this.createButton(Button.ADD_LEVEL));
// Edit Challenges
panelBuilder.item(21, this.createButton(Button.EDIT_CHALLENGE));
panelBuilder.item(22, this.createButton(Button.EDIT_LEVEL));
// Remove Challenges
panelBuilder.item(30, this.createButton(Button.DELETE_CHALLENGE));
panelBuilder.item(31, this.createButton(Button.DELETE_LEVEL));
// Import Challenges
panelBuilder.item(15, this.createButton(Button.DEFAULT_IMPORT_CHALLENGES));
panelBuilder.item(24, this.createButton(Button.LIBRARY));
// Not added as I do not think admins should use it. It still will be able via command.
// panelBuilder.item(33, this.createButton(Button.DEFAULT_EXPORT_CHALLENGES));
// Edit Addon Settings
panelBuilder.item(16, this.createButton(Button.EDIT_SETTINGS));
// Button that deletes everything from challenges addon
if (this.wipeAll)
{
panelBuilder.item(34, this.createButton(Button.COMPLETE_WIPE));
}
else
{
panelBuilder.item(34, this.createButton(Button.CHALLENGE_WIPE));
}
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method is used to create PanelItem for each button type.
* @param button Button which must be created.
* @return PanelItem with necessary functionality.
*/
private PanelItem createButton(Button button)
{
ItemStack icon;
String name;
String description;
boolean glow;
PanelItem.ClickHandler clickHandler;
String permissionSuffix;
switch (button)
{
case COMPLETE_USER_CHALLENGES:
permissionSuffix = COMPLETE;
name = this.user.getTranslation("challenges.gui.buttons.admin.complete");
description = this.user.getTranslation("challenges.gui.descriptions.admin.complete");
icon = new ItemStack(Material.WRITTEN_BOOK);
clickHandler = (panel, user, clickType, slot) -> {
new ListUsersGUI(this.addon,
this.world,
this.user,
ListUsersGUI.Mode.COMPLETE,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
case RESET_USER_CHALLENGES:
permissionSuffix = RESET;
name = this.user.getTranslation("challenges.gui.buttons.admin.reset");
description = this.user.getTranslation("challenges.gui.descriptions.admin.reset");
icon = new ItemStack(Material.WRITABLE_BOOK);
glow = this.resetAllMode;
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.resetAllMode = !this.resetAllMode;
this.build();
}
else
{
new ListUsersGUI(this.addon,
this.world,
this.user,
this.resetAllMode ? ListUsersGUI.Mode.RESET_ALL : ListUsersGUI.Mode.RESET,
this.topLabel,
this.permissionPrefix,
this).build();
}
return true;
};
break;
case ADD_CHALLENGE:
permissionSuffix = ADD;
name = this.user.getTranslation("challenges.gui.buttons.admin.create-challenge");
description = this.user.getTranslation("challenges.gui.descriptions.admin.create-challenge");
icon = new ItemStack(Material.BOOK);
clickHandler = (panel, user, clickType, slot) -> {
this.getNewUniqueID(challenge ->
{
if (challenge == null)
{
// Build Admin Gui if input is null.
this.build();
}
else
{
String uniqueId = Utils.getGameMode(this.world) + "_" + challenge;
ChallengeTypeGUI.open(user,
this.addon.getChallengesSettings().getLoreLineLength(),
(type, requirements) -> new EditChallengeGUI(this.addon,
this.world,
this.user,
this.addon.getChallengesManager().createChallenge(uniqueId, type, requirements),
this.topLabel,
this.permissionPrefix,
this).build());
}
},
input -> {
String uniqueId = Utils.getGameMode(this.world) + "_" + input;
return !this.addon.getChallengesManager().containsChallenge(uniqueId);
},
this.user.getTranslation("challenges.gui.questions.admin.unique-id")
);
return true;
};
glow = false;
break;
case ADD_LEVEL:
permissionSuffix = ADD;
name = this.user.getTranslation("challenges.gui.buttons.admin.create-level");
description = this.user.getTranslation("challenges.gui.descriptions.admin.create-level");
icon = new ItemStack(Material.BOOK);
clickHandler = (panel, user, clickType, slot) -> {
this.getNewUniqueID(level ->
{
if (level == null)
{
// Build Admin Gui if input is null.
this.build();
}
else
{
String newName = Utils.getGameMode(this.world) + "_" + level;
new EditLevelGUI(this.addon,
this.world,
this.user,
this.addon.getChallengesManager().createLevel(newName, this.world),
this.topLabel,
this.permissionPrefix,
this).build();
}
},
input -> {
String newName = Utils.getGameMode(this.world) + "_" + input;
return !this.addon.getChallengesManager().containsLevel(newName);
},
this.user.getTranslation("challenges.gui.questions.admin.unique-id")
);
return true;
};
glow = false;
break;
case EDIT_CHALLENGE:
permissionSuffix = EDIT;
name = this.user.getTranslation("challenges.gui.buttons.admin.edit-challenge");
description = this.user.getTranslation("challenges.gui.descriptions.admin.edit-challenge");
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user, clickType, slot) -> {
new ListChallengesGUI(this.addon,
this.world,
this.user,
ListChallengesGUI.Mode.EDIT,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
case EDIT_LEVEL:
{
permissionSuffix = EDIT;
name = this.user.getTranslation("challenges.gui.buttons.admin.edit-level");
description = this.user.getTranslation("challenges.gui.descriptions.admin.edit-level");
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user, clickType, slot) -> {
new ListLevelsGUI(this.addon,
this.world,
this.user,
ListLevelsGUI.Mode.EDIT,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
}
case DELETE_CHALLENGE:
{
permissionSuffix = DELETE;
name = this.user.getTranslation("challenges.gui.buttons.admin.delete-challenge");
description = this.user.getTranslation("challenges.gui.descriptions.admin.delete-challenge");
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
new ListChallengesGUI(this.addon,
this.world,
this.user,
ListChallengesGUI.Mode.DELETE,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
}
case DELETE_LEVEL:
{
permissionSuffix = DELETE;
name = this.user.getTranslation("challenges.gui.buttons.admin.delete-level");
description = this.user.getTranslation("challenges.gui.descriptions.admin.delete-level");
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
new ListLevelsGUI(this.addon,
this.world,
this.user,
ListLevelsGUI.Mode.DELETE,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
}
case DEFAULT_IMPORT_CHALLENGES:
{
permissionSuffix = DEFAULT;
name = this.user.getTranslation("challenges.gui.buttons.admin.default-import");
description = this.user.getTranslation("challenges.gui.descriptions.admin.default-import");
icon = new ItemStack(Material.HOPPER);
clickHandler = (panel, user, clickType, slot) -> {
// Run import command.
this.user.performCommand(this.topLabel + " " + CHALLENGES + " " + DEFAULT + " " + IMPORT);
return true;
};
glow = false;
break;
}
case DEFAULT_EXPORT_CHALLENGES:
{
permissionSuffix = DEFAULT;
name = this.user.getTranslation("challenges.gui.buttons.admin.default-export");
description = this.user.getTranslation("challenges.gui.descriptions.admin.default-export");
icon = new ItemStack(Material.HOPPER);
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.overwriteMode = !this.overwriteMode;
this.build();
}
else
{
// Run import command.
this.user.performCommand(this.topLabel + " " + CHALLENGES + " " + DEFAULT + " " + GENERATE +
(this.overwriteMode ? " overwrite" : ""));
}
return true;
};
glow = this.overwriteMode;
break;
}
case EDIT_SETTINGS:
{
permissionSuffix = SETTINGS;
name = this.user.getTranslation("challenges.gui.buttons.admin.settings");
description = this.user.getTranslation("challenges.gui.descriptions.admin.settings");
icon = new ItemStack(Material.CRAFTING_TABLE);
clickHandler = (panel, user, clickType, slot) -> {
new EditSettingsGUI(this.addon,
this.world,
this.user,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
};
glow = false;
break;
}
case COMPLETE_WIPE:
{
permissionSuffix = WIPE;
name = this.user.getTranslation("challenges.gui.buttons.admin.complete-wipe");
description = this.user.getTranslation("challenges.gui.descriptions.admin.complete-wipe");
icon = new ItemStack(Material.TNT);
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.wipeAll = false;
this.build();
}
else
{
new ConfirmationGUI(this.user, value -> {
if (value)
{
this.addon.getChallengesManager().wipeDatabase(false);
this.user.sendMessage("challenges.messages.admin.complete-wipe");
}
this.build();
});
}
return true;
};
glow = true;
break;
}
case CHALLENGE_WIPE:
{
permissionSuffix = WIPE;
name = this.user.getTranslation("challenges.gui.buttons.admin.challenge-wipe");
description = this.user.getTranslation("challenges.gui.descriptions.admin.challenge-wipe");
icon = new ItemStack(Material.TNT);
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.wipeAll = true;
this.build();
}
else
{
new ConfirmationGUI(this.user, value -> {
if (value)
{
this.addon.getChallengesManager().wipeDatabase(false);
this.user.sendMessage("challenges.messages.admin.challenge-wipe");
}
this.build();
});
}
return true;
};
glow = false;
break;
}
case USER_WIPE:
{
permissionSuffix = WIPE;
name = this.user.getTranslation("challenges.gui.buttons.admin.players-wipe");
description = this.user.getTranslation("challenges.gui.descriptions.admin.players-wipe");
icon = new ItemStack(Material.TNT);
clickHandler = (panel, user, clickType, slot) -> {
new ConfirmationGUI(this.user, value -> {
if (value)
{
this.addon.getChallengesManager().wipePlayers();
this.user.sendMessage("challenges.messages.admin.players-wipe");
}
this.build();
});
return true;
};
glow = false;
break;
}
case LIBRARY:
{
permissionSuffix = DOWNLOAD;
name = this.user.getTranslation("challenges.gui.buttons.admin.library");
description = this.user.getTranslation("challenges.gui.descriptions.admin.library");
if (WebManager.isEnabled())
{
icon = new ItemStack(Material.COBWEB);
}
else
{
description += "|" + this.user.getTranslation("challenges.gui.descriptions.admin.download-disabled");
icon = new ItemStack(Material.STRUCTURE_VOID);
}
clickHandler = (panel, user, clickType, slot) -> {
if (WebManager.isEnabled())
{
ListLibraryGUI.open(this);
}
return true;
};
glow = false;
break;
}
default:
// This should never happen.
return null;
}
// If user does not have permission to run command, then change icon and clickHandler.
final String actionPermission = this.permissionPrefix + ADMIN + "." + CHALLENGES + "." + permissionSuffix;
if (!this.user.hasPermission(actionPermission))
{
icon = new ItemStack(Material.BARRIER);
clickHandler = (panel, user, clickType, slot) -> {
this.user.sendMessage("general.errors.no-permission", "[permission]", actionPermission);
return true;
};
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())).
glow(glow).
clickHandler(clickHandler).
build();
}
// ---------------------------------------------------------------------
// Section: Conversation
// ---------------------------------------------------------------------
/**
* This method will close opened gui and writes inputText in chat. After players answers on
* inputText in chat, message will trigger consumer and gui will reopen.
* @param consumer Consumer that accepts player output text.
* @param question Message that will be displayed in chat when player triggers conversion.
*/
private void getNewUniqueID(Consumer<String> consumer,
Function<String, Boolean> stringValidation,
@NonNull String question)
{
final User user = this.user;
Conversation conversation =
new ConversationFactory(BentoBox.getInstance()).withFirstPrompt(
new ValidatingPrompt()
{
/**
* Gets the text to display to the user when
* this prompt is first presented.
*
* @param context Context information about the
* conversation.
* @return The text to display.
*/
@Override
public String getPromptText(ConversationContext context)
{
// Close input GUI.
user.closeInventory();
// There are no editable message. Just return question.
return question;
}
/**
* Override this method to check the validity of
* the player's input.
*
* @param context Context information about the
* conversation.
* @param input The player's raw console input.
* @return True or false depending on the
* validity of the input.
*/
@Override
protected boolean isInputValid(ConversationContext context, String input)
{
return stringValidation.apply(GuiUtils.sanitizeInput(input));
}
/**
* Optionally override this method to
* display an additional message if the
* user enters an invalid input.
*
* @param context Context information
* about the conversation.
* @param invalidInput The invalid input
* provided by the user.
* @return A message explaining how to
* correct the input.
*/
@Override
protected String getFailedValidationText(ConversationContext context,
String invalidInput)
{
return user.getTranslation("challenges.errors.unique-id", "[id]", GuiUtils.sanitizeInput(invalidInput));
}
/**
* Override this method to accept and processes
* the validated input from the user. Using the
* input, the next Prompt in the prompt graph
* should be returned.
*
* @param context Context information about the
* conversation.
* @param input The validated input text from
* the user.
* @return The next Prompt in the prompt graph.
*/
@Override
protected Prompt acceptValidatedInput(ConversationContext context, String input)
{
// Add answer to consumer.
consumer.accept(GuiUtils.sanitizeInput(input));
// End conversation
return Prompt.END_OF_CONVERSATION;
}
}).
// On cancel conversation will be closed.
withEscapeSequence("cancel").
// Use null value in consumer to detect if user has abandoned conversation.
addConversationAbandonedListener(abandonedEvent ->
{
if (!abandonedEvent.gracefulExit())
{
consumer.accept(null);
}
}).
withLocalEcho(false).
withPrefix(context -> user.getTranslation("challenges.gui.questions.prefix")).
buildConversation(user.getPlayer());
conversation.begin();
}
}

View File

@ -0,0 +1,549 @@
package world.bentobox.challenges.panel.admin;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import org.bukkit.Material;
import org.bukkit.World;
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;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.panel.CommonPanel;
import world.bentobox.challenges.panel.ConversationUtils;
import world.bentobox.challenges.panel.util.ChallengeTypeSelector;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
import world.bentobox.challenges.web.WebManager;
/**
* This class contains Main
*/
public class AdminPanel extends CommonPanel
{
// ---------------------------------------------------------------------
// Section: Constructor
// ---------------------------------------------------------------------
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
private AdminPanel(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
super(addon, user, world, topLabel, permissionPrefix);
}
/**
* Open the Challenges Admin GUI.
*
* @param addon the addon
* @param world the world
* @param user the user
* @param topLabel the top label
* @param permissionPrefix the permission prefix
*/
public static void open(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
new AdminPanel(addon, world, user, topLabel, permissionPrefix).build();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* {@inheritDoc}
*/
@Override
protected void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation(Constants.TITLE + "admin-gui"));
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(10, this.createButton(Button.COMPLETE_USER_CHALLENGES));
panelBuilder.item(19, this.createButton(Button.RESET_USER_CHALLENGES));
// Add All Player Data removal.
panelBuilder.item(28, this.createButton(Button.USER_WIPE));
// Add Challenges
panelBuilder.item(12, this.createButton(Button.ADD_CHALLENGE));
panelBuilder.item(13, this.createButton(Button.ADD_LEVEL));
// Edit Challenges
panelBuilder.item(21, this.createButton(Button.EDIT_CHALLENGE));
panelBuilder.item(22, this.createButton(Button.EDIT_LEVEL));
// Remove Challenges
panelBuilder.item(30, this.createButton(Button.DELETE_CHALLENGE));
panelBuilder.item(31, this.createButton(Button.DELETE_LEVEL));
// Import Challenges
panelBuilder.item(15, this.createButton(Button.IMPORT_CHALLENGES));
panelBuilder.item(24, this.createButton(Button.LIBRARY));
// Not added as I do not think admins should use it. It still will be able via command.
// panelBuilder.item(33, this.createButton(Button.DEFAULT_EXPORT_CHALLENGES));
// Edit Addon Settings
panelBuilder.item(16, this.createButton(Button.EDIT_SETTINGS));
// Button that deletes everything from challenges addon
if (this.wipeAll)
{
panelBuilder.item(34, this.createButton(Button.COMPLETE_WIPE));
}
else
{
panelBuilder.item(34, this.createButton(Button.CHALLENGE_WIPE));
}
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method is used to create PanelItem for each button type.
* @param button Button which must be created.
* @return PanelItem with necessary functionality.
*/
private PanelItem createButton(Button button)
{
final String name = this.user.getTranslation(Constants.BUTTON + button.name().toLowerCase() + ".name");
List<String> description = new ArrayList<>(3);
description.add(this.user.getTranslation(Constants.BUTTON + button.name().toLowerCase() + ".description"));
ItemStack icon;
boolean glow;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case COMPLETE_USER_CHALLENGES -> {
icon = new ItemStack(Material.WRITTEN_BOOK);
clickHandler = (panel, user, clickType, slot) -> {
ListUsersPanel.open(this, ListUsersPanel.Mode.COMPLETE);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open"));
}
case RESET_USER_CHALLENGES -> {
icon = new ItemStack(Material.WRITABLE_BOOK);
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.resetAllMode = !this.resetAllMode;
this.build();
}
else
{
ListUsersPanel.open(this,
this.resetAllMode ? ListUsersPanel.Mode.RESET_ALL : ListUsersPanel.Mode.RESET);
}
return true;
};
glow = this.resetAllMode;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "left-click-to-open"));
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "right-click-to-reset-all"));
}
case ADD_CHALLENGE -> {
icon = new ItemStack(Material.BOOK);
clickHandler = (panel, user, clickType, slot) -> {
String gameModePrefix = Utils.getGameMode(this.world).toLowerCase() + "_";
// This consumer process new bundle creating with a name and id from given
// consumer value..
Consumer<String> challengeIdConsumer = value -> {
if (value != null)
{
ChallengeTypeSelector.open(this.user,
(type, requirements) -> EditChallengePanel.open(this,
this.addon.getChallengesManager().createChallenge(
gameModePrefix + Utils.sanitizeInput(value),
value,
type,
requirements)));
}
else
{
// Operation is canceled. Open this panel again.
this.build();
}
};
// This function checks if generator with a given ID already exist.
Function<String, Boolean> validationFunction = uniqueId ->
!this.addon.getChallengesManager().containsChallenge(gameModePrefix + Utils.sanitizeInput(uniqueId));
// Call a conversation API to get input string.
ConversationUtils.createIDStringInput(challengeIdConsumer,
validationFunction,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "write-name"),
this.user.getTranslation(Constants.CONVERSATIONS + "new-object-created",
Constants.WORLD, this.world.getName()),
Constants.CONVERSATIONS + "object-already-exists");
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-create"));
}
case ADD_LEVEL -> {
icon = new ItemStack(Material.BOOK);
clickHandler = (panel, user, clickType, slot) -> {
String gameModePrefix = Utils.getGameMode(this.world).toLowerCase() + "_";
// This consumer process new bundle creating with a name and id from given
// consumer value..
Consumer<String> levelIdConsumer = value -> {
if (value != null)
{
EditLevelPanel.open(this,
this.addon.getChallengesManager().createLevel(
gameModePrefix + Utils.sanitizeInput(value),
value,
world));
}
else
{
// Operation is canceled. Open this panel again.
this.build();
}
};
// This function checks if generator with a given ID already exist.
Function<String, Boolean> validationFunction = uniqueId ->
!this.addon.getChallengesManager().containsLevel(gameModePrefix + Utils.sanitizeInput(uniqueId));
// Call a conversation API to get input string.
ConversationUtils.createIDStringInput(levelIdConsumer,
validationFunction,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "write-name"),
this.user.getTranslation(Constants.CONVERSATIONS + "new-object-created",
Constants.GAMEMODE, Utils.getGameMode(this.world)),
Constants.CONVERSATIONS + "object-already-exists");
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-create"));
}
case EDIT_CHALLENGE -> {
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user, clickType, slot) -> {
ListChallengesPanel.open(this, ListChallengesPanel.Mode.EDIT);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open"));
}
case EDIT_LEVEL -> {
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user, clickType, slot) -> {
ListLevelsPanel.open(this, ListLevelsPanel.Mode.EDIT);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open"));
}
case DELETE_CHALLENGE -> {
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
ListChallengesPanel.open(this, ListChallengesPanel.Mode.DELETE);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open"));
}
case DELETE_LEVEL -> {
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
ListLevelsPanel.open(this, ListLevelsPanel.Mode.DELETE);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open"));
}
case EDIT_SETTINGS -> {
icon = new ItemStack(Material.CRAFTING_TABLE);
clickHandler = (panel, user, clickType, slot) -> {
EditSettingsPanel.open(this);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open"));
}
case IMPORT_CHALLENGES -> {
icon = new ItemStack(Material.HOPPER);
clickHandler = (panel, user, clickType, slot) -> {
// TODO: Importing GUI.
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open"));
}
case EXPORT_CHALLENGES -> {
icon = new ItemStack(Material.HOPPER);
clickHandler = (panel, user, clickType, slot) -> {
// TODO: Exporting GUI.
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-export"));
}
case LIBRARY -> {
if (WebManager.isEnabled())
{
icon = new ItemStack(Material.COBWEB);
}
else
{
icon = new ItemStack(Material.STRUCTURE_VOID);
}
clickHandler = (panel, user, clickType, slot) -> {
if (WebManager.isEnabled())
{
ListLibraryPanel.open(this);
}
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-open"));
}
case COMPLETE_WIPE -> {
icon = new ItemStack(Material.TNT);
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.wipeAll = false;
this.build();
}
else
{
Consumer<Boolean> consumer = value -> {
if (value)
{
this.addon.getChallengesManager().wipeDatabase(this.wipeAll);
}
this.build();
};
// Create conversation that gets user acceptance to delete generator data.
ConversationUtils.createConfirmation(
consumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "confirm-all-data-deletion",
Constants.GAMEMODE, Utils.getGameMode(this.world)),
this.user.getTranslation(Constants.CONVERSATIONS + "all-data-removed",
Constants.GAMEMODE, Utils.getGameMode(this.world)));
}
return true;
};
glow = true;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "left-click-to-wipe"));
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "right-click-to-switch"));
}
case CHALLENGE_WIPE -> {
icon = new ItemStack(Material.TNT);
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.wipeAll = true;
this.build();
}
else
{
Consumer<Boolean> consumer = value -> {
if (value)
{
this.addon.getChallengesManager().wipeDatabase(this.wipeAll);
}
this.build();
};
// Create conversation that gets user acceptance to delete generator data.
ConversationUtils.createConfirmation(
consumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "confirm-challenge-data-deletion",
Constants.GAMEMODE, Utils.getGameMode(this.world)),
this.user.getTranslation(Constants.CONVERSATIONS + "challenge-data-removed",
Constants.GAMEMODE, Utils.getGameMode(this.world)));
}
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "left-click-to-wipe"));
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "right-click-to-switch"));
}
case USER_WIPE -> {
icon = new ItemStack(Material.TNT);
clickHandler = (panel, user, clickType, slot) -> {
Consumer<Boolean> consumer = value -> {
if (value)
{
this.addon.getChallengesManager().wipePlayers();
}
this.build();
};
// Create conversation that gets user acceptance to delete generator data.
ConversationUtils.createConfirmation(
consumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "confirm-user-data-deletion",
Constants.GAMEMODE, Utils.getGameMode(this.world)),
this.user.getTranslation(Constants.CONVERSATIONS + "user-data-removed",
Constants.GAMEMODE, Utils.getGameMode(this.world)));
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslationOrNothing(Constants.TIPS + "click-to-wipe"));
}
default -> {
icon = new ItemStack(Material.PAPER);
clickHandler = null;
glow = false;
}
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(description).
glow(glow).
clickHandler(clickHandler).
build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum contains all button variations. Just for cleaner code.
*/
private enum Button
{
COMPLETE_USER_CHALLENGES,
RESET_USER_CHALLENGES,
ADD_CHALLENGE,
ADD_LEVEL,
EDIT_CHALLENGE,
EDIT_LEVEL,
DELETE_CHALLENGE,
DELETE_LEVEL,
EDIT_SETTINGS,
IMPORT_CHALLENGES,
EXPORT_CHALLENGES,
/**
* Allows to remove whole database
*/
COMPLETE_WIPE,
/**
* Allows to remove only challenges and levels
*/
CHALLENGE_WIPE,
/**
* Allows to remove only players data
*/
USER_WIPE,
/**
* Allows to access Web Library
*/
LIBRARY
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This indicate if Reset Challenges must work as reset all.
*/
private boolean resetAllMode;
/**
* This indicate if wipe button should clear all data, or only challenges.
*/
private boolean wipeAll;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,764 +0,0 @@
package world.bentobox.challenges.panel.admin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.World;
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;
import world.bentobox.bentobox.api.user.User;
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.panel.CommonGUI;
import world.bentobox.challenges.panel.util.ItemSwitchGUI;
import world.bentobox.challenges.panel.util.NumberGUI;
import world.bentobox.challenges.panel.util.SelectBlocksGUI;
import world.bentobox.challenges.panel.util.SelectChallengeGUI;
import world.bentobox.challenges.panel.util.StringListGUI;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
/**
* This class contains all necessary elements to create Levels Edit GUI.
*/
public class EditLevelGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param challengeLevel ChallengeLevel that must be edited.
*/
public EditLevelGUI(ChallengesAddon addon,
World world,
User user,
ChallengeLevel challengeLevel,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, challengeLevel, topLabel, permissionPrefix, null);
}
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param challengeLevel ChallengeLevel that must be edited.
*/
public EditLevelGUI(ChallengesAddon addon,
World world,
User user,
ChallengeLevel challengeLevel,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.challengeLevel = challengeLevel;
this.currentMenuType = MenuType.PROPERTIES;
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.edit-level-title"));
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(2, this.createMenuButton(MenuType.PROPERTIES));
panelBuilder.item(4, this.createMenuButton(MenuType.REWARDS));
panelBuilder.item(6, this.createMenuButton(MenuType.CHALLENGES));
if (this.currentMenuType.equals(MenuType.PROPERTIES))
{
this.buildMainPropertiesPanel(panelBuilder);
}
else if (this.currentMenuType.equals(MenuType.CHALLENGES))
{
this.buildChallengesPanel(panelBuilder);
}
else if (this.currentMenuType.equals(MenuType.REWARDS))
{
this.buildRewardsPanel(panelBuilder);
}
panelBuilder.item(44, this.returnButton);
// Save challenge level every time this gui is build.
// It will ensure that changes are stored in database.
this.addon.getChallengesManager().saveLevel(this.challengeLevel);
panelBuilder.build();
}
/**
* This class populate LevelsEditGUI with main level settings.
* @param panelBuilder PanelBuilder where icons must be added.
*/
private void buildMainPropertiesPanel(PanelBuilder panelBuilder)
{
panelBuilder.item(10, this.createButton(Button.NAME));
panelBuilder.item(19, this.createButton(Button.ICON));
panelBuilder.item(28, this.createButton(Button.CLOSED_ICON));
panelBuilder.item(22, this.createButton(Button.UNLOCK_MESSAGE));
panelBuilder.item(25, this.createButton(Button.ORDER));
panelBuilder.item(31, this.createButton(Button.WAIVER_AMOUNT));
}
/**
* This class populate LevelsEditGUI with level rewards.
* @param panelBuilder PanelBuilder where icons must be added.
*/
private void buildRewardsPanel(PanelBuilder panelBuilder)
{
panelBuilder.item(12, this.createButton(Button.REWARD_DESCRIPTION));
panelBuilder.item(21, this.createButton(Button.REWARD_COMMANDS));
panelBuilder.item(13, this.createButton(Button.REWARD_ITEM));
panelBuilder.item(22, this.createButton(Button.REWARD_EXPERIENCE));
panelBuilder.item(31, this.createButton(Button.REWARD_MONEY));
}
/**
* This class populate LevelsEditGUI with level challenges.
* @param panelBuilder PanelBuilder where icons must be added.
*/
private void buildChallengesPanel(PanelBuilder panelBuilder)
{
List<Challenge> challengeList = this.addon.getChallengesManager().getLevelChallenges(this.challengeLevel);
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = challengeList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (challengeList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int challengeIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (challengeIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
challengeIndex < challengeList.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createChallengeIcon(challengeList.get(challengeIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (challengeList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
panelBuilder.item(39, this.createButton(Button.ADD_CHALLENGE));
panelBuilder.item(41, this.createButton(Button.REMOVE_CHALLENGE));
}
// ---------------------------------------------------------------------
// Section: Other methods
// ---------------------------------------------------------------------
/**
* This method creates top menu buttons, that allows to switch "tabs".
* @param menuType Menu Type which button must be constructed.
* @return PanelItem that represents given menu type.
*/
private PanelItem createMenuButton(MenuType menuType)
{
ItemStack icon;
String name;
String description;
boolean glow;
PanelItem.ClickHandler clickHandler;
switch (menuType)
{
case PROPERTIES:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.properties");
description = this.user.getTranslation("challenges.gui.descriptions.admin.properties");
icon = new ItemStack(Material.CRAFTING_TABLE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentMenuType = MenuType.PROPERTIES;
this.build();
return true;
};
glow = this.currentMenuType.equals(MenuType.PROPERTIES);
break;
}
case CHALLENGES:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.challenges");
description = this.user.getTranslation("challenges.gui.descriptions.admin.challenges");
icon = new ItemStack(Material.RAIL);
clickHandler = (panel, user, clickType, slot) -> {
this.currentMenuType = MenuType.CHALLENGES;
this.build();
return true;
};
glow = this.currentMenuType.equals(MenuType.CHALLENGES);
break;
}
case REWARDS:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.rewards");
description = this.user.getTranslation("challenges.gui.descriptions.admin.rewards");
icon = new ItemStack(Material.DROPPER);
clickHandler = (panel, user, clickType, slot) -> {
this.currentMenuType = MenuType.REWARDS;
this.build();
return true;
};
glow = this.currentMenuType.equals(MenuType.REWARDS);
break;
}
default:
return null;
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())).
glow(glow).
clickHandler(clickHandler).
build();
}
/**
* This method creates given challenge icon. On click it should open Edit Challenge GUI.
* @param challenge Challenge which icon must be created.
* @return PanelItem that represents given challenge.
*/
private PanelItem createChallengeIcon(Challenge challenge)
{
return new PanelItemBuilder().
name(ChatColor.translateAlternateColorCodes('&', challenge.getFriendlyName())).
description(GuiUtils.stringSplit(
challenge.getDescription(),
this.addon.getChallengesSettings().getLoreLineLength())).
icon(challenge.getIcon()).
clickHandler((panel, user1, clickType, slot) -> {
// Open challenges edit screen.
new EditChallengeGUI(this.addon,
this.world,
this.user,
challenge,
this.topLabel,
this.permissionPrefix,
this).build();
return true;
}).
glow(!challenge.isDeployed()).
build();
}
/**
* This method creates buttons for default main menu.
* @param button Button which panel item must be created.
* @return PanelItem that represents given button.
*/
private PanelItem createButton(Button button)
{
ItemStack icon;
String name;
List<String> description;
boolean glow;
PanelItem.ClickHandler clickHandler;
final int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
switch (button)
{
case NAME:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.name");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.name-level"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", this.challengeLevel.getFriendlyName()));
icon = new ItemStack(Material.DROPPER);
clickHandler = (panel, user, clickType, slot) -> {
this.getFriendlyName(reply ->
{
if (reply != null)
{
this.challengeLevel.setFriendlyName(reply);
}
this.build();
},
this.user.getTranslation("challenges.gui.questions.admin.level-name"),
this.challengeLevel.getFriendlyName()
);
return true;
};
glow = false;
break;
}
case ICON:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.icon");
description = Collections.singletonList(this.user.getTranslation(
"challenges.gui.descriptions.admin.icon-level"));
icon = this.challengeLevel.getIcon();
clickHandler = (panel, user, clickType, slot) -> {
new SelectBlocksGUI(this.user, true, (status, materials) -> {
if (status)
{
materials.forEach(material ->
this.challengeLevel.setIcon(new ItemStack(material)));
}
this.build();
});
return true;
};
glow = false;
break;
}
case CLOSED_ICON:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.locked-icon");
description = Collections.singletonList(this.user.getTranslation(
"challenges.gui.descriptions.admin.locked-icon"));
boolean isNull = this.challengeLevel.getLockedIcon() == null;
if (isNull)
{
icon = new ItemStack(Material.BARRIER);
}
else
{
icon = this.challengeLevel.getLockedIcon().clone();
}
clickHandler = (panel, user, clickType, slot) -> {
new SelectBlocksGUI(this.user, true, (status, materials) -> {
if (status)
{
materials.forEach(material ->
this.challengeLevel.setLockedIcon(new ItemStack(material)));
}
this.build();
});
return true;
};
glow = false;
break;
}
case UNLOCK_MESSAGE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.description");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.description"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", "|" + this.challengeLevel.getUnlockMessage()));
icon = new ItemStack(Material.WRITABLE_BOOK);
clickHandler = (panel, user, clickType, slot) -> {
new StringListGUI(this.user, this.challengeLevel.getUnlockMessage(), lineLength, (status, value) -> {
if (status)
{
String singleLineMessage = value.stream().
map(s -> s + "|").
collect(Collectors.joining());
if (singleLineMessage.endsWith("|"))
{
singleLineMessage = singleLineMessage.substring(0, singleLineMessage.length() - 1);
}
this.challengeLevel.setUnlockMessage(singleLineMessage);
}
this.build();
});
return true;
};
glow = false;
break;
}
case ORDER:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.order");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.order"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.challengeLevel.getOrder())));
icon = new ItemStack(Material.DROPPER);
clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getOrder(), -1, 54, lineLength, (status, value) -> {
if (status)
{
this.challengeLevel.setOrder(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case WAIVER_AMOUNT:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.waiver-amount");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.waiver-amount"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.challengeLevel.getWaiverAmount())));
icon = new ItemStack(Material.REDSTONE_TORCH);
clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getWaiverAmount(), 0, lineLength, (status, value) -> {
if (status)
{
this.challengeLevel.setWaiverAmount(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case REWARD_DESCRIPTION:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-text");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-text-level"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", "|" + this.challengeLevel.getRewardText()));
icon = new ItemStack(Material.WRITTEN_BOOK);
clickHandler = (panel, user, clickType, slot) -> {
new StringListGUI(this.user, this.challengeLevel.getRewardText(), lineLength, (status, value) -> {
if (status)
{
String singleLineMessage = value.stream().
map(s -> s + "|").
collect(Collectors.joining());
if (singleLineMessage.endsWith("|"))
{
singleLineMessage = singleLineMessage.substring(0, singleLineMessage.length() - 1);
}
this.challengeLevel.setRewardText(singleLineMessage);
}
this.build();
});
return true;
};
glow = false;
break;
}
case REWARD_ITEM:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-items");
description = new ArrayList<>(this.challengeLevel.getRewardItems().size() + 1);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-items"));
Utils.groupEqualItems(this.challengeLevel.getRewardItems()).forEach(itemStack ->
description.addAll(this.generateItemStackDescription(itemStack)));
icon = new ItemStack(Material.CHEST);
clickHandler = (panel, user, clickType, slot) -> {
new ItemSwitchGUI(this.user, this.challengeLevel.getRewardItems(), lineLength, (status, value) -> {
if (status)
{
this.challengeLevel.setRewardItems(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case REWARD_EXPERIENCE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-experience");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-experience"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.challengeLevel.getRewardExperience())));
icon = new ItemStack(Material.EXPERIENCE_BOTTLE);
clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getRewardExperience(), 0, lineLength, (status, value) -> {
if (status)
{
this.challengeLevel.setRewardExperience(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case REWARD_MONEY:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-money");
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-money"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.challengeLevel.getRewardMoney())));
icon = new ItemStack(this.addon.isEconomyProvided() ? Material.GOLD_INGOT : Material.BARRIER);
clickHandler = (panel, user, clickType, slot) -> {
new NumberGUI(this.user, this.challengeLevel.getRewardMoney(), 0, lineLength, (status, value) -> {
if (status)
{
this.challengeLevel.setRewardMoney(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case REWARD_COMMANDS:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reward-commands");
description = new ArrayList<>(this.challengeLevel.getRewardCommands().size() + 1);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reward-commands"));
for (String command : this.challengeLevel.getRewardCommands())
{
description.add(this.user.getTranslation("challenges.gui.descriptions.command",
"[command]", command));
}
icon = new ItemStack(Material.COMMAND_BLOCK);
clickHandler = (panel, user, clickType, slot) -> {
new StringListGUI(this.user, this.challengeLevel.getRewardCommands(), lineLength, (status, value) -> {
if (status)
{
this.challengeLevel.setRewardCommands(value);
}
this.build();
});
return true;
};
glow = false;
break;
}
case ADD_CHALLENGE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.add-challenge");
description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.add-challenge"));
icon = new ItemStack(Material.WATER_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
ChallengesManager manager = this.addon.getChallengesManager();
// Get all challenge that is not in current level.
List<Challenge> challengeList = manager.getAllChallenges(this.world);
challengeList.removeAll(manager.getLevelChallenges(this.challengeLevel));
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().
collect(Collectors.toMap(challenge -> challenge,
challenge -> this.generateChallengeDescription(challenge, this.user.getPlayer()),
(a, b) -> b,
() -> new LinkedHashMap<>(challengeList.size())));
// Open select gui
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge -> manager.addChallengeToLevel(challenge, this.challengeLevel));
}
this.build();
});
return true;
};
glow = false;
break;
}
case REMOVE_CHALLENGE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.remove-challenge");
description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.remove-challenge"));
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
ChallengesManager manager = this.addon.getChallengesManager();
// Get all challenge that is in current level.
List<Challenge> challengeList = manager.getLevelChallenges(this.challengeLevel);
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().
collect(Collectors.toMap(challenge -> challenge,
challenge -> this.generateChallengeDescription(challenge, this.user.getPlayer()),
(a, b) -> b,
() -> new LinkedHashMap<>(challengeList.size())));
// Open select gui
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge -> manager.removeChallengeFromLevel(challenge, this.challengeLevel));
}
this.build();
});
return true;
};
glow = false;
break;
}
default:
return null;
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(GuiUtils.stringSplit(description, lineLength)).
glow(glow).
clickHandler(clickHandler).
build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Represents different buttons that could be in menus.
*/
private enum Button
{
NAME,
ICON,
CLOSED_ICON,
UNLOCK_MESSAGE,
ORDER,
WAIVER_AMOUNT,
REWARD_DESCRIPTION,
REWARD_ITEM,
REWARD_EXPERIENCE,
REWARD_MONEY,
REWARD_COMMANDS,
ADD_CHALLENGE,
REMOVE_CHALLENGE
}
/**
* Represents different types of menus
*/
private enum MenuType
{
PROPERTIES,
CHALLENGES,
REWARDS
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable holds current challenge level that is in editing GUI.
*/
private ChallengeLevel challengeLevel;
/**
* Variable holds current active menu.
*/
private MenuType currentMenuType;
}

View File

@ -0,0 +1,876 @@
package world.bentobox.challenges.panel.admin;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.ItemStack;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelListener;
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.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.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.utils.Constants;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
/**
* This class contains all necessary elements to create Levels Edit GUI.
*/
public class EditLevelPanel extends CommonPagedPanel
{
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param challengeLevel ChallengeLevel that must be edited.
*/
private EditLevelPanel(ChallengesAddon addon,
User user,
World world,
String topLabel,
String permissionPrefix,
ChallengeLevel challengeLevel)
{
super(addon, user, world, topLabel, permissionPrefix);
this.challengeLevel = challengeLevel;
this.currentMenuType = MenuType.PROPERTIES;
}
/**
* @param challengeLevel ChallengeLevel that must be edited.
*/
private EditLevelPanel(CommonPanel parentGUI, ChallengeLevel challengeLevel)
{
super(parentGUI);
this.challengeLevel = challengeLevel;
this.currentMenuType = MenuType.PROPERTIES;
}
/**
* Open the Challenges Level Edit GUI.
*
* @param addon the addon
* @param world the world
* @param user the user
* @param topLabel the top label
* @param permissionPrefix the permission prefix
* @param level - level that needs editing
*/
public static void open(ChallengesAddon addon,
User user,
World world,
String topLabel,
String permissionPrefix,
ChallengeLevel level)
{
new EditLevelPanel(addon, user, world, topLabel, permissionPrefix, level).build();
}
/**
* Open the Challenges Level Edit GUI.
*
* @param panel - Parent Panel
* @param level - level that needs editing
*/
public static void open(CommonPanel panel, ChallengeLevel level)
{
new EditLevelPanel(panel, level).build();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* 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 + "edit-level",
"[level]", this.challengeLevel.getFriendlyName()));
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(2, this.createMenuButton(MenuType.PROPERTIES));
panelBuilder.item(4, this.createMenuButton(MenuType.REWARDS));
panelBuilder.item(6, this.createMenuButton(MenuType.CHALLENGES));
if (this.currentMenuType.equals(MenuType.PROPERTIES))
{
this.buildMainPropertiesPanel(panelBuilder);
}
else if (this.currentMenuType.equals(MenuType.CHALLENGES))
{
this.buildChallengesPanel(panelBuilder);
}
else if (this.currentMenuType.equals(MenuType.REWARDS))
{
this.buildRewardsPanel(panelBuilder);
}
panelBuilder.item(44, this.returnButton);
// Save challenge level every time this gui is build.
// It will ensure that changes are stored in database.
this.addon.getChallengesManager().saveLevel(this.challengeLevel);
panelBuilder.build();
}
/**
* This class populate LevelsEditGUI with main level settings.
* @param panelBuilder PanelBuilder where icons must be added.
*/
private void buildMainPropertiesPanel(PanelBuilder panelBuilder)
{
panelBuilder.listener(new IconChanger());
panelBuilder.item(10, this.createButton(Button.NAME));
panelBuilder.item(19, this.createButton(Button.ICON));
panelBuilder.item(28, this.createButton(Button.LOCKED_ICON));
panelBuilder.item(22, this.createButton(Button.DESCRIPTION));
panelBuilder.item(25, this.createButton(Button.ORDER));
panelBuilder.item(31, this.createButton(Button.WAIVER_AMOUNT));
}
/**
* This class populate LevelsEditGUI with level rewards.
* @param panelBuilder PanelBuilder where icons must be added.
*/
private void buildRewardsPanel(PanelBuilder panelBuilder)
{
panelBuilder.item(12, this.createButton(Button.REWARD_TEXT));
panelBuilder.item(21, this.createButton(Button.REWARD_COMMANDS));
panelBuilder.item(13, this.createButton(Button.REWARD_ITEMS));
panelBuilder.item(22, this.createButton(Button.REWARD_EXPERIENCE));
panelBuilder.item(31, this.createButton(Button.REWARD_MONEY));
}
/**
* This class populate LevelsEditGUI with level challenges.
* @param panelBuilder PanelBuilder where icons must be added.
*/
private void buildChallengesPanel(PanelBuilder panelBuilder)
{
List<Challenge> challengeList = this.addon.getChallengesManager().getLevelChallenges(this.challengeLevel);
this.populateElements(panelBuilder,
challengeList,
o -> this.createChallengeIcon((Challenge) o));
panelBuilder.item(39, this.createButton(Button.ADD_CHALLENGES));
panelBuilder.item(41, this.createButton(Button.REMOVE_CHALLENGES));
}
// ---------------------------------------------------------------------
// Section: Other methods
// ---------------------------------------------------------------------
/**
* This method creates top menu buttons, that allows to switch "tabs".
* @param menuType Menu Type which button must be constructed.
* @return PanelItem that represents given menu type.
*/
private PanelItem createMenuButton(MenuType menuType)
{
final String reference = Constants.BUTTON + menuType.name().toLowerCase() + ".";
final String name = this.user.getTranslation(reference + "name");
final List<String> description = new ArrayList<>(3);
description.add(this.user.getTranslation(reference + "description"));
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-select"));
ItemStack icon;
boolean glow;
PanelItem.ClickHandler clickHandler;
switch (menuType)
{
case PROPERTIES -> {
icon = new ItemStack(Material.CRAFTING_TABLE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentMenuType = MenuType.PROPERTIES;
this.build();
return true;
};
glow = this.currentMenuType.equals(MenuType.PROPERTIES);
}
case CHALLENGES -> {
icon = new ItemStack(Material.RAIL);
clickHandler = (panel, user, clickType, slot) -> {
this.currentMenuType = MenuType.CHALLENGES;
this.build();
return true;
};
glow = this.currentMenuType.equals(MenuType.CHALLENGES);
}
case REWARDS -> {
icon = new ItemStack(Material.DROPPER);
clickHandler = (panel, user, clickType, slot) -> {
this.currentMenuType = MenuType.REWARDS;
this.build();
return true;
};
glow = this.currentMenuType.equals(MenuType.REWARDS);
}
default -> {
icon = new ItemStack(Material.PAPER);
clickHandler = null;
glow = false;
}
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(description).
glow(glow).
clickHandler(clickHandler).
build();
}
/**
* This method creates given challenge icon. On click it should open Edit Challenge GUI.
* @param challenge Challenge which icon must be created.
* @return PanelItem that represents given challenge.
*/
private PanelItem createChallengeIcon(Challenge challenge)
{
return new PanelItemBuilder().
name(Util.translateColorCodes(challenge.getFriendlyName())).
description(this.generateChallengeDescription(challenge, null)).
description("").
description(this.user.getTranslation(Constants.TIPS + "click-to-edit")).
icon(challenge.getIcon()).
clickHandler((panel, user, clickType, slot) -> {
// Open challenges edit screen.
EditChallengePanel.open(this, challenge);
return true;
}).
glow(!challenge.isDeployed()).
build();
}
/**
* This method creates buttons for default main menu.
* @param button Button which panel item must be created.
* @return PanelItem that represents given button.
*/
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;
boolean glow;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case REWARD_TEXT -> {
icon = new ItemStack(Material.WRITTEN_BOOK);
description.add(this.user.getTranslation(reference + "value"));
description.add(this.challengeLevel.getRewardText());
clickHandler = (panel, user, clickType, i) ->
{
// Create consumer that process description change
Consumer<List<String>> consumer = value ->
{
if (value != null)
{
this.challengeLevel.setRewardText(String.join("\n", value));
}
this.build();
};
if (!this.challengeLevel.getRewardText().isEmpty() && clickType.isShiftClick())
{
// Reset to the empty value
consumer.accept(Collections.emptyList());
}
else
{
// start conversation
ConversationUtils.createStringListInput(consumer,
user,
user.getTranslation(Constants.CONVERSATIONS + "write-reward-text"),
user.getTranslation(Constants.CONVERSATIONS + "reward-text-changed"));
}
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
if (!this.challengeLevel.getRewardText().isEmpty())
{
description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset"));
}
}
case REWARD_ITEMS -> {
if (this.challengeLevel.getRewardItems().isEmpty())
{
description.add(this.user.getTranslation(reference + "none"));
}
else
{
description.add(this.user.getTranslation(reference + "title"));
Utils.groupEqualItems(this.challengeLevel.getRewardItems()).stream().
sorted(Comparator.comparing(ItemStack::getType)).
forEach(itemStack ->
description.add(this.user.getTranslationOrNothing(reference + "list",
"[item]", Utils.prettifyObject(itemStack, this.user))));
}
icon = new ItemStack(Material.CHEST);
clickHandler = (panel, user, clickType, slot) -> {
ItemSelector.open(this.user,
this.challengeLevel.getRewardItems(),
(status, value) -> {
if (status)
{
this.challengeLevel.setRewardItems(value);
}
this.build();
});
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
case REWARD_EXPERIENCE -> {
description.add(this.user.getTranslation(reference + "value",
Constants.NUMBER, String.valueOf(this.challengeLevel.getRewardExperience())));
icon = new ItemStack(Material.EXPERIENCE_BOTTLE);
clickHandler = (panel, user, clickType, i) -> {
Consumer<Number> numberConsumer = number -> {
if (number != null)
{
this.challengeLevel.setRewardExperience(number.intValue());
}
// reopen panel
this.build();
};
ConversationUtils.createNumericInput(numberConsumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "input-number"),
0,
Integer.MAX_VALUE);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
case REWARD_MONEY -> {
description.add(this.user.getTranslation(reference + "value",
Constants.NUMBER, String.valueOf(this.challengeLevel.getRewardMoney())));
icon = new ItemStack(this.addon.isEconomyProvided() ? Material.GOLD_INGOT : Material.BARRIER);
clickHandler = (panel, user, clickType, i) -> {
Consumer<Number> numberConsumer = number -> {
if (number != null)
{
this.challengeLevel.setRewardMoney(number.doubleValue());
}
// reopen panel
this.build();
};
ConversationUtils.createNumericInput(numberConsumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "input-number"),
0,
Double.MAX_VALUE);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
case REWARD_COMMANDS -> {
icon = new ItemStack(Material.COMMAND_BLOCK);
description.add(this.user.getTranslation(reference + "value"));
description.addAll(this.challengeLevel.getRewardCommands());
clickHandler = (panel, user, clickType, i) ->
{
// Create consumer that process description change
Consumer<List<String>> consumer = value ->
{
if (value != null)
{
this.challengeLevel.setRewardCommands(value);
}
this.build();
};
if (!this.challengeLevel.getRewardCommands().isEmpty() && clickType.isShiftClick())
{
// Reset to the empty value
consumer.accept(Collections.emptyList());
}
else
{
// start conversation
ConversationUtils.createStringListInput(consumer,
user,
user.getTranslation(Constants.CONVERSATIONS + "write-reward-commands"),
user.getTranslation(Constants.CONVERSATIONS + "reward-commands-changed"));
}
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
if (!this.challengeLevel.getRewardCommands().isEmpty())
{
description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset"));
}
}
case NAME -> {
description.add(this.user.getTranslation(reference + "value",
"[name]", this.challengeLevel.getFriendlyName()));
icon = new ItemStack(Material.NAME_TAG);
clickHandler = (panel, user, clickType, i) ->
{
// Create consumer that process description change
Consumer<String> consumer = value ->
{
if (value != null)
{
this.challengeLevel.setFriendlyName(value);
}
this.build();
};
// start conversation
ConversationUtils.createStringInput(consumer,
user,
user.getTranslation(Constants.CONVERSATIONS + "write-name"),
user.getTranslation(Constants.CONVERSATIONS + "name-changed"));
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
case DESCRIPTION -> {
icon = new ItemStack(Material.WRITTEN_BOOK);
description.add(this.user.getTranslation(reference + "value"));
description.add(this.challengeLevel.getUnlockMessage());
clickHandler = (panel, user, clickType, i) ->
{
// Create consumer that process description change
Consumer<List<String>> consumer = value ->
{
if (value != null)
{
this.challengeLevel.setUnlockMessage(String.join("\n", value));
}
this.build();
};
if (!this.challengeLevel.getUnlockMessage().isEmpty() && clickType.isShiftClick())
{
// Reset to the empty value
consumer.accept(Collections.emptyList());
}
else
{
// start conversation
ConversationUtils.createStringListInput(consumer,
user,
user.getTranslation(Constants.CONVERSATIONS + "write-description"),
user.getTranslation(Constants.CONVERSATIONS + "description-changed"));
}
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
if (!this.challengeLevel.getUnlockMessage().isEmpty())
{
description.add(this.user.getTranslation(Constants.TIPS + "shift-click-to-reset"));
}
}
case ICON, LOCKED_ICON -> {
icon = button == Button.LOCKED_ICON ?
this.challengeLevel.getLockedIcon() :
this.challengeLevel.getIcon();
clickHandler = (panel, user, clickType, i) ->
{
this.selectedButton = button;
this.build();
return true;
};
if (this.selectedButton != button)
{
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
else
{
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-on-item"));
}
glow = this.selectedButton == button;
}
case ORDER -> {
description.add(this.user.getTranslation(reference + "value",
Constants.NUMBER, String.valueOf(this.challengeLevel.getOrder())));
icon = new ItemStack(Material.HOPPER, Math.max(1, this.challengeLevel.getOrder()));
clickHandler = (panel, user, clickType, i) -> {
Consumer<Number> numberConsumer = number -> {
if (number != null)
{
this.challengeLevel.setOrder(number.intValue());
}
// reopen panel
this.build();
};
ConversationUtils.createNumericInput(numberConsumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "input-number"),
0,
2000);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
case WAIVER_AMOUNT -> {
description.add(this.user.getTranslation(reference + "value",
Constants.NUMBER, String.valueOf(this.challengeLevel.getWaiverAmount())));
icon = new ItemStack(Material.HOPPER, Math.max(1, this.challengeLevel.getWaiverAmount()));
clickHandler = (panel, user, clickType, i) -> {
Consumer<Number> numberConsumer = number -> {
if (number != null)
{
this.challengeLevel.setWaiverAmount(number.intValue());
}
// reopen panel
this.build();
};
ConversationUtils.createNumericInput(numberConsumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "input-number"),
0,
2000);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
case ADD_CHALLENGES -> {
icon = new ItemStack(Material.WATER_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
ChallengesManager manager = this.addon.getChallengesManager();
// Get all challenge that is not in current level.
List<Challenge> challengeList = manager.getAllChallenges(this.world);
challengeList.removeAll(manager.getLevelChallenges(this.challengeLevel));
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().
collect(Collectors.toMap(challenge -> challenge,
challenge -> this.generateChallengeDescription(challenge, null),
(a, b) -> b,
() -> new LinkedHashMap<>(challengeList.size())));
// Open select gui
ChallengeSelector.open(this.user,
Material.BLUE_STAINED_GLASS_PANE,
challengeDescriptionMap,
(status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge ->
manager.addChallengeToLevel(challenge, this.challengeLevel));
}
this.build();
});
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-add"));
}
case REMOVE_CHALLENGES -> {
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user, clickType, slot) -> {
ChallengesManager manager = this.addon.getChallengesManager();
// Get all challenge that is in current level.
List<Challenge> challengeList = manager.getLevelChallenges(this.challengeLevel);
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().
collect(Collectors.toMap(challenge -> challenge,
challenge -> this.generateChallengeDescription(challenge, null),
(a, b) -> b,
() -> new LinkedHashMap<>(challengeList.size())));
// Open select gui
ChallengeSelector.open(this.user,
Material.RED_STAINED_GLASS_PANE,
challengeDescriptionMap,
(status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge ->
manager.removeChallengeFromLevel(challenge, this.challengeLevel));
}
this.build();
});
return true;
};
glow = false;
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).
glow(glow).
clickHandler(clickHandler).
build();
}
// ---------------------------------------------------------------------
// Section: Classes
// ---------------------------------------------------------------------
/**
* This class allows changing icon for Generator Tier
*/
private class IconChanger implements PanelListener
{
/**
* Process inventory click. If generator icon is selected and user clicks on item in his inventory, then change
* icon to the item from inventory.
*
* @param user the user
* @param event the event
*/
@Override
public void onInventoryClick(User user, InventoryClickEvent event)
{
// Handle icon changing
if (EditLevelPanel.this.selectedButton != null &&
event.getCurrentItem() != null &&
!event.getCurrentItem().getType().equals(Material.AIR) &&
event.getRawSlot() > 44)
{
// set material and amount only. Other data should be removed.
if (EditLevelPanel.this.selectedButton == Button.ICON)
{
EditLevelPanel.this.challengeLevel.setIcon(event.getCurrentItem().clone());
// Deselect icon
EditLevelPanel.this.selectedButton = null;
// Rebuild icon
EditLevelPanel.this.build();
}
else if (EditLevelPanel.this.selectedButton == Button.LOCKED_ICON)
{
EditLevelPanel.this.challengeLevel.setLockedIcon(event.getCurrentItem().clone());
// Deselect icon
EditLevelPanel.this.selectedButton = null;
// Rebuild icon
EditLevelPanel.this.build();
}
}
}
/**
* On inventory close.
*
* @param event the event
*/
@Override
public void onInventoryClose(InventoryCloseEvent event)
{
// Do nothing
}
/**
* Setup current listener.
*/
@Override
public void setup()
{
// Do nothing
}
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Represents different buttons that could be in menus.
*/
private enum Button
{
NAME,
ICON,
LOCKED_ICON,
DESCRIPTION,
ORDER,
WAIVER_AMOUNT,
REWARD_TEXT,
REWARD_ITEMS,
REWARD_EXPERIENCE,
REWARD_MONEY,
REWARD_COMMANDS,
ADD_CHALLENGES,
REMOVE_CHALLENGES
}
/**
* Represents different types of menus
*/
private enum MenuType
{
PROPERTIES,
CHALLENGES,
REWARDS
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable holds current challenge level that is in editing GUI.
*/
private final ChallengeLevel challengeLevel;
/**
* Variable holds current active menu.
*/
private MenuType currentMenuType;
private Button selectedButton;
}

View File

@ -1,638 +0,0 @@
package world.bentobox.challenges.panel.admin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.bukkit.Material;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelListener;
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.config.SettingsUtils.ChallengeLore;
import world.bentobox.challenges.config.SettingsUtils.LevelLore;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class allows to change Input ItemStacks to different ItemStacks.
*/
public class EditLoreGUI extends CommonGUI
{
public EditLoreGUI(CommonGUI parent, LoreType loreType)
{
super(parent);
this.lore = loreType;
this.activeValues = new ArrayList<>();
switch (this.lore)
{
case CHALLENGES:
for (ChallengeLore lore : this.addon.getChallengesSettings().getChallengeLoreMessage())
{
this.activeValues.add(lore.name());
}
break;
case LEVELS:
for (LevelLore lore : this.addon.getChallengesSettings().getLevelLoreMessage())
{
this.activeValues.add(lore.name());
}
break;
}
}
/**
* This is static call method for easier GUI opening.
* @param parent Parent GUI.
* @param loreType loreType that will be edited.
*/
public static void open(CommonGUI parent, LoreType loreType)
{
new EditLoreGUI(parent, loreType).build();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds panel that allows to change given number value.
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().
name(this.user.getTranslation("challenges.gui.title.admin.lore-edit")).
user(this.user).
listener(new CustomPanelListener());
GuiUtils.fillBorder(panelBuilder, 5, Material.MAGENTA_STAINED_GLASS_PANE);
// Define all active buttons
panelBuilder.item(1, this.getButton(Button.SAVE));
panelBuilder.item(3, this.getButton(Button.ADD));
panelBuilder.item(4, this.getButton(Button.REMOVE));
// TODO: Need 2 View Buttons
// One for closes / One for opened.
// panelBuilder.item(6, this.getButton(Button.VIEW));
panelBuilder.item(44, this.returnButton);
// necessary as I have a border around this GUI
int currentIndex = 10;
// Only 21 elements will be displayed. On porpoise!
for (int i = 0; i < this.activeValues.size() || i > 21; i++)
{
panelBuilder.item(currentIndex++, this.getLoreButton(this.activeValues.get(i)));
// Border element
if (currentIndex % 9 == 8)
{
currentIndex += 2;
}
// Just in case. Should never occur.
if (currentIndex % 9 == 0)
{
currentIndex++;
}
}
panelBuilder.build();
}
/**
* This method create button that does some functionality in current gui.
* @param button Button functionality.
* @return PanelItem.
*/
private PanelItem getButton(Button button)
{
ItemStack icon;
String name;
List<String> description;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case SAVE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.save");
description = Collections.emptyList();
icon = new ItemStack(Material.COMMAND_BLOCK);
clickHandler = (panel, user, clickType, slot) -> {
switch (this.lore)
{
case CHALLENGES:
{
List<ChallengeLore> lore = this.activeValues.stream().
map(ChallengeLore::valueOf).
collect(Collectors.toCollection(() -> new ArrayList<>(this.activeValues.size())));
this.addon.getChallengesSettings().setChallengeLoreMessage(lore);
break;
}
case LEVELS:
{
List<LevelLore> lore = this.activeValues.stream().
map(LevelLore::valueOf).
collect(Collectors.toCollection(() -> new ArrayList<>(this.activeValues.size())));
this.addon.getChallengesSettings().setLevelLoreMessage(lore);
break;
}
}
// Save and return to parent gui.
this.parentGUI.build();
return true;
};
break;
}
case ADD:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.add");
description = Collections.emptyList();
icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
new AddLoreElementGUI(element -> {
this.activeValues.add(element);
this.build();
});
return true;
};
break;
}
case REMOVE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.remove-selected");
description = Collections.emptyList();
icon = new ItemStack(Material.RED_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
new RemoveLoreElementGUI((element, index) -> {
if (this.activeValues.get(index).equals(element))
{
this.activeValues.remove(element);
}
this.build();
});
return true;
};
break;
}
case VIEW:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.view");
description = Collections.emptyList();
icon = new ItemStack(Material.YELLOW_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
return true;
};
break;
}
default:
return null;
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())).
glow(false).
clickHandler(clickHandler).
build();
}
/**
* This method creates button for lore element.
* @param loreElement String that represents current lore element.
* @return PanelItem.
*/
@Nullable
private PanelItem getLoreButton(String loreElement)
{
switch (this.lore)
{
case CHALLENGES:
return this.getChallengeLoreButton(loreElement);
case LEVELS:
return this.getLevelLoreButton(loreElement);
default:
// this should never happen!
return null;
}
}
/**
* This method creates button for challenge lore element.
* @param loreElement String that represents current challenge lore element.
* @return PanelItem.
*/
private PanelItem getChallengeLoreButton(String loreElement)
{
Material icon;
String name = loreElement;
List<String> description = new ArrayList<>();
description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "lore." + loreElement.toLowerCase()));
PanelItem.ClickHandler clickHandler = (panel, user1, clickType, slot) -> true;
switch (ChallengeLore.valueOf(loreElement))
{
case LEVEL:
{
icon = Material.DIRT;
break;
}
case STATUS:
{
icon = Material.LEVER;
break;
}
case COUNT:
{
icon = Material.REPEATER;
break;
}
case DESCRIPTION:
{
icon = Material.WRITTEN_BOOK;
break;
}
case WARNINGS:
{
icon = Material.LAVA_BUCKET;
break;
}
case ENVIRONMENT:
{
icon = Material.GLASS;
break;
}
case REQUIREMENTS:
{
icon = Material.HOPPER;
break;
}
case REWARD_TEXT:
{
icon = Material.PAPER;
break;
}
case REWARD_OTHER:
{
icon = Material.CHEST;
break;
}
case REWARD_ITEMS:
{
icon = Material.TRAPPED_CHEST;
break;
}
case REWARD_COMMANDS:
{
icon = Material.COMMAND_BLOCK;
break;
}
default:
{
icon = Material.BARRIER;
break;
}
}
return new PanelItemBuilder().
name(name).
icon(icon).
description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())).
clickHandler(clickHandler).
glow(false).
build();
}
/**
* This method creates button for challenge level lore element.
* @param loreElement String that represents current challenge level lore element.
* @return PanelItem.
*/
private PanelItem getLevelLoreButton(String loreElement)
{
Material icon;
String name = loreElement;
List<String> description = new ArrayList<>();
description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "lore." + loreElement.toLowerCase()));
PanelItem.ClickHandler clickHandler = (panel, user1, clickType, slot) -> true;
switch (LevelLore.valueOf(loreElement))
{
case LEVEL_STATUS:
{
icon = Material.DIRT;
break;
}
case CHALLENGE_COUNT:
{
icon = Material.REPEATER;
break;
}
case UNLOCK_MESSAGE:
{
icon = Material.WRITTEN_BOOK;
break;
}
case WAIVER_AMOUNT:
{
icon = Material.COMPARATOR;
break;
}
case LEVEL_REWARD_TEXT:
{
icon = Material.PAPER;
break;
}
case LEVEL_REWARD_OTHER:
{
icon = Material.CHEST;
break;
}
case LEVEL_REWARD_ITEMS:
{
icon = Material.TRAPPED_CHEST;
break;
}
case LEVEL_REWARD_COMMANDS:
{
icon = Material.COMMAND_BLOCK;
break;
}
default:
{
icon = Material.BARRIER;
break;
}
}
return new PanelItemBuilder().
name(name).
icon(icon).
description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())).
clickHandler(clickHandler).
glow(false).
build();
}
// ---------------------------------------------------------------------
// Section: Select GUI
// ---------------------------------------------------------------------
/**
* This class opens new GUI that add an element from all available lore values.
*/
private class AddLoreElementGUI
{
private AddLoreElementGUI(Consumer<String> selectedElement)
{
PanelBuilder panelBuilder = new PanelBuilder().
name(EditLoreGUI.this.user.getTranslation("challenges.gui.title.admin.lore-add")).
user(EditLoreGUI.this.user);
GuiUtils.fillBorder(panelBuilder, 5, Material.MAGENTA_STAINED_GLASS_PANE);
int currentIndex = 10;
List<String> values = new ArrayList<>();
// Populate list with all elements.
switch (EditLoreGUI.this.lore)
{
case CHALLENGES:
for (ChallengeLore value : ChallengeLore.values())
{
values.add(value.name());
}
break;
case LEVELS:
for (LevelLore value : LevelLore.values())
{
values.add(value.name());
}
break;
}
for (String value : values)
{
PanelItem item = EditLoreGUI.this.getLoreButton(value);
if (item != null) {
item.setClickHandler((panel, user1, clickType, slot) -> {
selectedElement.accept(value);
return true;
});
panelBuilder.item(currentIndex++, item);
// Border element
if (currentIndex % 9 == 8)
{
currentIndex += 2;
}
// Just in case. Should never occur.
if (currentIndex % 9 == 0)
{
currentIndex++;
}
// Just in case. Should never occur.
if (currentIndex > 35)
{
break;
}
}
}
panelBuilder.build();
}
}
/**
* This class opens new GUI that remove an element from all available lore values.
*/
private class RemoveLoreElementGUI
{
private RemoveLoreElementGUI(BiConsumer<String, Integer> selectedElement)
{
PanelBuilder panelBuilder = new PanelBuilder().
name(EditLoreGUI.this.user.getTranslation("challenges.gui.title.admin.lore-remove")).
user(EditLoreGUI.this.user);
GuiUtils.fillBorder(panelBuilder, 5, Material.MAGENTA_STAINED_GLASS_PANE);
int currentIndex = 10;
List<String> values = EditLoreGUI.this.activeValues;
for (int i = 0; i < values.size(); i++)
{
final int counter = i;
String value = values.get(counter);
PanelItem item = EditLoreGUI.this.getLoreButton(value);
if (item != null) {
item.setClickHandler((panel, user1, clickType, slot) -> {
selectedElement.accept(value, counter);
return true;
});
panelBuilder.item(currentIndex++, item);
// Border element
if (currentIndex % 9 == 8)
{
currentIndex += 2;
}
// Just in case. Should never occur.
if (currentIndex % 9 == 0)
{
currentIndex++;
}
// Just in case. Should never occur.
if (currentIndex > 35)
{
break;
}
}
}
panelBuilder.build();
}
}
// ---------------------------------------------------------------------
// Section: Private classes
// ---------------------------------------------------------------------
/**
* This CustomPanelListener allows to move items in current panel.
*/
private class CustomPanelListener implements PanelListener
{
@Override
public void setup()
{
}
@Override
public void onInventoryClose(InventoryCloseEvent inventoryCloseEvent)
{
}
@Override
public void onInventoryClick(User user, InventoryClickEvent event)
{
// First row of elements should be ignored, as it contains buttons and blocked slots.
event.setCancelled(event.getRawSlot() < 9 ||
event.getRawSlot() < 35 ||
event.getRawSlot() % 9 == 0 ||
event.getRawSlot() % 9 == 8);
}
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum holds all button values in current gui.
*/
private enum Button
{
SAVE,
ADD,
REMOVE,
VIEW,
RETURN
}
/**
* This enum holds which Lore is edited with current GUI.
*/
public enum LoreType
{
CHALLENGES,
LEVELS,
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Lore that will be edited with current GUI.
*/
private final LoreType lore;
/**
* List of lore elements that are currently enabled.
*/
private List<String> activeValues;
// ---------------------------------------------------------------------
// Section: Constants
// ---------------------------------------------------------------------
private final static String REFERENCE_DESCRIPTION = "challenges.gui.descriptions.admin.";
}

View File

@ -1,606 +0,0 @@
package world.bentobox.challenges.panel.admin;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Material;
import org.bukkit.World;
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;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.config.Settings;
import world.bentobox.challenges.config.SettingsUtils.GuiMode;
import world.bentobox.challenges.config.SettingsUtils.VisibilityMode;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.NumberGUI;
import world.bentobox.challenges.panel.util.SelectBlocksGUI;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
/**
* This Class creates GUI that allows to change Challenges Addon Settings via in-game
* menu.
*/
public class EditSettingsGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
public EditSettingsGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, topLabel, permissionPrefix, null);
}
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
public EditSettingsGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.settings = this.addon.getChallengesSettings();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.settings-title"));
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(10, this.getSettingsButton(Button.ENABLE_TITLE));
if (this.settings.isShowCompletionTitle())
{
panelBuilder.item(19, this.getSettingsButton(Button.TITLE_SHOWTIME));
}
panelBuilder.item(28, this.getSettingsButton(Button.BROADCAST));
panelBuilder.item(11, this.getSettingsButton(Button.GLOW_COMPLETED));
panelBuilder.item(20, this.getSettingsButton(Button.REMOVE_COMPLETED));
panelBuilder.item(29, this.getSettingsButton(Button.VISIBILITY_MODE));
panelBuilder.item(21, this.getSettingsButton(Button.LOCKED_LEVEL_ICON));
panelBuilder.item(30, this.getSettingsButton(Button.FREE_AT_TOP));
panelBuilder.item(22, this.getSettingsButton(Button.GAMEMODE_GUI));
if (this.settings.isUseCommonGUI())
{
// This should be active only when single gui is enabled.
panelBuilder.item(31, this.getSettingsButton(Button.GAMEMODE_GUI_VIEW_MODE));
}
panelBuilder.item(14, this.getSettingsButton(Button.LORE_LENGTH));
panelBuilder.item(23, this.getSettingsButton(Button.CHALLENGE_LORE));
panelBuilder.item(32, this.getSettingsButton(Button.LEVEL_LORE));
panelBuilder.item(24, this.getSettingsButton(Button.HISTORY));
if (this.settings.isStoreHistory())
{
panelBuilder.item(33, this.getSettingsButton(Button.PURGE_HISTORY));
}
panelBuilder.item(25, this.getSettingsButton(Button.RESET_CHALLENGES));
panelBuilder.item(34, this.getSettingsButton(Button.STORE_MODE));
// Return Button
panelBuilder.item(44, this.returnButton);
// Save Settings every time this GUI is created. It will avoid issues with
// Overwritten setting after server stop.
this.addon.saveSettings();
panelBuilder.build();
}
private PanelItem getSettingsButton(Button button)
{
ItemStack icon;
String name;
List<String> description;
boolean glow;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case RESET_CHALLENGES:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.reset-on-new"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isResetChallenges() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.reset-on-new");
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setResetChallenges(
!this.settings.isResetChallenges());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isResetChallenges();
break;
}
case BROADCAST:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.broadcast"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isBroadcastMessages() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
description = new ArrayList<>(2);
name = this.user.getTranslation("challenges.gui.buttons.admin.broadcast");
icon = new ItemStack(Material.JUKEBOX);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setBroadcastMessages(
!this.settings.isBroadcastMessages());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isBroadcastMessages();
break;
}
case REMOVE_COMPLETED:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.remove-completed"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isRemoveCompleteOneTimeChallenges() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.remove-completed");
icon = new ItemStack(Material.MAGMA_BLOCK);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setRemoveCompleteOneTimeChallenges(
!this.settings.isRemoveCompleteOneTimeChallenges());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isRemoveCompleteOneTimeChallenges();
break;
}
case LORE_LENGTH:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.line-length"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.settings.getLoreLineLength())));
name = this.user.getTranslation("challenges.gui.buttons.admin.line-length");
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user1, clickType, i) -> {
new NumberGUI(this.user,
this.settings.getLoreLineLength(),
0,
this.settings.getLoreLineLength(),
(status, value) -> {
if (status)
{
this.settings.setLoreLineLength(value);
}
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
});
return true;
};
glow = false;
break;
}
case LEVEL_LORE:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.level-lore"));
name = this.user.getTranslation("challenges.gui.buttons.admin.level-lore");
icon = new ItemStack(Material.MAP);
clickHandler = (panel, user1, clickType, i) -> {
EditLoreGUI.open(this, EditLoreGUI.LoreType.LEVELS);
return true;
};
glow = false;
break;
}
case CHALLENGE_LORE:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.challenge-lore"));
name = this.user.getTranslation("challenges.gui.buttons.admin.challenge-lore");
icon = new ItemStack(Material.PAPER);
clickHandler = (panel, user1, clickType, i) -> {
EditLoreGUI.open(this, EditLoreGUI.LoreType.CHALLENGES);
return true;
};
glow = false;
break;
}
case FREE_AT_TOP:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.free-at-top"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isAddCompletedGlow() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.free-at-top");
icon = new ItemStack(Material.FILLED_MAP);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setFreeChallengesFirst(!this.settings.isFreeChallengesFirst());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isFreeChallengesFirst();
break;
}
case GLOW_COMPLETED:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.glow"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isAddCompletedGlow() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.glow");
icon = new ItemStack(Material.GLOWSTONE);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setAddCompletedGlow(!this.settings.isAddCompletedGlow());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isAddCompletedGlow();
break;
}
case GAMEMODE_GUI_VIEW_MODE:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.gui-view-mode"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST) ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.gui-view-mode");
icon = new ItemStack(Material.STONE_BUTTON);
clickHandler = (panel, user1, clickType, i) -> {
if (this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST))
{
this.settings.setUserGuiMode(GuiMode.CURRENT_WORLD);
}
else
{
this.settings.setUserGuiMode(GuiMode.GAMEMODE_LIST);
}
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST);
break;
}
case GAMEMODE_GUI:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.gui-mode"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isUseCommonGUI() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.gui-mode");
icon = new ItemStack(Material.BLACK_STAINED_GLASS_PANE);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setUseCommonGUI(!this.settings.isUseCommonGUI());
// We cannot use single item changing as this option enabling/disabling will change other
// option visibility.
this.build();
return true;
};
glow = this.settings.isUseCommonGUI();
break;
}
case HISTORY:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.history-store"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isStoreHistory() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.history-store");
icon = new ItemStack(Material.WRITTEN_BOOK);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setStoreHistory(!this.settings.isStoreHistory());
// Need to rebuild all as new buttons will show up.
this.build();
return true;
};
glow = this.settings.isStoreHistory();
break;
}
case PURGE_HISTORY:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.history-lifespan"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.settings.getLifeSpan())));
name = this.user.getTranslation("challenges.gui.buttons.admin.history-lifespan");
icon = new ItemStack(Material.FLINT_AND_STEEL);
clickHandler = (panel, user1, clickType, i) -> {
new NumberGUI(this.user,
this.settings.getLifeSpan(),
0,
this.settings.getLoreLineLength(),
(status, value) -> {
if (status)
{
this.settings.setLifeSpan(value);
}
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
});
return true;
};
glow = false;
break;
}
case STORE_MODE:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.island-store"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isStoreAsIslandData() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.island-store");
icon = new ItemStack(Material.GRASS_BLOCK);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setStoreAsIslandData(!this.settings.isStoreAsIslandData());
// TODO: Data Migration must be added here.
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.isStoreAsIslandData();
break;
}
case LOCKED_LEVEL_ICON:
{
description = new ArrayList<>(1);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.default-locked-icon"));
name = this.user.getTranslation("challenges.gui.buttons.admin.default-locked-icon");
icon = this.settings.getLockedLevelIcon();
clickHandler = (panel, user, clickType, slot) -> {
new SelectBlocksGUI(this.user, true, (status, materials) -> {
if (status)
{
materials.forEach(material ->
this.settings.setLockedLevelIcon(new ItemStack(material)));
}
this.build();
});
return true;
};
glow = false;
break;
}
case ENABLE_TITLE:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.title-enable"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.settings.isShowCompletionTitle() ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
name = this.user.getTranslation("challenges.gui.buttons.admin.title-enable");
icon = new ItemStack(Material.OAK_SIGN);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setShowCompletionTitle(!this.settings.isShowCompletionTitle());
// Need to rebuild all as new buttons will show up.
this.build();
return true;
};
glow = this.settings.isShowCompletionTitle();
break;
}
case TITLE_SHOWTIME:
{
description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.title-showtime"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]", Integer.toString(this.settings.getTitleShowtime())));
name = this.user.getTranslation("challenges.gui.buttons.admin.title-showtime");
icon = new ItemStack(Material.CLOCK);
clickHandler = (panel, user1, clickType, i) -> {
new NumberGUI(this.user,
this.settings.getTitleShowtime(),
0,
this.settings.getLoreLineLength(),
(status, value) -> {
if (status)
{
this.settings.setTitleShowtime(value);
}
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
});
return true;
};
glow = false;
break;
}
case VISIBILITY_MODE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.visibility-mode");
List<String> values = new ArrayList<>(5);
values.add(this.user.getTranslation("challenges.gui.descriptions.admin.visibility-mode"));
values.add((this.settings.getVisibilityMode().equals(VisibilityMode.VISIBLE) ? "&2" : "&c") +
this.user.getTranslation("challenges.gui.descriptions.visibility.visible"));
values.add((this.settings.getVisibilityMode().equals(VisibilityMode.HIDDEN) ? "&2" : "&c") +
this.user.getTranslation("challenges.gui.descriptions.visibility.hidden"));
values.add((this.settings.getVisibilityMode().equals(VisibilityMode.TOGGLEABLE) ? "&2" : "&c") +
this.user.getTranslation("challenges.gui.descriptions.visibility.toggleable"));
values.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",this.settings.getVisibilityMode().name()));
description = values;
if (this.settings.getVisibilityMode().equals(VisibilityMode.VISIBLE))
{
icon = new ItemStack(Material.OAK_PLANKS);
}
else if (this.settings.getVisibilityMode().equals(VisibilityMode.HIDDEN))
{
icon = new ItemStack(Material.OAK_SLAB);
}
else
{
icon = new ItemStack(Material.OAK_BUTTON);
}
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.settings.setVisibilityMode(
Utils.getPreviousValue(VisibilityMode.values(),
this.settings.getVisibilityMode()));
}
else
{
this.settings.setVisibilityMode(
Utils.getNextValue(VisibilityMode.values(),
this.settings.getVisibilityMode()));
}
// Rebuild just this icon
panel.getInventory().setItem(slot,
this.getSettingsButton(button).getItem());
return true;
};
glow = false;
break;
}
default:
return new PanelItemBuilder().build();
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(GuiUtils.stringSplit(description, this.settings.getLoreLineLength())).
glow(glow).
clickHandler(clickHandler).
build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This enum holds all settings buttons that must have been displayed in this panel.
*/
private enum Button
{
RESET_CHALLENGES,
BROADCAST,
REMOVE_COMPLETED,
LORE_LENGTH,
LEVEL_LORE,
CHALLENGE_LORE,
FREE_AT_TOP,
GAMEMODE_GUI_VIEW_MODE,
GAMEMODE_GUI,
HISTORY,
PURGE_HISTORY,
STORE_MODE,
GLOW_COMPLETED,
LOCKED_LEVEL_ICON,
ENABLE_TITLE,
TITLE_SHOWTIME,
/**
* This allows to switch between different challenges visibility modes.
*/
VISIBILITY_MODE
}
/**
* This allows faster access to challenges settings object.
*/
private Settings settings;
}

View File

@ -0,0 +1,576 @@
package world.bentobox.challenges.panel.admin;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.ItemStack;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelListener;
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.ChallengesAddon;
import world.bentobox.challenges.config.Settings;
import world.bentobox.challenges.config.SettingsUtils.GuiMode;
import world.bentobox.challenges.config.SettingsUtils.VisibilityMode;
import world.bentobox.challenges.panel.CommonPanel;
import world.bentobox.challenges.panel.ConversationUtils;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
/**
* This Class creates GUI that allows to change Challenges Addon Settings via in-game
* menu.
*/
public class EditSettingsPanel extends CommonPanel
{
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
private EditSettingsPanel(ChallengesAddon addon,
User user,
World world,
String topLabel,
String permissionPrefix)
{
super(addon, user, world, topLabel, permissionPrefix);
this.settings = this.addon.getChallengesSettings();
}
/**
* @param parentGUI Parent GUI.
*/
private EditSettingsPanel(CommonPanel parentGUI)
{
super(parentGUI);
this.settings = this.addon.getChallengesSettings();
}
/**
* Open the Challenges Admin GUI.
*
* @param addon the addon
* @param world the world
* @param user the user
* @param topLabel the top label
* @param permissionPrefix the permission prefix
*/
public static void open(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
new EditSettingsPanel(addon, user, world, topLabel, permissionPrefix).build();
}
/**
* Open the Challenges Admin GUI.
*/
public static void open(CommonPanel parentGUI)
{
new EditSettingsPanel(parentGUI).build();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
@Override
protected void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation(Constants.TITLE + "settings"));
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(10, this.getSettingsButton(Button.SHOW_TITLE));
if (this.settings.isShowCompletionTitle())
{
panelBuilder.item(19, this.getSettingsButton(Button.TITLE_SHOWTIME));
}
panelBuilder.item(28, this.getSettingsButton(Button.BROADCAST));
panelBuilder.item(11, this.getSettingsButton(Button.GLOW_COMPLETED));
panelBuilder.item(20, this.getSettingsButton(Button.REMOVE_COMPLETED));
panelBuilder.item(29, this.getSettingsButton(Button.VISIBILITY_MODE));
panelBuilder.item(21, this.getSettingsButton(Button.LOCKED_LEVEL_ICON));
panelBuilder.item(22, this.getSettingsButton(Button.GAMEMODE_GUI));
if (this.settings.isUseCommonGUI())
{
// This should be active only when single gui is enabled.
panelBuilder.item(31, this.getSettingsButton(Button.ACTIVE_WORLD_LIST));
}
panelBuilder.item(24, this.getSettingsButton(Button.STORE_HISTORY));
if (this.settings.isStoreHistory())
{
panelBuilder.item(33, this.getSettingsButton(Button.PURGE_HISTORY));
}
panelBuilder.item(25, this.getSettingsButton(Button.RESET_ON_NEW));
panelBuilder.item(34, this.getSettingsButton(Button.DATA_PER_ISLAND));
// Return Button
panelBuilder.item(44, this.returnButton);
panelBuilder.listener(new IconChanger());
panelBuilder.build();
}
private PanelItem getSettingsButton(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;
boolean glow;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case RESET_ON_NEW -> {
description.add(this.user.getTranslation(reference +
(this.settings.isResetChallenges() ? "enabled" : "disabled")));
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setResetChallenges(!this.settings.isResetChallenges());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
this.addon.saveSettings();
return true;
};
glow = this.settings.isResetChallenges();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
case BROADCAST -> {
description.add(this.user.getTranslation(reference +
(this.settings.isBroadcastMessages() ? "enabled" : "disabled")));
icon = new ItemStack(Material.JUKEBOX);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setBroadcastMessages(!this.settings.isBroadcastMessages());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
this.addon.saveSettings();
return true;
};
glow = this.settings.isBroadcastMessages();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
case REMOVE_COMPLETED -> {
description.add(this.user.getTranslation(reference +
(this.settings.isRemoveCompleteOneTimeChallenges() ? "enabled" : "disabled")));
icon = new ItemStack(Material.MAGMA_BLOCK);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setRemoveCompleteOneTimeChallenges(!this.settings.isRemoveCompleteOneTimeChallenges());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
this.addon.saveSettings();
return true;
};
glow = this.settings.isRemoveCompleteOneTimeChallenges();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
case ACTIVE_WORLD_LIST -> {
description.add(this.user.getTranslation(reference +
(this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST) ?
"disabled" : "enabled")));
icon = new ItemStack(Material.STONE_BUTTON);
clickHandler = (panel, user1, clickType, i) -> {
if (this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST))
{
this.settings.setUserGuiMode(GuiMode.CURRENT_WORLD);
}
else
{
this.settings.setUserGuiMode(GuiMode.GAMEMODE_LIST);
}
this.addon.saveSettings();
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
glow = this.settings.getUserGuiMode().equals(GuiMode.GAMEMODE_LIST);
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
case GAMEMODE_GUI -> {
description.add(this.user.getTranslation(reference +
(this.settings.isUseCommonGUI() ? "enabled" : "disabled")));
icon = new ItemStack(Material.BLACK_STAINED_GLASS_PANE);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setUseCommonGUI(!this.settings.isUseCommonGUI());
// Need to rebuild more icons
this.build();
this.addon.saveSettings();
return true;
};
glow = this.settings.isUseCommonGUI();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
case STORE_HISTORY -> {
description.add(this.user.getTranslation(reference +
(this.settings.isStoreHistory() ? "enabled" : "disabled")));
icon = new ItemStack(Material.WRITTEN_BOOK);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setStoreHistory(!this.settings.isStoreHistory());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
this.addon.saveSettings();
return true;
};
glow = this.settings.isStoreHistory();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
case PURGE_HISTORY -> {
description.add(this.user.getTranslation(reference + "value",
Constants.NUMBER, String.valueOf(this.settings.getLifeSpan())));
icon = new ItemStack(Material.FLINT_AND_STEEL, Math.max(1, this.settings.getLifeSpan()));
clickHandler = (panel, user, clickType, i) -> {
Consumer<Number> numberConsumer = number -> {
if (number != null)
{
this.settings.setLifeSpan(number.intValue());
this.addon.saveSettings();
}
// reopen panel
this.build();
};
ConversationUtils.createNumericInput(numberConsumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "input-number"),
0,
2000);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
case DATA_PER_ISLAND -> {
description.add(this.user.getTranslation(reference +
(this.settings.isStoreAsIslandData() ? "enabled" : "disabled")));
icon = new ItemStack(Material.GRASS_BLOCK);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setStoreAsIslandData(!this.settings.isStoreAsIslandData());
// TODO: Migration
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
this.addon.saveSettings();
return true;
};
glow = this.settings.isStoreAsIslandData();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
case GLOW_COMPLETED -> {
description.add(this.user.getTranslation(reference +
(this.settings.isAddCompletedGlow() ? "enabled" : "disabled")));
icon = new ItemStack(Material.GLOWSTONE);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setAddCompletedGlow(!this.settings.isAddCompletedGlow());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
this.addon.saveSettings();
return true;
};
glow = this.settings.isAddCompletedGlow();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
case LOCKED_LEVEL_ICON -> {
icon = this.settings.getLockedLevelIcon();
clickHandler = (panel, user, clickType, i) ->
{
if (this.selectedButton != null)
{
this.selectedButton = null;
}
else
{
this.selectedButton = button;
}
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
return true;
};
if (this.selectedButton != button)
{
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
else
{
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-on-item"));
}
glow = this.selectedButton == button;
}
case SHOW_TITLE -> {
description.add(this.user.getTranslation(reference +
(this.settings.isShowCompletionTitle() ? "enabled" : "disabled")));
icon = new ItemStack(Material.OAK_SIGN);
clickHandler = (panel, user1, clickType, i) -> {
this.settings.setShowCompletionTitle(!this.settings.isShowCompletionTitle());
panel.getInventory().setItem(i, this.getSettingsButton(button).getItem());
this.addon.saveSettings();
return true;
};
glow = this.settings.isShowCompletionTitle();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
case TITLE_SHOWTIME -> {
description.add(this.user.getTranslation(reference + "value",
Constants.NUMBER, String.valueOf(this.settings.getTitleShowtime())));
icon = new ItemStack(Material.CLOCK, Math.max(1, this.settings.getTitleShowtime()));
clickHandler = (panel, user, clickType, i) -> {
Consumer<Number> numberConsumer = number -> {
if (number != null)
{
this.settings.setTitleShowtime(number.intValue());
this.addon.saveSettings();
}
// reopen panel
this.build();
};
ConversationUtils.createNumericInput(numberConsumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "input-number"),
0,
2000);
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-change"));
}
case VISIBILITY_MODE -> {
description.add(this.user.getTranslation(reference +
(this.settings.getVisibilityMode().equals(VisibilityMode.VISIBLE) ? "enabled" : "disabled")) +
this.user.getTranslation(reference + "visible"));
description.add(this.user.getTranslation(reference +
(this.settings.getVisibilityMode().equals(VisibilityMode.HIDDEN) ? "enabled" : "disabled")) +
this.user.getTranslation(reference + "hidden"));
description.add(this.user.getTranslation(reference +
(this.settings.getVisibilityMode().equals(VisibilityMode.TOGGLEABLE) ? "enabled" : "disabled")) +
this.user.getTranslation(reference + "toggleable"));
if (this.settings.getVisibilityMode().equals(VisibilityMode.VISIBLE))
{
icon = new ItemStack(Material.OAK_PLANKS);
}
else if (this.settings.getVisibilityMode().equals(VisibilityMode.HIDDEN))
{
icon = new ItemStack(Material.OAK_SLAB);
}
else
{
icon = new ItemStack(Material.OAK_BUTTON);
}
clickHandler = (panel, user, clickType, slot) -> {
if (clickType.isRightClick())
{
this.settings.setVisibilityMode(Utils.getPreviousValue(VisibilityMode.values(),
this.settings.getVisibilityMode()));
}
else
{
this.settings.setVisibilityMode(Utils.getNextValue(VisibilityMode.values(),
this.settings.getVisibilityMode()));
}
// Rebuild just this icon
panel.getInventory().setItem(slot, this.getSettingsButton(button).getItem());
this.addon.saveSettings();
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-cycle"));
description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-cycle"));
}
default -> {
icon = new ItemStack(Material.PAPER);
clickHandler = null;
glow = false;
}
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(description).
glow(glow).
clickHandler(clickHandler).
build();
}
// ---------------------------------------------------------------------
// Section: Classes
// ---------------------------------------------------------------------
/**
* This class allows changing icon for Generator Tier
*/
private class IconChanger implements PanelListener
{
/**
* Process inventory click. If generator icon is selected and user clicks on item in his inventory, then change
* icon to the item from inventory.
*
* @param user the user
* @param event the event
*/
@Override
public void onInventoryClick(User user, InventoryClickEvent event)
{
// Handle icon changing
if (EditSettingsPanel.this.selectedButton != null &&
event.getCurrentItem() != null &&
!event.getCurrentItem().getType().equals(Material.AIR) &&
event.getRawSlot() > 44)
{
// set material and amount only. Other data should be removed.
if (EditSettingsPanel.this.selectedButton == Button.LOCKED_LEVEL_ICON)
{
EditSettingsPanel.this.settings.setLockedLevelIcon(event.getCurrentItem().clone());
EditSettingsPanel.this.addon.saveSettings();
// Deselect icon
EditSettingsPanel.this.selectedButton = null;
EditSettingsPanel.this.build();
}
}
}
/**
* On inventory close.
*
* @param event the event
*/
@Override
public void onInventoryClose(InventoryCloseEvent event)
{
// Do nothing
}
/**
* Setup current listener.
*/
@Override
public void setup()
{
// Do nothing
}
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This enum holds all settings buttons that must have been displayed in this panel.
*/
private enum Button
{
RESET_ON_NEW,
BROADCAST,
REMOVE_COMPLETED,
ACTIVE_WORLD_LIST,
GAMEMODE_GUI,
STORE_HISTORY,
PURGE_HISTORY,
DATA_PER_ISLAND,
GLOW_COMPLETED,
LOCKED_LEVEL_ICON,
SHOW_TITLE,
TITLE_SHOWTIME,
/**
* This allows to switch between different challenges visibility modes.
*/
VISIBILITY_MODE
}
/**
* This allows faster access to challenges settings object.
*/
private final Settings settings;
/**
* Allows changing locked level icon.
*/
private Button selectedButton;
}

View File

@ -1,9 +1,8 @@
package world.bentobox.challenges.panel.admin;
import java.util.List;
import java.util.function.Consumer;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.World;
@ -11,18 +10,22 @@ 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.bentobox.util.Util;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.ConfirmationGUI;
import world.bentobox.challenges.panel.CommonPagedPanel;
import world.bentobox.challenges.panel.CommonPanel;
import world.bentobox.challenges.panel.ConversationUtils;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
/**
* This class contains all necessary elements to create GUI that lists all challenges.
* It allows to edit them or remove, depending on given input mode.
*/
public class ListChallengesGUI extends CommonGUI
public class ListChallengesPanel extends CommonPagedPanel
{
// ---------------------------------------------------------------------
// Section: Constructor
@ -37,38 +40,57 @@ public class ListChallengesGUI extends CommonGUI
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param mode - mode that indicate what should do icon clicking.
*/
public ListChallengesGUI(ChallengesAddon addon,
private ListChallengesPanel(ChallengesAddon addon,
World world,
User user,
Mode mode,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, mode, topLabel, permissionPrefix, null);
super(addon, user, world, topLabel, permissionPrefix);
this.currentMode = mode;
}
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param mode - mode that indicate what should do icon clicking.
*/
public ListChallengesGUI(ChallengesAddon addon,
World world,
User user,
Mode mode,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
private ListChallengesPanel(CommonPanel parentGUI, Mode mode)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
super(parentGUI);
this.currentMode = mode;
}
/**
* Open the Challenges Admin GUI.
*
* @param addon the addon
* @param world the world
* @param user the user
* @param topLabel the top label
* @param permissionPrefix the permission prefix
*/
public static void open(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix,
Mode mode)
{
new ListChallengesPanel(addon, world, user, mode, topLabel, permissionPrefix).build();
}
/**
* Open the Challenges Admin GUI.
*/
public static void open(CommonPanel parentGUI, Mode mode)
{
new ListChallengesPanel(parentGUI, mode).build();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
@ -78,10 +100,10 @@ public class ListChallengesGUI extends CommonGUI
* {@inheritDoc}
*/
@Override
public void build()
protected void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.choose-challenge-title"));
this.user.getTranslation(Constants.TITLE + "choose-challenge"));
if (this.currentMode.equals(Mode.DELETE))
{
@ -92,42 +114,9 @@ public class ListChallengesGUI extends CommonGUI
GuiUtils.fillBorder(panelBuilder);
}
List<Challenge> challengeList = this.addon.getChallengesManager().getAllChallenges(this.world);
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = challengeList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (challengeList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int challengeIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (challengeIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
challengeIndex < challengeList.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createChallengeIcon(challengeList.get(challengeIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (challengeList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
this.populateElements(panelBuilder,
this.addon.getChallengesManager().getAllChallenges(this.world),
o -> this.createChallengeIcon((Challenge) o));
panelBuilder.item(44, this.returnButton);
@ -143,36 +132,46 @@ public class ListChallengesGUI extends CommonGUI
private PanelItem createChallengeIcon(Challenge challenge)
{
PanelItemBuilder itemBuilder = new PanelItemBuilder().
name(ChatColor.translateAlternateColorCodes('&', challenge.getFriendlyName())).
description(GuiUtils.stringSplit(this.generateChallengeDescription(challenge, this.user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength())).
icon(challenge.getIcon()).
glow(challenge.isDeployed());
name(Util.translateColorCodes(challenge.getFriendlyName())).
description(this.generateChallengeDescription(challenge, null)).
icon(challenge.getIcon()).
glow(!challenge.isDeployed());
if (this.currentMode.equals(Mode.EDIT))
{
itemBuilder.description("");
itemBuilder.description(this.user.getTranslation(Constants.TIPS + "click-to-edit"));
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
new EditChallengeGUI(this.addon,
this.world,
this.user,
challenge,
this.topLabel,
this.permissionPrefix,
this).build();
EditChallengePanel.open(this, challenge);
return true;
});
}
else if (this.currentMode.equals(Mode.DELETE))
{
itemBuilder.description("");
itemBuilder.description(this.user.getTranslation(Constants.TIPS + "click-to-remove"));
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
new ConfirmationGUI(this.user, value -> {
Consumer<Boolean> consumer = value -> {
if (value)
{
this.addon.getChallengesManager().deleteChallenge(challenge);
}
this.build();
});
};
// Create conversation that gets user acceptance to delete generator data.
ConversationUtils.createConfirmation(
consumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "confirm-challenge-deletion",
Constants.GAMEMODE, Utils.getGameMode(this.world),
Constants.CHALLENGE, challenge.getFriendlyName()),
this.user.getTranslation(Constants.CONVERSATIONS + "challenge-removed",
Constants.GAMEMODE, Utils.getGameMode(this.world),
Constants.CHALLENGE, challenge.getFriendlyName()));
return true;
});
}
@ -203,5 +202,5 @@ public class ListChallengesGUI extends CommonGUI
/**
* Current mode in which icons will act.
*/
private Mode currentMode;
private final Mode currentMode;
}

View File

@ -1,28 +1,31 @@
package world.bentobox.challenges.panel.admin;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.World;
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;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.ChallengeLevel;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.ConfirmationGUI;
import world.bentobox.challenges.panel.CommonPagedPanel;
import world.bentobox.challenges.panel.CommonPanel;
import world.bentobox.challenges.panel.ConversationUtils;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
/**
* This class creates GUI that lists all Levels. Clicking on Level icon will be processed
* by input mode.
*/
public class ListLevelsGUI extends CommonGUI
public class ListLevelsPanel extends CommonPagedPanel
{
// ---------------------------------------------------------------------
// Section: Constructor
@ -37,38 +40,57 @@ public class ListLevelsGUI extends CommonGUI
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param mode - mode that indicate what should do icon clicking.
*/
public ListLevelsGUI(ChallengesAddon addon,
private ListLevelsPanel(ChallengesAddon addon,
World world,
User user,
Mode mode,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, mode, topLabel, permissionPrefix, null);
super(addon, user, world, topLabel, permissionPrefix);
this.currentMode = mode;
}
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param mode - mode that indicate what should do icon clicking.
*/
public ListLevelsGUI(ChallengesAddon addon,
World world,
User user,
Mode mode,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
private ListLevelsPanel(CommonPanel parentGUI, Mode mode)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
super(parentGUI);
this.currentMode = mode;
}
/**
* Open the Challenges Admin GUI.
*
* @param addon the addon
* @param world the world
* @param user the user
* @param topLabel the top label
* @param permissionPrefix the permission prefix
*/
public static void open(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix,
Mode mode)
{
new ListLevelsPanel(addon, world, user, mode, topLabel, permissionPrefix).build();
}
/**
* Open the Challenges Admin GUI.
*/
public static void open(CommonPanel parentGUI, Mode mode)
{
new ListLevelsPanel(parentGUI, mode).build();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
@ -78,10 +100,10 @@ public class ListLevelsGUI extends CommonGUI
* {@inheritDoc}
*/
@Override
public void build()
protected void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.choose-level-title"));
this.user.getTranslation(Constants.TITLE + "choose-level"));
if (this.currentMode.equals(Mode.DELETE))
{
@ -92,42 +114,9 @@ public class ListLevelsGUI extends CommonGUI
GuiUtils.fillBorder(panelBuilder);
}
List<ChallengeLevel> levelList = this.addon.getChallengesManager().getLevels(this.world);
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = levelList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (levelList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int levelIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (levelIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
levelIndex < levelList.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createLevelIcon(levelList.get(levelIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (levelList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
this.populateElements(panelBuilder,
this.addon.getChallengesManager().getLevels(this.world),
o -> this.createLevelIcon((ChallengeLevel) o));
panelBuilder.item(44, this.returnButton);
@ -143,38 +132,45 @@ public class ListLevelsGUI extends CommonGUI
private PanelItem createLevelIcon(ChallengeLevel challengeLevel)
{
PanelItemBuilder itemBuilder = new PanelItemBuilder().
name(ChatColor.translateAlternateColorCodes('&', challengeLevel.getFriendlyName())).
description(GuiUtils.stringSplit(
this.generateLevelDescription(challengeLevel, this.user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength())).
icon(challengeLevel.getIcon()).
glow(false);
name(Util.translateColorCodes(challengeLevel.getFriendlyName())).
description(this.generateLevelDescription(challengeLevel)).
icon(challengeLevel.getIcon());
if (this.currentMode.equals(Mode.EDIT))
{
itemBuilder.description("");
itemBuilder.description(this.user.getTranslation(Constants.TIPS + "click-to-edit"));
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
new EditLevelGUI(this.addon,
this.world,
this.user,
challengeLevel,
this.topLabel,
this.permissionPrefix,
this).build();
EditLevelPanel.open(this, challengeLevel);
return true;
});
}
else if (this.currentMode.equals(Mode.DELETE))
{
itemBuilder.description("");
itemBuilder.description(this.user.getTranslation(Constants.TIPS + "click-to-remove"));
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
new ConfirmationGUI(this.user, value -> {
Consumer<Boolean> consumer = value -> {
if (value)
{
this.addon.getChallengesManager().
deleteChallengeLevel(challengeLevel);
this.addon.getChallengesManager().deleteChallengeLevel(challengeLevel);
}
this.build();
});
};
// Create conversation that gets user acceptance to delete generator data.
ConversationUtils.createConfirmation(
consumer,
this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "confirm-level-deletion",
Constants.GAMEMODE, Utils.getGameMode(this.world),
Constants.LEVEL, challengeLevel.getFriendlyName()),
this.user.getTranslation(Constants.CONVERSATIONS + "level-removed",
Constants.GAMEMODE, Utils.getGameMode(this.world),
Constants.LEVEL, challengeLevel.getFriendlyName()));
return true;
});
}
@ -202,8 +198,9 @@ public class ListLevelsGUI extends CommonGUI
// Section: Variables
// ---------------------------------------------------------------------
/**
* Current mode in which icons will act.
*/
private Mode currentMode;
private final Mode currentMode;
}

View File

@ -7,15 +7,21 @@ import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.scheduler.BukkitTask;
import world.bentobox.bentobox.api.panels.PanelItem;
import world.bentobox.bentobox.api.panels.PanelListener;
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.ChallengesAddon;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.CommonPagedPanel;
import world.bentobox.challenges.panel.CommonPanel;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
import world.bentobox.challenges.web.object.LibraryEntry;
@ -23,7 +29,7 @@ import world.bentobox.challenges.web.object.LibraryEntry;
* This class contains all necessary elements to create GUI that lists all challenges.
* It allows to edit them or remove, depending on given input mode.
*/
public class ListLibraryGUI extends CommonGUI
public class ListLibraryPanel extends CommonPagedPanel
{
// ---------------------------------------------------------------------
// Section: Constructor
@ -32,7 +38,7 @@ public class ListLibraryGUI extends CommonGUI
/**
* @param parentGUI ParentGUI object.
*/
public ListLibraryGUI(CommonGUI parentGUI)
private ListLibraryPanel(CommonPanel parentGUI)
{
super(parentGUI);
}
@ -45,23 +51,43 @@ public class ListLibraryGUI extends CommonGUI
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
public ListLibraryGUI(ChallengesAddon addon,
private ListLibraryPanel(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
super(addon, world, user, topLabel, permissionPrefix, null);
super(addon, user, world, topLabel, permissionPrefix);
}
/**
* Open the Challenges Admin GUI.
*
* @param addon the addon
* @param world the world
* @param user the user
* @param topLabel the top label
* @param permissionPrefix the permission prefix
*/
public static void open(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
new ListLibraryPanel(addon, world, user, topLabel, permissionPrefix).build();
}
/**
* This static method allows to easier open Library GUI.
* @param parentGui ParentGUI object.
*/
public static void open(CommonGUI parentGui)
public static void open(CommonPanel parentGui)
{
new ListLibraryGUI(parentGui).build();
new ListLibraryPanel(parentGui).build();
}
@ -74,52 +100,21 @@ public class ListLibraryGUI extends CommonGUI
* {@inheritDoc}
*/
@Override
public void build()
protected void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.library-title"));
this.user.getTranslation(Constants.TITLE + "library"));
GuiUtils.fillBorder(panelBuilder);
List<LibraryEntry> libraryEntries = this.addon.getWebManager().getLibraryEntries();
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = libraryEntries.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (libraryEntries.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int entryIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (entryIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
entryIndex < libraryEntries.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createEntryIcon(libraryEntries.get(entryIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (libraryEntries.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
this.populateElements(panelBuilder,
this.addon.getWebManager().getLibraryEntries(),
o -> this.createEntryIcon((LibraryEntry) o));
panelBuilder.item(4, this.createDownloadNow());
panelBuilder.item(44, this.createReturnButton());
panelBuilder.item(44, this.returnButton);
panelBuilder.listener(new DownloadCanceller());
panelBuilder.build();
}
@ -131,17 +126,20 @@ public class ListLibraryGUI extends CommonGUI
*/
private PanelItem createDownloadNow()
{
List<String> description = new ArrayList<>(2);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.download"));
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value",
"[value]",
this.clearCache ?
this.user.getTranslation("challenges.gui.descriptions.enabled") :
this.user.getTranslation("challenges.gui.descriptions.disabled")));
final String reference = Constants.BUTTON + "download.";
final List<String> description = new ArrayList<>(3);
description.add(this.user.getTranslation(reference + "description"));
description.add(this.user.getTranslation(reference +
(this.clearCache ? "enabled" : "disabled")));
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-download"));
description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-toggle"));
PanelItemBuilder itemBuilder = new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.download")).
description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())).
name(this.user.getTranslation(reference + "name")).
description(description).
icon(Material.HOPPER).
glow(this.clearCache);
@ -176,33 +174,6 @@ public class ListLibraryGUI extends CommonGUI
}
/**
* This creates return button, that allows to exist or return to parent gui,
* @return PanelItem for return button.
*/
private PanelItem createReturnButton()
{
return new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.return")).
icon(Material.OAK_DOOR).
clickHandler((panel, user1, clickType, i) -> {
if (this.updateTask != null)
{
this.updateTask.cancel();
}
if (this.parentGUI == null)
{
this.user.closeInventory();
return true;
}
this.parentGUI.build();
return true;
}).build();
}
/**
* This method creates button for given library entry.
* @param libraryEntry LibraryEntry which button must be created.
@ -211,10 +182,12 @@ public class ListLibraryGUI extends CommonGUI
private PanelItem createEntryIcon(LibraryEntry libraryEntry)
{
PanelItemBuilder itemBuilder = new PanelItemBuilder().
name(ChatColor.translateAlternateColorCodes('&', libraryEntry.getName())).
description(this.generateEntryDescription(libraryEntry)).
icon(libraryEntry.getIcon()).
glow(false);
name(ChatColor.translateAlternateColorCodes('&', libraryEntry.getName())).
description(this.generateEntryDescription(libraryEntry)).
description("").
description(this.user.getTranslation(Constants.TIPS + "click-to-install")).
icon(libraryEntry.getIcon()).
glow(false);
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
@ -222,7 +195,8 @@ public class ListLibraryGUI extends CommonGUI
{
this.blockedForDownland = true;
this.user.sendMessage("challenges.messages.admin.start-downloading");
Utils.sendMessage(this.user,
this.user.getTranslation(Constants.CONVERSATIONS + "start-downloading"));
// Run download task after 5 ticks.
this.addon.getPlugin().getServer().getScheduler().
@ -231,24 +205,7 @@ public class ListLibraryGUI extends CommonGUI
() -> this.addon.getWebManager().requestEntryGitHubData(this.user, this.world, libraryEntry),
5L);
if (this.parentGUI != null)
{
if (this.updateTask != null)
{
this.updateTask.cancel();
}
this.parentGUI.build();
}
else
{
if (this.updateTask != null)
{
this.updateTask.cancel();
}
this.user.closeInventory();
}
this.build();
}
return true;
@ -265,25 +222,66 @@ public class ListLibraryGUI extends CommonGUI
*/
private List<String> generateEntryDescription(LibraryEntry entry)
{
final String reference = Constants.DESCRIPTIONS + "library.";
List<String> description = new ArrayList<>();
description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "library-author",
"[author]",
entry.getAuthor()));
description.add(this.user.getTranslation(reference + "author",
"[author]", entry.getAuthor()));
description.add(entry.getDescription());
description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "library-gamemode",
"[gamemode]",
entry.getForGameMode()));
description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "library-lang",
"[lang]",
entry.getLanguage()));
description.add(this.user.getTranslation(REFERENCE_DESCRIPTION + "library-version",
"[version]",
entry.getVersion()));
description.add(this.user.getTranslation(reference + "gamemode",
"[gamemode]", entry.getForGameMode()));
description.add(this.user.getTranslation(reference + "lang",
"[lang]", entry.getLanguage()));
description.add(this.user.getTranslation(reference + "version",
"[version]", entry.getVersion()));
return GuiUtils.stringSplit(description,
this.addon.getChallengesSettings().getLoreLineLength());
return description;
}
/**
* This class allows changing icon for Generator Tier
*/
private class DownloadCanceller implements PanelListener
{
/**
* On inventory click.
*
* @param user the user
* @param event the event
*/
@Override
public void onInventoryClick(User user, InventoryClickEvent event)
{
// do nothing
}
/**
* On inventory close.
*
* @param event the event
*/
@Override
public void onInventoryClose(InventoryCloseEvent event)
{
if (ListLibraryPanel.this.updateTask != null)
{
ListLibraryPanel.this.updateTask.cancel();
}
}
/**
* Setup current listener.
*/
@Override
public void setup()
{
// Do nothing
}
}
@ -305,9 +303,4 @@ public class ListLibraryGUI extends CommonGUI
* This variable will protect against spam-click.
*/
private boolean blockedForDownland;
/**
* Reference string to description.
*/
private static final String REFERENCE_DESCRIPTION = "challenges.gui.descriptions.admin.";
}

View File

@ -1,334 +0,0 @@
package world.bentobox.challenges.panel.admin;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
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.bentobox.database.objects.Players;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.managers.ChallengesManager;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.ConfirmationGUI;
import world.bentobox.challenges.panel.util.SelectChallengeGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class contains methods that allows to select specific user.
*/
public class ListUsersGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with players that should be in GUI.
*/
private List<Player> onlineUsers;
/**
* Current operation mode.
*/
private Mode operationMode;
/**
* Current index of view mode
*/
private int modeIndex = 2;
/**
* This allows to switch which users should be in the list.
*/
private enum ViewMode
{
ONLINE,
WITH_ISLAND,
IN_WORLD
}
/**
* This allows to decide what User Icon should do.
*/
public enum Mode
{
COMPLETE,
RESET,
RESET_ALL
}
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param operationMode Indicate what should happen on player icon click.
*/
public ListUsersGUI(ChallengesAddon addon,
World world,
User user,
Mode operationMode,
String topLabel,
String permissionPrefix)
{
this(addon, world, user, operationMode, topLabel, permissionPrefix, null);
}
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param operationMode Indicate what should happen on player icon click.
*/
public ListUsersGUI(ChallengesAddon addon,
World world,
User user,
Mode operationMode,
String topLabel,
String permissionPrefix,
CommonGUI parentPanel)
{
super(addon, world, user, topLabel, permissionPrefix, parentPanel);
this.onlineUsers = this.collectUsers(ViewMode.IN_WORLD);
this.operationMode = operationMode;
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation("challenges.gui.title.admin.choose-user-title"));
GuiUtils.fillBorder(panelBuilder);
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = this.onlineUsers.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (this.onlineUsers.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int playerIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (playerIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
playerIndex < this.onlineUsers.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createPlayerIcon(this.onlineUsers.get(playerIndex++)));
}
index++;
}
// Add button that allows to toggle different player lists.
panelBuilder.item( 4, this.createToggleButton());
// Navigation buttons only if necessary
if (this.onlineUsers.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method creates button for given user. If user has island it will add valid click handler.
* @param player Player which button must be created.
* @return Player button.
*/
private PanelItem createPlayerIcon(Player player)
{
int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
if (this.addon.getIslands().getIsland(this.world, player.getUniqueId()) != null)
{
return new PanelItemBuilder().name(player.getName()).icon(player.getName()).clickHandler(
(panel, user1, clickType, slot) -> {
ChallengesManager manager = this.addon.getChallengesManager();
Map<Challenge, List<String>> challengeDescriptionMap;
switch (this.operationMode)
{
case COMPLETE:
challengeDescriptionMap = new LinkedHashMap<>();
for (Challenge challenge : manager.getAllChallenges(this.world))
{
if (!manager.isChallengeComplete(player.getUniqueId(), this.world, challenge))
{
challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player));
}
}
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge -> manager.setChallengeComplete(player.getUniqueId(), this.world, challenge, this.user.getUniqueId()));
}
this.build();
});
break;
case RESET:
challengeDescriptionMap = new LinkedHashMap<>();
for (Challenge challenge : manager.getAllChallenges(this.world))
{
if (manager.isChallengeComplete(player.getUniqueId(), this.world, challenge))
{
challengeDescriptionMap.put(challenge, this.generateChallengeDescription(challenge, player));
}
}
new SelectChallengeGUI(this.user, challengeDescriptionMap, lineLength, (status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge -> manager.resetChallenge(player.getUniqueId(), this.world, challenge, this.user.getUniqueId()));
}
this.build();
});
break;
case RESET_ALL:
new ConfirmationGUI(this.user, status -> {
if (status)
{
manager.resetAllChallenges(player.getUniqueId(), this.world, this.user.getUniqueId());
}
this.build();
});
break;
}
return true;
}).build();
}
else
{
return new PanelItemBuilder().
name(player.getName()).
icon(Material.BARRIER).
description(GuiUtils.stringSplit(this.user.getTranslation("general.errors.player-has-no-island"), lineLength)).
clickHandler((panel, user1, clickType, slot) -> false).
build();
}
}
/**
* This method collects users based on view mode.
* @param mode Given view mode.
* @return List with players in necessary view mode.
*/
private List<Player> collectUsers(ViewMode mode)
{
if (mode.equals(ViewMode.ONLINE))
{
return new ArrayList<>(Bukkit.getOnlinePlayers());
}
else if (mode.equals(ViewMode.WITH_ISLAND))
{
return this.addon.getPlayers().getPlayers().stream().
filter(player -> this.addon.getIslands().getIsland(this.world, player.getPlayerUUID()) != null).
map(Players::getPlayer).
collect(Collectors.toList());
}
else
{
return new ArrayList<>(this.world.getPlayers());
}
}
/**
* This method creates Player List view Mode toggle button.
* @return Button that toggles through player view mode.
*/
private PanelItem createToggleButton()
{
List<String> description = new ArrayList<>(ViewMode.values().length + 1);
description.add(this.user.getTranslation("challenges.gui.descriptions.admin.toggle-user-list"));
description.add((ViewMode.ONLINE == ViewMode.values()[this.modeIndex] ? "&2" : "&c") +
this.user.getTranslation("challenges.gui.descriptions.admin.mode-online"));
description.add((ViewMode.WITH_ISLAND == ViewMode.values()[this.modeIndex] ? "&2" : "&c") +
this.user.getTranslation("challenges.gui.descriptions.admin.mode-in-world"));
description.add((ViewMode.IN_WORLD == ViewMode.values()[this.modeIndex] ? "&2" : "&c") +
this.user.getTranslation("challenges.gui.descriptions.admin.mode-with-island"));
return new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin.toggle-user-list")).
description(GuiUtils.stringSplit(description, this.addon.getChallengesSettings().getLoreLineLength())).
icon(Material.STONE_BUTTON).
clickHandler(
(panel, user1, clickType, slot) -> {
if (clickType.isRightClick())
{
this.modeIndex--;
if (this.modeIndex < 0)
{
this.modeIndex = ViewMode.values().length - 1;
}
}
else
{
this.modeIndex++;
if (this.modeIndex >= ViewMode.values().length)
{
this.modeIndex = 0;
}
}
this.onlineUsers = this.collectUsers(ViewMode.values()[this.modeIndex]);
this.pageIndex = 0;
this.build();
return true;
}).build();
}
}

View File

@ -0,0 +1,376 @@
package world.bentobox.challenges.panel.admin;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Player;
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.bentobox.database.objects.Island;
import world.bentobox.bentobox.database.objects.Players;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.panel.CommonPagedPanel;
import world.bentobox.challenges.panel.CommonPanel;
import world.bentobox.challenges.panel.util.ChallengeSelector;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
/**
* This class contains methods that allows to select specific user.
*/
public class ListUsersPanel extends CommonPagedPanel
{
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
* @param operationMode Indicate what should happen on player icon click.
*/
private ListUsersPanel(ChallengesAddon addon,
User user,
World world,
String topLabel,
String permissionPrefix,
Mode operationMode)
{
super(addon, user, world, topLabel, permissionPrefix);
this.onlineUsers = this.collectUsers(ViewMode.IN_WORLD);
this.operationMode = operationMode;
}
/**
* @param operationMode Indicate what should happen on player icon click.
*/
private ListUsersPanel(CommonPanel panel, Mode operationMode)
{
super(panel);
this.onlineUsers = this.collectUsers(ViewMode.IN_WORLD);
this.operationMode = operationMode;
}
/**
* Open the Challenges Admin GUI.
*
* @param addon the addon
* @param world the world
* @param user the user
* @param topLabel the top label
* @param permissionPrefix the permission prefix
*/
public static void open(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix,
Mode mode)
{
new ListUsersPanel(addon, user, world, topLabel, permissionPrefix, mode).build();
}
/**
* Open the Challenges Admin GUI.
*/
public static void open(CommonPanel parentGUI, Mode mode)
{
new ListUsersPanel(parentGUI, mode).build();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
@Override
protected void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(
this.user.getTranslation(Constants.TITLE + "choose-player"));
GuiUtils.fillBorder(panelBuilder);
this.populateElements(panelBuilder,
this.onlineUsers,
o -> this.createPlayerIcon((Player) o));
// Add button that allows to toggle different player lists.
panelBuilder.item( 4, this.createToggleButton());
panelBuilder.item(44, this.returnButton);
panelBuilder.build();
}
/**
* This method creates button for given user. If user has island it will add valid click handler.
* @param player Player which button must be created.
* @return Player button.
*/
private PanelItem createPlayerIcon(Player player)
{
final String reference = Constants.BUTTON + "player.";
Island island = this.addon.getIslands().getIsland(this.world, player.getUniqueId());
if (island == null)
{
return new PanelItemBuilder().
name(this.user.getTranslation(reference + "name", "[name]", player.getName())).
icon(Material.BARRIER).
description(this.user.getTranslation(reference + "no-island")).
build();
}
List<String> description = new ArrayList<>(4);
description.add(this.user.getTranslation(reference + "description",
"[owner]", this.addon.getPlayers().getName(island.getOwner())));
// Is owner in his own island member set? I assume yes. Need testing.
if (island.getMemberSet().size() > 1)
{
description.add(this.user.getTranslation(reference + "members"));
island.getMemberSet().forEach(member -> {
if (member != island.getOwner())
{
description.add(this.user.getTranslation(reference + "member",
"[name]", this.addon.getPlayers().getName(member)));
}
});
}
description.add("");
if (this.operationMode == Mode.RESET_ALL && this.selectedPlayer != null)
{
description.add(this.user.getTranslation(Constants.TIPS + "click-to-reset-all"));
}
else
{
description.add(this.user.getTranslation(Constants.TIPS + "click-to-choose"));
}
return new PanelItemBuilder().
name(this.user.getTranslation(reference + "name", "[name]", player.getName())).
icon(player.getName()).
description(description).
glow(this.operationMode == Mode.RESET_ALL && this.selectedPlayer == player).
clickHandler((panel, user1, clickType, i) -> {
switch (this.operationMode)
{
case COMPLETE -> {
// Get all challenge that is in current level.
List<Challenge> challengeList = this.manager.getAllChallenges(this.world);
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().
filter(challenge -> !this.manager.isChallengeComplete(player.getUniqueId(), this.world, challenge)).
collect(Collectors.toMap(challenge -> challenge,
challenge -> this.generateChallengeDescription(challenge, User.getInstance(player)),
(a, b) -> b,
() -> new LinkedHashMap<>(challengeList.size())));
// Open select gui
ChallengeSelector.open(this.user,
Material.LIME_STAINED_GLASS_PANE,
challengeDescriptionMap,
(status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge ->
manager.setChallengeComplete(player.getUniqueId(),
this.world,
challenge,
this.user.getUniqueId()));
}
this.build();
});
}
case RESET -> {
// Get all challenge that is in current level.
List<Challenge> challengeList = this.manager.getAllChallenges(this.world);
// Generate descriptions for these challenges
Map<Challenge, List<String>> challengeDescriptionMap = challengeList.stream().
filter(challenge -> this.manager.isChallengeComplete(player.getUniqueId(), this.world, challenge)).
collect(Collectors.toMap(challenge -> challenge,
challenge -> this.generateChallengeDescription(challenge, User.getInstance(player)),
(a, b) -> b,
() -> new LinkedHashMap<>(challengeList.size())));
// Open select gui
ChallengeSelector.open(this.user,
Material.ORANGE_STAINED_GLASS_PANE,
challengeDescriptionMap,
(status, valueSet) -> {
if (status)
{
valueSet.forEach(challenge ->
this.manager.resetChallenge(player.getUniqueId(),
this.world,
challenge,
this.user.getUniqueId()));
}
this.build();
});
}
case RESET_ALL -> {
if (this.selectedPlayer == null)
{
this.selectedPlayer = player;
}
else
{
this.manager.resetAllChallenges(player.getUniqueId(), this.world, this.user.getUniqueId());
this.selectedPlayer = null;
}
this.build();
}
}
return true;
}).
build();
}
/**
* This method collects users based on view mode.
* @param mode Given view mode.
* @return List with players in necessary view mode.
*/
private List<Player> collectUsers(ViewMode mode)
{
return switch (mode) {
case ONLINE -> new ArrayList<>(Bukkit.getOnlinePlayers());
case WITH_ISLAND -> this.addon.getPlayers().getPlayers().stream().
filter(player -> this.addon.getIslands().getIsland(this.world, player.getPlayerUUID()) != null).
map(Players::getPlayer).
collect(Collectors.toList());
default -> new ArrayList<>(this.world.getPlayers());
};
}
/**
* This method creates Player List view Mode toggle button.
* @return Button that toggles through player view mode.
*/
private PanelItem createToggleButton()
{
final String reference = Constants.BUTTON + "player_list.";
List<String> description = new ArrayList<>(5);
description.add(this.user.getTranslation(reference + "description"));
description.add(this.user.getTranslation(reference +
(ViewMode.ONLINE == this.mode ? "enabled" : "disabled")) +
this.user.getTranslation(reference + "online"));
description.add(this.user.getTranslation(reference +
(ViewMode.WITH_ISLAND == this.mode ? "enabled" : "disabled")) +
this.user.getTranslation(reference + "with_island"));
description.add(this.user.getTranslation(reference +
(ViewMode.IN_WORLD == this.mode ? "enabled" : "disabled")) +
this.user.getTranslation(reference + "in_world"));
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-cycle"));
description.add(this.user.getTranslation(Constants.TIPS + "right-click-to-cycle"));
return new PanelItemBuilder().
name(this.user.getTranslation(reference + "name")).
icon(Material.STONE_BUTTON).
description(description).
clickHandler((panel, user1, clickType, slot) -> {
if (clickType.isRightClick())
{
this.mode = Utils.getPreviousValue(ViewMode.values(), this.mode);
this.onlineUsers = this.collectUsers(this.mode);
}
else
{
this.mode = Utils.getNextValue(ViewMode.values(), this.mode);
this.onlineUsers = this.collectUsers(this.mode);
}
this.build();
return true;
}).build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This allows to switch which users should be in the list.
*/
private enum ViewMode
{
ONLINE,
WITH_ISLAND,
IN_WORLD
}
/**
* This allows to decide what User Icon should do.
*/
public enum Mode
{
COMPLETE,
RESET,
RESET_ALL
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with players that should be in GUI.
*/
private List<Player> onlineUsers;
/**
* Current operation mode.
*/
private final Mode operationMode;
/**
* Current index of view mode
*/
private ViewMode mode = ViewMode.ONLINE;
/**
* Stores clicked player.
*/
private Player selectedPlayer;
}

View File

@ -1,241 +0,0 @@
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.Map;
import java.util.Set;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Material;
import org.bukkit.World;
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.ChallengesAddon;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.NumberGUI;
import world.bentobox.challenges.panel.util.SelectBlocksGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class allows to edit material that are in required material map.
*/
public class ManageBlocksGUI extends CommonGUI
{
public ManageBlocksGUI(ChallengesAddon addon,
World world,
User user,
Map<Material, Integer> materialMap,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.materialMap = materialMap;
this.materialList = new ArrayList<>(this.materialMap.keySet());
// Sort materials by their ordinal value.
this.materialList.sort(Comparator.comparing(Enum::ordinal));
this.selectedMaterials = new HashSet<>();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation("challenges.gui.title.admin.manage-blocks"));
// Create nice border.
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(3, this.createButton(Button.ADD));
panelBuilder.item(5, this.createButton(Button.REMOVE));
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = this.materialList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (this.materialList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int entitiesIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (entitiesIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
entitiesIndex < this.materialList.size() &&
index < 36)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createElementButton(this.materialList.get(entitiesIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (this.materialList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
// 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)
{
int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
PanelItemBuilder builder = new PanelItemBuilder();
switch (button)
{
case ADD:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.add"));
builder.icon(Material.BUCKET);
builder.clickHandler((panel, user1, clickType, slot) -> {
new SelectBlocksGUI(this.user, false, new HashSet<>(this.materialList), (status, materials) -> {
if (status)
{
materials.forEach(material -> {
this.materialMap.put(material, 1);
this.materialList.add(material);
});
}
this.build();
});
return true;
});
break;
case REMOVE:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.remove-selected"));
builder.description(GuiUtils.stringSplit(this.user.getTranslation("challenges.gui.descriptions.admin.remove-selected"), lineLength));
builder.icon(Material.LAVA_BUCKET);
builder.clickHandler((panel, user1, clickType, slot) -> {
this.materialMap.keySet().removeAll(this.selectedMaterials);
this.materialList.removeAll(this.selectedMaterials);
this.build();
return true;
});
break;
}
return builder.build();
}
/**
* This method creates button for given material.
* @param material material which button must be created.
* @return new Button for material.
*/
private PanelItem createElementButton(Material material)
{
return new PanelItemBuilder().
name(WordUtils.capitalize(material.name().toLowerCase().replace("_", " "))).
icon(GuiUtils.getMaterialItem(material, this.materialMap.get(material))).
description(this.selectedMaterials.contains(material) ?
this.user.getTranslation("challenges.gui.descriptions.admin.selected") : "").
clickHandler((panel, user1, clickType, slot) -> {
// On right click change which entities are selected for deletion.
if (clickType.isRightClick())
{
if (!this.selectedMaterials.add(material))
{
// Remove material if it is already selected
this.selectedMaterials.remove(material);
}
this.build();
}
else
{
new NumberGUI(this.user,
this.materialMap.get(material),
1,
this.addon.getChallengesSettings().getLoreLineLength(),
(status, value) -> {
if (status)
{
// Update value only when something changes.
this.materialMap.put(material, value);
}
this.build();
});
}
return true;
}).
glow(this.selectedMaterials.contains(material)).
build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Functional buttons in current GUI.
*/
private enum Button
{
ADD,
REMOVE
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Contains selected materials.
*/
private Set<Material> selectedMaterials;
/**
* List of materials to avoid order issues.
*/
private List<Material> materialList;
/**
* List of required materials.
*/
private Map<Material, Integer> materialMap;
}

View File

@ -0,0 +1,282 @@
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.Map;
import java.util.Set;
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;
import world.bentobox.challenges.panel.CommonPagedPanel;
import world.bentobox.challenges.panel.CommonPanel;
import world.bentobox.challenges.panel.ConversationUtils;
import world.bentobox.challenges.panel.util.MultiBlockSelector;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
/**
* This class allows to edit material that are in required material map.
*/
public class ManageBlocksPanel extends CommonPagedPanel
{
private ManageBlocksPanel(CommonPanel parentGUI, Map<Material, Integer> materialMap)
{
super(parentGUI);
this.materialMap = materialMap;
this.materialList = new ArrayList<>(this.materialMap.keySet());
// Sort materials by their ordinal value.
this.materialList.sort(Comparator.comparing(Enum::ordinal));
this.selectedMaterials = new HashSet<>();
}
/**
* Open the Challenges Admin GUI.
*/
public static void open(CommonPanel parentGUI, Map<Material, Integer> materialMap)
{
new ManageBlocksPanel(parentGUI, materialMap).build();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation(Constants.TITLE + "manage-blocks"));
// Create nice border.
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(3, this.createButton(Button.ADD_BLOCK));
panelBuilder.item(5, this.createButton(Button.REMOVE_BLOCK));
this.populateElements(panelBuilder,
this.materialList,
o -> this.createElementButton((Material) o));
// 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 -> {
icon = new ItemStack(Material.BUCKET);
clickHandler = (panel, user1, clickType, slot) ->
{
MultiBlockSelector.open(this.user,
MultiBlockSelector.Mode.BLOCKS,
new HashSet<>(this.materialList),
(status, materials) ->
{
if (status)
{
materials.forEach(material ->
{
this.materialMap.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 -> {
if (!this.selectedMaterials.isEmpty())
{
description.add(this.user.getTranslation(reference + "title"));
this.selectedMaterials.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.selectedMaterials.isEmpty())
{
this.materialMap.keySet().removeAll(this.selectedMaterials);
this.materialList.removeAll(this.selectedMaterials);
this.selectedMaterials.clear();
this.build();
}
return true;
};
glow = !this.selectedMaterials.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 material material which button must be created.
* @return new Button for material.
*/
private PanelItem createElementButton(Material material)
{
final String reference = Constants.BUTTON + "material.";
List<String> description = new ArrayList<>();
if (this.selectedMaterials.contains(material))
{
description.add(this.user.getTranslation(reference + "selected"));
}
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-choose"));
if (this.selectedMaterials.contains(material))
{
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", "[material]",
Utils.prettifyObject(material, this.user))).
icon(GuiUtils.getMaterialItem(material, this.materialMap.get(material))).
description(description).
clickHandler((panel, user1, clickType, slot) -> {
// On right click change which entities are selected for deletion.
if (clickType.isRightClick())
{
if (!this.selectedMaterials.add(material))
{
// Remove material if it is already selected
this.selectedMaterials.remove(material);
}
this.build();
}
else
{
Consumer<Number> numberConsumer = number -> {
if (number != null)
{
this.materialMap.put(material, 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.selectedMaterials.contains(material)).
build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Functional buttons in current GUI.
*/
private enum Button
{
ADD_BLOCK,
REMOVE_BLOCK
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* Contains selected materials.
*/
private final Set<Material> selectedMaterials;
/**
* List of materials to avoid order issues.
*/
private final List<Material> materialList;
/**
* List of required materials.
*/
private final Map<Material, Integer> materialMap;
}

View File

@ -1,258 +0,0 @@
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.Map;
import java.util.Set;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
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.ChallengesAddon;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.panel.util.NumberGUI;
import world.bentobox.challenges.panel.util.SelectEntityGUI;
import world.bentobox.challenges.utils.GuiUtils;
/**
* This class allows to edit entities that are in required entities map.
*/
public class ManageEntitiesGUI extends CommonGUI
{
public ManageEntitiesGUI(ChallengesAddon addon,
World world,
User user,
Map<EntityType, Integer> requiredEntities,
String topLabel,
String permissionPrefix,
CommonGUI parentGUI)
{
super(addon, world, user, topLabel, permissionPrefix, parentGUI);
this.requiredEntities = requiredEntities;
this.entityList = new ArrayList<>(this.requiredEntities.keySet());
this.entityList.sort(Comparator.comparing(Enum::name));
this.selectedEntities = new HashSet<>(EntityType.values().length);
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation("challenges.gui.title.admin.manage-entities"));
// create border
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(3, this.createButton(Button.ADD));
panelBuilder.item(5, this.createButton(Button.REMOVE));
panelBuilder.item(8, this.createButton(Button.SWITCH));
final int MAX_ELEMENTS = 21;
if (this.pageIndex < 0)
{
this.pageIndex = this.entityList.size() / MAX_ELEMENTS;
}
else if (this.pageIndex > (this.entityList.size() / MAX_ELEMENTS))
{
this.pageIndex = 0;
}
int entitiesIndex = MAX_ELEMENTS * this.pageIndex;
// I want first row to be only for navigation and return button.
int index = 10;
while (entitiesIndex < ((this.pageIndex + 1) * MAX_ELEMENTS) &&
entitiesIndex < this.entityList.size() &&
index < 26)
{
if (!panelBuilder.slotOccupied(index))
{
panelBuilder.item(index, this.createEntityButton(this.entityList.get(entitiesIndex++)));
}
index++;
}
// Navigation buttons only if necessary
if (this.entityList.size() > MAX_ELEMENTS)
{
panelBuilder.item(18, this.getButton(CommonButtons.PREVIOUS));
panelBuilder.item(26, this.getButton(CommonButtons.NEXT));
}
// 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)
{
int lineLength = this.addon.getChallengesSettings().getLoreLineLength();
PanelItemBuilder builder = new PanelItemBuilder();
switch (button)
{
case ADD:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.add"));
builder.icon(Material.BUCKET);
builder.clickHandler((panel, user1, clickType, slot) -> {
new SelectEntityGUI(this.user, this.requiredEntities.keySet(), this.asEggs, (status, entities) -> {
if (status)
{
entities.forEach(entity -> {
this.requiredEntities.put(entity, 1);
this.entityList.add(entity);
});
}
this.build();
});
return true;
});
break;
case REMOVE:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.remove-selected"));
builder.description(GuiUtils.stringSplit(this.user.getTranslation("challenges.gui.descriptions.admin.remove-selected"), lineLength));
builder.icon(Material.LAVA_BUCKET);
builder.clickHandler((panel, user1, clickType, slot) -> {
this.requiredEntities.keySet().removeAll(this.selectedEntities);
this.entityList.removeAll(this.selectedEntities);
this.build();
return true;
});
break;
case SWITCH:
builder.name(this.user.getTranslation("challenges.gui.buttons.admin.show-eggs"));
builder.description(GuiUtils.stringSplit(this.user.getTranslation("challenges.gui.descriptions.admin.show-eggs"), lineLength));
builder.icon(this.asEggs ? Material.EGG : Material.PLAYER_HEAD);
builder.clickHandler((panel, user1, clickType, slot) -> {
this.asEggs = !this.asEggs;
this.build();
return true;
});
break;
}
return builder.build();
}
/**
* This method creates button for given entity.
* @param entity Entity which button must be created.
* @return new Button for entity.
*/
private PanelItem createEntityButton(EntityType entity)
{
return new PanelItemBuilder().
name(WordUtils.capitalize(entity.name().toLowerCase().replace("_", " "))).
description(this.selectedEntities.contains(entity) ?
this.user.getTranslation("challenges.gui.descriptions.admin.selected") : "").
icon(this.asEggs ?
GuiUtils.getEntityEgg(entity, this.requiredEntities.get(entity)) :
GuiUtils.getEntityHead(entity, this.requiredEntities.get(entity))).
clickHandler((panel, user1, clickType, slot) -> {
// On right click change which entities are selected for deletion.
if (clickType.isRightClick())
{
if (!this.selectedEntities.add(entity))
{
// Remove entity if it is already selected
this.selectedEntities.remove(entity);
}
this.build();
}
else
{
new NumberGUI(this.user,
this.requiredEntities.get(entity),
1,
this.addon.getChallengesSettings().getLoreLineLength(),
(status, value) -> {
if (status)
{
// Update value only when something changes.
this.requiredEntities.put(entity, value);
}
this.build();
});
}
return true;
}).
glow(this.selectedEntities.contains(entity)).
build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Functional buttons in current GUI.
*/
private enum Button
{
ADD,
REMOVE,
SWITCH
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with entities to avoid list irregularities.
*/
private List<EntityType> entityList;
/**
* Set with entities that are selected.
*/
private Set<EntityType> selectedEntities;
/**
* Map that contains all entities and their cound.
*/
private Map<EntityType, Integer> requiredEntities;
/**
* Boolean indicate if entities should be displayed as eggs or mob heads.
*/
private boolean asEggs;
}

View File

@ -0,0 +1,302 @@
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.Map;
import java.util.Set;
import java.util.function.Consumer;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
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;
import world.bentobox.challenges.panel.CommonPagedPanel;
import world.bentobox.challenges.panel.CommonPanel;
import world.bentobox.challenges.panel.ConversationUtils;
import world.bentobox.challenges.panel.util.MultiEntitySelector;
import world.bentobox.challenges.utils.Constants;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.Utils;
/**
* This class allows to edit entities that are in required entities map.
*/
public class ManageEntitiesPanel extends CommonPagedPanel
{
private ManageEntitiesPanel(CommonPanel parentGUI, Map<EntityType, Integer> requiredEntities)
{
super(parentGUI);
this.requiredEntities = requiredEntities;
this.entityList = new ArrayList<>(this.requiredEntities.keySet());
this.entityList.sort(Comparator.comparing(Enum::name));
this.selectedEntities = new HashSet<>(EntityType.values().length);
}
/**
* Open the Challenges Admin GUI.
*/
public static void open(CommonPanel parentGUI, Map<EntityType, Integer> requiredEntities)
{
new ManageEntitiesPanel(parentGUI, requiredEntities).build();
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation(Constants.TITLE + "manage-entities"));
// create border
GuiUtils.fillBorder(panelBuilder);
panelBuilder.item(3, this.createButton(Button.ADD_ENTITY));
panelBuilder.item(5, this.createButton(Button.REMOVE_ENTITY));
panelBuilder.item(8, this.createButton(Button.SWITCH_ENTITY));
this.populateElements(panelBuilder,
this.entityList,
o -> this.createEntityButton((EntityType) o));
// 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 -> {
icon = new ItemStack(Material.BUCKET);
clickHandler = (panel, user1, clickType, slot) -> {
MultiEntitySelector.open(this.user,
this.asEggs,
MultiEntitySelector.Mode.ALIVE,
this.requiredEntities.keySet(),
(status, entities) -> {
if (status)
{
entities.forEach(entity -> {
this.requiredEntities.put(entity, 1);
this.entityList.add(entity);
});
}
this.build();
});
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-add"));
}
case REMOVE_ENTITY -> {
if (!this.selectedEntities.isEmpty())
{
description.add(this.user.getTranslation(reference + "title"));
this.selectedEntities.forEach(entity -> {
description.add(this.user.getTranslation(reference + "entity",
"[entity]", Utils.prettifyObject(entity, this.user)));
});
}
icon = new ItemStack(Material.LAVA_BUCKET);
clickHandler = (panel, user1, clickType, slot) ->
{
if (!this.selectedEntities.isEmpty())
{
this.requiredEntities.keySet().removeAll(this.selectedEntities);
this.entityList.removeAll(this.selectedEntities);
this.selectedEntities.clear();
this.build();
}
return true;
};
glow = !this.entityList.isEmpty();
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-remove"));
}
case SWITCH_ENTITY -> {
icon = new ItemStack(this.asEggs ? Material.EGG : Material.PLAYER_HEAD);
clickHandler = (panel, user1, clickType, slot) -> {
this.asEggs = !this.asEggs;
this.build();
return true;
};
glow = false;
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "click-to-toggle"));
}
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 entity.
* @param entity Entity which button must be created.
* @return new Button for entity.
*/
private PanelItem createEntityButton(EntityType entity)
{
final String reference = Constants.BUTTON + "entity.";
List<String> description = new ArrayList<>();
if (this.selectedEntities.contains(entity))
{
description.add(this.user.getTranslation(reference + "selected"));
}
description.add("");
description.add(this.user.getTranslation(Constants.TIPS + "left-click-to-choose"));
if (this.selectedEntities.contains(entity))
{
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", "[entity]",
Utils.prettifyObject(entity, this.user))).
icon(this.asEggs ?
GuiUtils.getEntityEgg(entity, this.requiredEntities.get(entity)) :
GuiUtils.getEntityHead(entity, this.requiredEntities.get(entity))).
description(description).
clickHandler((panel, user1, clickType, slot) -> {
// On right click change which entities are selected for deletion.
if (clickType.isRightClick())
{
if (!this.selectedEntities.add(entity))
{
// Remove entity if it is already selected
this.selectedEntities.remove(entity);
}
this.build();
}
else
{
Consumer<Number> numberConsumer = number -> {
if (number != null)
{
this.requiredEntities.put(entity, 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.selectedEntities.contains(entity)).
build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* Functional buttons in current GUI.
*/
private enum Button
{
ADD_ENTITY,
REMOVE_ENTITY,
SWITCH_ENTITY
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* List with entities to avoid list irregularities.
*/
private final List<EntityType> entityList;
/**
* Set with entities that are selected.
*/
private final Set<EntityType> selectedEntities;
/**
* Map that contains all entities and their cound.
*/
private final Map<EntityType, Integer> requiredEntities;
/**
* Boolean indicate if entities should be displayed as eggs or mob heads.
*/
private boolean asEggs;
}

View File

@ -1,528 +0,0 @@
package world.bentobox.challenges.panel.user;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.World;
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;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.challenges.ChallengesAddon;
import world.bentobox.challenges.managers.ChallengesManager;
import world.bentobox.challenges.config.SettingsUtils.VisibilityMode;
import world.bentobox.challenges.database.object.Challenge;
import world.bentobox.challenges.panel.CommonGUI;
import world.bentobox.challenges.tasks.TryToComplete;
import world.bentobox.challenges.utils.GuiUtils;
import world.bentobox.challenges.utils.LevelStatus;
/**
* This is UserGUI class. It contains everything necessary for user to use it.
*/
public class ChallengesGUI extends CommonGUI
{
// ---------------------------------------------------------------------
// Section: Constructors
// ---------------------------------------------------------------------
/**
* Default constructor that inits panels with minimal requirements, without parent panel.
*
* @param addon Addon where panel operates.
* @param world World from which panel was created.
* @param user User who created panel.
* @param topLabel Command top label which creates panel (f.e. island or ai)
* @param permissionPrefix Command permission prefix (f.e. bskyblock.)
*/
public ChallengesGUI(ChallengesAddon addon,
World world,
User user,
String topLabel,
String permissionPrefix)
{
super(addon, world, user, topLabel, permissionPrefix);
this.challengesManager = this.addon.getChallengesManager();
this.levelStatusList = this.challengesManager.getAllChallengeLevelStatus(this.user, this.world);
for (LevelStatus levelStatus : this.levelStatusList)
{
if (levelStatus.isUnlocked())
{
this.lastSelectedLevel = levelStatus;
}
else
{
break;
}
}
this.containsChallenges = this.challengesManager.hasAnyChallengeData(this.world);
}
// ---------------------------------------------------------------------
// Section: Methods
// ---------------------------------------------------------------------
/**
* This method builds all necessary elements in GUI panel.
*/
@Override
public void build()
{
// Do not open gui if there is no challenges.
if (!this.containsChallenges)
{
this.addon.logError("There are no challenges set up!");
this.user.sendMessage("challenges.errors.no-challenges");
return;
}
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation("challenges.gui.title.challenges"));
// TODO: get last completed level.
int nextItemIndex = 0;
if (this.addon.getChallengesSettings().isFreeChallengesFirst())
{
this.addFreeChallenges(panelBuilder, nextItemIndex);
// Start new row for challenges.
if (panelBuilder.nextSlot() % 9 != 0)
{
nextItemIndex = panelBuilder.nextSlot() - panelBuilder.nextSlot() % 9 + 9;
}
else
{
nextItemIndex = panelBuilder.nextSlot();
}
}
this.addChallenges(panelBuilder, nextItemIndex);
// Start new row for levels.
// Start new row for challenges.
if (panelBuilder.nextSlot() % 9 != 0)
{
nextItemIndex = panelBuilder.nextSlot() - panelBuilder.nextSlot() % 9 + 9;
}
else
{
nextItemIndex = panelBuilder.nextSlot();
}
this.addChallengeLevels(panelBuilder, nextItemIndex);
if (!this.addon.getChallengesSettings().isFreeChallengesFirst())
{
// Start new row for free challenges.
if (panelBuilder.nextSlot() % 9 != 0)
{
nextItemIndex = panelBuilder.nextSlot() - panelBuilder.nextSlot() % 9 + 9;
}
else
{
nextItemIndex = panelBuilder.nextSlot();
}
this.addFreeChallenges(panelBuilder, nextItemIndex);
}
panelBuilder.build();
}
/**
* This method adds free challenges to panelBuilder.
* @param panelBuilder where free challenges must be added.
* @param firstItemIndex index of first element.
*/
private void addFreeChallenges(PanelBuilder panelBuilder, int firstItemIndex)
{
List<Challenge> freeChallenges = this.challengesManager.getFreeChallenges(this.world);
if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges())
{
freeChallenges.removeIf(challenge -> !challenge.isRepeatable() &&
this.challengesManager.isChallengeComplete(this.user, this.world, challenge));
}
// Remove all undeployed challenges if VisibilityMode is set to Hidden.
if (this.addon.getChallengesSettings().getVisibilityMode().equals(VisibilityMode.HIDDEN))
{
freeChallenges.removeIf(challenge -> !challenge.isDeployed());
}
final int freeChallengesCount = freeChallenges.size();
if (freeChallengesCount > 18)
{
int index = firstItemIndex;
if (this.freeChallengeIndex > 0)
{
panelBuilder.item(index++, new PanelItemBuilder().
icon(Material.OAK_SIGN).
name(this.user.getTranslation("challenges.gui.buttons.previous")).
clickHandler((panel, user1, clickType, slot) -> {
this.freeChallengeIndex--;
this.build();
return true;
}).build());
}
int currentIndex = this.freeChallengeIndex;
while (panelBuilder.nextSlot() != firstItemIndex + 18 && currentIndex < freeChallengesCount)
{
panelBuilder.item(index++, this.getChallengeButton(freeChallenges.get(currentIndex++)));
}
// Check if one challenge is left
if (currentIndex + 1 == freeChallengesCount)
{
panelBuilder.item(index, this.getChallengeButton(freeChallenges.get(currentIndex)));
}
else if (currentIndex < freeChallengesCount)
{
panelBuilder.item(index, new PanelItemBuilder().
icon(Material.OAK_SIGN).
name(this.user.getTranslation("challenges.gui.buttons.next")).
clickHandler((panel, user1, clickType, slot) -> {
this.freeChallengeIndex++;
this.build();
return true;
}).build());
}
}
else
{
for (Challenge challenge : freeChallenges)
{
// there are no limitations. Just bunch insert.
panelBuilder.item(firstItemIndex++, this.getChallengeButton(challenge));
}
}
}
/**
* This method adds last selected level challenges to panelBuilder.
* @param panelBuilder where last selected level challenges must be added.
* @param firstItemIndex index of first element.
*/
private void addChallenges(PanelBuilder panelBuilder, int firstItemIndex)
{
if (this.lastSelectedLevel != null)
{
List<Challenge> challenges = this.challengesManager.getLevelChallenges(this.lastSelectedLevel.getLevel());
if (this.addon.getChallengesSettings().isRemoveCompleteOneTimeChallenges())
{
challenges.removeIf(challenge -> !challenge.isRepeatable() &&
this.challengesManager.isChallengeComplete(this.user, this.world, challenge));
}
// Remove all undeployed challenges if VisibilityMode is set to Hidden.
if (this.addon.getChallengesSettings().getVisibilityMode().equals(VisibilityMode.HIDDEN))
{
challenges.removeIf(challenge -> !challenge.isDeployed());
}
final int challengesCount = challenges.size();
if (challengesCount > 18)
{
int index = firstItemIndex;
if (this.pageIndex > 0)
{
panelBuilder.item(index++, new PanelItemBuilder().
icon(Material.OAK_SIGN).
name(this.user.getTranslation("challenges.gui.buttons.previous")).
clickHandler((panel, user1, clickType, slot) -> {
this.pageIndex--;
this.build();
return true;
}).build());
}
int currentIndex = this.pageIndex;
while (panelBuilder.nextSlot() != firstItemIndex + 18 && currentIndex < challengesCount)
{
panelBuilder.item(index++, this.getChallengeButton(challenges.get(currentIndex++)));
}
// Check if one challenge is left
if (currentIndex + 1 == challengesCount)
{
panelBuilder.item(index, this.getChallengeButton(challenges.get(currentIndex)));
}
else if (currentIndex < challengesCount)
{
panelBuilder.item(index, new PanelItemBuilder().
icon(Material.OAK_SIGN).
name(this.user.getTranslation("challenges.gui.buttons.next")).
clickHandler((panel, user1, clickType, slot) -> {
this.pageIndex++;
this.build();
return true;
}).build());
}
}
else
{
for (Challenge challenge : challenges)
{
// there are no limitations. Just bunch insert.
panelBuilder.item(firstItemIndex++, this.getChallengeButton(challenge));
}
}
}
}
/**
* This method adds challenge levels to panelBuilder.
* @param panelBuilder where challenge levels must be added.
* @param firstItemIndex index of first element.
*/
private void addChallengeLevels(PanelBuilder panelBuilder, int firstItemIndex)
{
final int levelCounts = this.levelStatusList.size();
if (levelCounts > 9)
{
int index = firstItemIndex;
if (this.levelIndex > 0)
{
panelBuilder.item(index++, new PanelItemBuilder().
icon(Material.OAK_SIGN).
name(this.user.getTranslation("challenges.gui.buttons.previous")).
clickHandler((panel, user1, clickType, slot) -> {
this.levelIndex--;
this.build();
return true;
}).build());
}
int currentIndex = this.levelIndex;
while (panelBuilder.nextSlot() != firstItemIndex + 9 && currentIndex < levelCounts)
{
panelBuilder.item(index++, this.getLevelButton(this.levelStatusList.get(currentIndex++)));
}
// Check if one challenge is left
if (currentIndex + 1 == levelCounts)
{
panelBuilder.item(index, this.getLevelButton(this.levelStatusList.get(currentIndex)));
}
else if (currentIndex < levelCounts)
{
panelBuilder.item(index, new PanelItemBuilder().
icon(Material.OAK_SIGN).
name(this.user.getTranslation("challenges.gui.buttons.next")).
clickHandler((panel, user1, clickType, slot) -> {
this.levelIndex++;
this.build();
return true;
}).build());
}
}
else
{
for (LevelStatus level : this.levelStatusList)
{
// there are no limitations. Just bunch insert.
panelBuilder.item(firstItemIndex++, this.getLevelButton(level));
}
}
}
// ---------------------------------------------------------------------
// Section: Icon building
// ---------------------------------------------------------------------
/**
* This method creates given challenges icon that on press tries to complete it.
* @param challenge which icon must be constructed.
* @return PanelItem icon for challenge.
*/
private PanelItem getChallengeButton(Challenge challenge)
{
return new PanelItemBuilder().
icon(challenge.getIcon()).
name(challenge.getFriendlyName().isEmpty() ?
challenge.getUniqueId() :
ChatColor.translateAlternateColorCodes('&', challenge.getFriendlyName())).
description(GuiUtils.stringSplit(this.generateChallengeDescription(challenge, this.user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength())).
clickHandler((panel, user1, clickType, slot) -> {
// Add ability to input how many repeats player should do.
// Do not open if challenge is not repeatable.
if (clickType.isRightClick() &&
challenge.isRepeatable() &&
this.user.hasPermission(this.permissionPrefix + "challenges.multiple"))
{
new MultipleGUI(this.user,
this.addon.getChallengesSettings().getLoreLineLength(),
value -> {
TryToComplete.complete(this.addon,
this.user,
challenge,
this.world,
this.topLabel,
this.permissionPrefix,
value);
this.build();
});
}
else
{
if (TryToComplete.complete(this.addon,
this.user,
challenge,
this.world,
this.topLabel,
this.permissionPrefix))
{
panel.getInventory().setItem(slot, this.getChallengeButton(challenge).getItem());
}
}
return true;
}).
glow(this.addon.getChallengesSettings().isAddCompletedGlow() &&
this.challengesManager.isChallengeComplete(this.user, this.world, challenge)).
build();
}
/**
* This method creates button for given level.
* @param level which button must be created.
* @return Button for given level.
*/
private PanelItem getLevelButton(LevelStatus level)
{
// Create a nice name for the level
String name = level.getLevel().getFriendlyName().isEmpty() ?
level.getLevel().getUniqueId() :
level.getLevel().getFriendlyName();
ItemStack icon;
List<String> description;
PanelItem.ClickHandler clickHandler;
boolean glow;
if (level == this.lastSelectedLevel)
{
icon = level.getLevel().getIcon();
description = GuiUtils.stringSplit(
this.generateLevelDescription(level.getLevel(), user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength());
clickHandler = null;
glow = true;
}
else if (level.isUnlocked())
{
icon = level.getLevel().getIcon();
description = GuiUtils.stringSplit(
this.generateLevelDescription(level.getLevel(), user.getPlayer()),
this.addon.getChallengesSettings().getLoreLineLength());
clickHandler = (panel, user1, clickType, slot) -> {
this.lastSelectedLevel = level;
// Reset page index for challenges.
this.pageIndex = 0;
this.build();
return true;
};
glow = this.addon.getChallengesSettings().isAddCompletedGlow() &&
this.challengesManager.isLevelCompleted(this.user, this.world, level.getLevel());
}
else
{
if (level.getLevel().getLockedIcon() != null)
{
// Clone will prevent issues with description storing.
// It can be done only here as it can be null.
icon = level.getLevel().getLockedIcon().clone();
}
else
{
icon = this.addon.getChallengesSettings().getLockedLevelIcon();
}
description = GuiUtils.stringSplit(
this.user.getTranslation("challenges.gui.descriptions.level-locked",
"[count]", Integer.toString(level.getNumberOfChallengesStillToDo()),
"[level]", level.getPreviousLevel().getFriendlyName()),
this.addon.getChallengesSettings().getLoreLineLength());
clickHandler = null;
glow = false;
}
return new PanelItemBuilder().
icon(icon).
name(ChatColor.translateAlternateColorCodes('&', name)).
description(description).
glow(glow).
clickHandler(clickHandler).
build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This will be used if free challenges are more then 18.
*/
private int freeChallengeIndex = 0;
/**
* This will be used if levels are more then 9.
*/
private int levelIndex;
/**
* This list contains all information about level completion in current world.
*/
private List<LevelStatus> levelStatusList;
/**
* This indicate last selected level.
*/
private LevelStatus lastSelectedLevel;
/**
* Challenge Manager object.
*/
private ChallengesManager challengesManager;
/**
* This boolean indicates if in the world there exist challenges for displaying in GUI.
*/
private final boolean containsChallenges;
}

View File

@ -1,215 +0,0 @@
package world.bentobox.challenges.panel.user;
import java.util.function.Consumer;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import world.bentobox.bentobox.api.panels.Panel;
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.GuiUtils;
/**
* This GUI will pop out when user uses right click on challenge. It is meant to choose
* how many times player will complete challenges.
*/
public class MultipleGUI
{
/**
* Default constructor.
* @param user User who opens gui.
* @param lineLength Length of lore message.
* @param action Action that will be performed on value clicking.
*/
public MultipleGUI(User user, int lineLength, Consumer<Integer> action)
{
this.user = user;
this.lineLength = lineLength;
this.action = action;
this.build();
}
/**
* This method builds panel that allows to change given number value.
*/
private void build()
{
PanelBuilder panelBuilder = new PanelBuilder().
user(this.user).
type(Panel.Type.HOPPER).
name(this.user.getTranslation("challenges.gui.title.multiple-complete"));
panelBuilder.item(2, this.getButton(Button.VALUE));
// Reduce
panelBuilder.item(0, this.getButton(Button.REDUCE_LOT));
panelBuilder.item(1, this.getButton(Button.REDUCE));
// Increase
panelBuilder.item(3, this.getButton(Button.INCREASE));
panelBuilder.item(4, this.getButton(Button.INCREASE_LOT));
panelBuilder.build();
}
/**
* This method creates PanelItem with required functionality.
* @param button Functionality requirement.
* @return PanelItem with functionality.
*/
private PanelItem getButton(Button button)
{
ItemStack icon;
String name;
String description;
PanelItem.ClickHandler clickHandler;
boolean glow;
switch (button)
{
case VALUE:
{
name = this.user.getTranslation("challenges.gui.buttons.value");
description = this.user.getTranslation("challenges.gui.descriptions.current-value", "[value]", Integer.toString(this.value));
icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.action.accept(this.value);
return true;
};
glow = false;
break;
}
case INCREASE:
{
name = this.user.getTranslation("challenges.gui.buttons.increase");
description = this.user.getTranslation("challenges.gui.descriptions.increase-by", "[value]", "1");
icon = new ItemStack(Material.BLUE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.value++;
// Necessary just to update second item
panel.getInventory().setItem(2, this.getButton(Button.VALUE).getItem());
return true;
};
glow = false;
break;
}
case INCREASE_LOT:
{
name = this.user.getTranslation("challenges.gui.buttons.increase");
description = this.user.getTranslation("challenges.gui.descriptions.increase-by", "[value]", "5");
icon = new ItemStack(Material.MAGENTA_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.value += 5;
// Necessary just to update second item
panel.getInventory().setItem(2, this.getButton(Button.VALUE).getItem());
return true;
};
glow = false;
break;
}
case REDUCE:
{
name = this.user.getTranslation("challenges.gui.buttons.reduce");
description = this.user.getTranslation("challenges.gui.descriptions.reduce-by", "[value]", "1");
icon = new ItemStack(Material.ORANGE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.value--;
if (this.value < 1)
{
this.value = 1;
}
// Necessary just to update second item
panel.getInventory().setItem(2, this.getButton(Button.VALUE).getItem());
return true;
};
glow = false;
break;
}
case REDUCE_LOT:
{
name = this.user.getTranslation("challenges.gui.buttons.reduce");
description = this.user.getTranslation("challenges.gui.descriptions.reduce-by", "[value]", "5");
icon = new ItemStack(Material.RED_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.value -= 5;
if (this.value < 1)
{
this.value = 1;
}
// Necessary just to update second item
panel.getInventory().setItem(2, this.getButton(Button.VALUE).getItem());
return true;
};
glow = false;
break;
}
default:
return null;
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(GuiUtils.stringSplit(description, this.lineLength)).
glow(glow).
clickHandler(clickHandler).
build();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum allows to easier define available buttons.
*/
enum Button
{
VALUE,
REDUCE,
REDUCE_LOT,
INCREASE,
INCREASE_LOT
}
// ---------------------------------------------------------------------
// Section: Instance variables
// ---------------------------------------------------------------------
/**
* This variable allows to access to user object.
*/
private User user;
/**
* This variable holds action that will be performed on accept.
*/
private Consumer<Integer> action;
/**
* This variable holds a number of characters in single line for lore message.
*/
private int lineLength;
/**
* This integer holds current value of completion count.
*/
private int value = 1;
}

View File

@ -1,114 +0,0 @@
package world.bentobox.challenges.panel.util;
import java.util.function.Consumer;
import org.bukkit.Material;
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.GuiUtils;
/**
* This GUI is used to confirm that user wants to run command, that should be created from
* command string list.
*/
public class ConfirmationGUI
{
/**
* This constructor inits and opens ConfirmationGUI.
*
* @param user Gui Caller.
*/
public ConfirmationGUI(User user, Consumer<Boolean> consumer)
{
this.user = user;
this.consumer = consumer;
this.build();
}
/**
* This method builds confirmation panel with 2 buttons.
*/
public void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.confirm-title"));
GuiUtils.fillBorder(panelBuilder, Material.BLUE_STAINED_GLASS_PANE);
// Accept buttons
panelBuilder.item(10, this.getButton(true));
panelBuilder.item(11, this.getButton(true));
panelBuilder.item(12, this.getButton(true));
panelBuilder.item(19, this.getButton(true));
panelBuilder.item(20, this.getButton(true));
panelBuilder.item(21, this.getButton(true));
panelBuilder.item(28, this.getButton(true));
panelBuilder.item(29, this.getButton(true));
panelBuilder.item(30, this.getButton(true));
// Cancel Buttons
panelBuilder.item(14, this.getButton(false));
panelBuilder.item(15, this.getButton(false));
panelBuilder.item(16, this.getButton(false));
panelBuilder.item(23, this.getButton(false));
panelBuilder.item(24, this.getButton(false));
panelBuilder.item(25, this.getButton(false));
panelBuilder.item(32, this.getButton(false));
panelBuilder.item(33, this.getButton(false));
panelBuilder.item(34, this.getButton(false));
panelBuilder.item(44,
new PanelItemBuilder().
icon(Material.OAK_DOOR).
name(this.user.getTranslation("challenges.gui.buttons.return")).
clickHandler( (panel, user1, clickType, slot) -> {
this.consumer.accept(false);
return true;
}).build());
panelBuilder.build();
}
/**
* This method creates button with requested value.
* @param returnValue requested value
* @return PanelItem button.
*/
private PanelItem getButton(boolean returnValue)
{
return new PanelItemBuilder().
name(this.user.getTranslation("challenges.gui.buttons.admin." + (returnValue ? "accept" : "cancel"))).
icon(returnValue ? Material.GREEN_STAINED_GLASS_PANE : Material.RED_STAINED_GLASS_PANE).
clickHandler((panel, user1, clickType, i) -> {
this.consumer.accept(returnValue);
return true;
}).
build();
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* User who wants to run command.
*/
private User user;
/**
* Stores current Consumer
*/
private Consumer<Boolean> consumer;
}

View File

@ -1,559 +0,0 @@
package world.bentobox.challenges.panel.util;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.bukkit.Material;
import org.bukkit.conversations.Conversation;
import org.bukkit.conversations.ConversationContext;
import org.bukkit.conversations.ConversationFactory;
import org.bukkit.conversations.NumericPrompt;
import org.bukkit.conversations.Prompt;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
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.GuiUtils;
/**
* This gui allows to change current number and returns it to previous GUI
*/
public class NumberGUI
{
public NumberGUI(User user, int value, int lineLength, BiConsumer<Boolean, Integer> consumer)
{
this(user, value, Integer.MIN_VALUE, Integer.MAX_VALUE, lineLength, consumer);
}
public NumberGUI(User user, int value, int minValue, int lineLength, BiConsumer<Boolean, Integer> consumer)
{
this(user, value, minValue, Integer.MAX_VALUE, lineLength, consumer);
}
public NumberGUI(User user, int value, int minValue, int maxValue, int lineLength, BiConsumer<Boolean, Integer> consumer)
{
this.user = user;
this.value = value;
this.consumer = consumer;
this.minValue = minValue;
this.maxValue = maxValue;
this.currentOperation = Button.SET;
this.lineLength = lineLength;
this.build();
}
/**
* This method builds panel that allows to change given number value.
*/
private void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).name(this.user.getTranslation("challenges.gui.title.admin.manage-numbers"));
GuiUtils.fillBorder(panelBuilder);
// Others
panelBuilder.item(1, this.getButton(Button.SAVE));
panelBuilder.item(19, this.getButton(Button.VALUE));
panelBuilder.item(44, this.getButton(Button.CANCEL));
panelBuilder.item(2, this.getButton(Button.INPUT));
// operations
panelBuilder.item(3, this.getButton(Button.SET));
panelBuilder.item(4, this.getButton(Button.INCREASE));
panelBuilder.item(5, this.getButton(Button.REDUCE));
panelBuilder.item(6, this.getButton(Button.MULTIPLY));
// Numbers
panelBuilder.item(11, this.createNumberButton(1));
panelBuilder.item(12, this.createNumberButton(10));
panelBuilder.item(13, this.createNumberButton(100));
panelBuilder.item(14, this.createNumberButton(1000));
panelBuilder.item(15, this.createNumberButton(10000));
panelBuilder.item(20, this.createNumberButton(2));
panelBuilder.item(21, this.createNumberButton(20));
panelBuilder.item(22, this.createNumberButton(200));
panelBuilder.item(23, this.createNumberButton(2000));
panelBuilder.item(24, this.createNumberButton(20000));
panelBuilder.item(29, this.createNumberButton(5));
panelBuilder.item(30, this.createNumberButton(50));
panelBuilder.item(31, this.createNumberButton(500));
panelBuilder.item(32, this.createNumberButton(5000));
panelBuilder.item(33, this.createNumberButton(50000));
panelBuilder.build();
}
/**
* This method creates PanelItem with required functionality.
* @param button Functionality requirement.
* @return PanelItem with functionality.
*/
private PanelItem getButton(Button button)
{
ItemStack icon;
String name;
String description;
PanelItem.ClickHandler clickHandler;
boolean glow;
switch (button)
{
case SAVE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.save");
description = this.user.getTranslation("challenges.gui.descriptions.admin.save");
icon = new ItemStack(Material.COMMAND_BLOCK);
clickHandler = (panel, user, clickType, slot) -> {
this.consumer.accept(true, this.value);
return true;
};
glow = false;
break;
}
case CANCEL:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.cancel");
description = this.user.getTranslation("challenges.gui.descriptions.admin.cancel");
icon = new ItemStack(Material.OAK_DOOR);
clickHandler = (panel, user, clickType, slot) -> {
this.consumer.accept(false, this.value);
return true;
};
glow = false;
break;
}
case INPUT:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.input");
description = this.user.getTranslation("challenges.gui.descriptions.admin.input");
icon = new ItemStack(Material.ANVIL);
clickHandler = (panel, user, clickType, slot) -> {
this.getNumberInput(number -> {
if (number != null)
{
// Null value is passed if user write cancel.
this.value = number.intValue();
}
this.build();
},
this.user.getTranslation("challenges.gui.questions.admin.number"));
return true;
};
glow = false;
break;
}
case VALUE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.value");
description = this.user.getTranslation("challenges.gui.descriptions.current-value", "[value]", Integer.toString(this.value));
icon = new ItemStack(Material.PAPER);
clickHandler = (panel, user, clickType, slot) -> true;
glow = false;
break;
}
case SET:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.set");
description = this.user.getTranslation("challenges.gui.descriptions.admin.set");
icon = new ItemStack(Material.WHITE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentOperation = Button.SET;
this.build();
return true;
};
glow = this.currentOperation.equals(Button.SET);
break;
}
case INCREASE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.increase");
description = this.user.getTranslation("challenges.gui.descriptions.admin.increase");
icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentOperation = Button.INCREASE;
this.build();
return true;
};
glow = this.currentOperation.equals(Button.INCREASE);
break;
}
case REDUCE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.reduce");
description = this.user.getTranslation("challenges.gui.descriptions.admin.reduce");
icon = new ItemStack(Material.RED_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentOperation = Button.REDUCE;
this.build();
return true;
};
glow = this.currentOperation.equals(Button.REDUCE);
break;
}
case MULTIPLY:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.multiply");
description = this.user.getTranslation("challenges.gui.descriptions.admin.multiply");
icon = new ItemStack(Material.BLUE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.currentOperation = Button.MULTIPLY;
this.build();
return true;
};
glow = this.currentOperation.equals(Button.MULTIPLY);
break;
}
default:
return null;
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(GuiUtils.stringSplit(description, this.lineLength)).
glow(glow).
clickHandler(clickHandler).
build();
}
/**
* This method creates Number Button based on input number.
* @param number Number which button must be created.
* @return PanelItem that represents number button.
*/
private PanelItem createNumberButton(int number)
{
PanelItemBuilder itemBuilder = new PanelItemBuilder();
switch (this.currentOperation)
{
case SET:
{
itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number)));
itemBuilder.icon(Material.WHITE_STAINED_GLASS_PANE);
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
this.value = number;
if (this.value > this.maxValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.maxValue;
}
if (this.value < this.minValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.minValue;
}
this.build();
return true;
});
break;
}
case INCREASE:
{
itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number)));
itemBuilder.icon(Material.GREEN_STAINED_GLASS_PANE);
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
this.value += number;
if (this.value > this.maxValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.maxValue;
}
this.build();
return true;
});
break;
}
case REDUCE:
{
itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number)));
itemBuilder.icon(Material.RED_STAINED_GLASS_PANE);
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
this.value -= number;
if (this.value < this.minValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.minValue;
}
this.build();
return true;
});
break;
}
case MULTIPLY:
{
itemBuilder.name(this.user.getTranslation("challenges.gui.buttons.admin.number","[number]", Integer.toString(number)));
itemBuilder.icon(Material.BLUE_STAINED_GLASS_PANE);
itemBuilder.clickHandler((panel, user1, clickType, i) -> {
this.value *= number;
if (this.value > this.maxValue)
{
this.user.sendMessage("challenges.errors.not-valid-integer",
"[value]", Integer.toString(this.value),
"[min]", Integer.toString(this.minValue),
"[max]", Integer.toString(this.maxValue));
this.value = this.maxValue;
}
this.build();
return true;
});
break;
}
default:
break;
}
return itemBuilder.build();
}
// ---------------------------------------------------------------------
// Section: Conversation
// ---------------------------------------------------------------------
/**
* This method will close opened gui and writes inputText in chat. After players answers on
* inputText in chat, message will trigger consumer and gui will reopen.
* @param consumer Consumer that accepts player output text.
* @param question Message that will be displayed in chat when player triggers conversion.
*/
private void getNumberInput(Consumer<Number> consumer, @NonNull String question)
{
final User user = this.user;
Conversation conversation =
new ConversationFactory(BentoBox.getInstance()).withFirstPrompt(
new NumericPrompt()
{
/**
* Override this method to perform some action with
* the user's integer response.
*
* @param context Context information about the
* conversation.
* @param input The user's response as a {@link
* Number}.
* @return The next {@link Prompt} in the prompt
* graph.
*/
@Override
protected Prompt acceptValidatedInput(ConversationContext context, Number input)
{
// Add answer to consumer.
consumer.accept(input);
// Reopen GUI
NumberGUI.this.build();
// End conversation
return Prompt.END_OF_CONVERSATION;
}
/**
* Override this method to do further validation on
* the numeric player input after the input has been
* determined to actually be a number.
*
* @param context Context information about the
* conversation.
* @param input The number the player provided.
* @return The validity of the player's input.
*/
@Override
protected boolean isNumberValid(ConversationContext context, Number input)
{
return input.intValue() >= NumberGUI.this.minValue &&
input.intValue() <= NumberGUI.this.maxValue;
}
/**
* Optionally override this method to display an
* additional message if the user enters an invalid
* number.
*
* @param context Context information about the
* conversation.
* @param invalidInput The invalid input provided by
* the user.
* @return A message explaining how to correct the
* input.
*/
@Override
protected String getInputNotNumericText(ConversationContext context,
String invalidInput)
{
return NumberGUI.this.user
.getTranslation("challenges.errors.not-a-integer", "[value]", invalidInput);
}
/**
* Optionally override this method to display an
* additional message if the user enters an invalid
* numeric input.
*
* @param context Context information about the
* conversation.
* @param invalidInput The invalid input provided by
* the user.
* @return A message explaining how to correct the
* input.
*/
@Override
protected String getFailedValidationText(ConversationContext context,
Number invalidInput)
{
return NumberGUI.this.user.getTranslation("challenges.errors.not-valid-integer",
"[value]", invalidInput.toString(),
"[min]", Integer.toString(NumberGUI.this.minValue),
"[max]", Integer.toString(NumberGUI.this.maxValue));
}
/**
* @see Prompt#getPromptText(ConversationContext)
*/
@Override
public String getPromptText(ConversationContext conversationContext)
{
// Close input GUI.
user.closeInventory();
// There are no editable message. Just return question.
return question;
}
}).
withLocalEcho(false).
// On cancel conversation will be closed.
withEscapeSequence("cancel").
// Use null value in consumer to detect if user has abandoned conversation.
addConversationAbandonedListener(abandonedEvent ->
{
if (!abandonedEvent.gracefulExit())
{
consumer.accept(null);
}
}).
withPrefix(context ->
NumberGUI.this.user.getTranslation("challenges.gui.questions.prefix")).
buildConversation(user.getPlayer());
conversation.begin();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum contains all button types.
*/
private enum Button
{
SAVE,
CANCEL,
INPUT,
VALUE,
SET,
INCREASE,
REDUCE,
MULTIPLY
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable stores current GUI consumer.
*/
private BiConsumer<Boolean, Integer> consumer;
/**
* User who runs GUI.
*/
private User user;
/**
* Current value.
*/
private int value;
/**
* Minimal value that is allowed to set.
*/
private int minValue;
/**
* Maximal value that is allowed to set.
*/
private int maxValue;
/**
* This variable holds which operation now is processed.
*/
private Button currentOperation;
/**
* This variable stores how large line can be, before warp it.
*/
private int lineLength;
}

View File

@ -1,366 +0,0 @@
package world.bentobox.challenges.panel.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.bukkit.Material;
import org.bukkit.conversations.Conversation;
import org.bukkit.conversations.ConversationContext;
import org.bukkit.conversations.ConversationFactory;
import org.bukkit.conversations.Prompt;
import org.bukkit.conversations.StringPrompt;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.TextComponent;
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.GuiUtils;
/**
* This GUI allows to edit List of strings. AnvilGUI has limited text space, so splitting
* text in multiple rows allows to edit each row separately.
*/
public class StringListGUI
{
public StringListGUI(User user, String value, int lineLength, BiConsumer<Boolean, List<String>> consumer)
{
this(user, Collections.singleton(value), lineLength, consumer);
}
public StringListGUI(User user, Collection<String> value, int lineLength, BiConsumer<Boolean, List<String>> consumer)
{
this(user, new ArrayList<>(value), lineLength, consumer);
}
public StringListGUI(User user, List<String> value, int lineLength, BiConsumer<Boolean, List<String>> consumer)
{
this.consumer = consumer;
this.user = user;
this.value = value;
this.lineLength = lineLength;
if (this.value.size() > 21)
{
// TODO: throw error that so large list cannot be edited.
this.consumer.accept(false, this.value);
}
else
{
this.build();
}
}
/**
* This method builds panel that allows to change given string value.
*/
private void build()
{
PanelBuilder panelBuilder = new PanelBuilder().user(this.user).
name(this.user.getTranslation("challenges.gui.title.admin.edit-text-fields"));
GuiUtils.fillBorder(panelBuilder, Material.BLACK_STAINED_GLASS_PANE);
panelBuilder.item(1, this.getButton(Button.SAVE));
panelBuilder.item(2, this.getButton(Button.VALUE));
panelBuilder.item(4, this.getButton(Button.ADD));
panelBuilder.item(5, this.getButton(Button.REMOVE));
panelBuilder.item(6, this.getButton(Button.CLEAR));
panelBuilder.item(44, this.getButton(Button.CANCEL));
int slot = 10;
for (int stringIndex = 0; stringIndex < this.value.size() && slot < 36; stringIndex++)
{
if (!panelBuilder.slotOccupied(slot))
{
panelBuilder.item(slot,
this.createStringElement(this.value.get(stringIndex), stringIndex));
}
slot++;
}
panelBuilder.build();
}
/**
* This method create button that does some functionality in current gui.
* @param button Button functionality.
* @return PanelItem.
*/
private PanelItem getButton(Button button)
{
ItemStack icon;
String name;
List<String> description;
PanelItem.ClickHandler clickHandler;
switch (button)
{
case SAVE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.save");
description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.save"));
icon = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.consumer.accept(true, this.value);
return true;
};
break;
}
case CANCEL:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.cancel");
description = Collections.singletonList(this.user.getTranslation("challenges.gui.descriptions.admin.cancel"));
icon = new ItemStack(Material.OAK_DOOR);
clickHandler = (panel, user, clickType, slot) -> {
this.consumer.accept(false, this.value);
return true;
};
break;
}
case VALUE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.value");
description = new ArrayList<>();
description.add(this.user.getTranslation("challenges.gui.descriptions.current-value", "[value]", ""));
description.addAll(this.value);
icon = new ItemStack(Material.PAPER);
clickHandler = (panel, user, clickType, slot) -> true;
break;
}
case ADD:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.add");
description = Collections.emptyList();
icon = new ItemStack(Material.WHITE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.getStringInput(value -> {
if (value != null)
{
this.value.add(value);
}
// Reopen GUI.
this.build();
},
this.user.getTranslation("challenges.gui.descriptions.admin.add-text-line"));
return true;
};
break;
}
case CLEAR:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.clear");
description = Collections.emptyList();
icon = new ItemStack(Material.RED_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.value.clear();
this.build();
return true;
};
break;
}
case REMOVE:
{
name = this.user.getTranslation("challenges.gui.buttons.admin.remove-empty");
description = Collections.emptyList();
icon = new ItemStack(Material.BLUE_STAINED_GLASS_PANE);
clickHandler = (panel, user, clickType, slot) -> {
this.value.removeIf(String::isEmpty);
this.build();
return true;
};
break;
}
default:
return null;
}
return new PanelItemBuilder().
icon(icon).
name(name).
description(GuiUtils.stringSplit(description, this.lineLength)).
glow(false).
clickHandler(clickHandler).
build();
}
/**
* This method creates paper icon that represents single line from list.
* @param element Paper Icon name
* @return PanelItem.
*/
private PanelItem createStringElement(String element, int stringIndex)
{
return new PanelItemBuilder().
name(element).
icon(Material.PAPER).
clickHandler((panel, user1, clickType, i) -> {
this.getStringInput(
value -> {
if (value != null)
{
this.value.set(stringIndex, value);
}
// Reopen GUI
this.build();
},
this.user.getTranslation("challenges.gui.descriptions.admin.edit-text-line"),
element);
return true;
}).build();
}
/**
* This method will close opened gui and writes inputText in chat. After players answers on inputText in
* chat, message will trigger consumer and gui will reopen.
* @param consumer Consumer that accepts player output text.
* @param question Message that will be displayed in chat when player triggers conversion.
*/
private void getStringInput(Consumer<String> consumer, @NonNull String question)
{
this.getStringInput(consumer, question, null);
}
/**
* This method will close opened gui and writes inputText in chat. After players answers on inputText in
* chat, message will trigger consumer and gui will reopen.
* @param consumer Consumer that accepts player output text.
* @param question Message that will be displayed in chat when player triggers conversion.
* @param message Message that will be set in player text field when clicked on question.
*/
private void getStringInput(Consumer<String> consumer, @NonNull String question, @Nullable String message)
{
final User user = this.user;
Conversation conversation =
new ConversationFactory(BentoBox.getInstance()).withFirstPrompt(
new StringPrompt()
{
/**
* @see Prompt#getPromptText(ConversationContext)
*/
@Override
public String getPromptText(ConversationContext conversationContext)
{
// Close input GUI.
user.closeInventory();
if (message != null)
{
// Create Edit Text message.
TextComponent component = new TextComponent(user.getTranslation("challenges.gui.descriptions.admin.click-to-edit"));
component.setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, message));
// Send question and message to player.
user.getPlayer().spigot().sendMessage(component);
}
// There are no editable message. Just return question.
return question;
}
/**
* @see Prompt#acceptInput(ConversationContext, String)
*/
@Override
public Prompt acceptInput(ConversationContext conversationContext, String answer)
{
// Add answer to consumer.
consumer.accept(answer);
// End conversation
return Prompt.END_OF_CONVERSATION;
}
}).
// On cancel conversation will be closed.
withEscapeSequence("cancel").
// Use null value in consumer to detect if user has abandoned conversation.
addConversationAbandonedListener(abandonedEvent ->
{
if (!abandonedEvent.gracefulExit())
{
consumer.accept(null);
}
}).
withLocalEcho(false).
withPrefix(context -> user.getTranslation("challenges.gui.questions.prefix")).
buildConversation(user.getPlayer());
conversation.begin();
}
// ---------------------------------------------------------------------
// Section: Enums
// ---------------------------------------------------------------------
/**
* This enum holds all button values in current gui.
*/
private enum Button
{
VALUE,
ADD,
REMOVE,
CANCEL,
CLEAR,
SAVE
}
// ---------------------------------------------------------------------
// Section: Variables
// ---------------------------------------------------------------------
/**
* This variable stores consumer.
*/
private BiConsumer<Boolean, List<String>> consumer;
/**
* User who runs GUI.
*/
private User user;
/**
* Current value.
*/
private List<String> value;
/**
* This variable stores how large line can be, before warp it.
*/
private int lineLength;
}

View File

@ -0,0 +1,291 @@
//
// Created by BONNe
// Copyright - 2020
//
package world.bentobox.challenges.utils;
/**
* This class contains String constants used in messages and guis.
*/
public class Constants
{
/**
* Reference string to ADDON_NAME in translations.
*/
public static final String ADDON_NAME = "challenges.";
// ---------------------------------------------------------------------
// Section: Commands
// ---------------------------------------------------------------------
/**
* Reference string to Commands in translations.
*/
public static final String COMMANDS = ADDON_NAME + "commands.";
/**
* Reference string to Admin in translations.
*/
public static final String ADMIN_COMMANDS = COMMANDS + "admin.";
/**
* Reference string to Player in translations.
*/
public static final String PLAYER_COMMANDS = COMMANDS + "player.";
// ---------------------------------------------------------------------
// Section: GUI
// ---------------------------------------------------------------------
/**
* Reference string to GUI in translations.
*/
public static final String GUI = ADDON_NAME + "gui.";
/**
* Reference string to TITLE in translations.
*/
public static final String TITLE = GUI + "titles.";
/**
* Reference string to BUTTON in translations.
*/
public static final String BUTTON = GUI + "buttons.";
/**
* Reference string to Biome group Buttons in translations.
*/
public static final String BIOME_GROUP_BUTTON = BUTTON + "biome-groups.";
/**
* Reference string to generator type Buttons in translations.
*/
public static final String GENERATOR_TYPE_BUTTON = BUTTON + "generator-types.";
/**
* Reference string to TIPS in translations.
*/
public static final String TIPS = GUI + "tips.";
/**
* Reference string to DESCRIPTION in translations.
*/
public static final String DESCRIPTIONS = GUI + "descriptions.";
/**
* Reference string to Messages in translations.
*/
public static final String MESSAGES = ADDON_NAME + "messages.";
/**
* Reference string to Errors in translations.
*/
public static final String ERRORS = ADDON_NAME + "errors.";
/**
* Reference string to Questions in translations.
*/
public static final String CONVERSATIONS = ADDON_NAME + "conversations.";
// ---------------------------------------------------------------------
// Section: Other
// ---------------------------------------------------------------------
/**
* Reference string to Biomes in translations.
*/
public static final String BIOMES = ADDON_NAME + "biomes.";
/**
* Reference string to materials in translations.
*/
public static final String MATERIALS = ADDON_NAME + "materials.";
/**
* Reference string to entities in translations.
*/
public static final String ENTITIES = ADDON_NAME + "entities.";
/**
* Reference string to Types in translations.
*/
public static final String TYPES = ADDON_NAME + "types.";
// ---------------------------------------------------------------------
// Section: Parameters
// ---------------------------------------------------------------------
/**
* Reference string to generator parameter in translations.
*/
public static final String GENERATOR = "[generator]";
/**
* Reference string to bundle parameter in translations.
*/
public static final String BUNDLE = "[bundle]";
/**
* Reference string to gamemode parameter in translations.
*/
public static final String GAMEMODE = "[gamemode]";
/**
* Reference string to world parameter in translations.
*/
public static final String WORLD = "[world]";
/**
* Reference string to value parameter in translations.
*/
public static final String VALUE = "[value]";
/**
* Reference string to block parameter in translations.
*/
public static final String BLOCK = "[material]";
/**
* Reference string to file parameter in translations.
*/
public static final String FILE = "[file]";
/**
* Reference string to id parameter in translations.
*/
public static final String ID = "[id]";
/**
* Reference string to min parameter in translations.
*/
public static final String MIN = "[min]";
/**
* Reference string to max parameter in translations.
*/
public static final String MAX = "[max]";
/**
* Reference to an author parameter in translation.
*/
public static final String AUTHOR = "[author]";
/**
* Reference to an lang parameter in translation.
*/
public static final String LANG = "[lang]";
/**
* Reference to an version parameter in translation.
*/
public static final String VERSION = "[version]";
/**
* Reference to an generators parameter in translation.
*/
public static final String GENERATORS = "[generators]";
/**
* Reference to an bundles parameter in translation.
*/
public static final String BUNDLES = "[bundles]";
/**
* Reference to number formant in 0.X
*/
public static final String TENS = "[#.#]";
/**
* Reference to number formant in 0.0X
*/
public static final String HUNDREDS = "[#.##]";
/**
* Reference to number formant in 0.00X
*/
public static final String THOUSANDS = "[#.###]";
/**
* Reference to number formant in 0.000X
*/
public static final String TEN_THOUSANDS = "[#.####]";
/**
* Reference to number formant in 0.0000X
*/
public static final String HUNDRED_THOUSANDS = "[#.#####]";
/**
* Reference to island in translations.
*/
public static final String ISLAND = "[island]";
/**
* Reference string to number parameter in translations.
*/
public static final String NUMBER = "[number]";
/**
* Reference string to type parameter in translations.
*/
public static final String TYPE = "[type]";
/**
* Reference string to permission parameter in translations.
*/
public static final String PERMISSION = "[permission]";
/**
* Reference string to biome parameter in translations.
*/
public static final String BIOME = "[biome]";
/**
* Reference string to player parameter in translations.
*/
public static final String PLAYER = "[player]";
/**
* Reference string to owner parameter in translations.
*/
public static final String OWNER = "[owner]";
/**
* Reference string to members parameter in translations.
*/
public static final String MEMBERS = "[members]";
/**
* Reference string to name parameter in translations.
*/
public static final String NAME = "[name]";
/**
* Reference string to description parameter in translations.
*/
public static final String DESCRIPTION = "[description]";
public static final String CHALLENGE = "[challenge]";
public static final String REQUIREMENTS = "[requirements]";
public static final String REWARDS = "[rewards]";
public static final String STATUS = "[status]";
public static final String LEVEL = "[level]";
public static final String ENVIRONMENT = "[environment]";
public static final String TYPE_REQUIREMENT = "[type-requirement]";
public static final String PERMISSIONS = "[permissions]";
public static final String MATERIAL = "[material]";
public static final String ENTITY = "[entity]";
}

View File

@ -3,8 +3,6 @@ package world.bentobox.challenges.utils;
import java.util.*;
import org.apache.commons.lang.WordUtils;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
@ -366,74 +364,9 @@ public class GuiUtils
private static BorderBlock getPanelBorder(Material material)
{
ItemStack itemStack = new ItemStack(material);
itemStack.getItemMeta().setDisplayName(" ");
itemStack.getItemMeta().setDisplayName("&r&8");
return new BorderBlock(itemStack);
}
}
/**
* Simple splitter
*
* @param string - string to be split
* @param warpLength - whn warp should be affected.
* @return list of split strings
*/
public static List<String> stringSplit(String string, int warpLength)
{
// Remove all ending lines from string.
string = string.replaceAll("([\\r\\n])", "\\|");
string = ChatColor.translateAlternateColorCodes('&', string);
// Check length of lines
List<String> result = new ArrayList<>();
Arrays.stream(string.split("\\|")).
map(line -> Arrays.asList(WordUtils.wrap(line, warpLength).split(System.getProperty("line.separator")))).
forEach(result::addAll);
// Fix colors, as splitting my lost that information.
for (int i = 0, resultSize = result.size(); i < resultSize; i++)
{
if (i > 0)
{
String lastColor = ChatColor.getLastColors(result.get(i - 1));
result.set(i, lastColor + result.get(i));
}
}
return result;
}
/**
* Simple splitter for all strings in list.
* @param stringList - list of string to be split
* @param warpLength - whn warp should be affected.
* @return list of split strings
*/
public static List<String> stringSplit(List<String> stringList, int warpLength)
{
if (stringList.isEmpty())
{
return stringList;
}
List<String> newList = new ArrayList<>(stringList.size());
stringList.stream().map(string -> GuiUtils.stringSplit(string, warpLength)).forEach(newList::addAll);
return newList;
}
/**
* Sanitizes the provided input.
* It replaces spaces and hyphens with underscores and lower cases the input.
* @param input input to sanitize
* @return sanitized input
*/
public static String sanitizeInput(String input)
{
return input.toLowerCase(Locale.ENGLISH).replace(" ", "_").replace("-", "_");
}
}

View File

@ -3,12 +3,19 @@ package world.bentobox.challenges.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.World;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.ItemStack;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.util.Util;
/**
@ -152,4 +159,103 @@ public class Utils
return currentValue;
}
/**
* Sanitizes the provided input. It replaces spaces and hyphens with underscores and lower cases the input.
* This code also removes all color codes from the input.
* @param input input to sanitize
* @return sanitized input
*/
public static String sanitizeInput(String input)
{
return ChatColor.stripColor(
Util.translateColorCodes(input.toLowerCase(Locale.ENGLISH).
replace(" ", "_").
replace("-", "_")));
}
/**
* Send given message to user and add prefix to the start of the message.
*
* @param user User who need to receive message.
* @param message String of message that must be send.
*/
public static void sendMessage(User user, String message)
{
user.sendMessage(user.getTranslation(Constants.CONVERSATIONS + "prefix") + message);
}
public static String prettifyObject(World.Environment object, User user)
{
return Util.prettifyText(object.name());
}
public static String prettifyObject(@Nullable Material object, User user)
{
if (object == null)
{
return "";
}
return Util.prettifyText(object.name());
}
public static String prettifyObject(@Nullable EntityType object, User user)
{
if (object == null)
{
return "";
}
return Util.prettifyText(object.name());
}
public static String prettifyObject(@Nullable ItemStack object, User user)
{
if (object == null)
{
return "";
}
return Util.prettifyText(object.getType().name());
}
public static String prettifyObject(@Nullable Statistic object, User user)
{
if (object == null)
{
return "";
}
return Util.prettifyText(object.name());
}
public static String prettifyDescription(@Nullable Statistic object, User user)
{
if (object == null)
{
return "";
}
return Util.prettifyText(object.name());
}
public static String prettifyDescription(World.Environment object, User user)
{
if (object == null)
{
return "";
}
return Util.prettifyText(object.name());
}
}