Compare commits

...
Author SHA1 Message Date
slprime 7d4c8b82ba Add custom render for PositionedStack (#1002) 2026-08-13 21:49:05 +03:00
slprime c6170f9795 Bookmarks: Fix Permutations with different amount (#1000) 2026-08-12 22:45:39 +03:00
Dream Master 5a533c8994 update+gradle+bs+deps 2026-08-11 00:26:14 +07:00
Nikolay S.andslprime d70a47a3a4 Modernize Java code (#997)
Co-authored-by: slprime <31038811+slprime@users.noreply.github.com>
2026-08-10 14:55:40 +03:00
boubou19andgithub-actions[bot] 6c3db443d7 Cache enum .values() (#998)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-10 07:40:36 +02:00
boubou19 a51836fe9b Optimize updateUnlimitedItems (#995) 2026-08-07 19:05:01 +03:00
slprime 139ca22e51 Fix Untranslator With Broken Item (#993) 2026-08-04 19:43:34 +03:00
slprime 10fc78bdcf Add Recipe Filter syntax tooltip (#992) 2026-08-04 19:18:27 +03:00
50 changed files with 447 additions and 249 deletions

No files matched your search

+5 -4
View File
@@ -5,12 +5,13 @@ configurations.create('gtnhlibEmbed') {
}
dependencies {
api('com.github.GTNewHorizons:CodeChickenCore:1.4.16:dev')
devOnlyNonPublishable('com.github.GTNewHorizons:GTNHLib:0.11.23:dev')
api('com.github.GTNewHorizons:CodeChickenCore:1.4.17:dev')
devOnlyNonPublishable('com.github.GTNewHorizons:GTNHLib:0.11.37:dev')
shadowImplementation('org.apache.commons:commons-csv:1.10.0')
compileOnly('maven.modrinth:forge-essentials:7.5.1')
compileOnly('com.cardinalstar.cubicchunks:CubicChunks1710:v0.1.14-alpha:dev')
antlr('org.antlr:antlr4:4.13.2')
shadowImplementation('org.antlr:antlr4-runtime:4.13.2')
@@ -22,8 +23,8 @@ dependencies {
testRuntimeOnly('org.junit.platform:junit-platform-launcher')
testRuntimeOnly("org.lwjgl.lwjgl:lwjgl:2.9.3");
compileOnly("com.github.GTNewHorizons:GTNHLib:0.11.23") { transitive = false }
gtnhlibEmbed("com.github.GTNewHorizons:GTNHLib:0.11.23") { transitive = false }
compileOnly("com.github.GTNewHorizons:GTNHLib:0.11.37") { transitive = false }
gtnhlibEmbed("com.github.GTNewHorizons:GTNHLib:0.11.37") { transitive = false }
}
[tasks.jar, tasks.shadowJar].each {
+10 -10
View File
@@ -1,12 +1,12 @@
#This file is generated by updateDaemonJvm
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c2dd35c9d0aaf0ba6ad0791320f99dfc/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/e5810bd7fd1f8a586644409d395a7e55/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/7b3c4877c0749019e6805bb61e421497/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d76df094a9cbbabd3b08251f9e61444a/redirect
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/97d46b5ff4df0bf61e95652a190a5567/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/9ef54a08e06b0754cee9fc95ed3a3134/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/97d46b5ff4df0bf61e95652a190a5567/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/9ef54a08e06b0754cee9fc95ed3a3134/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1df82b76031285ef2e6a4f59ffe9299d/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/c7d5be6a02945ac2e045048ee54a7d32/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/97d46b5ff4df0bf61e95652a190a5567/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/9ef54a08e06b0754cee9fc95ed3a3134/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/643f404f769811f5f265fd66f7af5d89/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/38256085a73e137cb4937ea9c4807fec/redirect
toolchainVersion=25
+1 -1
View File
@@ -17,7 +17,7 @@ pluginManagement {
}
plugins {
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.26'
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.29'
}
@@ -913,9 +913,7 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
this.grid.createRecipeChainMath(groupId));
}
if (this.recipeChainTooltipLineHandler != null) {
currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.recipeChainTooltipLineHandler));
}
currenttip.add(GuiDraw.TOOLTIP_HANDLER + GuiDraw.getTipLineId(this.recipeChainTooltipLineHandler));
return currenttip;
}
@@ -1096,10 +1094,13 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
}
activeStack = items.get((items.size() - shift + stackIndex) % items.size());
this.acceptsFollowingTooltipLineHandler.setActiveStack(activeStack);
this.grid.getBookmarkItem(Math.abs(itemIndex)).itemStack = activeStack;
this.grid.onItemsChanged();
final int targetItemIndex = Math.abs(itemIndex);
final BookmarkItem oldItem = this.grid.getBookmarkItem(targetItemIndex);
final BookmarkItem newItem = oldItem.copyWithPerm(activeStack);
this.grid.replaceBookmarkItem(targetItemIndex, newItem);
}
return true;
@@ -112,7 +112,7 @@ public class CollapsibleItems {
group.setFilter(itemStr);
}
if (group != null && group.filter != null) {
if (group.filter != null) {
addGroup(group);
group = new GroupItem();
}
@@ -79,14 +79,13 @@ public class ContainerCreativeInv extends Container {
@Override
public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int slotIndex) {
ItemStack transferredStack = null;
Slot slot = (Slot) inventorySlots.get(slotIndex);
Slot slot = inventorySlots.get(slotIndex);
if (slot != null && slot.getHasStack()) {
ItemStack stack = slot.getStack();
transferredStack = stack.copy();
if (stack.getItem() instanceof ItemArmor) {
ItemArmor armor = (ItemArmor) stack.getItem();
if (stack.getItem() instanceof ItemArmor armor) {
if (!getSlot(90 + armor.armorType).getHasStack()) {
getSlot(90 + armor.armorType).putStack(transferredStack);
slot.putStack(null);
@@ -8,7 +8,6 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.ContainerEnchantment;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagList;
@@ -164,14 +163,14 @@ public class ContainerEnchantmentModifier extends ContainerEnchantment {
public boolean addEnchantment(int e, int level) {
if (e < Enchantment.enchantmentsList.length && Enchantment.enchantmentsList[e] != null) {
((Slot) inventorySlots.get(0)).getStack().addEnchantment(Enchantment.enchantmentsList[e], level);
inventorySlots.get(0).getStack().addEnchantment(Enchantment.enchantmentsList[e], level);
return true;
}
return false;
}
public void removeEnchantment(int e) {
ItemStack stack = ((Slot) inventorySlots.get(0)).getStack();
ItemStack stack = inventorySlots.get(0).getStack();
NBTTagList nbttaglist = stack.getEnchantmentTagList();
if (nbttaglist != null) {
for (int i = 0; i < nbttaglist.tagCount(); i++) {
@@ -20,7 +20,7 @@ public class DefaultHighlightHandler implements IHighlightHandler {
String name = null;
try {
String s = GuiContainerManager.itemDisplayNameShort(stack);
if (s != null && !s.endsWith("Unnamed")) name = s;
if (!s.endsWith("Unnamed")) name = s;
if (name != null) currenttip.add(name);
} catch (Exception ignored) {}
@@ -91,7 +91,7 @@ public class FastTransferManager {
public static void clearSlots(Container container) {
for (int slotNo = 0; slotNo < container.inventorySlots.size(); slotNo++)
((Slot) container.inventorySlots.get(slotNo)).putStack(null);
container.inventorySlots.get(slotNo).putStack(null);
}
public void performMassTransfer(GuiContainer window, int fromSlot, int toSlot, ItemStack heldStack) {
@@ -289,7 +289,7 @@ public class FastTransferManager {
if (held == null) return -1;
for (int i = 0; held != null && i < window.inventorySlots.inventorySlots.size(); i++) {
for (int i = 0; i < window.inventorySlots.inventorySlots.size(); i++) {
final Slot slot = window.inventorySlots.inventorySlots.get(i);
if (slot.inventory instanceof InventoryPlayer && !slot.getHasStack() && slot.isItemValid(held)) {
@@ -82,8 +82,8 @@ public class GuiEnchantmentModifier extends GuiContainer {
private void changeLevel(int i) {
container.level += i;
((GuiButton) buttonList.get(0)).enabled = container.level != 1;
((GuiButton) buttonList.get(1)).enabled = container.level != 10;
buttonList.get(0).enabled = container.level != 1;
buttonList.get(1).enabled = container.level != 10;
}
protected void mouseClicked(int i, int j, int k) {
@@ -30,14 +30,7 @@ public class InfiniteStackSizeHandler implements IInfiniteItemHandler {
@Override
public void replenishInfiniteStack(InventoryPlayer inv, int slotNo) {
ItemStack stack = inv.getStackInSlot(slotNo);
stack.stackSize = 111;
for (int i = 0; i < inv.getSizeInventory(); i++) {
if (i == slotNo) continue;
if (NEIServerUtils.areStacksSameType(stack, inv.getStackInSlot(i))) inv.setInventorySlotContents(i, null);
}
inv.getStackInSlot(slotNo).stackSize = 111;
}
@Override
@@ -241,7 +241,7 @@ public class ItemCraftablesPanel
private GuiContainer getGuiContainer() {
final GuiContainer firstGui = NEIClientUtils.getGuiContainer();
return (firstGui instanceof GuiRecipe gui) ? gui.firstGui : firstGui;
return (firstGui instanceof GuiRecipe<?>gui) ? gui.firstGui : firstGui;
}
private Map<ItemStack, RecipeId> generateCraftables(GuiContainer firstGui) {
@@ -150,8 +150,7 @@ public class ItemListLoader {
if (item == null) {
return;
}
if (item instanceof IFluidContainerItem) {
IFluidContainerItem fluidItem = (IFluidContainerItem) item;
if (item instanceof IFluidContainerItem fluidItem) {
runChecked(stack, () -> fluidItem.getFluid(stack), "getFluid");
}
runChecked(stack, () -> item.isDamaged(stack), "isDamaged");
@@ -100,7 +100,7 @@ public class ItemMobSpawner extends ItemBlock {
return true;
}
return placed;
return false;
}
private String getMobTypeFromItemStack(ItemStack stack) {
@@ -238,7 +238,6 @@ public class ItemMobSpawner extends ItemBlock {
NEIClientConfig.logger.debug("Cleared all entity references from cache");
}
@SuppressWarnings("unchecked")
public static void loadSpawners() {
if (loaded) {
return;
@@ -246,8 +245,7 @@ public class ItemMobSpawner extends ItemBlock {
synchronized (ItemMobSpawner.class) {
try {
for (Map.Entry<Class<? extends Entity>, String> entry : ((Map<Class<? extends Entity>, String>) EntityList.classToStringMapping)
.entrySet()) {
for (Map.Entry<Class<? extends Entity>, String> entry : EntityList.classToStringMapping.entrySet()) {
Class<? extends Entity> clazz = entry.getKey();
String name = entry.getValue();
@@ -323,7 +321,7 @@ public class ItemMobSpawner extends ItemBlock {
String name = ENTITY_CLASS_TO_NAME_CACHE.get(entityClass);
if (name == null) {
name = (String) EntityList.classToStringMapping.get(entityClass);
name = EntityList.classToStringMapping.get(entityClass);
}
return name != null && shouldRegisterEntity(entityClass, name);
@@ -46,8 +46,7 @@ public class ItemStackMap<T> {
}
public boolean equals(Object o) {
if (!(o instanceof StackMetaKey)) return false;
StackMetaKey t = (StackMetaKey) o;
if (!(o instanceof StackMetaKey t)) return false;
return damage == t.damage && Objects.equal(tag, t.tag);
}
}
@@ -218,8 +217,7 @@ public class ItemStackMap<T> {
public void put(ItemStack key, T value) {
if (key == null || key.getItem() == null) return;
DetailMap map = itemMap.get(key.getItem());
if (map == null) itemMap.put(key.getItem(), map = new DetailMap());
DetailMap map = itemMap.computeIfAbsent(key.getItem(), k -> new DetailMap());
map.put(key, value);
}
@@ -921,9 +921,7 @@ public class NEIClientConfig {
return;
}
if (ItemPanels.bookmarkPanel != null) {
ItemPanels.bookmarkPanel.save();
}
ItemPanels.bookmarkPanel.save();
SubsetWidget.saveHidden();
FavoriteRecipes.save();
@@ -4,13 +4,13 @@ import static codechicken.lib.gui.GuiDraw.getMousePosition;
import static codechicken.nei.NEIClientConfig.canCheatItem;
import java.awt.Point;
import java.util.LinkedList;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.inventory.GuiContainerCreative;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Slot;
import net.minecraft.inventory.SlotCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraftforge.client.ClientCommandHandler;
@@ -77,29 +77,38 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
public static void updateUnlimitedItems(InventoryPlayer inventory) {
if (!NEIClientConfig.canPerformAction("item") || !NEIClientConfig.hasSMPCounterPart()) return;
LinkedList<ItemStack> beforeStacks = new LinkedList<>();
for (int i = 0; i < inventory.getSizeInventory(); i++)
beforeStacks.add(NEIServerUtils.copyStack(inventory.getStackInSlot(i)));
for (int i = 0; i < inventory.getSizeInventory(); i++) {
int size = inventory.getSizeInventory();
for (int i = 0; i < size; i++) {
ItemStack stack = inventory.getStackInSlot(i);
if (stack == null) continue;
for (IInfiniteItemHandler handler : ItemInfo.infiniteHandlers)
if (handler.canHandleItem(stack) && handler.isItemInfinite(stack))
handler.replenishInfiniteStack(inventory, i);
}
for (IInfiniteItemHandler handler : ItemInfo.infiniteHandlers) {
if (!handler.canHandleItem(stack) || !handler.isItemInfinite(stack)) continue;
for (int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack newstack = inventory.getStackInSlot(i);
long beforeSize = packStackSize(stack.stackSize, stack.getItemDamage());
handler.replenishInfiniteStack(inventory, i);
if (!NEIServerUtils.areStacksIdentical(beforeStacks.get(i), newstack)) {
inventory.setInventorySlotContents(i, beforeStacks.get(i)); // restore in case of SMP fail
NEIClientUtils.setSlotContents(i, newstack, false); // sends via SMP handler ;)
ItemStack newstack = inventory.getStackInSlot(i);
if (!sameStack(stack, beforeSize, newstack)) {
NEIClientUtils.setSlotContents(i, newstack, false); // sends via SMP handler ;)
stack.stackSize = (int) (beforeSize >> 32);
stack.setItemDamage((int) beforeSize);
inventory.setInventorySlotContents(i, stack); // restore in case of SMP fail
}
}
}
}
private static long packStackSize(int stackSize, int itemDamage) {
return ((long) stackSize << 32) | (itemDamage & 0xFFFFFFFFL);
}
private static boolean sameStack(ItemStack before, long beforeSize, ItemStack stack) {
if (stack == null) return before == null;
return before != null && Item.getIdFromItem(before.getItem()) == Item.getIdFromItem(stack.getItem())
&& beforeSize == packStackSize(stack.stackSize, stack.getItemDamage());
}
public static void processCreativeCycling(InventoryPlayer inventory) {
if (NEIClientConfig.invCreativeMode() && NEIClientUtils.controlKey()) {
if (selectedItem != inventory.currentItem) {
@@ -34,7 +34,6 @@ import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.WorldSettings.GameType;
import net.minecraftforge.oredict.OreDictionary;
@@ -76,7 +75,7 @@ public class NEIServerUtils {
public static void toggleRaining(World world, boolean notify) {
boolean raining = !world.isRaining();
if (!raining) // turn off
((WorldServer) world).provider.resetRainAndThunder();
world.provider.resetRainAndThunder();
else world.getWorldInfo().setRaining(!isRaining(world));
if (notify)
@@ -262,9 +261,6 @@ public class NEIServerUtils {
/**
* GT Items don't have any NBT set for the recipe, so if either of the stacks has a NULL nbt, and the other doesn't,
* pretend they stack
*
* @param ItemStack stack
* @return
*/
public static boolean isItemTool(ItemStack stack) {
return GTMetaBaseItemHolder.gtMetaBaseItem != null
@@ -456,7 +452,7 @@ public class NEIServerUtils {
}
public static List<Integer> getRange(final int start, final int end) {
return new AbstractList<Integer>() {
return new AbstractList<>() {
@Override
public Integer get(int index) {
@@ -13,6 +13,7 @@ import net.minecraftforge.oredict.OreDictionary;
import codechicken.nei.api.ItemFilter;
import codechicken.nei.api.ItemInfo;
import codechicken.nei.guihook.GuiContainerManager;
import codechicken.nei.recipe.Badge;
import codechicken.nei.recipe.GuiRecipe;
import codechicken.nei.recipe.StackInfo;
@@ -20,19 +21,21 @@ import codechicken.nei.recipe.StackInfo;
/**
* Simply an {@link ItemStack} with position. Mainly used in the recipe handlers.
*/
public class PositionedStack {
public class PositionedStack implements Cloneable {
/** Maximum chance value representing 100% probability (1 unit = 0.01%). */
public static final int CHANCE_FULL = 10_000;
public int relx;
public int rely;
public int width = 16;
public int height = 16;
public ItemStack[] items;
// compatibility dummy
public ItemStack item;
protected int chance = CHANCE_FULL;
private boolean permutated = false;
protected boolean permutated = false;
public PositionedStack(Object object, int x, int y, boolean genPerms) {
items = NEIServerUtils.extractRecipeItems(object);
@@ -91,6 +94,10 @@ public class PositionedStack {
return null;
}
public List<String> getTooltip() {
return null;
}
public int getChance() {
return this.chance;
}
@@ -100,14 +107,20 @@ public class PositionedStack {
}
public PositionedStack copy() {
PositionedStack pStack = new PositionedStack(
Arrays.stream(this.items).map(ItemStack::copy).toArray(ItemStack[]::new),
relx,
rely,
false);
pStack.permutated = this.permutated;
pStack.chance = this.chance;
return pStack;
try {
PositionedStack pStack = (PositionedStack) super.clone();
pStack.items = Arrays.stream(this.items).map(ItemStack::copy).toArray(ItemStack[]::new);
pStack.item = this.item == null ? null : this.item.copy();
return pStack;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
public void draw(int mousex, int mousey) {
final int x = this.relx + (this.width - 16) / 2;
final int y = this.rely + (this.height - 16) / 2;
GuiContainerManager.drawItem(x, y, this.item);
}
public List<ItemStack> getFilteredPermutations() {
@@ -164,7 +177,9 @@ public class PositionedStack {
}
public boolean contains(int mx, int my) {
return mx >= this.relx - 1 && mx < this.relx + 17 && my >= this.rely - 1 && my < this.rely + 17;
return mx >= this.relx - 1 && mx < this.relx + this.width + 1
&& my >= this.rely - 1
&& my < this.rely + this.height + 1;
}
public boolean contains(ItemStack ingredient) {
@@ -192,4 +207,21 @@ public class PositionedStack {
public String toString() {
return "PositionedStack(output='" + item.toString() + "')";
}
/**
* A {@link PositionedStack} that keeps its items but never draws them.
*/
public static class Placeholder extends PositionedStack {
public Placeholder(Object object, int x, int y, boolean genPerms) {
super(object, x, y, genPerms);
}
public Placeholder(Object object, int x, int y) {
this(object, x, y, true);
}
@Override
public void draw(int mousex, int mousey) {}
}
}
@@ -163,9 +163,7 @@ public class PresetsList {
public static void load() {
final File presetsFile = new File(CommonUtils.getMinecraftDir(), "saves/NEI/global/presets.ini");
if (presetsFile == null || !presetsFile.exists()) {
return;
}
if (!presetsFile.exists()) return;
List<String> itemStrings;
try (FileInputStream reader = new FileInputStream(presetsFile)) {
@@ -15,7 +15,6 @@ import net.minecraftforge.fluids.FluidStack;
import codechicken.lib.gui.GuiDraw;
import codechicken.nei.ItemList.NothingItemFilter;
import codechicken.nei.SearchTokenParser.ISearchParserProvider;
import codechicken.nei.SearchTokenParser.SearchMode;
import codechicken.nei.api.IRecipeFilter;
import codechicken.nei.api.IRecipeFilter.IRecipeFilterProvider;
import codechicken.nei.api.ItemFilter;
@@ -85,8 +84,8 @@ public class SearchField extends TextField implements ItemFilterProvider {
}
@Override
public SearchMode getSearchMode() {
return SearchMode.fromInt(NEIClientConfig.getIntSetting("inventory.search." + this.name + "SearchMode"));
public String getName() {
return this.name;
}
}
@@ -59,7 +59,13 @@ public class SearchTokenParser {
public EnumChatFormatting getHighlightedColor();
public SearchMode getSearchMode();
default SearchMode getSearchMode() {
return SearchMode.fromInt(NEIClientConfig.getIntSetting("inventory.search." + getName() + "SearchMode"));
}
default String getName() {
return String.valueOf(getPrefix());
}
}
private static class ProvidersCache {
@@ -179,7 +185,7 @@ public class SearchTokenParser {
public synchronized ItemFilter getFilter(String rawText, boolean skipRecipeTokens) {
final String filterText = EnumChatFormatting.getTextWithoutFormattingCodes(rawText).toLowerCase();
if (filterText == null || filterText.isEmpty()) {
if (filterText.isEmpty()) {
return new EverythingItemFilter();
}
@@ -253,7 +259,7 @@ public class SearchTokenParser {
public synchronized IRecipeFilter getRecipeFilter(String filterText) {
filterText = EnumChatFormatting.getTextWithoutFormattingCodes(filterText).toLowerCase();
if (filterText == null || filterText.isEmpty()) {
if (filterText.isEmpty()) {
return new RecipeFilter(FilterContext.ANY, true, new EverythingItemFilter());
}
@@ -46,8 +46,7 @@ public class ServerHandler {
@SubscribeEvent
public void tickEvent(TickEvent.PlayerTickEvent event) {
if (event.phase == Phase.START && event.player instanceof EntityPlayerMP) {
EntityPlayerMP player = (EntityPlayerMP) event.player;
if (event.phase == Phase.START && event.player instanceof EntityPlayerMP player) {
PlayerSave save = NEIServerConfig.forPlayer(player.getCommandSenderName());
if (save == null) return;
updateMagneticPlayer(player, save);
@@ -399,8 +399,8 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
}
@Override
public SearchMode getSearchMode() {
return SearchMode.fromInt(NEIClientConfig.getIntSetting("inventory.search.subsetsSearchMode"));
public String getName() {
return "subsets";
}
private boolean matches(String name, String searchText, Pattern pattern) {
@@ -1,7 +1,5 @@
package codechicken.nei;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
@@ -23,6 +21,8 @@ import net.minecraft.world.chunk.Chunk;
import org.lwjgl.opengl.GL11;
import com.cardinalstar.cubicchunks.world.api.IMinMaxHeight;
import codechicken.lib.math.MathHelper;
import codechicken.nei.KeyManager.IKeyStateTracker;
import cpw.mods.fml.relauncher.ReflectionHelper;
@@ -416,38 +416,18 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
GL11.glDisable(GL11.GL_BLEND);
}
/** Holder defers class loading until Cubic Chunks is confirmed present. */
private static final class CCWorldBounds {
static final MethodHandle GET_MIN_HEIGHT;
static final MethodHandle GET_MAX_HEIGHT;
static {
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
// Mixined into World by CC, use reflection + MethodHandles to call these
GET_MIN_HEIGHT = lookup.unreflect(World.class.getMethod("getMinHeight"));
GET_MAX_HEIGHT = lookup.unreflect(World.class.getMethod("getMaxHeight"));
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
}
}
private static int worldMinHeight(World world) {
if (!NEIModContainer.isCCLoaded()) return 0;
try {
return (int) CCWorldBounds.GET_MIN_HEIGHT.invoke(world);
} catch (Throwable ignored) {
if (NEIModContainer.isCCLoaded() && world instanceof IMinMaxHeight worldHeights) {
return worldHeights.getMinHeight();
} else {
return 0;
}
}
private static int worldMaxHeight(World world) {
if (!NEIModContainer.isCCLoaded()) return world.getHeight();
try {
return (int) CCWorldBounds.GET_MAX_HEIGHT.invoke(world);
} catch (Throwable ignored) {
if (NEIModContainer.isCCLoaded() && world instanceof IMinMaxHeight worldHeights) {
return worldHeights.getMaxHeight();
} else {
return world.getHeight();
}
}
@@ -77,10 +77,13 @@ import cpw.mods.fml.common.registry.GameRegistry.UniqueIdentifier;
*/
public class ItemInfo {
public static enum Layout {
public enum Layout {
HEADER,
BODY,
FOOTER
FOOTER;
public static final Layout[] VALUES = values();
}
public static final ArrayListMultimap<Layout, IHighlightHandler> highlightHandlers = ArrayListMultimap.create();
@@ -472,7 +475,7 @@ public class ItemInfo {
MovingObjectPosition mop) {
List<String> retString = new ArrayList<>();
for (ItemInfo.Layout layout : ItemInfo.Layout.values())
for (ItemInfo.Layout layout : Layout.VALUES)
for (IHighlightHandler handler : ItemInfo.highlightHandlers.get(layout))
retString = handler.handleTextData(itemStack, world, player, mop, retString, layout);
@@ -274,7 +274,7 @@ public abstract class ShortcutInputHandler {
if (slot.getGroup().crafting == null) {
final Recipe recipe = Recipe.of(slot.getRecipeId());
if (recipe != null) {
math = RecipeChainMath.of(recipe, Math.max(1, slot != null ? slot.getMultiplier() : 1));
math = RecipeChainMath.of(recipe, Math.max(1, slot.getMultiplier()));
}
} else {
math = ItemPanels.bookmarkPanel.getGrid()
@@ -441,7 +441,7 @@ public abstract class ShortcutInputHandler {
}
}
if (gui instanceof GuiRecipe guiRecipe) {
if (gui instanceof GuiRecipe<?>guiRecipe) {
recipe = guiRecipe.getFocusedRecipe();
}
@@ -736,7 +736,7 @@ public abstract class ShortcutInputHandler {
return itemSlot.getRecipeId();
}
if (gui instanceof GuiRecipe guiRecipe) {
if (gui instanceof GuiRecipe<?>guiRecipe) {
final Recipe focusedRecipe = guiRecipe.getFocusedRecipe();
if (focusedRecipe != null) {
@@ -879,6 +879,16 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
return this.bookmarkItems.get(itemIndex);
}
public void replaceBookmarkItem(int itemIndex, BookmarkItem newItem) {
if (itemIndex < 0 || itemIndex >= this.bookmarkItems.size()) {
return;
}
this.bookmarkItems.set(itemIndex, newItem);
onItemsChanged();
}
public int getAbsoluteSlotIndex(int itemIndex) {
return this.gridGenerator.itemToSlot.getOrDefault(itemIndex, -1);
}
@@ -228,11 +228,15 @@ public class BookmarkItem {
final List<RecipeIngredient> items = type == BookmarkItemType.RESULT ? recipe.getResults()
: recipe.getIngredients();
final Builder builder = builder(groupId, stack).type(type).recipe(recipe);
final ItemStack emptyStack = StackInfo.withAmount(stack, 0);
long amount = 0;
for (RecipeIngredient res : items) {
if (res.contains(stack)) {
amount += 1L * res.getAmount() * res.getChance();
for (ItemStack perm : res.getPermutations()) {
if (NEIClientUtils.areStacksSameTypeWithNBT(emptyStack, StackInfo.withAmount(perm, 0))) {
amount += 1L * StackInfo.getAmount(perm) * res.getChance();
break;
}
}
}
@@ -308,6 +312,47 @@ public class BookmarkItem {
return copyWithMultiplier(this.multiplier);
}
public BookmarkItem copyWithPerm(ItemStack stack) {
if (this.recipeId != null
&& !NEIClientUtils.areStacksSameTypeWithNBT(StackInfo.withAmount(stack, 0), this.getItemStack(0))) {
final ItemStack oldPerm = findPermutation(this.itemStack);
final ItemStack newPerm = findPermutation(stack);
if (oldPerm != null && newPerm != null) {
final long oldAmount = StackInfo.getAmount(oldPerm);
final long amount = oldAmount > 0 ? this.factor * this.chance * StackInfo.getAmount(newPerm) / oldAmount
: 0;
final long factor = (amount % PositionedStack.CHANCE_FULL) == 0 ? amount / PositionedStack.CHANCE_FULL
: 1;
final long chance = factor == 1 ? amount : PositionedStack.CHANCE_FULL;
return new BookmarkItem(
this.groupId,
this.multiplier,
factor,
chance,
newPerm,
this.permutations,
this.recipeId,
this.type);
}
}
return copy();
}
private ItemStack findPermutation(ItemStack stack) {
for (ItemStack itemStack : this.permutations.values()) {
if (StackInfo.equalItemAndNBT(stack, itemStack, true)) {
return itemStack;
}
}
return null;
}
public boolean containsItems(BookmarkItem item) {
return this.permutations.keySet().stream().anyMatch(item.permutations::containsKey);
}
@@ -316,21 +361,47 @@ public class BookmarkItem {
return getAmount(this.multiplier);
}
public long getAmount(long multiplier, ItemStack perm) {
if (this.recipeId != null && perm != null
&& !NEIClientUtils.areStacksSameTypeWithNBT(StackInfo.withAmount(perm, 0), this.getItemStack(0))) {
final ItemStack oldPerm = findPermutation(this.itemStack);
final ItemStack newPerm = findPermutation(perm);
if (oldPerm != null && newPerm != null) {
final long oldAmount = StackInfo.getAmount(oldPerm);
final long amount = oldAmount > 0 ? this.factor * this.chance * StackInfo.getAmount(newPerm) / oldAmount
: 0;
final long factor = (amount % PositionedStack.CHANCE_FULL) == 0 ? amount / PositionedStack.CHANCE_FULL
: 1;
final long chance = factor == 1 ? amount : PositionedStack.CHANCE_FULL;
return getAmount(multiplier, factor, chance);
}
}
return getAmount(multiplier);
}
public long getAmount(long multiplier) {
long amount = this.factor * multiplier;
return getAmount(multiplier, this.factor, this.chance);
}
protected long getAmount(long multiplier, long factor, long chance) {
long amount = factor * multiplier;
if (this.fluidCellAmount > 1) {
amount = amount * this.fluidCellAmount;
}
if (this.chance != PositionedStack.CHANCE_FULL) {
if (chance != PositionedStack.CHANCE_FULL) {
if (this.type == BookmarkItemType.INGREDIENT) {
// For ingredients, round up the expected amount to be conservative.
amount = (amount * this.chance + PositionedStack.CHANCE_FULL - 1) / PositionedStack.CHANCE_FULL;
return (amount * chance + PositionedStack.CHANCE_FULL - 1) / PositionedStack.CHANCE_FULL;
} else {
// For results, round down the expected amount to be conservative.
amount = (amount * this.chance) / PositionedStack.CHANCE_FULL;
return (amount * chance) / PositionedStack.CHANCE_FULL;
}
}
@@ -1,5 +1,7 @@
package codechicken.nei.bookmark;
import static codechicken.nei.bookmark.BookmarkGrid.DEFAULT_GROUP_ID;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
@@ -139,13 +141,11 @@ public class SortableItem {
return;
}
if (overGroupId != BookmarkGrid.DEFAULT_GROUP_ID
&& beforeGroupId != BookmarkGrid.DEFAULT_GROUP_ID) {
beforeGroupId = BookmarkGrid.DEFAULT_GROUP_ID;
if (overGroupId != DEFAULT_GROUP_ID && beforeGroupId != DEFAULT_GROUP_ID) {
beforeGroupId = DEFAULT_GROUP_ID;
}
if (overGroupId == BookmarkGrid.DEFAULT_GROUP_ID && beforeGroupId != BookmarkGrid.DEFAULT_GROUP_ID
&& afterGroupId != BookmarkGrid.DEFAULT_GROUP_ID) {
if (overGroupId == DEFAULT_GROUP_ID && afterGroupId != DEFAULT_GROUP_ID) {
return;
}
@@ -160,12 +160,11 @@ public class SortableItem {
return;
}
if (overGroupId != BookmarkGrid.DEFAULT_GROUP_ID && afterGroupId != BookmarkGrid.DEFAULT_GROUP_ID) {
afterGroupId = BookmarkGrid.DEFAULT_GROUP_ID;
if (overGroupId != DEFAULT_GROUP_ID && afterGroupId != DEFAULT_GROUP_ID) {
afterGroupId = DEFAULT_GROUP_ID;
}
if (overGroupId == BookmarkGrid.DEFAULT_GROUP_ID && beforeGroupId != BookmarkGrid.DEFAULT_GROUP_ID
&& afterGroupId != BookmarkGrid.DEFAULT_GROUP_ID) {
if (overGroupId == DEFAULT_GROUP_ID && beforeGroupId != DEFAULT_GROUP_ID) {
return;
}
@@ -17,7 +17,6 @@ import codechicken.nei.recipe.GuiRecipeTab;
import codechicken.nei.recipe.GuiUsageRecipe;
import codechicken.nei.recipe.HandlerInfo;
import codechicken.nei.recipe.IRecipeHandler;
import codechicken.nei.recipe.TemplateRecipeHandler;
import codechicken.nei.util.NBTJson;
public class HandlerDumper extends DataDumper {
@@ -37,10 +36,7 @@ public class HandlerDumper extends DataDumper {
LinkedList<String[]> list = new LinkedList<>();
for (IRecipeHandler handler : GuiUsageRecipe.usagehandlers) {
final String handlerName = handler.getHandlerId();
final String handlerId = Objects.firstNonNull(
handler instanceof TemplateRecipeHandler ? ((TemplateRecipeHandler) handler).getOverlayIdentifier()
: null,
"null");
final String handlerId = Objects.firstNonNull(handler.getOverlayIdentifier(), "null");
HandlerInfo info = GuiRecipeTab.getHandlerInfo(handlerName, handlerId);
list.add(
@@ -64,7 +64,7 @@ public class BookmarkRecipeId {
return false;
}
Short idx = 0;
short idx = 0;
for (PositionedStack pStack : stacks) {
final NBTTagCompound tagCompoundA = StackInfo
@@ -123,8 +123,7 @@ public class BookmarkRecipeId {
return true;
}
if (anObject instanceof BookmarkRecipeId) {
final BookmarkRecipeId anRecipeId = (BookmarkRecipeId) anObject;
if (anObject instanceof BookmarkRecipeId anRecipeId) {
if (!handlerName.equals(anRecipeId.handlerName)) {
return false;
@@ -13,7 +13,7 @@ public class BrewingOverlayHandler extends DefaultOverlayHandler {
public Slot[][] mapIngredSlots(GuiContainer gui, List<PositionedStack> ingredients) {
Slot[][] map = super.mapIngredSlots(gui, ingredients);
Slot[] potSlots = new Slot[3];
for (int i = 0; i < 3; i++) potSlots[i] = (Slot) gui.inventorySlots.inventorySlots.get(i);
for (int i = 0; i < 3; i++) potSlots[i] = gui.inventorySlots.inventorySlots.get(i);
map[1] = potSlots;
return map;
}
@@ -53,8 +53,7 @@ public class FuelRecipeHandler extends FurnaceRecipeHandler {
private void loadAllSmelting() {
// Note: Not safe as written for parallelStream
final Map<ItemStack, ItemStack> smeltingRecipes = (Map<ItemStack, ItemStack>) FurnaceRecipes.smelting()
.getSmeltingList();
final Map<ItemStack, ItemStack> smeltingRecipes = FurnaceRecipes.smelting().getSmeltingList();
smeltingRecipes.entrySet().stream().map(recipe -> new SmeltingPair(recipe.getKey(), recipe.getValue()))
.collect(Collectors.toCollection(() -> mfurnace));
}
@@ -84,7 +84,7 @@ public class FurnaceRecipeHandler extends TemplateRecipeHandler {
public void loadCraftingRecipes(String outputId, Object... results) {
if (outputId.equals("smelting") && getClass() == FurnaceRecipeHandler.class) { // don't want subclasses getting
// a hold of this
Map<ItemStack, ItemStack> recipes = (Map<ItemStack, ItemStack>) FurnaceRecipes.smelting().getSmeltingList();
Map<ItemStack, ItemStack> recipes = FurnaceRecipes.smelting().getSmeltingList();
for (Entry<ItemStack, ItemStack> recipe : recipes.entrySet())
arecipes.add(new SmeltingPair(recipe.getKey(), recipe.getValue()));
} else super.loadCraftingRecipes(outputId, results);
@@ -92,7 +92,7 @@ public class FurnaceRecipeHandler extends TemplateRecipeHandler {
@Override
public void loadCraftingRecipes(ItemStack result) {
Map<ItemStack, ItemStack> recipes = (Map<ItemStack, ItemStack>) FurnaceRecipes.smelting().getSmeltingList();
Map<ItemStack, ItemStack> recipes = FurnaceRecipes.smelting().getSmeltingList();
for (Entry<ItemStack, ItemStack> recipe : recipes.entrySet())
if (NEIServerUtils.areStacksSameType(recipe.getValue(), result))
arecipes.add(new SmeltingPair(recipe.getKey(), recipe.getValue()));
@@ -108,7 +108,7 @@ public class FurnaceRecipeHandler extends TemplateRecipeHandler {
@Override
public void loadUsageRecipes(ItemStack ingredient) {
Map<ItemStack, ItemStack> recipes = (Map<ItemStack, ItemStack>) FurnaceRecipes.smelting().getSmeltingList();
Map<ItemStack, ItemStack> recipes = FurnaceRecipes.smelting().getSmeltingList();
for (Entry<ItemStack, ItemStack> recipe : recipes.entrySet())
if (NEIServerUtils.areStacksSameTypeCrafting(recipe.getKey(), ingredient)) {
SmeltingPair arecipe = new SmeltingPair(recipe.getKey(), recipe.getValue());
@@ -119,7 +119,7 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
public static RecipeId getRecipeId(GuiScreen gui, ItemStack stackover) {
if (gui instanceof GuiRecipe guiRecipe) {
if (gui instanceof GuiRecipe<?>guiRecipe) {
final Recipe focusedRecipe = guiRecipe.getFocusedRecipe();
if (focusedRecipe != null) {
@@ -155,11 +155,16 @@ public class GuiFavoriteButton extends GuiRecipeButton {
if (this.selectedResult == null) return;
NEIClientUtils.gl2DRenderContext(
() -> GuiDraw.drawRect(this.selectedResult.relx, this.selectedResult.rely, 16, 16, 0x66333333));
() -> GuiDraw.drawRect(
this.selectedResult.relx,
this.selectedResult.rely,
this.selectedResult.width,
this.selectedResult.height,
0x66333333));
final Image icon = isFavorite() ? ICON_STATE_ON : ICON_STATE_OFF;
final int iconX = this.selectedResult.relx + (16 - icon.width) / 2;
final int iconY = this.selectedResult.rely + (18 - icon.height) / 2;
final int iconX = this.selectedResult.relx + (this.selectedResult.width - icon.width) / 2;
final int iconY = this.selectedResult.rely + (this.selectedResult.height + 2 - icon.height) / 2;
LayoutManager.drawIcon(iconX, iconY, icon);
}
@@ -34,6 +34,8 @@ import codechicken.nei.PositionedStack;
import codechicken.nei.RecipeSearchField;
import codechicken.nei.RestartableTask;
import codechicken.nei.SearchField;
import codechicken.nei.SearchTokenParser.ISearchParserProvider;
import codechicken.nei.SearchTokenParser.SearchMode;
import codechicken.nei.VisiblityData;
import codechicken.nei.Widget;
import codechicken.nei.api.IGuiContainerOverlay;
@@ -54,6 +56,7 @@ import codechicken.nei.scroll.ScrollBar;
import codechicken.nei.scroll.ScrollBar.OverflowType;
import codechicken.nei.scroll.ScrollBar.ScrollPlace;
import codechicken.nei.scroll.ScrollContainer;
import codechicken.nei.search.SearchExpressionUtils;
import codechicken.nei.util.EmptyContainer;
import codechicken.nei.util.SlotInaccessible;
@@ -173,6 +176,59 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
return true;
}
@Override
public void addTooltips(List<String> tooltip) {
tooltip.add(NEIClientUtils.translate("recipe.search.tooltip.name") + GuiDraw.TOOLTIP_LINESPACE);
if (NEIClientUtils.shiftKey()) {
tooltip.add(
NEIClientUtils.translate(
"recipe.search.tooltip.input",
SearchExpressionUtils.HIGHLIGHTS.RECIPE + "<"));
tooltip.add(
NEIClientUtils.translate(
"recipe.search.tooltip.output",
SearchExpressionUtils.HIGHLIGHTS.RECIPE + ">"));
for (ISearchParserProvider provider : SearchField.searchParser.getProviders()) {
if (provider.getSearchMode() == SearchMode.PREFIX) {
addPrefixTooltip(tooltip, provider);
}
}
tooltip.add(
NEIClientUtils.translate(
"recipe.search.tooltip.exclude",
SearchExpressionUtils.HIGHLIGHTS.NEGATE + "-"));
tooltip.add(
NEIClientUtils.translate(
"recipe.search.tooltip.exclude_recipe",
SearchExpressionUtils.HIGHLIGHTS.NEGATE + "!"));
tooltip.add(
NEIClientUtils
.translate("recipe.search.tooltip.or", SearchExpressionUtils.HIGHLIGHTS.OR.f + "|"));
tooltip.add(
NEIClientUtils.translate(
"recipe.search.tooltip.exact",
SearchExpressionUtils.HIGHLIGHTS.QUOTED + "\"",
SearchExpressionUtils.HIGHLIGHTS.QUOTED + "\""));
} else {
tooltip.add(NEIClientUtils.translate("recipe.search.tooltip.shift"));
}
}
private void addPrefixTooltip(List<String> tooltip, ISearchParserProvider provider) {
final char prefix = SearchField.searchParser.getRedefinedPrefix(provider.getPrefix());
final String modeName = NEIClientUtils.translate("recipe.search.tooltip.prefix." + provider.getName());
tooltip.add(
NEIClientUtils.translate(
"recipe.search.tooltip.prefix",
provider.getHighlightedColor() + String.valueOf(prefix),
modeName));
}
};
/**
@@ -760,6 +816,10 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
this.recipeTabs.handleTooltip(mousex, mousey, currenttip);
if (this.handler != null && this.handler.searchingAvailable()) {
currenttip = GuiRecipe.toggleSearch.handleTooltip(mousex, mousey, currenttip);
}
if (currenttip.isEmpty() && isHandlerTitleHovered(mousex, mousey)) {
currenttip.add(NEIClientUtils.translate("recipe.tab.view_all.tooltip"));
}
@@ -1023,7 +1083,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
final int curRecipe = indices.isEmpty() ? 0 : indices.get(0);
final Recipe recipe = Recipe.of(gRecipe.handler.original, curRecipe);
return recipe != null ? recipe.getRecipeId() : null;
return recipe.getRecipeId();
}
return null;
@@ -223,7 +223,7 @@ public class NEIRecipeWidget extends Widget {
button -> (this.showAsWidget ? button instanceof GuiOverlayButton : button.contains(mouseX, mouseY))
? button
: null,
(GuiRecipeButton) null);
null);
if (overlayButton != null) {
NEIClientUtils.gl2DRenderContext(() -> overlayButton.drawItemOverlay());
@@ -247,14 +247,15 @@ public class NEIRecipeWidget extends Widget {
}
protected void drawItem(PositionedStack pStack, int mouseX, int mouseY, int yShift, boolean input) {
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
pStack.draw(mouseX - this.x, mouseY - this.y - yShift);
if (this.handlerInfo.getShowBadge()) {
drawBadge(pStack, input);
}
if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) {
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(pStack.relx, pStack.rely, 16, 16, 0x80FFFFFF));
NEIClientUtils.gl2DRenderContext(
() -> GuiDraw.drawRect(pStack.relx, pStack.rely, pStack.width, pStack.height, 0x80FFFFFF));
}
}
@@ -291,7 +292,7 @@ public class NEIRecipeWidget extends Widget {
final List<Badge> badges = getBadges(pStack, input);
for (Badge badge : badges) {
badge.draw(new Rectangle4i(pStack.relx, pStack.rely, 16, 16));
badge.draw(new Rectangle4i(pStack.relx, pStack.rely, pStack.width, pStack.height));
}
}
@@ -409,14 +410,22 @@ public class NEIRecipeWidget extends Widget {
if (itemstack != null) {
final PositionedStack hovered = getPositionedStackMouseOver(mousex, mousey);
if (hovered != null && this.handlerInfo.getShowBadge()) {
final List<Badge> badges = getBadges(hovered, getOutputs().indexOf(hovered) == -1);
if (hovered != null) {
if (this.handlerInfo.getShowBadge()) {
final List<Badge> badges = getBadges(hovered, getOutputs().indexOf(hovered) == -1);
for (Badge badge : badges) {
if (badge.getTooltip() != null && !badge.getTooltip().isEmpty()) {
tooltip.addAll(badge.getTooltip());
for (Badge badge : badges) {
if (badge.getTooltip() != null && !badge.getTooltip().isEmpty()) {
tooltip.addAll(badge.getTooltip());
}
}
}
final List<String> customTooltip = hovered.getTooltip();
if (customTooltip != null && !customTooltip.isEmpty()) {
tooltip.addAll(customTooltip);
}
}
if (hovered == null || !NEIClientConfig.showCycledIngredientsTooltip()
@@ -168,7 +168,7 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
private boolean isHandlerTitleHovered(int recipe, Point mouse) {
final GuiContainer guiContainer = NEIClientUtils.getGuiContainer();
if (guiContainer instanceof GuiRecipe guiRecipe) {
if (guiContainer instanceof GuiRecipe<?>guiRecipe) {
final Point recipePosition = guiRecipe.getRecipePosition(recipe);
return new Rectangle(recipePosition.x, recipePosition.y, WIDTH, 16)
.contains(mouse.x - guiContainer.guiLeft, mouse.y - guiContainer.guiTop);
@@ -250,7 +250,7 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
if (r.handler != null) {
final GuiContainer guiContainer = NEIClientUtils.getGuiContainer();
if (guiContainer instanceof GuiRecipe guiRecipe) {
if (guiContainer instanceof GuiRecipe<?>guiRecipe) {
int index = guiRecipe.currenthandlers.indexOf(r.handler);
if (index != -1) {
@@ -288,13 +288,18 @@ public class Recipe {
protected int relx;
protected int rely;
protected int width;
protected int height;
public RecipeIngredient(int relx, int rely, List<ItemStack> items, int chance, int activeIndex) {
public RecipeIngredient(int relx, int rely, int width, int height, List<ItemStack> items, int chance,
int activeIndex) {
this.items = items.stream().map(ItemStack::copy).toArray(size -> new ItemStack[size]);
this.amount = StackInfo.getAmount(this.items[activeIndex]);
this.activeIndex = activeIndex;
this.relx = relx;
this.rely = rely;
this.width = width;
this.height = height;
this.chance = chance;
}
@@ -314,11 +319,19 @@ public class Recipe {
}
}
return of(positionedStack.relx, positionedStack.rely, stacks, positionedStack.getChance(), activeIndex);
return of(
positionedStack.relx,
positionedStack.rely,
positionedStack.width,
positionedStack.height,
stacks,
positionedStack.getChance(),
activeIndex);
}
public static RecipeIngredient of(int relx, int rely, List<ItemStack> stacks, int chance, int activeIndex) {
return new RecipeIngredient(relx, rely, stacks, chance, activeIndex);
public static RecipeIngredient of(int relx, int rely, int width, int height, List<ItemStack> stacks, int chance,
int activeIndex) {
return new RecipeIngredient(relx, rely, width, height, stacks, chance, activeIndex);
}
public int getAmount() {
@@ -335,34 +348,25 @@ public class Recipe {
public void setActiveIndex(int activeIndex) {
this.activeIndex = Math.max(0, Math.min(activeIndex, this.items.length - 1));
this.amount = StackInfo.getAmount(this.items[this.activeIndex]);
}
public boolean contains(ItemStack stackA) {
return getPermutations().stream()
.anyMatch(stackB -> NEIClientUtils.areStacksSameTypeWithNBT(stackB, stackA));
final ItemStack stack = StackInfo.withAmount(stackA, 0);
return getPermutations().stream().anyMatch(
stackB -> NEIClientUtils.areStacksSameTypeWithNBT(StackInfo.withAmount(stackB, 0), stack));
}
public List<ItemStack> getPermutations() {
return Arrays.asList(this.items);
}
public RecipeIngredient setAmount(int amount) {
for (int index = 0; index < this.items.length; index++) {
this.items[index] = StackInfo.withAmount(this.items[index], amount);
}
return this;
}
public void setChance(int chance) {
this.chance = chance;
}
public RecipeIngredient copy() {
return new RecipeIngredient(
this.relx,
this.rely,
this.width,
this.height,
getPermutations().stream().map(ItemStack::copy).collect(Collectors.toList()),
this.chance,
this.activeIndex);
@@ -447,7 +451,7 @@ public class Recipe {
}
if (item instanceof ItemStack stack) {
return RecipeIngredient.of(0, 0, Arrays.asList(stack), PositionedStack.CHANCE_FULL, 0);
return RecipeIngredient.of(0, 0, 16, 16, Arrays.asList(stack), PositionedStack.CHANCE_FULL, 0);
}
if (item instanceof RecipeIngredient ingr) {
@@ -59,7 +59,7 @@ public class RecipeHandlerRef {
private GuiContainer prepareGui(GuiContainer firstGui) {
if (firstGui instanceof GuiRecipe gui) {
if (firstGui instanceof GuiRecipe<?>gui) {
firstGui = gui.firstGui;
}
@@ -50,8 +50,7 @@ public class RecipeInfo {
public static void registerGuiOverlay(Class<? extends GuiContainer> classz, String ident,
IStackPositioner positioner) {
positionerMap.put(new OverlayKey(classz, ident), positioner);
if (positioner instanceof OffsetPositioner && !offsets.containsKey(classz)) {
OffsetPositioner p = (OffsetPositioner) positioner;
if (positioner instanceof OffsetPositioner p && !offsets.containsKey(classz)) {
setGuiOffset(classz, p.offsetx, p.offsety);
}
}
@@ -1,6 +1,8 @@
package codechicken.nei.recipe;
import java.awt.Rectangle;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
@@ -13,8 +15,6 @@ import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.ShapedRecipes;
import net.minecraftforge.oredict.ShapedOreRecipe;
import codechicken.core.ReflectionManager;
import codechicken.nei.NEIClientConfig;
import codechicken.nei.NEIClientUtils;
import codechicken.nei.NEIServerUtils;
import codechicken.nei.PositionedStack;
@@ -25,6 +25,24 @@ import codechicken.nei.api.IStackPositioner;
public class ShapedRecipeHandler extends TemplateRecipeHandler {
private static final MethodHandle SHAPED_ORE_RECIPE_WIDTH, SHAPED_ORE_RECIPE_HEIGHT;
static {
try {
final var lookup = MethodHandles.lookup();
final var widthField = ShapedOreRecipe.class.getDeclaredField("width");
final var heightField = ShapedOreRecipe.class.getDeclaredField("height");
widthField.setAccessible(true);
heightField.setAccessible(true);
SHAPED_ORE_RECIPE_WIDTH = lookup.unreflectGetter(widthField);
SHAPED_ORE_RECIPE_HEIGHT = lookup.unreflectGetter(heightField);
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new RuntimeException(e);
}
}
public class CachedShapedRecipe extends CachedRecipe {
public ArrayList<PositionedStack> ingredients;
@@ -84,7 +102,7 @@ public class ShapedRecipeHandler extends TemplateRecipeHandler {
@Override
public void loadCraftingRecipes(String outputId, Object... results) {
if (outputId.equals("crafting") && getClass() == ShapedRecipeHandler.class) {
for (IRecipe irecipe : (List<IRecipe>) CraftingManager.getInstance().getRecipeList()) {
for (IRecipe irecipe : CraftingManager.getInstance().getRecipeList()) {
CachedShapedRecipe recipe = null;
if (irecipe instanceof ShapedRecipes shaped) {
@@ -99,7 +117,7 @@ public class ShapedRecipeHandler extends TemplateRecipeHandler {
}
}
} else if (outputId.equals("crafting2x2") && getClass() == ShapedRecipeHandler.class) {
for (IRecipe irecipe : (List<IRecipe>) CraftingManager.getInstance().getRecipeList()) {
for (IRecipe irecipe : CraftingManager.getInstance().getRecipeList()) {
if (irecipe instanceof ShapedRecipes shaped && shaped.recipeWidth <= 2 && shaped.recipeHeight <= 2) {
CachedShapedRecipe recipe = new CachedShapedRecipe(shaped);
@@ -115,7 +133,7 @@ public class ShapedRecipeHandler extends TemplateRecipeHandler {
@Override
public void loadCraftingRecipes(ItemStack result) {
for (IRecipe irecipe : (List<IRecipe>) CraftingManager.getInstance().getRecipeList()) {
for (IRecipe irecipe : CraftingManager.getInstance().getRecipeList()) {
if (NEIServerUtils.areStacksSameTypeCrafting(irecipe.getRecipeOutput(), result)) {
CachedShapedRecipe recipe = null;
if (irecipe instanceof ShapedRecipes) recipe = new CachedShapedRecipe((ShapedRecipes) irecipe);
@@ -131,7 +149,7 @@ public class ShapedRecipeHandler extends TemplateRecipeHandler {
@Override
public void loadUsageRecipes(ItemStack ingredient) {
for (IRecipe irecipe : (List<IRecipe>) CraftingManager.getInstance().getRecipeList()) {
for (IRecipe irecipe : CraftingManager.getInstance().getRecipeList()) {
CachedShapedRecipe recipe = null;
if (irecipe instanceof ShapedRecipes) recipe = new CachedShapedRecipe((ShapedRecipes) irecipe);
else if (irecipe instanceof ShapedOreRecipe) recipe = forgeShapedRecipe((ShapedOreRecipe) irecipe);
@@ -147,19 +165,21 @@ public class ShapedRecipeHandler extends TemplateRecipeHandler {
}
public CachedShapedRecipe forgeShapedRecipe(ShapedOreRecipe recipe) {
int width, height;
try {
int width = ReflectionManager.getField(ShapedOreRecipe.class, Integer.class, recipe, 4);
int height = ReflectionManager.getField(ShapedOreRecipe.class, Integer.class, recipe, 5);
Object[] items = recipe.getInput();
for (Object item : items) if (item instanceof List && ((List<?>) item).isEmpty()) // ore handler, no ores
return null;
return new CachedShapedRecipe(width, height, items, recipe.getRecipeOutput());
} catch (Exception e) {
NEIClientConfig.logger.error("Error loading recipe: ", e);
return null;
width = (int) SHAPED_ORE_RECIPE_WIDTH.invokeExact(recipe);
height = (int) SHAPED_ORE_RECIPE_HEIGHT.invokeExact(recipe);
} catch (Throwable e) {
throw new IllegalStateException("Unreachable");
}
Object[] items = recipe.getInput();
for (Object item : items) {
if (item instanceof List<?>ores && ores.isEmpty()) // ore handler, no ores
return null;
}
return new CachedShapedRecipe(width, height, items, recipe.getRecipeOutput());
}
@Override
@@ -233,7 +233,7 @@ public class RecipeChainMath {
final long amount = item.getAmount(multiplier);
rootIngredients.add(
BookmarkItem.builder(-1, item.getItemStack(amount)).factor(item.getStackSize(amount))
.permutations(BookmarkItem.Builder.generatePermutations(item.itemStack))
.permutations(BookmarkItem.Builder.generatePermutations(item.getItemStack(amount)))
.recipeId(ROOT_RECIPE_ID).type(BookmarkItemType.INGREDIENT).build());
}
@@ -348,14 +348,14 @@ public class RecipeChainMath {
for (BookmarkItem prefItem : this.recipeResults) {
if (!prefItem.emptyFactor() && this.outputRecipes.containsKey(prefItem.recipeId)) {
final long prefAmount = prefItem.getAmount(this.outputRecipes.get(prefItem.recipeId));
final long prefMultiplier = this.outputRecipes.get(prefItem.recipeId);
if (prefItem.itemStack.getItem().hasContainerItem(prefItem.itemStack)) {
this.containerItemsBlacklist.add(prefItem.itemStack);
}
this.preferredItems.put(prefItem, prefItem);
calculateSuitableRecipe(prefItem, prefAmount, new ArrayList<>(), visitor);
calculateSuitableRecipe(prefItem, prefMultiplier, new ArrayList<>(), visitor);
this.preferredItems.remove(prefItem);
}
}
@@ -372,9 +372,11 @@ public class RecipeChainMath {
return this;
}
private void calculateSuitableRecipe(BookmarkItem ingrItem, long ingrAmount, List<RecipeId> visited,
private void calculateSuitableRecipe(BookmarkItem ingrItem, long ingrMultiplier, List<RecipeId> visited,
ChainVisitor visitor) {
final BookmarkItem prefItem = this.preferredItems.get(ingrItem);
long ingrAmount = ingrItem
.getAmount(ingrMultiplier, prefItem != null ? prefItem.itemStack : ingrItem.itemStack);
visitor.addIngredient(prefItem != null ? prefItem : ingrItem, ingrAmount);
@@ -426,7 +428,7 @@ public class RecipeChainMath {
for (BookmarkItem item : this.recipeIngredients) {
if (!item.emptyFactor() && recipeId.equals(item.recipeId)) {
calculateSuitableRecipe(item, item.getAmount(multiplier), visited, visitor);
calculateSuitableRecipe(item, multiplier, visited, visitor);
}
}
@@ -382,7 +382,7 @@ public class DebugHandlerWidget extends Widget {
public void update() {
final GuiContainer gui = NEIClientUtils.getGuiContainer();
if (this.showWidget && gui instanceof GuiRecipe recipe) {
if (this.showWidget && gui instanceof GuiRecipe<?>recipe) {
if (this.record == null || !this.record.handlerKey.equals(getHandlerID(recipe.getHandler()))) {
final IRecipeHandler handler = recipe.getHandler();
@@ -85,8 +85,7 @@ public class SearchExpressionFormatVisitor extends AbstractSearchExpressionVisit
}
private String formatChild(ParseTree child, Character prefix) {
if (child instanceof TerminalNode) {
final TerminalNode node = (TerminalNode) child;
if (child instanceof TerminalNode node) {
final int type = node.getSymbol().getType();
final String format = Optional.ofNullable(
// check if highlight is defined for the token
@@ -36,7 +36,7 @@ import cpw.mods.fml.relauncher.ReflectionHelper;
public class ItemUntranslator {
private class LanguageRegistryPatch implements AutoCloseable {
private static class LanguageRegistryPatch implements AutoCloseable {
// RAII-style helper that temporarily swaps language data in
// LanguageRegistry / StringTranslate using reflection. This allows
// reading translation entries for a different language (eg. en_US)
@@ -252,13 +252,20 @@ public class ItemUntranslator {
return this.processedNames.computeIfAbsent(guidKey, stackKey -> {
String displayName = this.secondNames.get(stackKey);
if (displayName == null) {
final String guid = findBestGUIDForLookup(stack);
displayName = this.secondNames
.computeIfAbsent(guid == null ? stackKey : guid, g -> getFallbackDisplayName(stack));
try {
if (displayName == null) {
final String guid = findBestGUIDForLookup(stack);
displayName = this.secondNames
.computeIfAbsent(guid == null ? stackKey : guid, g -> getFallbackDisplayName(stack));
}
return displayName.equals(stripFormatting(stack.getDisplayName())) ? "" : displayName;
} catch (Throwable e) {
NEIClientConfig.logger.warn("Failed to get display name for itemstack {}", stack, e);
}
return displayName.equals(stripFormatting(stack.getDisplayName())) ? "" : displayName;
return displayName != null ? displayName : "";
});
}
@@ -39,13 +39,12 @@ public class NBTJson {
@SuppressWarnings("unchecked")
public static JsonElement toJsonObject(NBTBase nbt) {
if (nbt instanceof NBTTagCompound) {
if (nbt instanceof NBTTagCompound nbtTagCompound) {
// NBTTagCompound
final NBTTagCompound nbtTagCompound = (NBTTagCompound) nbt;
final Map<String, NBTBase> tagMap = (Map<String, NBTBase>) nbtTagCompound.tagMap;
final JsonObject root = new JsonObject();
tagMap.entrySet().stream().sorted(Map.Entry.<String, NBTBase>comparingByKey())
tagMap.entrySet().stream().sorted(Map.Entry.comparingByKey())
.forEach(nbtEntry -> { root.add(nbtEntry.getKey(), toJsonObject(nbtEntry.getValue())); });
return root;
@@ -73,9 +72,8 @@ public class NBTJson {
} else if (nbt instanceof NBTTagString) {
// String
return new JsonPrimitive(((NBTTagString) nbt).func_150285_a_());
} else if (nbt instanceof NBTTagList) {
} else if (nbt instanceof NBTTagList list) {
// Tag List
final NBTTagList list = (NBTTagList) nbt;
if (list.tagList.isEmpty()) {
return createEmptyList(list);
@@ -85,9 +83,8 @@ public class NBTJson {
return arr;
}
} else if (nbt instanceof NBTTagIntArray) {
} else if (nbt instanceof NBTTagIntArray list) {
// Int Array
final NBTTagIntArray list = (NBTTagIntArray) nbt;
if (list.func_150302_c().length == 0) {
return createEmptyList(list);
@@ -101,9 +98,8 @@ public class NBTJson {
return arr;
}
} else if (nbt instanceof NBTTagByteArray) {
} else if (nbt instanceof NBTTagByteArray list) {
// Byte Array
final NBTTagByteArray list = (NBTTagByteArray) nbt;
if (list.func_150292_c().length == 0) {
return createEmptyList(list);
@@ -123,9 +119,8 @@ public class NBTJson {
}
public static NBTBase toNbt(JsonElement jsonElement) {
if (jsonElement instanceof JsonPrimitive) {
if (jsonElement instanceof JsonPrimitive jsonPrimitive) {
// Number or String
final JsonPrimitive jsonPrimitive = (JsonPrimitive) jsonElement;
final String jsonString = jsonPrimitive.getAsString();
final Matcher m = numberPattern.matcher(jsonString);
if (m.find()) {
@@ -158,9 +153,8 @@ public class NBTJson {
// String
return new NBTTagString(jsonString);
}
} else if (jsonElement instanceof JsonArray) {
} else if (jsonElement instanceof JsonArray jsonArray) {
// NBTTagIntArray or NBTTagList
final JsonArray jsonArray = (JsonArray) jsonElement;
final List<NBTBase> nbtList = new ArrayList<>();
for (JsonElement element : jsonArray) {
@@ -183,9 +177,8 @@ public class NBTJson {
return nbtTagList;
}
} else if (jsonElement instanceof JsonObject) {
} else if (jsonElement instanceof JsonObject jsonObject) {
// NBTTagCompound
final JsonObject jsonObject = (JsonObject) jsonElement;
final NBTBase custom = restoreEmptyList(jsonObject);
if (custom == null) {
@@ -571,6 +571,24 @@ nei.debug.RecipeHandler.reset=Reset
nei.recipe.page=Page %s/%s
nei.recipe.tooltip=Recipes
nei.recipe.tab.view_all.tooltip=View all categories
nei.recipe.search.tooltip.name=Filter Syntax
nei.recipe.search.tooltip.shift=§7Hold §6Shift§7 for more info
nei.recipe.search.tooltip.input=%s§ftext§8 - §7search in inputs
nei.recipe.search.tooltip.output=%s§ftext§8 - §7search in outputs
nei.recipe.search.tooltip.prefix=%stext§8 - §7%s
nei.recipe.search.tooltip.prefix.modName=search by mod
nei.recipe.search.tooltip.prefix.tooltip=search by tooltip
nei.recipe.search.tooltip.prefix.oreDict=search by ore dict
nei.recipe.search.tooltip.prefix.identifier=search by resource ID
nei.recipe.search.tooltip.prefix.subsets=search by subsets
nei.recipe.search.tooltip.prefix.chemicalFormula=search by chemical formula
nei.recipe.search.tooltip.exclude=%s§ftext§8 - §7exclude items with text
nei.recipe.search.tooltip.exclude_recipe=%s§ftext§8 - §7exclude recipes with text
nei.recipe.search.tooltip.or=§fa%s§fb§8 - §7match a or b
nei.recipe.search.tooltip.exact=%s§ftext%s§8 - §7match exact phrase
nei.recipe.shaped=Shaped Crafting
nei.recipe.shapeless=Shapeless Crafting
nei.recipe.furnace=Smelting