@@ -188,24 +188,79 @@ private boolean entryMatches(LootExportHelper.LootEntry entry, String query) {
188188 if (query .isEmpty ()) {
189189 return true ;
190190 }
191+ List <String > tokens = tokenizeQuery (query );
192+ if (tokens .isEmpty ()) {
193+ return true ;
194+ }
191195 for (LootExportHelper .LootItem item : entry .items ()) {
192- if (containsIgnoreCase ( item . itemId (), query ) || containsIgnoreCase ( item . displayName ( ), query ) || containsIgnoreCase ( item . nbt (), query )) {
196+ if (allTokensPresent ( buildItemSearchText ( item ), tokens )) {
193197 return true ;
194198 }
199+ }
200+ return allTokensPresent (normalizeSearchText (entry .type ()) + " " + normalizeSearchText (entry .pieceName ()), tokens );
201+ }
202+
203+ private static List <String > tokenizeQuery (String query ) {
204+ String normalized = normalizeSearchText (query );
205+ if (normalized .isBlank ()) {
206+ return List .of ();
207+ }
208+ return java .util .Arrays .stream (normalized .split ("\\ s+" ))
209+ .filter (token -> !token .isBlank ())
210+ .toList ();
211+ }
212+
213+ private static String buildItemSearchText (LootExportHelper .LootItem item ) {
214+ StringBuilder sb = new StringBuilder (160 );
215+ appendSearchField (sb , item .itemId ());
216+ appendSearchField (sb , item .displayName ());
217+ appendSearchField (sb , item .nbt ());
218+ if (item .enchantments () != null ) {
195219 for (String enchantment : item .enchantments ()) {
196- if (containsIgnoreCase (enchantment , query )) {
197- return true ;
198- }
220+ appendSearchField (sb , enchantment );
221+ }
222+ }
223+
224+ // Potion-like terms are usually in NBT; include explicit normalized aliases for easier matching.
225+ String nbt = normalizeSearchText (item .nbt ());
226+ if (!nbt .isBlank ()) {
227+ if (nbt .contains ("potion" )) {
228+ sb .append (" potion " );
199229 }
230+ if (nbt .contains ("effect" )) {
231+ sb .append (" effect effects " );
232+ }
233+ }
234+ return sb .toString ();
235+ }
236+
237+ private static void appendSearchField (StringBuilder sb , String value ) {
238+ String normalized = normalizeSearchText (value );
239+ if (!normalized .isBlank ()) {
240+ sb .append (normalized ).append (' ' );
200241 }
201- return containsIgnoreCase (entry .type (), query ) || containsIgnoreCase (entry .pieceName (), query );
202242 }
203243
204- private static boolean containsIgnoreCase (String value , String query ) {
205- if (value == null || value .isBlank ()) {
244+ private static boolean allTokensPresent (String haystack , List <String > tokens ) {
245+ if (tokens .isEmpty ()) {
246+ return true ;
247+ }
248+ if (haystack == null || haystack .isBlank ()) {
206249 return false ;
207250 }
208- return value .toLowerCase (Locale .ROOT ).contains (query );
251+ for (String token : tokens ) {
252+ if (!haystack .contains (token )) {
253+ return false ;
254+ }
255+ }
256+ return true ;
257+ }
258+
259+ private static String normalizeSearchText (String value ) {
260+ if (value == null ) {
261+ return "" ;
262+ }
263+ return value .toLowerCase (Locale .ROOT ).trim ();
209264 }
210265
211266 private void rebuildRowButtons () {
0 commit comments