mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-11-15 09:44:44 +00:00
Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8cec9a78c | ||
|
|
fb43a662eb | ||
|
|
b2e0b8878a | ||
|
|
374f019103 | ||
|
|
5dfcff6f30 | ||
|
|
bd17301cb9 | ||
|
|
96ccd4e109 | ||
|
|
b30ca57e68 | ||
|
|
8f949bc1d1 | ||
|
|
d25365942a | ||
|
|
eb58e1dabc | ||
|
|
f4601e7eed | ||
|
|
ba48806667 | ||
|
|
70c332796a | ||
|
|
bcc25d4369 | ||
|
|
10a3109714 | ||
|
|
b60769864f | ||
|
|
6bc899769f |
No files matched your search
+2
-2
@@ -1,8 +1,8 @@
|
||||
// Add your dependencies here
|
||||
|
||||
dependencies {
|
||||
api('com.github.GTNewHorizons:CodeChickenCore:1.4.10:dev')
|
||||
devOnlyNonPublishable('com.github.GTNewHorizons:GTNHLib:0.9.13:dev')
|
||||
api('com.github.GTNewHorizons:CodeChickenCore:1.4.12:dev')
|
||||
devOnlyNonPublishable('com.github.GTNewHorizons:GTNHLib:0.9.47:dev')
|
||||
|
||||
shadowImplementation('org.apache.commons:commons-csv:1.10.0')
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#This file is generated by updateDaemonJvm
|
||||
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c5ee947fbfb70bc347d8d531e3a578c4/redirect
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/5ee463876563a46fff651cce1bc53a4c/redirect
|
||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c5ee947fbfb70bc347d8d531e3a578c4/redirect
|
||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/5ee463876563a46fff651cce1bc53a4c/redirect
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e1118b4c7c2858d28154d086dbff010e/redirect
|
||||
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect
|
||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect
|
||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/d4fd992c9557644e637ebe98263e0ae7/redirect
|
||||
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/faa12903720d410b387cc69ccafb1a74/redirect
|
||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c5ee947fbfb70bc347d8d531e3a578c4/redirect
|
||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/5ee463876563a46fff651cce1bc53a4c/redirect
|
||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/1630f7ebef05444cb27a2709ea0249b3/redirect
|
||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/cd495626d2ee49a75447e3fdc6afb287/redirect
|
||||
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/a4c09dd2e2d7079373d30e524bbc2829/redirect
|
||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/b96cb7670c095245220e7d01d5927b58/redirect
|
||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/8e1d9ee5d0f13e442218f6884a306da1/redirect
|
||||
toolchainVersion=25
|
||||
@@ -19,6 +19,7 @@ import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
@@ -184,27 +185,33 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
|
||||
if (itemStack != null && this.grid.indexOf(groupId, itemStack, recipeId, false) == -1) {
|
||||
final boolean existsRecipe = recipeId != null
|
||||
&& this.grid.existsRecipe(recipeId, BookmarkGrid.DEFAULT_GROUP_ID);
|
||||
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(itemStack);
|
||||
long count = nbTag.getInteger("Count");
|
||||
long factor = existsRecipe ? Math.max(count, 1) : 1;
|
||||
final Recipe recipe = Recipe.of(recipeId);
|
||||
final BookmarkItem.Builder builder;
|
||||
|
||||
if (recipe != null) {
|
||||
builder = BookmarkItem.builder(groupId, itemStack, recipe, BookmarkItemType.RESULT);
|
||||
} else {
|
||||
builder = BookmarkItem.builder(groupId, itemStack).recipeId(recipeId)
|
||||
.factor(StackInfo.getAmount(itemStack));
|
||||
}
|
||||
|
||||
builder.multiplier(1);
|
||||
|
||||
if (existsRecipe) {
|
||||
builder.type(BookmarkItemType.RESULT);
|
||||
|
||||
for (int i = 0; i < this.grid.size(); i++) {
|
||||
if (this.grid.getBookmarkItem(i).equalsRecipe(recipeId, groupId)) {
|
||||
count *= this.grid.getBookmarkItem(i).getMultiplier();
|
||||
builder.multiplier(this.grid.getBookmarkItem(i).getMultiplier());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
builder.type(BookmarkItemType.ITEM);
|
||||
}
|
||||
|
||||
this.grid.addItem(
|
||||
BookmarkItem.of(
|
||||
groupId,
|
||||
StackInfo.withAmount(itemStack, count),
|
||||
factor,
|
||||
recipeId,
|
||||
existsRecipe ? BookmarkItemType.RESULT : BookmarkItemType.ITEM),
|
||||
true);
|
||||
this.grid.addItem(builder.build(), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -212,9 +219,11 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
|
||||
}
|
||||
|
||||
public boolean addRecipe(Recipe recipe, int multiplier, int groupId) {
|
||||
if (recipe == null) return false;
|
||||
|
||||
final RecipeId recipeId = recipe.getRecipeId();
|
||||
|
||||
if (recipe != null && this.grid.getGroup(groupId) != null && !this.grid.existsRecipe(recipeId, groupId)) {
|
||||
if (this.grid.getGroup(groupId) != null && !this.grid.existsRecipe(recipeId, groupId)) {
|
||||
this.grid.addRecipe(recipe, multiplier, groupId);
|
||||
return true;
|
||||
}
|
||||
@@ -245,15 +254,22 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
|
||||
ItemStack stack = recipeId.getResult();
|
||||
|
||||
if (stack != null && uniqueRecipe.add(recipeId)) {
|
||||
this.grid.addItem(
|
||||
BookmarkItem
|
||||
.of(groupId, stack, StackInfo.getAmount(stack), recipeId, BookmarkItemType.ITEM),
|
||||
true);
|
||||
final Recipe recipe = Recipe.of(recipeId);
|
||||
final BookmarkItem.Builder builder;
|
||||
|
||||
if (recipe != null) {
|
||||
builder = BookmarkItem.builder(groupId, stack, recipe, BookmarkItemType.RESULT);
|
||||
} else {
|
||||
builder = BookmarkItem.builder(groupId, stack).recipeId(recipeId)
|
||||
.factor(StackInfo.getAmount(stack));
|
||||
}
|
||||
|
||||
this.grid.addItem(builder.multiplier(1).type(BookmarkItemType.ITEM).build(), true);
|
||||
uniqueStack.add(stack);
|
||||
}
|
||||
|
||||
} else {
|
||||
ItemStack stack = extractItem(item);
|
||||
final ItemStack stack = extractItem(item);
|
||||
|
||||
if (stack != null && !uniqueStack.contains(stack)) {
|
||||
this.grid.addItem(BookmarkItem.of(groupId, stack), true);
|
||||
@@ -925,6 +941,17 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
|
||||
|
||||
if (slot != null) {
|
||||
|
||||
if (slot.getBookmarkItem().chance != PositionedStack.CHANCE_FULL) {
|
||||
final String chanceText = NEIClientUtils
|
||||
.formatChance(slot.getBookmarkItem().chance / (float) PositionedStack.CHANCE_FULL);
|
||||
currenttip.add(
|
||||
1,
|
||||
EnumChatFormatting.GRAY + NEIClientUtils.translate(
|
||||
slot.getType() == BookmarkItemType.INGREDIENT ? "recipe.badge.chance.consume"
|
||||
: "recipe.badge.chance.output",
|
||||
chanceText));
|
||||
}
|
||||
|
||||
if (slot.getType() == BookmarkItemType.INGREDIENT && slot.getRecipeId() != null
|
||||
&& slot.getBookmarkItem().permutations.size() > 1) {
|
||||
RecipeId recipeId = slot.getRecipeId();
|
||||
@@ -1119,7 +1146,7 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
|
||||
|
||||
for (BookmarkItem item : math.initialItems) {
|
||||
final long invStackSize = inventory.getOrDefault(item.itemStack, 0L);
|
||||
final long amount = item.amount - invStackSize * item.fluidCellAmount;
|
||||
final long amount = item.getAmount() - invStackSize * item.fluidCellAmount;
|
||||
if (amount > 0) {
|
||||
pullItemStacks.add(item.getItemStack(amount));
|
||||
}
|
||||
@@ -1133,7 +1160,7 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
|
||||
for (BookmarkItem item : math.initialItems) {
|
||||
final long invStackSize = inventory.getOrDefault(item.itemStack, 0L);
|
||||
final long strStackSize = containerStorage.getOrDefault(item.itemStack, 0L);
|
||||
final long amount = item.amount - invStackSize * item.fluidCellAmount
|
||||
final long amount = item.getAmount() - invStackSize * item.fluidCellAmount
|
||||
- strStackSize * item.fluidCellAmount;
|
||||
|
||||
if (amount > 0) {
|
||||
|
||||
@@ -296,15 +296,26 @@ public class FormattedTextField extends GuiTextField {
|
||||
int shift = 0;
|
||||
|
||||
for (int i = 0; i < position; i++) {
|
||||
while (this.formattedText.length() > i + shift && this.formattedText.charAt(i + shift) == '\u00a7') {
|
||||
while (this.formattedText.length() > i + shift + 1 && this.formattedText.charAt(i + shift) == '\u00a7'
|
||||
&& isFormattingCode(this.formattedText.charAt(i + shift + 1))) {
|
||||
shift += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return position + shift;
|
||||
return Math.min(position + shift, this.formattedText.length());
|
||||
}
|
||||
|
||||
private static boolean isFormattingCode(char c) {
|
||||
return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
|
||||
|| (c >= 'k' && c <= 'o')
|
||||
|| c == 'r'
|
||||
|| (c >= 'A' && c <= 'F')
|
||||
|| (c >= 'K' && c <= 'O')
|
||||
|| c == 'R';
|
||||
}
|
||||
|
||||
private String getPreviousColor(int position) {
|
||||
position = Math.min(position, this.formattedText.length() - 1);
|
||||
while (position >= 0) {
|
||||
if (this.formattedText.charAt(position) == '\u00a7') {
|
||||
return this.formattedText.substring(position, position + 2);
|
||||
|
||||
@@ -73,6 +73,7 @@ public class IMCForNEI {
|
||||
|
||||
API.registerRecipeHandler(new ProfilerRecipeHandler(true));
|
||||
API.registerUsageHandler(new ProfilerRecipeHandler(false));
|
||||
sendProfilerRecipeHandler();
|
||||
}
|
||||
|
||||
private static void sendHandler(String aName, String aBlock) {
|
||||
@@ -136,6 +137,19 @@ public class IMCForNEI {
|
||||
FMLInterModComms.sendMessage("NotEnoughItems", "registerHandlerInfo", aNBT);
|
||||
}
|
||||
|
||||
private static void sendProfilerRecipeHandler() {
|
||||
NBTTagCompound aNBT = new NBTTagCompound();
|
||||
aNBT.setString("handler", "codechicken.nei.recipe.ProfilerRecipeHandler");
|
||||
aNBT.setString("modName", "Not Enough Items");
|
||||
aNBT.setString("modId", "nei");
|
||||
aNBT.setString("itemName", "minecraft:clock");
|
||||
aNBT.setInteger("handlerHeight", 16);
|
||||
aNBT.setInteger("handlerWidth", 166);
|
||||
aNBT.setBoolean("multipleWidgetsAllowed", true);
|
||||
aNBT.setInteger("yShift", 0);
|
||||
FMLInterModComms.sendMessage("NotEnoughItems", "registerHandlerInfo", aNBT);
|
||||
}
|
||||
|
||||
private static void sendCatalyst(String aName, String aStack) {
|
||||
NBTTagCompound aNBT = new NBTTagCompound();
|
||||
aNBT.setString("handlerID", aName);
|
||||
|
||||
@@ -95,6 +95,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
|
||||
/** Formats a number with group separator and at most 2 fraction digits. */
|
||||
private static final Map<Locale, DecimalFormat> decimalFormatters = new HashMap<>();
|
||||
private static final DecimalFormat CHANCE_FORMAT = new DecimalFormat("##0.##%");
|
||||
|
||||
public static final int ALT_HASH = NEIKeyboardUtils.ALT_HASH;
|
||||
public static final int SHIFT_HASH = NEIKeyboardUtils.SHIFT_HASH;
|
||||
@@ -126,7 +127,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public static String formatNumber(long aNumber) {
|
||||
public static String formatNumber(Number aNumber) {
|
||||
|
||||
if (NEIModContainer.isGTNHLibLoaded()) {
|
||||
return NumberFormatUtil.formatNumber(aNumber);
|
||||
@@ -135,7 +136,7 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
return getDecimalFormat().format(aNumber);
|
||||
}
|
||||
|
||||
public static String formatFluid(long aNumber) {
|
||||
public static String formatFluid(Number aNumber) {
|
||||
|
||||
if (NEIModContainer.isGTNHLibLoaded()) {
|
||||
return NumberFormatUtil.formatFluid(aNumber);
|
||||
@@ -144,6 +145,10 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
return getDecimalFormat().format(aNumber) + " L";
|
||||
}
|
||||
|
||||
public static String formatChance(float chance) {
|
||||
return CHANCE_FORMAT.format(chance);
|
||||
}
|
||||
|
||||
public static void deleteHeldItem() {
|
||||
deleteSlotStack(-999);
|
||||
}
|
||||
@@ -526,6 +531,11 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTextColorOrDefault(String key, String defaultColor) {
|
||||
final String translated = NEIClientUtils.translate(key); // Optional localization string for resource packs
|
||||
return translated.startsWith("nei.") ? defaultColor : translated;
|
||||
}
|
||||
|
||||
public static void drawRect(double left, double top, double width, double height, Color color) {
|
||||
final boolean is2DTexture = GL11.glGetBoolean(GL11.GL_TEXTURE_2D);
|
||||
final boolean isBlend = GL11.glGetBoolean(GL11.GL_BLEND);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.getMousePosition;
|
||||
import static codechicken.nei.NEIClientConfig.canCheatItem;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.LinkedList;
|
||||
@@ -151,6 +152,8 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
&& slot != null
|
||||
&& slot.getStack() != null
|
||||
&& slot.isItemValid(slot.getStack())) {
|
||||
if (!canCheatItem(slot.getStack())) return false;
|
||||
|
||||
NEIClientUtils.cheatItem(slot.getStack(), button, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.recipe.Badge;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
@@ -21,12 +22,16 @@ import codechicken.nei.recipe.StackInfo;
|
||||
*/
|
||||
public class PositionedStack {
|
||||
|
||||
/** 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 ItemStack[] items;
|
||||
// compatibility dummy
|
||||
public ItemStack item;
|
||||
|
||||
protected int chance = CHANCE_FULL;
|
||||
private boolean permutated = false;
|
||||
|
||||
public PositionedStack(Object object, int x, int y, boolean genPerms) {
|
||||
@@ -82,6 +87,18 @@ public class PositionedStack {
|
||||
for (ItemStack item : items) if (item.stackSize > i) item.stackSize = i;
|
||||
}
|
||||
|
||||
public List<Badge> getBadges() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getChance() {
|
||||
return this.chance;
|
||||
}
|
||||
|
||||
public void setChance(int chance) {
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
public PositionedStack copy() {
|
||||
PositionedStack pStack = new PositionedStack(
|
||||
Arrays.stream(this.items).map(ItemStack::copy).toArray(ItemStack[]::new),
|
||||
@@ -89,6 +106,7 @@ public class PositionedStack {
|
||||
rely,
|
||||
false);
|
||||
pStack.permutated = this.permutated;
|
||||
pStack.chance = this.chance;
|
||||
return pStack;
|
||||
}
|
||||
|
||||
|
||||
@@ -694,13 +694,10 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
|
||||
if (NEIClientConfig.subsetWidgetOnTop()) {
|
||||
return NEIClientUtils.translate("inventory.item_subsets");
|
||||
} else {
|
||||
final String translated = NEIClientUtils.translate("gui.button.label.subset");
|
||||
if (!translated.startsWith("nei.")) { // Optional localization string for resource packs
|
||||
return translated;
|
||||
}
|
||||
|
||||
return EnumChatFormatting.DARK_PURPLE + String.valueOf(SearchField.searchParser.getRedefinedPrefix(PREFIX))
|
||||
+ EnumChatFormatting.RESET;
|
||||
return NEIClientUtils.getTextColorOrDefault(
|
||||
"gui.button.label.subset",
|
||||
EnumChatFormatting.DARK_PURPLE
|
||||
+ String.valueOf(SearchField.searchParser.getRedefinedPrefix(PREFIX)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import codechicken.nei.ItemsGrid.ItemsGridSlot;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.SearchField;
|
||||
import codechicken.nei.bookmark.BookmarkGrid;
|
||||
import codechicken.nei.bookmark.BookmarkGroup;
|
||||
@@ -646,8 +647,10 @@ public abstract class ShortcutInputHandler {
|
||||
final List<ItemStack> playerInventory = AutoCraftingManager.getInventoryItems(guiContainer).values();
|
||||
final RecipeId rootRecipeId = math.createMasterRoot();
|
||||
|
||||
for (BookmarkItem item : math.recipeIngredients) {
|
||||
if (item.amount > 0 && rootRecipeId.equals(item.recipeId)) {
|
||||
for (int i = 0; i < math.recipeIngredients.size(); i++) {
|
||||
final BookmarkItem item = math.recipeIngredients.get(i);
|
||||
|
||||
if (item.getAmount() > 0 && rootRecipeId.equals(item.recipeId)) {
|
||||
long amount = 0;
|
||||
|
||||
for (ItemStack stack : playerInventory) {
|
||||
@@ -656,8 +659,12 @@ public abstract class ShortcutInputHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (amount >= item.amount) {
|
||||
item.factor = item.amount = amount + item.amount - (amount % item.amount);
|
||||
if (amount >= item.getAmount()) {
|
||||
math.recipeIngredients.set(
|
||||
i,
|
||||
BookmarkItem.builder(item).multiplier(1)
|
||||
.factor(amount + item.getAmount() - (amount % item.getAmount()))
|
||||
.chance(PositionedStack.CHANCE_FULL).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.BookmarkPanel.BookmarkViewMode;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.ItemStackAmount;
|
||||
import codechicken.nei.ItemStackSet;
|
||||
import codechicken.nei.ItemsGrid;
|
||||
import codechicken.nei.ItemsGrid.MouseContext;
|
||||
import codechicken.nei.LayoutManager;
|
||||
@@ -33,6 +33,7 @@ import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
|
||||
import codechicken.nei.recipe.Recipe;
|
||||
import codechicken.nei.recipe.Recipe.RecipeId;
|
||||
import codechicken.nei.recipe.Recipe.RecipeIngredient;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.recipe.chain.RecipeChainMath;
|
||||
|
||||
@@ -139,17 +140,16 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
if (group.collapsedRecipes.contains(collapsedRecipeId)) {
|
||||
|
||||
for (BookmarkItem item : this.bookmarkItems) {
|
||||
if (item.groupId == groupId && collapsedRecipeId.equals(item.recipeId)
|
||||
&& item.amount == item.factor) {
|
||||
item.amount = 0;
|
||||
if (item.groupId == groupId && collapsedRecipeId.equals(item.recipeId) && item.multiplier == 1) {
|
||||
item.multiplier = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (BookmarkItem item : this.bookmarkItems) {
|
||||
if (item.groupId == groupId && collapsedRecipeId.equals(item.recipeId) && item.amount == 0) {
|
||||
item.amount = item.factor;
|
||||
if (item.groupId == groupId && collapsedRecipeId.equals(item.recipeId) && item.multiplier == 0) {
|
||||
item.multiplier = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -627,15 +627,17 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
for (int itemIndex = 0; itemIndex < this.bookmarkItems.size(); itemIndex++) {
|
||||
final BookmarkItem item = this.bookmarkItems.get(itemIndex);
|
||||
if (item.groupId == groupId && (recipeRelations == null || recipeRelations.contains(item.recipeId))) {
|
||||
long amount = item.amount;
|
||||
|
||||
if (recipeId != null && group.crafting != null
|
||||
&& group.crafting.calculatedItems.containsKey(itemIndex)
|
||||
&& recipeId.equals(item.recipeId)) {
|
||||
amount = group.crafting.calculatedItems.get(itemIndex).getCalculatedAmount();
|
||||
chainItems.add(
|
||||
item.copyWithMultiplier(
|
||||
group.crafting.calculatedItems.get(itemIndex).getCalculatedMultiplier()));
|
||||
} else {
|
||||
chainItems.add(item.copy());
|
||||
}
|
||||
|
||||
chainItems.add(item.copyWithAmount(amount));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -896,34 +898,38 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
}
|
||||
|
||||
public void addRecipe(Recipe recipe, int multiplier, int groupId) {
|
||||
final RecipeId recipeId = recipe.getRecipeId();
|
||||
final List<ItemStack> results = recipe.getResults().stream().map(res -> res.getItemStack())
|
||||
.collect(Collectors.toList());
|
||||
final List<ItemStack> ingredients = recipe.getIngredients().stream().map(ingr -> ingr.getItemStack())
|
||||
.collect(Collectors.toList());
|
||||
final ItemStackSet seenResults = new ItemStackSet();
|
||||
final ItemStackSet seenIngredients = new ItemStackSet();
|
||||
final List<ItemStack> results = new ArrayList<>();
|
||||
final List<ItemStack> ingredients = new ArrayList<>();
|
||||
|
||||
for (ItemStack stack : ItemStackAmount.of(results).values()) {
|
||||
long factor = StackInfo.getAmount(stack);
|
||||
for (RecipeIngredient result : recipe.getResults()) {
|
||||
ItemStack stack = result.getItemStack();
|
||||
if (!seenResults.contains(stack)) {
|
||||
seenResults.add(stack);
|
||||
results.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
for (RecipeIngredient ingr : recipe.getIngredients()) {
|
||||
ItemStack stack = ingr.getItemStack();
|
||||
if (!seenIngredients.contains(stack)) {
|
||||
seenIngredients.add(stack);
|
||||
ingredients.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
for (ItemStack stack : results) {
|
||||
this.addItem(
|
||||
BookmarkItem.of(
|
||||
groupId,
|
||||
StackInfo.withAmount(stack, factor * multiplier),
|
||||
factor,
|
||||
recipeId,
|
||||
BookmarkItemType.RESULT),
|
||||
BookmarkItem.builder(groupId, stack, recipe, BookmarkItemType.RESULT).multiplier(multiplier)
|
||||
.build(),
|
||||
true);
|
||||
}
|
||||
|
||||
for (ItemStack stack : ItemStackAmount.of(ingredients).values()) {
|
||||
long factor = StackInfo.getAmount(stack);
|
||||
for (ItemStack stack : ingredients) {
|
||||
this.addItem(
|
||||
BookmarkItem.of(
|
||||
groupId,
|
||||
StackInfo.withAmount(stack, factor * multiplier),
|
||||
factor,
|
||||
recipeId,
|
||||
BookmarkItemType.INGREDIENT,
|
||||
BookmarkItem.generatePermutations(stack, recipe)),
|
||||
BookmarkItem.builder(groupId, stack, recipe, BookmarkItemType.INGREDIENT).multiplier(multiplier)
|
||||
.build(),
|
||||
true);
|
||||
}
|
||||
}
|
||||
@@ -1133,8 +1139,8 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
final Set<Long> sizes = new HashSet<>();
|
||||
|
||||
for (BookmarkItem item : this.bookmarkItems) {
|
||||
if (item.groupId == targetGroupId && item.amount > 0) {
|
||||
sizes.add(Math.max(item.getStackSize(), item.factor / item.fluidCellAmount));
|
||||
if (item.groupId == targetGroupId && item.getAmount() > 0) {
|
||||
sizes.add(Math.max(item.getStackSize(), item.getStackSize(item.getAmount(1))));
|
||||
items.add(item);
|
||||
}
|
||||
}
|
||||
@@ -1143,14 +1149,16 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
long multiplier = Integer.MAX_VALUE;
|
||||
|
||||
for (BookmarkItem item : items) {
|
||||
long customFactor = (long) Math.ceil(item.amount / (double) gcd);
|
||||
long customMultiplier = (long) (customFactor > 0 ? Math.ceil(item.amount / (double) customFactor) : 0);
|
||||
final long amount = item.getAmount();
|
||||
final long customFactor = (amount + gcd - 1) / gcd;
|
||||
final long customMultiplier = customFactor > 0 ? ((amount + customFactor - 1) / customFactor) : 0;
|
||||
multiplier = Math.min(shiftMultiplier(customMultiplier, shift, 1), multiplier);
|
||||
}
|
||||
|
||||
for (BookmarkItem item : items) {
|
||||
long customFactor = (long) Math.ceil(item.amount / (double) gcd);
|
||||
item.amount = customFactor * multiplier;
|
||||
final long amount = item.getAmount();
|
||||
final long customFactor = (amount + gcd - 1) / gcd;
|
||||
item.multiplier = item.getMultiplierFromAmount(customFactor * multiplier);
|
||||
}
|
||||
} else {
|
||||
final Map<RecipeId, Long> recipeMultipliers = new HashMap<>();
|
||||
@@ -1158,7 +1166,7 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
final List<BookmarkItem> items = new ArrayList<>();
|
||||
|
||||
for (BookmarkItem item : this.bookmarkItems) {
|
||||
if (item.factor > 0
|
||||
if (!item.emptyFactor()
|
||||
&& outputRecipes.stream().anyMatch(recipeId -> item.equalsRecipe(recipeId, targetGroupId))) {
|
||||
final long multiplier = recipeMultipliers.getOrDefault(item.recipeId, (long) Integer.MAX_VALUE);
|
||||
final boolean recipeInMiddle = group.crafting != null
|
||||
@@ -1168,7 +1176,7 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
item.recipeId,
|
||||
Math.min(
|
||||
shiftMultiplier(
|
||||
Math.max(recipeInMiddle ? 1 : 0, item.getMultiplier()),
|
||||
Math.max(recipeInMiddle ? 1 : 0, item.multiplier),
|
||||
shift,
|
||||
recipeInMiddle ? 1 : 0),
|
||||
multiplier));
|
||||
@@ -1177,7 +1185,7 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
}
|
||||
|
||||
for (BookmarkItem item : items) {
|
||||
item.amount = item.factor * recipeMultipliers.getOrDefault(item.recipeId, 0L);
|
||||
item.multiplier = recipeMultipliers.getOrDefault(item.recipeId, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1197,10 +1205,10 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
long multiplier = Integer.MAX_VALUE;
|
||||
|
||||
for (BookmarkItem item : this.bookmarkItems) {
|
||||
if (item.equalsRecipe(recipeId, targetItem.groupId) && item.factor > 0) {
|
||||
if (item.equalsRecipe(recipeId, targetItem.groupId) && !item.emptyFactor()) {
|
||||
multiplier = Math.min(
|
||||
shiftMultiplier(
|
||||
Math.max(recipeInMiddle ? 1 : 0, item.getMultiplier()),
|
||||
Math.max(recipeInMiddle ? 1 : 0, item.multiplier),
|
||||
shift,
|
||||
recipeInMiddle ? 1 : 0),
|
||||
multiplier);
|
||||
@@ -1208,8 +1216,8 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
}
|
||||
|
||||
for (BookmarkItem item : this.bookmarkItems) {
|
||||
if (item.equalsRecipe(recipeId, targetItem.groupId) && item.factor > 0) {
|
||||
item.amount = item.factor * multiplier;
|
||||
if (item.equalsRecipe(recipeId, targetItem.groupId) && !item.emptyFactor()) {
|
||||
item.multiplier = multiplier;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1217,7 +1225,7 @@ public class BookmarkGrid extends ItemsGrid<BookmarksGridSlot, BookmarkGrid.Book
|
||||
|
||||
for (BookmarkItem item : this.bookmarkItems) {
|
||||
if (targetItem.equals(item)) {
|
||||
item.amount = item.factor * shiftMultiplier(item.getMultiplier(), shift, 0);
|
||||
item.multiplier = shiftMultiplier(item.multiplier, shift, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,10 +66,14 @@ public class BookmarkGridGenerator {
|
||||
while (itemIndex < size && absoluteSlotIndex != -1) {
|
||||
final BookmarkItem bookmarkItem = this.grid.getBookmarkItem(itemIndex);
|
||||
final BookmarkGroup group = this.grid.getGroup(bookmarkItem.groupId);
|
||||
final boolean isCollapsedRecipeAnchor = group.crafting != null && bookmarkItem.recipeId != null
|
||||
&& bookmarkItem.type != BookmarkItemType.INGREDIENT
|
||||
&& group.collapsedRecipes.contains(bookmarkItem.recipeId);
|
||||
|
||||
if (group.crafting != null && (!group.crafting.calculatedItems.containsKey(itemIndex)
|
||||
|| bookmarkItem.recipeId != null && !bookmarkItem.recipeId
|
||||
.equals(group.crafting.itemToRecipe.getOrDefault(itemIndex, bookmarkItem.recipeId)))) {
|
||||
if (group.crafting != null && !isCollapsedRecipeAnchor
|
||||
&& (!group.crafting.calculatedItems.containsKey(itemIndex)
|
||||
|| bookmarkItem.recipeId != null && !bookmarkItem.recipeId.equals(
|
||||
group.crafting.itemToRecipe.getOrDefault(itemIndex, bookmarkItem.recipeId)))) {
|
||||
itemIndex++;
|
||||
} else if (group.collapsed) {
|
||||
final List<Integer> results = getGroupResults(bookmarkItem.groupId, itemIndex, size);
|
||||
@@ -189,13 +193,11 @@ public class BookmarkGridGenerator {
|
||||
for (int shadowIndex : shadows) {
|
||||
final boolean isIngredient = shadows.get(0) != shadowIndex
|
||||
|| group.crafting.calculatedItems.get(shadowIndex).calculatedType == CalculatedType.INGREDIENT;
|
||||
final BookmarkItem shadowBookmarkItem = BookmarkItem.of(
|
||||
bookmarkItem.groupId,
|
||||
bookmarkItem.itemStack,
|
||||
1,
|
||||
bookmarkItem.recipeId,
|
||||
isIngredient ? BookmarkItemType.INGREDIENT : BookmarkItemType.RESULT,
|
||||
Collections.emptyMap());
|
||||
|
||||
final BookmarkItem shadowBookmarkItem = BookmarkItem.builder(bookmarkItem.groupId, bookmarkItem.itemStack)
|
||||
.multiplier(1).factor(StackInfo.getAmount(bookmarkItem.itemStack)).recipeId(bookmarkItem.recipeId)
|
||||
.type(isIngredient ? BookmarkItemType.INGREDIENT : BookmarkItemType.RESULT)
|
||||
.permutations(Collections.emptyMap()).build();
|
||||
|
||||
if ((absoluteSlotIndex = nextSlotIndex(
|
||||
absoluteSlotIndex + 1,
|
||||
@@ -320,7 +322,7 @@ public class BookmarkGridGenerator {
|
||||
return group.crafting.calculatedItems.get(itemIndex);
|
||||
} else {
|
||||
BookmarkChainItem item = BookmarkChainItem.of(this.grid.getBookmarkItem(itemIndex));
|
||||
item.setRealAmount(item.getShiftAmount());
|
||||
item.setRealMultiplier(item.getCalculatedMultiplier());
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -333,7 +335,7 @@ public class BookmarkGridGenerator {
|
||||
return new BookmarksGridSlot(
|
||||
slotIndex,
|
||||
itemIndex,
|
||||
chainItem.getRealAmount(),
|
||||
chainItem.getRealMultiplier(),
|
||||
0,
|
||||
0,
|
||||
chainItem.getItem(),
|
||||
@@ -343,9 +345,9 @@ public class BookmarkGridGenerator {
|
||||
return new BookmarksGridSlot(
|
||||
slotIndex,
|
||||
itemIndex,
|
||||
chainItem.getRealAmount(),
|
||||
chainItem.getRealMultiplier(),
|
||||
chainItem.getShiftAmount(),
|
||||
chainItem.getCalculatedAmount(),
|
||||
chainItem.getCalculatedMultiplier(),
|
||||
chainItem.getItem(),
|
||||
chainItem.calculatedType,
|
||||
group);
|
||||
|
||||
@@ -2,6 +2,7 @@ package codechicken.nei.bookmark;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -10,6 +11,7 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.recipe.Recipe;
|
||||
import codechicken.nei.recipe.Recipe.RecipeId;
|
||||
import codechicken.nei.recipe.Recipe.RecipeIngredient;
|
||||
@@ -17,6 +19,147 @@ import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class BookmarkItem {
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private static Map<ItemStack, String> fuzzyPermutations = new HashMap<>();
|
||||
|
||||
private final int groupId;
|
||||
private final ItemStack stack;
|
||||
private long factor;
|
||||
private long multiplier = -1;
|
||||
private long chance = PositionedStack.CHANCE_FULL;
|
||||
private RecipeId recipeId = null;
|
||||
private Recipe recipe = null;
|
||||
private BookmarkItemType type = BookmarkItemType.ITEM;
|
||||
private Map<String, ItemStack> permutations = null;
|
||||
|
||||
private Builder(int groupId, ItemStack stack) {
|
||||
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack);
|
||||
|
||||
this.groupId = groupId;
|
||||
this.stack = stack;
|
||||
this.factor = nbTag.hasKey("gtFluidName") ? Math.min(144, nbTag.getInteger("Count")) : 1;
|
||||
}
|
||||
|
||||
public Builder factor(long factor) {
|
||||
this.factor = factor;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder multiplier(long multiplier) {
|
||||
this.multiplier = multiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder chance(long chance) {
|
||||
this.chance = chance;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder recipe(Recipe recipe) {
|
||||
this.recipe = recipe;
|
||||
this.recipeId = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder recipeId(RecipeId recipeId) {
|
||||
this.recipeId = recipeId;
|
||||
this.recipe = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder type(BookmarkItemType type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder permutations(Map<String, ItemStack> permutations) {
|
||||
this.permutations = permutations;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BookmarkItem build() {
|
||||
final Map<String, ItemStack> perms;
|
||||
long multiplier = 0;
|
||||
|
||||
if (this.permutations != null) {
|
||||
perms = this.permutations;
|
||||
} else if (this.type == BookmarkItemType.INGREDIENT) {
|
||||
|
||||
if (this.recipe != null) {
|
||||
perms = Builder.generatePermutations(this.stack, this.recipe);
|
||||
} else if (this.recipeId != null) {
|
||||
perms = Builder.generatePermutations(this.stack, Recipe.of(this.recipeId));
|
||||
} else {
|
||||
perms = Builder.generatePermutations(this.stack);
|
||||
}
|
||||
|
||||
} else {
|
||||
perms = Builder.generatePermutations(this.stack);
|
||||
}
|
||||
|
||||
if (this.multiplier >= 0) {
|
||||
multiplier = this.multiplier;
|
||||
} else if (this.factor > 0) {
|
||||
multiplier = StackInfo.getAmount(this.stack) / this.factor;
|
||||
}
|
||||
|
||||
return new BookmarkItem(
|
||||
this.groupId,
|
||||
multiplier,
|
||||
this.factor,
|
||||
this.chance,
|
||||
this.stack,
|
||||
perms,
|
||||
this.recipeId != null ? this.recipeId : this.recipe != null ? this.recipe.getRecipeId() : null,
|
||||
this.type);
|
||||
}
|
||||
|
||||
public static Map<String, ItemStack> generatePermutations(ItemStack stack) {
|
||||
return Collections.singletonMap(getItemGUID(stack), stack);
|
||||
}
|
||||
|
||||
public static Map<String, ItemStack> generatePermutations(ItemStack stack, Recipe recipe) {
|
||||
|
||||
if (recipe != null) {
|
||||
final RecipeIngredient ingr = recipe.getIngredients().stream()
|
||||
.filter(ingredient -> ingredient.contains(stack)).findAny().orElse(null);
|
||||
|
||||
if (ingr != null) {
|
||||
final Map<String, ItemStack> permutations = new HashMap<>();
|
||||
for (ItemStack ingrStack : ingr.getPermutations()) {
|
||||
permutations.put(getItemGUID(ingrStack), ingrStack);
|
||||
}
|
||||
return permutations;
|
||||
}
|
||||
}
|
||||
|
||||
return generatePermutations(stack);
|
||||
}
|
||||
|
||||
private static synchronized String getItemGUID(ItemStack stack) {
|
||||
final FluidStack fluidStack = StackInfo.getFluid(stack);
|
||||
|
||||
if (fluidStack != null) {
|
||||
return fluidStack.getFluid().getName() + ":" + fluidStack.tag;
|
||||
} else {
|
||||
|
||||
for (Map.Entry<ItemStack, String> entry : Builder.fuzzyPermutations.entrySet()) {
|
||||
if (NEIClientUtils.areStacksSameTypeCraftingWithNBT(stack, entry.getKey())) {
|
||||
Builder.fuzzyPermutations.put(stack, entry.getValue());
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
final String stackGUID = StackInfo.getItemStackGUID(stack);
|
||||
Builder.fuzzyPermutations.put(stack, stackGUID);
|
||||
|
||||
return stackGUID;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum BookmarkItemType {
|
||||
|
||||
INGREDIENT,
|
||||
@@ -32,150 +175,128 @@ public class BookmarkItem {
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<ItemStack, String> fuzzyPermutations = new HashMap<>();
|
||||
|
||||
public int groupId;
|
||||
|
||||
public long amount = 0L;
|
||||
public final int fluidCellAmount;
|
||||
public ItemStack itemStack;
|
||||
public Map<String, ItemStack> permutations;
|
||||
|
||||
public long factor;
|
||||
public RecipeId recipeId;
|
||||
public BookmarkItemType type = BookmarkItemType.ITEM;
|
||||
|
||||
protected BookmarkItem(int groupId, long amount, int fluidCellAmount, ItemStack itemStack,
|
||||
Map<String, ItemStack> permutations, long factor, RecipeId recipeId, BookmarkItemType type) {
|
||||
public long multiplier = 1L;
|
||||
public final long factor;
|
||||
public final int fluidCellAmount;
|
||||
public final long chance;
|
||||
|
||||
protected BookmarkItem(int groupId, long multiplier, long factor, long chance, ItemStack itemStack,
|
||||
Map<String, ItemStack> permutations, RecipeId recipeId, BookmarkItemType type) {
|
||||
final FluidStack fluidStack = StackInfo.getFluid(itemStack);
|
||||
|
||||
if (fluidStack != null) {
|
||||
this.fluidCellAmount = Math.max(1, StackInfo.isFluidContainer(itemStack) ? fluidStack.amount : 1);
|
||||
} else {
|
||||
this.fluidCellAmount = 1;
|
||||
}
|
||||
|
||||
this.groupId = groupId;
|
||||
|
||||
this.amount = amount;
|
||||
this.fluidCellAmount = fluidCellAmount;
|
||||
this.itemStack = itemStack;
|
||||
this.permutations = permutations;
|
||||
|
||||
this.factor = factor;
|
||||
this.recipeId = recipeId;
|
||||
this.type = type == null ? BookmarkItemType.ITEM : type;
|
||||
|
||||
this.multiplier = multiplier;
|
||||
this.factor = factor;
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
public static BookmarkItem of(int groupId, ItemStack stack, long factor, RecipeId recipeId, BookmarkItemType type,
|
||||
Map<String, ItemStack> permutations) {
|
||||
final FluidStack fluidStack = StackInfo.getFluid(stack);
|
||||
int fluidCellAmount = 1;
|
||||
long amount;
|
||||
public static Builder builder(int groupId, ItemStack stack) {
|
||||
return new Builder(groupId, stack);
|
||||
}
|
||||
|
||||
if (fluidStack != null) {
|
||||
amount = fluidStack.amount * (long) Math.max(0, stack.stackSize);
|
||||
fluidCellAmount = Math.max(1, StackInfo.isFluidContainer(stack) ? fluidStack.amount : 1);
|
||||
} else {
|
||||
amount = StackInfo.getAmount(stack);
|
||||
public static Builder builder(BookmarkItem item) {
|
||||
return new Builder(item.groupId, item.itemStack).factor(item.factor).multiplier(item.multiplier)
|
||||
.chance(item.chance).recipeId(item.recipeId).type(item.type).permutations(item.permutations);
|
||||
}
|
||||
|
||||
public static Builder builder(int groupId, ItemStack stack, Recipe recipe, BookmarkItemType type) {
|
||||
final List<RecipeIngredient> items = type == BookmarkItemType.RESULT ? recipe.getResults()
|
||||
: recipe.getIngredients();
|
||||
final Builder builder = builder(groupId, stack).type(type).recipe(recipe);
|
||||
long amount = 0;
|
||||
|
||||
for (RecipeIngredient res : items) {
|
||||
if (res.contains(stack)) {
|
||||
amount += 1L * res.getAmount() * res.getChance();
|
||||
}
|
||||
}
|
||||
|
||||
return new BookmarkItem(
|
||||
groupId,
|
||||
amount,
|
||||
fluidCellAmount,
|
||||
stack,
|
||||
permutations,
|
||||
factor * fluidCellAmount,
|
||||
recipeId,
|
||||
type);
|
||||
}
|
||||
if ((amount % PositionedStack.CHANCE_FULL) == 0) {
|
||||
builder.factor(amount / PositionedStack.CHANCE_FULL);
|
||||
} else {
|
||||
builder.factor(1).chance(amount);
|
||||
}
|
||||
|
||||
public static BookmarkItem of(int groupId, ItemStack stack, long factor, RecipeId recipeId, BookmarkItemType type) {
|
||||
return of(
|
||||
groupId,
|
||||
stack,
|
||||
factor,
|
||||
recipeId,
|
||||
type,
|
||||
generatePermutations(stack, recipeId, type == BookmarkItemType.INGREDIENT));
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static BookmarkItem of(int groupId, ItemStack stack) {
|
||||
final NBTTagCompound nbTag = StackInfo.itemStackToNBT(stack);
|
||||
final long factor = nbTag.hasKey("gtFluidName") ? Math.min(144, nbTag.getInteger("Count")) : 1;
|
||||
return BookmarkItem.of(
|
||||
groupId,
|
||||
stack,
|
||||
factor,
|
||||
null,
|
||||
BookmarkItemType.ITEM,
|
||||
Collections.singletonMap(getItemGUID(stack), stack));
|
||||
return builder(groupId, stack).build();
|
||||
}
|
||||
|
||||
public BookmarkItem copyWithAmount(long amount) {
|
||||
public BookmarkItem copyWithMultiplier(long multiplier) {
|
||||
return new BookmarkItem(
|
||||
this.groupId,
|
||||
amount,
|
||||
this.fluidCellAmount,
|
||||
multiplier,
|
||||
this.factor,
|
||||
this.chance,
|
||||
this.itemStack,
|
||||
this.permutations,
|
||||
this.factor,
|
||||
this.recipeId,
|
||||
this.type);
|
||||
}
|
||||
|
||||
public BookmarkItem copyWithAmount(long amount) {
|
||||
return copyWithMultiplier(getMultiplierFromAmount(amount));
|
||||
}
|
||||
|
||||
public BookmarkItem copy() {
|
||||
return copyWithAmount(this.amount);
|
||||
}
|
||||
|
||||
public static Map<String, ItemStack> generatePermutations(ItemStack stack, RecipeId recipeId,
|
||||
boolean isIngredient) {
|
||||
|
||||
if (isIngredient && recipeId != null) {
|
||||
return generatePermutations(stack, Recipe.of(recipeId));
|
||||
}
|
||||
|
||||
return Collections.singletonMap(getItemGUID(stack), stack);
|
||||
}
|
||||
|
||||
public static Map<String, ItemStack> generatePermutations(ItemStack stack, Recipe recipe) {
|
||||
|
||||
if (recipe != null) {
|
||||
final RecipeIngredient ingr = recipe.getIngredients().stream()
|
||||
.filter(ingredient -> ingredient.contains(stack)).findAny().orElse(null);
|
||||
|
||||
if (ingr != null) {
|
||||
final Map<String, ItemStack> permutations = new HashMap<>();
|
||||
for (ItemStack ingrStack : ingr.getPermutations()) {
|
||||
permutations.put(getItemGUID(ingrStack), ingrStack);
|
||||
}
|
||||
return permutations;
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.singletonMap(getItemGUID(stack), stack);
|
||||
}
|
||||
|
||||
private static synchronized String getItemGUID(ItemStack stack) {
|
||||
final FluidStack fluidStack = StackInfo.getFluid(stack);
|
||||
|
||||
if (fluidStack != null) {
|
||||
return fluidStack.getFluid().getName() + ":" + fluidStack.tag;
|
||||
} else {
|
||||
|
||||
for (Map.Entry<ItemStack, String> entry : BookmarkItem.fuzzyPermutations.entrySet()) {
|
||||
if (NEIClientUtils.areStacksSameTypeCraftingWithNBT(stack, entry.getKey())) {
|
||||
BookmarkItem.fuzzyPermutations.put(stack, entry.getValue());
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
final String stackGUID = StackInfo.getItemStackGUID(stack);
|
||||
BookmarkItem.fuzzyPermutations.put(stack, stackGUID);
|
||||
|
||||
return stackGUID;
|
||||
}
|
||||
return copyWithMultiplier(this.multiplier);
|
||||
}
|
||||
|
||||
public boolean containsItems(BookmarkItem item) {
|
||||
return this.permutations.keySet().stream().anyMatch(item.permutations::containsKey);
|
||||
}
|
||||
|
||||
public long getAmount() {
|
||||
return getAmount(this.multiplier);
|
||||
}
|
||||
|
||||
public long getAmount(long multiplier) {
|
||||
long amount = this.factor * multiplier;
|
||||
|
||||
if (this.fluidCellAmount > 1) {
|
||||
amount = amount * this.fluidCellAmount;
|
||||
}
|
||||
|
||||
if (this.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;
|
||||
} else {
|
||||
// For results, round down the expected amount to be conservative.
|
||||
amount = (amount * this.chance) / PositionedStack.CHANCE_FULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return getItemStack(this.amount);
|
||||
return getItemStack(getAmount());
|
||||
}
|
||||
|
||||
public ItemStack getItemStack(long amount) {
|
||||
@@ -183,23 +304,34 @@ public class BookmarkItem {
|
||||
}
|
||||
|
||||
public long getStackSize() {
|
||||
return getStackSize(this.amount);
|
||||
return getStackSize(getAmount());
|
||||
}
|
||||
|
||||
public long getStackSize(long amount) {
|
||||
return (long) (this.factor > 0 ? Math.ceil(amount / (double) this.fluidCellAmount) : 0);
|
||||
|
||||
if (this.fluidCellAmount > 1) {
|
||||
amount = (amount + this.fluidCellAmount - 1) / this.fluidCellAmount;
|
||||
}
|
||||
|
||||
return amount;
|
||||
}
|
||||
|
||||
public long getMultiplierFromAmount(long amount) {
|
||||
if (this.factor <= 0 || this.chance <= 0) return 0;
|
||||
|
||||
if (this.fluidCellAmount > 1) {
|
||||
amount = (amount + this.fluidCellAmount - 1) / this.fluidCellAmount;
|
||||
}
|
||||
|
||||
if (this.chance == PositionedStack.CHANCE_FULL) {
|
||||
return (amount + this.factor - 1) / this.factor;
|
||||
}
|
||||
|
||||
return (amount * PositionedStack.CHANCE_FULL + this.factor * this.chance - 1) / (this.factor * this.chance);
|
||||
}
|
||||
|
||||
public long getMultiplier() {
|
||||
return getMultiplier(this.amount);
|
||||
}
|
||||
|
||||
public long getMultiplier(long amount) {
|
||||
return (long) (this.factor > 0 ? Math.ceil(amount / (double) this.factor) : 0);
|
||||
}
|
||||
|
||||
public long getFactor() {
|
||||
return this.factor / this.fluidCellAmount;
|
||||
return this.multiplier;
|
||||
}
|
||||
|
||||
public boolean equalsRecipe(BookmarkItem meta) {
|
||||
@@ -210,6 +342,10 @@ public class BookmarkItem {
|
||||
return groupId == this.groupId && recipeId != null && recipeId.equals(this.recipeId);
|
||||
}
|
||||
|
||||
public boolean emptyFactor() {
|
||||
return this.factor <= 0 || this.chance <= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(this.groupId, this.fluidCellAmount, this.type.toInt(), this.recipeId);
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import codechicken.nei.BookmarkPanel.BookmarkViewMode;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
|
||||
import codechicken.nei.recipe.Recipe.RecipeId;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
@@ -249,30 +250,36 @@ public class BookmarkStorage {
|
||||
ItemStack itemStack = StackInfo.loadFromNBT(itemStackNBT);
|
||||
|
||||
if (itemStack != null) {
|
||||
RecipeId recipeId = null;
|
||||
boolean isFluid = itemStackNBT.hasKey("gtFluidName");
|
||||
int groupId = jsonObject.has("groupId") ? jsonObject.get("groupId").getAsInt()
|
||||
int groupId = jsonObject.has("groupId") && grid.groups.containsKey(jsonObject.get("groupId").getAsInt())
|
||||
? jsonObject.get("groupId").getAsInt()
|
||||
: BookmarkGrid.DEFAULT_GROUP_ID;
|
||||
int factor = jsonObject.has("factor") ? Math.abs(jsonObject.get("factor").getAsInt()) : (isFluid ? 144 : 1);
|
||||
BookmarkItemType type = jsonObject.has("type") ? BookmarkItemType.fromInt(jsonObject.get("type").getAsInt())
|
||||
: null;
|
||||
final BookmarkItem.Builder builder = BookmarkItem.builder(groupId, itemStack);
|
||||
|
||||
if (type == null) {
|
||||
// old format
|
||||
type = jsonObject.has("ingredient") && jsonObject.get("ingredient").getAsBoolean()
|
||||
? BookmarkItemType.INGREDIENT
|
||||
: BookmarkItemType.RESULT;
|
||||
if (jsonObject.has("type")) {
|
||||
builder.type(BookmarkItemType.fromInt(jsonObject.get("type").getAsInt()));
|
||||
} else if (jsonObject.has("ingredient") && jsonObject.get("ingredient").getAsBoolean()) {
|
||||
builder.type(BookmarkItemType.INGREDIENT);
|
||||
} else {
|
||||
builder.type(BookmarkItemType.RESULT);
|
||||
}
|
||||
|
||||
if (jsonObject.has("multiplier")) {
|
||||
builder.multiplier(jsonObject.get("multiplier").getAsInt());
|
||||
}
|
||||
|
||||
if (jsonObject.has("factor")) {
|
||||
builder.factor(jsonObject.get("factor").getAsInt());
|
||||
}
|
||||
|
||||
if (jsonObject.has("chance")) {
|
||||
builder.chance(jsonObject.get("chance").getAsInt());
|
||||
}
|
||||
|
||||
if (jsonObject.get("recipeId") instanceof JsonObject recipeJson) {
|
||||
recipeId = RecipeId.of(recipeJson);
|
||||
builder.recipeId(RecipeId.of(recipeJson));
|
||||
}
|
||||
|
||||
if (!grid.groups.containsKey(groupId)) {
|
||||
groupId = BookmarkGrid.DEFAULT_GROUP_ID;
|
||||
}
|
||||
|
||||
grid.addItem(BookmarkItem.of(groupId, itemStack, factor, recipeId, type), false);
|
||||
grid.addItem(builder.build(), false);
|
||||
}
|
||||
|
||||
return itemStack != null;
|
||||
@@ -321,7 +328,8 @@ public class BookmarkStorage {
|
||||
JsonObject row = new JsonObject();
|
||||
|
||||
row.add("item", NBTJson.toJsonObject(StackInfo.itemStackToNBT(item.getItemStack())));
|
||||
row.add("factor", new JsonPrimitive(item.getFactor()));
|
||||
row.add("multiplier", new JsonPrimitive(item.multiplier));
|
||||
row.add("factor", new JsonPrimitive(item.factor));
|
||||
row.add("type", new JsonPrimitive(item.type.toInt()));
|
||||
|
||||
if (item.groupId != BookmarkGrid.DEFAULT_GROUP_ID) {
|
||||
@@ -332,6 +340,10 @@ public class BookmarkStorage {
|
||||
row.add("recipeId", item.recipeId.toJsonObject());
|
||||
}
|
||||
|
||||
if (item.chance != PositionedStack.CHANCE_FULL) {
|
||||
row.add("chance", new JsonPrimitive(item.chance));
|
||||
}
|
||||
|
||||
strings.add(NBTJson.toJson(row));
|
||||
} catch (JsonSyntaxException e) {
|
||||
NEIClientConfig.logger.error("Failed to stringify bookmarked ItemStack to json string");
|
||||
|
||||
@@ -14,6 +14,7 @@ import codechicken.nei.ItemsGrid.MouseContext;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIClientUtils.Alignment;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.bookmark.BookmarkGrid.BookmarkMouseContext;
|
||||
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
|
||||
import codechicken.nei.bookmark.RecipeChainDetails.CalculatedType;
|
||||
@@ -63,18 +64,18 @@ public class BookmarksGridSlot extends ItemsGridSlot {
|
||||
protected final boolean isFirstOutput;
|
||||
protected final int rowIndex;
|
||||
|
||||
public BookmarksGridSlot(int slotIndex, int itemIndex, long realAmount, long shiftAmount, long calculatedAmount,
|
||||
BookmarkItem bookmarkItem, CalculatedType calculatedType, BookmarkGroup group) {
|
||||
public BookmarksGridSlot(int slotIndex, int itemIndex, long realMultiplier, long shiftAmount,
|
||||
long calculatedMultiplier, BookmarkItem bookmarkItem, CalculatedType calculatedType, BookmarkGroup group) {
|
||||
super(
|
||||
slotIndex,
|
||||
itemIndex,
|
||||
calculatedType != null ? bookmarkItem.getItemStack(calculatedAmount)
|
||||
: bookmarkItem.getItemStack(realAmount));
|
||||
calculatedType != null ? bookmarkItem.getItemStack(bookmarkItem.getAmount(calculatedMultiplier))
|
||||
: bookmarkItem.getItemStack(bookmarkItem.getAmount(realMultiplier)));
|
||||
|
||||
this.emptyItemStack = bookmarkItem.getItemStack(0);
|
||||
this.realAmount = realAmount;
|
||||
this.realAmount = bookmarkItem.getAmount(realMultiplier);
|
||||
this.shiftAmount = shiftAmount;
|
||||
this.calculatedAmount = calculatedAmount;
|
||||
this.calculatedAmount = calculatedType != null ? bookmarkItem.getAmount(calculatedMultiplier) : this.realAmount;
|
||||
|
||||
this.group = group;
|
||||
this.calculatedType = calculatedType;
|
||||
@@ -83,8 +84,8 @@ public class BookmarksGridSlot extends ItemsGridSlot {
|
||||
this.isOutputRecipe = group.crafting != null && group.crafting.outputRecipes.contains(bookmarkItem.recipeId);
|
||||
this.isFluidDisplay = StackInfo.itemStackToNBT(bookmarkItem.itemStack).hasKey("gtFluidName");
|
||||
|
||||
this.realMultiplier = bookmarkItem.getMultiplier(realAmount);
|
||||
this.calculatedMultiplier = bookmarkItem.getMultiplier(calculatedAmount);
|
||||
this.realMultiplier = realMultiplier;
|
||||
this.calculatedMultiplier = calculatedMultiplier;
|
||||
|
||||
if (this.group.crafting != null && this.group.crafting.calculatedItems.containsKey(this.itemIndex)) {
|
||||
this.realType = this.group.crafting.calculatedItems.get(this.itemIndex).calculatedType
|
||||
@@ -347,17 +348,22 @@ public class BookmarksGridSlot extends ItemsGridSlot {
|
||||
}
|
||||
|
||||
protected void drawStackSize(Rectangle4i rect, ShownItemType shownItemType) {
|
||||
boolean drawChance = this.calculatedMultiplier > 0;
|
||||
long amount = this.calculatedAmount;
|
||||
|
||||
if (shownItemType == null || shownItemType == ShownItemType.REAL || this.calculatedType == null) {
|
||||
amount = this.realAmount;
|
||||
drawChance = this.realMultiplier > 0;
|
||||
} else if (shownItemType == ShownItemType.SHIFT) {
|
||||
amount = this.shiftAmount;
|
||||
drawChance = false;
|
||||
}
|
||||
|
||||
if (amount > 0 || shownItemType == ShownItemType.REAL && this.bookmarkItem.factor > 0) {
|
||||
if (amount > 0 || this.bookmarkItem.chance != PositionedStack.CHANCE_FULL && drawChance
|
||||
|| shownItemType == ShownItemType.REAL && !this.bookmarkItem.emptyFactor()) {
|
||||
final float panelFactor = (rect.w - 2) / (DEFAULT_SLOT_SIZE - 2);
|
||||
final long stackSize = this.bookmarkItem.getStackSize(amount);
|
||||
int color = 0xFFFFFF;
|
||||
String amountString = "";
|
||||
|
||||
if (stackSize < 10_000) {
|
||||
@@ -370,11 +376,16 @@ public class BookmarksGridSlot extends ItemsGridSlot {
|
||||
amountString += "L";
|
||||
}
|
||||
|
||||
if (this.bookmarkItem.chance != PositionedStack.CHANCE_FULL) {
|
||||
amountString = "~" + amountString;
|
||||
color = 0xFFAA00;
|
||||
}
|
||||
|
||||
NEIClientUtils.drawNEIOverlayText(
|
||||
amountString,
|
||||
new Rectangle4i(rect.x + 1, rect.y + 1, rect.w - 2, rect.h - 2),
|
||||
panelFactor,
|
||||
0xFFFFFF,
|
||||
color,
|
||||
true,
|
||||
this.isFluidDisplay ? Alignment.BottomLeft : Alignment.BottomRight);
|
||||
}
|
||||
|
||||
@@ -42,34 +42,35 @@ public class RecipeChainDetails {
|
||||
|
||||
private final BookmarkItem item;
|
||||
|
||||
private long realAmount = 0L;
|
||||
private long realMultiplier = 0L;
|
||||
private long shiftAmount = 0L;
|
||||
private long calculatedAmount = 0L;
|
||||
private long calculatedMultiplier = 0L;
|
||||
|
||||
public CalculatedType calculatedType;
|
||||
|
||||
protected BookmarkChainItem(BookmarkItem item, long shiftItem, long calculatedItem,
|
||||
protected BookmarkChainItem(BookmarkItem item, long shiftItem, long calculatedMultiplier,
|
||||
CalculatedType calculatedType) {
|
||||
this.item = item.copy();
|
||||
this.shiftAmount = shiftItem;
|
||||
this.calculatedAmount = calculatedItem;
|
||||
this.calculatedMultiplier = calculatedMultiplier;
|
||||
this.calculatedType = calculatedType;
|
||||
}
|
||||
|
||||
public static BookmarkChainItem of(BookmarkItem item, long shiftItem, long calculatedAmount,
|
||||
public static BookmarkChainItem of(BookmarkItem item, long shiftItem, long calculatedMultiplier,
|
||||
CalculatedType calculatedType) {
|
||||
return new BookmarkChainItem(item, shiftItem, calculatedAmount, calculatedType);
|
||||
return new BookmarkChainItem(item, shiftItem, calculatedMultiplier, calculatedType);
|
||||
}
|
||||
|
||||
public static BookmarkChainItem of(BookmarkItem item, long shiftItem, CalculatedType calculatedType) {
|
||||
return new BookmarkChainItem(item, shiftItem, item.amount, calculatedType);
|
||||
return new BookmarkChainItem(item, shiftItem, item.getMultiplier(), calculatedType);
|
||||
}
|
||||
|
||||
public static BookmarkChainItem of(BookmarkItem item) {
|
||||
final long amount = item.getAmount();
|
||||
return new BookmarkChainItem(
|
||||
item,
|
||||
item.amount,
|
||||
item.amount,
|
||||
amount,
|
||||
item.getMultiplier(),
|
||||
item.type == BookmarkItemType.INGREDIENT ? CalculatedType.INGREDIENT : CalculatedType.RESULT);
|
||||
}
|
||||
|
||||
@@ -77,30 +78,34 @@ public class RecipeChainDetails {
|
||||
return this.item.getItemStack(amount);
|
||||
}
|
||||
|
||||
public void setRealAmount(long amount) {
|
||||
this.realAmount = amount;
|
||||
public void setRealMultiplier(long multiplier) {
|
||||
this.realMultiplier = multiplier;
|
||||
}
|
||||
|
||||
public long getRealAmount() {
|
||||
return this.realAmount;
|
||||
public long getRealMultiplier() {
|
||||
return this.realMultiplier;
|
||||
}
|
||||
|
||||
public void setCalculatedMultiplier(long multiplier) {
|
||||
this.calculatedMultiplier = multiplier;
|
||||
}
|
||||
|
||||
public long getCalculatedMultiplier() {
|
||||
return this.calculatedMultiplier;
|
||||
}
|
||||
|
||||
public long getShiftAmount() {
|
||||
return this.shiftAmount;
|
||||
}
|
||||
|
||||
public long getCalculatedAmount() {
|
||||
return this.calculatedAmount;
|
||||
}
|
||||
|
||||
public BookmarkItem getItem() {
|
||||
return this.item;
|
||||
}
|
||||
|
||||
public void append(long amount, long calculatedAmount) {
|
||||
this.shiftAmount += amount;
|
||||
this.calculatedAmount += calculatedAmount;
|
||||
this.item.amount = this.calculatedAmount;
|
||||
this.calculatedMultiplier += this.item.getMultiplierFromAmount(calculatedAmount);
|
||||
this.item.multiplier = this.calculatedMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,10 +185,9 @@ public class RecipeChainDetails {
|
||||
if (itemIndex >= 0 && this.calculatedItems.containsKey(itemIndex)) {
|
||||
final BookmarkItem item = entry.getValue();
|
||||
if (this.recipeInMiddle.contains(item.recipeId)) {
|
||||
this.calculatedItems.get(itemIndex)
|
||||
.setRealAmount(Math.max(0, item.factor * (item.getMultiplier() - 1)));
|
||||
this.calculatedItems.get(itemIndex).setRealMultiplier(Math.max(0, item.getMultiplier() - 1));
|
||||
} else {
|
||||
this.calculatedItems.get(itemIndex).setRealAmount(item.amount);
|
||||
this.calculatedItems.get(itemIndex).setRealMultiplier(item.getMultiplier());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,7 +243,7 @@ public class RecipeChainDetails {
|
||||
|
||||
for (BookmarkItem item : chainItems) {
|
||||
if (recipeRelations.contains(item.recipeId)) {
|
||||
subChainItems.add(item.copyWithAmount(recipeId.equals(item.recipeId) ? item.amount : 0));
|
||||
subChainItems.add(item.copyWithMultiplier(recipeId.equals(item.recipeId) ? item.multiplier : 0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,7 +262,8 @@ public class RecipeChainDetails {
|
||||
}
|
||||
|
||||
if (this.calculatedItems.containsKey(itemIndex)) {
|
||||
this.calculatedItems.get(itemIndex).setRealAmount(value.getShiftAmount());
|
||||
this.calculatedItems.get(itemIndex)
|
||||
.setRealMultiplier(value.getItem().getMultiplierFromAmount(value.getShiftAmount()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,18 +277,19 @@ public class RecipeChainDetails {
|
||||
for (RecipeId relRecipeId : recipeRelations) {
|
||||
for (BookmarkItem item : math.recipeResults) {
|
||||
if (item.recipeId.equals(relRecipeId)) {
|
||||
final long amount = item.amount - math.requiredAmount.getOrDefault(item, 0L);
|
||||
final long amount = item.getAmount() - math.requiredAmount.getOrDefault(item, 0L);
|
||||
|
||||
if (item.recipeId.equals(recipeId)) {
|
||||
multiplier.put(item.recipeId, item.getMultiplier());
|
||||
items.computeIfAbsent(
|
||||
StackInfo.getItemStackGUID(item.itemStack),
|
||||
is -> BookmarkChainItem.of(item, 0, 0, CalculatedType.RESULT))
|
||||
.append(amount, item.amount);
|
||||
.append(amount, item.getAmount());
|
||||
} else if (amount > 0) {
|
||||
items.computeIfAbsent(
|
||||
StackInfo.getItemStackGUID(item.itemStack),
|
||||
is -> BookmarkChainItem.of(item, 0, 0, CalculatedType.RESULT)).append(amount, amount);
|
||||
is -> BookmarkChainItem.of(item, 0, 0, CalculatedType.RESULT))
|
||||
.append(amount, item.getAmount());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -292,17 +298,17 @@ public class RecipeChainDetails {
|
||||
if (item.recipeId.equals(relRecipeId)) {
|
||||
final BookmarkItem prefItem = math.preferredItems.get(item);
|
||||
final long amount = math.requiredAmount.containsKey(prefItem) ? 0
|
||||
: math.requiredAmount.getOrDefault(item, item.amount);
|
||||
: math.requiredAmount.getOrDefault(item, item.getAmount());
|
||||
final long refAmount = prefItem != null && !topLevelRecipes.contains(prefItem.recipeId)
|
||||
? math.requiredAmount.getOrDefault(prefItem, 0L)
|
||||
: 0;
|
||||
|
||||
if (amount != 0 || item.amount > refAmount && math.requiredAmount.containsKey(prefItem)
|
||||
if (amount != 0 || item.getAmount() > refAmount && math.requiredAmount.containsKey(prefItem)
|
||||
|| recipeId.equals(item.recipeId) && multiplier.get(recipeId) == 0) {
|
||||
items.computeIfAbsent(
|
||||
StackInfo.getItemStackGUID(item.itemStack),
|
||||
is -> BookmarkChainItem.of(item, 0, 0, CalculatedType.INGREDIENT))
|
||||
.append(amount, item.amount - refAmount);
|
||||
.append(amount, item.getAmount() - refAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -312,7 +318,7 @@ public class RecipeChainDetails {
|
||||
}
|
||||
|
||||
private void generateResult(RecipeChainMath math, BookmarkItem item, int itemIndex) {
|
||||
final long amount = item.amount - math.requiredAmount.getOrDefault(item, 0L);
|
||||
final long amount = item.getAmount() - math.requiredAmount.getOrDefault(item, 0L);
|
||||
final CalculatedType calculatedType = math.outputRecipes.containsKey(item.recipeId) ? CalculatedType.RESULT
|
||||
: CalculatedType.REMAINDER;
|
||||
|
||||
@@ -322,7 +328,7 @@ public class RecipeChainDetails {
|
||||
private void generateIngredient(RecipeChainMath math, BookmarkItem item, int itemIndex) {
|
||||
final BookmarkItem prefItem = math.preferredItems.get(item);
|
||||
final long amount = math.requiredAmount.containsKey(prefItem) ? 0
|
||||
: math.requiredAmount.getOrDefault(item, item.amount);
|
||||
: math.requiredAmount.getOrDefault(item, item.getAmount());
|
||||
|
||||
this.calculatedItems.put(itemIndex, BookmarkChainItem.of(item, amount, CalculatedType.INGREDIENT));
|
||||
}
|
||||
|
||||
@@ -8,13 +8,15 @@ import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.command.CommandBase;
|
||||
@@ -39,6 +41,7 @@ import codechicken.nei.recipe.GuiRecipeTab;
|
||||
import codechicken.nei.recipe.ICraftingHandler;
|
||||
import codechicken.nei.recipe.Recipe;
|
||||
import codechicken.nei.recipe.RecipeHandlerQuery;
|
||||
import codechicken.nei.recipe.TemplateRecipeHandler;
|
||||
import codechicken.nei.util.NBTJson;
|
||||
|
||||
public class CommandRecipeId extends CommandBase {
|
||||
@@ -125,12 +128,16 @@ public class CommandRecipeId extends CommandBase {
|
||||
|
||||
private ArrayList<ICraftingHandler> craftinghandlers = new ArrayList<>();
|
||||
private ArrayList<ICraftingHandler> serialCraftingHandlers = new ArrayList<>();
|
||||
|
||||
protected final ICommandSender sender;
|
||||
protected final File currFile;
|
||||
protected final boolean fastDump;
|
||||
|
||||
public ProcessDumpThread(ICommandSender sender, File currFile) {
|
||||
public ProcessDumpThread(ICommandSender sender, File currFile, boolean fastDump) {
|
||||
this.sender = sender;
|
||||
this.currFile = currFile;
|
||||
this.fastDump = fastDump;
|
||||
|
||||
ClientHandler.loadSettingsFile("recipeidblacklist.cfg", lines -> {
|
||||
final Set<String> names = lines.collect(Collectors.toSet());
|
||||
|
||||
@@ -150,38 +157,10 @@ public class CommandRecipeId extends CommandBase {
|
||||
sendChatInfoMessage(sender, "nei.chat.recipeid.dump.start");
|
||||
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(currFile.toPath(), StandardCharsets.UTF_8)) {
|
||||
int total = ItemList.items.size();
|
||||
int count = 0;
|
||||
|
||||
for (ItemStack stack : ItemList.items) {
|
||||
|
||||
if (count % 1000 == 0) {
|
||||
NEIClientConfig.logger.info(
|
||||
"({}/{}). Processing {} crafting recipes...",
|
||||
count,
|
||||
total,
|
||||
stack.getDisplayName());
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
for (ICraftingHandler handler : getCraftingHandlers(stack)) {
|
||||
for (int index = 0, num = handler.numRecipes(); index < num; index++) {
|
||||
try {
|
||||
final Recipe recipe = Recipe.of(handler, index);
|
||||
if (!recipe.getIngredients().isEmpty() && !recipe.getResults().isEmpty()) {
|
||||
writer.write(NBTJson.toJson(recipe.getRecipeId().toJsonObject()));
|
||||
writer.newLine();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
NEIClientConfig.logger.error(
|
||||
"Found Broken RecipeId {}:{}",
|
||||
GuiRecipeTab.getHandlerInfo(handler).getHandlerName(),
|
||||
stack,
|
||||
ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fastDump) {
|
||||
processFastDump(writer);
|
||||
} else {
|
||||
processDump(writer);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -192,15 +171,118 @@ public class CommandRecipeId extends CommandBase {
|
||||
sendChatInfoMessage(sender, "nei.chat.recipeid.dump.finish");
|
||||
}
|
||||
|
||||
/**
|
||||
* + technically more reliable and supports some weird handlers
|
||||
* <p>
|
||||
* - very very very slow, took 1 hour to get a dump in GTNH on M1 in background
|
||||
* <p>
|
||||
* - generates a lot of duplicates, up to 75% of file size is duplicates (and it's 300mb out of 400mb...)
|
||||
*/
|
||||
private void processDump(BufferedWriter writer) throws IOException {
|
||||
final int total = ItemList.items.size();
|
||||
int count = 0;
|
||||
|
||||
for (ItemStack stack : ItemList.items) {
|
||||
if (count % 1000 == 0) {
|
||||
NEIClientConfig.logger
|
||||
.info("({}/{}). Processing {} crafting recipes...", count, total, stack.getDisplayName());
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
for (ICraftingHandler handler : getCraftingHandlers(stack)) {
|
||||
writeLines(writer, collectRecipeLines(handler, stack.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* - may skip some handlers if they're not TemplateRecipeHandler / just weird ones (like gendustry handlers)
|
||||
* <p>
|
||||
* + but in terms of GT recipes everything is dumped, and surprisingly it catches even more GT recipes than the
|
||||
* regular dumper (in particular, it has a lot of new hammer, extruder, blast furnace, etc. recipes)
|
||||
* <p>
|
||||
* + way faster, took like 2.5 minutes
|
||||
* <p>
|
||||
* + doesn't have nearly as many duplicates, but something can still slip in, for example from
|
||||
* FuelRecipeHandler. The dump has a size of only 100 MB instead of 400 MB from the regular dumper
|
||||
*/
|
||||
private void processFastDump(BufferedWriter writer) throws IOException {
|
||||
final ArrayList<ICraftingHandler> handlers = getCraftingHandlers();
|
||||
final int total = handlers.size();
|
||||
final AtomicInteger count = new AtomicInteger();
|
||||
|
||||
try {
|
||||
final List<List<String>> linesByHandler = ItemList.forkJoinPool.submit(() -> {
|
||||
return handlers.parallelStream().map(handler -> {
|
||||
final String handlerName = GuiRecipeTab.getHandlerInfo(handler).getHandlerName();
|
||||
final List<String> lines = collectRecipeLines(handler, handlerName);
|
||||
final int current = count.incrementAndGet();
|
||||
NEIClientConfig.logger
|
||||
.info("({}/{}). Processed {} handler recipes.", current, total, handlerName);
|
||||
return lines;
|
||||
}).collect(Collectors.toList());
|
||||
}).get();
|
||||
|
||||
for (List<String> lines : linesByHandler) {
|
||||
writeLines(writer, lines);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new IOException("Interrupted while dumping RecipeId", e);
|
||||
} catch (ExecutionException e) {
|
||||
throw new IOException("Error while dumping RecipeId", e);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> collectRecipeLines(ICraftingHandler handler, String context) {
|
||||
final List<String> lines = new ArrayList<>(handler.numRecipes());
|
||||
|
||||
for (int index = 0, num = handler.numRecipes(); index < num; index++) {
|
||||
try {
|
||||
final Recipe recipe = Recipe.of(handler, index);
|
||||
if (!recipe.getIngredients().isEmpty() && !recipe.getResults().isEmpty()) {
|
||||
lines.add(NBTJson.toJson(recipe.getRecipeId().toJsonObject()));
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
NEIClientConfig.logger.error(
|
||||
"Found Broken RecipeId {}:{}",
|
||||
GuiRecipeTab.getHandlerInfo(handler).getHandlerName(),
|
||||
context,
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
return lines;
|
||||
}
|
||||
|
||||
private void writeLines(BufferedWriter writer, List<String> lines) throws IOException {
|
||||
for (String line : lines) {
|
||||
writer.write(line);
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<ICraftingHandler> getCraftingHandlers(Object... results) {
|
||||
return new RecipeHandlerQuery<>(
|
||||
h -> h.getRecipeHandler("item", results),
|
||||
handler -> handler.getRecipeHandler("item", results),
|
||||
this.craftinghandlers,
|
||||
this.serialCraftingHandlers,
|
||||
"Error while looking up crafting recipe",
|
||||
"outputId: item",
|
||||
"results: " + Arrays.toString(results))
|
||||
.runWithProfiling(NEIClientUtils.translate("recipe.concurrent.crafting"));
|
||||
"outputId: item").runWithProfiling(NEIClientUtils.translate("recipe.concurrent.crafting"));
|
||||
}
|
||||
|
||||
private ArrayList<ICraftingHandler> getCraftingHandlers() {
|
||||
return new RecipeHandlerQuery<>(handler -> {
|
||||
if (handler instanceof TemplateRecipeHandler templateHandler) {
|
||||
return templateHandler.getAllRecipeHandler();
|
||||
}
|
||||
return handler.getRecipeHandler("all");
|
||||
},
|
||||
this.craftinghandlers,
|
||||
this.serialCraftingHandlers,
|
||||
"Error while looking up crafting recipe",
|
||||
"outputId: all").runWithProfiling(NEIClientUtils.translate("recipe.concurrent.crafting"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -212,7 +294,7 @@ public class CommandRecipeId extends CommandBase {
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "/recipeid dump <filename> OR /recipeid diff <prev-filename> <curr-filename> [subset name]";
|
||||
return "/recipeid [dump|fast-dump] <filename> OR /recipeid diff <prev-filename> <curr-filename> <subset name>";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -220,12 +302,27 @@ public class CommandRecipeId extends CommandBase {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> addTabCompletionOptions(ICommandSender sender, String[] args) {
|
||||
if (args.length == 1) {
|
||||
return getListOfStringsMatchingLastWord(args, "dump", "fast-dump", "diff");
|
||||
}
|
||||
|
||||
if ("diff".equals(args[0]) && (args.length == 2 || args.length == 3)) {
|
||||
return getListOfStringsMatchingLastWord(args, getRecipeIdFilenames());
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand(ICommandSender sender, String[] args) {
|
||||
final String command = args.length == 0 ? null : args[0];
|
||||
|
||||
if ("dump".equals(command)) {
|
||||
processDumpCommand(sender, args);
|
||||
processDumpCommand(sender, args, false);
|
||||
} else if ("fast-dump".equals(command)) {
|
||||
processDumpCommand(sender, args, true);
|
||||
} else if ("diff".equals(command)) {
|
||||
processDiffCommand(sender, args);
|
||||
} else {
|
||||
@@ -263,7 +360,7 @@ public class CommandRecipeId extends CommandBase {
|
||||
(new ProcessDiffThread(sender, prevFilename, currFilename, diffFilename)).start();
|
||||
}
|
||||
|
||||
protected void processDumpCommand(ICommandSender sender, String[] args) {
|
||||
protected void processDumpCommand(ICommandSender sender, String[] args, boolean fastDump) {
|
||||
|
||||
if (args.length > 2) {
|
||||
sendChatErrorMessage(sender, "nei.chat.recipeid.many_params", getCommandUsage(sender));
|
||||
@@ -274,13 +371,30 @@ public class CommandRecipeId extends CommandBase {
|
||||
final String currFilename = args.length == 2 ? args[1] : "recipeId";
|
||||
if (!dir.exists()) dir.mkdirs();
|
||||
|
||||
(new ProcessDumpThread(sender, getFile(currFilename))).start();
|
||||
(new ProcessDumpThread(sender, getFile(currFilename), fastDump)).start();
|
||||
}
|
||||
|
||||
private static File getFile(String filename) {
|
||||
return new File(CommonUtils.getMinecraftDir(), "recipeid/" + filename + ".json");
|
||||
}
|
||||
|
||||
private static String[] getRecipeIdFilenames() {
|
||||
final File dir = new File(CommonUtils.getMinecraftDir(), "recipeid");
|
||||
final File[] files = dir.listFiles((currentDir, name) -> name.endsWith(".json"));
|
||||
|
||||
if (files == null || files.length == 0) {
|
||||
return new String[] {};
|
||||
}
|
||||
|
||||
final String[] names = new String[files.length];
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
final String name = files[i].getName();
|
||||
names[i] = name.substring(0, name.length() - ".json".length());
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
private static void sendChatInfoMessage(ICommandSender sender, String translationKey, Object... args) {
|
||||
sender.addChatMessage(
|
||||
new ChatComponentTranslation(translationKey, args)
|
||||
|
||||
@@ -103,6 +103,7 @@ public class IMCHandler {
|
||||
info.setUseCustomScroll(tag.hasKey("useCustomScroll") && tag.getBoolean("useCustomScroll"));
|
||||
info.setShowFavoritesButton(!tag.hasKey("showFavoritesButton") || tag.getBoolean("showFavoritesButton"));
|
||||
info.setShowOverlayButton(!tag.hasKey("showOverlayButton") || tag.getBoolean("showOverlayButton"));
|
||||
info.setShowBadge(tag.hasKey("showBadge") && tag.getBoolean("showBadge"));
|
||||
|
||||
GuiRecipeTab.handlerAdderFromIMC.remove(handler);
|
||||
GuiRecipeTab.handlerAdderFromIMC.put(handler, info);
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.Item;
|
||||
@@ -23,7 +24,11 @@ import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
public class ItemPanelDumper extends DataDumper {
|
||||
|
||||
private static final int[] resolutions = new int[] { 16, 32, 48, 64, 128, 256 };
|
||||
public static final int CSV = 0;
|
||||
public static final int NBT = 1;
|
||||
public static final int JSON = 2;
|
||||
public static final int PNG = 3;
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
public ItemPanelDumper(String name) {
|
||||
super(name);
|
||||
@@ -54,19 +59,29 @@ public class ItemPanelDumper extends DataDumper {
|
||||
|
||||
public int getRes() {
|
||||
int i = renderTag(name + ".res").getIntValue(0);
|
||||
if (i >= resolutions.length || i < 0) renderTag().setIntValue(i = 0);
|
||||
return resolutions[i];
|
||||
int size = 16 << i;
|
||||
if (size >= getSmallerScreenAxisSize() || i < 0) {
|
||||
getTag(name + ".res").setIntValue(0);
|
||||
size = 16;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
private int getSmallerScreenAxisSize() {
|
||||
int width = mc.displayWidth;
|
||||
int height = mc.displayHeight;
|
||||
return Math.min(width, height);
|
||||
}
|
||||
|
||||
public Rectangle4i resButtonSize() {
|
||||
int width = 50;
|
||||
int width = 60;
|
||||
return new Rectangle4i(modeButtonSize().x - width - 6, 0, width, 20);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey, float frame) {
|
||||
super.draw(mousex, mousey, frame);
|
||||
if (getMode() == 3) {
|
||||
if (getMode() == PNG) {
|
||||
int res = getRes();
|
||||
drawButton(mousex, mousey, resButtonSize(), res + "x" + res);
|
||||
}
|
||||
@@ -74,23 +89,35 @@ public class ItemPanelDumper extends DataDumper {
|
||||
|
||||
@Override
|
||||
public void mouseClicked(int mousex, int mousey, int button) {
|
||||
if (getMode() == 3 && resButtonSize().contains(mousex, mousey)) {
|
||||
if (getMode() != PNG) {
|
||||
super.mouseClicked(mousex, mousey, button);
|
||||
return;
|
||||
}
|
||||
if (resButtonSize().contains(mousex, mousey)) {
|
||||
NEIClientUtils.playClickSound();
|
||||
getTag(name + ".res").setIntValue((renderTag(name + ".res").getIntValue(0) + 1) % resolutions.length);
|
||||
} else super.mouseClicked(mousex, mousey, button);
|
||||
int current = renderTag(name + ".res").getIntValue(0);
|
||||
int next;
|
||||
// 31 - numberOfLeadingZeros(x) = floor(log2(x))
|
||||
int max = 31 - Integer.numberOfLeadingZeros(getSmallerScreenAxisSize()) - 3;
|
||||
if (button == 1) { // Right click to cycle backward
|
||||
next = (current - 1 + max) % max;
|
||||
} else { // Left click to cycle forward
|
||||
next = (current + 1) % max;
|
||||
}
|
||||
getTag(name + ".res").setIntValue(next);
|
||||
} else if (!dumpButtonSize().contains(mousex, mousey) || acknowledgedItemSizeWarning()) {
|
||||
super.mouseClicked(mousex, mousey, button);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileExtension() {
|
||||
switch (getMode()) {
|
||||
case 0:
|
||||
return ".csv";
|
||||
case 1:
|
||||
return ".nbt";
|
||||
case 2:
|
||||
return ".json";
|
||||
}
|
||||
return null;
|
||||
return switch (getMode()) {
|
||||
case CSV -> ".csv";
|
||||
case NBT -> ".nbt";
|
||||
case JSON -> ".json";
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,15 +132,29 @@ public class ItemPanelDumper extends DataDumper {
|
||||
|
||||
@Override
|
||||
public void dumpFile() {
|
||||
if (getMode() == 3) Minecraft.getMinecraft().displayGuiScreen(new GuiItemIconDumper(this, getRes()));
|
||||
if (getMode() == PNG && acknowledgedItemSizeWarning())
|
||||
mc.displayGuiScreen(new GuiItemIconDumper(this, getRes()));
|
||||
else super.dumpFile();
|
||||
}
|
||||
|
||||
private boolean acknowledgedItemSizeWarning() {
|
||||
return !showItemSizeWarning() || NEIClientUtils.shiftKey();
|
||||
}
|
||||
|
||||
private boolean showItemSizeWarning() {
|
||||
int res = getRes();
|
||||
// More than 4 items at 2048x2048, 16 items at 1024x1024, 64 at 512x512, etc.
|
||||
int WARNING_SIZE = 16_777_216;
|
||||
return ItemPanels.itemPanel.getItems().size() * res * res > WARNING_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpTo(File file) throws IOException {
|
||||
if (getMode() == 0) super.dumpTo(file);
|
||||
else if (getMode() == 1) dumpNBT(file);
|
||||
else dumpJson(file);
|
||||
switch (getMode()) {
|
||||
case CSV -> super.dumpTo(file);
|
||||
case NBT -> dumpNBT(file);
|
||||
default -> dumpJson(file);
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpNBT(File file) throws IOException {
|
||||
@@ -141,4 +182,22 @@ public class ItemPanelDumper extends DataDumper {
|
||||
public int modeCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(int mousex, int mousey, List<String> currenttip) {
|
||||
if (getMode() == PNG && dumpButtonSize().contains(mousex, mousey) && showItemSizeWarning()) {
|
||||
int res = getRes();
|
||||
currenttip.add(
|
||||
NEIClientUtils.translate(
|
||||
"options.tools.dump.itempanel.icon.warning.1",
|
||||
ItemPanels.itemPanel.getItems().size(),
|
||||
res,
|
||||
res));
|
||||
currenttip.add(
|
||||
NEIClientUtils.translate(
|
||||
"options.tools.dump.itempanel.icon.warning.2",
|
||||
NEIClientUtils.translate("key.shift")));
|
||||
}
|
||||
return currenttip;
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,7 @@ public class AutoCraftingManager {
|
||||
|
||||
for (BookmarkItem item : math.initialItems) {
|
||||
final long invStackSize = inventory.getOrDefault(item.itemStack, 0L);
|
||||
final long amount = Math.max(0, item.amount - invStackSize * item.fluidCellAmount);
|
||||
final long amount = Math.max(0, item.getAmount() - invStackSize * item.fluidCellAmount);
|
||||
if (amount > 0) {
|
||||
initialItems.add(item.copyWithAmount(amount));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIClientUtils.Alignment;
|
||||
|
||||
public class Badge {
|
||||
|
||||
protected final String text;
|
||||
protected final List<String> tooltip;
|
||||
protected int badgeTextColor = 0xFDD835;
|
||||
protected boolean shadow = false;
|
||||
protected Alignment alignment = Alignment.TopLeft;
|
||||
|
||||
public Badge(String text, String... tooltip) {
|
||||
this.text = text;
|
||||
this.tooltip = Arrays.stream(tooltip).map(t -> EnumChatFormatting.GRAY + t).collect(Collectors.toList());
|
||||
this.badgeTextColor = getHexValue(
|
||||
NEIClientUtils.getTextColorOrDefault("recipe.badge.color", "0xFDD835"),
|
||||
0xFDD835);
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return this.text;
|
||||
}
|
||||
|
||||
public List<String> getTooltip() {
|
||||
return this.tooltip;
|
||||
}
|
||||
|
||||
public Badge setColor(int color) {
|
||||
this.badgeTextColor = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return this.badgeTextColor;
|
||||
}
|
||||
|
||||
public Badge setShadow(boolean shadow) {
|
||||
this.shadow = shadow;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean hasShadow() {
|
||||
return this.shadow;
|
||||
}
|
||||
|
||||
public Badge setAlignment(Alignment alignment) {
|
||||
this.alignment = alignment;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Alignment getAlignment() {
|
||||
return this.alignment;
|
||||
}
|
||||
|
||||
private static int getHexValue(String color, int defaultValue) {
|
||||
try {
|
||||
return (int) Long.parseLong(color.replace("0x", ""), 16);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public void draw(Rectangle4i rect) {
|
||||
NEIClientUtils.drawNEIOverlayText(getText(), rect, 0.5f, getColor(), hasShadow(), getAlignment());
|
||||
}
|
||||
|
||||
public static Badge notConsumed() {
|
||||
return new Badge(
|
||||
NEIClientUtils.translate("recipe.badge.nc"),
|
||||
NEIClientUtils.translate("recipe.badge.nc.tooltip"));
|
||||
}
|
||||
|
||||
public static Badge notConsumedParallel() {
|
||||
return new Badge(
|
||||
NEIClientUtils.translate("recipe.badge.ncp"),
|
||||
NEIClientUtils.translate("recipe.badge.ncp.tooltip"));
|
||||
}
|
||||
|
||||
public static Badge consumeChance(float chance) {
|
||||
final String chanceText = NEIClientUtils.formatChance(chance);
|
||||
return new Badge(chanceText, NEIClientUtils.translate("recipe.badge.chance.consume", chanceText));
|
||||
}
|
||||
|
||||
public static Badge outputChance(float chance) {
|
||||
final String chanceText = NEIClientUtils.formatChance(chance);
|
||||
return new Badge(chanceText, NEIClientUtils.translate("recipe.badge.chance.output", chanceText));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,7 +21,6 @@ import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
|
||||
import codechicken.nei.bookmark.BookmarksGridSlot;
|
||||
import codechicken.nei.recipe.Recipe.RecipeId;
|
||||
import codechicken.nei.recipe.TemplateRecipeHandler.RecipeTransferRect;
|
||||
|
||||
public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
|
||||
@@ -103,18 +102,7 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
|
||||
private static ICraftingHandler buildAllRecipesHandler(ICraftingHandler handler) {
|
||||
if (handler instanceof TemplateRecipeHandler templateHandler) {
|
||||
TemplateRecipeHandler allHandler = templateHandler.newInstance();
|
||||
if (allHandler.transferRects.isEmpty()) {
|
||||
allHandler.loadCraftingRecipes("all");
|
||||
return allHandler;
|
||||
}
|
||||
for (RecipeTransferRect rect : allHandler.transferRects) {
|
||||
if (allHandler.specifyTransferRect() == null
|
||||
|| allHandler.specifyTransferRect().equals(rect.outputId)) {
|
||||
allHandler.loadCraftingRecipes(rect.outputId, rect.results);
|
||||
return allHandler;
|
||||
}
|
||||
}
|
||||
return templateHandler.getAllRecipeHandler();
|
||||
}
|
||||
return handler.getRecipeHandler("all");
|
||||
}
|
||||
|
||||
@@ -784,9 +784,10 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
public void forceRefreshPage() {
|
||||
this.currenthandlers.sort(NEIClientConfig.HANDLER_COMPARATOR);
|
||||
|
||||
final int currentPage = this.handlerPages.getCurrentPageIndex();
|
||||
this.currenthandlers.sort(NEIClientConfig.HANDLER_COMPARATOR);
|
||||
this.recipetype = this.currenthandlers.indexOf(this.handler.original);
|
||||
|
||||
setRecipePage(this.recipetype);
|
||||
this.handlerPages.changePage(currentPage);
|
||||
|
||||
@@ -898,12 +899,15 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
}
|
||||
|
||||
private String getHandlerTitleColorCode(boolean hovered) {
|
||||
final String key = hovered ? "recipe.title.color.hover" : "recipe.title.color.normal";
|
||||
final String translated = NEIClientUtils.translate(key);
|
||||
if (!translated.startsWith("nei.")) { // Optional localization string for resource packs
|
||||
return translated;
|
||||
|
||||
if (hovered) {
|
||||
return NEIClientUtils
|
||||
.getTextColorOrDefault("recipe.title.color.hover", EnumChatFormatting.YELLOW.toString());
|
||||
} else {
|
||||
return NEIClientUtils
|
||||
.getTextColorOrDefault("recipe.title.color.normal", EnumChatFormatting.WHITE.toString());
|
||||
}
|
||||
return hovered ? EnumChatFormatting.YELLOW.toString() : EnumChatFormatting.WHITE.toString();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,12 +23,12 @@ import net.minecraftforge.common.MinecraftForge;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.commons.csv.CSVParser;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.Widget;
|
||||
import codechicken.nei.drawable.DrawableResource;
|
||||
import codechicken.nei.event.NEIRegisterHandlerInfosEvent;
|
||||
@@ -139,18 +139,16 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
|
||||
public void addTooltips(List<String> tooltip) {
|
||||
tooltip.add(handler.getRecipeTabName().trim());
|
||||
|
||||
String handlerMod = getHandlerMod(handlerName, handlerID);
|
||||
tooltip.add(EnumChatFormatting.BLUE + handlerMod);
|
||||
|
||||
boolean shiftHeld = Keyboard.getEventKeyState()
|
||||
&& (Keyboard.getEventKey() == Keyboard.KEY_LSHIFT || Keyboard.getEventKey() == Keyboard.KEY_RSHIFT);
|
||||
if (handlerMod.equals("Unknown") || shiftHeld) {
|
||||
if (handlerMod.equals("Unknown") || NEIClientUtils.shiftKey()) {
|
||||
tooltip.add("");
|
||||
tooltip.add("HandlerName: " + handlerName);
|
||||
tooltip.add("HandlerID: " + handlerID);
|
||||
tooltip.add("HandlerOrder: " + NEIClientConfig.getHandlerOrder(handler));
|
||||
tooltip.add(EnumChatFormatting.GRAY + "HandlerName: " + handlerName);
|
||||
tooltip.add(EnumChatFormatting.GRAY + "HandlerID: " + handlerID);
|
||||
tooltip.add(EnumChatFormatting.GRAY + "HandlerOrder: " + NEIClientConfig.getHandlerOrder(handler));
|
||||
}
|
||||
|
||||
tooltip.add(EnumChatFormatting.BLUE + handlerMod);
|
||||
}
|
||||
|
||||
public abstract boolean onButtonPress(boolean rightclick);
|
||||
|
||||
@@ -30,6 +30,7 @@ public class HandlerInfo {
|
||||
private boolean multipleWidgetsAllowed = false;
|
||||
private boolean showFavoritesButton = true;
|
||||
private boolean showOverlayButton = true;
|
||||
private boolean showBadge = false;
|
||||
private boolean useCustomScroll = false;
|
||||
|
||||
private ItemStack itemStack = null;
|
||||
@@ -142,6 +143,14 @@ public class HandlerInfo {
|
||||
this.showOverlayButton = showOverlayButton;
|
||||
}
|
||||
|
||||
public boolean getShowBadge() {
|
||||
return this.showBadge;
|
||||
}
|
||||
|
||||
public void setShowBadge(boolean showBadge) {
|
||||
this.showBadge = showBadge;
|
||||
}
|
||||
|
||||
public boolean getUseCustomScroll() {
|
||||
return this.useCustomScroll;
|
||||
}
|
||||
@@ -216,6 +225,11 @@ public class HandlerInfo {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setShowBadge(boolean showBadge) {
|
||||
this.info.showBadge = showBadge;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Builder setMaxRecipesPerPage(int maxRecipesPerPage) {
|
||||
this.info.multipleWidgetsAllowed = maxRecipesPerPage > 1;
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.FavoriteRecipes;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
@@ -40,6 +41,7 @@ public class NEIRecipeWidget extends Widget {
|
||||
protected AcceptsFollowingTooltipLineHandler acceptsFollowingTooltipLineHandler;
|
||||
protected final Map<PositionedStack, Integer> favoriteIndexes = new WeakHashMap<>();
|
||||
protected final Map<PositionedStack, List<ItemStack>> permutations = new WeakHashMap<>();
|
||||
protected final Map<PositionedStack, List<Badge>> badgeCache = new WeakHashMap<>();
|
||||
protected int favoriteRevision = -1;
|
||||
protected boolean update = true;
|
||||
protected int cycleticks = 0;
|
||||
@@ -196,11 +198,7 @@ public class NEIRecipeWidget extends Widget {
|
||||
updatePermutationsFor(pStack);
|
||||
}
|
||||
|
||||
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
|
||||
|
||||
if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) {
|
||||
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(pStack.relx, pStack.rely, 16, 16, 0x80FFFFFF));
|
||||
}
|
||||
drawItem(pStack, mouseX, mouseY, yShift, true);
|
||||
}
|
||||
|
||||
for (PositionedStack pStack : getCatalysts()) {
|
||||
@@ -209,19 +207,11 @@ public class NEIRecipeWidget extends Widget {
|
||||
updatePermutationsFor(pStack);
|
||||
}
|
||||
|
||||
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
|
||||
|
||||
if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) {
|
||||
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(pStack.relx, pStack.rely, 16, 16, 0x80FFFFFF));
|
||||
}
|
||||
drawItem(pStack, mouseX, mouseY, yShift, true);
|
||||
}
|
||||
|
||||
for (PositionedStack pStack : getOutputs()) {
|
||||
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
|
||||
|
||||
if (pStack.contains(mouseX - this.x, mouseY - this.y - yShift)) {
|
||||
NEIClientUtils.gl2DRenderContext(() -> GuiDraw.drawRect(pStack.relx, pStack.rely, 16, 16, 0x80FFFFFF));
|
||||
}
|
||||
drawItem(pStack, mouseX, mouseY, yShift, false);
|
||||
}
|
||||
|
||||
GuiContainerManager.disableMatrixStackLogging();
|
||||
@@ -255,6 +245,55 @@ public class NEIRecipeWidget extends Widget {
|
||||
DebugHandlerWidget.instance.drawGuiPlaceholder(this);
|
||||
}
|
||||
|
||||
protected void drawItem(PositionedStack pStack, int mouseX, int mouseY, int yShift, boolean input) {
|
||||
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
protected List<Badge> getBadges(PositionedStack pStack, boolean input) {
|
||||
|
||||
return this.badgeCache.computeIfAbsent(pStack, k -> {
|
||||
final List<Badge> badges = k.getBadges();
|
||||
|
||||
if (badges == null) {
|
||||
|
||||
if (input) {
|
||||
if (StackInfo.getAmount(pStack.item) == 0) {
|
||||
return Collections.singletonList(Badge.notConsumed());
|
||||
} else if (pStack.getChance() == 0) {
|
||||
return Collections.singletonList(Badge.notConsumedParallel());
|
||||
} else if (pStack.getChance() != PositionedStack.CHANCE_FULL) {
|
||||
return Collections.singletonList(
|
||||
Badge.consumeChance(pStack.getChance() / (float) PositionedStack.CHANCE_FULL));
|
||||
}
|
||||
} else if (pStack.getChance() != PositionedStack.CHANCE_FULL) {
|
||||
return Collections.singletonList(
|
||||
Badge.outputChance(pStack.getChance() / (float) PositionedStack.CHANCE_FULL));
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return badges;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
protected void drawBadge(PositionedStack pStack, boolean input) {
|
||||
final List<Badge> badges = getBadges(pStack, input);
|
||||
|
||||
for (Badge badge : badges) {
|
||||
badge.draw(new Rectangle4i(pStack.relx, pStack.rely, 16, 16));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyPress(int keyID, char keyChar) {
|
||||
|
||||
@@ -366,27 +405,22 @@ public class NEIRecipeWidget extends Widget {
|
||||
|
||||
tooltip = this.handlerRef.handler.handleItemTooltip(guiRecipe, itemstack, tooltip, this.handlerRef.recipeIndex);
|
||||
|
||||
if (NEIClientConfig.showCycledIngredientsTooltip() && itemstack != null) {
|
||||
final int yShift = this.handlerInfo.getYShift();
|
||||
PositionedStack hovered = null;
|
||||
if (itemstack != null) {
|
||||
final PositionedStack hovered = getPositionedStackMouseOver(mousex, mousey);
|
||||
|
||||
for (PositionedStack pStack : getInputs()) {
|
||||
if (pStack.contains(mousex - this.x, mousey - this.y - yShift)) {
|
||||
hovered = pStack;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hovered != null && this.handlerInfo.getShowBadge()) {
|
||||
final List<Badge> badges = getBadges(hovered, getOutputs().indexOf(hovered) == -1);
|
||||
|
||||
if (hovered == null) {
|
||||
for (PositionedStack pStack : getCatalysts()) {
|
||||
if (pStack.contains(mousex - this.x, mousey - this.y - yShift)) {
|
||||
hovered = pStack;
|
||||
break;
|
||||
for (Badge badge : badges) {
|
||||
if (badge.getTooltip() != null && !badge.getTooltip().isEmpty()) {
|
||||
tooltip.addAll(badge.getTooltip());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hovered == null || this.permutations.getOrDefault(hovered, Collections.emptyList()).size() <= 1) {
|
||||
if (hovered == null || !NEIClientConfig.showCycledIngredientsTooltip()
|
||||
|| this.permutations.getOrDefault(hovered, Collections.emptyList()).size() <= 1
|
||||
|| getOutputs().indexOf(hovered) != -1) {
|
||||
this.acceptsFollowingTooltipLineHandler = null;
|
||||
} else if (this.acceptsFollowingTooltipLineHandler == null
|
||||
|| this.acceptsFollowingTooltipLineHandler.tooltipGUID != hovered) {
|
||||
@@ -568,6 +602,7 @@ public class NEIRecipeWidget extends Widget {
|
||||
this.acceptsFollowingTooltipLineHandler = null;
|
||||
this.favoriteIndexes.clear();
|
||||
this.permutations.clear();
|
||||
this.badgeCache.clear();
|
||||
}
|
||||
|
||||
for (PositionedStack pStack : getInputs()) {
|
||||
|
||||
@@ -1,16 +1,24 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawString;
|
||||
import static codechicken.lib.gui.GuiDraw.getStringWidth;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Container;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import codechicken.core.TaskProfiler.ProfilerResult;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
@@ -20,12 +28,104 @@ import codechicken.nei.util.AsyncTaskProfiler;
|
||||
|
||||
public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
|
||||
private static final AsyncTaskProfiler profiler = new AsyncTaskProfiler();
|
||||
public static class RecipeProfiler {
|
||||
|
||||
private final AsyncTaskProfiler profiler = new AsyncTaskProfiler();
|
||||
private final Map<String, IRecipeHandler> handlerMap = new ConcurrentHashMap<>();
|
||||
private final AtomicInteger idCounter = new AtomicInteger(0);
|
||||
private boolean isProfiling = false;
|
||||
|
||||
public <T extends IRecipeHandler> ArrayList<T> start(String profilerSection, Supplier<ArrayList<T>> callback) {
|
||||
profilerInfos.clear();
|
||||
this.handlerMap.clear();
|
||||
this.idCounter.set(0);
|
||||
|
||||
if (NEIClientConfig.isProfileRecipeEnabled()) {
|
||||
this.profiler.clear();
|
||||
this.profiler.start(EnumChatFormatting.getTextWithoutFormattingCodes(profilerSection));
|
||||
this.isProfiling = true;
|
||||
|
||||
try {
|
||||
return callback.get();
|
||||
} finally {
|
||||
this.profiler.end();
|
||||
this.isProfiling = false;
|
||||
|
||||
final List<ProfilerResult> results = this.profiler.getResults();
|
||||
|
||||
results.sort(
|
||||
Comparator.comparingLong((ProfilerResult profilerResult) -> profilerResult.time)
|
||||
.reversed());
|
||||
|
||||
for (ProfilerResult profilerResult : results) {
|
||||
profilerInfos.add(new ProfilerInfo(handlerMap.get(profilerResult.name), profilerResult));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
return callback.get();
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends IRecipeHandler> T profile(T handler, Supplier<T> callback) {
|
||||
if (this.isProfiling && !(handler instanceof ProfilerRecipeHandler)) {
|
||||
final String id = String.valueOf(idCounter.incrementAndGet());
|
||||
this.handlerMap.put(id, handler);
|
||||
this.profiler.clearCurrent();
|
||||
this.profiler.start(id);
|
||||
|
||||
try {
|
||||
T result = callback.get();
|
||||
|
||||
if (result != null) {
|
||||
this.handlerMap.put(id, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
} finally {
|
||||
this.profiler.end();
|
||||
}
|
||||
} else {
|
||||
return callback.get();
|
||||
}
|
||||
}
|
||||
|
||||
public static AsyncTaskProfiler getProfiler() {
|
||||
return profiler;
|
||||
}
|
||||
|
||||
protected static class ProfilerInfo {
|
||||
|
||||
public final String modName;
|
||||
public final IRecipeHandler handler;
|
||||
public final List<String> tooltip = new ArrayList<>();
|
||||
public final String title;
|
||||
public final String time;
|
||||
|
||||
public ProfilerInfo(IRecipeHandler handler, ProfilerResult result) {
|
||||
this.handler = handler;
|
||||
this.time = (result.time < 1_000_000 ? (result.time / 1_000) + "us" : (result.time / 1_000_000) + "ms");
|
||||
|
||||
if (handler == null) {
|
||||
this.title = result.name;
|
||||
this.modName = "Unknown";
|
||||
} else {
|
||||
final HandlerInfo handlerInfo = GuiRecipeTab.getHandlerInfo(handler);
|
||||
final String handlerName = handlerInfo != null ? handlerInfo.getHandlerName() : "Unknown";
|
||||
|
||||
this.title = EnumChatFormatting.getTextWithoutFormattingCodes(handler.getRecipeName());
|
||||
this.modName = handlerInfo != null ? handlerInfo.getModName() : "Unknown";
|
||||
|
||||
this.tooltip.add(EnumChatFormatting.GRAY + "HandlerName: " + handlerName);
|
||||
this.tooltip.add(EnumChatFormatting.GRAY + "HandlerID: " + handler.getOverlayIdentifier());
|
||||
this.tooltip.add(EnumChatFormatting.GRAY + "HandlerOrder: " + NEIClientConfig.getHandlerOrder(handler));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final RecipeProfiler recipeProfiler = new RecipeProfiler();
|
||||
protected static final List<ProfilerInfo> profilerInfos = new ArrayList<>();
|
||||
private static final int WIDTH = 166;
|
||||
private final boolean crafting;
|
||||
|
||||
public ProfilerRecipeHandler(boolean crafting) {
|
||||
@@ -39,11 +139,7 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
|
||||
@Override
|
||||
public int numRecipes() {
|
||||
if (!NEIClientConfig.isProfileRecipeEnabled()) return 0;
|
||||
|
||||
return (int) Math.ceil(
|
||||
((crafting ? GuiCraftingRecipe.craftinghandlers.size() : GuiUsageRecipe.usagehandlers.size()) - 1)
|
||||
/ 6D);
|
||||
return NEIClientConfig.isProfileRecipeEnabled() ? Math.max(1, profilerInfos.size()) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,21 +147,32 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
|
||||
@Override
|
||||
public void drawForeground(int recipe) {
|
||||
List<ProfilerResult> results = profiler.getResults();
|
||||
results.removeIf(profilerResult -> getRecipeName().equals(profilerResult.name));
|
||||
if (recipe >= profilerInfos.size()) return;
|
||||
|
||||
results.sort((o1, o2) -> o1.time < o2.time ? 1 : -1);
|
||||
final ProfilerInfo info = profilerInfos.get(recipe);
|
||||
final int valueWidth = getStringWidth(info.time);
|
||||
final IRecipeHandler handler = info.handler;
|
||||
final boolean hovered = handler != null && handler.numRecipes() > 0
|
||||
&& isHandlerTitleHovered(recipe, GuiDraw.getMousePosition());
|
||||
|
||||
for (int i = recipe * 6; i < results.size() && i < (recipe + 1) * 6; i++) {
|
||||
ProfilerResult r = results.get(i);
|
||||
int y = (i % 6) * 20 + 6;
|
||||
drawString(r.name, 8, y, 0xFF808080, false);
|
||||
GuiDraw.drawString(
|
||||
NEIClientUtils.cropText(GuiDraw.fontRenderer, info.title, WIDTH - valueWidth - 2),
|
||||
0,
|
||||
3,
|
||||
hovered ? 0xFFFFDD00 : 0xFF808080,
|
||||
false);
|
||||
GuiDraw.drawString(info.time, WIDTH - valueWidth, 3, 0xFF404040, false);
|
||||
}
|
||||
|
||||
String s;
|
||||
if (r.time < 1000000L) s = (r.time / 1000) + "us";
|
||||
else s = (r.time / 1000000) + "ms";
|
||||
private boolean isHandlerTitleHovered(int recipe, Point mouse) {
|
||||
final GuiContainer guiContainer = NEIClientUtils.getGuiContainer();
|
||||
|
||||
drawString(s, 156 - getStringWidth(s), y + 10, 0xFF404040, false);
|
||||
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);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +211,22 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(GuiRecipe<?> gui, List<String> currenttip, int recipe) {
|
||||
if (recipe >= profilerInfos.size()) return currenttip;
|
||||
|
||||
final ProfilerInfo r = profilerInfos.get(recipe);
|
||||
|
||||
currenttip.add(r.title + ": " + r.time);
|
||||
|
||||
if (r.handler != null) {
|
||||
currenttip.add(EnumChatFormatting.GRAY + "Recipes: " + r.handler.numRecipes() + GuiDraw.TOOLTIP_LINESPACE);
|
||||
|
||||
if (NEIClientUtils.shiftKey()) {
|
||||
currenttip.addAll(r.tooltip);
|
||||
}
|
||||
|
||||
currenttip.add(EnumChatFormatting.BLUE + r.modName);
|
||||
}
|
||||
|
||||
return currenttip;
|
||||
}
|
||||
|
||||
@@ -119,6 +242,23 @@ public class ProfilerRecipeHandler implements ICraftingHandler, IUsageHandler {
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked(GuiRecipe<?> gui, int button, int recipe) {
|
||||
if (recipe >= profilerInfos.size()) return false;
|
||||
|
||||
final ProfilerInfo r = profilerInfos.get(recipe);
|
||||
|
||||
if (r.handler != null) {
|
||||
final GuiContainer guiContainer = NEIClientUtils.getGuiContainer();
|
||||
|
||||
if (guiContainer instanceof GuiRecipe guiRecipe) {
|
||||
int index = guiRecipe.currenthandlers.indexOf(r.handler);
|
||||
|
||||
if (index != -1) {
|
||||
guiRecipe.setRecipePage(index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -282,17 +282,20 @@ public class Recipe {
|
||||
|
||||
protected final ItemStack[] items;
|
||||
protected int activeIndex = 0;
|
||||
|
||||
protected int amount = 0;
|
||||
protected int chance = PositionedStack.CHANCE_FULL;
|
||||
|
||||
protected int relx;
|
||||
protected int rely;
|
||||
|
||||
public RecipeIngredient(int relx, int rely, List<ItemStack> items, int activeIndex) {
|
||||
public RecipeIngredient(int relx, int rely, 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.chance = chance;
|
||||
}
|
||||
|
||||
public static RecipeIngredient of(PositionedStack positionedStack) {
|
||||
@@ -311,17 +314,21 @@ public class Recipe {
|
||||
}
|
||||
}
|
||||
|
||||
return of(positionedStack.relx, positionedStack.rely, stacks, activeIndex);
|
||||
return of(positionedStack.relx, positionedStack.rely, stacks, positionedStack.getChance(), activeIndex);
|
||||
}
|
||||
|
||||
public static RecipeIngredient of(int relx, int rely, List<ItemStack> stacks, int activeIndex) {
|
||||
return new RecipeIngredient(relx, rely, stacks, 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 int getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public int getChance() {
|
||||
return this.chance;
|
||||
}
|
||||
|
||||
public ItemStack getItemStack() {
|
||||
return this.items[this.activeIndex];
|
||||
}
|
||||
@@ -348,11 +355,16 @@ public class Recipe {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setChance(int chance) {
|
||||
this.chance = chance;
|
||||
}
|
||||
|
||||
public RecipeIngredient copy() {
|
||||
return new RecipeIngredient(
|
||||
this.relx,
|
||||
this.rely,
|
||||
getPermutations().stream().map(ItemStack::copy).collect(Collectors.toList()),
|
||||
this.chance,
|
||||
this.activeIndex);
|
||||
}
|
||||
}
|
||||
@@ -435,7 +447,7 @@ public class Recipe {
|
||||
}
|
||||
|
||||
if (item instanceof ItemStack stack) {
|
||||
return RecipeIngredient.of(0, 0, Arrays.asList(stack), 0);
|
||||
return RecipeIngredient.of(0, 0, Arrays.asList(stack), PositionedStack.CHANCE_FULL, 0);
|
||||
}
|
||||
|
||||
if (item instanceof RecipeIngredient ingr) {
|
||||
|
||||
@@ -12,10 +12,8 @@ import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
|
||||
import codechicken.core.TaskProfiler;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.util.AsyncTaskProfiler;
|
||||
|
||||
public class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
|
||||
@@ -34,30 +32,22 @@ public class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
}
|
||||
|
||||
public ArrayList<T> runWithProfiling(String profilerSection) {
|
||||
TaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
|
||||
return ProfilerRecipeHandler.recipeProfiler.start(profilerSection, () -> {
|
||||
|
||||
// Save the current config state here, as it may be altered
|
||||
// if getRecipeHandlesParallel took so long and player accidentally changed config.
|
||||
boolean profileRecipes = NEIClientConfig.isProfileRecipeEnabled();
|
||||
if (profileRecipes) {
|
||||
profiler.clear();
|
||||
profiler.start(profilerSection);
|
||||
}
|
||||
try {
|
||||
ArrayList<T> handlers = getRecipeHandlersParallel();
|
||||
|
||||
try {
|
||||
ArrayList<T> handlers = getRecipeHandlersParallel();
|
||||
|
||||
if (error) {
|
||||
if (error) {
|
||||
displayRecipeLookupError();
|
||||
}
|
||||
return handlers;
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
printLog(e);
|
||||
displayRecipeLookupError();
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
return handlers;
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
printLog(e);
|
||||
displayRecipeLookupError();
|
||||
return new ArrayList<>(0);
|
||||
} finally {
|
||||
if (profileRecipes) profiler.end();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private ArrayList<T> getRecipeHandlersParallel() throws InterruptedException, ExecutionException {
|
||||
@@ -77,40 +67,42 @@ public class RecipeHandlerQuery<T extends IRecipeHandler> {
|
||||
|
||||
private ArrayList<T> getSerialHandlersWithRecipes() {
|
||||
|
||||
return serialRecipeHandlers.stream().map(handler -> {
|
||||
AsyncTaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
|
||||
profiler.clearCurrent();
|
||||
profiler.start(handler.getRecipeName());
|
||||
try {
|
||||
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
|
||||
} catch (Throwable t) {
|
||||
printLog(t);
|
||||
error = true;
|
||||
return null;
|
||||
} finally {
|
||||
profiler.end();
|
||||
}
|
||||
}).filter(h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
|
||||
return serialRecipeHandlers.stream()
|
||||
.map(handler -> ProfilerRecipeHandler.recipeProfiler.profile(handler, () -> {
|
||||
|
||||
try {
|
||||
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
|
||||
} catch (Throwable t) {
|
||||
printLog(t);
|
||||
error = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
}))
|
||||
.filter(
|
||||
h -> h != null && h.numRecipes() > 0
|
||||
&& SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
private ArrayList<T> getHandlersWithRecipes() throws InterruptedException, ExecutionException {
|
||||
|
||||
return ItemList.forkJoinPool.submit(() -> recipeHandlers.parallelStream().map(handler -> {
|
||||
AsyncTaskProfiler profiler = ProfilerRecipeHandler.getProfiler();
|
||||
profiler.clearCurrent();
|
||||
profiler.start(handler.getRecipeName());
|
||||
try {
|
||||
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
|
||||
} catch (Throwable t) {
|
||||
printLog(t);
|
||||
error = true;
|
||||
return null;
|
||||
} finally {
|
||||
profiler.end();
|
||||
}
|
||||
}).filter(h -> h != null && h.numRecipes() > 0 && SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
|
||||
.collect(Collectors.toCollection(ArrayList::new))).get();
|
||||
return ItemList.forkJoinPool.submit(
|
||||
() -> recipeHandlers.parallelStream()
|
||||
.map(handler -> ProfilerRecipeHandler.recipeProfiler.profile(handler, () -> {
|
||||
try {
|
||||
return isHidden(handler) ? null : recipeHandlerFunction.apply(handler);
|
||||
} catch (Throwable t) {
|
||||
printLog(t);
|
||||
error = true;
|
||||
return null;
|
||||
}
|
||||
}))
|
||||
.filter(
|
||||
h -> h != null && h.numRecipes() > 0
|
||||
&& SearchRecipeHandler.findFirst(h, (recipeIndex) -> true) != -1)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get();
|
||||
}
|
||||
|
||||
private boolean isHidden(T handler) {
|
||||
|
||||
@@ -120,10 +120,14 @@ public class RepairRecipeHandler extends TemplateRecipeHandler {
|
||||
final List<ItemStack> permutations = new ArrayList<>();
|
||||
|
||||
for (ItemStack itemstack2 : ItemList.items) {
|
||||
if (itemstack1.getItem().getIsRepairable(itemstack1, itemstack2)) {
|
||||
final ItemStack right = itemstack2.copy();
|
||||
right.stackSize = 4;
|
||||
permutations.add(right);
|
||||
try {
|
||||
if (itemstack1.getItem().getIsRepairable(itemstack1, itemstack2)) {
|
||||
final ItemStack right = itemstack2.copy();
|
||||
right.stackSize = 4;
|
||||
permutations.add(right);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Catch exceptions from mods that don't properly implement getIsRepairable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -535,6 +535,24 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
}
|
||||
}
|
||||
|
||||
public ICraftingHandler getAllRecipeHandler() {
|
||||
TemplateRecipeHandler handler = newInstance();
|
||||
if (handler.transferRects.isEmpty()) {
|
||||
handler.loadCraftingRecipes("all");
|
||||
return handler;
|
||||
}
|
||||
|
||||
final String transferRectId = handler.specifyTransferRect();
|
||||
for (RecipeTransferRect rect : handler.transferRects) {
|
||||
if (transferRectId == null || transferRectId.equals(rect.outputId)) {
|
||||
handler.loadCraftingRecipes(rect.outputId, rect.results);
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
return handler.getRecipeHandler("all");
|
||||
}
|
||||
|
||||
public ICraftingHandler getRecipeHandler(String outputId, Object... results) {
|
||||
TemplateRecipeHandler handler = newInstance();
|
||||
handler.loadCraftingRecipes(outputId, results);
|
||||
|
||||
@@ -49,9 +49,9 @@ public class RecipeChainIterator implements Iterator<Map<RecipeId, Long>> {
|
||||
final Set<RecipeId> skipRecipes = new HashSet<>();
|
||||
final Map<RecipeId, Long> rootRecipes = new HashMap<>();
|
||||
final HashMap<BookmarkItem, BookmarkItem> preferredItems = new HashMap<>(this.math.preferredItems);
|
||||
preferredItems.values()
|
||||
.removeIf(item -> item == null || item.amount == 0 || this.precessedRecipes.contains(item.recipeId));
|
||||
preferredItems.keySet().removeIf(item -> item.amount == 0);
|
||||
preferredItems.values().removeIf(
|
||||
item -> item == null || item.getAmount() == 0 || this.precessedRecipes.contains(item.recipeId));
|
||||
preferredItems.keySet().removeIf(item -> item.getAmount() == 0);
|
||||
|
||||
for (Map.Entry<BookmarkItem, BookmarkItem> entry : preferredItems.entrySet()) {
|
||||
final BookmarkItem keyItem = entry.getKey();
|
||||
|
||||
@@ -14,6 +14,7 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import codechicken.nei.ItemStackAmount;
|
||||
import codechicken.nei.ItemStackSet;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.bookmark.BookmarkItem;
|
||||
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
|
||||
@@ -48,6 +49,7 @@ public class RecipeChainMath {
|
||||
public final List<BookmarkItem> recipeResults = new ArrayList<>();
|
||||
|
||||
public final Map<BookmarkItem, BookmarkItem> preferredItems = new HashMap<>();
|
||||
|
||||
public final Map<BookmarkItem, Long> requiredAmount = new HashMap<>();
|
||||
public final List<ItemStack> containerItems = new ArrayList<>();
|
||||
private final List<ItemStack> containerItemsBlacklist = new ArrayList<>();
|
||||
@@ -59,9 +61,9 @@ public class RecipeChainMath {
|
||||
if (item.recipeId == null || item.type == BookmarkItemType.ITEM) {
|
||||
this.initialItems.add(item.copy());
|
||||
} else if (item.type == BookmarkItemType.INGREDIENT) {
|
||||
this.recipeIngredients.add(item.copyWithAmount(0));
|
||||
this.recipeIngredients.add(item.copyWithMultiplier(0));
|
||||
} else {
|
||||
this.recipeResults.add(item.copyWithAmount(0));
|
||||
this.recipeResults.add(item.copyWithMultiplier(0));
|
||||
multipliers.put(
|
||||
item.recipeId,
|
||||
Math.max(multipliers.getOrDefault(item.recipeId, 0L), item.getMultiplier()));
|
||||
@@ -129,17 +131,18 @@ public class RecipeChainMath {
|
||||
visited.add(recipeId);
|
||||
|
||||
for (BookmarkItem ingrItem : this.recipeIngredients) {
|
||||
if (ingrItem.factor > 0 && recipeId.equals(ingrItem.recipeId) && !preferredItems.containsKey(ingrItem)) {
|
||||
if (!ingrItem.emptyFactor() && recipeId.equals(ingrItem.recipeId)
|
||||
&& !preferredItems.containsKey(ingrItem)) {
|
||||
BookmarkItem activeItem = null;
|
||||
BookmarkItem prefItem = null;
|
||||
|
||||
for (BookmarkItem item : this.recipeResults) {
|
||||
if (item.factor > 0 && !visited.contains(item.recipeId) && item.containsItems(ingrItem)) {
|
||||
if (!item.emptyFactor() && !visited.contains(item.recipeId) && item.containsItems(ingrItem)) {
|
||||
|
||||
if ((activeItem == null || item.factor > activeItem.factor) && NEIClientUtils
|
||||
if ((activeItem == null || item.getAmount(1) > activeItem.getAmount(1)) && NEIClientUtils
|
||||
.areStacksSameTypeCraftingWithNBT(ingrItem.itemStack, item.itemStack)) {
|
||||
activeItem = item;
|
||||
} else if (prefItem == null || item.factor > prefItem.factor) {
|
||||
} else if (prefItem == null || item.getAmount(1) > prefItem.getAmount(1)) {
|
||||
prefItem = item;
|
||||
}
|
||||
|
||||
@@ -164,7 +167,7 @@ public class RecipeChainMath {
|
||||
int maxDepth = 0;
|
||||
|
||||
for (BookmarkItem ingrItem : preferredItems.keySet()) {
|
||||
if (ingrItem.factor > 0 && recipeId.equals(ingrItem.recipeId)) {
|
||||
if (!ingrItem.emptyFactor() && recipeId.equals(ingrItem.recipeId)) {
|
||||
maxDepth = Math.max(maxDepth, getMaxDepth(preferredItems.get(ingrItem).recipeId, preferredItems) + 1);
|
||||
}
|
||||
}
|
||||
@@ -176,7 +179,7 @@ public class RecipeChainMath {
|
||||
visited.add(recipeId);
|
||||
|
||||
for (BookmarkItem ingrItem : this.recipeIngredients) {
|
||||
if (ingrItem.factor > 0 && recipeId.equals(ingrItem.recipeId) && preferredItems.containsKey(ingrItem)) {
|
||||
if (!ingrItem.emptyFactor() && recipeId.equals(ingrItem.recipeId) && preferredItems.containsKey(ingrItem)) {
|
||||
BookmarkItem prefItem = preferredItems.get(ingrItem);
|
||||
|
||||
if (visited.contains(prefItem.recipeId)) {
|
||||
@@ -184,6 +187,7 @@ public class RecipeChainMath {
|
||||
} else {
|
||||
removeLoop(prefItem.recipeId, preferredItems, visited);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,22 +199,22 @@ public class RecipeChainMath {
|
||||
|
||||
for (BookmarkItem item : this.recipeResults) {
|
||||
if (this.outputRecipes.containsKey(item.recipeId) && !ROOT_RECIPE_ID.equals(item.recipeId)) {
|
||||
final long amount = item.factor * this.outputRecipes.get(item.recipeId);
|
||||
final long multiplier = this.outputRecipes.get(item.recipeId);
|
||||
final long amount = item.getAmount(multiplier);
|
||||
rootIngredients.add(
|
||||
BookmarkItem.of(
|
||||
-1,
|
||||
item.getItemStack(amount),
|
||||
item.getStackSize(amount),
|
||||
ROOT_RECIPE_ID,
|
||||
BookmarkItemType.INGREDIENT,
|
||||
BookmarkItem.generatePermutations(item.itemStack, null)));
|
||||
BookmarkItem.builder(-1, item.getItemStack(amount)).factor(item.getStackSize(amount))
|
||||
.permutations(BookmarkItem.Builder.generatePermutations(item.itemStack))
|
||||
.recipeId(ROOT_RECIPE_ID).type(BookmarkItemType.INGREDIENT).build());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.outputRecipes.clear();
|
||||
this.outputRecipes.put(ROOT_RECIPE_ID, 1L);
|
||||
this.recipeResults.removeIf(item -> ROOT_RECIPE_ID.equals(item.recipeId));
|
||||
this.recipeResults.add(BookmarkItem.of(-1, ROOT_ITEM, 1, ROOT_RECIPE_ID, BookmarkItemType.RESULT));
|
||||
this.recipeResults.add(
|
||||
BookmarkItem.builder(-1, ROOT_ITEM).factor(1).recipeId(ROOT_RECIPE_ID).type(BookmarkItemType.RESULT)
|
||||
.build());
|
||||
this.recipeIngredients.addAll(rootIngredients);
|
||||
|
||||
return ROOT_RECIPE_ID;
|
||||
@@ -226,24 +230,20 @@ public class RecipeChainMath {
|
||||
|
||||
public static RecipeChainMath of(Recipe recipe, long multiplier) {
|
||||
final List<BookmarkItem> chainItems = new ArrayList<>();
|
||||
final RecipeId recipeId = recipe.getRecipeId();
|
||||
final ItemStack result = recipe.getResult();
|
||||
final ItemStackSet ingredients = new ItemStackSet();
|
||||
|
||||
chainItems.add(BookmarkItem.of(-1, result, StackInfo.getAmount(result), recipeId, BookmarkItemType.RESULT));
|
||||
chainItems
|
||||
.add(BookmarkItem.builder(-1, result, recipe, BookmarkItemType.RESULT).multiplier(multiplier).build());
|
||||
|
||||
for (RecipeIngredient ingr : recipe.getIngredients()) {
|
||||
chainItems.add(
|
||||
BookmarkItem.of(
|
||||
-1,
|
||||
ingr.getItemStack(),
|
||||
ingr.getAmount(),
|
||||
recipeId,
|
||||
BookmarkItemType.INGREDIENT,
|
||||
BookmarkItem.generatePermutations(ingr.getItemStack(), recipe)));
|
||||
ingredients.add(ingr.getItemStack());
|
||||
}
|
||||
|
||||
for (BookmarkItem item : chainItems) {
|
||||
item.amount *= multiplier;
|
||||
for (ItemStack ingrStack : ingredients.values()) {
|
||||
chainItems.add(
|
||||
BookmarkItem.builder(-1, ingrStack, recipe, BookmarkItemType.INGREDIENT).multiplier(multiplier)
|
||||
.build());
|
||||
}
|
||||
|
||||
return new RecipeChainMath(chainItems, Collections.emptySet());
|
||||
@@ -253,7 +253,7 @@ public class RecipeChainMath {
|
||||
final ItemStackAmount missedItems = new ItemStackAmount();
|
||||
|
||||
for (BookmarkItem item : this.recipeResults) {
|
||||
long amount = item.amount - this.requiredAmount.getOrDefault(item, 0L);
|
||||
long amount = item.getAmount() - this.requiredAmount.getOrDefault(item, 0L);
|
||||
if (amount > 0) {
|
||||
missedItems.add(item.getItemStack(amount));
|
||||
}
|
||||
@@ -261,7 +261,7 @@ public class RecipeChainMath {
|
||||
|
||||
for (BookmarkItem item : this.recipeIngredients) {
|
||||
long amount = this.requiredAmount.containsKey(this.preferredItems.get(item)) ? 0
|
||||
: this.requiredAmount.getOrDefault(item, item.amount);
|
||||
: this.requiredAmount.getOrDefault(item, item.getAmount());
|
||||
if (amount > 0) {
|
||||
missedItems.add(item.getItemStack(amount));
|
||||
}
|
||||
@@ -279,11 +279,11 @@ public class RecipeChainMath {
|
||||
private void resetCalculation() {
|
||||
|
||||
for (BookmarkItem item : this.recipeIngredients) {
|
||||
item.amount = 0;
|
||||
item.multiplier = 0;
|
||||
}
|
||||
|
||||
for (BookmarkItem item : this.recipeResults) {
|
||||
item.amount = 0;
|
||||
item.multiplier = 0;
|
||||
}
|
||||
|
||||
this.preferredItems.clear();
|
||||
@@ -313,8 +313,8 @@ public class RecipeChainMath {
|
||||
}
|
||||
|
||||
for (BookmarkItem prefItem : this.recipeResults) {
|
||||
if (prefItem.factor > 0 && this.outputRecipes.containsKey(prefItem.recipeId)) {
|
||||
final long prefAmount = prefItem.factor * this.outputRecipes.get(prefItem.recipeId);
|
||||
if (!prefItem.emptyFactor() && this.outputRecipes.containsKey(prefItem.recipeId)) {
|
||||
final long prefAmount = prefItem.getAmount(this.outputRecipes.get(prefItem.recipeId));
|
||||
|
||||
if (prefItem.itemStack.getItem().hasContainerItem(prefItem.itemStack)) {
|
||||
this.containerItemsBlacklist.add(prefItem.itemStack);
|
||||
@@ -327,9 +327,9 @@ public class RecipeChainMath {
|
||||
}
|
||||
|
||||
for (BookmarkItem prefItem : this.recipeResults) {
|
||||
if (prefItem.factor > 0 && this.outputRecipes.containsKey(prefItem.recipeId)
|
||||
if (!prefItem.emptyFactor() && this.outputRecipes.containsKey(prefItem.recipeId)
|
||||
&& this.requiredAmount.containsKey(prefItem)) {
|
||||
final long prefAmount = prefItem.factor * this.outputRecipes.get(prefItem.recipeId);
|
||||
final long prefAmount = prefItem.getAmount(this.outputRecipes.get(prefItem.recipeId));
|
||||
this.requiredAmount.put(prefItem, this.requiredAmount.get(prefItem) - prefAmount);
|
||||
}
|
||||
}
|
||||
@@ -338,14 +338,6 @@ public class RecipeChainMath {
|
||||
return this;
|
||||
}
|
||||
|
||||
private void prepareIngredients(RecipeId recipeId, long stepShift, List<RecipeId> visited) {
|
||||
for (BookmarkItem item : this.recipeIngredients) {
|
||||
if (item.factor > 0 && recipeId.equals(item.recipeId)) {
|
||||
calculateSuitableRecipe(item, item.factor * stepShift, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateSuitableRecipe(BookmarkItem ingrItem, long ingrAmount, List<RecipeId> visited) {
|
||||
final BookmarkItem prefItem = this.preferredItems.get(ingrItem);
|
||||
|
||||
@@ -366,7 +358,7 @@ public class RecipeChainMath {
|
||||
if (ingrAmount > 0) {
|
||||
for (BookmarkItem item : this.initialItems) {
|
||||
if (item.containsItems(ingrItem)
|
||||
&& (ingrAmount = addRequiredAmount(item, ingrAmount, item.amount)) == 0) {
|
||||
&& (ingrAmount = addRequiredAmount(item, ingrAmount, item.getAmount())) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -379,19 +371,27 @@ public class RecipeChainMath {
|
||||
addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE);
|
||||
} else {
|
||||
addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE);
|
||||
final long shift = (long) Math
|
||||
.ceil((this.requiredAmount.get(prefItem) - prefItem.amount) / (double) prefItem.factor);
|
||||
final long multiplier = Math
|
||||
.max(0, prefItem.getMultiplierFromAmount(this.requiredAmount.get(prefItem)) - prefItem.multiplier);
|
||||
|
||||
if (shift > 0) {
|
||||
addShift(prefItem.recipeId, shift);
|
||||
if (multiplier > 0) {
|
||||
addShift(prefItem.recipeId, multiplier);
|
||||
visited.add(prefItem.recipeId);
|
||||
prepareIngredients(prefItem.recipeId, shift, visited);
|
||||
prepareIngredients(prefItem.recipeId, multiplier, visited);
|
||||
visited.remove(prefItem.recipeId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void prepareIngredients(RecipeId recipeId, long multiplier, List<RecipeId> visited) {
|
||||
for (BookmarkItem item : this.recipeIngredients) {
|
||||
if (!item.emptyFactor() && recipeId.equals(item.recipeId)) {
|
||||
calculateSuitableRecipe(item, item.getAmount(multiplier), visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long addRequiredAmount(BookmarkItem prefItem, long ingrAmount, long maxAmount) {
|
||||
long shiftAmount = this.requiredAmount.getOrDefault(prefItem, 0L);
|
||||
|
||||
@@ -489,7 +489,7 @@ public class RecipeChainMath {
|
||||
final NBTTagCompound toolStats = tagCompound.getCompoundTag("GT.ToolStats");
|
||||
final long maxDamage = toolStats.getLong("MaxDamage");
|
||||
final long damage = toolStats.getLong("Damage");
|
||||
final long leftSteps = (long) Math.ceil((maxDamage - damage) / (double) damagePerContainerCraft);
|
||||
final long leftSteps = (maxDamage - damage + damagePerContainerCraft - 1) / damagePerContainerCraft;
|
||||
final long availableSteps = Math.min(steps, Math.max(1, leftSteps));
|
||||
|
||||
steps -= availableSteps;
|
||||
@@ -552,13 +552,13 @@ public class RecipeChainMath {
|
||||
private void addShift(RecipeId recipeId, long shift) {
|
||||
for (BookmarkItem item : this.recipeIngredients) {
|
||||
if (recipeId.equals(item.recipeId)) {
|
||||
item.amount += item.factor * shift;
|
||||
item.multiplier += shift;
|
||||
}
|
||||
}
|
||||
|
||||
for (BookmarkItem item : this.recipeResults) {
|
||||
if (recipeId.equals(item.recipeId)) {
|
||||
item.amount += item.factor * shift;
|
||||
item.multiplier += shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
if (!this.lastControlKey) {
|
||||
final List<ItemStack> items = inventory.values();
|
||||
for (BookmarkItem item : math.recipeResults) {
|
||||
if (item.factor > 0 && this.math.outputRecipes.containsKey(item.recipeId)) {
|
||||
if (!item.emptyFactor() && this.math.outputRecipes.containsKey(item.recipeId)) {
|
||||
long amount = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
@@ -83,15 +83,18 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
}
|
||||
}
|
||||
|
||||
if (amount >= item.amount) {
|
||||
final long itemAmount = item.factor * this.math.outputRecipes.get(item.recipeId);
|
||||
if (amount >= item.getAmount()) {
|
||||
final long itemAmount = item.getAmount(this.math.outputRecipes.get(item.recipeId));
|
||||
|
||||
if (itemAmount > 0) {
|
||||
amount += itemAmount - amount % itemAmount;
|
||||
}
|
||||
|
||||
this.math.outputRecipes.put(
|
||||
item.recipeId,
|
||||
Math.max(this.math.outputRecipes.get(item.recipeId), amount / item.factor));
|
||||
Math.max(
|
||||
this.math.outputRecipes.get(item.recipeId),
|
||||
item.getMultiplierFromAmount(amount)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +125,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
|
||||
for (BookmarkItem item : math.recipeIngredients) {
|
||||
final long amount = math.requiredAmount.containsKey(math.preferredItems.get(item)) ? 0
|
||||
: math.requiredAmount.getOrDefault(item, item.amount);
|
||||
: math.requiredAmount.getOrDefault(item, item.getAmount());
|
||||
|
||||
if (amount > 0) {
|
||||
inputs.add(item.getItemStack(amount));
|
||||
@@ -130,7 +133,7 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
}
|
||||
|
||||
for (BookmarkItem item : math.recipeResults) {
|
||||
final long amount = item.amount - math.requiredAmount.getOrDefault(item, 0L);
|
||||
final long amount = item.getAmount() - math.requiredAmount.getOrDefault(item, 0L);
|
||||
|
||||
if (amount > 0) {
|
||||
if (math.outputRecipes.containsKey(item.recipeId)) {
|
||||
@@ -155,12 +158,12 @@ public class RecipeChainTooltipLineHandler implements ITooltipLineHandler {
|
||||
if (inventory.contains(item.itemStack)) {
|
||||
final long invAmount = inventory.get(item.itemStack) * item.fluidCellAmount;
|
||||
|
||||
if ((item.amount - invAmount) > 0) {
|
||||
inputs.add(item.getItemStack(item.amount - invAmount));
|
||||
if ((item.getAmount() - invAmount) > 0) {
|
||||
inputs.add(item.getItemStack(item.getAmount() - invAmount));
|
||||
}
|
||||
|
||||
if (Math.min(item.amount, invAmount) > 0) {
|
||||
available.add(item.getItemStack(Math.min(item.amount, invAmount)));
|
||||
if (Math.min(item.getAmount(), invAmount) > 0) {
|
||||
available.add(item.getItemStack(Math.min(item.getAmount(), invAmount)));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -18,6 +17,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
@@ -25,6 +25,7 @@ import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.ClientHandler;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
@@ -45,6 +46,7 @@ public class DebugHandlerWidget extends Widget {
|
||||
|
||||
private static class HandlerInfoRecord {
|
||||
|
||||
public HandlerInfo info;
|
||||
public String handlerKey;
|
||||
public int yShift;
|
||||
public int width;
|
||||
@@ -54,10 +56,12 @@ public class DebugHandlerWidget extends Widget {
|
||||
public boolean useCustomScroll;
|
||||
public boolean showFavorites;
|
||||
public boolean showOverlay;
|
||||
public boolean showBadge;
|
||||
|
||||
private String csvLine;
|
||||
|
||||
public HandlerInfoRecord(String handlerKey, HandlerInfo info) {
|
||||
this.info = info;
|
||||
this.handlerKey = handlerKey;
|
||||
this.yShift = info.getYShift();
|
||||
this.width = info.getWidth();
|
||||
@@ -67,36 +71,64 @@ public class DebugHandlerWidget extends Widget {
|
||||
this.useCustomScroll = info.getUseCustomScroll();
|
||||
this.showFavorites = info.getShowFavoritesButton();
|
||||
this.showOverlay = info.getShowOverlayButton();
|
||||
this.showBadge = info.getShowBadge();
|
||||
this.csvLine = toCsvLine();
|
||||
}
|
||||
|
||||
public void applyTo(HandlerInfo info) {
|
||||
info.setYShift(this.yShift);
|
||||
info.setHandlerDimensions(this.width, this.height);
|
||||
info.setMultipleWidgetsAllowed(this.multiWidgets);
|
||||
info.setUseCustomScroll(this.useCustomScroll);
|
||||
info.setShowFavoritesButton(this.showFavorites);
|
||||
info.setShowOverlayButton(this.showOverlay);
|
||||
public void apply() {
|
||||
this.info.setYShift(this.yShift);
|
||||
this.info.setHandlerDimensions(this.width, this.height);
|
||||
this.info.setMultipleWidgetsAllowed(this.multiWidgets);
|
||||
this.info.setUseCustomScroll(this.useCustomScroll);
|
||||
this.info.setShowFavoritesButton(this.showFavorites);
|
||||
this.info.setShowOverlayButton(this.showOverlay);
|
||||
this.info.setShowBadge(this.showBadge);
|
||||
NEIClientConfig.handlerOrdering.put(this.handlerKey, this.order);
|
||||
}
|
||||
|
||||
public void apply(String csvLine) {
|
||||
final String[] parts = csvLine.split(",");
|
||||
|
||||
this.yShift = intOrDefault(parts[1], this.yShift);
|
||||
this.height = intOrDefault(parts[2], this.height);
|
||||
this.width = intOrDefault(parts[3], this.width);
|
||||
this.multiWidgets = intOrDefault(parts[4], this.multiWidgets ? 1 : 0) == 1;
|
||||
this.order = intOrDefault(parts[5], this.order);
|
||||
this.useCustomScroll = intOrDefault(parts[6], this.useCustomScroll ? 1 : 0) == 1;
|
||||
this.showFavorites = intOrDefault(parts[7], this.showFavorites ? 1 : 0) == 1;
|
||||
this.showOverlay = intOrDefault(parts[8], this.showOverlay ? 1 : 0) == 1;
|
||||
this.showBadge = intOrDefault(parts[9], this.showBadge ? 1 : 0) == 1;
|
||||
|
||||
apply();
|
||||
}
|
||||
|
||||
public String toCsvLine() {
|
||||
return String.join(
|
||||
",",
|
||||
handlerKey,
|
||||
String.valueOf(yShift),
|
||||
String.valueOf(height),
|
||||
String.valueOf(width),
|
||||
String.valueOf(multiWidgets ? 1 : 0),
|
||||
String.valueOf(order),
|
||||
String.valueOf(useCustomScroll ? 1 : 0),
|
||||
String.valueOf(showFavorites ? 1 : 0),
|
||||
String.valueOf(showOverlay ? 1 : 0));
|
||||
this.handlerKey,
|
||||
String.valueOf(this.yShift),
|
||||
String.valueOf(this.height),
|
||||
String.valueOf(this.width),
|
||||
String.valueOf(this.multiWidgets ? 1 : 0),
|
||||
String.valueOf(this.order),
|
||||
String.valueOf(this.useCustomScroll ? 1 : 0),
|
||||
String.valueOf(this.showFavorites ? 1 : 0),
|
||||
String.valueOf(this.showOverlay ? 1 : 0),
|
||||
String.valueOf(this.showBadge ? 1 : 0));
|
||||
}
|
||||
|
||||
public boolean isUnmodified() {
|
||||
return this.csvLine.equals(this.toCsvLine());
|
||||
}
|
||||
|
||||
private int intOrDefault(String str, int defaultValue) {
|
||||
if (str == null || str.isEmpty()) return defaultValue;
|
||||
try {
|
||||
return Integer.parseInt(str);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final int WINDOW_WIDTH = 176;
|
||||
@@ -105,7 +137,7 @@ public class DebugHandlerWidget extends Widget {
|
||||
private static final int LABEL_WIDTH = 50;
|
||||
|
||||
private static final String TOOLTIP_PREFIX = "debug.RecipeHandler.";
|
||||
private static final String HEADER = "HandlerId,YShift,Height,Width,MultiWidgets,Order,UseCustomScroll,ShowFavorites,ShowOverlay";
|
||||
private static final String HEADER = "HandlerId,YShift,Height,Width,MultiWidgets,Order,UseCustomScroll,ShowFavorites,ShowOverlay,ShowBadge";
|
||||
private final int[] COLORS = new int[] { 0x2200FF00, 0x22FF0000, 0x220000FF, 0x2200FFFF, 0x22FF00FF, 0x22FFFF00 };
|
||||
|
||||
public static DebugHandlerWidget instance = new DebugHandlerWidget();
|
||||
@@ -114,12 +146,11 @@ public class DebugHandlerWidget extends Widget {
|
||||
private final Map<String, IUpdatableWidget> values = new LinkedHashMap<>();
|
||||
private Map<String, HandlerInfoRecord> patches = new HashMap<>();
|
||||
|
||||
private IRecipeHandler handler;
|
||||
private HandlerInfo handlerInfo;
|
||||
private HandlerInfoRecord record;
|
||||
|
||||
private Point dragPoint = null;
|
||||
private boolean showWidget = false;
|
||||
private Button resetButton;
|
||||
|
||||
private final DrawableResource BG_TEXTURE = new DrawableBuilder(
|
||||
"nei:textures/gui/recipebg.png",
|
||||
@@ -147,29 +178,19 @@ public class DebugHandlerWidget extends Widget {
|
||||
y = addInfoWidget("HHack", y);
|
||||
y = addInfoWidget("ModName", y);
|
||||
y = addInfoWidget("ModId", y);
|
||||
y = addInfoWidget("Override", y);
|
||||
y = addOverrideInfoWidget("Override", y);
|
||||
|
||||
y = addTextFieldWidget("Order", 0, (field, oldText) -> {
|
||||
|
||||
if (field.getInteger() != record.order) {
|
||||
record.order = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}
|
||||
|
||||
record.order = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
|
||||
y = addTextFieldWidget("yShift", 0, (field, oldText) -> {
|
||||
|
||||
if (field.getInteger() != handlerInfo.getYShift()) {
|
||||
handlerInfo.setYShift(field.getInteger());
|
||||
record.yShift = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}
|
||||
|
||||
record.yShift = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
|
||||
y = addCheckboxWidget("MultiWidgets", button -> {
|
||||
handlerInfo.setMultipleWidgetsAllowed(button.value);
|
||||
record.multiWidgets = button.value;
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
@@ -182,43 +203,35 @@ public class DebugHandlerWidget extends Widget {
|
||||
this.values.put("height_readonly", readonly);
|
||||
|
||||
y = addTextFieldWidget("Height", HandlerInfo.DEFAULT_HEIGHT, (field, oldText) -> {
|
||||
|
||||
if (field.getInteger() != handlerInfo.getHeight()) {
|
||||
handlerInfo.setHandlerDimensions(handlerInfo.getWidth(), field.getInteger());
|
||||
record.height = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}
|
||||
|
||||
record.height = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
|
||||
y = addTextFieldWidget("Width", HandlerInfo.DEFAULT_WIDTH, (field, oldText) -> {
|
||||
|
||||
if (field.getInteger() != handlerInfo.getWidth()) {
|
||||
handlerInfo.setHandlerDimensions(field.getInteger(), handlerInfo.getHeight());
|
||||
record.width = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}
|
||||
|
||||
record.width = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
|
||||
y = addCheckboxWidget("UseCustomScroll", button -> {
|
||||
handlerInfo.setUseCustomScroll(button.value);
|
||||
record.useCustomScroll = button.value;
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
|
||||
y = addCheckboxWidget("ShowFavorites", button -> {
|
||||
handlerInfo.setShowFavoritesButton(button.value);
|
||||
record.showFavorites = button.value;
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
|
||||
y = addCheckboxWidget("ShowOverlay", button -> {
|
||||
handlerInfo.setShowOverlayButton(button.value);
|
||||
record.showOverlay = button.value;
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
|
||||
y = addCheckboxWidget("ShowBadge", button -> {
|
||||
record.showBadge = button.value;
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
|
||||
this.h = 10 + LINE_HEIGHT + y;
|
||||
this.container.h = this.h - INLINE_PADDING * 2 - LINE_HEIGHT;
|
||||
}
|
||||
@@ -278,10 +291,52 @@ public class DebugHandlerWidget extends Widget {
|
||||
return y + value.h + 1;
|
||||
}
|
||||
|
||||
private int addOverrideInfoWidget(String key, int y) {
|
||||
final LabelWidget label = new LabelWidget(0x888888, false);
|
||||
final LabelWidget value = new LabelWidget(0xffffff, true);
|
||||
this.resetButton = new Button(NEIClientUtils.translate("debug.RecipeHandler.reset")) {
|
||||
|
||||
@Override
|
||||
public boolean onButtonPress(boolean rightclick) {
|
||||
if (record != null) {
|
||||
record.apply(record.csvLine);
|
||||
saveHandlerInfoPatch();
|
||||
record = null;// force update of button state
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mousex, int mousey) {
|
||||
this.state = record != null && record.isUnmodified() ? 2 : 0;
|
||||
super.draw(mousex, mousey);
|
||||
}
|
||||
};
|
||||
|
||||
this.resetButton.w = 58;
|
||||
this.resetButton.h = 16;
|
||||
this.resetButton.y = label.y = value.y = y;
|
||||
this.resetButton.x = this.w - INLINE_PADDING * 2 - this.resetButton.w - 1;
|
||||
|
||||
label.w = LABEL_WIDTH;
|
||||
value.x = LABEL_WIDTH + 5;
|
||||
value.w = this.resetButton.x - value.x - 2;
|
||||
|
||||
label.updateValue(NEIClientUtils.translate(TOOLTIP_PREFIX + key));
|
||||
|
||||
this.container.addWidget(label);
|
||||
this.container.addWidget(value);
|
||||
this.values.put(key.toLowerCase(), value);
|
||||
|
||||
this.container.addWidget(this.resetButton);
|
||||
|
||||
return y + value.h + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(int mx, int my) {
|
||||
|
||||
if (this.handler != null) {
|
||||
if (this.record != null) {
|
||||
GL11.glColor4f(1F, 1F, 1F, 1F);
|
||||
GL11.glScaled(1, 1, 2f);
|
||||
GL11.glDisable(GL11.GL_DEPTH_TEST);
|
||||
@@ -318,24 +373,22 @@ public class DebugHandlerWidget extends Widget {
|
||||
|
||||
if (this.showWidget && gui instanceof GuiRecipe recipe) {
|
||||
|
||||
if (this.handler != recipe.getHandler()) {
|
||||
this.handler = recipe.getHandler();
|
||||
this.handlerInfo = GuiRecipeTab.getHandlerInfo(handler);
|
||||
if (this.record == null || !this.record.handlerKey.equals(getHandlerID(recipe.getHandler()))) {
|
||||
final IRecipeHandler handler = recipe.getHandler();
|
||||
this.record = this.patches.computeIfAbsent(
|
||||
getHandlerID(handler),
|
||||
handlerKey -> new HandlerInfoRecord(handlerKey, handlerInfo));
|
||||
|
||||
handlerKey -> new HandlerInfoRecord(handlerKey, GuiRecipeTab.getHandlerInfo(handler)));
|
||||
final boolean isHeightHackApplied = NEIClientConfig.heightHackHandlerRegex.stream()
|
||||
.map(pattern -> pattern.matcher(this.handler.getHandlerId())).anyMatch(Matcher::matches);
|
||||
.map(pattern -> pattern.matcher(handler.getHandlerId())).anyMatch(Matcher::matches);
|
||||
|
||||
this.values.get("name").updateValue(this.handler.getRecipeName());
|
||||
this.values.get("id").updateValue(this.handler.getOverlayIdentifier());
|
||||
this.values.get("key").updateValue(this.handler.getHandlerId());
|
||||
this.values.get("name").updateValue(handler.getRecipeName());
|
||||
this.values.get("id").updateValue(handler.getOverlayIdentifier());
|
||||
this.values.get("key").updateValue(handler.getHandlerId());
|
||||
this.values.get("hhack").updateValue(
|
||||
isHeightHackApplied ? NEIClientUtils.translate("debug.RecipeHandler.yes")
|
||||
: NEIClientUtils.translate("debug.RecipeHandler.no"));
|
||||
this.values.get("modname").updateValue(this.handlerInfo.getModName());
|
||||
this.values.get("modid").updateValue(this.handlerInfo.getModId());
|
||||
this.values.get("modname").updateValue(this.record.info.getModName());
|
||||
this.values.get("modid").updateValue(this.record.info.getModId());
|
||||
|
||||
this.values.get("order").updateValue(String.valueOf(this.record.order));
|
||||
this.values.get("yshift").updateValue(String.valueOf(this.record.yShift));
|
||||
@@ -348,10 +401,9 @@ public class DebugHandlerWidget extends Widget {
|
||||
|
||||
this.values.get("showfavorites").updateValue(String.valueOf(this.record.showFavorites));
|
||||
this.values.get("showoverlay").updateValue(String.valueOf(this.record.showOverlay));
|
||||
this.values.get("showbadge").updateValue(String.valueOf(this.record.showBadge));
|
||||
|
||||
this.values.get("override").updateValue(
|
||||
this.record.isUnmodified() ? NEIClientUtils.translate("debug.RecipeHandler.no")
|
||||
: NEIClientUtils.translate("debug.RecipeHandler.yes"));
|
||||
updateOverride();
|
||||
|
||||
this.container.removeIf(
|
||||
widget -> this.values.get("height") == widget || this.values.get("height_readonly") == widget);
|
||||
@@ -364,9 +416,7 @@ public class DebugHandlerWidget extends Widget {
|
||||
}
|
||||
|
||||
} else {
|
||||
this.handler = null;
|
||||
this.record = null;
|
||||
this.handlerInfo = null;
|
||||
this.showWidget = false;
|
||||
}
|
||||
|
||||
@@ -375,12 +425,12 @@ public class DebugHandlerWidget extends Widget {
|
||||
|
||||
@Override
|
||||
public List<String> handleTooltip(int mx, int my, List<String> tooltip) {
|
||||
return this.handler != null ? this.container.handleTooltip(mx, my, tooltip) : tooltip;
|
||||
return this.record != null ? this.container.handleTooltip(mx, my, tooltip) : tooltip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> handleHotkeys(int mousex, int mousey, Map<String, String> hotkeys) {
|
||||
return this.handler != null ? this.container.handleHotkeys(mousex, mousey, hotkeys) : hotkeys;
|
||||
return this.record != null ? this.container.handleHotkeys(mousex, mousey, hotkeys) : hotkeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -390,7 +440,7 @@ public class DebugHandlerWidget extends Widget {
|
||||
&& NEIClientUtils.shiftKey()) {
|
||||
this.showWidget = !this.showWidget;
|
||||
return true;
|
||||
} else if (this.handler != null) {
|
||||
} else if (this.record != null) {
|
||||
|
||||
if (this.container.handleKeyPress(keyID, keyChar)) {
|
||||
return true;
|
||||
@@ -406,7 +456,7 @@ public class DebugHandlerWidget extends Widget {
|
||||
|
||||
@Override
|
||||
public void onGuiClick(int mx, int my) {
|
||||
if (this.handler != null) {
|
||||
if (this.record != null) {
|
||||
this.container.onGuiClick(mx, my);
|
||||
}
|
||||
}
|
||||
@@ -414,7 +464,7 @@ public class DebugHandlerWidget extends Widget {
|
||||
@Override
|
||||
public boolean handleClick(int mx, int my, int button) {
|
||||
|
||||
if (this.handler != null) {
|
||||
if (this.record != null) {
|
||||
|
||||
if (new Rectangle4i(this.x + INLINE_PADDING, this.y + BORDER_PADDING, this.w - INLINE_PADDING * 2, 12)
|
||||
.contains(mx, my)) {
|
||||
@@ -424,19 +474,19 @@ public class DebugHandlerWidget extends Widget {
|
||||
this.container.handleClick(mx, my, button);
|
||||
}
|
||||
|
||||
return this.handler != null;
|
||||
return this.record != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int px, int py) {
|
||||
return this.handler != null && super.contains(px, py);
|
||||
return this.record != null && super.contains(px, py);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp(int mx, int my, int button) {
|
||||
this.dragPoint = null;
|
||||
|
||||
if (this.handler != null) {
|
||||
if (this.record != null) {
|
||||
this.container.mouseUp(mx, my, button);
|
||||
}
|
||||
}
|
||||
@@ -444,7 +494,7 @@ public class DebugHandlerWidget extends Widget {
|
||||
@Override
|
||||
public boolean onMouseWheel(int scrolled, int mousex, int mousey) {
|
||||
|
||||
if (this.handler != null && contains(mousex, mousey)) {
|
||||
if (this.record != null && contains(mousex, mousey)) {
|
||||
this.container.onMouseWheel(scrolled, mousex, mousey);
|
||||
return true;
|
||||
}
|
||||
@@ -454,7 +504,7 @@ public class DebugHandlerWidget extends Widget {
|
||||
|
||||
@Override
|
||||
public boolean handleClickExt(int mx, int my, int button) {
|
||||
return this.handler != null && this.container.handleClickExt(mx, my, button);
|
||||
return this.record != null && this.container.handleClickExt(mx, my, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -542,24 +592,14 @@ public class DebugHandlerWidget extends Widget {
|
||||
|
||||
for (String line : lines.collect(Collectors.toCollection(HashSet::new))) {
|
||||
if (HEADER.equals(line)) continue;
|
||||
final String[] parts = Arrays.copyOf((line + ",null,null,null,null,null,null,null,null").split(","), 9);
|
||||
final String handler = parts[0];
|
||||
final String[] parts = (line).split(",");
|
||||
final String handlerKey = parts[0];
|
||||
|
||||
if (GuiRecipeTab.handlerMap.containsKey(handler)) {
|
||||
final HandlerInfo info = GuiRecipeTab.handlerMap.get(handler);
|
||||
final HandlerInfoRecord record = patches
|
||||
.computeIfAbsent(handler, handlerKey -> new HandlerInfoRecord(handler, info));
|
||||
|
||||
record.yShift = intOrDefault(parts[1], info.getYShift());
|
||||
record.height = intOrDefault(parts[2], info.getHeight());
|
||||
record.width = intOrDefault(parts[3], info.getWidth());
|
||||
record.multiWidgets = intOrDefault(parts[4], info.isMultipleWidgetsAllowed() ? 1 : 0) == 1;
|
||||
record.order = intOrDefault(parts[5], NEIClientConfig.handlerOrdering.getOrDefault(handler, 0));
|
||||
record.useCustomScroll = intOrDefault(parts[6], info.getUseCustomScroll() ? 1 : 0) == 1;
|
||||
record.showFavorites = intOrDefault(parts[7], info.getShowFavoritesButton() ? 1 : 0) == 1;
|
||||
record.showOverlay = intOrDefault(parts[8], info.getShowOverlayButton() ? 1 : 0) == 1;
|
||||
|
||||
record.applyTo(info);
|
||||
if (GuiRecipeTab.handlerMap.containsKey(handlerKey)) {
|
||||
final HandlerInfoRecord record = patches.computeIfAbsent(
|
||||
handlerKey,
|
||||
key -> new HandlerInfoRecord(key, GuiRecipeTab.handlerMap.get(key)));
|
||||
record.apply((line + ",null,null,null,null,null,null,null,null,null"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -585,9 +625,8 @@ public class DebugHandlerWidget extends Widget {
|
||||
} catch (IOException e) {}
|
||||
|
||||
if (this.record != null) {
|
||||
this.values.get("override").updateValue(
|
||||
this.record.isUnmodified() ? NEIClientUtils.translate("debug.RecipeHandler.no")
|
||||
: NEIClientUtils.translate("debug.RecipeHandler.yes"));
|
||||
updateOverride();
|
||||
record.apply();
|
||||
}
|
||||
|
||||
if (NEIClientUtils.getGuiContainer() instanceof GuiRecipe<?>recipe) {
|
||||
@@ -595,12 +634,15 @@ public class DebugHandlerWidget extends Widget {
|
||||
}
|
||||
}
|
||||
|
||||
private int intOrDefault(String str, int defaultValue) {
|
||||
if (str == null || str.isEmpty()) return defaultValue;
|
||||
try {
|
||||
return Integer.parseInt(str);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
private void updateOverride() {
|
||||
this.container.removeIf(widget -> widget == this.resetButton);
|
||||
|
||||
if (this.record.isUnmodified()) {
|
||||
this.values.get("override").updateValue(NEIClientUtils.translate("debug.RecipeHandler.no"));
|
||||
} else {
|
||||
this.values.get("override")
|
||||
.updateValue(EnumChatFormatting.RED + NEIClientUtils.translate("debug.RecipeHandler.yes"));
|
||||
this.container.addWidget(this.resetButton);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -519,6 +519,8 @@ nei.options.tools.dump.itempanel.mode.2=Json
|
||||
nei.options.tools.dump.itempanel.mode.3=PNG
|
||||
nei.options.tools.dump.itempanel.icon.dumped=Item Panel icons were dumped to %s
|
||||
nei.options.tools.dump.itempanel.icon.cancelled=Dump cancelled
|
||||
nei.options.tools.dump.itempanel.icon.warning.1=§cWARNING§r: You are about to dump %s items at %sx%s resolution
|
||||
nei.options.tools.dump.itempanel.icon.warning.2=Hold %s while clicking this button to proceed
|
||||
nei.options.tools.dump.handlers=NEI Handlers
|
||||
nei.options.tools.dump.handlers.dumped=handlers were dumped to %s
|
||||
nei.options.tools.dump.handlers.mode.0=CSV
|
||||
@@ -539,12 +541,14 @@ nei.debug.RecipeHandler.Height=Height
|
||||
nei.debug.RecipeHandler.Width=Width
|
||||
nei.debug.RecipeHandler.ShowFavorites=Show Favorites
|
||||
nei.debug.RecipeHandler.ShowOverlay=Show Overlays
|
||||
nei.debug.RecipeHandler.ShowBadge=Show Badge
|
||||
nei.debug.RecipeHandler.UseCustomScroll=Use Custom Scroll
|
||||
nei.debug.RecipeHandler.Override=Override
|
||||
nei.debug.RecipeHandler.checkbox.on=On
|
||||
nei.debug.RecipeHandler.checkbox.off=Off
|
||||
nei.debug.RecipeHandler.yes=Yes
|
||||
nei.debug.RecipeHandler.no=No
|
||||
nei.debug.RecipeHandler.reset=Reset
|
||||
|
||||
nei.recipe.page=Page %s/%s
|
||||
nei.recipe.tooltip=Recipes
|
||||
@@ -554,6 +558,16 @@ nei.recipe.shapeless=Shapeless Crafting
|
||||
nei.recipe.furnace=Smelting
|
||||
nei.recipe.fuel=Fuel
|
||||
nei.recipe.fuel.smeltCount=Smelts %s items
|
||||
|
||||
nei.recipe.badge.nc=NC
|
||||
nei.recipe.badge.nc.tooltip=Does not get consumed in the process
|
||||
|
||||
nei.recipe.badge.ncp=NC(P)
|
||||
nei.recipe.badge.ncp.tooltip=Considered in parallel calculation, but not get consumed
|
||||
|
||||
nei.recipe.badge.chance.consume=Consume Chance: %s
|
||||
nei.recipe.badge.chance.output=Output Chance: %s
|
||||
|
||||
# Deprecated
|
||||
nei.recipe.fuel.required=%s required
|
||||
# Deprecated
|
||||
|
||||
Reference in new issue
Block a user