Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<version>1.18.38</version>
</path>
</annotationProcessorPaths>
</configuration>
Expand Down Expand Up @@ -247,7 +247,7 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.34</version>
<version>1.18.38</version>
<scope>provided</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -365,7 +365,7 @@
<dependency>
<groupId>net.wesjd</groupId>
<artifactId>anvilgui</artifactId>
<version>1.10.12-SNAPSHOT</version>
<version>1.10.13-SNAPSHOT</version>
<scope>compile</scope>
</dependency>

Expand Down
51 changes: 38 additions & 13 deletions src/main/java/com/balugaq/jeg/api/groups/SearchGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,22 @@ public class SearchGroup extends BaseGroup<SearchGroup> {
new Char2ObjectOpenHashMap<>(); // fast way for by display item name
public static final Map<String, Reference<Set<String>>> SPECIAL_CACHE = new HashMap<>();

/**
* Pre-built cache of display item names per Slimefun item ID.
* Populated once during {@link #init()} alongside CACHE2.
* <p>
* Key: Slimefun item ID.<br>
* Value: unmodifiable list of lower-cased display names from
* {@code getDisplayRecipes()}. Uses a hard reference (not SoftReference)
* so the cache is never evicted under memory pressure — the strings are
* cheap compared to retaining the live ItemStack objects.
* <p>
* Consumed by {@link com.balugaq.jeg.api.objects.enums.FilterType#BY_DISPLAY_ITEM_NAME}
* to match display-item names without ever calling {@code getDisplayRecipes()}
* at search time.
*/
public static final Map<String, List<String>> DISPLAY_ITEM_NAMES_CACHE = new ConcurrentHashMap<>(5000);

public static final Boolean SHOW_HIDDEN_ITEM_GROUPS =
Slimefun.getConfigManager().isShowHiddenItemGroupsInSearch();
public static final Integer DEFAULT_HASH_SIZE = 5000;
Expand Down Expand Up @@ -686,28 +702,37 @@ else if (Orecipes instanceof List<?> recipes) {
}
}
if (displayRecipes != null) {
List<String> displayNames = new ArrayList<>();
for (ItemStack itemStack : displayRecipes) {
if (itemStack != null) {
String name2 = ChatColor.stripColor(
ItemStackHelper.getDisplayName(itemStack));
for (char c : name2.toCharArray()) {
char d = Character.toLowerCase(c);
CACHE2.putIfAbsent(d, new SoftReference<>(new HashSet<>()));
Reference<Set<SlimefunItem>> ref = CACHE2.get(d);
if (ref != null) {
Set<SlimefunItem> set = ref.get();
if (set == null) {
set = new HashSet<>();
CACHE2.put(d, new SoftReference<>(set));
}
if (!inBanlist(slimefunItem)
&& !inBlacklist(slimefunItem)) {
set.add(slimefunItem);
if (!name2.isEmpty()) {
// Populate DISPLAY_ITEM_NAMES_CACHE for fast string-only lookup.
displayNames.add(name2.toLowerCase(Locale.ROOT));
// Also populate the character-index CACHE2 as before.
for (char c : name2.toCharArray()) {
char d = Character.toLowerCase(c);
CACHE2.putIfAbsent(d, new SoftReference<>(new HashSet<>()));
Reference<Set<SlimefunItem>> ref = CACHE2.get(d);
if (ref != null) {
Set<SlimefunItem> set = ref.get();
if (set == null) {
set = new HashSet<>();
CACHE2.put(d, new SoftReference<>(set));
}
if (!inBanlist(slimefunItem)
&& !inBlacklist(slimefunItem)) {
set.add(slimefunItem);
}
}
}
}
}
}
if (!displayNames.isEmpty()) {
DISPLAY_ITEM_NAMES_CACHE.put(slimefunItem.getId(), List.copyOf(displayNames));
}
}

String id = slimefunItem.getId();
Expand Down
49 changes: 9 additions & 40 deletions src/main/java/com/balugaq/jeg/api/objects/enums/FilterType.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,10 @@

import com.balugaq.jeg.api.groups.SearchGroup;
import com.balugaq.jeg.api.objects.collection.Pair;
import com.balugaq.jeg.utils.Debug;
import com.balugaq.jeg.utils.LocalHelper;
import com.balugaq.jeg.utils.SpecialMenuProvider;
import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.core.attributes.RecipeDisplayItem;
import io.github.thebusybiscuit.slimefun4.core.multiblocks.MultiBlockMachine;
import lombok.Getter;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
Expand Down Expand Up @@ -91,44 +86,18 @@ public enum FilterType {
BY_DISPLAY_ITEM_NAME(
Set.of("%", "产"),
(player, item, lowerFilterValue, pinyin) -> {
List<ItemStack> display = null;
if (item instanceof AContainer ac) {
// Fix: Cannot search item when SlimeCustomizer crashed
try {
display = ac.getDisplayRecipes();
} catch (Exception ignored) {
}
} else if (item instanceof MultiBlockMachine mb) {
// Fix: NullPointerException occurred when searching items from SlimeFood
try {
display = mb.getDisplayRecipes();
} catch (Exception ignored) {
}
} else {
try {
if (SpecialMenuProvider.ENABLED_LogiTech
&& SpecialMenuProvider.classLogiTech_CustomSlimefunItem != null
&& SpecialMenuProvider.classLogiTech_CustomSlimefunItem.isInstance(item)
&& item instanceof RecipeDisplayItem rdi) {
display = rdi.getDisplayRecipes();
}
} catch (Exception e) {
Debug.trace(e, "searching");
return false;
}
}
if (display != null) {
try {
for (ItemStack itemStack : display) {
if (SearchGroup.isSearchFilterApplicable(itemStack, lowerFilterValue, false)) {
return true;
}
}
} catch (Exception ignored) {
return false;
// Use the pre-built name cache populated during SearchGroup.init().
// This avoids calling getDisplayRecipes() at search time, which would
// clone SlimefunItemStacks, construct CraftMetaSkull/CraftPlayerProfile
// objects, and ultimately fire Mojang sessionserver HTTP requests.
List<String> cached = SearchGroup.DISPLAY_ITEM_NAMES_CACHE.get(item.getId());
if (cached != null) {
for (String name : cached) {
if (name.contains(lowerFilterValue)) return true;
}
}

// SPECIAL_CACHE: addons may register extra searchable strings at runtime.
String id = item.getId();
Reference<Set<String>> ref = SearchGroup.SPECIAL_CACHE.get(id);
if (ref != null) {
Expand Down