Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,24 @@ private void rebuildCards() {
? (List<IIngredientListElement<?>>) (List) Internal.getIngredientFilter().getIngredientList("")
: Collections.emptyList();

// Precompute UIDs once for all ingredients.
String[] elementUids = new String[ingredientList.size()];
for (int i = 0; i < ingredientList.size(); i++) {
IIngredientListElement<?> e = ingredientList.get(i);
@SuppressWarnings({"unchecked", "rawtypes"})
String uid = ((mezz.jei.api.ingredients.IIngredientHelper) e.getIngredientHelper()).getUniqueId(e.getIngredient());
elementUids[i] = uid;
}

for (CollapsibleGroup group : allGroups) {
CollapsedGroupIngredient ingredient = group.getIngredient();
List<IIngredientListElement<?>> previewItems = new ArrayList<>();
int itemCount = 0;
for (IIngredientListElement<?> element : ingredientList) {
if (ingredient.matches(element)) {
for (int i = 0; i < ingredientList.size(); i++) {
if (ingredient.matchesUid(elementUids[i])) {
itemCount++;
if (previewItems.size() < PREVIEW_FETCH_MAX) {
previewItems.add(element);
previewItems.add(ingredientList.get(i));
}
}
}
Expand Down Expand Up @@ -584,14 +593,6 @@ private <T> void renderIngredientTooltip(IIngredientListElement<T> element, int
}
}

/**
* Called when returning from the editor screen to refresh the card list.
*/
public void onEditorClosed() {
rebuildCards();
rebuildPageButtons();
}

private static class GroupCardEntry {
final String id;
final String displayName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import mezz.jei.gui.ingredients.IIngredientListElement;
import mezz.jei.ingredients.IngredientFilter;
import mezz.jei.ingredients.group.CollapsedGroupIngredient;
import mezz.jei.ingredients.group.CollapsibleGroup;
import mezz.jei.util.Translator;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
Expand Down Expand Up @@ -90,11 +91,14 @@ public class GuiCustomGroupEditor extends GuiScreen {
// Maps each right-panel element to its stored UID (exact or wildcard ending in ":*")
private final Map<IIngredientListElement<?>, String> selectedStackToStoredUid = new HashMap<>();

// Index of OTHER custom groups — used to tint items that already belong to a different group.
// Index of OTHER groups (any source: DEFAULT, MOD, CUSTOM) — used to tint items that already belong to a different group.
// Built once in initGui(); key = exact UID, value = list of display names.
private Map<String, List<String>> otherGroupExactUids = new HashMap<>();
// [prefix, displayName] pairs for wildcard entries in other groups
private List<String[]> otherGroupWildcardPrefixes = new ArrayList<>();
// Pre-computed set of UIDs (from filteredItems) that belong to another group — used for O(1)
// per-slot lookup in drawLeftGrid() instead of calling getOtherGroupNames() every frame.
private Set<String> otherGroupUidCache = new HashSet<>();

// Drag-select state
private boolean isDragging = false;
Expand Down Expand Up @@ -219,31 +223,51 @@ private boolean isUidSelected(String normalUid) {
}

/**
* Builds a reverse index of all other custom groups for fast membership lookup
* Builds a reverse index of all other groups (DEFAULT, MOD, and CUSTOM) for fast membership lookup.
*/
private void buildOtherGroupIndex() {
otherGroupExactUids.clear();
otherGroupWildcardPrefixes.clear();
CustomGroupsConfig cfg = Config.getCustomGroupsConfig();
if (cfg == null) return;
for (CustomGroupsConfig.CustomGroup g : cfg.getCustomGroups()) {
if (g.id.equals(group.id) || g.itemUids == null) continue;
String name = (g.displayName != null && !g.displayName.isEmpty()) ? g.displayName : g.id;
for (String uid : g.itemUids) {
otherGroupUidCache.clear();
Map<String, CollapsibleGroup> allGroups = Internal.getCollapsedGroupRegistry().getAllGroups();
for (Map.Entry<String, CollapsibleGroup> entry : allGroups.entrySet()) {
if (entry.getKey().equals(group.id)) continue;
CollapsedGroupIngredient ingredient = entry.getValue().getIngredient();
String name = ingredient.getDisplayName();
if (name == null || name.isEmpty()) name = entry.getKey();
for (String uid : ingredient.getUids()) {
if (uid.endsWith(":*")) {
otherGroupWildcardPrefixes.add(new String[]{uid.substring(0, uid.length() - 2), name});
} else {
otherGroupExactUids.computeIfAbsent(uid, k -> new ArrayList<>()).add(name);
}
}
}
rebuildOtherGroupUidCache();
}

/** Returns the names of other custom groups that contain the given normal UID, or an empty list. */
private void rebuildOtherGroupUidCache() {
otherGroupUidCache.clear();
for (IIngredientListElement element : filteredItems) {
String uid = getIngredientUid(element.getIngredient());
if (!otherGroupExactUids.isEmpty() && otherGroupExactUids.containsKey(uid)) {
otherGroupUidCache.add(uid);
} else {
for (String[] entry : otherGroupWildcardPrefixes) {
if (uid.startsWith(entry[0]) &&
(uid.length() == entry[0].length() || uid.charAt(entry[0].length()) == ':')) {
otherGroupUidCache.add(uid);
break;
}
}
}
}
}
private List<String> getOtherGroupNames(String normalUid) {
List<String> names = new ArrayList<>(otherGroupExactUids.getOrDefault(normalUid, Collections.emptyList()));
for (String[] entry : otherGroupWildcardPrefixes) {
if (normalUid.equals(entry[0]) || normalUid.startsWith(entry[0] + ":")) {
if (normalUid.startsWith(entry[0]) &&
(normalUid.length() == entry[0].length() || normalUid.charAt(entry[0].length()) == ':')) {
names.add(entry[1]);
}
}
Expand Down Expand Up @@ -345,6 +369,7 @@ private void updateFilteredItems() {
if (leftPage >= leftTotalPages) {
leftPage = leftTotalPages - 1;
}
rebuildOtherGroupUidCache();
}

private void updateSelectedStacks() {
Expand Down Expand Up @@ -443,7 +468,6 @@ private void saveAndClose() {
filter.notifyListenersOfChange();
}
}
parentScreen.onEditorClosed();
this.mc.displayGuiScreen(parentScreen);
}

Expand Down Expand Up @@ -560,7 +584,7 @@ private void drawLeftGrid(int mouseX, int mouseY) {

// Orange tint if this item belongs to another custom group
String uid = getIngredientUid(ingredient);
if (!getOtherGroupNames(uid).isEmpty()) {
if (otherGroupUidCache.contains(uid)) {
RenderHelper.disableStandardItemLighting();
GlStateManager.disableDepth();
GlStateManager.colorMask(true, true, true, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ public enum GroupSource {
private final GroupSource source;
private final List<IIngredientListElement<?>> filterElements;
private final Set<String> uids;
/** Pre-extracted from {@code uids}: the prefix before {@code :*} for each wildcard entry. */
private final List<String> wildcardPrefixes;
private final int backgroundColor;
private final int borderColor;

Expand All @@ -61,6 +63,17 @@ public CollapsedGroupIngredient(String id, String langKey, int backgroundColor,
this.filterElements = new ArrayList<>(uids.size());
this.backgroundColor = backgroundColor;
this.borderColor = borderColor;
// Pre-extract wildcard prefixes so matches() doesn't scan all UIDs on every call
List<String> wc = null;
for (String uid : uids) {
if (uid.endsWith(":*")) {
if (wc == null) {
wc = new ArrayList<>();
}
wc.add(uid.substring(0, uid.length() - 2));
}
}
this.wildcardPrefixes = wc != null ? Collections.unmodifiableList(wc) : Collections.emptyList();
}

public String getId() {
Expand Down Expand Up @@ -97,15 +110,21 @@ public void toggleExpanded() {

public boolean matches(IIngredientListElement element) {
String uid = element.getIngredientHelper().getUniqueId(element.getIngredient());
return matchesUid(uid);
}

/**
* Matches against a pre-computed UID string.
* Prefer this overload when checking many elements to avoid recomputing the UID per group.
*/
public boolean matchesUid(String uid) {
if (this.uids.contains(uid)) {
return true;
}
for (String stored : this.uids) {
if (stored.endsWith(":*")) {
String prefix = stored.substring(0, stored.length() - 2);
if (uid.equals(prefix) || uid.startsWith(prefix + ":")) {
return true;
}
for (String prefix : this.wildcardPrefixes) {
if (uid.startsWith(prefix) &&
(uid.length() == prefix.length() || uid.charAt(prefix.length()) == ':')) {
return true;
}
}
return false;
Expand Down