From ea87e70599cf3a7af3c2c0acf682b7bb5559a4ef Mon Sep 17 00:00:00 2001 From: BrokenK3yboard <63761658+BrokenK3yboard@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:31:29 -0600 Subject: [PATCH] Refactor CreativeTabManager Use functions provided by Neoforge to add items to creative tabs. --- .../zeta/registry/CreativeTabManager.java | 258 ++++++------------ 1 file changed, 89 insertions(+), 169 deletions(-) diff --git a/src/main/java/org/violetmoon/zeta/registry/CreativeTabManager.java b/src/main/java/org/violetmoon/zeta/registry/CreativeTabManager.java index 4eb79bc..7ac0928 100644 --- a/src/main/java/org/violetmoon/zeta/registry/CreativeTabManager.java +++ b/src/main/java/org/violetmoon/zeta/registry/CreativeTabManager.java @@ -5,30 +5,19 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTab.TabVisibility; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ItemLike; -import net.neoforged.neoforge.common.util.MutableHashedLinkedMap; import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; import org.violetmoon.zeta.Zeta; import org.violetmoon.zeta.config.ZetaGeneralConfig; import org.violetmoon.zeta.module.IDisableable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; +import java.util.*; import java.util.function.Supplier; public class CreativeTabManager { private static final Object MUTEX = new Object(); - private static final Map itemLikeCache = new HashMap<>(); private static final Map, CreativeTabAdditions> additions = new HashMap<>(); private static final Multimap> mappedItems = HashMultimap.create(); @@ -47,15 +36,12 @@ public static void endDaisyChain() { } public static void addToCreativeTab(ResourceKey tab, ItemLike item) { - if(daisyChainMode) { - if(daisyChainedSet == null) - throw new IllegalArgumentException("Must start daisy chain with addToCreativeTabNextTo"); - + if (daisyChainMode) { + if (daisyChainedSet == null) throw new IllegalArgumentException("Must start daisy chain with addToCreativeTabNextTo"); addToDaisyChain(item); - } - else + } else { getForTab(tab).appendToEnd.add(item); - + } mappedItems.put(item, tab); } @@ -63,27 +49,26 @@ public static void addToCreativeTabNextTo(ResourceKey tab, Item tab = guessTab(target, tab); CreativeTabAdditions additions = getForTab(tab); Map map = (behind ? additions.appendBehind : additions.appendInFront); - ItemSet toAdd = null; if(daisyChainMode) { boolean newSet = daisyChainedSet == null; ItemSet set = addToDaisyChain(item); - + if(newSet) toAdd = set; - } - else + } else { toAdd = new ItemSet(item); + } if(toAdd != null) map.put(toAdd, target); - + mappedItems.put(item, tab); } private static ItemSet addToDaisyChain(ItemLike item) { - if(daisyChainMode && daisyChainedSet != null) { + if (daisyChainMode && daisyChainedSet != null) { daisyChainedSet.items.add(item); return daisyChainedSet; } @@ -96,11 +81,8 @@ private static ItemSet addToDaisyChain(ItemLike item) { } private static ResourceKey guessTab(ItemLike parent, ResourceKey tab) { - if(parent != null && mappedItems.containsKey(parent)) - tab = mappedItems.get(parent).iterator().next(); - - return tab; - } + return (parent != null && mappedItems.containsKey(parent)) ? mappedItems.get(parent).iterator().next() : tab; + } private static CreativeTabAdditions getForTab(ResourceKey tab) { return additions.computeIfAbsent(tab, tabRk -> new CreativeTabAdditions()); @@ -108,171 +90,111 @@ private static CreativeTabAdditions getForTab(ResourceKey tab) public static void buildContents(BuildCreativeModeTabContentsEvent event) { synchronized(MUTEX) { + ResourceKey tabKey = event.getTabKey(); - MutableHashedLinkedMap entries = event.getEntries(); if(additions.containsKey(tabKey)) { CreativeTabAdditions add = additions.get(tabKey); - for(ItemLike item : add.appendToEnd) + for(ItemLike item : add.appendToEnd) { acceptItem(event, item); - + } + if(ZetaGeneralConfig.forceCreativeTabAppends) { for(ItemSet itemset : add.appendInFront.keySet()) for(ItemLike item : itemset.items) acceptItem(event, item); + for(ItemSet itemset : add.appendBehind.keySet()) for(ItemLike item : itemset.items) acceptItem(event, item); - return; } - + Map front = new LinkedHashMap<>(add.appendInFront); Map behind = new LinkedHashMap<>(add.appendBehind); - - final int failsafe = 100; - final int printThreshold = failsafe - 10; - - int misses = 0; - boolean failsafing = false; - - while(true) { - boolean missed = false; - logVerbose(() -> "front empty=" + front.isEmpty() + " / behind empty=" + behind.isEmpty()); - - if(entries.isEmpty()) { - Zeta.GLOBAL_LOG.error("entries map for tab " + tabKey + " is empty, this should never happen"); - return; - } - - if(!front.isEmpty()) - missed = appendNextTo(tabKey, entries, front, false, failsafing); - if(!behind.isEmpty()) - missed |= appendNextTo(tabKey, entries, behind, true, failsafing); - - if(missed) { - int fMisses = misses; - logVerbose(() -> "Missed " + fMisses + "times out of " + failsafe); - - misses++; - } - - // arbitrary failsafe, should never happen - if(misses > failsafe) { - logVerbose(() -> { - StringBuilder sb = new StringBuilder(); - for(Entry entry : entries) { - sb.append(entry.getKey()); - sb.append("; "); - } - return sb.toString(); - }); - new RuntimeException("Creative tab placement misses exceeded failsafe, aborting logic").printStackTrace(); - return; - } - if(misses > printThreshold) - failsafing = true; - - if(front.isEmpty() && behind.isEmpty()) - return; - } + final int maxFails = 100; + final int logThreshold = maxFails - 10; + int failedAttempts = 0; + + while (failedAttempts < 100) { + if (!front.isEmpty()) { + failedAttempts = addItems(event, front, false, failedAttempts > logThreshold) ? failedAttempts : failedAttempts + 1; + } + if (!behind.isEmpty()) { + failedAttempts = addItems(event, behind, true, failedAttempts > logThreshold) ? failedAttempts : failedAttempts + 1; + } + } } } } - private static boolean isItemEnabled(ItemLike item) { - if(item instanceof IDisableable id) - return id.isEnabled(); - - return true; - } - - private static void acceptItem(BuildCreativeModeTabContentsEvent event, ItemLike item) { - if(!isItemEnabled(item)) - return; - - if(item instanceof AppendsUniquely au) - event.acceptAll(au.appendItemsToCreativeTab()); - else - event.accept(item); - } - - private static void addToEntries(ItemStack target, MutableHashedLinkedMap entries, ItemLike item, boolean behind) { - logVerbose(() -> "adding target=" + target + " next to " + item + " with behind=" + behind); - if(!isItemEnabled(item)) - return; - - List stacksToAdd = Arrays.asList(new ItemStack(item)); - if(item instanceof AppendsUniquely au) - stacksToAdd = au.appendItemsToCreativeTab(); - - if(!behind) - Collections.reverse(stacksToAdd); - - for(ItemStack addStack : stacksToAdd) { - if(behind) - entries.putBefore(target, addStack, TabVisibility.PARENT_AND_SEARCH_TABS); - else - entries.putAfter(target, addStack, TabVisibility.PARENT_AND_SEARCH_TABS); - } - } + private static boolean addItems(BuildCreativeModeTabContentsEvent event, Map itemsMap, boolean insertAfter, boolean log) { + Collection collection = itemsMap.keySet(); + ItemSet itemsToAdd = collection.iterator().next(); + ItemLike firstSetItem = itemsToAdd.items.getFirst(); + ItemLike target = itemsMap.get(itemsToAdd); + logVerbose(() -> "target is " + target); - /** - * Returns true if the item needs to be tried again later - */ - private static boolean appendNextTo(ResourceKey tabKey, MutableHashedLinkedMap entries, Map map, boolean behind, boolean log) { - logVerbose(() -> "appendNextTo " + tabKey + " / behind=" + behind); - Collection coll = map.keySet(); - if(coll.isEmpty()) - throw new RuntimeException("Tab collection is empty, this should never happen."); + itemsMap.remove(itemsToAdd); - ItemSet firstSet = coll.iterator().next(); - ItemLike firstSetItem = firstSet.items.get(0); - ItemLike target = map.get(firstSet); - logVerbose(() -> "target is " + target); - if(log) { Zeta.GLOBAL_LOG.error("Creative tab loop found when adding {} next to {}", firstSetItem, target); Zeta.GLOBAL_LOG.error("For more info enable Creative Verbose Logging in the Zeta config, or set Force Creative Tab Appends to true to disable this behavior"); } - - map.remove(firstSet); - - if(!isItemEnabled(firstSetItem) || target == null) { - logVerbose(() -> "hit early false return"); - return false; - } - - if(!itemLikeCache.containsKey(target)) - itemLikeCache.put(target, target.asItem()); - Item targetItem = itemLikeCache.get(target); - - for(Entry entry : entries) { - ItemStack stack = entry.getKey(); - Item item = stack.getItem(); - - logVerbose(() -> "Comparing item " + item + " to our target " + targetItem); - - if(item == targetItem) { - logVerbose(() -> "Matched! Adding successfully"); - for(int i = 0; i < firstSet.items.size(); i++) { - int j = i; - if(!behind) - j = firstSet.items.size() - 1 - i; - - addToEntries(stack, entries, firstSet.items.get(j), behind); + + if (!isItemEnabled(firstSetItem) || target == null) return true; + + ItemStack targetStack = new ItemStack(target); + + for (ItemLike item : itemsToAdd.items) { + if (!isItemEnabled(item)) continue; + List stacksToAdd = List.of(new ItemStack(item)); + + if (item instanceof AppendsUniquely au) { + stacksToAdd = au.appendItemsToCreativeTab(); + } + + if(!insertAfter) { + Collections.reverse(stacksToAdd); + } + + for(ItemStack addStack : stacksToAdd) { + if (insertAfter) { + try { + event.insertAfter(targetStack, addStack, TabVisibility.PARENT_AND_SEARCH_TABS); + } catch (IllegalArgumentException exception) { + logVerbose(exception::getMessage); + itemsMap.put(itemsToAdd, target); + return false; + } + } else { + try { + event.insertBefore(targetStack, addStack, TabVisibility.PARENT_AND_SEARCH_TABS); + } catch (IllegalArgumentException exception) { + logVerbose(exception::getMessage); + itemsMap.put(itemsToAdd, target); + return false; + } } - - return false; } } - - // put the set back at the end of the map to try it again after the target is added - map.put(firstSet, target); return true; } - + + private static boolean isItemEnabled(ItemLike item) { + return !(item instanceof IDisableable id) || id.isEnabled(); + } + + private static void acceptItem(BuildCreativeModeTabContentsEvent event, ItemLike item) { + if (!isItemEnabled(item)) return; + + if(item instanceof AppendsUniquely au) + event.acceptAll(au.appendItemsToCreativeTab()); + else + event.accept(item); + } + private static void logVerbose(Supplier s) { if(ZetaGeneralConfig.enableCreativeVerboseLogging) Zeta.GLOBAL_LOG.warn(s.get()); @@ -280,10 +202,9 @@ private static void logVerbose(Supplier s) { private static class CreativeTabAdditions { - private List appendToEnd = new ArrayList<>(); - private Map appendInFront = new LinkedHashMap<>(); - private Map appendBehind = new LinkedHashMap<>(); - + private final List appendToEnd = new ArrayList<>(); + private final Map appendInFront = new LinkedHashMap<>(); + private final Map appendBehind = new LinkedHashMap<>(); } private static class ItemSet { @@ -293,10 +214,9 @@ private static class ItemSet { public ItemSet(ItemLike item) { items.add(item); } - } public interface AppendsUniquely extends ItemLike { List appendItemsToCreativeTab(); } -} +} \ No newline at end of file