From 5a0d63a27256b8917a5c30d3ba00f1dfcf2b0578 Mon Sep 17 00:00:00 2001 From: BONNe Date: Wed, 22 Apr 2020 01:12:46 +0300 Subject: [PATCH] Add option to quit from conversation by writing "cancel" in chat. Move sanitizeInput to a GuiUtil class. --- .../bentobox/challenges/panel/CommonGUI.java | 4 + .../challenges/panel/admin/AdminGUI.java | 86 ++++---- .../panel/admin/EditChallengeGUI.java | 6 +- .../challenges/panel/admin/EditLevelGUI.java | 10 +- .../challenges/panel/util/NumberGUI.java | 186 ++++++++++-------- .../challenges/panel/util/StringListGUI.java | 26 ++- .../bentobox/challenges/utils/GuiUtils.java | 17 +- 7 files changed, 200 insertions(+), 135 deletions(-) diff --git a/src/main/java/world/bentobox/challenges/panel/CommonGUI.java b/src/main/java/world/bentobox/challenges/panel/CommonGUI.java index 5d41ac0..39897d6 100644 --- a/src/main/java/world/bentobox/challenges/panel/CommonGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/CommonGUI.java @@ -1082,6 +1082,10 @@ public abstract class CommonGUI } }). withLocalEcho(false). + // On cancel conversation will be closed. + withEscapeSequence("cancel"). + // Use null value in consumer to detect if user has abandoned conversation. + addConversationAbandonedListener(abandonedEvent -> consumer.accept(null)). withPrefix(context -> user.getTranslation("challenges.gui.questions.prefix")). buildConversation(user.getPlayer()); diff --git a/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java index b01d43f..a0efdd7 100644 --- a/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/admin/AdminGUI.java @@ -7,11 +7,7 @@ import java.util.function.Function; import org.bukkit.Material; import org.bukkit.World; -import org.bukkit.conversations.Conversation; -import org.bukkit.conversations.ConversationContext; -import org.bukkit.conversations.ConversationFactory; -import org.bukkit.conversations.Prompt; -import org.bukkit.conversations.ValidatingPrompt; +import org.bukkit.conversations.*; import org.bukkit.inventory.ItemStack; import org.eclipse.jdt.annotation.NonNull; @@ -252,20 +248,27 @@ public class AdminGUI extends CommonGUI icon = new ItemStack(Material.BOOK); clickHandler = (panel, user, clickType, slot) -> { - this.getNewUniqueID(challenge -> { - String uniqueId = Utils.getGameMode(this.world) + "_" + challenge; + 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(); - }); + 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; @@ -287,16 +290,25 @@ public class AdminGUI extends CommonGUI icon = new ItemStack(Material.BOOK); clickHandler = (panel, user, clickType, slot) -> { - this.getNewUniqueID(level -> { - String newName = Utils.getGameMode(this.world) + "_" + level; + 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(); + 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; @@ -660,7 +672,7 @@ public class AdminGUI extends CommonGUI @Override protected boolean isInputValid(ConversationContext context, String input) { - return stringValidation.apply(sanitizeInput(input)); + return stringValidation.apply(GuiUtils.sanitizeInput(input)); } @@ -680,7 +692,7 @@ public class AdminGUI extends CommonGUI protected String getFailedValidationText(ConversationContext context, String invalidInput) { - return user.getTranslation("challenges.errors.unique-id", "[id]", sanitizeInput(invalidInput)); + return user.getTranslation("challenges.errors.unique-id", "[id]", GuiUtils.sanitizeInput(invalidInput)); } @@ -700,25 +712,19 @@ public class AdminGUI extends CommonGUI protected Prompt acceptValidatedInput(ConversationContext context, String input) { // Add answer to consumer. - consumer.accept(sanitizeInput(input)); + 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 -> consumer.accept(null)). withLocalEcho(false). withPrefix(context -> user.getTranslation("challenges.gui.questions.prefix")). buildConversation(user.getPlayer()); conversation.begin(); } - - /** - * Sanitizes the provided input. - * It replaces spaces and hyphens with underscores and lowercases the input. - * @param input input to sanitize - * @return sanitized input - */ - private String sanitizeInput(String input) { - return input.toLowerCase(Locale.ENGLISH).replace(" ", "_").replace("-", "_"); - } } \ No newline at end of file diff --git a/src/main/java/world/bentobox/challenges/panel/admin/EditChallengeGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/EditChallengeGUI.java index b94a1f4..f064182 100644 --- a/src/main/java/world/bentobox/challenges/panel/admin/EditChallengeGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/admin/EditChallengeGUI.java @@ -500,7 +500,11 @@ public class EditChallengeGUI extends CommonGUI clickHandler = (panel, user, clickType, slot) -> { this.getFriendlyName(reply -> { - this.challenge.setFriendlyName(reply); + if (reply != null) + { + this.challenge.setFriendlyName(reply); + } + this.build(); }, this.user.getTranslation("challenges.gui.questions.admin.challenge-name"), diff --git a/src/main/java/world/bentobox/challenges/panel/admin/EditLevelGUI.java b/src/main/java/world/bentobox/challenges/panel/admin/EditLevelGUI.java index 8938d98..bd6b841 100644 --- a/src/main/java/world/bentobox/challenges/panel/admin/EditLevelGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/admin/EditLevelGUI.java @@ -338,9 +338,13 @@ public class EditLevelGUI extends CommonGUI icon = new ItemStack(Material.DROPPER); clickHandler = (panel, user, clickType, slot) -> { - this.getFriendlyName(reply -> { - this.challengeLevel.setFriendlyName(reply); - this.build(); + this.getFriendlyName(reply -> + { + if (reply != null) + { + this.challengeLevel.setFriendlyName(reply); + } + this.build(); }, this.user.getTranslation("challenges.gui.questions.admin.level-name"), this.challengeLevel.getFriendlyName() diff --git a/src/main/java/world/bentobox/challenges/panel/util/NumberGUI.java b/src/main/java/world/bentobox/challenges/panel/util/NumberGUI.java index a80decd..4f00cbc 100644 --- a/src/main/java/world/bentobox/challenges/panel/util/NumberGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/util/NumberGUI.java @@ -148,7 +148,12 @@ public class NumberGUI clickHandler = (panel, user, clickType, slot) -> { this.getNumberInput(number -> { - this.value = number.intValue(); + 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")); @@ -370,99 +375,114 @@ public class NumberGUI 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; - } + 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; - } + /** + * 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 + * 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)); - } + /** + * 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(); + /** + * @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; - } - }). + // 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 -> consumer.accept(null)). withPrefix(context -> - NumberGUI.this.user.getTranslation("challenges.gui.questions.prefix")). + NumberGUI.this.user.getTranslation("challenges.gui.questions.prefix")). buildConversation(user.getPlayer()); conversation.begin(); diff --git a/src/main/java/world/bentobox/challenges/panel/util/StringListGUI.java b/src/main/java/world/bentobox/challenges/panel/util/StringListGUI.java index 62df5c7..0e7ea8f 100644 --- a/src/main/java/world/bentobox/challenges/panel/util/StringListGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/util/StringListGUI.java @@ -156,7 +156,15 @@ public class StringListGUI icon = new ItemStack(Material.WHITE_STAINED_GLASS_PANE); clickHandler = (panel, user, clickType, slot) -> { - this.getStringInput(value -> this.value.add(value), + 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; @@ -215,7 +223,15 @@ public class StringListGUI clickHandler((panel, user1, clickType, i) -> { this.getStringInput( - value -> this.value.set(stringIndex, value), + value -> { + if (value != null) + { + this.value.set(stringIndex, value); + } + + // Reopen GUI + this.build(); + }, this.user.getTranslation("challenges.gui.descriptions.admin.edit-text-line"), element); @@ -282,12 +298,14 @@ public class StringListGUI { // Add answer to consumer. consumer.accept(answer); - // Reopen GUI - StringListGUI.this.build(); // 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 -> consumer.accept(null)). withLocalEcho(false). withPrefix(context -> user.getTranslation("challenges.gui.questions.prefix")). buildConversation(user.getPlayer()); diff --git a/src/main/java/world/bentobox/challenges/utils/GuiUtils.java b/src/main/java/world/bentobox/challenges/utils/GuiUtils.java index fea25bd..40b069c 100644 --- a/src/main/java/world/bentobox/challenges/utils/GuiUtils.java +++ b/src/main/java/world/bentobox/challenges/utils/GuiUtils.java @@ -1,10 +1,7 @@ package world.bentobox.challenges.utils; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.util.*; import org.apache.commons.lang.WordUtils; import org.bukkit.ChatColor; @@ -424,4 +421,16 @@ public class GuiUtils 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("-", "_"); + } } \ No newline at end of file