From dc9b33c354a5fa188895a574166b3d771cf01094 Mon Sep 17 00:00:00 2001 From: fendi Date: Thu, 4 Jun 2026 00:16:57 +0200 Subject: [PATCH] dialogs+small caps replacer --- .../zauctionhouse/api/filter/SearchField.java | 1 + .../api/filter/SearchQueryFormatter.java | 37 ++++ .../api/filter/SearchTextMatcher.java | 23 +++ .../api/filter/SearchTextNormalizer.java | 59 ++++++ .../zauctionhouse/api/messages/Message.java | 4 +- .../api/filter/SearchQueryFormatterTest.java | 38 ++++ .../api/filter/SearchQueryTest.java | 55 ++++++ .../api/filter/SearchTextMatcherTest.java | 29 +++ .../api/filter/SearchTextNormalizerTest.java | 23 +++ build.gradle.kts | 9 +- .../zauctionhouse/ZAuctionPlugin.java | 14 +- .../buttons/ClearSearchButton.java | 3 +- .../zauctionhouse/buttons/SearchButton.java | 5 +- .../commands/CommandAuctionSearch.java | 9 +- .../search/ChatSearchListener.java | 52 ----- .../search/SearchDialogService.java | 177 ++++++++++++++++++ .../zauctionhouse/services/SearchService.java | 67 +++++-- src/main/resources/config.yml | 2 +- src/main/resources/es/config.yml | 2 +- src/main/resources/es/inventories/auction.yml | 17 +- src/main/resources/es/messages.yml | 2 +- src/main/resources/fr/config.yml | 2 +- src/main/resources/fr/inventories/auction.yml | 17 +- src/main/resources/fr/messages.yml | 2 +- src/main/resources/inventories/auction.yml | 17 +- src/main/resources/it/config.yml | 2 +- src/main/resources/it/inventories/auction.yml | 17 +- src/main/resources/it/messages.yml | 2 +- src/main/resources/messages.yml | 4 +- src/main/resources/plugin.yml | 4 +- src/main/resources/th/config.yml | 4 +- src/main/resources/th/inventories/auction.yml | 17 +- src/main/resources/th/messages.yml | 4 +- 33 files changed, 555 insertions(+), 165 deletions(-) create mode 100644 API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryFormatter.java create mode 100644 API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextMatcher.java create mode 100644 API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextNormalizer.java create mode 100644 API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryFormatterTest.java create mode 100644 API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryTest.java create mode 100644 API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextMatcherTest.java create mode 100644 API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextNormalizerTest.java delete mode 100644 src/main/java/fr/maxlego08/zauctionhouse/search/ChatSearchListener.java create mode 100644 src/main/java/fr/maxlego08/zauctionhouse/search/SearchDialogService.java diff --git a/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchField.java b/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchField.java index a04b1ff..e3cea10 100644 --- a/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchField.java +++ b/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchField.java @@ -5,6 +5,7 @@ */ public enum SearchField { + ALL("all"), NAME("name"), MATERIAL("material"), LORE("lore"), diff --git a/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryFormatter.java b/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryFormatter.java new file mode 100644 index 0000000..ca45972 --- /dev/null +++ b/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryFormatter.java @@ -0,0 +1,37 @@ +package fr.maxlego08.zauctionhouse.api.filter; + +import fr.maxlego08.zauctionhouse.api.configuration.records.SearchFilterConfiguration; + +import java.util.Locale; + +public final class SearchQueryFormatter { + + private SearchQueryFormatter() { + } + + public static String format(String raw, SearchFilterConfiguration configuration) { + SearchQuery query = SearchQuery.parse(raw, configuration); + if (query.value().isBlank()) { + return "None"; + } + + SearchField field = query.field() == null ? SearchField.ALL : query.field(); + SearchFilterType type = query.type() == null ? SearchFilterType.CONTAINS_IGNORE_CASE : query.type(); + return fieldLabel(field) + " " + modeLabel(type) + ": " + query.value(); + } + + private static String fieldLabel(SearchField field) { + if (field == SearchField.ALL) { + return "Everything"; + } + String key = field.getKey().toLowerCase(Locale.ROOT); + return Character.toUpperCase(key.charAt(0)) + key.substring(1); + } + + private static String modeLabel(SearchFilterType type) { + return switch (type) { + case EQUALS, EQUALS_IGNORE_CASE -> "exact"; + case CONTAINS, CONTAINS_IGNORE_CASE -> "contains"; + }; + } +} diff --git a/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextMatcher.java b/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextMatcher.java new file mode 100644 index 0000000..f2d123c --- /dev/null +++ b/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextMatcher.java @@ -0,0 +1,23 @@ +package fr.maxlego08.zauctionhouse.api.filter; + +/** + * Applies search filter operators to plain text values. + */ +public final class SearchTextMatcher { + + private SearchTextMatcher() { + } + + public static boolean matches(String fieldValue, SearchFilterType type, String queryValue) { + if (fieldValue == null || queryValue == null) { + return false; + } + + return switch (type) { + case CONTAINS -> fieldValue.contains(queryValue); + case EQUALS -> fieldValue.equals(queryValue); + case CONTAINS_IGNORE_CASE -> SearchTextNormalizer.normalize(fieldValue).contains(SearchTextNormalizer.normalize(queryValue)); + case EQUALS_IGNORE_CASE -> SearchTextNormalizer.normalize(fieldValue).equals(SearchTextNormalizer.normalize(queryValue)); + }; + } +} diff --git a/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextNormalizer.java b/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextNormalizer.java new file mode 100644 index 0000000..b2118d4 --- /dev/null +++ b/API/src/main/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextNormalizer.java @@ -0,0 +1,59 @@ +package fr.maxlego08.zauctionhouse.api.filter; + +import java.text.Normalizer; + +/** + * Normalizes searchable text so styled small-caps item names remain discoverable. + */ +public final class SearchTextNormalizer { + + private SearchTextNormalizer() { + } + + public static String normalize(String value) { + if (value == null || value.isEmpty()) { + return ""; + } + + String normalized = Normalizer.normalize(value, Normalizer.Form.NFKC); + StringBuilder builder = new StringBuilder(normalized.length()); + + normalized.codePoints().forEach(codePoint -> { + int mappedCodePoint = mapSmallCaps(codePoint); + builder.appendCodePoint(Character.toLowerCase(mappedCodePoint)); + }); + + return builder.toString(); + } + + private static int mapSmallCaps(int codePoint) { + return switch (codePoint) { + case 0x1D00 -> 'a'; + case 0x0299 -> 'b'; + case 0x1D04 -> 'c'; + case 0x1D05 -> 'd'; + case 0x1D07 -> 'e'; + case 0xA730 -> 'f'; + case 0x0262 -> 'g'; + case 0x029C -> 'h'; + case 0x026A -> 'i'; + case 0x1D0A -> 'j'; + case 0x1D0B -> 'k'; + case 0x029F -> 'l'; + case 0x1D0D -> 'm'; + case 0x0274 -> 'n'; + case 0x1D0F -> 'o'; + case 0x1D18 -> 'p'; + case 0xA7AF -> 'q'; + case 0x0280 -> 'r'; + case 0xA731 -> 's'; + case 0x1D1B -> 't'; + case 0x1D1C -> 'u'; + case 0x1D20 -> 'v'; + case 0x1D21 -> 'w'; + case 0x028F -> 'y'; + case 0x1D22 -> 'z'; + default -> codePoint; + }; + } +} diff --git a/API/src/main/java/fr/maxlego08/zauctionhouse/api/messages/Message.java b/API/src/main/java/fr/maxlego08/zauctionhouse/api/messages/Message.java index b0ce3f8..38182ea 100644 --- a/API/src/main/java/fr/maxlego08/zauctionhouse/api/messages/Message.java +++ b/API/src/main/java/fr/maxlego08/zauctionhouse/api/messages/Message.java @@ -157,7 +157,7 @@ public enum Message { MIGRATION_FAILED("Migration failed: %error%"), // Search messages - SEARCH_START("<#8a8a8a>Please type your search in the chat."), + SEARCH_START("<#8a8a8a>Opening search dialog."), SEARCH_CLEARED("<#8a8a8a>Search cleared."), SEARCH_NO_RESULTS("<#8a8a8a>No items found for <#ffffff>%query%<#8a8a8a>."), SEARCH_SEARCHING("<#8a8a8a>Searching for <#ffffff>%query%<#8a8a8a>..."), @@ -256,4 +256,4 @@ public void setPlugin(AuctionPlugin plugin) { public List getMessageAsStringList() { return this.messages.stream().filter(AuctionMessage -> AuctionMessage instanceof ClassicMessage).map(AuctionMessage -> (ClassicMessage) AuctionMessage).map(ClassicMessage::messages).flatMap(List::stream).toList(); } -} \ No newline at end of file +} diff --git a/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryFormatterTest.java b/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryFormatterTest.java new file mode 100644 index 0000000..0abb290 --- /dev/null +++ b/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryFormatterTest.java @@ -0,0 +1,38 @@ +package fr.maxlego08.zauctionhouse.api.filter; + +import fr.maxlego08.zauctionhouse.api.configuration.records.SearchFilterConfiguration; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SearchQueryFormatterTest { + + private final SearchFilterConfiguration configuration = new SearchFilterConfiguration(Map.of( + SearchFilterType.CONTAINS, "~", + SearchFilterType.EQUALS, "=", + SearchFilterType.CONTAINS_IGNORE_CASE, "~=", + SearchFilterType.EQUALS_IGNORE_CASE, "==" + )); + + @Test + void formatsBlankQueryAsNone() { + assertEquals("None", SearchQueryFormatter.format("", configuration)); + } + + @Test + void formatsAllContainsQuery() { + assertEquals("Everything contains: sandaly", SearchQueryFormatter.format("all ~= sandaly", configuration)); + } + + @Test + void formatsFieldExactQuery() { + assertEquals("Name exact: Sandaly", SearchQueryFormatter.format("name == Sandaly", configuration)); + } + + @Test + void formatsDefaultQueryAsEverythingContains() { + assertEquals("Everything contains: diamond", SearchQueryFormatter.format("diamond", configuration)); + } +} diff --git a/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryTest.java b/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryTest.java new file mode 100644 index 0000000..46592df --- /dev/null +++ b/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchQueryTest.java @@ -0,0 +1,55 @@ +package fr.maxlego08.zauctionhouse.api.filter; + +import fr.maxlego08.zauctionhouse.api.configuration.records.SearchFilterConfiguration; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +class SearchQueryTest { + + private final SearchFilterConfiguration configuration = new SearchFilterConfiguration(Map.of( + SearchFilterType.CONTAINS, "~", + SearchFilterType.EQUALS, "=", + SearchFilterType.CONTAINS_IGNORE_CASE, "~=", + SearchFilterType.EQUALS_IGNORE_CASE, "==" + )); + + @Test + void parsesExplicitAllField() { + SearchQuery query = SearchQuery.parse("all ~= sandaly", configuration); + + assertEquals(SearchField.ALL, query.field()); + assertEquals(SearchFilterType.CONTAINS_IGNORE_CASE, query.type()); + assertEquals("sandaly", query.value()); + } + + @Test + void parsesNameEqualsIgnoreCase() { + SearchQuery query = SearchQuery.parse("name == sandaly", configuration); + + assertEquals(SearchField.NAME, query.field()); + assertEquals(SearchFilterType.EQUALS_IGNORE_CASE, query.type()); + assertEquals("sandaly", query.value()); + } + + @Test + void parsesSellerContainsIgnoreCase() { + SearchQuery query = SearchQuery.parse("seller ~= Notch", configuration); + + assertEquals(SearchField.SELLER, query.field()); + assertEquals(SearchFilterType.CONTAINS_IGNORE_CASE, query.type()); + assertEquals("Notch", query.value()); + } + + @Test + void keepsBlankQueryAsDefaultSearch() { + SearchQuery query = SearchQuery.parse("", configuration); + + assertNull(query.field()); + assertNull(query.type()); + assertEquals("", query.value()); + } +} diff --git a/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextMatcherTest.java b/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextMatcherTest.java new file mode 100644 index 0000000..8b95369 --- /dev/null +++ b/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextMatcherTest.java @@ -0,0 +1,29 @@ +package fr.maxlego08.zauctionhouse.api.filter; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class SearchTextMatcherTest { + + @Test + void containsIgnoreCaseMatchesSmallCaps() { + assertTrue(SearchTextMatcher.matches("sᴀɴᴅᴀʟʏ ᴘᴏsʟᴀɴᴄᴀ", SearchFilterType.CONTAINS_IGNORE_CASE, "sandaly")); + } + + @Test + void equalsIgnoreCaseMatchesSmallCaps() { + assertTrue(SearchTextMatcher.matches("sᴀɴᴅᴀʟʏ", SearchFilterType.EQUALS_IGNORE_CASE, "sandaly")); + } + + @Test + void caseSensitiveContainsKeepsExistingBehavior() { + assertFalse(SearchTextMatcher.matches("Diamond Sword", SearchFilterType.CONTAINS, "diamond")); + } + + @Test + void exactMatchKeepsExistingBehavior() { + assertFalse(SearchTextMatcher.matches("sᴀɴᴅᴀʟʏ", SearchFilterType.EQUALS, "sandaly")); + } +} diff --git a/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextNormalizerTest.java b/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextNormalizerTest.java new file mode 100644 index 0000000..ee468e3 --- /dev/null +++ b/API/src/test/java/fr/maxlego08/zauctionhouse/api/filter/SearchTextNormalizerTest.java @@ -0,0 +1,23 @@ +package fr.maxlego08.zauctionhouse.api.filter; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class SearchTextNormalizerTest { + + @Test + void normalizesSmallCapsToPlainAscii() { + assertEquals("sandaly", SearchTextNormalizer.normalize("sᴀɴᴅᴀʟʏ")); + } + + @Test + void normalizesMixedCaseAndSmallCapsTogether() { + assertEquals("sandaly poslanca", SearchTextNormalizer.normalize("Sᴀɴᴅᴀʟʏ Pᴏsʟᴀɴᴄᴀ")); + } + + @Test + void lowercasesRegularText() { + assertEquals("diamond sword", SearchTextNormalizer.normalize("Diamond Sword")); + } +} diff --git a/build.gradle.kts b/build.gradle.kts index ace67b5..3d4feab 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,5 @@ import org.gradle.kotlin.dsl.invoke +import org.gradle.api.tasks.testing.Test plugins { `java-library` @@ -63,13 +64,19 @@ allprojects { } dependencies { - compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT") compileOnly("me.clip:placeholderapi:2.11.6") compileOnly("fr.maxlego08.menu:zmenu-api:1.1.1.0") implementation("fr.maxlego08.sarah:sarah:1.23") implementation("com.tcoded:FoliaLib:0.5.1") implementation("fr.traqueur.currencies:currenciesapi:1.0.13") + + testImplementation("org.junit.jupiter:junit-jupiter:5.10.3") + } + + tasks.withType().configureEach { + useJUnitPlatform() } } diff --git a/src/main/java/fr/maxlego08/zauctionhouse/ZAuctionPlugin.java b/src/main/java/fr/maxlego08/zauctionhouse/ZAuctionPlugin.java index 6a95fe5..8b1f1d6 100644 --- a/src/main/java/fr/maxlego08/zauctionhouse/ZAuctionPlugin.java +++ b/src/main/java/fr/maxlego08/zauctionhouse/ZAuctionPlugin.java @@ -47,7 +47,7 @@ import fr.maxlego08.zauctionhouse.services.BroadcastService; import fr.maxlego08.zauctionhouse.rule.ZItemRuleManager; import fr.maxlego08.zauctionhouse.rule.ZRuleLoaderRegistry; -import fr.maxlego08.zauctionhouse.search.ChatSearchListener; +import fr.maxlego08.zauctionhouse.search.SearchDialogService; import fr.maxlego08.zauctionhouse.storage.ZStorageManager; import fr.maxlego08.zauctionhouse.utils.LocaleHelper; import fr.maxlego08.zauctionhouse.utils.Metrics; @@ -90,7 +90,7 @@ public class ZAuctionPlugin extends JavaPlugin implements AuctionPlugin { private final MessageHelper messageHelper = new MessageHelper(); private LocaleHelper localeHelper; private InventoriesLoader inventoriesLoader; - private ChatSearchListener chatSearchListener; + private SearchDialogService searchDialogService; private BroadcastService broadcastService; private DiscordWebhookService discordWebhookService; private VersionChecker versionChecker; @@ -137,9 +137,9 @@ public void onEnable() { this.broadcastService = new BroadcastService(this); this.discordWebhookService = new DiscordWebhookService(this); - this.chatSearchListener = new ChatSearchListener(this); + this.searchDialogService = new SearchDialogService(this); this.addListener(new PlayerListener(this)); - this.addListener(this.chatSearchListener); + this.addListener(this.searchDialogService); java.util.List aliases = new java.util.ArrayList<>(getConfig().getStringList("commands.main-command.aliases")); String primaryCommand; @@ -453,8 +453,8 @@ public Placeholder getPlaceholder() { return this.placeholder; } - public ChatSearchListener getChatSearchListener() { - return this.chatSearchListener; + public SearchDialogService getSearchDialogService() { + return this.searchDialogService; } public BroadcastService getBroadcastService() { @@ -615,4 +615,4 @@ void send(AuctionPlugin plugin, org.bukkit.command.CommandSender sender, Message this.message(plugin, sender, message, args); } } -} \ No newline at end of file +} diff --git a/src/main/java/fr/maxlego08/zauctionhouse/buttons/ClearSearchButton.java b/src/main/java/fr/maxlego08/zauctionhouse/buttons/ClearSearchButton.java index 12be888..d0a95f2 100644 --- a/src/main/java/fr/maxlego08/zauctionhouse/buttons/ClearSearchButton.java +++ b/src/main/java/fr/maxlego08/zauctionhouse/buttons/ClearSearchButton.java @@ -5,6 +5,7 @@ import fr.maxlego08.menu.api.utils.Placeholders; import fr.maxlego08.zauctionhouse.api.AuctionPlugin; import fr.maxlego08.zauctionhouse.api.cache.PlayerCacheKey; +import fr.maxlego08.zauctionhouse.api.filter.SearchQueryFormatter; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.ItemStack; @@ -46,7 +47,7 @@ public ItemStack getCustomItemStack(@NotNull Player player, boolean useCache, @N return null; } - placeholders.register("search_query", query); + placeholders.register("search_query", SearchQueryFormatter.format(query, this.plugin.getConfiguration().getSearchFilter())); return this.getItemStack().build(player, false, placeholders); } diff --git a/src/main/java/fr/maxlego08/zauctionhouse/buttons/SearchButton.java b/src/main/java/fr/maxlego08/zauctionhouse/buttons/SearchButton.java index da03d5c..d17c61a 100644 --- a/src/main/java/fr/maxlego08/zauctionhouse/buttons/SearchButton.java +++ b/src/main/java/fr/maxlego08/zauctionhouse/buttons/SearchButton.java @@ -6,6 +6,7 @@ import fr.maxlego08.zauctionhouse.ZAuctionPlugin; import fr.maxlego08.zauctionhouse.api.AuctionPlugin; import fr.maxlego08.zauctionhouse.api.cache.PlayerCacheKey; +import fr.maxlego08.zauctionhouse.api.filter.SearchQueryFormatter; import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.ItemStack; @@ -31,7 +32,7 @@ public ItemStack getCustomItemStack(@NotNull Player player, boolean useCache, @N String query = cache.get(PlayerCacheKey.SEARCH_QUERY); boolean hasActiveQuery = query != null && !query.isBlank(); - placeholders.register("search_query", hasActiveQuery ? query : "None"); + placeholders.register("search_query", hasActiveQuery ? SearchQueryFormatter.format(query, this.plugin.getConfiguration().getSearchFilter()) : "None"); placeholders.register("search_active", hasActiveQuery ? "true" : "false"); return this.getItemStack().build(player, false, placeholders); @@ -53,7 +54,7 @@ public void onClick(@NonNull Player player, @NonNull InventoryClickEvent event, } if (this.plugin instanceof ZAuctionPlugin zAuctionPlugin) { - zAuctionPlugin.getChatSearchListener().startSearch(player); + zAuctionPlugin.getSearchDialogService().openSearchDialog(player); } } } diff --git a/src/main/java/fr/maxlego08/zauctionhouse/command/commands/CommandAuctionSearch.java b/src/main/java/fr/maxlego08/zauctionhouse/command/commands/CommandAuctionSearch.java index e9c758e..6b032e7 100644 --- a/src/main/java/fr/maxlego08/zauctionhouse/command/commands/CommandAuctionSearch.java +++ b/src/main/java/fr/maxlego08/zauctionhouse/command/commands/CommandAuctionSearch.java @@ -1,5 +1,6 @@ package fr.maxlego08.zauctionhouse.command.commands; +import fr.maxlego08.zauctionhouse.ZAuctionPlugin; import fr.maxlego08.zauctionhouse.api.AuctionPlugin; import fr.maxlego08.zauctionhouse.api.messages.Message; import fr.maxlego08.zauctionhouse.api.utils.Permission; @@ -31,10 +32,6 @@ public CommandAuctionSearch(AuctionPlugin plugin) { @Override protected CommandType perform(AuctionPlugin plugin) { - if (this.args.length < 2) { - return CommandType.SYNTAX_ERROR; - } - StringBuilder queryBuilder = new StringBuilder(); for (int i = 1; i < this.args.length; i++) { if (i > 1) queryBuilder.append(" "); @@ -42,7 +39,9 @@ protected CommandType perform(AuctionPlugin plugin) { } String query = queryBuilder.toString(); - plugin.getAuctionManager().startSearch(this.player, query); + if (plugin instanceof ZAuctionPlugin zAuctionPlugin) { + zAuctionPlugin.getSearchDialogService().openSearchDialog(this.player, query); + } return CommandType.SUCCESS; } } diff --git a/src/main/java/fr/maxlego08/zauctionhouse/search/ChatSearchListener.java b/src/main/java/fr/maxlego08/zauctionhouse/search/ChatSearchListener.java deleted file mode 100644 index e8406db..0000000 --- a/src/main/java/fr/maxlego08/zauctionhouse/search/ChatSearchListener.java +++ /dev/null @@ -1,52 +0,0 @@ -package fr.maxlego08.zauctionhouse.search; - -import fr.maxlego08.zauctionhouse.api.AuctionPlugin; -import fr.maxlego08.zauctionhouse.api.messages.Message; -import io.papermc.paper.event.player.AsyncChatEvent; -import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerQuitEvent; - -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public class ChatSearchListener implements Listener { - - private final AuctionPlugin plugin; - private final Set waitingForInput = ConcurrentHashMap.newKeySet(); - - public ChatSearchListener(AuctionPlugin plugin) { - this.plugin = plugin; - } - - public void startSearch(Player player) { - waitingForInput.add(player.getUniqueId()); - player.closeInventory(); - this.plugin.sendMessage(player, Message.SEARCH_START); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onChat(AsyncChatEvent event) { - if (!waitingForInput.remove(event.getPlayer().getUniqueId())) return; - - event.setCancelled(true); - - String query = PlainTextComponentSerializer.plainText().serialize(event.message()); - Player player = event.getPlayer(); - - this.plugin.getScheduler().runAtEntity(player, w -> { - if (player.isOnline()) { - this.plugin.getAuctionManager().startSearch(player, query); - } - }); - } - - @EventHandler - public void onQuit(PlayerQuitEvent event) { - waitingForInput.remove(event.getPlayer().getUniqueId()); - } -} diff --git a/src/main/java/fr/maxlego08/zauctionhouse/search/SearchDialogService.java b/src/main/java/fr/maxlego08/zauctionhouse/search/SearchDialogService.java new file mode 100644 index 0000000..ab15cc2 --- /dev/null +++ b/src/main/java/fr/maxlego08/zauctionhouse/search/SearchDialogService.java @@ -0,0 +1,177 @@ +package fr.maxlego08.zauctionhouse.search; + +import fr.maxlego08.zauctionhouse.ZAuctionPlugin; +import fr.maxlego08.zauctionhouse.api.cache.PlayerCacheKey; +import fr.maxlego08.zauctionhouse.api.filter.SearchField; +import fr.maxlego08.zauctionhouse.api.filter.SearchFilterType; +import fr.maxlego08.zauctionhouse.api.filter.SearchQuery; +import fr.maxlego08.zauctionhouse.api.inventories.Inventories; +import io.papermc.paper.connection.PlayerGameConnection; +import io.papermc.paper.dialog.Dialog; +import io.papermc.paper.dialog.DialogResponseView; +import io.papermc.paper.event.player.PlayerCustomClickEvent; +import io.papermc.paper.registry.data.dialog.ActionButton; +import io.papermc.paper.registry.data.dialog.DialogBase; +import io.papermc.paper.registry.data.dialog.action.DialogAction; +import io.papermc.paper.registry.data.dialog.body.DialogBody; +import io.papermc.paper.registry.data.dialog.input.DialogInput; +import io.papermc.paper.registry.data.dialog.input.SingleOptionDialogInput; +import io.papermc.paper.registry.data.dialog.type.DialogType; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +import java.util.List; +import java.util.Locale; + +public class SearchDialogService implements Listener { + + private static final String INPUT_QUERY = "query"; + private static final String INPUT_FIELD = "field"; + private static final String INPUT_MODE = "mode"; + private static final String FIELD_ALL = "all"; + private static final String MODE_CONTAINS = "contains"; + private static final String MODE_EXACT = "exact"; + private static final Key ACTION_SEARCH = Key.key("zauctionhouse", "search/apply"); + private static final Key ACTION_CLEAR = Key.key("zauctionhouse", "search/clear"); + private static final Key ACTION_CANCEL = Key.key("zauctionhouse", "search/cancel"); + + private final ZAuctionPlugin plugin; + + public SearchDialogService(ZAuctionPlugin plugin) { + this.plugin = plugin; + } + + public void openSearchDialog(Player player) { + openSearchDialog(player, currentQuery(player)); + } + + public void openSearchDialog(Player player, String initialQuery) { + SearchQuery initial = SearchQuery.parse(initialQuery, this.plugin.getConfiguration().getSearchFilter()); + String field = initialField(initial); + String mode = initialMode(initial); + String query = initial.value(); + + Dialog dialog = Dialog.create(builder -> builder.empty() + .base(DialogBase.builder(Component.text("Auction Search")) + .canCloseWithEscape(true) + .afterAction(DialogBase.DialogAfterAction.CLOSE) + .body(List.of(DialogBody.plainMessage(Component.text("Choose where to search, enter text, and confirm.")))) + .inputs(List.of( + DialogInput.text(INPUT_QUERY, Component.text("Search text")) + .width(300) + .initial(query) + .maxLength(128) + .build(), + DialogInput.singleOption(INPUT_FIELD, Component.text("Field"), List.of( + option(FIELD_ALL, "Everything", FIELD_ALL.equals(field)), + option(SearchField.NAME.getKey(), "Name", SearchField.NAME.getKey().equals(field)), + option(SearchField.LORE.getKey(), "Lore", SearchField.LORE.getKey().equals(field)), + option(SearchField.MATERIAL.getKey(), "Material", SearchField.MATERIAL.getKey().equals(field)), + option(SearchField.SELLER.getKey(), "Seller", SearchField.SELLER.getKey().equals(field)) + )) + .width(300) + .build(), + DialogInput.singleOption(INPUT_MODE, Component.text("Match"), List.of( + option(MODE_CONTAINS, "Contains", MODE_CONTAINS.equals(mode)), + option(MODE_EXACT, "Exact", MODE_EXACT.equals(mode)) + )) + .width(300) + .build() + )) + .build()) + .type(DialogType.multiAction(List.of( + actionButton("Search", "Apply this search.", ACTION_SEARCH), + actionButton("Clear", "Clear the active search.", ACTION_CLEAR) + ), actionButton("Cancel", "Return without changing search.", ACTION_CANCEL), 2)) + ); + + player.showDialog(dialog); + } + + @EventHandler + public void onCustomClick(PlayerCustomClickEvent event) { + if (!(event.getCommonConnection() instanceof PlayerGameConnection connection)) { + return; + } + + Player player = connection.getPlayer(); + Key identifier = event.getIdentifier(); + + if (ACTION_SEARCH.equals(identifier)) { + handleSearch(player, event.getDialogResponseView()); + } else if (ACTION_CLEAR.equals(identifier)) { + this.plugin.getAuctionManager().clearSearch(player); + openAuction(player); + } else if (ACTION_CANCEL.equals(identifier)) { + openAuction(player); + } + } + + private void handleSearch(Player player, DialogResponseView responseView) { + String query = safeText(responseView.getText(INPUT_QUERY)).trim(); + if (query.isBlank()) { + this.plugin.getAuctionManager().startSearch(player, query); + return; + } + + String field = safeKey(responseView.getText(INPUT_FIELD)); + String mode = safeKey(responseView.getText(INPUT_MODE)); + + SearchField searchField = SearchField.fromKey(field); + if (searchField == null) { + searchField = SearchField.ALL; + } + + SearchFilterType filterType = MODE_EXACT.equalsIgnoreCase(mode) + ? SearchFilterType.EQUALS_IGNORE_CASE + : SearchFilterType.CONTAINS_IGNORE_CASE; + String operator = this.plugin.getConfiguration().getSearchFilter().getOperator(filterType); + + this.plugin.getAuctionManager().startSearch(player, searchField.getKey() + " " + operator + " " + query); + } + + private void openAuction(Player player) { + int page = this.plugin.getAuctionManager().getCache(player).get(PlayerCacheKey.CURRENT_PAGE, 1); + this.plugin.getInventoriesLoader().openInventory(player, Inventories.AUCTION, page); + } + + private String currentQuery(Player player) { + String query = this.plugin.getAuctionManager().getCache(player).get(PlayerCacheKey.SEARCH_QUERY); + return query == null ? "" : query; + } + + private String initialField(SearchQuery query) { + return query.field() == null ? FIELD_ALL : query.field().getKey(); + } + + private String initialMode(SearchQuery query) { + if (query.type() == SearchFilterType.EQUALS || query.type() == SearchFilterType.EQUALS_IGNORE_CASE) { + return MODE_EXACT; + } + return MODE_CONTAINS; + } + + private static SingleOptionDialogInput.OptionEntry option(String id, String label, boolean initial) { + return SingleOptionDialogInput.OptionEntry.create(id, Component.text(label), initial); + } + + private static ActionButton actionButton(String label, String tooltip, Key key) { + return ActionButton.create( + Component.text(label), + Component.text(tooltip), + 100, + DialogAction.customClick(key, null) + ); + } + + private static String safeText(String value) { + return value == null ? "" : value; + } + + private static String safeKey(String value) { + return value == null ? "" : value.toLowerCase(Locale.ROOT); + } +} diff --git a/src/main/java/fr/maxlego08/zauctionhouse/services/SearchService.java b/src/main/java/fr/maxlego08/zauctionhouse/services/SearchService.java index bf6cd2b..2c37017 100644 --- a/src/main/java/fr/maxlego08/zauctionhouse/services/SearchService.java +++ b/src/main/java/fr/maxlego08/zauctionhouse/services/SearchService.java @@ -5,6 +5,8 @@ import fr.maxlego08.zauctionhouse.api.filter.SearchField; import fr.maxlego08.zauctionhouse.api.filter.SearchFilterType; import fr.maxlego08.zauctionhouse.api.filter.SearchQuery; +import fr.maxlego08.zauctionhouse.api.filter.SearchTextMatcher; +import fr.maxlego08.zauctionhouse.api.filter.SearchTextNormalizer; import fr.maxlego08.zauctionhouse.api.item.Item; import fr.maxlego08.zauctionhouse.api.item.SortItem; import fr.maxlego08.zauctionhouse.api.item.StorageType; @@ -51,14 +53,12 @@ public IntList search(SortedItemsCache sortedItemsCache, String query, SortItem itemMap.put(item.getId(), item); } - String lowerValue = parsedQuery.value().toLowerCase(); - for (int id : allIds) { Item item = itemMap.get(id); if (item == null) continue; if (parsedQuery.isDefault()) { - if (matchDefault(item, lowerValue)) { + if (matchDefault(item, parsedQuery.value())) { results.add(id); } } else { @@ -74,23 +74,25 @@ public IntList search(SortedItemsCache sortedItemsCache, String query, SortItem /** * Default match: substring case-insensitive on material name, display name, lore, and seller name. */ - private boolean matchDefault(Item item, String lowerQuery) { + private boolean matchDefault(Item item, String query) { + String normalizedQuery = SearchTextNormalizer.normalize(query); + // Material name - if (item.getTranslationKey() != null && item.getTranslationKey().toLowerCase().contains(lowerQuery)) { + if (item.getTranslationKey() != null && SearchTextNormalizer.normalize(item.getTranslationKey()).contains(normalizedQuery)) { return true; } // Check material type name if (item instanceof AuctionItem auctionItem) { ItemStack itemStack = auctionItem.getItemStack(); - if (itemStack != null && itemStack.getType().name().toLowerCase().contains(lowerQuery)) { + if (itemStack != null && SearchTextNormalizer.normalize(itemStack.getType().name()).contains(normalizedQuery)) { return true; } } // Display name String displayName = getDisplayName(item); - if (displayName != null && displayName.toLowerCase().contains(lowerQuery)) { + if (displayName != null && SearchTextNormalizer.normalize(displayName).contains(normalizedQuery)) { return true; } @@ -98,14 +100,14 @@ private boolean matchDefault(Item item, String lowerQuery) { List lore = getLore(item); if (lore != null) { for (String line : lore) { - if (line.toLowerCase().contains(lowerQuery)) { + if (SearchTextNormalizer.normalize(line).contains(normalizedQuery)) { return true; } } } // Seller name (exact case-insensitive) - if (item.getSellerName() != null && item.getSellerName().equalsIgnoreCase(lowerQuery)) { + if (item.getSellerName() != null && SearchTextNormalizer.normalize(item.getSellerName()).equals(normalizedQuery)) { return true; } @@ -116,6 +118,10 @@ private boolean matchDefault(Item item, String lowerQuery) { * Targeted match with a specific field and filter type. */ private boolean matchWithFilter(Item item, SearchField field, SearchFilterType type, String value) { + if (field == SearchField.ALL) { + return matchAllFields(item, type, value); + } + String fieldValue = getFieldValue(item, field); if (fieldValue == null) { // For the LORE field, check all lines @@ -134,16 +140,47 @@ private boolean matchWithFilter(Item item, SearchField field, SearchFilterType t } private boolean matchValue(String fieldValue, SearchFilterType type, String queryValue) { - return switch (type) { - case CONTAINS -> fieldValue.contains(queryValue); - case EQUALS -> fieldValue.equals(queryValue); - case CONTAINS_IGNORE_CASE -> fieldValue.toLowerCase().contains(queryValue.toLowerCase()); - case EQUALS_IGNORE_CASE -> fieldValue.equalsIgnoreCase(queryValue); - }; + return SearchTextMatcher.matches(fieldValue, type, queryValue); + } + + private boolean matchAllFields(Item item, SearchFilterType type, String value) { + String displayName = getDisplayName(item); + if (displayName != null && matchValue(displayName, type, value)) { + return true; + } + + if (item.getSellerName() != null && matchValue(item.getSellerName(), type, value)) { + return true; + } + + String translationKey = item.getTranslationKey(); + if (translationKey != null && matchValue(translationKey, type, value)) { + return true; + } + + if (item instanceof AuctionItem auctionItem) { + ItemStack itemStack = auctionItem.getItemStack(); + if (itemStack != null && matchValue(itemStack.getType().name(), type, value)) { + return true; + } + } + + List lore = getLore(item); + if (lore == null) { + return false; + } + + for (String line : lore) { + if (matchValue(line, type, value)) { + return true; + } + } + return false; } private String getFieldValue(Item item, SearchField field) { return switch (field) { + case ALL -> null; case NAME -> getDisplayName(item); case MATERIAL -> { if (item instanceof AuctionItem auctionItem) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index cacf5d2..b917027 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -281,7 +281,7 @@ commands: arguments: - name: query display-name: query - required: true + required: false auto-completion: [] # Page command: /zauctionhouse page diff --git a/src/main/resources/es/config.yml b/src/main/resources/es/config.yml index d5b765c..d1fe525 100644 --- a/src/main/resources/es/config.yml +++ b/src/main/resources/es/config.yml @@ -281,7 +281,7 @@ commands: arguments: - name: query display-name: consulta - required: true + required: false auto-completion: [] # Comando page: /zauctionhouse page diff --git a/src/main/resources/es/inventories/auction.yml b/src/main/resources/es/inventories/auction.yml index 0ecf970..ae8c884 100644 --- a/src/main/resources/es/inventories/auction.yml +++ b/src/main/resources/es/inventories/auction.yml @@ -211,7 +211,7 @@ items: #--------------------------------------------------------------------------- # BOTON BUSCAR #--------------------------------------------------------------------------- - # Abre la entrada de busqueda por chat para filtrar objetos. + # Abre el dialogo de busqueda para filtrar objetos. search: type: ZAUCTIONHOUSE_SEARCH @@ -224,19 +224,10 @@ items: - "" - "#92ffffBusqueda actual#8c8c8c: #2CCED2%search_query%" - "" - - "#92ffffFiltros#8c8c8c:" - - "#8c8c8c name #76CDCD~ #8c8c8cvalor #555555(contiene)" - - "#8c8c8c name #76CDCD= #8c8c8cvalor #555555(exacto)" - - "#8c8c8c name #76CDCD~= #8c8c8cvalor #555555(contiene, sin mayusculas)" - - "#8c8c8c name #76CDCD== #8c8c8cvalor #555555(exacto, sin mayusculas)" + - "#92ffffOpciones#8c8c8c: #76CDCDall#8c8c8c, #76CDCDname#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDseller" + - "#92ffffModos#8c8c8c: #76CDCDcontiene#8c8c8c, #76CDCDexacto" - "" - - "#92ffffCampos#8c8c8c: #76CDCDname#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDseller" - - "" - - "#92ffffEjemplos#8c8c8c:" - - "#8c8c8c seller #76CDCD= #8c8c8cNotch" - - "#8c8c8c name #76CDCD~ #8c8c8cDiamond" - - "" - - "#8c8c8c- #2CCED2Clic izquierdo #92ffffpara buscar" + - "#8c8c8c- #2CCED2Clic izquierdo #92ffffpara abrir el dialogo" - "#8c8c8c- #2CCED2Clic derecho #92ffffpara borrar la busqueda" #--------------------------------------------------------------------------- diff --git a/src/main/resources/es/messages.yml b/src/main/resources/es/messages.yml index 98ce927..c82222a 100644 --- a/src/main/resources/es/messages.yml +++ b/src/main/resources/es/messages.yml @@ -573,7 +573,7 @@ migration-failed: "La migracion ha fallado: %error%" # MENSAJES DE BUSQUEDA #============================================================================= -search-start: "<#8a8a8a>Por favor escribe tu busqueda en el chat." +search-start: "<#8a8a8a>Abriendo el dialogo de busqueda." search-cleared: "<#8a8a8a>Busqueda borrada." search-no-results: "<#8a8a8a>No se encontraron objetos para <#ffffff>%query%<#8a8a8a>." search-searching: "<#8a8a8a>Buscando <#ffffff>%query%<#8a8a8a>..." diff --git a/src/main/resources/fr/config.yml b/src/main/resources/fr/config.yml index 701b181..df8de6a 100644 --- a/src/main/resources/fr/config.yml +++ b/src/main/resources/fr/config.yml @@ -281,7 +281,7 @@ commands: arguments: - name: query display-name: recherche - required: true + required: false auto-completion: [] # Commande page: /zauctionhouse page diff --git a/src/main/resources/fr/inventories/auction.yml b/src/main/resources/fr/inventories/auction.yml index f60c26e..447c5e9 100644 --- a/src/main/resources/fr/inventories/auction.yml +++ b/src/main/resources/fr/inventories/auction.yml @@ -211,7 +211,7 @@ items: #--------------------------------------------------------------------------- # BOUTON RECHERCHE #--------------------------------------------------------------------------- - # Ouvre la saisie de recherche dans le chat pour filtrer les objets. + # Ouvre le dialogue de recherche pour filtrer les objets. search: type: ZAUCTIONHOUSE_SEARCH @@ -224,19 +224,10 @@ items: - "" - "#92ffffRecherche actuelle#8c8c8c: #2CCED2%search_query%" - "" - - "#92ffffFiltres#8c8c8c:" - - "#8c8c8c nom #76CDCD~ #8c8c8cvaleur #555555(contient)" - - "#8c8c8c nom #76CDCD= #8c8c8cvaleur #555555(exact)" - - "#8c8c8c nom #76CDCD~= #8c8c8cvaleur #555555(contient, sans casse)" - - "#8c8c8c nom #76CDCD== #8c8c8cvaleur #555555(exact, sans casse)" + - "#92ffffOptions#8c8c8c: #76CDCDall#8c8c8c, #76CDCDname#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDseller" + - "#92ffffModes#8c8c8c: #76CDCDcontient#8c8c8c, #76CDCDexact" - "" - - "#92ffffChamps#8c8c8c: #76CDCDname#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDseller" - - "" - - "#92ffffExemples#8c8c8c:" - - "#8c8c8c seller #76CDCD= #8c8c8cNotch" - - "#8c8c8c name #76CDCD~ #8c8c8cDiamond" - - "" - - "#8c8c8c- #2CCED2Clic gauche #92ffffpour rechercher" + - "#8c8c8c- #2CCED2Clic gauche #92ffffpour ouvrir le dialogue" - "#8c8c8c- #2CCED2Clic droit #92ffffpour effacer la recherche" #--------------------------------------------------------------------------- diff --git a/src/main/resources/fr/messages.yml b/src/main/resources/fr/messages.yml index 91a8e01..280a6fa 100644 --- a/src/main/resources/fr/messages.yml +++ b/src/main/resources/fr/messages.yml @@ -573,7 +573,7 @@ migration-failed: "La migration a échoué: %error%" # MESSAGES DE RECHERCHE #============================================================================= -search-start: "<#8a8a8a>Veuillez taper votre recherche dans le chat." +search-start: "<#8a8a8a>Ouverture du dialogue de recherche." search-cleared: "<#8a8a8a>Recherche effacée." search-no-results: "<#8a8a8a>Aucun objet trouvé pour <#ffffff>%query%<#8a8a8a>." search-searching: "<#8a8a8a>Recherche de <#ffffff>%query%<#8a8a8a>..." diff --git a/src/main/resources/inventories/auction.yml b/src/main/resources/inventories/auction.yml index d33501a..4c441a8 100644 --- a/src/main/resources/inventories/auction.yml +++ b/src/main/resources/inventories/auction.yml @@ -211,7 +211,7 @@ items: #--------------------------------------------------------------------------- # SEARCH BUTTON #--------------------------------------------------------------------------- - # Opens the chat search input for filtering items. + # Opens the search dialog for filtering items. search: type: ZAUCTIONHOUSE_SEARCH @@ -224,19 +224,10 @@ items: - "" - "#92ffffCurrent search#8c8c8c: #2CCED2%search_query%" - "" - - "#92ffffFilters#8c8c8c:" - - "#8c8c8c name #76CDCD~ #8c8c8cvalue #555555(contains)" - - "#8c8c8c name #76CDCD= #8c8c8cvalue #555555(exact)" - - "#8c8c8c name #76CDCD~= #8c8c8cvalue #555555(contains, ignore case)" - - "#8c8c8c name #76CDCD== #8c8c8cvalue #555555(exact, ignore case)" + - "#92ffffDialog options#8c8c8c: #76CDCDall#8c8c8c, #76CDCDname#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDseller" + - "#92ffffMatch modes#8c8c8c: #76CDCDcontains#8c8c8c, #76CDCDexact" - "" - - "#92ffffFields#8c8c8c: #76CDCDname#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDseller" - - "" - - "#92ffffExamples#8c8c8c:" - - "#8c8c8c seller #76CDCD= #8c8c8cNotch" - - "#8c8c8c name #76CDCD~ #8c8c8cDiamond" - - "" - - "#8c8c8c- #2CCED2Left-click #92ffffto search" + - "#8c8c8c- #2CCED2Left-click #92ffffto open search dialog" - "#8c8c8c- #2CCED2Right-click #92ffffto reset search" #--------------------------------------------------------------------------- # REFRESH BUTTON diff --git a/src/main/resources/it/config.yml b/src/main/resources/it/config.yml index 319fb38..c4ede33 100644 --- a/src/main/resources/it/config.yml +++ b/src/main/resources/it/config.yml @@ -281,7 +281,7 @@ commands: arguments: - name: query display-name: ricerca - required: true + required: false auto-completion: [] # Comando page: /zauctionhouse page diff --git a/src/main/resources/it/inventories/auction.yml b/src/main/resources/it/inventories/auction.yml index e16ac4a..abdebf1 100644 --- a/src/main/resources/it/inventories/auction.yml +++ b/src/main/resources/it/inventories/auction.yml @@ -211,7 +211,7 @@ items: #--------------------------------------------------------------------------- # PULSANTE CERCA #--------------------------------------------------------------------------- - # Apre l'input di ricerca nella chat per filtrare gli oggetti. + # Apre il dialogo di ricerca per filtrare gli oggetti. search: type: ZAUCTIONHOUSE_SEARCH @@ -224,19 +224,10 @@ items: - "" - "#92ffffRicerca attuale#8c8c8c: #2CCED2%search_query%" - "" - - "#92ffffFiltri#8c8c8c:" - - "#8c8c8c name #76CDCD~ #8c8c8cvalore #555555(contiene)" - - "#8c8c8c name #76CDCD= #8c8c8cvalore #555555(esatto)" - - "#8c8c8c name #76CDCD~= #8c8c8cvalore #555555(contiene, ignora maiuscole)" - - "#8c8c8c name #76CDCD== #8c8c8cvalore #555555(esatto, ignora maiuscole)" + - "#92ffffOpzioni#8c8c8c: #76CDCDall#8c8c8c, #76CDCDname#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDseller" + - "#92ffffModalita#8c8c8c: #76CDCDcontiene#8c8c8c, #76CDCDesatto" - "" - - "#92ffffCampi#8c8c8c: #76CDCDname#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDseller" - - "" - - "#92ffffEsempi#8c8c8c:" - - "#8c8c8c seller #76CDCD= #8c8c8cNotch" - - "#8c8c8c name #76CDCD~ #8c8c8cDiamond" - - "" - - "#8c8c8c- #2CCED2Clic sinistro #92ffffper cercare" + - "#8c8c8c- #2CCED2Clic sinistro #92ffffper aprire il dialogo" - "#8c8c8c- #2CCED2Clic destro #92ffffper cancellare la ricerca" #--------------------------------------------------------------------------- diff --git a/src/main/resources/it/messages.yml b/src/main/resources/it/messages.yml index fac3d8b..25d2c74 100644 --- a/src/main/resources/it/messages.yml +++ b/src/main/resources/it/messages.yml @@ -573,7 +573,7 @@ migration-failed: "La migrazione è fallita: %error%" # MESSAGGI DI RICERCA #============================================================================= -search-start: "<#8a8a8a>Scrivi la tua ricerca nella chat." +search-start: "<#8a8a8a>Apertura del dialogo di ricerca." search-cleared: "<#8a8a8a>Ricerca cancellata." search-no-results: "<#8a8a8a>Nessun oggetto trovato per <#ffffff>%query%<#8a8a8a>." search-searching: "<#8a8a8a>Ricerca di <#ffffff>%query%<#8a8a8a>..." diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index 947acc2..ea84d01 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -573,8 +573,8 @@ migration-failed: "Migration failed: %error%" # SEARCH MESSAGES #============================================================================= -# Shown when the player starts a search via chat. -search-start: "<#8a8a8a>Please type your search in the chat." +# Shown when the player opens the search dialog. +search-start: "<#8a8a8a>Opening search dialog." # Shown when the search is cleared. search-cleared: "<#8a8a8a>Search cleared." diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 94bf218..738062c 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,7 +1,7 @@ name: zAuctionHouse version: ${version} main: fr.maxlego08.zauctionhouse.ZAuctionPlugin -api-version: '1.20' +api-version: '1.21' authors: [ Maxlego08 ] description: Buy, resell, rent, bid your items! website: https://groupez.dev/ @@ -16,4 +16,4 @@ softdepend: - LuckPerms - AxShulkers libraries: - - org.mariadb.jdbc:mariadb-java-client:3.5.6 \ No newline at end of file + - org.mariadb.jdbc:mariadb-java-client:3.5.6 diff --git a/src/main/resources/th/config.yml b/src/main/resources/th/config.yml index 00b6cea..3589114 100644 --- a/src/main/resources/th/config.yml +++ b/src/main/resources/th/config.yml @@ -252,7 +252,7 @@ commands: arguments: - name: query display-name: query - required: true + required: false auto-completion: [] # คำสั่งเปิดหน้า: /zauctionhouse page @@ -1106,4 +1106,4 @@ admin-generate: # ถ้า true: แจกจ่ายจำนวนไอเท็มให้กระจายเท่า ๆ กันในแต่ละ economy # ถ้า false: สุ่ม economy ให้แต่ละไอเท็มแบบอิสระ - even-distribution: false \ No newline at end of file + even-distribution: false diff --git a/src/main/resources/th/inventories/auction.yml b/src/main/resources/th/inventories/auction.yml index 5c2d088..c62d3fa 100644 --- a/src/main/resources/th/inventories/auction.yml +++ b/src/main/resources/th/inventories/auction.yml @@ -222,19 +222,10 @@ items: - "" - "#92ffffค้นหาปัจจุบัน#8c8c8c: #2CCED2%search_query%" - "" - - "#92ffffตัวกรอง#8c8c8c:" - - "#8c8c8c name #76CDCD~ #8c8c8cค่า #555555(มีคำนี้)" - - "#8c8c8c name #76CDCD= #8c8c8cค่า #555555(ตรงทั้งหมด)" - - "#8c8c8c name #76CDCD~= #8c8c8cค่า #555555(มีคำนี้, ไม่สนตัวพิมพ์)" - - "#8c8c8c name #76CDCD== #8c8c8cค่า #555555(ตรงทั้งหมด, ไม่สนตัวพิมพ์)" + - "#92ffffOptions#8c8c8c: #76CDCDall#8c8c8c, #76CDCDname#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDseller" + - "#92ffffModes#8c8c8c: #76CDCDcontains#8c8c8c, #76CDCDexact" - "" - - "#92ffffฟิลด์#8c8c8c: #76CDCDname#8c8c8c, #76CDCDmaterial#8c8c8c, #76CDCDlore#8c8c8c, #76CDCDseller" - - "" - - "#92ffffตัวอย่าง#8c8c8c:" - - "#8c8c8c seller #76CDCD= #8c8c8cNotch" - - "#8c8c8c name #76CDCD~ #8c8c8cDiamond" - - "" - - "#8c8c8c• #2CCED2คลิก #92ffffเพื่อค้นหา" + - "#8c8c8c• #2CCED2Click #92ffffto open search dialog" #--------------------------------------------------------------------------- # ปุ่มรีเฟรช (REFRESH BUTTON) @@ -318,4 +309,4 @@ items: - "%ASCENDING_DATE%" - "%ASCENDING_PRICE%" - "" - - "#8c8c8c• #2CCED2คลิก #92ffffเพื่อเปลี่ยนรูปแบบการเรียง" \ No newline at end of file + - "#8c8c8c• #2CCED2คลิก #92ffffเพื่อเปลี่ยนรูปแบบการเรียง" diff --git a/src/main/resources/th/messages.yml b/src/main/resources/th/messages.yml index 62a151c..4302e76 100644 --- a/src/main/resources/th/messages.yml +++ b/src/main/resources/th/messages.yml @@ -573,7 +573,7 @@ migration-failed: "การย้ายข้อมูลล้มเห # ข้อความค้นหา #============================================================================= -search-start: "<#8a8a8a>กรุณาพิมพ์คำค้นหาในแชท" +search-start: "<#8a8a8a>Opening search dialog." search-cleared: "<#8a8a8a>ล้างการค้นหาแล้ว" search-no-results: "<#8a8a8a>ไม่พบไอเทมสำหรับ <#ffffff>%query%<#8a8a8a>" search-searching: "<#8a8a8a>กำลังค้นหา <#ffffff>%query%<#8a8a8a>..." @@ -598,4 +598,4 @@ admin-option-set: "ตั้งค่าตัวเลือก ตัวเลือกทั้งหมดของ %player% ถูกรีเซ็ตเป็นค่าเริ่มต้นแล้ว" admin-option-list-header: "ตัวเลือกสำหรับ %player%:" -remove-all-items: "#e6fff3คุณได้รับไอเทมคืนจำนวน %amount%<#e6fff3> ชิ้น" \ No newline at end of file +remove-all-items: "#e6fff3คุณได้รับไอเทมคืนจำนวน %amount%<#e6fff3> ชิ้น"