mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-11-15 09:44:44 +00:00
Compare commits
46
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f55dc716e3 | ||
|
|
26beb079f0 | ||
|
|
841b73c6fe | ||
|
|
0c7eeebb1f | ||
|
|
65b56735a7 | ||
|
|
ff428bf538 | ||
|
|
a406021f26 | ||
|
|
8500ac57eb | ||
|
|
d97123ec13 | ||
|
|
434931bfac | ||
|
|
860011036b | ||
|
|
937c1858a4 | ||
|
|
4562ecf087 | ||
|
|
d621d5d5bd | ||
|
|
3175b316af | ||
|
|
61930ac7a8 | ||
|
|
fcbf1dcade | ||
|
|
3fa69e826c | ||
|
|
31fff21a55 | ||
|
|
2e9ab88692 | ||
|
|
a02d293d44 | ||
|
|
1265113390 | ||
|
|
4ffd614017 | ||
|
|
41554f4c5b | ||
|
|
2104184077 | ||
|
|
d5f25a4be8 | ||
|
|
ccbf94790a | ||
|
|
2f4f72a2d6 | ||
|
|
f8cec9a78c | ||
|
|
fb43a662eb | ||
|
|
b2e0b8878a | ||
|
|
374f019103 | ||
|
|
5dfcff6f30 | ||
|
|
bd17301cb9 | ||
|
|
96ccd4e109 | ||
|
|
b30ca57e68 | ||
|
|
8f949bc1d1 | ||
|
|
d25365942a | ||
|
|
eb58e1dabc | ||
|
|
f4601e7eed | ||
|
|
ba48806667 | ||
|
|
70c332796a | ||
|
|
bcc25d4369 | ||
|
|
10a3109714 | ||
|
|
b60769864f | ||
|
|
6bc899769f |
No files matched your search
+18
-2
@@ -1,8 +1,12 @@
|
||||
// Add your dependencies here
|
||||
configurations.create('gtnhlibEmbed') {
|
||||
canBeConsumed = false
|
||||
canBeResolved = true
|
||||
}
|
||||
|
||||
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.16:dev')
|
||||
devOnlyNonPublishable('com.github.GTNewHorizons:GTNHLib:0.11.23:dev')
|
||||
|
||||
shadowImplementation('org.apache.commons:commons-csv:1.10.0')
|
||||
|
||||
@@ -17,4 +21,16 @@ dependencies {
|
||||
|
||||
testRuntimeOnly('org.junit.platform:junit-platform-launcher')
|
||||
testRuntimeOnly("org.lwjgl.lwjgl:lwjgl:2.9.3");
|
||||
|
||||
compileOnly("com.github.GTNewHorizons:GTNHLib:0.11.23") { transitive = false }
|
||||
gtnhlibEmbed("com.github.GTNewHorizons:GTNHLib:0.11.23") { transitive = false }
|
||||
}
|
||||
|
||||
[tasks.jar, tasks.shadowJar].each {
|
||||
it.configure {
|
||||
from({ project.configurations.getByName('gtnhlibEmbed').collect { zipTree(it) } }) {
|
||||
include 'com/gtnewhorizon/gtnhlib/color/ColorResource.class'
|
||||
include 'com/gtnewhorizon/gtnhlib/color/ColorResource$*.class'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.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.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.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
|
||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
|
||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
|
||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
|
||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/c2dd35c9d0aaf0ba6ad0791320f99dfc/redirect
|
||||
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/e5810bd7fd1f8a586644409d395a7e55/redirect
|
||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/cf726b4a1c84b50457225f9bba6d7650/redirect
|
||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/fa1e318c287360478e3c83a9a3ef1007/redirect
|
||||
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/7b3c4877c0749019e6805bb61e421497/redirect
|
||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/d76df094a9cbbabd3b08251f9e61444a/redirect
|
||||
toolchainVersion=25
|
||||
+1
-1
@@ -17,7 +17,7 @@ pluginManagement {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.24'
|
||||
id 'com.gtnewhorizons.gtnhsettingsconvention' version '2.0.26'
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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).multiplier(1);
|
||||
} else if (recipeId != null) {
|
||||
builder = BookmarkItem.builder(groupId, itemStack).recipeId(recipeId)
|
||||
.factor(StackInfo.getAmount(itemStack)).multiplier(1);
|
||||
} else {
|
||||
builder = BookmarkItem.builder(groupId, itemStack).factor(1).multiplier(StackInfo.getAmount(itemStack));
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -783,15 +799,15 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
|
||||
NEIMouseUtils.getKeyName(NEIMouseUtils.MOUSE_BTN_RMB),
|
||||
NEIClientUtils.translate("bookmark.group.toggle_crafting_chain"));
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.remove_recipe"),
|
||||
KeyManager.getKeyName("bookmark.remove_recipe", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.remove_recipe"));
|
||||
|
||||
if (BookmarkContainerInfo.getBookmarkContainerHandler(NEIClientUtils.getGuiContainer()) != null) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark_pull_items"),
|
||||
KeyManager.getKeyName("bookmark.pull_items"),
|
||||
NEIClientUtils.translate("bookmark.group.pull_items"));
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark_pull_items", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.pull_items", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.pull_items_shift"));
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -57,6 +57,10 @@ public abstract class Button extends Widget {
|
||||
return label;
|
||||
}
|
||||
|
||||
public int getRenderLabelColor() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public final String label;
|
||||
public Image icon;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import codechicken.core.ClassDiscoverer;
|
||||
import codechicken.core.ClientUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.nei.api.API;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.IConfigureNEI;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
@@ -374,6 +375,7 @@ public class ClientHandler {
|
||||
} else if (event.gui == null) {
|
||||
/* prevent WorldClient reference being held in the Gui */
|
||||
NEIController.manager = null;
|
||||
GuiInfo.clearGuiHandlers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.color.ColorResource;
|
||||
|
||||
public class ColorUtils {
|
||||
|
||||
private static final ColorResource.Factory color = new ColorResource.Factory("nei");
|
||||
|
||||
public static final ColorResource
|
||||
// spotless:off
|
||||
textGray = color.rgb("textGray", "0x404040"),
|
||||
textLightGray = color.rgb("textLightGray", "0x606060"),
|
||||
recipeTitle = color.rgb("recipeTitle", "0xFFFFFF"),
|
||||
recipeTitleHover = color.rgb("recipeTitleHover", "0xFFFF55"),
|
||||
subsetWidget = color.rgb("subsetWidget", "0xAA00AA"),
|
||||
recipeBadge = color.rgb("recipeBadge", "0xFDD835"),
|
||||
buttonLabelNormal = color.rgb("buttonLabelNormal", "0xE0E0E0"),
|
||||
buttonLabelHover = color.rgb("buttonLabelHover", "0xFFFFA0"),
|
||||
buttonLabelDisabled = color.rgb("buttonLabelDisabled", "0x601010"),
|
||||
buttonLabelInactive = color.rgb("buttonLabelInactive", "0xA0A0A0");
|
||||
// spotless:on
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -24,8 +24,8 @@ public class GuiEnchantmentModifier extends GuiContainer {
|
||||
|
||||
@Override
|
||||
protected void drawGuiContainerForegroundLayer(int par1, int par2) {
|
||||
fontRendererObj.drawString(translate("enchant"), 12, 6, 0x404040);
|
||||
fontRendererObj.drawString(translate("enchant.level"), 19, 20, 0x404040);
|
||||
fontRendererObj.drawString(translate("enchant"), 12, 6, ColorUtils.textGray.getColor());
|
||||
fontRendererObj.drawString(translate("enchant.level"), 19, 20, ColorUtils.textGray.getColor());
|
||||
}
|
||||
|
||||
protected void drawGuiContainerBackgroundLayer(float f, int i, int j) {
|
||||
@@ -39,7 +39,11 @@ public class GuiEnchantmentModifier extends GuiContainer {
|
||||
container.drawScrollBar(this);
|
||||
|
||||
String levelstring = "" + container.level;
|
||||
fontRendererObj.drawString(levelstring, 33 - fontRendererObj.getStringWidth(levelstring) / 2, 34, 0xFF606060);
|
||||
fontRendererObj.drawString(
|
||||
levelstring,
|
||||
33 - fontRendererObj.getStringWidth(levelstring) / 2,
|
||||
34,
|
||||
ColorUtils.textLightGray.getColor());
|
||||
|
||||
GL11.glTranslatef(-guiLeft, -guiTop, 0);
|
||||
}
|
||||
|
||||
@@ -45,15 +45,14 @@ public class GuiNEIButton extends GuiButton {
|
||||
}
|
||||
|
||||
protected int getTextColour(boolean mouseOver) {
|
||||
int color = 0xe0e0e0;
|
||||
|
||||
if (!enabled) {
|
||||
color = 0xffa0a0a0;
|
||||
return ColorUtils.buttonLabelInactive.getColor();
|
||||
} else if (mouseOver) {
|
||||
color = 0xffffa0;
|
||||
return ColorUtils.buttonLabelHover.getColor();
|
||||
}
|
||||
|
||||
return color;
|
||||
return ColorUtils.buttonLabelNormal.getColor();
|
||||
}
|
||||
|
||||
protected void drawContent(Minecraft minecraft, int y, int x, boolean mouseOver) {
|
||||
|
||||
@@ -289,10 +289,10 @@ public class GuiPotionCreator extends GuiContainerWidget {
|
||||
CCRenderState.changeTexture("nei:textures/gui/potion.png");
|
||||
drawTexturedModalRect(0, 0, 0, 0, xSize, ySize);
|
||||
|
||||
FontUtils.drawCenteredString(translate("potion.favourite"), xSize / 2, 4, 0x404040);
|
||||
fontRendererObj.drawString(translate("potion.duration"), 12, 40, 0x404040);
|
||||
fontRendererObj.drawString(translate("potion.level"), 19, 73, 0x404040);
|
||||
FontUtils.drawCenteredString(translateAmplifier(amplifier), 33, 86, 0xFF606060);
|
||||
FontUtils.drawCenteredString(translate("potion.favourite"), xSize / 2, 4, ColorUtils.textGray.getColor());
|
||||
fontRendererObj.drawString(translate("potion.duration"), 12, 40, ColorUtils.textGray.getColor());
|
||||
fontRendererObj.drawString(translate("potion.level"), 19, 73, ColorUtils.textGray.getColor());
|
||||
FontUtils.drawCenteredString(translateAmplifier(amplifier), 33, 86, ColorUtils.textGray.getColor());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,7 +28,7 @@ public class HUDRenderer implements IKeyStateTracker {
|
||||
|
||||
@Override
|
||||
public void tickKeyStates() {
|
||||
if (KeyManager.keyStates.get("world.highlight_tips").down) {
|
||||
if (KeyManager.isPressed("world.highlight_tips")) {
|
||||
ConfigTag tag = NEIClientConfig.getSetting("world.highlight_tips");
|
||||
tag.setBooleanValue(!tag.getBooleanValue());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -2,40 +2,23 @@ package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.ForkJoinWorkerThread;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraftforge.fluids.IFluidContainerItem;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
|
||||
import codechicken.nei.ThreadOperationTimer.TimeoutException;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.recipe.InformationHandler;
|
||||
import codechicken.nei.recipe.RecipeHandlerRef;
|
||||
import codechicken.nei.recipe.RepairRecipeHandler;
|
||||
import codechicken.nei.search.TooltipFilter;
|
||||
import codechicken.nei.util.ItemUntranslator;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
|
||||
public class ItemList {
|
||||
|
||||
@@ -53,9 +36,6 @@ public class ItemList {
|
||||
public static final List<ItemFilterProvider> itemFilterers = new LinkedList<>();
|
||||
public static final List<ItemsLoadedCallback> loadCallbacks = new LinkedList<>();
|
||||
|
||||
private static final HashSet<Item> erroredItems = new HashSet<>();
|
||||
private static final HashSet<String> stackTraces = new HashSet<>();
|
||||
private static Map<ItemStack, Integer> ordering = new HashMap<>();
|
||||
/**
|
||||
* Unlike {@link LayoutManager#itemsLoaded}, this indicates whether item loading is actually finished or not.
|
||||
*/
|
||||
@@ -117,7 +97,15 @@ public class ItemList {
|
||||
displayName = EnumChatFormatting
|
||||
.getTextWithoutFormattingCodes(item.getItem().getItemStackDisplayName(item));
|
||||
|
||||
return displayName != null && !displayName.isEmpty() && this.pattern.matcher(displayName).find();
|
||||
if (displayName != null && !displayName.isEmpty() && this.pattern.matcher(displayName).find()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (String alias : ItemInfo.getAliases(item)) {
|
||||
if (this.pattern.matcher(alias).find()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -218,231 +206,6 @@ public class ItemList {
|
||||
return filters;
|
||||
}
|
||||
|
||||
public static final RestartableTask loadItems = new RestartableTask("NEI Item Loading") {
|
||||
|
||||
private void damageSearch(Item item, List<ItemStack> permutations) {
|
||||
HashSet<String> damageIconSet = new HashSet<>();
|
||||
for (int damage = 0; damage < 16; damage++) try {
|
||||
ItemStack itemstack = new ItemStack(item, 1, damage);
|
||||
IIcon icon = item.getIconIndex(itemstack);
|
||||
String name = getTooltip(itemstack);
|
||||
String s = name + "@" + (icon == null ? 0 : icon.hashCode());
|
||||
if (damageIconSet.add(s)) {
|
||||
permutations.add(itemstack);
|
||||
}
|
||||
} catch (TimeoutException t) {
|
||||
throw t;
|
||||
} catch (Throwable t) {
|
||||
NEIServerUtils.logOnce(
|
||||
t,
|
||||
stackTraces,
|
||||
"Ommiting " + item + ":" + damage + " " + item.getClass().getSimpleName(),
|
||||
item.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private String getTooltip(ItemStack stack) {
|
||||
try {
|
||||
return String.join("\n", stack.getTooltip(Minecraft.getMinecraft().thePlayer, false));
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private void updateOrdering(List<ItemStack> items) {
|
||||
final Map<ItemStack, Integer> newOrdering = new HashMap<>();
|
||||
ItemSorter.sort(items);
|
||||
|
||||
if (!CollapsibleItems.isEmpty()) {
|
||||
final HashMap<Integer, Integer> groups = new HashMap<>();
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
final int groupIndex = CollapsibleItems.getGroupIndex(stack);
|
||||
|
||||
if (groupIndex == -1) {
|
||||
newOrdering.put(stack, orderIndex++);
|
||||
} else {
|
||||
|
||||
if (!groups.containsKey(groupIndex)) {
|
||||
groups.put(groupIndex, orderIndex++);
|
||||
}
|
||||
|
||||
newOrdering.put(stack, groups.get(groupIndex));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
newOrdering.put(stack, orderIndex++);
|
||||
}
|
||||
}
|
||||
|
||||
ItemList.ordering = newOrdering;
|
||||
}
|
||||
|
||||
private List<ItemStack> getPermutations(Item item) {
|
||||
final List<ItemStack> permutations = new LinkedList<>(ItemInfo.itemOverrides.get(item));
|
||||
|
||||
if (permutations.isEmpty()) {
|
||||
item.getSubItems(item, null, permutations);
|
||||
}
|
||||
|
||||
if (permutations.isEmpty()) {
|
||||
damageSearch(item, permutations);
|
||||
}
|
||||
|
||||
permutations.addAll(ItemInfo.itemVariants.get(item));
|
||||
|
||||
return permutations.stream()
|
||||
.filter(
|
||||
stack -> stack.getItem() != null && stack.getItem().delegate.name() != null
|
||||
&& !ItemInfo.isHidden(stack))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void runChecked(ItemStack stack, Runnable action, String reason) {
|
||||
int hashOld = 0;
|
||||
if (stack.hasTagCompound()) {
|
||||
hashOld = stack.stackTagCompound.hashCode();
|
||||
}
|
||||
|
||||
action.run();
|
||||
|
||||
if (stack.hasTagCompound() && hashOld != stack.stackTagCompound.hashCode()) {
|
||||
FMLLog.warning(
|
||||
"NEI: Forced tag update with reason (" + reason
|
||||
+ ") for "
|
||||
+ stack
|
||||
+ "("
|
||||
+ stack.getItem()
|
||||
+ ")");
|
||||
}
|
||||
}
|
||||
|
||||
private void forceTagCompoundInitialization(ItemStack stack) {
|
||||
Item item = stack.getItem();
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
if (item instanceof IFluidContainerItem) {
|
||||
IFluidContainerItem fluidItem = (IFluidContainerItem) item;
|
||||
runChecked(stack, () -> fluidItem.getFluid(stack), "getFluid");
|
||||
}
|
||||
runChecked(stack, () -> item.isDamaged(stack), "isDamaged");
|
||||
runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
||||
runChecked(stack, () -> item.showDurabilityBar(stack), "showDurabilityBar");
|
||||
runChecked(stack, () -> item.getAttributeModifiers(stack), "getAttributeModifiers");
|
||||
runChecked(stack, () -> item.getDurabilityForDisplay(stack), "getDurabilityForDisplay");
|
||||
runChecked(stack, () -> item.getItemStackLimit(stack), "getItemStackLimit");
|
||||
runChecked(stack, () -> item.getToolClasses(stack), "getToolClasses");
|
||||
runChecked(stack, () -> item.getUnlocalizedNameInefficiently(stack), "getUnlocalizedNameInefficiently");
|
||||
runChecked(stack, () -> item.hasEffect(stack), "hasEffect");
|
||||
runChecked(stack, () -> item.getDigSpeed(stack, Blocks.stone, 0), "getDigSpeed");
|
||||
|
||||
/*
|
||||
* unused... for now runChecked(stack, () -> GameRegistry.getFuelValue(stack), "getFuelValue");
|
||||
* runChecked(stack, () -> item.getUnlocalizedName(stack), "getUnlocalizedName"); runChecked(stack, () ->
|
||||
* item.doesContainerItemLeaveCraftingGrid(stack), "doesContainerItemLeaveCraftingGrid"); runChecked(stack,
|
||||
* () -> item.getItemUseAction(stack), "getItemUseAction"); runChecked(stack, () ->
|
||||
* item.getMaxItemUseDuration(stack), "getMaxItemUseDuration"); runChecked(stack, () ->
|
||||
* item.getPotionEffect(stack), "getPotionEffect"); runChecked(stack, () -> item.isPotionIngredient(stack),
|
||||
* "isPotionIngredient"); runChecked(stack, () -> item.getRarity(stack), "getRarity"); runChecked(stack, ()
|
||||
* -> item.hasCustomEntity(stack), "hasCustomEntity"); runChecked(stack, () ->
|
||||
* item.getSmeltingExperience(stack), "getSmeltingExperience"); runChecked(stack, () ->
|
||||
* item.getMaxDamage(stack), "getMaxDamage"); runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
||||
* runChecked(stack, stack::isItemDamaged, "isItemDamaged"); runChecked(stack, () -> item.hasEffect(stack,
|
||||
* 0), "hasEffect"); runChecked(stack, () -> item.getItemEnchantability(stack), "getItemEnchantability");
|
||||
* runChecked(stack, () -> item.isBeaconPayment(stack), "isBeaconPayment"); runChecked(stack, () ->
|
||||
* item.getDamage(stack), "getDamage"); runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
||||
* runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
||||
*/
|
||||
}
|
||||
|
||||
// Generate itemlist, permutations, orders, collapsibleitems, and informationhandler stacks
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void execute() {
|
||||
if (!NEIClientConfig.isEnabled() || NEIClientUtils.mc().thePlayer == null) return;
|
||||
|
||||
ThreadOperationTimer timer = getTimer(NEIClientConfig.getItemLoadingTimeout());
|
||||
LayoutManager.itemsLoaded = true;
|
||||
loadFinished = false;
|
||||
|
||||
SearchField.searchParser.clearCache();
|
||||
ItemSorter.instance.ordering.clear();
|
||||
CollapsibleItems.clearCache();
|
||||
TooltipFilter.clearCache();
|
||||
InformationHandler.clearCache();
|
||||
|
||||
List<ItemStack> items = new ArrayList<>();
|
||||
ListMultimap<Item, ItemStack> itemMap = ArrayListMultimap.create();
|
||||
ItemStackSet unique = new ItemStackSet();
|
||||
|
||||
StreamSupport.stream(((Iterable<Item>) Item.itemRegistry).spliterator(), true).forEach(item -> {
|
||||
if (item == null || item.delegate.name() == null || erroredItems.contains(item)) return;
|
||||
|
||||
try {
|
||||
timer.reset(item);
|
||||
List<ItemStack> permutations = getPermutations(item);
|
||||
timer.reset();
|
||||
|
||||
for (ItemStack stack : permutations) {
|
||||
if (!unique.contains(stack)) {
|
||||
|
||||
synchronized (unique) {
|
||||
unique.add(stack);
|
||||
}
|
||||
|
||||
synchronized (items) {
|
||||
items.add(stack);
|
||||
}
|
||||
|
||||
forceTagCompoundInitialization(stack);
|
||||
|
||||
CollapsibleItems.putItem(stack);
|
||||
TooltipFilter.getSearchTooltip(stack);
|
||||
InformationHandler.populateStacks(stack);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (itemMap) {
|
||||
itemMap.putAll(item, permutations);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
NEIServerConfig.logger.error("Removing item: {} from list.", item, t);
|
||||
erroredItems.add(item);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
int index = 0;
|
||||
for (Item item : (Iterable<Item>) Item.itemRegistry) {
|
||||
for (ItemStack stack : itemMap.get(item)) {
|
||||
ItemSorter.instance.ordering.put(stack, index++);
|
||||
}
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemList.items = items;
|
||||
ItemList.itemMap = itemMap;
|
||||
for (ItemsLoadedCallback callback : loadCallbacks) callback.itemsLoaded();
|
||||
|
||||
if (interrupted()) return;
|
||||
updateOrdering(ItemList.items);
|
||||
|
||||
loadFinished = true;
|
||||
|
||||
RepairRecipeHandler.findRepairRecipesOnceParallel();
|
||||
RecipeHandlerRef.clearCache();
|
||||
FavoriteRecipes.reload();
|
||||
SubsetWidget.updateHiddenItems();
|
||||
ItemPanels.bookmarkPanel.load();
|
||||
updateFilter.restart();
|
||||
}
|
||||
};
|
||||
|
||||
public static ForkJoinPool forkJoinPool;
|
||||
|
||||
static {
|
||||
@@ -462,35 +225,12 @@ public class ItemList {
|
||||
forkJoinPool = new ForkJoinPool(poolSize, factory, null, false);
|
||||
}
|
||||
|
||||
public static final RestartableTask updateFilter = new RestartableTask("NEI Item Filtering") {
|
||||
// The item list pipeline lives in ItemListLoader; these references are kept for backward compatibility.
|
||||
public static final RestartableTask loadItems = ItemListLoader.loadItems;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
public static final RestartableTask refreshItems = ItemListLoader.refreshItems;
|
||||
|
||||
if (!loadFinished) return;
|
||||
ItemFilter filter = getItemListFilter();
|
||||
ArrayList<ItemStack> filtered;
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool.submit(
|
||||
() -> items.parallelStream().filter(filter::matches)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
filtered = new ArrayList<>();
|
||||
e.printStackTrace();
|
||||
stop();
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
|
||||
filtered.sort(Comparator.comparingInt(ItemList.ordering::get));
|
||||
|
||||
if (interrupted()) return;
|
||||
|
||||
ItemPanel.updateItemList(filtered);
|
||||
}
|
||||
};
|
||||
public static final RestartableTask updateFilter = ItemListLoader.updateFilter;
|
||||
|
||||
/**
|
||||
* @deprecated Use updateFilter.restart()
|
||||
|
||||
@@ -0,0 +1,376 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraftforge.fluids.IFluidContainerItem;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
|
||||
import codechicken.nei.ItemList.ItemsLoadedCallback;
|
||||
import codechicken.nei.ThreadOperationTimer.TimeoutException;
|
||||
import codechicken.nei.api.ItemFilter;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.recipe.InformationHandler;
|
||||
import codechicken.nei.recipe.RecipeHandlerRef;
|
||||
import codechicken.nei.recipe.RepairRecipeHandler;
|
||||
import codechicken.nei.search.TooltipFilter;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
|
||||
public class ItemListLoader {
|
||||
|
||||
private static final HashSet<Item> erroredItems = new HashSet<>();
|
||||
private static final HashSet<String> stackTraces = new HashSet<>();
|
||||
private static Map<ItemStack, Integer> ordering = new HashMap<>();
|
||||
|
||||
private ItemListLoader() {}
|
||||
|
||||
private static void damageSearch(Item item, List<ItemStack> permutations) {
|
||||
final Set<String> damageIconSet = new HashSet<>();
|
||||
final EntityPlayer player = Minecraft.getMinecraft().thePlayer;
|
||||
|
||||
for (int damage = 0; damage < 16; damage++) {
|
||||
try {
|
||||
final ItemStack itemstack = new ItemStack(item, 1, damage);
|
||||
final IIcon icon = item.getIconIndex(itemstack);
|
||||
final String key = itemstack.getDisplayName() + "@"
|
||||
+ (icon == null ? 0 : icon.hashCode())
|
||||
+ "@"
|
||||
+ getInformation(itemstack, player);
|
||||
|
||||
if (damageIconSet.add(key)) {
|
||||
permutations.add(itemstack);
|
||||
}
|
||||
} catch (TimeoutException t) {
|
||||
throw t;
|
||||
} catch (Throwable t) {
|
||||
NEIServerUtils.logOnce(
|
||||
t,
|
||||
stackTraces,
|
||||
"Ommiting " + item + ":" + damage + " " + item.getClass().getSimpleName(),
|
||||
item.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getInformation(ItemStack stack, EntityPlayer player) {
|
||||
try {
|
||||
final List<String> tooltip = new ArrayList<>();
|
||||
stack.getItem().addInformation(stack, player, tooltip, false);
|
||||
return String.join("\n", tooltip);
|
||||
} catch (Throwable ignored) {}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
private static void updateOrdering(List<ItemStack> items) {
|
||||
final Map<ItemStack, Integer> newOrdering = new HashMap<>();
|
||||
|
||||
if (!CollapsibleItems.isEmpty()) {
|
||||
final HashMap<Integer, Integer> groups = new HashMap<>();
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
final int groupIndex = CollapsibleItems.getGroupIndex(stack);
|
||||
|
||||
if (groupIndex == -1) {
|
||||
newOrdering.put(stack, orderIndex++);
|
||||
} else {
|
||||
|
||||
if (!groups.containsKey(groupIndex)) {
|
||||
groups.put(groupIndex, orderIndex++);
|
||||
}
|
||||
|
||||
newOrdering.put(stack, groups.get(groupIndex));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int orderIndex = 0;
|
||||
|
||||
for (ItemStack stack : items) {
|
||||
newOrdering.put(stack, orderIndex++);
|
||||
}
|
||||
}
|
||||
|
||||
ordering = newOrdering;
|
||||
}
|
||||
|
||||
private static List<ItemStack> getPermutations(Item item) {
|
||||
final List<ItemStack> permutations = new LinkedList<>(ItemInfo.itemOverrides.get(item));
|
||||
|
||||
if (permutations.isEmpty()) {
|
||||
item.getSubItems(item, null, permutations);
|
||||
}
|
||||
|
||||
if (permutations.isEmpty()) {
|
||||
damageSearch(item, permutations);
|
||||
}
|
||||
|
||||
permutations.addAll(ItemInfo.itemVariants.get(item));
|
||||
|
||||
return permutations.stream()
|
||||
.filter(
|
||||
stack -> stack.getItem() != null && stack.getItem().delegate.name() != null
|
||||
&& !ItemInfo.isHidden(stack))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static void runChecked(ItemStack stack, Runnable action, String reason) {
|
||||
int hashOld = 0;
|
||||
if (stack.hasTagCompound()) {
|
||||
hashOld = stack.stackTagCompound.hashCode();
|
||||
}
|
||||
|
||||
action.run();
|
||||
|
||||
if (stack.hasTagCompound() && hashOld != stack.stackTagCompound.hashCode()) {
|
||||
FMLLog.warning(
|
||||
"NEI: Forced tag update with reason (" + reason + ") for " + stack + "(" + stack.getItem() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
private static void forceTagCompoundInitialization(ItemStack stack) {
|
||||
Item item = stack.getItem();
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
if (item instanceof IFluidContainerItem) {
|
||||
IFluidContainerItem fluidItem = (IFluidContainerItem) item;
|
||||
runChecked(stack, () -> fluidItem.getFluid(stack), "getFluid");
|
||||
}
|
||||
runChecked(stack, () -> item.isDamaged(stack), "isDamaged");
|
||||
runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
||||
runChecked(stack, () -> item.showDurabilityBar(stack), "showDurabilityBar");
|
||||
runChecked(stack, () -> item.getAttributeModifiers(stack), "getAttributeModifiers");
|
||||
runChecked(stack, () -> item.getDurabilityForDisplay(stack), "getDurabilityForDisplay");
|
||||
runChecked(stack, () -> item.getItemStackLimit(stack), "getItemStackLimit");
|
||||
runChecked(stack, () -> item.getToolClasses(stack), "getToolClasses");
|
||||
runChecked(stack, () -> item.getUnlocalizedNameInefficiently(stack), "getUnlocalizedNameInefficiently");
|
||||
runChecked(stack, () -> item.hasEffect(stack), "hasEffect");
|
||||
runChecked(stack, () -> item.getDigSpeed(stack, Blocks.stone, 0), "getDigSpeed");
|
||||
|
||||
/*
|
||||
* unused... for now runChecked(stack, () -> GameRegistry.getFuelValue(stack), "getFuelValue");
|
||||
* runChecked(stack, () -> item.getUnlocalizedName(stack), "getUnlocalizedName"); runChecked(stack, () ->
|
||||
* item.doesContainerItemLeaveCraftingGrid(stack), "doesContainerItemLeaveCraftingGrid"); runChecked(stack, ()
|
||||
* -> item.getItemUseAction(stack), "getItemUseAction"); runChecked(stack, () ->
|
||||
* item.getMaxItemUseDuration(stack), "getMaxItemUseDuration"); runChecked(stack, () ->
|
||||
* item.getPotionEffect(stack), "getPotionEffect"); runChecked(stack, () -> item.isPotionIngredient(stack),
|
||||
* "isPotionIngredient"); runChecked(stack, () -> item.getRarity(stack), "getRarity"); runChecked(stack, () ->
|
||||
* item.hasCustomEntity(stack), "hasCustomEntity"); runChecked(stack, () -> item.getSmeltingExperience(stack),
|
||||
* "getSmeltingExperience"); runChecked(stack, () -> item.getMaxDamage(stack), "getMaxDamage");
|
||||
* runChecked(stack, () -> item.getDamage(stack), "getDamage"); runChecked(stack, stack::isItemDamaged,
|
||||
* "isItemDamaged"); runChecked(stack, () -> item.hasEffect(stack, 0), "hasEffect"); runChecked(stack, () ->
|
||||
* item.getItemEnchantability(stack), "getItemEnchantability"); runChecked(stack, () ->
|
||||
* item.isBeaconPayment(stack), "isBeaconPayment"); runChecked(stack, () -> item.getDamage(stack), "getDamage");
|
||||
* runChecked(stack, () -> item.getDamage(stack), "getDamage"); runChecked(stack, () -> item.getDamage(stack),
|
||||
* "getDamage");
|
||||
*/
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<ItemStack> gatherItems(ThreadOperationTimer timer) {
|
||||
ItemSorter.instance.ordering.clear();
|
||||
|
||||
List<ItemStack> items = new ArrayList<>();
|
||||
ListMultimap<Item, ItemStack> itemMap = ArrayListMultimap.create();
|
||||
ItemStackSet unique = new ItemStackSet();
|
||||
|
||||
final List<Item> registryItems = new ArrayList<>();
|
||||
for (Item item : (Iterable<Item>) Item.itemRegistry) registryItems.add(item);
|
||||
|
||||
registryItems.parallelStream().forEach(item -> {
|
||||
if (item == null || item.delegate.name() == null || erroredItems.contains(item)) return;
|
||||
|
||||
try {
|
||||
timer.reset(item);
|
||||
List<ItemStack> permutations = getPermutations(item);
|
||||
timer.reset();
|
||||
|
||||
synchronized (itemMap) {
|
||||
itemMap.putAll(item, permutations);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
NEIServerConfig.logger.error(
|
||||
"Removing item: {} from list.\n{}: {}",
|
||||
item,
|
||||
t.getMessage(),
|
||||
Throwables.getStackTraceAsString(t));
|
||||
erroredItems.add(item);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
int index = 0;
|
||||
for (Item item : (Iterable<Item>) Item.itemRegistry) {
|
||||
for (ItemStack stack : itemMap.get(item)) {
|
||||
ItemSorter.instance.ordering.put(stack, index++);
|
||||
|
||||
if (!unique.contains(stack)) {
|
||||
unique.add(stack);
|
||||
items.add(stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ItemList.itemMap = itemMap;
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
private static void buildItemCaches(List<ItemStack> items) {
|
||||
SearchField.searchParser.clearCache();
|
||||
TooltipFilter.clearCache();
|
||||
InformationHandler.clearCache();
|
||||
|
||||
items.parallelStream().forEach(stack -> {
|
||||
try {
|
||||
forceTagCompoundInitialization(stack);
|
||||
InformationHandler.populateStacks(stack);
|
||||
} catch (Throwable t) {
|
||||
NEIServerConfig.logger.error(
|
||||
"Failed to build caches for: {}\n{}: {}",
|
||||
stack,
|
||||
t.getMessage(),
|
||||
Throwables.getStackTraceAsString(t));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void indexCollapsibleItems(List<ItemStack> items) {
|
||||
CollapsibleItems.clearCache();
|
||||
items.parallelStream().forEach(CollapsibleItems::putItem);
|
||||
}
|
||||
|
||||
public static final RestartableTask loadItems = new RestartableTask("NEI Item Loading") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
if (!NEIClientConfig.isEnabled() || NEIClientUtils.mc().thePlayer == null) return;
|
||||
|
||||
final ThreadOperationTimer timer = getTimer(NEIClientConfig.getItemLoadingTimeout());
|
||||
LayoutManager.itemsLoaded = true;
|
||||
ItemList.loadFinished = false;
|
||||
warmTooltips.stop();
|
||||
|
||||
List<ItemStack> items = gatherItems(timer);
|
||||
|
||||
if (interrupted()) return;
|
||||
buildItemCaches(items);
|
||||
indexCollapsibleItems(items);
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemSorter.sort(items);
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemList.items = items;
|
||||
for (ItemsLoadedCallback callback : ItemList.loadCallbacks) callback.itemsLoaded();
|
||||
|
||||
if (interrupted()) return;
|
||||
updateOrdering(ItemList.items);
|
||||
|
||||
ItemList.loadFinished = true;
|
||||
|
||||
RepairRecipeHandler.findRepairRecipesOnceParallel();
|
||||
RecipeHandlerRef.clearCache();
|
||||
FavoriteRecipes.reload();
|
||||
SubsetWidget.updateHiddenItems();
|
||||
updateFilter.restart();
|
||||
warmTooltips.restart();
|
||||
loadBookmarks.restart();
|
||||
}
|
||||
};
|
||||
|
||||
public static final RestartableTask warmTooltips = new RestartableTask("NEI Tooltip Caching") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
if (!ItemList.loadFinished) return;
|
||||
// Use the common pool, not ItemList.forkJoinPool, so it does not queue behind updateFilter.
|
||||
ItemList.items.parallelStream().forEach(stack -> {
|
||||
if (interrupted()) return;
|
||||
try {
|
||||
TooltipFilter.getSearchTooltip(stack);
|
||||
} catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
public static final RestartableTask loadBookmarks = new RestartableTask("NEI Bookmark Loading") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ItemPanels.bookmarkPanel.load();
|
||||
}
|
||||
};
|
||||
|
||||
public static final RestartableTask refreshItems = new RestartableTask("NEI Item Reordering") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
if (!ItemList.loadFinished) return;
|
||||
|
||||
final List<ItemStack> items = new ArrayList<>(ItemList.items);
|
||||
|
||||
indexCollapsibleItems(items);
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemSorter.sort(items);
|
||||
|
||||
if (interrupted()) return;
|
||||
ItemList.items = items;
|
||||
updateOrdering(ItemList.items);
|
||||
|
||||
FavoriteRecipes.reload();
|
||||
SubsetWidget.updateHiddenItems();
|
||||
updateFilter.restart();
|
||||
loadBookmarks.restart();
|
||||
}
|
||||
};
|
||||
|
||||
public static final RestartableTask updateFilter = new RestartableTask("NEI Item Filtering") {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
|
||||
if (!ItemList.loadFinished) return;
|
||||
ItemFilter filter = ItemList.getItemListFilter();
|
||||
ArrayList<ItemStack> filtered;
|
||||
|
||||
try {
|
||||
filtered = ItemList.forkJoinPool.submit(
|
||||
() -> ItemList.items.parallelStream().filter(filter::matches)
|
||||
.collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
filtered = new ArrayList<>();
|
||||
e.printStackTrace();
|
||||
stop();
|
||||
}
|
||||
|
||||
if (interrupted()) return;
|
||||
|
||||
filtered.sort(Comparator.comparingInt(ordering::get));
|
||||
|
||||
if (interrupted()) return;
|
||||
|
||||
ItemPanel.updateItemList(filtered);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class ItemZoom extends Widget implements IContainerInputHandler {
|
||||
|
||||
if (this.stack != null && this.availableAreaWidth >= SLOT_SIZE * 2
|
||||
&& (NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled")
|
||||
|| NEIClientConfig.isKeyHashDown("gui.itemzoom_hold"))
|
||||
|| KeyManager.isHashDown("itemzoom.hold"))
|
||||
&& GuiContainerManager.shouldShowTooltip(NEIClientUtils.getGuiContainer())) {
|
||||
final float inverseScaleFactor = 1.0f / this.scale;
|
||||
final float screenScale = getScreenScale();
|
||||
@@ -74,7 +74,7 @@ public class ItemZoom extends Widget implements IContainerInputHandler {
|
||||
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled")
|
||||
&& NEIClientConfig.getBooleanSetting("inventory.itemzoom.helpText")) {
|
||||
String keyName = NEIClientConfig.getKeyName("gui.itemzoom_toggle");
|
||||
String keyName = KeyManager.getKeyName("itemzoom.toggle", NEIClientUtils.SHIFT_HASH);
|
||||
|
||||
if (keyName != null) {
|
||||
String helpText = NEIClientUtils.translate("itemzoom.toggle", keyName);
|
||||
@@ -198,24 +198,24 @@ public class ItemZoom extends Widget implements IContainerInputHandler {
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.itemzoom_toggle")) {
|
||||
if (KeyManager.isHashDown("itemzoom.toggle", NEIClientUtils.SHIFT_HASH)) {
|
||||
NEIClientConfig.getSetting("inventory.itemzoom.enabled")
|
||||
.setBooleanValue(!NEIClientConfig.getBooleanSetting("inventory.itemzoom.enabled"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_hold")) {
|
||||
if (this.stack != null && KeyManager.isHashDown("itemzoom.hold")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_zoom_in")) {
|
||||
if (this.stack != null && KeyManager.isHashDown("itemzoom.zoom_in")) {
|
||||
increaseZoom(gui);
|
||||
previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && NEIClientConfig.isKeyHashDown("gui.itemzoom_zoom_out")) {
|
||||
if (this.stack != null && KeyManager.isHashDown("itemzoom.zoom_out")) {
|
||||
decreaseZoom(gui);
|
||||
previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
|
||||
@@ -15,6 +15,7 @@ import net.minecraft.client.shader.Framebuffer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.api.GuiInfo;
|
||||
@@ -27,7 +28,7 @@ public abstract class ItemsGrid<T extends ItemsGrid.ItemsGridSlot, M extends Ite
|
||||
protected static class ScreenCapture {
|
||||
|
||||
private long nextCacheRefresh = 0;
|
||||
private Framebuffer framebuffer;
|
||||
private final Framebuffer framebuffer;
|
||||
|
||||
public ScreenCapture() {
|
||||
this.framebuffer = new Framebuffer(1, 1, true);
|
||||
@@ -51,7 +52,7 @@ public abstract class ItemsGrid<T extends ItemsGrid.ItemsGridSlot, M extends Ite
|
||||
}
|
||||
|
||||
public void captureScreen(Runnable callback, int mode) {
|
||||
GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_LIGHTING_BIT);
|
||||
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
|
||||
|
||||
resetFramebuffer();
|
||||
this.framebuffer.bindFramebuffer(false);
|
||||
@@ -84,6 +85,21 @@ public abstract class ItemsGrid<T extends ItemsGrid.ItemsGridSlot, M extends Ite
|
||||
} else {
|
||||
this.framebuffer.framebufferClear();
|
||||
}
|
||||
|
||||
// Copy stencil values (required by mui2)
|
||||
OpenGlHelper.func_153171_g(GL30.GL_READ_FRAMEBUFFER, minecraft.getFramebuffer().framebufferObject);
|
||||
OpenGlHelper.func_153171_g(GL30.GL_DRAW_FRAMEBUFFER, this.framebuffer.framebufferObject);
|
||||
GL30.glBlitFramebuffer(
|
||||
0,
|
||||
0,
|
||||
minecraft.displayWidth,
|
||||
minecraft.displayHeight,
|
||||
0,
|
||||
0,
|
||||
minecraft.displayWidth,
|
||||
minecraft.displayHeight,
|
||||
GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT,
|
||||
GL11.GL_NEAREST);
|
||||
}
|
||||
|
||||
public void renderCapturedScreen() {
|
||||
|
||||
@@ -2,14 +2,19 @@ package codechicken.nei;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import codechicken.nei.util.NEIKeyboardUtils;
|
||||
import codechicken.nei.util.NEIMouseUtils;
|
||||
import cpw.mods.fml.client.registry.ClientRegistry;
|
||||
|
||||
/**
|
||||
* Good old down/held/up keystate tracker
|
||||
* Registers NEI key bindings as vanilla {@link KeyBinding}s and exposes their state to the rest of NEI.
|
||||
*/
|
||||
public class KeyManager {
|
||||
|
||||
@@ -18,33 +23,92 @@ public class KeyManager {
|
||||
public void tickKeyStates();
|
||||
}
|
||||
|
||||
public static class KeyState {
|
||||
|
||||
public boolean down;
|
||||
public boolean held;
|
||||
public boolean up;
|
||||
}
|
||||
|
||||
public static HashMap<String, KeyState> keyStates = new HashMap<>();
|
||||
public static LinkedList<IKeyStateTracker> trackers = new LinkedList<>();
|
||||
|
||||
public static void tickKeyStates() {
|
||||
for (Entry<String, KeyState> entry : keyStates.entrySet()) {
|
||||
final int keyCode = NEIKeyboardUtils.unhash(NEIClientConfig.getKeyBinding(entry.getKey()));
|
||||
final boolean down = keyCode > 0 && keyCode < Keyboard.KEYBOARD_SIZE && Keyboard.isKeyDown(keyCode);
|
||||
final KeyState state = entry.getValue();
|
||||
private static final Map<String, KeyBinding> keyBindings = new HashMap<>();
|
||||
|
||||
if (down) {
|
||||
state.down = !state.held;
|
||||
state.up = false;
|
||||
} else {
|
||||
state.up = state.held;
|
||||
state.down = false;
|
||||
}
|
||||
public static KeyBinding registerKeyBinding(String ident, int defaultKey) {
|
||||
return keyBindings.computeIfAbsent(ident, id -> {
|
||||
final KeyBinding binding = new KeyBinding(
|
||||
"nei.options.keys." + id,
|
||||
NEIKeyboardUtils.unhash(defaultKey),
|
||||
categoryFor(id));
|
||||
ClientRegistry.registerKeyBinding(binding);
|
||||
return binding;
|
||||
});
|
||||
}
|
||||
|
||||
state.held = down;
|
||||
public static KeyBinding getKeyBinding(String ident) {
|
||||
return keyBindings.get(ident);
|
||||
}
|
||||
|
||||
public static int getKeyCode(String ident) {
|
||||
final KeyBinding binding = keyBindings.get(ident);
|
||||
return binding == null ? Keyboard.KEY_NONE : binding.getKeyCode();
|
||||
}
|
||||
|
||||
public static boolean isKeyDown(String ident) {
|
||||
final KeyBinding binding = keyBindings.get(ident);
|
||||
final int keyCode = binding == null ? Keyboard.KEY_NONE : binding.getKeyCode();
|
||||
return keyCode > Keyboard.KEY_NONE && keyCode < Keyboard.KEYBOARD_SIZE && Keyboard.isKeyDown(keyCode);
|
||||
}
|
||||
|
||||
public static boolean isHashDown(String ident) {
|
||||
return isHashDown(ident, 0);
|
||||
}
|
||||
|
||||
public static boolean isHashDown(String ident, int modifierMask) {
|
||||
if (isKeyDown(ident)) {
|
||||
return ((modifierMask & NEIKeyboardUtils.CTRL_HASH) != 0) == NEIClientUtils.controlKey()
|
||||
&& ((modifierMask & NEIKeyboardUtils.SHIFT_HASH) != 0) == NEIClientUtils.shiftKey()
|
||||
&& ((modifierMask & NEIKeyboardUtils.ALT_HASH) != 0) == NEIClientUtils.altKey();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String getKeyName(String ident) {
|
||||
return getKeyName(ident, 0);
|
||||
}
|
||||
|
||||
public static String getKeyName(String ident, int meta) {
|
||||
final int keyCode = getKeyCode(ident);
|
||||
return keyCode == Keyboard.KEY_NONE ? null : NEIKeyboardUtils.getKeyName(keyCode + meta);
|
||||
}
|
||||
|
||||
public static String getKeyName(String ident, int meta, int mouseBind) {
|
||||
final int keyCode = getKeyCode(ident);
|
||||
return keyCode == Keyboard.KEY_NONE && mouseBind == NEIMouseUtils.MOUSE_BTN_NONE ? null
|
||||
: getKeyName(keyCode + meta, mouseBind);
|
||||
}
|
||||
|
||||
public static String getKeyName(int keyBind, int mouseBind) {
|
||||
StringJoiner keyText = new StringJoiner(" + ");
|
||||
String keyHash = keyBind == Keyboard.KEY_NONE ? "" : NEIKeyboardUtils.getKeyName(keyBind);
|
||||
String mouseHash = mouseBind == NEIMouseUtils.MOUSE_BTN_NONE ? "" : NEIMouseUtils.getKeyName(mouseBind);
|
||||
|
||||
if (!keyHash.isEmpty()) {
|
||||
keyText.add(keyHash);
|
||||
}
|
||||
|
||||
if (!mouseHash.isEmpty()) {
|
||||
keyText.add(mouseHash);
|
||||
}
|
||||
|
||||
return keyText.toString();
|
||||
}
|
||||
|
||||
public static boolean isPressed(String ident) {
|
||||
final KeyBinding binding = keyBindings.get(ident);
|
||||
return binding != null && binding.isPressed();
|
||||
}
|
||||
|
||||
private static String categoryFor(String ident) {
|
||||
final int dot = ident.indexOf('.');
|
||||
return dot < 0 ? "nei.options.keys" : "nei.options.keys." + ident.substring(0, dot);
|
||||
}
|
||||
|
||||
public static void tickKeyStates() {
|
||||
for (IKeyStateTracker tracker : trackers) tracker.tickKeyStates();
|
||||
}
|
||||
}
|
||||
@@ -224,17 +224,17 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.hide")) {
|
||||
if (KeyManager.isHashDown("gui.hide")) {
|
||||
toggleBooleanSetting("inventory.hidden");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.hide_bookmarks")) {
|
||||
if (KeyManager.isHashDown("bookmark.hide")) {
|
||||
toggleBooleanSetting("inventory.bookmarks.enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.next_tooltip") && GuiContainerManager.incrementTooltipPage()) {
|
||||
if (KeyManager.isKeyDown("gui.next_tooltip") && GuiContainerManager.incrementTooltipPage()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -941,12 +941,12 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
public void tickKeyStates() {
|
||||
if (Minecraft.getMinecraft().currentScreen != null) return;
|
||||
|
||||
if (KeyManager.keyStates.get("world.dawn").down) timeButtons[0].onButtonPress(false);
|
||||
if (KeyManager.keyStates.get("world.noon").down) timeButtons[1].onButtonPress(false);
|
||||
if (KeyManager.keyStates.get("world.dusk").down) timeButtons[2].onButtonPress(false);
|
||||
if (KeyManager.keyStates.get("world.midnight").down) timeButtons[3].onButtonPress(false);
|
||||
if (KeyManager.keyStates.get("world.rain").down) rain.onButtonPress(false);
|
||||
if (KeyManager.keyStates.get("world.heal").down) heal.onButtonPress(false);
|
||||
if (KeyManager.keyStates.get("world.creative").down) gamemode.onButtonPress(false);
|
||||
if (KeyManager.isPressed("world.dawn")) timeButtons[0].onButtonPress(false);
|
||||
if (KeyManager.isPressed("world.noon")) timeButtons[1].onButtonPress(false);
|
||||
if (KeyManager.isPressed("world.dusk")) timeButtons[2].onButtonPress(false);
|
||||
if (KeyManager.isPressed("world.midnight")) timeButtons[3].onButtonPress(false);
|
||||
if (KeyManager.isPressed("world.rain")) rain.onButtonPress(false);
|
||||
if (KeyManager.isPressed("world.heal")) heal.onButtonPress(false);
|
||||
if (KeyManager.isPressed("world.creative")) gamemode.onButtonPress(false);
|
||||
}
|
||||
}
|
||||
@@ -244,7 +244,11 @@ public class LayoutStyleMinecraft extends LayoutStyle {
|
||||
|
||||
Image icon = b.getRenderIcon();
|
||||
if (icon == null) {
|
||||
int colour = tex == 2 ? 0xffffa0 : tex == 0 ? 0x601010 : 0xe0e0e0;
|
||||
int labelColor = b.getRenderLabelColor();
|
||||
int colour = labelColor != 0 ? labelColor
|
||||
: tex == 2 ? ColorUtils.buttonLabelHover.getColor()
|
||||
: tex == 0 ? ColorUtils.buttonLabelDisabled.getColor()
|
||||
: ColorUtils.buttonLabelNormal.getColor();
|
||||
|
||||
drawStringC(b.getRenderLabel(), b.x + b.w / 2, b.y + (b.h - 8) / 2, colour);
|
||||
} else {
|
||||
|
||||
@@ -54,6 +54,7 @@ public class NEIActions {
|
||||
addAction("magnet", true);
|
||||
addAction("enchant", true);
|
||||
addAction("potion", true);
|
||||
addAction("autocraft");
|
||||
|
||||
canDisable.add("dawn");
|
||||
canDisable.add("noon");
|
||||
|
||||
@@ -61,7 +61,6 @@ import codechicken.nei.recipe.IRecipeHandler;
|
||||
import codechicken.nei.recipe.InformationHandler;
|
||||
import codechicken.nei.recipe.RecipeCatalysts;
|
||||
import codechicken.nei.util.ItemUntranslator;
|
||||
import codechicken.nei.util.NEIKeyboardUtils;
|
||||
import codechicken.obfuscator.ObfuscationRun;
|
||||
|
||||
public class NEIClientConfig {
|
||||
@@ -263,6 +262,10 @@ public class NEIClientConfig {
|
||||
.setComment("Require holding shift to move items when overlaying recipe").getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.shiftOverlayRecipe", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.scrollPages").setComment("Disable page scroll when overlaying recipe")
|
||||
.getBooleanValue(true);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.scrollPages", true));
|
||||
|
||||
tag.getTag("inventory.guirecipe.profile").getBooleanValue(false);
|
||||
API.addOption(new OptionToggleButton("inventory.guirecipe.profile", true));
|
||||
|
||||
@@ -307,7 +310,7 @@ public class NEIClientConfig {
|
||||
super.onClick(button);
|
||||
CollapsibleItems.saveStates();
|
||||
CollapsibleItems.load();
|
||||
LayoutManager.markItemsDirty();
|
||||
ItemList.refreshItems.restart();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -811,35 +814,37 @@ public class NEIClientConfig {
|
||||
}
|
||||
|
||||
private static void setDefaultKeyBindings() {
|
||||
API.addHashBind("gui.recipe", Keyboard.KEY_R);
|
||||
API.addHashBind("gui.usage", Keyboard.KEY_U);
|
||||
API.addKeyBind("gui.back", Keyboard.KEY_BACK);
|
||||
API.addHashBind("gui.enchant", Keyboard.KEY_X);
|
||||
API.addHashBind("gui.potion", Keyboard.KEY_P);
|
||||
API.addKeyBind("gui.enchant", Keyboard.KEY_X);
|
||||
API.addKeyBind("gui.potion", Keyboard.KEY_P);
|
||||
API.addKeyBind("gui.prev", Keyboard.KEY_PRIOR);
|
||||
API.addKeyBind("gui.next", Keyboard.KEY_NEXT);
|
||||
API.addKeyBind("gui.prev_machine", Keyboard.KEY_UP);
|
||||
API.addKeyBind("gui.next_machine", Keyboard.KEY_DOWN);
|
||||
API.addKeyBind("gui.prev_recipe", Keyboard.KEY_LEFT);
|
||||
API.addKeyBind("gui.next_recipe", Keyboard.KEY_RIGHT);
|
||||
API.addHashBind("gui.hide", Keyboard.KEY_O);
|
||||
API.addHashBind("gui.search", Keyboard.KEY_F);
|
||||
API.addKeyBind("gui.bookmark", Keyboard.KEY_A);
|
||||
API.addHashBind("gui.favorite", Keyboard.KEY_F + NEIClientUtils.SHIFT_HASH);
|
||||
API.addKeyBind("gui.favorite_item", Keyboard.KEY_F);
|
||||
API.addHashBind("gui.remove_recipe", Keyboard.KEY_A + NEIClientUtils.SHIFT_HASH);
|
||||
API.addKeyBind("gui.bookmark_pull_items", Keyboard.KEY_V);
|
||||
API.addKeyBind("gui.hide", Keyboard.KEY_O);
|
||||
API.addKeyBind("gui.search", Keyboard.KEY_F);
|
||||
API.addKeyBind("gui.overlay", Keyboard.KEY_S);
|
||||
API.addKeyBind("gui.craft_items", Keyboard.KEY_C);
|
||||
API.addHashBind("gui.hide_bookmarks", Keyboard.KEY_B);
|
||||
API.addKeyBind("gui.getprevioussearch", Keyboard.KEY_UP);
|
||||
API.addKeyBind("gui.getnextsearch", Keyboard.KEY_DOWN);
|
||||
API.addKeyBind("gui.next_tooltip", Keyboard.KEY_Z);
|
||||
|
||||
API.addHashBind("gui.itemzoom_toggle", Keyboard.KEY_Z + NEIClientUtils.SHIFT_HASH);
|
||||
API.addHashBind("gui.itemzoom_hold", 0);
|
||||
API.addHashBind("gui.itemzoom_zoom_in", 0);
|
||||
API.addHashBind("gui.itemzoom_zoom_out", 0);
|
||||
API.addKeyBind("recipe.recipe", Keyboard.KEY_R);
|
||||
API.addKeyBind("recipe.usage", Keyboard.KEY_U);
|
||||
API.addKeyBind("recipe.back", Keyboard.KEY_BACK);
|
||||
API.addKeyBind("recipe.prev_machine", Keyboard.KEY_UP);
|
||||
API.addKeyBind("recipe.next_machine", Keyboard.KEY_DOWN);
|
||||
API.addKeyBind("recipe.prev_recipe", Keyboard.KEY_LEFT);
|
||||
API.addKeyBind("recipe.next_recipe", Keyboard.KEY_RIGHT);
|
||||
|
||||
API.addKeyBind("bookmark.add", Keyboard.KEY_A);
|
||||
API.addKeyBind("bookmark.favorite", Keyboard.KEY_F);
|
||||
API.addKeyBind("bookmark.favorite_item", Keyboard.KEY_F);
|
||||
API.addKeyBind("bookmark.remove_recipe", Keyboard.KEY_A);
|
||||
API.addKeyBind("bookmark.pull_items", Keyboard.KEY_V);
|
||||
API.addKeyBind("bookmark.hide", Keyboard.KEY_B);
|
||||
|
||||
API.addKeyBind("itemzoom.toggle", Keyboard.KEY_Z);
|
||||
API.addKeyBind("itemzoom.hold", 0);
|
||||
API.addKeyBind("itemzoom.zoom_in", 0);
|
||||
API.addKeyBind("itemzoom.zoom_out", 0);
|
||||
|
||||
API.addKeyBind("world.chunkoverlay", Keyboard.KEY_F9);
|
||||
API.addKeyBind("world.moboverlay", Keyboard.KEY_F7);
|
||||
@@ -851,10 +856,11 @@ public class NEIClientConfig {
|
||||
API.addKeyBind("world.rain", 0);
|
||||
API.addKeyBind("world.heal", 0);
|
||||
API.addKeyBind("world.creative", 0);
|
||||
API.addHashBind("gui.copy_name", Keyboard.KEY_C + NEIClientUtils.CTRL_HASH);
|
||||
API.addHashBind("gui.copy_oredict", Keyboard.KEY_D + NEIClientUtils.CTRL_HASH);
|
||||
API.addHashBind("gui.copy_id", Keyboard.KEY_X + NEIClientUtils.CTRL_HASH);
|
||||
API.addHashBind("gui.chat_link_item", Keyboard.KEY_L + NEIClientUtils.CTRL_HASH);
|
||||
|
||||
API.addKeyBind("copy.name", Keyboard.KEY_C);
|
||||
API.addKeyBind("copy.oredict", Keyboard.KEY_D);
|
||||
API.addKeyBind("copy.identifier", Keyboard.KEY_X);
|
||||
API.addKeyBind("copy.chat_link_item", Keyboard.KEY_L);
|
||||
}
|
||||
|
||||
public static OptionList getOptionList() {
|
||||
@@ -925,50 +931,28 @@ public class NEIClientConfig {
|
||||
world.saveNBT();
|
||||
}
|
||||
|
||||
private static final Map<String, String> keySettings = new HashMap<>();
|
||||
|
||||
public static int getKeyBinding(String string) {
|
||||
final String key = keySettings.computeIfAbsent(string, s -> "keys." + s);
|
||||
return getSetting(key).getIntValue(Keyboard.KEY_NONE);
|
||||
return KeyManager.getKeyCode(string);
|
||||
}
|
||||
|
||||
public static void setDefaultKeyBinding(String string, int key) {
|
||||
getSetting("keys." + string).getIntValue(key);
|
||||
KeyManager.registerKeyBinding(string, key);
|
||||
}
|
||||
|
||||
public static boolean isKeyHashDown(String string) {
|
||||
final int hash = getKeyBinding(string);
|
||||
|
||||
if (hash != Keyboard.CHAR_NONE && Keyboard.getEventKeyState()) {
|
||||
return KeyManager.keyStates.containsKey(string) ? Keyboard.isKeyDown(NEIKeyboardUtils.unhash(hash))
|
||||
: hash == NEIClientUtils.getKeyHash();
|
||||
}
|
||||
|
||||
return false;
|
||||
return KeyManager.isHashDown(string);
|
||||
}
|
||||
|
||||
public static String getKeyName(String keyBind) {
|
||||
return getKeyName(keyBind, 0);
|
||||
return KeyManager.getKeyName(keyBind);
|
||||
}
|
||||
|
||||
public static String getKeyName(String keyBind, int meta, int mouseBind) {
|
||||
final int hash = getKeyBinding(keyBind);
|
||||
|
||||
if (hash == Keyboard.CHAR_NONE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return NEIClientUtils.getKeyName(hash + meta, mouseBind);
|
||||
return KeyManager.getKeyName(keyBind, meta, mouseBind);
|
||||
}
|
||||
|
||||
public static String getKeyName(String keyBind, int meta) {
|
||||
final int hash = getKeyBinding(keyBind);
|
||||
|
||||
if (hash == Keyboard.CHAR_NONE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return NEIKeyboardUtils.getKeyName(hash + meta);
|
||||
return KeyManager.getKeyName(keyBind, meta);
|
||||
}
|
||||
|
||||
public static void bootNEI() {
|
||||
@@ -1021,7 +1005,11 @@ public class NEIClientConfig {
|
||||
}.start();
|
||||
} else {
|
||||
SubsetWidget.loadHidden();
|
||||
ItemList.loadItems.restart();
|
||||
if (ItemList.loadFinished) {
|
||||
ItemList.refreshItems.restart();
|
||||
} else {
|
||||
ItemList.loadItems.restart();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1045,7 +1033,9 @@ public class NEIClientConfig {
|
||||
}
|
||||
|
||||
public static boolean autocraftingEnabled() {
|
||||
return getBooleanSetting("inventory.autocrafting");
|
||||
if (!getBooleanSetting("inventory.autocrafting")) return false;
|
||||
if (hasSMPCounterpart) return permissableActions.contains("autocraft");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean favoritesEnabled() {
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -57,7 +56,6 @@ import codechicken.nei.api.GuiInfo;
|
||||
import codechicken.nei.api.IInfiniteItemHandler;
|
||||
import codechicken.nei.api.ItemInfo;
|
||||
import codechicken.nei.util.NEIKeyboardUtils;
|
||||
import codechicken.nei.util.NEIMouseUtils;
|
||||
|
||||
public class NEIClientUtils extends NEIServerUtils {
|
||||
|
||||
@@ -95,6 +93,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 +125,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 +134,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 +143,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);
|
||||
}
|
||||
@@ -451,55 +454,8 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
return Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU);
|
||||
}
|
||||
|
||||
public static int getMetaHash() {
|
||||
if (Keyboard.getEventKeyState()) {
|
||||
int hash = 0;
|
||||
|
||||
if (altKey()) {
|
||||
hash = hash | ALT_HASH;
|
||||
}
|
||||
|
||||
if (shiftKey()) {
|
||||
hash = hash | SHIFT_HASH;
|
||||
}
|
||||
|
||||
if (controlKey()) {
|
||||
hash = hash | CTRL_HASH;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static int getKeyHash() {
|
||||
|
||||
if (Keyboard.getEventKeyState()) {
|
||||
final int keycode = Keyboard.getEventKey();
|
||||
|
||||
if (!NEIKeyboardUtils.isHashKey(keycode)) {
|
||||
return getMetaHash() + keycode;
|
||||
}
|
||||
}
|
||||
|
||||
return Keyboard.CHAR_NONE;
|
||||
}
|
||||
|
||||
public static String getKeyName(int keyBind, int mouseBind) {
|
||||
StringJoiner keyText = new StringJoiner(" + ");
|
||||
String keyHash = keyBind == Keyboard.KEY_NONE ? "" : NEIKeyboardUtils.getKeyName(keyBind);
|
||||
String mouseHash = mouseBind == NEIMouseUtils.MOUSE_BTN_NONE ? "" : NEIMouseUtils.getKeyName(mouseBind);
|
||||
|
||||
if (!keyHash.isEmpty()) {
|
||||
keyText.add(keyHash);
|
||||
}
|
||||
|
||||
if (!mouseHash.isEmpty()) {
|
||||
keyText.add(mouseHash);
|
||||
}
|
||||
|
||||
return keyText.toString();
|
||||
return KeyManager.getKeyName(keyBind, mouseBind);
|
||||
}
|
||||
|
||||
public static void playClickSound() {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ public class NEIServerConfig {
|
||||
setDefaultFeature("save-state");
|
||||
setDefaultFeature("item");
|
||||
setDefaultFeature("delete");
|
||||
setDefaultFeature("autocraft", "ALL");
|
||||
setDefaultFeature("notify-item", "CONSOLE, OP");
|
||||
}
|
||||
|
||||
|
||||
@@ -309,12 +309,12 @@ public abstract class PanelWidget<T extends ItemsGrid<? extends ItemsGridSlot, ?
|
||||
final Point mouse = GuiDraw.getMousePosition();
|
||||
if (!contains(mouse.x, mouse.y)) return false;
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.next")) {
|
||||
if (KeyManager.isKeyDown("gui.next")) {
|
||||
this.grid.shiftPage(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.prev")) {
|
||||
if (KeyManager.isKeyDown("gui.prev")) {
|
||||
this.grid.shiftPage(-1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -24,12 +24,12 @@ public class PopupInputHandler implements IContainerInputHandler {
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.enchant") && canPerformAction("enchant")) {
|
||||
if (KeyManager.isHashDown("gui.enchant") && canPerformAction("enchant")) {
|
||||
NEICPH.sendOpenEnchantmentWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.potion") && canPerformAction("potion")) {
|
||||
if (KeyManager.isHashDown("gui.potion") && canPerformAction("potion")) {
|
||||
NEICPH.sendOpenPotionWindow();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ public class PresetsList {
|
||||
updateSubsets();
|
||||
CollapsibleItems.saveStates();
|
||||
CollapsibleItems.load();
|
||||
LayoutManager.markItemsDirty();
|
||||
ItemList.refreshItems.restart();
|
||||
}
|
||||
|
||||
private static void updateSubsets() {
|
||||
|
||||
@@ -50,11 +50,11 @@ public abstract class RecipeSearchField extends TextField implements ItemFilterP
|
||||
@Override
|
||||
public void lastKeyTyped(int keyID, char keyChar) {
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getprevioussearch")) {
|
||||
if (focused() && KeyManager.isKeyDown("gui.getprevioussearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
||||
}
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getnextsearch")) {
|
||||
if (focused() && KeyManager.isKeyDown("gui.getnextsearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,14 +230,14 @@ public class SearchField extends TextField implements ItemFilterProvider {
|
||||
@Override
|
||||
public void lastKeyTyped(int keyID, char keyChar) {
|
||||
|
||||
if (isVisible() && NEIClientConfig.isKeyHashDown("gui.search")) {
|
||||
if (isVisible() && KeyManager.isHashDown("gui.search")) {
|
||||
setFocus(true);
|
||||
}
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getprevioussearch")) {
|
||||
if (focused() && KeyManager.isKeyDown("gui.getprevioussearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
||||
}
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getnextsearch")) {
|
||||
if (focused() && KeyManager.isKeyDown("gui.getnextsearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public class SearchTokenParser {
|
||||
clearCache();
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
public synchronized void clearCache() {
|
||||
this.providersCache.clear();
|
||||
this.filtersCache.clear();
|
||||
this.recipesCache.clear();
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -19,6 +18,7 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.nbt.NBTTagString;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -413,9 +413,10 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* All operations on this variable should be synchronised.
|
||||
* Canonical {@link StackInfo#getItemStackGUID(ItemStack)} of every hidden item, stored by GUID so the state
|
||||
* survives world reloads. All operations should be synchronised.
|
||||
*/
|
||||
private static final ItemStackSet hiddenItems = new ItemStackSet();
|
||||
private static final Set<String> hiddenItems = new HashSet<>();
|
||||
|
||||
private static final Map<String, SubsetTag> tags = new HashMap<>();
|
||||
private static final SubsetTag root = new SubsetTag("");
|
||||
@@ -456,11 +457,16 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
|
||||
}
|
||||
|
||||
public static boolean isHidden(ItemStack item) {
|
||||
final String guid = StackInfo.getItemStackGUID(item);
|
||||
synchronized (hiddenLock) {
|
||||
return hiddenItems.contains(item);
|
||||
return hiddenItems.contains(guid);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> toGUIDs(List<ItemStack> items) {
|
||||
return items.stream().map(StackInfo::getItemStackGUID).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static List<ItemStack> getItems(SubsetTag tag, List<ItemStack> items) {
|
||||
items.addAll(tag.items);
|
||||
|
||||
@@ -472,19 +478,22 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
|
||||
}
|
||||
|
||||
public static void showOnly(SubsetTag tag) {
|
||||
final List<String> allItems = toGUIDs(getItems(root, new ArrayList<>()));
|
||||
final List<String> tagItems = toGUIDs(getItems(tag, new ArrayList<>()));
|
||||
|
||||
synchronized (hiddenLock) {
|
||||
hiddenItems.clear();
|
||||
hiddenItems.addAll(getItems(root, new ArrayList<>()));
|
||||
hiddenItems.removeAll(getItems(tag, new ArrayList<>()));
|
||||
hiddenItems.addAll(allItems);
|
||||
hiddenItems.removeAll(tagItems);
|
||||
}
|
||||
|
||||
calculateVisibility();
|
||||
}
|
||||
|
||||
public static void setHidden(SubsetTag tag, boolean hidden) {
|
||||
synchronized (hiddenLock) {
|
||||
final List<ItemStack> tagItems = getItems(tag, new ArrayList<>());
|
||||
final List<String> tagItems = toGUIDs(getItems(tag, new ArrayList<>()));
|
||||
|
||||
synchronized (hiddenLock) {
|
||||
if (hidden) {
|
||||
hiddenItems.addAll(tagItems);
|
||||
} else {
|
||||
@@ -496,11 +505,13 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
|
||||
}
|
||||
|
||||
public static void setHidden(ItemStack item, boolean hidden) {
|
||||
final String guid = StackInfo.getItemStackGUID(item);
|
||||
|
||||
synchronized (hiddenLock) {
|
||||
if (hidden) {
|
||||
hiddenItems.add(item);
|
||||
hiddenItems.add(guid);
|
||||
} else {
|
||||
hiddenItems.remove(item);
|
||||
hiddenItems.remove(guid);
|
||||
}
|
||||
}
|
||||
calculateVisibility();
|
||||
@@ -582,13 +593,23 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
|
||||
}
|
||||
|
||||
public static void loadHidden() {
|
||||
final List<ItemStack> itemList = new LinkedList<>();
|
||||
final Set<String> guids = new HashSet<>();
|
||||
|
||||
try {
|
||||
final NBTTagList guidList = NEIClientConfig.world.nbt.getTagList("hiddenItems", 8);
|
||||
|
||||
for (int i = 0; i < guidList.tagCount(); i++) {
|
||||
guids.add(guidList.getStringTagAt(i));
|
||||
}
|
||||
|
||||
final NBTTagList list = NEIClientConfig.world.nbt.getTagList("hiddenItems", 10);
|
||||
|
||||
for (int i = 0; i < list.tagCount(); i++) {
|
||||
itemList.add(ItemStack.loadItemStackFromNBT(list.getCompoundTagAt(i)));
|
||||
final ItemStack stack = ItemStack.loadItemStackFromNBT(list.getCompoundTagAt(i));
|
||||
|
||||
if (stack != null) {
|
||||
guids.add(StackInfo.getItemStackGUID(stack));
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger.error("Error loading hiddenItems", e);
|
||||
@@ -597,7 +618,7 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
|
||||
|
||||
synchronized (hiddenLock) {
|
||||
hiddenItems.clear();
|
||||
hiddenItems.addAll(itemList);
|
||||
hiddenItems.addAll(guids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,8 +627,8 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
|
||||
|
||||
final NBTTagList list = new NBTTagList();
|
||||
synchronized (hiddenLock) {
|
||||
for (ItemStack stack : hiddenItems.values()) {
|
||||
list.appendTag(stack.writeToNBT(new NBTTagCompound()));
|
||||
for (String guid : hiddenItems) {
|
||||
list.appendTag(new NBTTagString(guid));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -689,20 +710,17 @@ public class SubsetWidget extends Button implements ItemFilterProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
public int getRenderLabelColor() {
|
||||
return NEIClientConfig.subsetWidgetOnTop() ? 0 : ColorUtils.subsetWidget.getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRenderLabel() {
|
||||
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 String.valueOf(SearchField.searchParser.getRedefinedPrefix(PREFIX));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.entity.Entity;
|
||||
@@ -26,24 +30,23 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
public static int mobOverlay = 0;
|
||||
private static byte[] mobSpawnCache;
|
||||
private static long mobOverlayUpdateTime;
|
||||
private static String oregenPatternName;
|
||||
|
||||
public static void reset() {
|
||||
mobOverlay = 0;
|
||||
chunkOverlay = 0;
|
||||
oregenPatternName = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tickKeyStates() {
|
||||
if (Minecraft.getMinecraft().currentScreen != null) return;
|
||||
|
||||
if (KeyManager.keyStates.get("world.moboverlay").down) {
|
||||
if (KeyManager.isPressed("world.moboverlay")) {
|
||||
mobOverlay = (mobOverlay + 1) % 2;
|
||||
NEIClientUtils
|
||||
.printChatMessage(new ChatComponentText(NEIClientUtils.translate("chat.moboverlay." + mobOverlay)));
|
||||
}
|
||||
if (KeyManager.keyStates.get("world.chunkoverlay").down) {
|
||||
|
||||
if (KeyManager.isPressed("world.chunkoverlay")) {
|
||||
chunkOverlay = (chunkOverlay + 1) % (NEIModContainer.isGT5Loaded() ? 4 : 3);
|
||||
// 0-2 (or 3 with gt)
|
||||
NEIClientUtils.printChatMessage(
|
||||
@@ -377,20 +380,43 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
|
||||
private static Callable<String> oregenPatternReader;
|
||||
|
||||
private static String getOregenPatternName() {
|
||||
|
||||
if (oregenPatternName == null) {
|
||||
try {
|
||||
final ClassLoader loader = WorldOverlayRenderer.class.getClassLoader();
|
||||
final Class<?> gtWorldGenerator = ReflectionHelper
|
||||
.getClass(loader, "gregtech.common.GTWorldgenerator", "gregtech.common.GT_Worldgenerator");
|
||||
oregenPatternName = ((Enum<?>) gtWorldGenerator.getDeclaredField("oregenPattern").get(null)).name();
|
||||
} catch (Exception ignored) {
|
||||
oregenPatternName = "AXISSYMMETRICAL";
|
||||
}
|
||||
if (oregenPatternReader == null) {
|
||||
oregenPatternReader = resolveOregenPatternReader();
|
||||
}
|
||||
try {
|
||||
return oregenPatternReader.call();
|
||||
} catch (Exception ignored) {
|
||||
return "AXISSYMMETRICAL";
|
||||
}
|
||||
}
|
||||
|
||||
return oregenPatternName;
|
||||
private static Callable<String> resolveOregenPatternReader() {
|
||||
try {
|
||||
final Class<?> gtWorldGenerator = ReflectionHelper.getClass(
|
||||
WorldOverlayRenderer.class.getClassLoader(),
|
||||
"gregtech.common.GTWorldgenerator",
|
||||
"gregtech.common.GT_Worldgenerator");
|
||||
|
||||
try {
|
||||
// GT5-Unofficial >= 5.09.54.02 support
|
||||
final Method server = gtWorldGenerator.getMethod("getServerOregenPattern");
|
||||
final Method client = gtWorldGenerator.getMethod("getClientOregenPattern");
|
||||
return () -> {
|
||||
final Method accessor = Minecraft.getMinecraft().isSingleplayer() ? server : client;
|
||||
return ((Enum<?>) accessor.invoke(null)).name();
|
||||
};
|
||||
} catch (NoSuchMethodException legacy) {
|
||||
// Older GT
|
||||
final Field oregenPattern = gtWorldGenerator.getDeclaredField("oregenPattern");
|
||||
oregenPattern.setAccessible(true);
|
||||
return () -> ((Enum<?>) oregenPattern.get(null)).name();
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
return () -> "AXISSYMMETRICAL";
|
||||
}
|
||||
}
|
||||
|
||||
public static void load() {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
@@ -20,7 +22,6 @@ import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemSorter;
|
||||
import codechicken.nei.ItemStackSet;
|
||||
import codechicken.nei.KeyManager;
|
||||
import codechicken.nei.KeyManager.KeyState;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.OffsetPositioner;
|
||||
@@ -32,7 +33,6 @@ import codechicken.nei.SubsetWidget.SubsetTag;
|
||||
import codechicken.nei.api.IRecipeFilter.IRecipeFilterProvider;
|
||||
import codechicken.nei.api.ItemFilter.ItemFilterProvider;
|
||||
import codechicken.nei.config.Option;
|
||||
import codechicken.nei.config.OptionKeyBind;
|
||||
import codechicken.nei.recipe.CatalystInfo;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
@@ -176,6 +176,21 @@ public class API {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an alias name that this item can be found by in the search field, in addition to its display name.
|
||||
*/
|
||||
public static void setAliases(ItemStack item, String... aliases) {
|
||||
final List<String> list = Arrays.asList(aliases).stream().filter(Objects::nonNull).map(String::trim)
|
||||
.filter(s -> !s.isEmpty()).collect(Collectors.toList());
|
||||
|
||||
if (list.isEmpty()) {
|
||||
ItemInfo.itemAliases.remove(item);
|
||||
} else {
|
||||
ItemInfo.itemAliases.put(item, list);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the item panel. Any items added using this function will override the default search pattern.
|
||||
*
|
||||
@@ -206,20 +221,11 @@ public class API {
|
||||
* @param defaultKey The default value, commonly obtained from {@link Keyboard}
|
||||
*/
|
||||
public static void addKeyBind(String ident, int defaultKey) {
|
||||
NEIClientConfig.setDefaultKeyBinding(ident, defaultKey);
|
||||
KeyManager.keyStates.put(ident, new KeyState());
|
||||
addOption(new OptionKeyBind(ident));
|
||||
KeyManager.registerKeyBinding(ident, defaultKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom KeyBinding to be configured in the Controls menu.
|
||||
*
|
||||
* @param ident An identifier for your key, eg "shoot"
|
||||
* @param defaultKey The default value, commonly obtained from {@link Keyboard}
|
||||
*/
|
||||
public static void addHashBind(String ident, int defaultKey) {
|
||||
NEIClientConfig.setDefaultKeyBinding(ident, defaultKey);
|
||||
addOption(new OptionKeyBind(ident, true));
|
||||
KeyManager.registerKeyBinding(ident, defaultKey);
|
||||
}
|
||||
|
||||
public static void addOption(Option option) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.stream.Collectors;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.recipe.GuiOverlayButton.ItemOverlayState;
|
||||
import codechicken.nei.recipe.IRecipeHandler;
|
||||
@@ -32,6 +33,10 @@ public interface IOverlayHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean requireShiftForOverlayRecipe() {
|
||||
return NEIClientConfig.requireShiftForOverlayRecipe();
|
||||
}
|
||||
|
||||
default List<ItemOverlayState> presenceOverlay(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex) {
|
||||
final List<ItemOverlayState> itemPresenceSlots = new ArrayList<>();
|
||||
final List<PositionedStack> ingredients = recipe.getIngredientStacks(recipeIndex);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -84,6 +85,7 @@ public class ItemInfo {
|
||||
|
||||
public static final ArrayListMultimap<Layout, IHighlightHandler> highlightHandlers = ArrayListMultimap.create();
|
||||
public static final ItemStackMap<String> nameOverrides = new ItemStackMap<>();
|
||||
public static final ItemStackMap<List<String>> itemAliases = new ItemStackMap<>();
|
||||
public static final ItemStackSet hiddenItems = new ItemStackSet();
|
||||
public static final AnyMultiItemFilter hiddenItemsRules = new AnyMultiItemFilter();
|
||||
public static final ItemStackSet finiteItems = new ItemStackSet();
|
||||
@@ -109,6 +111,11 @@ public class ItemInfo {
|
||||
return nameOverrides.get(stack);
|
||||
}
|
||||
|
||||
public static List<String> getAliases(ItemStack stack) {
|
||||
final List<String> aliases = itemAliases.get(stack);
|
||||
return aliases != null ? aliases : Collections.emptyList();
|
||||
}
|
||||
|
||||
public static boolean canBeInfinite(ItemStack stack) {
|
||||
return !finiteItems.contains(stack);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.LinkedList;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.config.GuiOptionList;
|
||||
import codechicken.nei.config.OptionCycled;
|
||||
|
||||
public class NEIInfo {
|
||||
@@ -13,7 +14,8 @@ public class NEIInfo {
|
||||
|
||||
public static void load(World world) {
|
||||
OptionCycled modeOption = (OptionCycled) NEIClientConfig.getOptionList().getOption("inventory.cheatmode");
|
||||
modeOption.parent.synthesizeEnvironment(false);
|
||||
// kept alive so the WeakReference in Option.slotRef isn't GC'd before copyGlobals/cycle use it
|
||||
GuiOptionList env = modeOption.parent.synthesizeEnvironment(false);
|
||||
if (!modeOption.optionValid(modeOption.value())) {
|
||||
modeOption.copyGlobals();
|
||||
modeOption.cycle();
|
||||
|
||||
@@ -20,9 +20,11 @@ import codechicken.nei.FavoriteRecipes;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.ItemQuantityField;
|
||||
import codechicken.nei.ItemsGrid.ItemsGridSlot;
|
||||
import codechicken.nei.KeyManager;
|
||||
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;
|
||||
@@ -74,8 +76,7 @@ public abstract class ShortcutInputHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.overlay") && stackover == null
|
||||
&& LayoutManager.overlayRenderer != null) {
|
||||
if (KeyManager.isKeyDown("gui.overlay") && stackover == null && LayoutManager.overlayRenderer != null) {
|
||||
LayoutManager.overlayRenderer = null;
|
||||
return true;
|
||||
}
|
||||
@@ -85,16 +86,16 @@ public abstract class ShortcutInputHandler {
|
||||
|
||||
if (groupId != -1) {
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.remove_recipe")) {
|
||||
if (KeyManager.isHashDown("bookmark.remove_recipe", NEIClientUtils.SHIFT_HASH)) {
|
||||
ItemPanels.bookmarkPanel.removeGroup(groupId);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark_pull_items")) {
|
||||
if (KeyManager.isKeyDown("bookmark.pull_items")) {
|
||||
return ItemPanels.bookmarkPanel.pullBookmarkItems(groupId, NEIClientUtils.shiftKey());
|
||||
}
|
||||
|
||||
if (NEIClientConfig.autocraftingEnabled() && NEIClientConfig.isKeyHashDown("gui.craft_items")
|
||||
if (NEIClientConfig.autocraftingEnabled() && KeyManager.isKeyDown("gui.craft_items")
|
||||
&& NEIClientUtils.shiftKey()
|
||||
&& ItemPanels.bookmarkPanel.getGrid().isCraftingMode(groupId)) {
|
||||
final RecipeChainMath math = ItemPanels.bookmarkPanel.getGrid().createRecipeChainMath(groupId);
|
||||
@@ -117,46 +118,47 @@ public abstract class ShortcutInputHandler {
|
||||
|
||||
stackover = stackover.copy();
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.overlay")) {
|
||||
if (KeyManager.isKeyDown("gui.overlay")) {
|
||||
return openOverlayRecipe(stackover);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.copy_name")) {
|
||||
if (KeyManager.isHashDown("copy.name", NEIClientUtils.CTRL_HASH)) {
|
||||
return copyItemStackName(stackover);
|
||||
}
|
||||
if (NEIClientConfig.isKeyHashDown("gui.copy_id")) {
|
||||
|
||||
if (KeyManager.isHashDown("copy.identifier", NEIClientUtils.CTRL_HASH)) {
|
||||
return copyItemStackID(stackover);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.copy_oredict")) {
|
||||
if (KeyManager.isHashDown("copy.oredict", NEIClientUtils.CTRL_HASH)) {
|
||||
return copyItemStackOreDictionary(stackover);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.chat_link_item")) {
|
||||
if (KeyManager.isHashDown("copy.chat_link_item", NEIClientUtils.CTRL_HASH)) {
|
||||
return sendItemStackChatLink(stackover);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.recipe")) {
|
||||
if (KeyManager.isHashDown("recipe.recipe")) {
|
||||
return GuiCraftingRecipe.openRecipeGui("item", stackover);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.usage")) {
|
||||
if (KeyManager.isHashDown("recipe.usage")) {
|
||||
return GuiUsageRecipe.openRecipeGui("item", stackover);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.favorite")) {
|
||||
if (KeyManager.isHashDown("bookmark.favorite", NEIClientUtils.SHIFT_HASH)) {
|
||||
return saveFavoriteTree(stackover);
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark")) {
|
||||
if (KeyManager.isKeyDown("bookmark.add")) {
|
||||
return saveRecipeInBookmark(stackover, NEIClientUtils.shiftKey(), NEIClientUtils.controlKey());
|
||||
}
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark_pull_items")) {
|
||||
if (KeyManager.isKeyDown("bookmark.pull_items")) {
|
||||
return pullRecipeItems(stackover, NEIClientUtils.shiftKey());
|
||||
}
|
||||
|
||||
if (NEIClientConfig.autocraftingEnabled() && NEIClientConfig.isKeyHashDown("gui.craft_items")
|
||||
if (NEIClientConfig.autocraftingEnabled() && KeyManager.isKeyDown("gui.craft_items")
|
||||
&& NEIClientUtils.shiftKey()) {
|
||||
return runAutoCrafting(stackover, !NEIClientUtils.controlKey());
|
||||
}
|
||||
@@ -444,15 +446,15 @@ public abstract class ShortcutInputHandler {
|
||||
if (groupId != -1) {
|
||||
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.remove_recipe"),
|
||||
KeyManager.getKeyName("bookmark.remove_recipe", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.remove_recipe"));
|
||||
|
||||
if (BookmarkContainerInfo.getBookmarkContainerHandler(gui) != null) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark_pull_items"),
|
||||
KeyManager.getKeyName("bookmark.pull_items"),
|
||||
NEIClientUtils.translate("bookmark.group.pull_items"));
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark_pull_items", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.pull_items", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.pull_items_shift"));
|
||||
}
|
||||
|
||||
@@ -462,7 +464,7 @@ public abstract class ShortcutInputHandler {
|
||||
.getKeyName("gui.craft_items", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.craft_missing"));
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.craft_items", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("gui.craft_items", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.craft_all"));
|
||||
}
|
||||
|
||||
@@ -483,30 +485,28 @@ public abstract class ShortcutInputHandler {
|
||||
|
||||
if (group.crafting != null && group.collapsed) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.remove_recipe"));
|
||||
} else if (slot.getRecipeId() == null || slot.getType() == BookmarkItemType.ITEM) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark"),
|
||||
NEIClientUtils.translate("bookmark.remove_item"));
|
||||
hotkeys.put(KeyManager.getKeyName("bookmark.add"), NEIClientUtils.translate("bookmark.remove_item"));
|
||||
} else if (group.crafting != null && group.crafting.recipeRelations.entrySet().stream().anyMatch(
|
||||
entry -> entry.getKey().equals(slot.getRecipeId())
|
||||
|| entry.getValue().contains(slot.getRecipeId()))) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.remove_recipe"));
|
||||
} else {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.remove_recipe"));
|
||||
|
||||
if (slot.getType() == BookmarkItemType.INGREDIENT) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark"),
|
||||
KeyManager.getKeyName("bookmark.add"),
|
||||
NEIClientUtils.translate("bookmark.remove_item"));
|
||||
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.remove_recipe"));
|
||||
} else {
|
||||
final BookmarkItem item = slot.getBookmarkItem();
|
||||
@@ -516,14 +516,14 @@ public abstract class ShortcutInputHandler {
|
||||
m -> m.type == BookmarkItemType.RESULT && !m.equals(item)
|
||||
&& item.equalsRecipe(m))) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark"),
|
||||
KeyManager.getKeyName("bookmark.add"),
|
||||
NEIClientUtils.translate("bookmark.remove_recipe"));
|
||||
} else {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark"),
|
||||
KeyManager.getKeyName("bookmark.add"),
|
||||
NEIClientUtils.translate("bookmark.remove_item"));
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.remove_recipe"));
|
||||
}
|
||||
|
||||
@@ -533,60 +533,65 @@ public abstract class ShortcutInputHandler {
|
||||
|
||||
if (BookmarkContainerInfo.getBookmarkContainerHandler(gui) != null) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark_pull_items"),
|
||||
KeyManager.getKeyName("bookmark.pull_items"),
|
||||
NEIClientUtils.translate("bookmark.group.pull_items"));
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark_pull_items", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.pull_items", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.pull_items_shift"));
|
||||
}
|
||||
|
||||
} else {
|
||||
hotkeys.put(NEIClientConfig.getKeyName("gui.bookmark"), NEIClientUtils.translate("bookmark.add_item"));
|
||||
hotkeys.put(KeyManager.getKeyName("bookmark.add"), NEIClientUtils.translate("bookmark.add_item"));
|
||||
|
||||
if (StackInfo.getAmount(stack) > 0) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.CTRL_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("bookmark.add_item_with_count"));
|
||||
}
|
||||
|
||||
if (recipeId != null) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig
|
||||
.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("bookmark.add_item_with_recipe_and_count"));
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.add_item_with_recipe"));
|
||||
}
|
||||
|
||||
if ((ItemPanels.itemPanel.contains(mousex, mousey)
|
||||
|| ItemPanels.itemPanel.historyPanel.contains(mousex, mousey)) && FavoriteRecipes.contains(stack)) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.favorite"),
|
||||
KeyManager.getKeyName("bookmark.favorite", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("recipe.favorite.bookmark_recipe"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
hotkeys.put(NEIClientConfig.getKeyName("gui.recipe"), NEIClientUtils.translate("itempanel.open_crafting"));
|
||||
hotkeys.put(NEIClientConfig.getKeyName("gui.usage"), NEIClientUtils.translate("itempanel.open_usage"));
|
||||
hotkeys.put(KeyManager.getKeyName("recipe.recipe"), NEIClientUtils.translate("itempanel.open_crafting"));
|
||||
hotkeys.put(KeyManager.getKeyName("recipe.usage"), NEIClientUtils.translate("itempanel.open_usage"));
|
||||
|
||||
hotkeys.put(NEIClientConfig.getKeyName("gui.copy_name"), NEIClientUtils.translate("itempanel.copy_name"));
|
||||
hotkeys.put(NEIClientConfig.getKeyName("gui.copy_oredict"), NEIClientUtils.translate("itempanel.copy_oredict"));
|
||||
hotkeys.put(NEIClientConfig.getKeyName("gui.copy_id"), NEIClientUtils.translate("itempanel.copy_id"));
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.chat_link_item"),
|
||||
KeyManager.getKeyName("copy.name", NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("itempanel.copy_name"));
|
||||
hotkeys.put(
|
||||
KeyManager.getKeyName("copy.oredict", NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("itempanel.copy_oredict"));
|
||||
hotkeys.put(
|
||||
KeyManager.getKeyName("copy.identifier", NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("itempanel.copy_id"));
|
||||
hotkeys.put(
|
||||
KeyManager.getKeyName("copy.chat_link_item", NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("itempanel.chat_link_item"));
|
||||
|
||||
if (!(gui instanceof GuiRecipe) && NEIClientConfig.canCheatItem(stack)) {
|
||||
hotkeys.put(
|
||||
NEIClientUtils.getKeyName(NEIClientUtils.SHIFT_HASH, NEIMouseUtils.MOUSE_BTN_LMB),
|
||||
KeyManager.getKeyName(NEIClientUtils.SHIFT_HASH, NEIMouseUtils.MOUSE_BTN_LMB),
|
||||
NEIClientUtils.translate("itempanel.open_crafting"));
|
||||
hotkeys.put(
|
||||
NEIClientUtils.getKeyName(NEIClientUtils.SHIFT_HASH, NEIMouseUtils.MOUSE_BTN_RMB),
|
||||
KeyManager.getKeyName(NEIClientUtils.SHIFT_HASH, NEIMouseUtils.MOUSE_BTN_RMB),
|
||||
NEIClientUtils.translate("itempanel.open_usage"));
|
||||
hotkeys.put(
|
||||
NEIClientUtils.getKeyName(NEIClientUtils.CTRL_HASH, NEIMouseUtils.MOUSE_BTN_LMB),
|
||||
KeyManager.getKeyName(NEIClientUtils.CTRL_HASH, NEIMouseUtils.MOUSE_BTN_LMB),
|
||||
NEIClientUtils.translate("itempanel.infinite_item"));
|
||||
} else {
|
||||
hotkeys.put(
|
||||
@@ -604,18 +609,18 @@ public abstract class ShortcutInputHandler {
|
||||
|
||||
if (handlerRef.canUseOverlayRenderer(gui)) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.overlay"),
|
||||
KeyManager.getKeyName("gui.overlay"),
|
||||
NEIClientUtils.translate("itempanel.overlay_recipe"));
|
||||
}
|
||||
|
||||
if (handlerRef.canFillCraftingGrid(gui)) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.overlay", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("gui.overlay", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("itempanel.fill_crafting_grid"));
|
||||
|
||||
if (handlerRef.allowedTransferAlghoritm(gui)) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName(
|
||||
KeyManager.getKeyName(
|
||||
"gui.overlay",
|
||||
NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("itempanel.fill_crafting_grid_quantity"));
|
||||
@@ -624,12 +629,12 @@ public abstract class ShortcutInputHandler {
|
||||
|
||||
if (NEIClientConfig.autocraftingEnabled()) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName(
|
||||
KeyManager.getKeyName(
|
||||
"gui.craft_items",
|
||||
NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("itempanel.craft_missing"));
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.craft_items", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("gui.craft_items", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("itempanel.craft_all"));
|
||||
}
|
||||
}
|
||||
@@ -646,8 +651,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 +663,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)
|
||||
|
||||
@@ -92,8 +92,8 @@ public abstract class DataDumper extends Option {
|
||||
}
|
||||
|
||||
public Rectangle4i dumpButtonSize() {
|
||||
int width = 80;
|
||||
return new Rectangle4i(slot.slotWidth() - width, 0, width, 20);
|
||||
int width = 50;
|
||||
return new Rectangle4i(getSlot().slotWidth() - width, 0, width, 20);
|
||||
}
|
||||
|
||||
public Rectangle4i modeButtonSize() {
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.lwjgl.input.Keyboard;
|
||||
|
||||
import codechicken.core.gui.GuiCCButton;
|
||||
import codechicken.core.gui.GuiScreenWidget;
|
||||
import codechicken.lib.config.ConfigTag;
|
||||
import codechicken.lib.math.MathHelper;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.HUDRenderer;
|
||||
@@ -27,12 +28,16 @@ public class GuiHighlightTips extends GuiScreenWidget {
|
||||
private final String name;
|
||||
private GuiCCButton toggleButton;
|
||||
private final Option opt;
|
||||
private final GuiOptionList parentGui;
|
||||
private final boolean world;
|
||||
private Point dragDown;
|
||||
|
||||
public GuiHighlightTips(Option opt) {
|
||||
super(80, 20);
|
||||
this.opt = opt;
|
||||
name = opt.name;
|
||||
this.parentGui = (GuiOptionList) Minecraft.getMinecraft().currentScreen;
|
||||
this.world = parentGui.worldConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,7 +53,7 @@ public class GuiHighlightTips extends GuiScreenWidget {
|
||||
@Override
|
||||
public void actionPerformed(String ident, Object... params) {
|
||||
if (ident.equals("show")) {
|
||||
opt.getTag(name).setBooleanValue(!show());
|
||||
getTag(name).setBooleanValue(!show());
|
||||
updateNames();
|
||||
}
|
||||
}
|
||||
@@ -58,13 +63,21 @@ public class GuiHighlightTips extends GuiScreenWidget {
|
||||
}
|
||||
|
||||
private boolean show() {
|
||||
return opt.renderTag(name).getBooleanValue();
|
||||
return renderTag(name).getBooleanValue();
|
||||
}
|
||||
|
||||
private ConfigTag getTag(String s) {
|
||||
return (world ? opt.worldConfigSet() : opt.globalConfigSet()).config.getTag(s);
|
||||
}
|
||||
|
||||
private ConfigTag renderTag(String s) {
|
||||
return (world && opt.worldSpecific(s) ? opt.worldConfigSet() : opt.globalConfigSet()).config.getTag(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char c, int keycode) {
|
||||
if (keycode == Keyboard.KEY_ESCAPE || keycode == Keyboard.KEY_BACK) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(opt.slot.getGui());
|
||||
Minecraft.getMinecraft().displayGuiScreen(parentGui);
|
||||
return;
|
||||
}
|
||||
super.keyTyped(c, keycode);
|
||||
@@ -82,7 +95,7 @@ public class GuiHighlightTips extends GuiScreenWidget {
|
||||
}
|
||||
|
||||
public Point getPos() {
|
||||
return new Point(opt.renderTag(name + ".x").getIntValue(), opt.renderTag(name + ".y").getIntValue());
|
||||
return new Point(renderTag(name + ".x").getIntValue(), renderTag(name + ".y").getIntValue());
|
||||
}
|
||||
|
||||
public Dimension sampleSize() // copied from HUDManager when running with the sample for this gui
|
||||
@@ -148,8 +161,8 @@ public class GuiHighlightTips extends GuiScreenWidget {
|
||||
}
|
||||
|
||||
private void setPos(Point p) {
|
||||
opt.getTag(name).setBooleanValue(show()); // duplicates global tag for the option gui if in world mode
|
||||
opt.getTag(name + ".x").setIntValue(p.x);
|
||||
opt.getTag(name + ".y").setIntValue(p.y);
|
||||
getTag(name).setBooleanValue(show()); // duplicates global tag for the option gui if in world mode
|
||||
getTag(name + ".x").setIntValue(p.x);
|
||||
getTag(name + ".y").setIntValue(p.y);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ public class GuiItemIconDumper extends GuiScreen {
|
||||
}
|
||||
|
||||
private Option opt;
|
||||
private final GuiOptionList parentGui;
|
||||
private int drawIndex;
|
||||
private int parseIndex;
|
||||
private final File dir = new File(CommonUtils.getMinecraftDir(), "dumps/itempanel_icons");
|
||||
@@ -52,6 +53,7 @@ public class GuiItemIconDumper extends GuiScreen {
|
||||
|
||||
public GuiItemIconDumper(Option opt, int iconSize) {
|
||||
this.opt = opt;
|
||||
this.parentGui = (GuiOptionList) Minecraft.getMinecraft().currentScreen;
|
||||
this.iconSize = iconSize;
|
||||
borderSize = iconSize / 16;
|
||||
boxSize = iconSize + borderSize * 2;
|
||||
@@ -62,7 +64,7 @@ public class GuiItemIconDumper extends GuiScreen {
|
||||
}
|
||||
|
||||
private void returnScreen(IChatComponent msg) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(opt.slot.getGui());
|
||||
Minecraft.getMinecraft().displayGuiScreen(parentGui);
|
||||
NEIClientUtils.printChatMessage(msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,14 @@ import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.lib.config.ConfigTag;
|
||||
import codechicken.lib.math.MathHelper;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemSorter;
|
||||
import codechicken.nei.ItemSorter.SortEntry;
|
||||
import codechicken.nei.LayoutManager;
|
||||
@@ -48,6 +51,8 @@ public class GuiItemSorter extends GuiOptionPane {
|
||||
public final Option opt;
|
||||
public final List<SortItem> slots = new ArrayList<>();
|
||||
public final List<SortEntry> list;
|
||||
private final GuiOptionList parentGui;
|
||||
private final boolean world;
|
||||
|
||||
boolean dragging;
|
||||
public SortItem dragged;
|
||||
@@ -56,7 +61,9 @@ public class GuiItemSorter extends GuiOptionPane {
|
||||
|
||||
public GuiItemSorter(Option opt) {
|
||||
this.opt = opt;
|
||||
list = ItemSorter.fromSaveString(opt.renderTag().getValue());
|
||||
this.parentGui = (GuiOptionList) Minecraft.getMinecraft().currentScreen;
|
||||
this.world = parentGui.worldConfig();
|
||||
list = ItemSorter.fromSaveString(renderTag(opt.configName()).getValue());
|
||||
for (SortEntry e : list) slots.add(new SortItem(e));
|
||||
}
|
||||
|
||||
@@ -98,7 +105,7 @@ public class GuiItemSorter extends GuiOptionPane {
|
||||
|
||||
@Override
|
||||
public GuiScreen getParentScreen() {
|
||||
return opt.slot.getGui();
|
||||
return parentGui;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -114,16 +121,25 @@ public class GuiItemSorter extends GuiOptionPane {
|
||||
list.remove(dragged.e);
|
||||
list.add(nslot, dragged.e);
|
||||
|
||||
opt.getTag().setValue(ItemSorter.getSaveString(list));
|
||||
LayoutManager.markItemsDirty();
|
||||
getTag(opt.configName()).setValue(ItemSorter.getSaveString(list));
|
||||
|
||||
if (opt.activeTag() == opt.getTag()) {
|
||||
if (opt.activeTag() == getTag(opt.configName())) {
|
||||
ItemSorter.list = new ArrayList<>(list);
|
||||
}
|
||||
|
||||
ItemList.refreshItems.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ConfigTag getTag(String s) {
|
||||
return (world ? opt.worldConfigSet() : opt.globalConfigSet()).config.getTag(s);
|
||||
}
|
||||
|
||||
private ConfigTag renderTag(String s) {
|
||||
return (world && opt.worldSpecific(s) ? opt.worldConfigSet() : opt.globalConfigSet()).config.getTag(s);
|
||||
}
|
||||
|
||||
public SortItem itemAt(int mx, int my) {
|
||||
if (!pane.windowBounds().contains(mx, my)) return null;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL12;
|
||||
|
||||
import codechicken.core.gui.GuiScreenWidget;
|
||||
import codechicken.lib.config.ConfigTag;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.render.CCRenderState;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
@@ -21,7 +22,7 @@ import codechicken.nei.guihook.GuiContainerManager;
|
||||
|
||||
public class GuiPanelSettings extends GuiScreenWidget {
|
||||
|
||||
private final Option opt;
|
||||
private final GuiOptionList parentGui;
|
||||
|
||||
private PanelPlaceholder bookmarksPanel;
|
||||
private PanelPlaceholder itemsPanel;
|
||||
@@ -54,6 +55,7 @@ public class GuiPanelSettings extends GuiScreenWidget {
|
||||
|
||||
private final Option opt;
|
||||
private final String name;
|
||||
private final boolean world;
|
||||
private Rectangle4i margin;
|
||||
private Point dragDown;
|
||||
private String dragDir;
|
||||
@@ -67,9 +69,10 @@ public class GuiPanelSettings extends GuiScreenWidget {
|
||||
private PanelResizeButton rightButton = new PanelResizeButton(PANEL_SIZE, PANEL_SIZE * 2);
|
||||
private PanelResizeButton bottomButton = new PanelResizeButton(PANEL_SIZE * 2, PANEL_SIZE);
|
||||
|
||||
public PanelPlaceholder(Option opt, String name) {
|
||||
public PanelPlaceholder(Option opt, String name, boolean world) {
|
||||
this.opt = opt;
|
||||
this.name = name;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
public void resize(Rectangle4i margin) {
|
||||
@@ -116,10 +119,10 @@ public class GuiPanelSettings extends GuiScreenWidget {
|
||||
final int minWidth = ItemsGrid.SLOT_SIZE;
|
||||
final int minHeight = ItemsGrid.SLOT_SIZE;
|
||||
|
||||
int paddingLeft = (int) Math.ceil(margin.w * opt.renderTag(name + ".left").getIntValue() / 100000.0);
|
||||
int paddingTop = (int) Math.ceil(margin.h * opt.renderTag(name + ".top").getIntValue() / 100000.0);
|
||||
int paddingRight = (int) Math.ceil(margin.w * opt.renderTag(name + ".right").getIntValue() / 100000.0);
|
||||
int paddingBottom = (int) Math.ceil(margin.h * opt.renderTag(name + ".bottom").getIntValue() / 100000.0);
|
||||
int paddingLeft = (int) Math.ceil(margin.w * getTag(name + ".left").getIntValue() / 100000.0);
|
||||
int paddingTop = (int) Math.ceil(margin.h * getTag(name + ".top").getIntValue() / 100000.0);
|
||||
int paddingRight = (int) Math.ceil(margin.w * getTag(name + ".right").getIntValue() / 100000.0);
|
||||
int paddingBottom = (int) Math.ceil(margin.h * getTag(name + ".bottom").getIntValue() / 100000.0);
|
||||
|
||||
if (dragDir != null) {
|
||||
final Point mouse = GuiDraw.getMousePosition();
|
||||
@@ -159,6 +162,10 @@ public class GuiPanelSettings extends GuiScreenWidget {
|
||||
return new int[] { paddingLeft, paddingTop, paddingRight, paddingBottom };
|
||||
}
|
||||
|
||||
private ConfigTag getTag(String s) {
|
||||
return (world ? opt.worldConfigSet() : opt.globalConfigSet()).config.getTag(s);
|
||||
}
|
||||
|
||||
protected void drawItems() {
|
||||
final int columns = (w - 2) / ItemsGrid.SLOT_SIZE;
|
||||
final int rows = (h - (PANEL_SIZE + 2) * 2 - 2) / ItemsGrid.SLOT_SIZE;
|
||||
@@ -219,10 +226,10 @@ public class GuiPanelSettings extends GuiScreenWidget {
|
||||
if (button == 0 && dragDown != null) {
|
||||
int[] padding = getPaddings();
|
||||
|
||||
opt.renderTag(name + ".left").setIntValue(padding[0] * 100000 / margin.w);
|
||||
opt.renderTag(name + ".top").setIntValue(padding[1] * 100000 / margin.h);
|
||||
opt.renderTag(name + ".right").setIntValue(padding[2] * 100000 / margin.w);
|
||||
opt.renderTag(name + ".bottom").setIntValue(padding[3] * 100000 / margin.h);
|
||||
getTag(name + ".left").setIntValue(padding[0] * 100000 / margin.w);
|
||||
getTag(name + ".top").setIntValue(padding[1] * 100000 / margin.h);
|
||||
getTag(name + ".right").setIntValue(padding[2] * 100000 / margin.w);
|
||||
getTag(name + ".bottom").setIntValue(padding[3] * 100000 / margin.h);
|
||||
|
||||
dragDir = null;
|
||||
dragDown = null;
|
||||
@@ -232,10 +239,11 @@ public class GuiPanelSettings extends GuiScreenWidget {
|
||||
|
||||
public GuiPanelSettings(Option opt) {
|
||||
super(176, 198);
|
||||
this.opt = opt;
|
||||
this.parentGui = (GuiOptionList) Minecraft.getMinecraft().currentScreen;
|
||||
|
||||
bookmarksPanel = new PanelPlaceholder(opt, opt.name + ".bookmarks");
|
||||
itemsPanel = new PanelPlaceholder(opt, opt.name + ".items");
|
||||
boolean world = parentGui.worldConfig();
|
||||
bookmarksPanel = new PanelPlaceholder(opt, opt.name + ".bookmarks", world);
|
||||
itemsPanel = new PanelPlaceholder(opt, opt.name + ".items", world);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -247,7 +255,7 @@ public class GuiPanelSettings extends GuiScreenWidget {
|
||||
public void keyTyped(char c, int keycode) {
|
||||
|
||||
if (keycode == Keyboard.KEY_ESCAPE || keycode == Keyboard.KEY_BACK) {
|
||||
Minecraft.getMinecraft().displayGuiScreen(opt.slot.getGui());
|
||||
Minecraft.getMinecraft().displayGuiScreen(parentGui);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,10 +99,12 @@ public class IMCHandler {
|
||||
NEIClientConfig.logger.info("Error setting handler dimensions for {}", handler);
|
||||
}
|
||||
|
||||
// true if not set to false
|
||||
info.setUseCustomScroll(tag.hasKey("useCustomScroll") && tag.getBoolean("useCustomScroll"));
|
||||
final boolean allowOverflow = tag.hasKey("useCustomScroll") && tag.getBoolean("useCustomScroll");
|
||||
info.setAllowOverflowX(tag.hasKey("allowOverflowX") ? tag.getBoolean("allowOverflowX") : true);
|
||||
info.setAllowOverflowY(tag.hasKey("allowOverflowY") ? tag.getBoolean("allowOverflowY") : allowOverflow);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package codechicken.nei.config;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -17,7 +18,11 @@ public abstract class Option {
|
||||
.playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
}
|
||||
|
||||
public OptionScrollSlot slot;
|
||||
private WeakReference<OptionScrollSlot> slotRef;
|
||||
|
||||
public OptionScrollSlot getSlot() {
|
||||
return slotRef != null ? slotRef.get() : null;
|
||||
}
|
||||
|
||||
public String namespace = null;
|
||||
public final String name;
|
||||
@@ -134,7 +139,7 @@ public abstract class Option {
|
||||
* @return true if the gui is in world config mode
|
||||
*/
|
||||
public boolean worldConfig() {
|
||||
return slot.getGui().worldConfig();
|
||||
return getSlot().getGui().worldConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +194,7 @@ public abstract class Option {
|
||||
}
|
||||
|
||||
public void onAdded(OptionScrollSlot slot) {
|
||||
this.slot = slot;
|
||||
this.slotRef = new WeakReference<>(slot);
|
||||
}
|
||||
|
||||
public void onAdded(OptionList list) {
|
||||
|
||||
@@ -57,10 +57,10 @@ public abstract class OptionButton extends Option {
|
||||
}
|
||||
|
||||
public Rectangle buttonSize() {
|
||||
if (getPrefix() == null) return new Rectangle(0, 0, slot.slotWidth(), 20);
|
||||
if (getPrefix() == null) return new Rectangle(0, 0, getSlot().slotWidth(), 20);
|
||||
|
||||
int width = Math.max(60, getStringWidth(getButtonText()) + 8);
|
||||
return new Rectangle(slot.slotWidth() - width, 0, width, 20);
|
||||
return new Rectangle(getSlot().slotWidth() - width, 0, width, 20);
|
||||
}
|
||||
|
||||
public String getPrefix() {
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
package codechicken.nei.config;
|
||||
|
||||
import static codechicken.lib.gui.GuiDraw.drawRect;
|
||||
import static codechicken.lib.gui.GuiDraw.drawStringC;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.util.NEIKeyboardUtils;
|
||||
|
||||
public class OptionKeyBind extends OptionButton {
|
||||
|
||||
private boolean editing = false;
|
||||
private boolean useHash = false;
|
||||
private int keyboard = Keyboard.CHAR_NONE;
|
||||
|
||||
public OptionKeyBind(String name) {
|
||||
this(name, false);
|
||||
}
|
||||
|
||||
public OptionKeyBind(final String name, final boolean useHash) {
|
||||
super("keys." + name);
|
||||
this.useHash = useHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMouseClicked(int mousex, int mousey, int button) {
|
||||
if (editing) {
|
||||
resetChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char c, int keycode) {
|
||||
|
||||
if (!editing) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (keycode == Keyboard.KEY_RETURN) {
|
||||
applyChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
keyboard = useHash ? NEIClientUtils.getKeyHash() : keycode;
|
||||
|
||||
if (keyboard != Keyboard.CHAR_NONE) {
|
||||
applyChanges();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onClick(int btn) {
|
||||
|
||||
if (editing) {
|
||||
return true;
|
||||
} else if (btn == 0) {
|
||||
editing = true;
|
||||
return true;
|
||||
} else if (btn == 1) {
|
||||
keyboard = Keyboard.CHAR_NONE;
|
||||
applyChanges();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void applyChanges() {
|
||||
setValue(keyboard);
|
||||
resetChanges();
|
||||
}
|
||||
|
||||
protected void resetChanges() {
|
||||
editing = false;
|
||||
keyboard = Keyboard.CHAR_NONE;
|
||||
}
|
||||
|
||||
public boolean conflicted() {
|
||||
final int keyboard = getValue();
|
||||
|
||||
if (keyboard <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Option o : slot.options) {
|
||||
if (o instanceof OptionKeyBind && o != this && ((OptionKeyBind) o).getValue() == keyboard) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setValue(int keycode) {
|
||||
getTag().setIntValue(keycode);
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return renderTag().getIntValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPrefix() {
|
||||
return translateN(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawButton(int mx, int my) {
|
||||
|
||||
if (editing) {
|
||||
Rectangle b = buttonSize();
|
||||
drawRect(b.x, b.y, b.width, b.height, -6250336);
|
||||
drawRect(b.x + 1, b.y + 1, b.width - 2, b.height - 2, -16777216);
|
||||
drawStringC(getButtonText(), b.x, b.y, b.width, b.height, getTextColour(mx, my));
|
||||
} else {
|
||||
super.drawButton(mx, my);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getButtonText() {
|
||||
|
||||
if (editing) {
|
||||
return NEIKeyboardUtils.getHashName(NEIClientUtils.getMetaHash());
|
||||
}
|
||||
|
||||
return NEIKeyboardUtils.getKeyName(Math.max(getValue(), 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTextColour(int mousex, int mousey) {
|
||||
return !editing && conflicted() ? 0xFFFF6666 : -1;
|
||||
}
|
||||
}
|
||||
@@ -131,13 +131,15 @@ public class OptionList extends OptionButton {
|
||||
/**
|
||||
* Adds this option to a temporary slot and gui for internal setting manipulation.
|
||||
*/
|
||||
public void synthesizeEnvironment(boolean world) {
|
||||
getGui(null, this, world).addWidgets();
|
||||
public GuiOptionList synthesizeEnvironment(boolean world) {
|
||||
GuiOptionList gui = getGui(null, this, world);
|
||||
gui.addWidgets();
|
||||
return gui;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onClick(int button) {
|
||||
openGui(slot.getGui(), slot.getGui().worldConfig());
|
||||
openGui(getSlot().getGui(), getSlot().getGui().worldConfig());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +131,6 @@ public abstract class OptionStringSet extends Option {
|
||||
}
|
||||
|
||||
public int buttonX() {
|
||||
return slot.slotWidth() - (24 * options.size() - 4);
|
||||
return getSlot().slotWidth() - (24 * options.size() - 4);
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public class OptionTextField extends Option {
|
||||
}
|
||||
|
||||
protected int getMaxInputWidth() {
|
||||
return slot.slotWidth();
|
||||
return getSlot().slotWidth();
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
@@ -64,9 +64,10 @@ public class OptionTextField extends Option {
|
||||
public void draw(int mousex, int mousey, float frame) {
|
||||
GuiDraw.drawString(getPrefix(), 10, 6, -1);
|
||||
|
||||
textField.w = Math
|
||||
.max(60, Math.min(getMaxInputWidth(), slot.slotWidth() - GuiDraw.getStringWidth(getPrefix())) - 16);
|
||||
textField.x = slot.slotWidth() - textField.w;
|
||||
textField.w = Math.max(
|
||||
60,
|
||||
Math.min(getMaxInputWidth(), getSlot().slotWidth() - GuiDraw.getStringWidth(getPrefix())) - 16);
|
||||
textField.x = getSlot().slotWidth() - textField.w;
|
||||
textField.draw(mousex, mousey);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import static codechicken.lib.gui.GuiDraw.drawStringC;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.ColorUtils;
|
||||
import codechicken.nei.LayoutManager;
|
||||
|
||||
public abstract class CheckboxButton extends Button {
|
||||
@@ -38,7 +39,8 @@ public abstract class CheckboxButton extends Button {
|
||||
tex = 1;
|
||||
}
|
||||
|
||||
int colour = tex == 2 ? 0xffffa0 : tex == 0 ? 0x601010 : 0xe0e0e0;
|
||||
int colour = tex == 2 ? ColorUtils.buttonLabelHover.getColor()
|
||||
: tex == 0 ? ColorUtils.buttonLabelDisabled.getColor() : ColorUtils.buttonLabelNormal.getColor();
|
||||
LayoutManager.drawButtonBackground(x, y, w, h, true, isChecked() ? 0 : tex);
|
||||
drawStringC(getRenderLabel(), x + w / 2, y + (h - 8) / 2, colour);
|
||||
}
|
||||
|
||||
@@ -17,12 +17,14 @@ import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
import codechicken.nei.config.GuiOptionList;
|
||||
import codechicken.nei.config.GuiOptionPane;
|
||||
import codechicken.nei.config.Option;
|
||||
|
||||
public class GuiPresetList extends GuiOptionPane {
|
||||
|
||||
private final Option opt;
|
||||
private final GuiOptionList parentGui;
|
||||
protected static final int SLOT_HEIGHT = 24;
|
||||
protected static final int BUTTON_HEIGHT = 20;
|
||||
protected GuiCCButton createButton;
|
||||
@@ -31,6 +33,7 @@ public class GuiPresetList extends GuiOptionPane {
|
||||
|
||||
public GuiPresetList(Option opt) {
|
||||
this.opt = opt;
|
||||
this.parentGui = (GuiOptionList) Minecraft.getMinecraft().currentScreen;
|
||||
this.createButton = new GuiCCButton(0, 2, 0, 16, NEIClientUtils.translate("presets.new"))
|
||||
.setActionCommand("create");
|
||||
this.toggleButton = new GuiCCButton(0, 2, 0, 16, NEIClientUtils.translate("presets.toggle"))
|
||||
@@ -253,7 +256,7 @@ public class GuiPresetList extends GuiOptionPane {
|
||||
|
||||
@Override
|
||||
public GuiScreen getParentScreen() {
|
||||
return opt.slot.getGui();
|
||||
return parentGui;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,7 +21,7 @@ import codechicken.nei.ItemList.AnyMultiItemFilter;
|
||||
import codechicken.nei.ItemList.NegatedItemFilter;
|
||||
import codechicken.nei.ItemsGrid;
|
||||
import codechicken.nei.ItemsGrid.ItemsGridSlot;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.KeyManager;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PresetsList;
|
||||
import codechicken.nei.PresetsList.Preset;
|
||||
@@ -81,15 +81,15 @@ public class RightPanel extends GuiWidget {
|
||||
@Override
|
||||
public void lastKeyTyped(int keyID, char keyChar) {
|
||||
|
||||
if (!focused() && NEIClientConfig.isKeyHashDown("gui.search")) {
|
||||
if (!focused() && KeyManager.isHashDown("gui.search")) {
|
||||
setFocus(true);
|
||||
}
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getprevioussearch")) {
|
||||
if (focused() && KeyManager.isHashDown("gui.getprevioussearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
||||
}
|
||||
|
||||
if (focused() && NEIClientConfig.isKeyHashDown("gui.getnextsearch")) {
|
||||
if (focused() && KeyManager.isHashDown("gui.getnextsearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import org.lwjgl.opengl.GL12;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.ItemStackSet;
|
||||
import codechicken.nei.KeyManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIModContainer;
|
||||
@@ -762,7 +763,7 @@ public class GuiContainerManager {
|
||||
"inventory.tooltip.page",
|
||||
tooltipPage + 1,
|
||||
maxTooltipPage,
|
||||
NEIClientConfig.getKeyName("gui.next_tooltip"));
|
||||
KeyManager.getKeyName("gui.next_tooltip"));
|
||||
|
||||
if (lastLine.startsWith(GuiDraw.TOOLTIP_HANDLER)) {
|
||||
currentTooltip.add(lastLine);
|
||||
|
||||
@@ -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,89 @@
|
||||
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.ColorUtils;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIClientUtils.Alignment;
|
||||
|
||||
public class Badge {
|
||||
|
||||
protected final String text;
|
||||
protected final List<String> tooltip;
|
||||
protected int badgeTextColor;
|
||||
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 = ColorUtils.recipeBadge.getColor();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -197,7 +197,7 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
return ingredSlots;
|
||||
}
|
||||
|
||||
private void moveIngredients(GuiContainer gui, List<IngredientDistribution> assignedIngredients, int multiplier) {
|
||||
protected void moveIngredients(GuiContainer gui, List<IngredientDistribution> assignedIngredients, int multiplier) {
|
||||
final Slot craftingSlot = getCraftingResultSlot(gui);
|
||||
|
||||
for (Slot slot : gui.inventorySlots.inventorySlots) {
|
||||
@@ -249,7 +249,7 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private int calculateRecipeQuantity(List<IngredientDistribution> assignedIngredients) {
|
||||
protected int calculateRecipeQuantity(List<IngredientDistribution> assignedIngredients) {
|
||||
int quantity = Integer.MAX_VALUE;
|
||||
|
||||
for (IngredientDistribution distrib : assignedIngredients) {
|
||||
@@ -275,7 +275,7 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
return quantity;
|
||||
}
|
||||
|
||||
private Slot[][] assignIngredSlots(GuiContainer gui, List<PositionedStack> ingredients,
|
||||
protected Slot[][] assignIngredSlots(GuiContainer gui, List<PositionedStack> ingredients,
|
||||
List<IngredientDistribution> assignedIngredients) {
|
||||
Slot[][] recipeSlots = mapIngredSlots(gui, ingredients); // setup the slot map
|
||||
|
||||
@@ -320,7 +320,7 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
return recipeSlots;
|
||||
}
|
||||
|
||||
private List<IngredientDistribution> assignIngredients(List<PositionedStack> ingredients,
|
||||
protected List<IngredientDistribution> assignIngredients(List<PositionedStack> ingredients,
|
||||
List<DistributedIngred> ingredStacks) {
|
||||
ArrayList<IngredientDistribution> assignedIngredients = new ArrayList<>();
|
||||
for (PositionedStack posstack : ingredients) // assign what we need and have
|
||||
@@ -358,7 +358,7 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
return assignedIngredients;
|
||||
}
|
||||
|
||||
private void findInventoryQuantities(GuiContainer gui, List<DistributedIngred> ingredStacks) {
|
||||
protected void findInventoryQuantities(GuiContainer gui, List<DistributedIngred> ingredStacks) {
|
||||
for (Slot slot : gui.inventorySlots.inventorySlots) /* work out how much we have to go round */ {
|
||||
if (slot.getHasStack() && canMoveFrom(slot, gui)) {
|
||||
final ItemStack pstack = slot.getStack();
|
||||
@@ -390,7 +390,7 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private List<DistributedIngred> getPermutationIngredients(List<PositionedStack> ingredients) {
|
||||
protected List<DistributedIngred> getPermutationIngredients(List<PositionedStack> ingredients) {
|
||||
ArrayList<DistributedIngred> ingredStacks = new ArrayList<>();
|
||||
for (PositionedStack posstack : ingredients) /* work out what we need */ {
|
||||
for (ItemStack pstack : posstack.items) {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import codechicken.nei.FavoriteRecipes;
|
||||
import codechicken.nei.Image;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.ItemStackSet;
|
||||
import codechicken.nei.KeyManager;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
@@ -122,7 +123,7 @@ public class GuiFavoriteButton extends GuiRecipeButton {
|
||||
|
||||
public void lastKeyTyped(char keyChar, int keyID) {
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark") && NEIClientUtils.shiftKey()) {
|
||||
if (KeyManager.isKeyDown("bookmark.add") && NEIClientUtils.shiftKey()) {
|
||||
saveRecipeInBookmark();
|
||||
}
|
||||
|
||||
@@ -131,7 +132,7 @@ public class GuiFavoriteButton extends GuiRecipeButton {
|
||||
@Override
|
||||
public Map<String, String> handleHotkeys(int mousex, int mousey, Map<String, String> hotkeys) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH),
|
||||
translate("recipe.favorite.bookmark_recipe"));
|
||||
|
||||
if (this.recipe.getResults().size() > 1) {
|
||||
|
||||
@@ -15,10 +15,12 @@ import org.lwjgl.opengl.GL11;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.ItemsTooltipLineHandler;
|
||||
import codechicken.nei.KeyManager;
|
||||
import codechicken.nei.LayoutManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import codechicken.nei.bookmark.BookmarkGrid;
|
||||
import codechicken.nei.drawable.DrawableBuilder;
|
||||
import codechicken.nei.drawable.DrawableResource;
|
||||
@@ -96,13 +98,18 @@ public class GuiOverlayButton extends GuiRecipeButton {
|
||||
super(handlerRef, x, y, handlerRef.recipeIndex + BUTTON_ID_SHIFT, "+");
|
||||
this.firstGui = firstGui != null && firstGui.inventorySlots != null ? firstGui : null;
|
||||
|
||||
IOverlayHandler overlayHandler = null;
|
||||
|
||||
if (this.firstGui != null) {
|
||||
overlayHandler = this.handlerRef.getOverlayHandler(this.firstGui);
|
||||
this.canUseOverlayRenderer = this.handlerRef.getRecipeOverlayRenderer(this.firstGui) != null;
|
||||
this.canFillCraftingGrid = this.handlerRef.canFillCraftingGrid(this.firstGui);
|
||||
this.hasOverlay = this.canUseOverlayRenderer || this.handlerRef.getOverlayHandler(this.firstGui) != null;
|
||||
this.hasOverlay = this.canUseOverlayRenderer || overlayHandler != null;
|
||||
}
|
||||
|
||||
setRequireShiftForOverlayRecipe(NEIClientConfig.requireShiftForOverlayRecipe());
|
||||
setRequireShiftForOverlayRecipe(
|
||||
overlayHandler != null ? overlayHandler.requireShiftForOverlayRecipe()
|
||||
: NEIClientConfig.requireShiftForOverlayRecipe());
|
||||
ingredientsOverlay();
|
||||
}
|
||||
|
||||
@@ -157,11 +164,11 @@ public class GuiOverlayButton extends GuiRecipeButton {
|
||||
}
|
||||
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("recipe.overlay.bookmarkRecipe"));
|
||||
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.bookmark", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("recipe.overlay.bookmarkRecipeAndCount"));
|
||||
|
||||
return hotkeys;
|
||||
@@ -319,7 +326,7 @@ public class GuiOverlayButton extends GuiRecipeButton {
|
||||
|
||||
@Override
|
||||
public void lastKeyTyped(char keyChar, int keyID) {
|
||||
if (NEIClientConfig.isKeyHashDown("gui.bookmark") && NEIClientUtils.shiftKey()) {
|
||||
if (KeyManager.isKeyDown("bookmark.add") && NEIClientUtils.shiftKey()) {
|
||||
saveRecipeInBookmark();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -25,7 +24,9 @@ import org.lwjgl.opengl.GL11;
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.lib.vec.Rectangle4i;
|
||||
import codechicken.nei.Button;
|
||||
import codechicken.nei.ColorUtils;
|
||||
import codechicken.nei.GuiNEIButton;
|
||||
import codechicken.nei.KeyManager;
|
||||
import codechicken.nei.NEICPH;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
@@ -92,6 +93,9 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
private GuiButton prevtype;
|
||||
private GuiButton nexttype;
|
||||
|
||||
private Rectangle typeArea = new Rectangle();
|
||||
private Rectangle pageArea = new Rectangle();
|
||||
|
||||
private int lastPage = -1;
|
||||
private final GuiRecipeTabs recipeTabs;
|
||||
private final GuiRecipeCatalyst recipeCatalyst;
|
||||
@@ -308,7 +312,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
@Override
|
||||
public Widget getWidgetUnderMouse(int mousex, int mousey) {
|
||||
|
||||
if (handlerInfo.getUseCustomScroll() && !this.widgets.isEmpty()) {
|
||||
if (handlerInfo.isAllowOverflowY() && !this.widgets.isEmpty()) {
|
||||
return this.widgets.get(0);
|
||||
}
|
||||
|
||||
@@ -346,7 +350,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
this.container.x = this.guiLeft + 3;
|
||||
this.container.y = this.guiTop + 32;
|
||||
this.container.h = this.ySize - 32 - 5;
|
||||
this.container.h = this.ySize - 32 - 4;
|
||||
|
||||
GuiRecipe.toggleSearch.icon = new DrawableBuilder("nei:textures/nei_sprites.png", 0, 76, 10, 10).build();
|
||||
GuiRecipe.toggleSearch.w = GuiRecipe.toggleSearch.h = 12;
|
||||
@@ -358,8 +362,18 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
GuiRecipe.searchField.w = this.xSize - (BORDER_PADDING + BUTTON_WIDTH) * 2 + 1 - GuiRecipe.toggleSearch.w - 45;
|
||||
GuiRecipe.searchField.h = 14;
|
||||
|
||||
this.buttonList.addAll(Arrays.asList(this.prevtype, this.nexttype, this.prevpage, this.nextpage));
|
||||
this.typeArea.setBounds(
|
||||
this.prevtype.xPosition + BUTTON_WIDTH,
|
||||
this.prevtype.yPosition,
|
||||
this.nexttype.xPosition - this.prevtype.xPosition - BUTTON_WIDTH - 1,
|
||||
BUTTON_HEIGHT);
|
||||
this.pageArea.setBounds(
|
||||
this.prevpage.xPosition + BUTTON_WIDTH,
|
||||
this.prevpage.yPosition,
|
||||
this.nextpage.xPosition - this.prevpage.xPosition - BUTTON_WIDTH - 1,
|
||||
BUTTON_HEIGHT);
|
||||
|
||||
this.buttonList.addAll(Arrays.asList(this.prevtype, this.nexttype, this.prevpage, this.nextpage));
|
||||
if (this.currenthandlers.size() == 1) {
|
||||
this.prevtype.visible = false;
|
||||
this.nexttype.visible = false;
|
||||
@@ -372,9 +386,19 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
if (this.handlerPages.rebuildPages() || this.lastPage != this.handlerPages.getCurrentPageIndex()) {
|
||||
this.lastPage = this.handlerPages.getCurrentPageIndex();
|
||||
updateContainerSize();
|
||||
|
||||
this.container.setWidgets(this.handlerPages.getCurrentPageWidgets());
|
||||
|
||||
if (this.handlerInfo.getUseCustomScroll()) {
|
||||
if (!this.handlerInfo.isAllowOverflowX() && this.handlerInfo.getWidth() > this.xSize - 6) {
|
||||
this.container.setPaddingInline(0, 2);
|
||||
this.container.setHorizontalScroll(ScrollBar.defaultHorizontalBar().setTrackPadding(1, 0, 1, 0));
|
||||
} else {
|
||||
this.container.setPaddingInline(0, 0);
|
||||
this.container.setHorizontalScroll(null);
|
||||
}
|
||||
|
||||
if (this.handlerInfo.isAllowOverflowY()) {
|
||||
this.container.setVerticalScroll(null);
|
||||
} else if (this.container.w == this.xSize - 6) {
|
||||
this.container.setVerticalScroll(VERTICAL_SCROLLBAR);
|
||||
@@ -416,7 +440,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
this.recipetype = (this.currenthandlers.size() + idx) % this.currenthandlers.size();
|
||||
this.handler = new SearchRecipeHandler<>(this.currenthandlers.get(this.recipetype));
|
||||
this.handlerInfo = GuiRecipeTab.getHandlerInfo(this.handler.original);
|
||||
this.container.w = Math.max(this.xSize - 6, this.handlerInfo.getWidth());
|
||||
updateContainerSize();
|
||||
this.handlerPages = new RecipePageManager(this.handler, this.handlerInfo, this.container);
|
||||
this.prevpage.enabled = this.nextpage.enabled = this.handlerPages.getNumPages() > 1;
|
||||
this.lastPage = -1;
|
||||
@@ -426,9 +450,21 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
GuiRecipe.toggleSearch.state = 0;
|
||||
|
||||
this.container.setVerticalScrollOffset(0);
|
||||
this.container.setHorizontalScrollOffset(0);
|
||||
this.recipeTabs.update(this);
|
||||
}
|
||||
|
||||
private void updateContainerSize() {
|
||||
final int width = this.xSize - 6;
|
||||
this.container.w = Math.max(width, this.handlerInfo.getWidth());
|
||||
this.container.h = this.ySize - 32 - 4;
|
||||
|
||||
if (!this.handlerInfo.isAllowOverflowX() && this.handlerInfo.getWidth() > width) {
|
||||
this.container.w = width;
|
||||
this.container.h -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
public int openTargetRecipe(RecipeId recipeId) {
|
||||
int refIndex = -1;
|
||||
int recipetype = 0;
|
||||
@@ -564,15 +600,15 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
if (i == mc.gameSettings.keyBindInventory.getKeyCode()) {
|
||||
this.mc.displayGuiScreen(getFirstScreenGeneral());
|
||||
NEICPH.sendRequestContainer();
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.back")) {
|
||||
} else if (KeyManager.isKeyDown("recipe.back")) {
|
||||
this.mc.displayGuiScreen(this.prevGui);
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.prev_machine")) {
|
||||
} else if (KeyManager.isKeyDown("recipe.prev_machine")) {
|
||||
prevType();
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.next_machine")) {
|
||||
} else if (KeyManager.isKeyDown("recipe.next_machine")) {
|
||||
nextType();
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.prev_recipe")) {
|
||||
} else if (KeyManager.isKeyDown("recipe.prev_recipe")) {
|
||||
prevPage();
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.next_recipe")) {
|
||||
} else if (KeyManager.isKeyDown("recipe.next_recipe")) {
|
||||
nextPage();
|
||||
}
|
||||
}
|
||||
@@ -671,7 +707,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
// If shift is held, try switching to the next recipe handler. Replicates the
|
||||
// GuiRecipeTabs.mouseScrolled()
|
||||
// without the checking for the cursor being inside the tabbar.
|
||||
if (NEIClientUtils.shiftKey()) {
|
||||
if (NEIClientUtils.shiftKey() || this.typeArea.contains(mouse)) {
|
||||
if (scroll < 0) {
|
||||
nextType();
|
||||
} else {
|
||||
@@ -683,7 +719,12 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
// Finally, if nothing else has handled scrolling, try changing to the next
|
||||
// recipe page.
|
||||
if (new Rectangle(this.guiLeft, this.guiTop, this.xSize, this.ySize).contains(mouse)) {
|
||||
if (NEIClientConfig.getBooleanSetting("inventory.guirecipe.scrollPages")
|
||||
&& this.container.boundsInside().contains(mouse.x, mouse.y)
|
||||
|| this.pageArea.contains(mouse)
|
||||
&& (!this.handler.searchingAvailable() || !GuiRecipe.toggleSearch.contains(mouse.x, mouse.y))
|
||||
&& (!GuiRecipe.searchField.isVisible() || !GuiRecipe.searchField.contains(mouse.x, mouse.y))) {
|
||||
|
||||
if (scroll > 0) {
|
||||
prevPage();
|
||||
} else {
|
||||
@@ -784,9 +825,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);
|
||||
|
||||
@@ -824,26 +866,26 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
final int textMiddle = (BUTTON_WIDTH - this.fontRendererObj.FONT_HEIGHT) / 2;
|
||||
|
||||
drawRect(
|
||||
this.prevtype.xPosition + BUTTON_WIDTH - 1,
|
||||
this.prevtype.yPosition,
|
||||
this.nexttype.xPosition,
|
||||
this.prevtype.yPosition + BUTTON_HEIGHT,
|
||||
this.typeArea.x,
|
||||
this.typeArea.y,
|
||||
this.typeArea.x + this.typeArea.width,
|
||||
this.typeArea.y + this.typeArea.height,
|
||||
0x30000000);
|
||||
drawRect(
|
||||
this.prevpage.xPosition + BUTTON_WIDTH - 1,
|
||||
this.prevpage.yPosition,
|
||||
this.nextpage.xPosition,
|
||||
this.prevpage.yPosition + BUTTON_HEIGHT,
|
||||
this.pageArea.x,
|
||||
this.pageArea.y,
|
||||
this.pageArea.x + this.pageArea.width,
|
||||
this.pageArea.y + this.pageArea.height,
|
||||
0x30000000);
|
||||
|
||||
final String handlerTitle = this.handler.original.getRecipeName().trim();
|
||||
final String titleColorCode = getHandlerTitleColorCode(isHandlerTitleHovered(mouseX, mouseY));
|
||||
final int titleColor = getHandlerTitleColor(isHandlerTitleHovered(mouseX, mouseY));
|
||||
drawCenteredString(
|
||||
this.fontRendererObj,
|
||||
titleColorCode + handlerTitle + EnumChatFormatting.RESET,
|
||||
handlerTitle,
|
||||
this.guiLeft + this.xSize / 2,
|
||||
this.prevtype.yPosition + textMiddle,
|
||||
0xffffff);
|
||||
this.typeArea.y + textMiddle,
|
||||
titleColor);
|
||||
|
||||
if (this.handler.searchingAvailable()) {
|
||||
GuiRecipe.toggleSearch.draw(mouseX, mouseY);
|
||||
@@ -865,7 +907,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
this.fontRendererObj,
|
||||
recipePage,
|
||||
GuiRecipe.searchField.x + GuiRecipe.searchField.w + 22,
|
||||
this.prevpage.yPosition + textMiddle,
|
||||
this.pageArea.y + textMiddle,
|
||||
0xffffff);
|
||||
} else {
|
||||
final String recipePage = NEIClientUtils.translate(
|
||||
@@ -876,7 +918,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
this.fontRendererObj,
|
||||
recipePage,
|
||||
this.guiLeft + this.xSize / 2,
|
||||
this.prevpage.yPosition + textMiddle,
|
||||
this.pageArea.y + textMiddle,
|
||||
0xffffff);
|
||||
}
|
||||
|
||||
@@ -897,13 +939,8 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
return new Rectangle(titleX, titleY, titleWidth, this.fontRendererObj.FONT_HEIGHT).contains(mousex, mousey);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
return hovered ? EnumChatFormatting.YELLOW.toString() : EnumChatFormatting.WHITE.toString();
|
||||
private int getHandlerTitleColor(boolean hovered) {
|
||||
return hovered ? ColorUtils.recipeTitleHover.getColor() : ColorUtils.recipeTitle.getColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,12 +23,13 @@ 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.ColorUtils;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.Widget;
|
||||
import codechicken.nei.drawable.DrawableResource;
|
||||
import codechicken.nei.event.NEIRegisterHandlerInfosEvent;
|
||||
@@ -127,7 +128,7 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
|
||||
int textCenterX = x + (int) (getWidth() / 2f);
|
||||
int textCenterY = y + (int) (getHeight() / 2f) - 3;
|
||||
int color = selected ? 0xffffa0 : 0xe0e0e0;
|
||||
int color = selected ? ColorUtils.buttonLabelHover.getColor() : ColorUtils.buttonLabelNormal.getColor();
|
||||
fontRenderer.drawStringWithShadow(
|
||||
text,
|
||||
textCenterX - (int) (fontRenderer.getStringWidth(text) / 2f),
|
||||
@@ -139,18 +140,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);
|
||||
@@ -265,8 +264,13 @@ public abstract class GuiRecipeTab extends Widget {
|
||||
NEIClientConfig.logger.info("Error setting handler dimensions for " + handler);
|
||||
}
|
||||
|
||||
info.setUseCustomScroll(
|
||||
record.isSet("useCustomScroll") ? Boolean.parseBoolean(record.get("useCustomScroll")) : false);
|
||||
final boolean allowOverflow = record.isSet("useCustomScroll")
|
||||
&& Boolean.parseBoolean(record.get("useCustomScroll"));
|
||||
info.setAllowOverflowX(
|
||||
record.isSet("allowOverflowX") ? Boolean.parseBoolean(record.get("allowOverflowX")) : true);
|
||||
info.setAllowOverflowY(
|
||||
record.isSet("allowOverflowY") ? Boolean.parseBoolean(record.get("allowOverflowY"))
|
||||
: allowOverflow);
|
||||
handlerMap.put(handler, info);
|
||||
NEIClientConfig.logger.info("Loaded " + handler);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,10 @@ public class HandlerInfo {
|
||||
private boolean multipleWidgetsAllowed = false;
|
||||
private boolean showFavoritesButton = true;
|
||||
private boolean showOverlayButton = true;
|
||||
private boolean useCustomScroll = false;
|
||||
private boolean showBadge = false;
|
||||
|
||||
private boolean allowOverflowX = true;
|
||||
private boolean allowOverflowY = false;
|
||||
|
||||
private ItemStack itemStack = null;
|
||||
private DrawableResource image = null;
|
||||
@@ -142,12 +145,34 @@ public class HandlerInfo {
|
||||
this.showOverlayButton = showOverlayButton;
|
||||
}
|
||||
|
||||
public boolean getUseCustomScroll() {
|
||||
return this.useCustomScroll;
|
||||
public boolean getShowBadge() {
|
||||
return this.showBadge;
|
||||
}
|
||||
|
||||
public void setShowBadge(boolean showBadge) {
|
||||
this.showBadge = showBadge;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setUseCustomScroll(boolean useCustomScroll) {
|
||||
this.useCustomScroll = useCustomScroll;
|
||||
this.allowOverflowX = useCustomScroll;
|
||||
this.allowOverflowY = useCustomScroll;
|
||||
}
|
||||
|
||||
public boolean isAllowOverflowX() {
|
||||
return this.allowOverflowX;
|
||||
}
|
||||
|
||||
public void setAllowOverflowX(boolean allowOverflowX) {
|
||||
this.allowOverflowX = allowOverflowX;
|
||||
}
|
||||
|
||||
public boolean isAllowOverflowY() {
|
||||
return this.allowOverflowY;
|
||||
}
|
||||
|
||||
public void setAllowOverflowY(boolean allowOverflowY) {
|
||||
this.allowOverflowY = allowOverflowY;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
@@ -186,6 +211,7 @@ public class HandlerInfo {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Builder setUseCustomScroll(boolean useCustomScroll) {
|
||||
this.info.setUseCustomScroll(useCustomScroll);
|
||||
return this;
|
||||
@@ -216,6 +242,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;
|
||||
@@ -227,6 +258,16 @@ public class HandlerInfo {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAllowOverflowX(boolean allowOverflowX) {
|
||||
this.info.allowOverflowX = allowOverflowX;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setAllowOverflowY(boolean allowOverflowY) {
|
||||
this.info.allowOverflowY = allowOverflowY;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HandlerInfo build() {
|
||||
return this.info;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,9 @@ 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.KeyManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIServerUtils;
|
||||
@@ -40,6 +42,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;
|
||||
@@ -64,7 +67,7 @@ public class NEIRecipeWidget extends Widget {
|
||||
|
||||
public void update() {
|
||||
|
||||
if (this.showAsWidget || !this.handlerInfo.getUseCustomScroll()) {
|
||||
if (this.showAsWidget || !this.handlerInfo.isAllowOverflowY()) {
|
||||
final int recipeHeight = this.handlerRef.handler.getRecipeHeight(this.handlerRef.recipeIndex);
|
||||
this.w = Math.max(166, this.handlerInfo.getWidth());
|
||||
this.h = recipeHeight > 0 ? recipeHeight : this.handlerInfo.getHeight();
|
||||
@@ -143,7 +146,7 @@ public class NEIRecipeWidget extends Widget {
|
||||
final List<GuiRecipeButton> buttons = new ArrayList<>();
|
||||
final boolean showFavorites = NEIClientConfig.favoritesEnabled() && handlerInfo.getShowFavoritesButton();
|
||||
final boolean showOverlay = handlerInfo.getShowOverlayButton();
|
||||
final int x = Math.min(168, this.w) - GuiRecipeButton.BUTTON_WIDTH;
|
||||
final int x = Math.min(166, this.w) - GuiRecipeButton.BUTTON_WIDTH;
|
||||
int y = this.h - GuiRecipeButton.BUTTON_HEIGHT - 6;
|
||||
|
||||
if (guiContainer instanceof IGuiContainerOverlay overlay) {
|
||||
@@ -196,11 +199,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 +208,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,11 +246,60 @@ 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) {
|
||||
|
||||
if (NEIClientConfig.favoritesEnabled() && NEIClientUtils.shiftKey()
|
||||
&& NEIClientConfig.isKeyHashDown("gui.favorite_item")) {
|
||||
if (NEIClientConfig.favoritesEnabled()
|
||||
&& KeyManager.isHashDown("bookmark.favorite_item", NEIClientUtils.SHIFT_HASH)) {
|
||||
final Point mouse = GuiDraw.getMousePosition();
|
||||
final int yShift = this.handlerInfo.getYShift();
|
||||
PositionedStack pStackOver = null;
|
||||
@@ -366,27 +406,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) {
|
||||
@@ -423,7 +458,7 @@ public class NEIRecipeWidget extends Widget {
|
||||
pStack -> this.permutations.getOrDefault(pStack, Collections.emptyList()).size() > 1
|
||||
&& pStack.contains(mouseX - this.x, mouseY - this.y - yShift))) {
|
||||
hotkeys.put(
|
||||
NEIClientConfig.getKeyName("gui.favorite_item", NEIClientUtils.SHIFT_HASH),
|
||||
KeyManager.getKeyName("bookmark.favorite_item", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("recipe.favorite.toggle"));
|
||||
}
|
||||
|
||||
@@ -568,6 +603,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,25 @@
|
||||
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.ColorUtils;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
@@ -20,12 +29,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 +140,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 +148,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, ColorUtils.textGray.getColor(), 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 +212,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 +243,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) {
|
||||
|
||||
@@ -77,9 +77,24 @@ public class RecipeHandlerRef {
|
||||
return this.handler.getOverlayHandler(firstGui, this.recipeIndex);
|
||||
}
|
||||
|
||||
if (firstGui != null && canUseSmartOverlay(firstGui)) {
|
||||
return SmartOverlayHandler.INSTANCE;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean canUseSmartOverlay(GuiContainer gui) {
|
||||
if (!(this.handler instanceof TemplateRecipeHandler templateHandler)
|
||||
|| templateHandler.getOverlayIdentifier() == null
|
||||
|| templateHandler.getGuiClass() == null
|
||||
|| !templateHandler.getGuiClass().isAssignableFrom(gui.getClass())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return SmartOverlayHandler.canHandle(gui, this.handler, this.recipeIndex);
|
||||
}
|
||||
|
||||
public boolean canFillCraftingGrid(GuiContainer gui) {
|
||||
final IOverlayHandler overlayHandler = getOverlayHandler(gui);
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@ public class RecipePageManager {
|
||||
this.cacheKey = cacheKey;
|
||||
this.pageWidgets.clear();
|
||||
|
||||
final boolean useCustomScroll = this.handlerInfo.getUseCustomScroll();
|
||||
final boolean allowOverflowY = this.handlerInfo.isAllowOverflowY();
|
||||
final int handlerHeight = this.handlerInfo.getHeight() + this.handlerInfo.getYShift();
|
||||
final boolean multipleWidgetsAllowed = !useCustomScroll && handlerInfo.isMultipleWidgetsAllowed();
|
||||
final boolean infiniteScroll = !useCustomScroll
|
||||
final boolean multipleWidgetsAllowed = !allowOverflowY && handlerInfo.isMultipleWidgetsAllowed();
|
||||
final boolean infiniteScroll = !allowOverflowY
|
||||
&& NEIClientConfig.getBooleanSetting("inventory.guirecipe.infiniteScroll");
|
||||
|
||||
final int heightAvailable = this.container.getVisibleHeight();
|
||||
@@ -59,7 +59,7 @@ public class RecipePageManager {
|
||||
final NEIRecipeWidget widget = RecipeHandlerRef.of(this.handler.original, recipeIndex).getRecipeWidget();
|
||||
widget.w = width;
|
||||
|
||||
if (useCustomScroll) {
|
||||
if (allowOverflowY) {
|
||||
widget.h = Math.min(handlerHeight, heightAvailable);
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public class RecipePageManager {
|
||||
}
|
||||
|
||||
public boolean isMultipleWidgetsAllowed() {
|
||||
return !this.handlerInfo.getUseCustomScroll() && this.handlerInfo.isMultipleWidgetsAllowed();
|
||||
return !this.handlerInfo.isAllowOverflowY() && this.handlerInfo.isMultipleWidgetsAllowed();
|
||||
}
|
||||
|
||||
public int getNumRecipes() {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.inventory.SlotCrafting;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import codechicken.nei.FastTransferManager;
|
||||
import codechicken.nei.PositionedStack;
|
||||
|
||||
public class SmartOverlayHandler extends DefaultOverlayHandler {
|
||||
|
||||
public static final SmartOverlayHandler INSTANCE = new SmartOverlayHandler();
|
||||
|
||||
private static final int MAX_RECIPE_SLOTS = 12;
|
||||
private static final int MAX_COST_DELTA = 16 * 16;
|
||||
|
||||
private SmartOverlayHandler() {}
|
||||
|
||||
public static boolean canHandle(GuiContainer gui, IRecipeHandler handler, int recipeIndex) {
|
||||
return INSTANCE.resolveSlots(gui, handler.getIngredientStacks(recipeIndex)) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int transferRecipe(GuiContainer gui, IRecipeHandler handler, int recipeIndex, int multiplier) {
|
||||
final List<PositionedStack> ingredients = handler.getIngredientStacks(recipeIndex);
|
||||
final List<DistributedIngred> ingredStacks = getPermutationIngredients(ingredients);
|
||||
final Slot[][] recipeSlots = resolveSlots(gui, ingredients);
|
||||
|
||||
if (recipeSlots == null || !clearMappedSlots(gui, recipeSlots)) return 0;
|
||||
|
||||
findInventoryQuantities(gui, ingredStacks);
|
||||
|
||||
final List<IngredientDistribution> assignedIngredients = assignIngredients(ingredients, ingredStacks);
|
||||
if (assignedIngredients == null) return 0;
|
||||
|
||||
assignIngredSlots(gui, ingredients, assignedIngredients);
|
||||
multiplier = Math.min(multiplier == 0 ? 64 : multiplier, calculateRecipeQuantity(assignedIngredients));
|
||||
|
||||
moveIngredients(gui, assignedIngredients, Math.max(1, multiplier));
|
||||
|
||||
return assignedIngredients.stream().anyMatch(distrib -> distrib.distrib.distributed == 0) ? 0 : multiplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canFillCraftingGrid(GuiContainer firstGui, IRecipeHandler handler, int recipeIndex) {
|
||||
return canHandle(firstGui, handler, recipeIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<Slot> getCraftMatrixSlots(GuiContainer gui, IRecipeHandler handler) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slot[][] mapIngredSlots(GuiContainer gui, List<PositionedStack> ingredients) {
|
||||
Slot[][] exactSlots = super.mapIngredSlots(gui, ingredients);
|
||||
if (!hasEmptyMappings(exactSlots)) {
|
||||
return exactSlots;
|
||||
}
|
||||
|
||||
Slot[][] smartSlots = resolveSlots(gui, ingredients);
|
||||
return smartSlots == null ? exactSlots : smartSlots;
|
||||
}
|
||||
|
||||
private boolean clearMappedSlots(GuiContainer gui, Slot[][] recipeSlots) {
|
||||
Set<Slot> cleared = new HashSet<>();
|
||||
|
||||
for (Slot[] slots : recipeSlots) {
|
||||
for (Slot slot : slots) {
|
||||
if (cleared.add(slot) && slot.getHasStack() && slot.canTakeStack(gui.mc.thePlayer)) {
|
||||
FastTransferManager.clickSlot(gui, slot.slotNumber, 0, 1);
|
||||
if (slot.getHasStack()) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FastTransferManager.dropHeldItem(gui);
|
||||
return gui.mc.thePlayer.inventory.getItemStack() == null;
|
||||
}
|
||||
|
||||
private Slot[][] resolveSlots(GuiContainer gui, List<PositionedStack> ingredients) {
|
||||
if (ingredients == null || ingredients.isEmpty() || ingredients.size() > MAX_RECIPE_SLOTS) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Slot> candidates = new ArrayList<>();
|
||||
for (Slot slot : gui.inventorySlots.inventorySlots) {
|
||||
if (isDestinationCandidate(slot)) {
|
||||
candidates.add(slot);
|
||||
}
|
||||
}
|
||||
|
||||
if (candidates.size() < ingredients.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Assignment best = new Assignment();
|
||||
Assignment secondBest = new Assignment();
|
||||
searchAssignments(
|
||||
ingredients,
|
||||
candidates,
|
||||
new boolean[candidates.size()],
|
||||
new Slot[ingredients.size()],
|
||||
0,
|
||||
0,
|
||||
best,
|
||||
secondBest);
|
||||
|
||||
if (best.slots == null || secondBest.cost - best.cost <= MAX_COST_DELTA) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Slot[][] resolved = new Slot[ingredients.size()][];
|
||||
for (int i = 0; i < ingredients.size(); i++) {
|
||||
resolved[i] = new Slot[] { best.slots[i] };
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
private void searchAssignments(List<PositionedStack> ingredients, List<Slot> candidates, boolean[] used,
|
||||
Slot[] assigned, int ingredientIndex, int cost, Assignment best, Assignment secondBest) {
|
||||
if (cost >= secondBest.cost) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ingredientIndex == ingredients.size()) {
|
||||
if (cost < best.cost) {
|
||||
secondBest.copyFrom(best);
|
||||
best.set(cost, assigned);
|
||||
} else if (cost < secondBest.cost) {
|
||||
secondBest.set(cost, assigned);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
PositionedStack ingredient = ingredients.get(ingredientIndex);
|
||||
for (int i = 0; i < candidates.size(); i++) {
|
||||
if (used[i]) continue;
|
||||
|
||||
Slot slot = candidates.get(i);
|
||||
int slotCost = getSlotCost(ingredient, slot);
|
||||
if (slotCost < 0) continue;
|
||||
|
||||
used[i] = true;
|
||||
assigned[ingredientIndex] = slot;
|
||||
searchAssignments(
|
||||
ingredients,
|
||||
candidates,
|
||||
used,
|
||||
assigned,
|
||||
ingredientIndex + 1,
|
||||
cost + slotCost,
|
||||
best,
|
||||
secondBest);
|
||||
assigned[ingredientIndex] = null;
|
||||
used[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
private int getSlotCost(PositionedStack ingredient, Slot slot) {
|
||||
boolean acceptsAnyPermutation = false;
|
||||
for (ItemStack permutation : ingredient.items) {
|
||||
if (canUseSlot(slot, permutation)) {
|
||||
acceptsAnyPermutation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!acceptsAnyPermutation) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int dx = slot.xDisplayPosition - (ingredient.relx + offsetx);
|
||||
int dy = slot.yDisplayPosition - (ingredient.rely + offsety);
|
||||
int cost = dx * dx + dy * dy;
|
||||
|
||||
if (slot.getHasStack()) {
|
||||
cost += 10_000;
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
private boolean canUseSlot(Slot slot, ItemStack stack) {
|
||||
if (stack == null || stack.stackSize <= 0 || !slot.isItemValid(stack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!slot.inventory.isItemValidForSlot(slot.getSlotIndex(), stack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !slot.getHasStack() || canStack(slot.getStack(), stack);
|
||||
}
|
||||
|
||||
private boolean isDestinationCandidate(Slot slot) {
|
||||
return slot != null && !(slot.inventory instanceof InventoryPlayer) && !(slot instanceof SlotCrafting);
|
||||
}
|
||||
|
||||
private boolean hasEmptyMappings(Slot[][] recipeSlots) {
|
||||
for (Slot[] recipeSlot : recipeSlots) {
|
||||
if (recipeSlot.length == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class Assignment {
|
||||
|
||||
int cost = Integer.MAX_VALUE;
|
||||
Slot[] slots;
|
||||
|
||||
void set(int cost, Slot[] slots) {
|
||||
this.cost = cost;
|
||||
this.slots = slots.clone();
|
||||
}
|
||||
|
||||
void copyFrom(Assignment other) {
|
||||
this.cost = other.cost;
|
||||
this.slots = other.slots == null ? null : other.slots.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import com.google.common.base.Stopwatch;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.ItemList;
|
||||
import codechicken.nei.KeyManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.NEIServerUtils;
|
||||
@@ -84,12 +85,13 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
efuels.add(Item.getItemFromBlock(Blocks.wooden_door));
|
||||
efuels.add(Item.getItemFromBlock(Blocks.trapped_chest));
|
||||
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
final Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
final List<ItemStack> itemsSnapshot = new ArrayList<>(ItemList.items);
|
||||
if (parallel) {
|
||||
try {
|
||||
FurnaceRecipeHandler.afuels = ItemList.forkJoinPool
|
||||
.submit(
|
||||
() -> ItemList.items.parallelStream().map(TemplateRecipeHandler::identifyFuel)
|
||||
() -> itemsSnapshot.parallelStream().map(TemplateRecipeHandler::identifyFuel)
|
||||
.filter(Objects::nonNull).collect(Collectors.toCollection(ArrayList::new)))
|
||||
.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
@@ -97,7 +99,7 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
FurnaceRecipeHandler.afuels = ItemList.items.stream().map(TemplateRecipeHandler::identifyFuel)
|
||||
FurnaceRecipeHandler.afuels = itemsSnapshot.stream().map(TemplateRecipeHandler::identifyFuel)
|
||||
.filter(Objects::nonNull).collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
@@ -287,9 +289,9 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
if (!canHandle(gui)) return false;
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.recipe")) {
|
||||
if (KeyManager.isHashDown("recipe.recipe")) {
|
||||
return transferRect(gui, false);
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.usage")) {
|
||||
} else if (KeyManager.isHashDown("recipe.usage")) {
|
||||
return transferRect(gui, true);
|
||||
}
|
||||
|
||||
@@ -380,8 +382,13 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
public LinkedList<RecipeTransferRect> transferRects = new LinkedList<>();
|
||||
|
||||
public TemplateRecipeHandler() {
|
||||
loadTransferRects();
|
||||
RecipeTransferRectHandler.registerRectsToGuis(getRecipeTransferRectGuis(), transferRects);
|
||||
try {
|
||||
loadTransferRects();
|
||||
RecipeTransferRectHandler.registerRectsToGuis(getRecipeTransferRectGuis(), transferRects);
|
||||
} catch (Exception e) {
|
||||
NEIClientConfig.logger
|
||||
.error("NEI: Failed to load transfer rects for {}: {}", getClass().getName(), e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -535,6 +542,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);
|
||||
@@ -648,9 +673,9 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
@Override
|
||||
public boolean keyTyped(GuiRecipe<?> gui, char keyChar, int keyCode, int recipe) {
|
||||
|
||||
if (NEIClientConfig.isKeyHashDown("gui.recipe")) {
|
||||
if (KeyManager.isHashDown("recipe.recipe")) {
|
||||
return transferRect(gui, recipe, false);
|
||||
} else if (NEIClientConfig.isKeyHashDown("gui.usage")) {
|
||||
} else if (KeyManager.isHashDown("recipe.usage")) {
|
||||
return transferRect(gui, recipe, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,18 +6,18 @@ 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;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.IntPredicate;
|
||||
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,58 +46,94 @@ public class DebugHandlerWidget extends Widget {
|
||||
|
||||
private static class HandlerInfoRecord {
|
||||
|
||||
public HandlerInfo info;
|
||||
public String handlerKey;
|
||||
public int yShift;
|
||||
public int width;
|
||||
public int height;
|
||||
public boolean multiWidgets;
|
||||
public int order;
|
||||
public boolean useCustomScroll;
|
||||
public boolean allowOverflowX;
|
||||
public boolean allowOverflowY;
|
||||
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();
|
||||
this.height = info.getHeight();
|
||||
this.multiWidgets = info.isMultipleWidgetsAllowed();
|
||||
this.order = NEIClientConfig.handlerOrdering.getOrDefault(handlerKey, 0);
|
||||
this.useCustomScroll = info.getUseCustomScroll();
|
||||
this.allowOverflowX = info.isAllowOverflowX();
|
||||
this.allowOverflowY = info.isAllowOverflowY();
|
||||
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.setAllowOverflowX(this.allowOverflowX);
|
||||
this.info.setAllowOverflowY(this.allowOverflowY);
|
||||
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.allowOverflowX = intOrDefault(parts[6], this.allowOverflowX ? 1 : 0) == 1;
|
||||
this.allowOverflowY = intOrDefault(parts[7], this.allowOverflowY ? 1 : 0) == 1;
|
||||
this.showFavorites = intOrDefault(parts[8], this.showFavorites ? 1 : 0) == 1;
|
||||
this.showOverlay = intOrDefault(parts[9], this.showOverlay ? 1 : 0) == 1;
|
||||
this.showBadge = intOrDefault(parts[10], 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.allowOverflowX ? 1 : 0),
|
||||
String.valueOf(this.allowOverflowY ? 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 +142,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,AllowOverflowX,AllowOverflowY,ShowFavorites,ShowOverlay,ShowBadge";
|
||||
private final int[] COLORS = new int[] { 0x2200FF00, 0x22FF0000, 0x220000FF, 0x2200FFFF, 0x22FF00FF, 0x22FFFF00 };
|
||||
|
||||
public static DebugHandlerWidget instance = new DebugHandlerWidget();
|
||||
@@ -114,12 +151,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 +183,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();
|
||||
}
|
||||
|
||||
}, y);
|
||||
record.order = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}, null, y);
|
||||
|
||||
y = addTextFieldWidget("yShift", 0, (field, oldText) -> {
|
||||
|
||||
if (field.getInteger() != handlerInfo.getYShift()) {
|
||||
handlerInfo.setYShift(field.getInteger());
|
||||
record.yShift = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}
|
||||
|
||||
}, y);
|
||||
record.yShift = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}, null, y);
|
||||
|
||||
y = addCheckboxWidget("MultiWidgets", button -> {
|
||||
handlerInfo.setMultipleWidgetsAllowed(button.value);
|
||||
record.multiWidgets = button.value;
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
@@ -182,43 +208,40 @@ 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();
|
||||
}
|
||||
|
||||
}, y);
|
||||
record.height = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}, newValue -> newValue > 0, y);
|
||||
|
||||
y = addTextFieldWidget("Width", HandlerInfo.DEFAULT_WIDTH, (field, oldText) -> {
|
||||
record.width = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}, newValue -> newValue >= HandlerInfo.DEFAULT_WIDTH, y);
|
||||
|
||||
if (field.getInteger() != handlerInfo.getWidth()) {
|
||||
handlerInfo.setHandlerDimensions(field.getInteger(), handlerInfo.getHeight());
|
||||
record.width = field.getInteger();
|
||||
saveHandlerInfoPatch();
|
||||
}
|
||||
|
||||
y = addCheckboxWidget("AllowOverflowX", button -> {
|
||||
record.allowOverflowX = button.value;
|
||||
saveHandlerInfoPatch();
|
||||
}, y);
|
||||
|
||||
y = addCheckboxWidget("UseCustomScroll", button -> {
|
||||
handlerInfo.setUseCustomScroll(button.value);
|
||||
record.useCustomScroll = button.value;
|
||||
y = addCheckboxWidget("AllowOverflowY", button -> {
|
||||
record.allowOverflowY = 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;
|
||||
}
|
||||
@@ -241,9 +264,10 @@ public class DebugHandlerWidget extends Widget {
|
||||
return y + value.h + 1;
|
||||
}
|
||||
|
||||
private int addTextFieldWidget(String key, int defaultValue, BiConsumer<IntegerField, String> onChange, int y) {
|
||||
private int addTextFieldWidget(String key, int defaultValue, BiConsumer<IntegerField, String> onChange,
|
||||
IntPredicate validator, int y) {
|
||||
final LabelWidget label = new LabelWidget(0x888888, false);
|
||||
final IntegerField value = new IntegerField(key, onChange, defaultValue);
|
||||
final IntegerField value = new IntegerField(key, onChange, validator, defaultValue);
|
||||
|
||||
label.y = value.y = y;
|
||||
value.w = 60;
|
||||
@@ -278,10 +302,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 +384,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));
|
||||
@@ -344,14 +408,14 @@ public class DebugHandlerWidget extends Widget {
|
||||
this.values.get("width").updateValue(String.valueOf(this.record.width));
|
||||
|
||||
this.values.get("multiwidgets").updateValue(String.valueOf(this.record.multiWidgets));
|
||||
this.values.get("usecustomscroll").updateValue(String.valueOf(this.record.useCustomScroll));
|
||||
this.values.get("allowoverflowx").updateValue(String.valueOf(this.record.allowOverflowX));
|
||||
this.values.get("allowoverflowy").updateValue(String.valueOf(this.record.allowOverflowY));
|
||||
|
||||
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 +428,7 @@ public class DebugHandlerWidget extends Widget {
|
||||
}
|
||||
|
||||
} else {
|
||||
this.handler = null;
|
||||
this.record = null;
|
||||
this.handlerInfo = null;
|
||||
this.showWidget = false;
|
||||
}
|
||||
|
||||
@@ -375,12 +437,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 +452,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 +468,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 +476,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 +486,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 +506,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 +516,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
|
||||
@@ -539,29 +601,23 @@ public class DebugHandlerWidget extends Widget {
|
||||
public void loadHandlerInfoPatch() {
|
||||
|
||||
ClientHandler.loadSettingsFile("handlers.patch", lines -> {
|
||||
final List<String> linesList = lines.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
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];
|
||||
if (linesList.isEmpty() || !HEADER.equals(linesList.get(0))) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
linesList.remove(0);
|
||||
|
||||
for (String line : linesList) {
|
||||
final String[] parts = line.split(",");
|
||||
final String handlerKey = parts[0];
|
||||
final HandlerInfoRecord record = patches.computeIfAbsent(
|
||||
handlerKey,
|
||||
key -> new HandlerInfoRecord(
|
||||
key,
|
||||
GuiRecipeTab.handlerMap.getOrDefault(key, GuiRecipeTab.DEFAULT_HANDLER_INFO)));
|
||||
record.apply((line + ",null,null,null,null,null,null,null,null,null,null"));
|
||||
}
|
||||
|
||||
});
|
||||
@@ -585,9 +641,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,20 +650,22 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
private String getHandlerID(IRecipeHandler handler) {
|
||||
|
||||
if (GuiRecipeTab.handlerMap.containsKey(handler.getHandlerId())) {
|
||||
return handler.getHandlerId();
|
||||
} else if (handler instanceof TemplateRecipeHandler) {
|
||||
if (!GuiRecipeTab.handlerMap.containsKey(handler.getHandlerId()) && handler instanceof TemplateRecipeHandler
|
||||
&& handler.getOverlayIdentifier() != null) {
|
||||
return handler.getOverlayIdentifier();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package codechicken.nei.recipe.debug;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.IntPredicate;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
@@ -13,10 +14,13 @@ public class IntegerField extends TextField implements IUpdatableWidget {
|
||||
|
||||
protected int defaultValue = 0;
|
||||
protected BiConsumer<IntegerField, String> onChange;
|
||||
protected IntPredicate validator;
|
||||
|
||||
public IntegerField(String ident, BiConsumer<IntegerField, String> onChange, int defaultValue) {
|
||||
public IntegerField(String ident, BiConsumer<IntegerField, String> onChange, IntPredicate validator,
|
||||
int defaultValue) {
|
||||
super(ident);
|
||||
this.onChange = onChange;
|
||||
this.validator = validator;
|
||||
this.defaultValue = defaultValue;
|
||||
this.h = 16;
|
||||
this.z = 2;
|
||||
@@ -68,8 +72,12 @@ public class IntegerField extends TextField implements IUpdatableWidget {
|
||||
}
|
||||
|
||||
protected int getInteger() {
|
||||
return getInteger(text());
|
||||
}
|
||||
|
||||
protected int getInteger(String text) {
|
||||
try {
|
||||
return Integer.parseInt(text());
|
||||
return Integer.parseInt(text);
|
||||
} catch (NumberFormatException nfe) {
|
||||
return this.defaultValue;
|
||||
}
|
||||
@@ -78,10 +86,17 @@ public class IntegerField extends TextField implements IUpdatableWidget {
|
||||
@Override
|
||||
public boolean onMouseWheel(int i, int mx, int my) {
|
||||
if (!contains(mx, my)) return false;
|
||||
setText(Integer.toString(getInteger() + i));
|
||||
setText(Integer.toString(getInteger() - i));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText(String newValue) {
|
||||
if (validator == null || validator.test(getInteger(newValue))) {
|
||||
super.setText(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateValue(String newValue) {
|
||||
setText(newValue);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ public class DefaultStackStringifyHandler implements IStackStringifyHandler {
|
||||
final NBTTagCompound nbTag = new NBTTagCompound();
|
||||
nbTag.setString("strId", strId);
|
||||
nbTag.setInteger("Count", saveStackSize ? stack.stackSize : 1);
|
||||
nbTag.setShort("Damage", (short) stack.getItemDamage());
|
||||
nbTag.setInteger("Damage", stack.getItemDamage());
|
||||
|
||||
if (stack.hasTagCompound() && !stack.getTagCompound().hasNoTags()) {
|
||||
nbTag.setTag("tag", stack.getTagCompound().copy());
|
||||
@@ -35,7 +35,7 @@ public class DefaultStackStringifyHandler implements IStackStringifyHandler {
|
||||
final String strId = nbtTag.getString("strId");
|
||||
|
||||
nbtTag = (NBTTagCompound) nbtTag.copy();
|
||||
nbtTag.setShort("id", (short) GameData.getItemRegistry().getId(strId)); // getObject
|
||||
nbtTag.setInteger("id", GameData.getItemRegistry().getId(strId)); // getObject
|
||||
|
||||
final ItemStack stack = ItemStack.loadItemStackFromNBT(nbtTag);
|
||||
|
||||
|
||||
@@ -179,11 +179,15 @@ public class ItemUntranslator {
|
||||
}
|
||||
|
||||
private void collectDisplayNameForStack(ItemStack stack, Map<String, String> items) {
|
||||
final String displayName = stripFormatting(stack.getDisplayName());
|
||||
final String guidKey = determineGUIDForGeneration(stack, displayName, items);
|
||||
try {
|
||||
final String displayName = stripFormatting(stack.getDisplayName());
|
||||
final String guidKey = determineGUIDForGeneration(stack, displayName, items);
|
||||
|
||||
if (!items.containsKey(guidKey)) {
|
||||
items.put(guidKey, displayName);
|
||||
if (!items.containsKey(guidKey)) {
|
||||
items.put(guidKey, displayName);
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
NEIClientConfig.logger.warn("Failed to get display name for itemstack {}", stack, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,11 +60,11 @@ nei.options.wbutton.tip.1=Přepisuji globální nastavení
|
||||
|
||||
nei.options.keys=Nastavení kláves
|
||||
nei.options.keys.gui=Inventář
|
||||
nei.options.keys.gui.recipe=Recept
|
||||
nei.options.keys.gui.usage=Použití
|
||||
nei.options.keys.recipe.recipe=Recept
|
||||
nei.options.keys.recipe.usage=Použití
|
||||
nei.options.keys.gui.enchant=Očarování
|
||||
nei.options.keys.gui.potion=Lektvary
|
||||
nei.options.keys.gui.back=Předchozí recept
|
||||
nei.options.keys.recipe.back=Předchozí recept
|
||||
nei.options.keys.gui.prev=Předchozí stránka
|
||||
nei.options.keys.gui.next=Další stránka
|
||||
nei.options.keys.gui.hide=Přepnout viditelnost NEI
|
||||
|
||||
@@ -64,11 +64,11 @@ nei.options.wbutton.tip.1=Übergeht globale Einstellungen
|
||||
|
||||
nei.options.keys=Tastenbelegung
|
||||
nei.options.keys.gui=Inventar
|
||||
nei.options.keys.gui.recipe=Rezept
|
||||
nei.options.keys.gui.usage=Nutzung
|
||||
nei.options.keys.recipe.recipe=Rezept
|
||||
nei.options.keys.recipe.usage=Nutzung
|
||||
nei.options.keys.gui.enchant=Verzauberungen
|
||||
nei.options.keys.gui.potion=Tränke
|
||||
nei.options.keys.gui.back=Vorheriges Rezept
|
||||
nei.options.keys.recipe.back=Vorheriges Rezept
|
||||
nei.options.keys.gui.prev=Vorherige Seite
|
||||
nei.options.keys.gui.next=Nächste Seite
|
||||
nei.options.keys.gui.hide=Verstelle NEI-Sichtbarkeit
|
||||
|
||||
@@ -169,41 +169,46 @@ nei.options.wbutton.tip.0=Using global settings
|
||||
nei.options.wbutton.tip.1=Overriding global setting
|
||||
|
||||
nei.options.keys=KeyBindings
|
||||
nei.options.keys.tip=Configure NEI key bindings in the Minecraft controls screen
|
||||
nei.options.keys.gui=NEI Inventory
|
||||
nei.options.keys.world=NEI World
|
||||
nei.options.keys.recipe=NEI Recipe
|
||||
nei.options.keys.bookmark=NEI Bookmarks
|
||||
nei.options.keys.copy=NEI Copy
|
||||
nei.options.keys.itemzoom=NEI Item Zoom
|
||||
nei.options.keys.showenchant=Show Enchant
|
||||
nei.options.keys.gui=Inventory
|
||||
nei.options.keys.gui.recipe=Recipe
|
||||
nei.options.keys.gui.usage=Usage
|
||||
nei.options.keys.recipe.recipe=Recipe
|
||||
nei.options.keys.recipe.usage=Usage
|
||||
nei.options.keys.gui.enchant=Enchantments
|
||||
nei.options.keys.gui.potion=Potions
|
||||
nei.options.keys.gui.back=Back to last Recipe
|
||||
nei.options.keys.recipe.back=Back to last Recipe
|
||||
nei.options.keys.gui.prev=Prev Item Panel Page
|
||||
nei.options.keys.gui.next=Next Item Panel Page
|
||||
nei.options.keys.gui.hide=Toggle NEI Visibility
|
||||
nei.options.keys.gui.next_recipe=Next Recipe
|
||||
nei.options.keys.gui.prev_recipe=Prev Recipe
|
||||
nei.options.keys.gui.next_machine=Next Machine
|
||||
nei.options.keys.gui.prev_machine=Prev Machine
|
||||
nei.options.keys.gui.hide=Toggle Visibility
|
||||
nei.options.keys.recipe.next_recipe=Next Recipe
|
||||
nei.options.keys.recipe.prev_recipe=Prev Recipe
|
||||
nei.options.keys.recipe.next_machine=Next Machine
|
||||
nei.options.keys.recipe.prev_machine=Prev Machine
|
||||
nei.options.keys.gui.search=Focus Search Bar
|
||||
nei.options.keys.gui.bookmark=Add Bookmark
|
||||
nei.options.keys.gui.remove_recipe=Remove Group from Bookmarks
|
||||
nei.options.keys.gui.bookmark_pull_items=Pull all Bookmarked Items
|
||||
nei.options.keys.gui.hide_bookmarks=Toggle Bookmark Panel Visibility
|
||||
nei.options.keys.bookmark.add=Add Bookmark
|
||||
nei.options.keys.bookmark.remove_recipe=Remove Group from Bookmarks (Shift +)
|
||||
nei.options.keys.bookmark.pull_items=Pull all Bookmarked Items
|
||||
nei.options.keys.bookmark.hide=Toggle Bookmark Panel Visibility
|
||||
nei.options.keys.gui.overlay=Fill/Overlay Crafting Grid
|
||||
nei.options.keys.gui.getprevioussearch=Previous Search
|
||||
nei.options.keys.gui.getnextsearch=Next Search
|
||||
nei.options.keys.gui.next_tooltip=Next Tooltip
|
||||
nei.options.keys.gui.copy_name=Copy Item Name
|
||||
nei.options.keys.gui.craft_items=Craft Items
|
||||
nei.options.keys.gui.copy_oredict=Copy Item OreDictionary
|
||||
nei.options.keys.gui.copy_id=Copy Item ID
|
||||
nei.options.keys.gui.chat_link_item=Send item link to chat
|
||||
nei.options.keys.gui.itemzoom_toggle=Toggle Item Zoom
|
||||
nei.options.keys.gui.itemzoom_hold=Hold to Display Item Zoom
|
||||
nei.options.keys.gui.itemzoom_zoom_in=Item Zoom In
|
||||
nei.options.keys.gui.itemzoom_zoom_out=Item Zoom Out
|
||||
nei.options.keys.gui.favorite=Add Favorite
|
||||
nei.options.keys.gui.favorite_item=Toggle Favorite
|
||||
nei.options.keys.world=World
|
||||
nei.options.keys.copy.name=Copy Item Name (Ctrl +)
|
||||
nei.options.keys.gui.craft_items=Craft Items (Shift +)
|
||||
nei.options.keys.copy.oredict=Copy Item OreDictionary (Ctrl +)
|
||||
nei.options.keys.copy.identifier=Copy Item ID (Ctrl +)
|
||||
nei.options.keys.copy.chat_link_item=Send item link to chat (Ctrl +)
|
||||
nei.options.keys.itemzoom.toggle=Toggle Item Zoom (Shift +)
|
||||
nei.options.keys.itemzoom.hold=Hold to Display Item Zoom
|
||||
nei.options.keys.itemzoom.zoom_in=Item Zoom In
|
||||
nei.options.keys.itemzoom.zoom_out=Item Zoom Out
|
||||
nei.options.keys.bookmark.favorite=Add Favorite (Shift +)
|
||||
nei.options.keys.bookmark.favorite_item=Toggle Favorite (Shift +)
|
||||
nei.options.keys.world.chunkoverlay=Chunk Boundary Overlay
|
||||
nei.options.keys.world.moboverlay=Mob Spawn Overlay
|
||||
nei.options.keys.world.highlight_tips=Highlight Tooltips
|
||||
@@ -301,6 +306,11 @@ nei.options.inventory.guirecipe.handlerInfo=Handler Info Widget
|
||||
nei.options.inventory.guirecipe.handlerInfo.tip=Use shift+d while in the Recipes GUI
|
||||
nei.options.inventory.guirecipe.handlerInfo.true=Enabled
|
||||
nei.options.inventory.guirecipe.handlerInfo.false=Disabled
|
||||
|
||||
nei.options.inventory.guirecipe.scrollPages=Scroll Pages
|
||||
nei.options.inventory.guirecipe.scrollPages.true=Enabled
|
||||
nei.options.inventory.guirecipe.scrollPages.false=Disabled
|
||||
|
||||
nei.options.inventory.guirecipe.maxHeight=Max Height
|
||||
nei.options.inventory.showItemQuantityWidget=Show Item Quantity Widget
|
||||
nei.options.inventory.showItemQuantityWidget.true=Yes
|
||||
@@ -519,6 +529,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 +551,15 @@ 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.UseCustomScroll=Use Custom Scroll
|
||||
nei.debug.RecipeHandler.ShowBadge=Show Badge
|
||||
nei.debug.RecipeHandler.AllowOverflowY=Allow Overflow Y
|
||||
nei.debug.RecipeHandler.AllowOverflowX=Allow Overflow X
|
||||
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 +569,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
|
||||
|
||||
@@ -63,11 +63,11 @@ nei.options.wbutton.tip.1=Globaalsete seadmete ületegemine
|
||||
|
||||
nei.options.keys=Klahviseosed
|
||||
nei.options.keys.gui=Seljakott
|
||||
nei.options.keys.gui.recipe=Retsept
|
||||
nei.options.keys.gui.usage=Kasutus
|
||||
nei.options.keys.recipe.recipe=Retsept
|
||||
nei.options.keys.recipe.usage=Kasutus
|
||||
nei.options.keys.gui.enchant=Loitsud
|
||||
nei.options.keys.gui.potion=Joogid
|
||||
nei.options.keys.gui.back=Eel. Retsept
|
||||
nei.options.keys.recipe.back=Eel. Retsept
|
||||
nei.options.keys.gui.prev=Eel. Leht
|
||||
nei.options.keys.gui.next=Järg. Leht
|
||||
nei.options.keys.gui.hide=Lülita NEI nähtavust
|
||||
|
||||
@@ -61,11 +61,11 @@ nei.options.wbutton.tip.1=Annuler l'utilisation des paramètres globaux
|
||||
|
||||
nei.options.keys=Raccourcis clavier
|
||||
nei.options.keys.gui=Inventaire
|
||||
nei.options.keys.gui.recipe=Recette
|
||||
nei.options.keys.gui.usage=Usage
|
||||
nei.options.keys.recipe.recipe=Recette
|
||||
nei.options.keys.recipe.usage=Usage
|
||||
nei.options.keys.gui.enchant=Enchantements
|
||||
nei.options.keys.gui.potion=Potions
|
||||
nei.options.keys.gui.back=Recette précédente
|
||||
nei.options.keys.recipe.back=Recette précédente
|
||||
nei.options.keys.gui.prev=Recette suivante
|
||||
nei.options.keys.gui.next=Page suivante
|
||||
nei.options.keys.gui.hide=Afficher ou cacher NEI
|
||||
|
||||
@@ -64,11 +64,11 @@ nei.options.wbutton.tip.1=Sovrascrivendo le opzioni globali
|
||||
|
||||
nei.options.keys=Controlli
|
||||
nei.options.keys.gui=Inventario
|
||||
nei.options.keys.gui.recipe=Ricetta
|
||||
nei.options.keys.gui.usage=Usi
|
||||
nei.options.keys.recipe.recipe=Ricetta
|
||||
nei.options.keys.recipe.usage=Usi
|
||||
nei.options.keys.gui.enchant=Incantare
|
||||
nei.options.keys.gui.potion=Pozioni
|
||||
nei.options.keys.gui.back=Ricetta precedente
|
||||
nei.options.keys.recipe.back=Ricetta precedente
|
||||
nei.options.keys.gui.prev=Pagina precedente
|
||||
nei.options.keys.gui.next=Pagina successiva
|
||||
nei.options.keys.gui.hide=Modifica visibilità NEI
|
||||
|
||||
@@ -59,11 +59,11 @@ nei.options.wbutton.tip.1=전역 설정
|
||||
|
||||
nei.options.keys=키 바인딩
|
||||
nei.options.keys.gui=인벤토리
|
||||
nei.options.keys.gui.recipe=레시피
|
||||
nei.options.keys.gui.usage=사용법
|
||||
nei.options.keys.gui.nei.enchant=인첸트
|
||||
nei.options.keys.recipe.recipe=레시피
|
||||
nei.options.keys.recipe.usage=사용법
|
||||
nei.options.keys.gui.enchant=인첸트
|
||||
nei.options.keys.gui.potion=포션
|
||||
nei.options.keys.gui.back=이전 레시피
|
||||
nei.options.keys.recipe.back=이전 레시피
|
||||
nei.options.keys.gui.prev=이전 페이지
|
||||
nei.options.keys.gui.next=다음 페이지
|
||||
nei.options.keys.gui.hide=NEI 활성/비활성화
|
||||
|
||||
@@ -60,11 +60,11 @@ nei.options.wbutton.tip.1=Nadpisywanie ustawienia globalnego
|
||||
|
||||
nei.options.keys=Ustawienia klawiszy
|
||||
nei.options.keys.gui=Ekwipunek
|
||||
nei.options.keys.gui.recipe=Recepta
|
||||
nei.options.keys.gui.usage=Użytek
|
||||
nei.options.keys.recipe.recipe=Recepta
|
||||
nei.options.keys.recipe.usage=Użytek
|
||||
nei.options.keys.gui.enchant=Zaklęcia
|
||||
nei.options.keys.gui.potion=Eleksiry
|
||||
nei.options.keys.gui.back=Poprzednia recepta
|
||||
nei.options.keys.recipe.back=Poprzednia recepta
|
||||
nei.options.keys.gui.prev=Poprzednia strona
|
||||
nei.options.keys.gui.next=Następna strona
|
||||
nei.options.keys.gui.hide=Przełącz widzialność NEI
|
||||
|
||||
@@ -60,11 +60,11 @@ nei.options.wbutton.tip.1=Substituindo configurações globais
|
||||
|
||||
nei.options.keys=Atalhos de Teclado
|
||||
nei.options.keys.gui=Inventário
|
||||
nei.options.keys.gui.recipe=Receita
|
||||
nei.options.keys.gui.usage=Uso
|
||||
nei.options.keys.recipe.recipe=Receita
|
||||
nei.options.keys.recipe.usage=Uso
|
||||
nei.options.keys.gui.enchant=Encantamentos
|
||||
nei.options.keys.gui.potion=Poções
|
||||
nei.options.keys.gui.back=Receita Ant.
|
||||
nei.options.keys.recipe.back=Receita Ant.
|
||||
nei.options.keys.gui.prev=Pág. Anterior
|
||||
nei.options.keys.gui.next=Próxima Pág.
|
||||
nei.options.keys.gui.hide=Trocar Visibilidade do NEI
|
||||
|
||||
@@ -116,39 +116,46 @@ nei.options.wbutton.tip.0=Используются глобальные наст
|
||||
nei.options.wbutton.tip.1=Переопределение глобальной настройки
|
||||
|
||||
nei.options.keys=Привязки клавиш
|
||||
nei.options.keys.tip=Настройте привязки клавиш NEI на экране управления Minecraft
|
||||
nei.options.keys.gui=NEI Инвентарь
|
||||
nei.options.keys.world=NEI Мир
|
||||
nei.options.keys.recipe=NEI Рецепт
|
||||
nei.options.keys.bookmark=NEI Закладки
|
||||
nei.options.keys.copy=NEI Копирование
|
||||
nei.options.keys.itemzoom=NEI Увеличение предмета
|
||||
nei.options.keys.showenchant=Показать зачарование
|
||||
nei.options.keys.gui=Инвентарь
|
||||
nei.options.keys.gui.recipe=Рецепт
|
||||
nei.options.keys.gui.usage=Использование
|
||||
nei.options.keys.recipe.recipe=Рецепт
|
||||
nei.options.keys.recipe.usage=Использование
|
||||
nei.options.keys.gui.enchant=Зачарования
|
||||
nei.options.keys.gui.potion=Зелья
|
||||
nei.options.keys.gui.back=Назад к последнему рецепту
|
||||
nei.options.keys.recipe.back=Назад к последнему рецепту
|
||||
nei.options.keys.gui.prev=Предыдущая страница панели предметов
|
||||
nei.options.keys.gui.next=Следующая страница панели предметов
|
||||
nei.options.keys.gui.hide=Переключить видимость NEI
|
||||
nei.options.keys.gui.next_recipe=Следующий рецепт
|
||||
nei.options.keys.gui.prev_recipe=Предыдущий рецепт
|
||||
nei.options.keys.gui.next_machine=Следующая машина
|
||||
nei.options.keys.gui.prev_machine=Предыдущая машина
|
||||
nei.options.keys.recipe.next_recipe=Следующий рецепт
|
||||
nei.options.keys.recipe.prev_recipe=Предыдущий рецепт
|
||||
nei.options.keys.recipe.next_machine=Следующая машина
|
||||
nei.options.keys.recipe.prev_machine=Предыдущая машина
|
||||
nei.options.keys.gui.search=Сфокусироваться на строке поиска
|
||||
nei.options.keys.gui.bookmark=Добавить закладку
|
||||
nei.options.keys.gui.remove_recipe=Удалить группу из закладок
|
||||
nei.options.keys.gui.bookmark_recipe=Добавить закладку с рецептом
|
||||
nei.options.keys.gui.bookmark_count=Добавить закладку с учётом количества
|
||||
nei.options.keys.gui.bookmark_pull_items=Переместить все отмеченные предметы
|
||||
nei.options.keys.gui.hide_bookmarks=Переключить видимость панели закладок
|
||||
nei.options.keys.bookmark.add=Добавить закладку
|
||||
nei.options.keys.bookmark.remove_recipe=Удалить группу из закладок (Shift +)
|
||||
nei.options.keys.bookmark.pull_items=Переместить все отмеченные предметы
|
||||
nei.options.keys.bookmark.hide=Переключить видимость панели закладок
|
||||
nei.options.keys.gui.overlay=Заполнить сетку крафта
|
||||
nei.options.keys.gui.getprevioussearch=Предыдущий поиск
|
||||
nei.options.keys.gui.getnextsearch=Следующий поиск
|
||||
nei.options.keys.gui.next_tooltip=Следующая подсказка
|
||||
nei.options.keys.gui.copy_name=Скопировать название предмета
|
||||
nei.options.keys.gui.copy_oredict=Скопировать OreDictionary предмета
|
||||
nei.options.keys.gui.chat_link_item=Отправить ссылку на предмет в чат
|
||||
nei.options.keys.gui.itemzoom_toggle=Переключить увеличение предмета
|
||||
nei.options.keys.gui.itemzoom_hold=Удерживать для отображения увеличения предмета
|
||||
nei.options.keys.gui.itemzoom_zoom_in=Увеличить предмет
|
||||
nei.options.keys.gui.itemzoom_zoom_out=Уменьшить предмет
|
||||
nei.options.keys.world=Мир
|
||||
nei.options.keys.copy.name=Скопировать название предмета (Ctrl +)
|
||||
nei.options.keys.gui.craft_items=Создать предметы (Shift +)
|
||||
nei.options.keys.copy.oredict=Скопировать OreDictionary предмета (Ctrl +)
|
||||
nei.options.keys.copy.identifier=Скопировать ID предмета (Ctrl +)
|
||||
nei.options.keys.copy.chat_link_item=Отправить ссылку на предмет в чат (Ctrl +)
|
||||
nei.options.keys.itemzoom.toggle=Переключить увеличение предмета (Shift +)
|
||||
nei.options.keys.itemzoom.hold=Удерживать для отображения увеличения предмета
|
||||
nei.options.keys.itemzoom.zoom_in=Увеличить предмет
|
||||
nei.options.keys.itemzoom.zoom_out=Уменьшить предмет
|
||||
nei.options.keys.bookmark.favorite=Добавить в избранное (Shift +)
|
||||
nei.options.keys.bookmark.favorite_item=Переключить избранное (Shift +)
|
||||
nei.options.keys.world.chunkoverlay=Отображение границ чанков
|
||||
nei.options.keys.world.moboverlay=Отображение спавна мобов
|
||||
nei.options.keys.world.highlight_tips=Подсветка подсказок
|
||||
|
||||
@@ -60,11 +60,11 @@ nei.options.wbutton.tip.1=Globálne nastavenia sú nahradené
|
||||
|
||||
nei.options.keys=Klávesové skratky
|
||||
nei.options.keys.gui=Inventár
|
||||
nei.options.keys.gui.recipe=Recept
|
||||
nei.options.keys.gui.usage=Použitie
|
||||
nei.options.keys.recipe.recipe=Recept
|
||||
nei.options.keys.recipe.usage=Použitie
|
||||
nei.options.keys.gui.enchant=Očarovania
|
||||
nei.options.keys.gui.potion=Elixíry
|
||||
nei.options.keys.gui.back=Predchádzajúci recept
|
||||
nei.options.keys.recipe.back=Predchádzajúci recept
|
||||
nei.options.keys.gui.prev=Predchádzajúca strana
|
||||
nei.options.keys.gui.next=Nasledujúca strana
|
||||
nei.options.keys.gui.hide=Prepni viditeľnosť NEI
|
||||
|
||||
@@ -60,11 +60,11 @@ nei.options.wbutton.tip.1=Genel ayarların üstüne yazılıyor
|
||||
|
||||
nei.options.keys=Tuşlar
|
||||
nei.options.keys.gui=Envanter
|
||||
nei.options.keys.gui.recipe=Tarifler
|
||||
nei.options.keys.gui.usage=Kullanım yeri
|
||||
nei.options.keys.recipe.recipe=Tarifler
|
||||
nei.options.keys.recipe.usage=Kullanım yeri
|
||||
nei.options.keys.gui.enchant=Büylüler
|
||||
nei.options.keys.gui.potion=İksirler
|
||||
nei.options.keys.gui.back=Önceki tarif
|
||||
nei.options.keys.recipe.back=Önceki tarif
|
||||
nei.options.keys.gui.prev=Önceki sayfa
|
||||
nei.options.keys.gui.next=Sonraki sayfa
|
||||
nei.options.keys.gui.hide=Nei görünürlük ayarı
|
||||
|
||||
Loaded 100 of 103 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user