mirror of
https://github.com/GTNewHorizons/NotEnoughItems.git
synced 2026-10-26 22:33:52 +00:00
Compare commits
23
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2169ba03d0 | ||
|
|
7f182757c3 | ||
|
|
83ee2e0d53 | ||
|
|
ff518c81b3 | ||
|
|
5fb5ab6698 | ||
|
|
f47a8766a9 | ||
|
|
4cc72444d9 | ||
|
|
b48956ef94 | ||
|
|
583d28ed12 | ||
|
|
384813347c | ||
|
|
2660460c87 | ||
|
|
2b28068382 | ||
|
|
1767d4be63 | ||
|
|
e6684ddebb | ||
|
|
89110ccb7e | ||
|
|
434b4ac879 | ||
|
|
24e6f7c57d | ||
|
|
2c204c25aa | ||
|
|
5e6ff1d63b | ||
|
|
53ce50b35a | ||
|
|
835c4f7e01 | ||
|
|
f8c1f39faf | ||
|
|
4c4716e64f |
No files matched your search
@@ -1294,7 +1294,7 @@ public class BookmarkPanel extends PanelWidget<BookmarkGrid> {
|
||||
public BookmarkRecipeId getBookmarkRecipeId(int itemIndex) {
|
||||
BookmarkItem item = this.grid.getCalculatedItem(itemIndex);
|
||||
return item == null || item.type == BookmarkItemType.INGREDIENT || item.recipeId == null ? null
|
||||
: new BookmarkRecipeId(item.recipeId.getHandleName(), item.recipeId.getIngredients());
|
||||
: new BookmarkRecipeId(item.recipeId.getHandlerName(), item.recipeId.getIngredients());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
|
||||
@@ -8,7 +8,6 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -129,8 +128,8 @@ public class FavoriteRecipes {
|
||||
}
|
||||
|
||||
protected List<PositionedStack> getOutputs(IRecipeHandler handler, int recipeIndex) {
|
||||
final PositionedStack pStackResult = handler.getResultStack(recipeIndex);
|
||||
return pStackResult != null ? Collections.singletonList(pStackResult) : handler.getOtherStacks(recipeIndex);
|
||||
final List<PositionedStack> pStackResults = handler.getResultStacks(recipeIndex);
|
||||
return !pStackResults.isEmpty() ? pStackResults : handler.getOtherStacks(recipeIndex);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -225,7 +224,7 @@ public class FavoriteRecipes {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FAVORITE_ITEM.equals(recipeId.getHandleName()) || RecipeHandlerRef.of(recipeId) != null) {
|
||||
if (FAVORITE_ITEM.equals(recipeId.getHandlerName()) || RecipeHandlerRef.of(recipeId) != null) {
|
||||
manualFavorites.add(stack, recipeId);
|
||||
} else {
|
||||
hasErrors = true;
|
||||
|
||||
@@ -23,6 +23,7 @@ import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IIcon;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.MinecraftForgeClient;
|
||||
import net.minecraftforge.common.util.ForgeDirection;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
@@ -65,26 +66,40 @@ public class ItemMobSpawner extends ItemBlock {
|
||||
@Override
|
||||
public boolean onItemUse(ItemStack itemstack, EntityPlayer entityplayer, World world, int x, int y, int z, int side,
|
||||
float hitX, float hitY, float hitZ) {
|
||||
int targetX = x;
|
||||
int targetY = y;
|
||||
int targetZ = z;
|
||||
|
||||
placedX = x;
|
||||
placedY = y;
|
||||
placedZ = z;
|
||||
if (!world.getBlock(x, y, z).isReplaceable(world, x, y, z)) {
|
||||
ForgeDirection direction = ForgeDirection.getOrientation(side);
|
||||
targetX += direction.offsetX;
|
||||
targetY += direction.offsetY;
|
||||
targetZ += direction.offsetZ;
|
||||
}
|
||||
|
||||
placedX = targetX;
|
||||
placedY = targetY;
|
||||
placedZ = targetZ;
|
||||
|
||||
String mobType = getMobTypeFromItemStack(itemstack);
|
||||
|
||||
boolean placed = super.onItemUse(itemstack, entityplayer, world, x, y, z, side, hitX, hitY, hitZ);
|
||||
|
||||
if (placed && !world.isRemote) {
|
||||
TileEntity tileEntity = world.getTileEntity(x, y, z);
|
||||
if (tileEntity instanceof TileEntityMobSpawner) {
|
||||
TileEntityMobSpawner spawner = (TileEntityMobSpawner) tileEntity;
|
||||
String mobType = getMobTypeFromItemStack(itemstack);
|
||||
if (mobType != null) {
|
||||
spawner.func_145881_a().setEntityName(mobType);
|
||||
world.markBlockForUpdate(x, y, z);
|
||||
NEICPH.sendMobSpawnerID(x, y, z, mobType);
|
||||
if (placed) {
|
||||
TileEntity tileEntity = world.getTileEntity(targetX, targetY, targetZ);
|
||||
|
||||
if (tileEntity instanceof TileEntityMobSpawner spawner && mobType != null) {
|
||||
spawner.func_145881_a().setEntityName(mobType);
|
||||
|
||||
if (!world.isRemote) {
|
||||
world.markBlockForUpdate(targetX, targetY, targetZ);
|
||||
NEICPH.sendMobSpawnerID(targetX, targetY, targetZ, mobType);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return placed;
|
||||
}
|
||||
|
||||
|
||||
@@ -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")
|
||||
|| KeyManager.isHashDown("itemzoom.hold"))
|
||||
|| KeyManager.isKeyDown("itemzoom.hold"))
|
||||
&& GuiContainerManager.shouldShowTooltip(NEIClientUtils.getGuiContainer())) {
|
||||
final float inverseScaleFactor = 1.0f / this.scale;
|
||||
final float screenScale = getScreenScale();
|
||||
@@ -204,18 +204,18 @@ public class ItemZoom extends Widget implements IContainerInputHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && KeyManager.isHashDown("itemzoom.hold")) {
|
||||
if (this.stack != null && KeyManager.isKeyDown("itemzoom.hold")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && KeyManager.isHashDown("itemzoom.zoom_in")) {
|
||||
if (this.stack != null && KeyManager.isKeyDown("itemzoom.zoom_in")) {
|
||||
increaseZoom(gui);
|
||||
previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.stack != null && KeyManager.isHashDown("itemzoom.zoom_out")) {
|
||||
if (this.stack != null && KeyManager.isKeyDown("itemzoom.zoom_out")) {
|
||||
decreaseZoom(gui);
|
||||
previousKeyboardRepeatEnabled = Keyboard.areRepeatEventsEnabled();
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
|
||||
@@ -5,9 +5,11 @@ import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
|
||||
import codechicken.nei.util.NEIKeyboardUtils;
|
||||
import codechicken.nei.util.NEIMouseUtils;
|
||||
@@ -24,8 +26,16 @@ public class KeyManager {
|
||||
}
|
||||
|
||||
public static LinkedList<IKeyStateTracker> trackers = new LinkedList<>();
|
||||
|
||||
private static final Map<String, KeyBinding> keyBindings = new HashMap<>();
|
||||
private static final Map<String, String> keyAliases = new HashMap<>();
|
||||
private static volatile boolean pendingOptionsReload = false;
|
||||
|
||||
static {
|
||||
// Aliases for legacy keybinds
|
||||
keyAliases.put("gui.recipe", "recipe.recipe");
|
||||
keyAliases.put("gui.usage", "recipe.usage");
|
||||
keyAliases.put("gui.hide_bookmarks", "bookmark.hide");
|
||||
}
|
||||
|
||||
public static KeyBinding registerKeyBinding(String ident, int defaultKey) {
|
||||
return keyBindings.computeIfAbsent(ident, id -> {
|
||||
@@ -39,18 +49,37 @@ public class KeyManager {
|
||||
}
|
||||
|
||||
public static KeyBinding getKeyBinding(String ident) {
|
||||
return keyBindings.get(ident);
|
||||
return keyBindings.get(keyAliases.getOrDefault(ident, ident));
|
||||
}
|
||||
|
||||
public static boolean isRegistered(String description) {
|
||||
for (KeyBinding binding : keyBindings.values()) {
|
||||
if (binding.getKeyDescription().equals(description)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static int getKeyCode(String ident) {
|
||||
final KeyBinding binding = keyBindings.get(ident);
|
||||
final KeyBinding binding = getKeyBinding(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);
|
||||
final KeyBinding binding = getKeyBinding(ident);
|
||||
|
||||
if (binding != null) {
|
||||
final int keyCode = binding.getKeyCode();
|
||||
|
||||
if (keyCode < 0) {
|
||||
return Mouse.isButtonDown(keyCode + 100);
|
||||
} else if (keyCode > Keyboard.KEY_NONE && keyCode < Keyboard.KEYBOARD_SIZE) {
|
||||
return Keyboard.isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isHashDown(String ident) {
|
||||
@@ -58,13 +87,18 @@ public class KeyManager {
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (!isKeyDown(ident)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (NEIKeyboardUtils.isHashKey(getKeyCode(ident))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return ((modifierMask & NEIKeyboardUtils.CTRL_HASH) != 0) == NEIClientUtils.controlKey()
|
||||
&& ((modifierMask & NEIKeyboardUtils.SHIFT_HASH) != 0) == NEIClientUtils.shiftKey()
|
||||
&& ((modifierMask & NEIKeyboardUtils.ALT_HASH) != 0) == NEIClientUtils.altKey();
|
||||
}
|
||||
|
||||
public static String getKeyName(String ident) {
|
||||
@@ -99,7 +133,7 @@ public class KeyManager {
|
||||
}
|
||||
|
||||
public static boolean isPressed(String ident) {
|
||||
final KeyBinding binding = keyBindings.get(ident);
|
||||
final KeyBinding binding = getKeyBinding(ident);
|
||||
return binding != null && binding.isPressed();
|
||||
}
|
||||
|
||||
@@ -108,7 +142,17 @@ public class KeyManager {
|
||||
return dot < 0 ? "nei.options.keys" : "nei.options.keys." + ident.substring(0, dot);
|
||||
}
|
||||
|
||||
public static void requestOptionsReload() {
|
||||
pendingOptionsReload = true;
|
||||
}
|
||||
|
||||
public static void tickKeyStates() {
|
||||
|
||||
if (pendingOptionsReload) {
|
||||
pendingOptionsReload = false;
|
||||
Minecraft.getMinecraft().gameSettings.loadOptions();
|
||||
}
|
||||
|
||||
for (IKeyStateTracker tracker : trackers) tracker.tickKeyStates();
|
||||
}
|
||||
}
|
||||
@@ -224,12 +224,12 @@ public class LayoutManager implements IContainerInputHandler, IContainerTooltipH
|
||||
@Override
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) {
|
||||
|
||||
if (KeyManager.isHashDown("gui.hide")) {
|
||||
if (KeyManager.isKeyDown("gui.hide")) {
|
||||
toggleBooleanSetting("inventory.hidden");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (KeyManager.isHashDown("bookmark.hide")) {
|
||||
if (KeyManager.isKeyDown("bookmark.hide")) {
|
||||
toggleBooleanSetting("inventory.bookmarks.enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import static codechicken.nei.PacketIDs.S2C;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.inventory.GuiInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.play.INetHandlerPlayClient;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraft.world.World;
|
||||
@@ -14,6 +15,7 @@ import codechicken.core.ClientUtils;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.lib.packet.PacketCustom.IClientPacketHandler;
|
||||
import codechicken.nei.commands.CommandBookmarkAdd;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
|
||||
public class NEICPH implements IClientPacketHandler {
|
||||
@@ -56,6 +58,18 @@ public class NEICPH implements IClientPacketHandler {
|
||||
case S2C.OPEN_POTION_GUI:
|
||||
ClientUtils.openSMPGui(packet.readUByte(), new GuiPotionCreator(mc.thePlayer.inventory));
|
||||
break;
|
||||
case S2C.CACHE_BOOKMARK_DATA:
|
||||
handleCacheBookmarkData(packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCacheBookmarkData(PacketCustom packet) {
|
||||
final String payloadId = packet.readString();
|
||||
final NBTTagCompound payloadTag = packet.readNBTTagCompound();
|
||||
|
||||
if (payloadTag != null) {
|
||||
CommandBookmarkAdd.cachePayload(payloadId, payloadTag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,9 +200,9 @@ public class NEICPH implements IClientPacketHandler {
|
||||
packet.sendToServer();
|
||||
}
|
||||
|
||||
public static void sendChatLink(ItemStack stackover) {
|
||||
public static void sendChatLink(NBTTagCompound payloadTag) {
|
||||
PacketCustom packet = new PacketCustom(channel, C2S.SEND_CHAT_ITEM_LINK);
|
||||
packet.writeItemStack(stackover);
|
||||
packet.writeNBTTagCompound(payloadTag);
|
||||
packet.sendToServer();
|
||||
}
|
||||
|
||||
|
||||
@@ -839,6 +839,7 @@ public class NEIClientConfig {
|
||||
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.chat_link", Keyboard.KEY_L);
|
||||
API.addKeyBind("bookmark.hide", Keyboard.KEY_B);
|
||||
|
||||
API.addKeyBind("itemzoom.toggle", Keyboard.KEY_Z);
|
||||
@@ -860,7 +861,6 @@ public class NEIClientConfig {
|
||||
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() {
|
||||
@@ -987,6 +987,7 @@ public class NEIClientConfig {
|
||||
}
|
||||
});
|
||||
|
||||
KeyManager.requestOptionsReload();
|
||||
RecipeCatalysts.loadCatalystInfo();
|
||||
SubsetWidget.loadCustomSubsets();
|
||||
SubsetWidget.loadHidden();
|
||||
|
||||
@@ -38,6 +38,7 @@ import net.minecraft.inventory.Container;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
@@ -379,8 +380,8 @@ public class NEIClientUtils extends NEIServerUtils {
|
||||
else sendCommand(getStringSetting("command.heal"), mc().thePlayer.getCommandSenderName());
|
||||
}
|
||||
|
||||
public static void sendChatItemLink(ItemStack stackover) {
|
||||
if (hasSMPCounterPart()) NEICPH.sendChatLink(stackover);
|
||||
public static void sendChatItemLink(NBTTagCompound payload) {
|
||||
if (hasSMPCounterPart()) NEICPH.sendChatLink(payload);
|
||||
}
|
||||
|
||||
public static void toggleMagnetMode() {
|
||||
|
||||
@@ -27,7 +27,7 @@ import codechicken.nei.commands.CommandUntranslator;
|
||||
import codechicken.nei.guihook.GuiContainerManager;
|
||||
import codechicken.nei.guihook.IContainerInputHandler;
|
||||
import codechicken.nei.guihook.IContainerSlotClickHandler;
|
||||
import codechicken.nei.recipe.GuiRecipe;
|
||||
import codechicken.nei.util.EmptyContainer;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
@@ -252,7 +252,7 @@ public class NEIController implements IContainerSlotClickHandler, IContainerInpu
|
||||
|
||||
// slot in GuiRecipe does not contain actual stack
|
||||
// and scroll should be handled by GuiRecipe, not here
|
||||
if (gui instanceof GuiRecipe) return false;
|
||||
if (gui.inventorySlots instanceof EmptyContainer) return false;
|
||||
|
||||
Point mousePos = getMousePosition();
|
||||
Slot mouseover = manager.window.getSlotAtPosition(mousePos.x, mousePos.y);
|
||||
|
||||
@@ -43,6 +43,7 @@ public class NEIModContainer extends DummyModContainer {
|
||||
|
||||
private static boolean gregTech5Loaded;
|
||||
private static boolean gtnhLibLoaded;
|
||||
private static boolean cubicChunksLoaded;
|
||||
|
||||
private static ASMDataTable asmDataTable;
|
||||
|
||||
@@ -69,6 +70,10 @@ public class NEIModContainer extends DummyModContainer {
|
||||
return gtnhLibLoaded;
|
||||
}
|
||||
|
||||
public static boolean isCCLoaded() {
|
||||
return cubicChunksLoaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<ArtifactVersion> getRequirements() {
|
||||
Set<ArtifactVersion> deps = new HashSet<>();
|
||||
@@ -96,6 +101,7 @@ public class NEIModContainer extends DummyModContainer {
|
||||
public void preInit(FMLPreInitializationEvent event) {
|
||||
gregTech5Loaded = Loader.isModLoaded("gregtech") && !Loader.isModLoaded("gregapi_post");
|
||||
gtnhLibLoaded = Loader.isModLoaded("gtnhlib");
|
||||
cubicChunksLoaded = Loader.isModLoaded("cubicchunks");
|
||||
if (CommonUtils.isClient()) ClientHandler.preInit();
|
||||
asmDataTable = event.getAsmData();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.inventory.InventoryBasic;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.network.play.INetHandlerPlayServer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityMobSpawner;
|
||||
@@ -95,7 +96,8 @@ public class NEISPH implements IServerPacketHandler {
|
||||
}
|
||||
|
||||
private void handleSendChatItemLink(EntityPlayerMP sender, PacketCustom packet) {
|
||||
NEIServerUtils.sendChatItemLink(sender, packet.readItemStack());
|
||||
final NBTTagCompound payloadTag = packet.readNBTTagCompound();
|
||||
NEIServerUtils.sendChatItemLink(sender, payloadTag);
|
||||
}
|
||||
|
||||
private void handleDummySlotSet(EntityPlayerMP sender, PacketCustom packet) {
|
||||
|
||||
@@ -10,6 +10,7 @@ import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.ZipException;
|
||||
|
||||
import net.minecraft.command.ICommandSender;
|
||||
@@ -28,6 +29,7 @@ import net.minecraft.nbt.NBTException;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
@@ -44,6 +46,7 @@ import codechicken.lib.inventory.InventoryRange;
|
||||
import codechicken.lib.inventory.InventoryUtils;
|
||||
import codechicken.lib.packet.PacketCustom;
|
||||
import codechicken.nei.PacketIDs.S2C;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.NBTHelper;
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.common.registry.GameRegistry;
|
||||
@@ -86,16 +89,46 @@ public class NEIServerUtils {
|
||||
player.extinguish();
|
||||
}
|
||||
|
||||
public static void sendChatItemLink(EntityPlayerMP sender, ItemStack stackover) {
|
||||
ServerUtils.sendChatToAll(
|
||||
new ChatComponentTranslation(
|
||||
"nei.chat.item_link.text",
|
||||
sender.getDisplayName(),
|
||||
stackover.func_151000_E().setChatStyle(
|
||||
stackover.func_151000_E().getChatStyle().setChatClickEvent(
|
||||
new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
"/nei_bookmark " + stackover.writeToNBT(new NBTTagCompound()))))));
|
||||
public static void sendChatItemLink(EntityPlayerMP sender, NBTTagCompound payload) {
|
||||
if (payload == null) {
|
||||
sender.addChatMessage(new ChatComponentText("Invalid bookmark payload"));
|
||||
return;
|
||||
}
|
||||
|
||||
final String linkType = payload.getString("linkType");
|
||||
final String payloadId = UUID.randomUUID().toString().substring(0, 8);
|
||||
final PacketCustom packet = new PacketCustom(NEISPH.channel, S2C.CACHE_BOOKMARK_DATA).writeString(payloadId)
|
||||
.writeNBTTagCompound((NBTTagCompound) payload.copy());
|
||||
|
||||
for (EntityPlayer player : ServerUtils.getPlayers()) {
|
||||
if (player instanceof EntityPlayerMP playerMP) {
|
||||
packet.sendToPlayer(playerMP);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final IChatComponent clickable;
|
||||
|
||||
if (payload.hasKey("item")) {
|
||||
clickable = StackInfo.loadFromNBT(payload.getCompoundTag("item")).func_151000_E();
|
||||
} else {
|
||||
clickable = new ChatComponentText("[")
|
||||
.appendSibling(new ChatComponentTranslation("nei.chat.item_link." + linkType + ".text"))
|
||||
.appendText("]");
|
||||
}
|
||||
|
||||
if (clickable == null) {
|
||||
throw new Exception("Invalid ItemStack NBT");
|
||||
}
|
||||
|
||||
clickable.getChatStyle()
|
||||
.setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/nei_bookmark " + payloadId));
|
||||
ServerUtils.sendChatToAll(
|
||||
new ChatComponentTranslation("nei.chat.item_link.text", sender.getDisplayName(), clickable));
|
||||
} catch (Exception e) {
|
||||
sender.addChatMessage(new ChatComponentText(e.toString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static long getTime(World world) {
|
||||
|
||||
@@ -37,5 +37,6 @@ public final class PacketIDs {
|
||||
public static final int OPEN_ENCHANTMENT_GUI = 21;
|
||||
public static final int SET_CREATIVE_PLUS_MODE = 23;
|
||||
public static final int OPEN_POTION_GUI = 24;
|
||||
public static final int CACHE_BOOKMARK_DATA = 25;
|
||||
}
|
||||
}
|
||||
@@ -89,9 +89,9 @@ public class PresetsList {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PositionedStack result = handler.getResultStack(recipeIndex);
|
||||
final List<PositionedStack> results = handler.getResultStacks(recipeIndex);
|
||||
|
||||
if (result != null && matchPositionedStack(result)) {
|
||||
if (!results.isEmpty() && matchPositionedStack(results, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,13 @@ public class PresetsList {
|
||||
return true;
|
||||
}
|
||||
|
||||
return result == null && others.isEmpty();
|
||||
final List<PositionedStack> extraInputs = handler.getCatalystStacks(recipeIndex);
|
||||
|
||||
if (!extraInputs.isEmpty() && matchPositionedStack(extraInputs, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return results.isEmpty() && others.isEmpty();
|
||||
}
|
||||
|
||||
private boolean matchPositionedStack(List<PositionedStack> items, boolean dir) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package codechicken.nei;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Callable;
|
||||
@@ -58,6 +60,7 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
}
|
||||
|
||||
public static void render(float frame) {
|
||||
GL11.glPushAttrib(GL11.GL_ENABLE_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_LINE_BIT);
|
||||
GL11.glPushMatrix();
|
||||
Entity entity = Minecraft.getMinecraft().renderViewEntity;
|
||||
|
||||
@@ -71,9 +74,12 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
|
||||
GL11.glTranslated(-interpPosX + intOffsetX, -interpPosY + intOffsetY, -interpPosZ + intOffsetZ);
|
||||
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glDepthFunc(GL11.GL_LEQUAL);
|
||||
renderChunkBounds(entity, intOffsetX, intOffsetY, intOffsetZ);
|
||||
renderMobSpawnOverlay(entity, intOffsetX, intOffsetY, intOffsetZ);
|
||||
GL11.glPopMatrix();
|
||||
GL11.glPopAttrib();
|
||||
}
|
||||
|
||||
private static void buildMobSpawnOverlay(Entity entity) {
|
||||
@@ -231,6 +237,9 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
private static void renderChunkBounds(Entity entity, int intOffsetX, int intOffsetY, int intOffsetZ) {
|
||||
if (chunkOverlay == 0) return;
|
||||
|
||||
int worldMinY = worldMinHeight(entity.worldObj);
|
||||
int worldMaxY = worldMaxHeight(entity.worldObj);
|
||||
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
@@ -249,14 +258,13 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
double dy = 128;
|
||||
double y1 = Math.floor(entity.posY - dy / 2);
|
||||
double y2 = y1 + dy;
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
if (y1 < worldMinY) {
|
||||
y1 = worldMinY;
|
||||
y2 = worldMinY + dy;
|
||||
}
|
||||
|
||||
if (y1 > entity.worldObj.getHeight()) {
|
||||
y2 = entity.worldObj.getHeight();
|
||||
y1 = y2 - dy;
|
||||
if (y2 > worldMaxY) {
|
||||
y2 = worldMaxY;
|
||||
y1 = Math.max(worldMaxY - dy, worldMinY);
|
||||
}
|
||||
|
||||
y1 -= intOffsetY;
|
||||
@@ -282,19 +290,34 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
tess.addVertex(x1, y2, z1);
|
||||
}
|
||||
|
||||
if (NEIModContainer.isCCLoaded()) {
|
||||
tess.setColorRGBA_F(0, 0.5F, 0.9F, (float) dist * 0.5F);
|
||||
int cubeBase = (int) Math.floor((y1 + intOffsetY) / 16.0) * 16;
|
||||
for (int cubeY = cubeBase; cubeY <= y2 + intOffsetY; cubeY += 16) {
|
||||
double ry = cubeY - intOffsetY;
|
||||
tess.addVertex(x1, ry, z1);
|
||||
tess.addVertex(x2, ry, z1);
|
||||
tess.addVertex(x1, ry, z2);
|
||||
tess.addVertex(x2, ry, z2);
|
||||
tess.addVertex(x1, ry, z1);
|
||||
tess.addVertex(x1, ry, z2);
|
||||
tess.addVertex(x2, ry, z1);
|
||||
tess.addVertex(x2, ry, z2);
|
||||
}
|
||||
}
|
||||
|
||||
if (cx == 0 && cz == 0) {
|
||||
if (chunkOverlay == 2) {
|
||||
dy = 32;
|
||||
y1 = Math.floor(entity.posY - dy / 2);
|
||||
y2 = y1 + dy;
|
||||
if (y1 < 0) {
|
||||
y1 = 0;
|
||||
y2 = dy;
|
||||
if (y1 < worldMinY) {
|
||||
y1 = worldMinY;
|
||||
y2 = worldMinY + dy;
|
||||
}
|
||||
|
||||
if (y1 > entity.worldObj.getHeight()) {
|
||||
y2 = entity.worldObj.getHeight();
|
||||
y1 = y2 - dy;
|
||||
if (y2 > worldMaxY) {
|
||||
y2 = worldMaxY;
|
||||
y1 = Math.max(worldMaxY - dy, worldMinY);
|
||||
}
|
||||
|
||||
y1 -= intOffsetY;
|
||||
@@ -393,6 +416,42 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
}
|
||||
|
||||
/** Holder defers class loading until Cubic Chunks is confirmed present. */
|
||||
private static final class CCWorldBounds {
|
||||
|
||||
static final MethodHandle GET_MIN_HEIGHT;
|
||||
static final MethodHandle GET_MAX_HEIGHT;
|
||||
|
||||
static {
|
||||
try {
|
||||
MethodHandles.Lookup lookup = MethodHandles.lookup();
|
||||
// Mixined into World by CC, use reflection + MethodHandles to call these
|
||||
GET_MIN_HEIGHT = lookup.unreflect(World.class.getMethod("getMinHeight"));
|
||||
GET_MAX_HEIGHT = lookup.unreflect(World.class.getMethod("getMaxHeight"));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new ExceptionInInitializerError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int worldMinHeight(World world) {
|
||||
if (!NEIModContainer.isCCLoaded()) return 0;
|
||||
try {
|
||||
return (int) CCWorldBounds.GET_MIN_HEIGHT.invoke(world);
|
||||
} catch (Throwable ignored) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static int worldMaxHeight(World world) {
|
||||
if (!NEIModContainer.isCCLoaded()) return world.getHeight();
|
||||
try {
|
||||
return (int) CCWorldBounds.GET_MAX_HEIGHT.invoke(world);
|
||||
} catch (Throwable ignored) {
|
||||
return world.getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
private static Callable<String> oregenPatternReader;
|
||||
|
||||
private static String getOregenPatternName() {
|
||||
@@ -414,13 +473,9 @@ public class WorldOverlayRenderer implements IKeyStateTracker {
|
||||
"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();
|
||||
};
|
||||
// GT5-Unofficial >= 5.09.54.29 support
|
||||
final Method accessor = gtWorldGenerator.getMethod("getOregenPattern");
|
||||
return () -> ((Enum<?>) accessor.invoke(null)).name();
|
||||
} catch (NoSuchMethodException legacy) {
|
||||
// Older GT
|
||||
final Field oregenPattern = gtWorldGenerator.getDeclaredField("oregenPattern");
|
||||
|
||||
@@ -224,6 +224,7 @@ public class API {
|
||||
KeyManager.registerKeyBinding(ident, defaultKey);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void addHashBind(String ident, int defaultKey) {
|
||||
KeyManager.registerKeyBinding(ident, defaultKey);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import codechicken.nei.bookmark.BookmarkGrid;
|
||||
import codechicken.nei.bookmark.BookmarkGroup;
|
||||
import codechicken.nei.bookmark.BookmarkItem;
|
||||
import codechicken.nei.bookmark.BookmarkItem.BookmarkItemType;
|
||||
import codechicken.nei.bookmark.BookmarkPayload;
|
||||
import codechicken.nei.bookmark.BookmarksGridSlot;
|
||||
import codechicken.nei.recipe.AutoCraftingManager;
|
||||
import codechicken.nei.recipe.GuiCraftingRecipe;
|
||||
@@ -95,6 +96,11 @@ public abstract class ShortcutInputHandler {
|
||||
return ItemPanels.bookmarkPanel.pullBookmarkItems(groupId, NEIClientUtils.shiftKey());
|
||||
}
|
||||
|
||||
if (KeyManager.isKeyDown("bookmark.chat_link") && NEIClientUtils.controlKey()) {
|
||||
NEIClientUtils.sendChatItemLink(BookmarkPayload.of(groupId).toNBT());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NEIClientConfig.autocraftingEnabled() && KeyManager.isKeyDown("gui.craft_items")
|
||||
&& NEIClientUtils.shiftKey()
|
||||
&& ItemPanels.bookmarkPanel.getGrid().isCraftingMode(groupId)) {
|
||||
@@ -134,15 +140,15 @@ public abstract class ShortcutInputHandler {
|
||||
return copyItemStackOreDictionary(stackover);
|
||||
}
|
||||
|
||||
if (KeyManager.isHashDown("copy.chat_link_item", NEIClientUtils.CTRL_HASH)) {
|
||||
return sendItemStackChatLink(stackover);
|
||||
if (KeyManager.isKeyDown("bookmark.chat_link") && NEIClientUtils.controlKey()) {
|
||||
return sendRecipeInChatLink(stackover, NEIClientUtils.shiftKey());
|
||||
}
|
||||
|
||||
if (KeyManager.isHashDown("recipe.recipe")) {
|
||||
if (KeyManager.isKeyDown("recipe.recipe")) {
|
||||
return GuiCraftingRecipe.openRecipeGui("item", stackover);
|
||||
}
|
||||
|
||||
if (KeyManager.isHashDown("recipe.usage")) {
|
||||
if (KeyManager.isKeyDown("recipe.usage")) {
|
||||
return GuiUsageRecipe.openRecipeGui("item", stackover);
|
||||
}
|
||||
|
||||
@@ -198,10 +204,37 @@ public abstract class ShortcutInputHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean sendItemStackChatLink(ItemStack stackover) {
|
||||
if (stackover == null) return false;
|
||||
private static boolean sendRecipeInChatLink(ItemStack stackover, boolean saveIngredients) {
|
||||
final Point mousePos = GuiDraw.getMousePosition();
|
||||
final BookmarksGridSlot slot = ItemPanels.bookmarkPanel.getSlotMouseOver(mousePos.x, mousePos.y);
|
||||
|
||||
NEIClientUtils.sendChatItemLink(stackover); // I wish clients could just send formatted messages
|
||||
if (slot != null && saveIngredients && slot.getType() == BookmarkItemType.RESULT) {
|
||||
NEIClientUtils.sendChatItemLink(BookmarkPayload.of(slot.getBookmarkItem()).toNBT());
|
||||
return true;
|
||||
}
|
||||
|
||||
final Recipe recipe = getFocusedRecipe(stackover, mousePos.x, mousePos.y, saveIngredients);
|
||||
|
||||
if (recipe != null && saveIngredients) {
|
||||
NEIClientUtils.sendChatItemLink(BookmarkPayload.of(recipe).toNBT());
|
||||
return true;
|
||||
}
|
||||
|
||||
final RecipeId recipeId;
|
||||
|
||||
if (slot != null) {
|
||||
recipeId = slot.getType() == BookmarkItemType.INGREDIENT ? null : slot.getRecipeId();
|
||||
} else {
|
||||
recipeId = recipe != null ? recipe.getRecipeId() : null;
|
||||
}
|
||||
|
||||
final boolean existsRecipe = NEIClientConfig.getBooleanSetting("inventory.bookmarks.bookmarkItemsWithRecipe");
|
||||
|
||||
if (ItemPanels.itemPanel.containsWithSubpanels(mousePos.x, mousePos.y)) {
|
||||
stackover = ItemQuantityField.prepareStackWithQuantity(stackover, 0);
|
||||
}
|
||||
|
||||
NEIClientUtils.sendChatItemLink(BookmarkPayload.of(stackover, existsRecipe ? recipeId : null).toNBT());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -449,6 +482,10 @@ public abstract class ShortcutInputHandler {
|
||||
KeyManager.getKeyName("bookmark.remove_recipe", NEIClientUtils.SHIFT_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.remove_recipe"));
|
||||
|
||||
hotkeys.put(
|
||||
KeyManager.getKeyName("bookmark.chat_link", NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("bookmark.group.chat_link"));
|
||||
|
||||
if (BookmarkContainerInfo.getBookmarkContainerHandler(gui) != null) {
|
||||
hotkeys.put(
|
||||
KeyManager.getKeyName("bookmark.pull_items"),
|
||||
@@ -579,9 +616,10 @@ public abstract class ShortcutInputHandler {
|
||||
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"));
|
||||
KeyManager.getKeyName("bookmark.chat_link", NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("bookmark.item.chat_link"));
|
||||
|
||||
if (!(gui instanceof GuiRecipe) && NEIClientConfig.canCheatItem(stack)) {
|
||||
hotkeys.put(
|
||||
@@ -639,6 +677,9 @@ public abstract class ShortcutInputHandler {
|
||||
}
|
||||
}
|
||||
|
||||
hotkeys.put(
|
||||
KeyManager.getKeyName("bookmark.chat_link", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("bookmark.recipe.chat_link"));
|
||||
}
|
||||
|
||||
hotkeysCache.update(mousex, mousey, stack, groupId, hotkeys);
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package codechicken.nei.asm;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
|
||||
import cpw.mods.fml.relauncher.ReflectionHelper;
|
||||
|
||||
public final class KeyBindingFixHooks {
|
||||
|
||||
private static volatile boolean initialized;
|
||||
private static Field keybindArrayField;
|
||||
private static Field pressedField;
|
||||
private static Field pressTimeField;
|
||||
|
||||
private KeyBindingFixHooks() {}
|
||||
|
||||
public static void onTickAll(int keyCode) {
|
||||
|
||||
if (keyCode == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (KeyBinding binding : getBindings()) {
|
||||
if (binding.getKeyCode() == keyCode) {
|
||||
try {
|
||||
pressTimeField.setInt(binding, pressTimeField.getInt(binding) + 1);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void setKeyBindStateAll(int keyCode, boolean pressed) {
|
||||
|
||||
if (keyCode == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (KeyBinding binding : getBindings()) {
|
||||
if (binding.getKeyCode() == keyCode) {
|
||||
try {
|
||||
pressedField.setBoolean(binding, pressed);
|
||||
} catch (Exception ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static List<KeyBinding> getBindings() {
|
||||
init();
|
||||
|
||||
try {
|
||||
return (List<KeyBinding>) keybindArrayField.get(null);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private static synchronized void init() {
|
||||
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
keybindArrayField = ReflectionHelper.findField(KeyBinding.class, "keybindArray", "field_74516_a");
|
||||
pressedField = ReflectionHelper.findField(KeyBinding.class, "pressed", "field_74513_e");
|
||||
pressTimeField = ReflectionHelper.findField(KeyBinding.class, "pressTime", "field_151474_i");
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,7 +56,8 @@ public class NEITransformer implements IClassTransformer {
|
||||
|
||||
public NEITransformer() {
|
||||
if (FMLLaunchHandler.side().isClient()) {
|
||||
// Generates method to set the placed position of a mob spawner for the item callback. More portable than
|
||||
// Generates method to set the placed position of a mob spawner for the item
|
||||
// callback. More portable than
|
||||
// copying vanilla placement code
|
||||
transformer.add(
|
||||
new MethodWriter(
|
||||
@@ -82,7 +83,6 @@ public class NEITransformer implements IClassTransformer {
|
||||
asmblocks.get("commaFix"),
|
||||
true));
|
||||
|
||||
// fix workbench container losing items on shift click output without room for the full stack
|
||||
transformer.add(
|
||||
new MethodTransformer(
|
||||
new ObfMapping(
|
||||
@@ -105,6 +105,33 @@ public class NEITransformer implements IClassTransformer {
|
||||
asmblocks.get("d_glintAlphaFix"),
|
||||
asmblocks.get("glintAlphaFix")));
|
||||
|
||||
if (FMLLaunchHandler.side().isClient()) {
|
||||
transformer.add(
|
||||
new MethodWriter(
|
||||
ACC_PUBLIC | ACC_STATIC,
|
||||
new ObfMapping("net/minecraft/client/settings/KeyBinding", "func_74507_a", "(I)V"),
|
||||
asmblocks.get("m_keyBindingOnTickAll")));
|
||||
|
||||
transformer.add(
|
||||
new MethodWriter(
|
||||
ACC_PUBLIC | ACC_STATIC,
|
||||
new ObfMapping("net/minecraft/client/settings/KeyBinding", "func_74510_a", "(IZ)V"),
|
||||
asmblocks.get("m_keyBindingSetStateAll")));
|
||||
|
||||
transformer.add(
|
||||
new MethodInjector(
|
||||
new ObfMapping("net/minecraft/client/settings/GameSettings", "func_74303_b", "()V"),
|
||||
asmblocks.get("saveOptionsHook"),
|
||||
true));
|
||||
|
||||
transformer.add(
|
||||
new MethodInjector(
|
||||
new ObfMapping("net/minecraft/client/settings/GameSettings", "func_74303_b", "()V"),
|
||||
asmblocks.get("n_saveOptionsSendSettings"),
|
||||
asmblocks.get("saveOptionsRestoreHook"),
|
||||
false));
|
||||
}
|
||||
|
||||
String GuiContainer = "net/minecraft/client/gui/inventory/GuiContainer";
|
||||
// add manager field
|
||||
transformer.add(
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package codechicken.nei.asm;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import codechicken.core.CommonUtils;
|
||||
import codechicken.nei.KeyManager;
|
||||
import codechicken.nei.NEIClientConfig;
|
||||
|
||||
public final class SaveOptionsFixHooks {
|
||||
|
||||
private static final String KEY_PREFIX = "key_nei.options.keys.";
|
||||
|
||||
private static List<String> pendingRestoreLines;
|
||||
|
||||
private SaveOptionsFixHooks() {}
|
||||
|
||||
public static void onBeforeSaveOptions() {
|
||||
pendingRestoreLines = null;
|
||||
|
||||
if (NEIClientConfig.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final File optionsFile = new File(CommonUtils.getMinecraftDir(), "options.txt");
|
||||
if (!optionsFile.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<String> missing = new ArrayList<>();
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(optionsFile))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (!line.startsWith(KEY_PREFIX)) continue;
|
||||
final int colon = line.indexOf(':');
|
||||
if (colon <= 0) continue;
|
||||
|
||||
final String description = line.substring(4, colon);
|
||||
if (!KeyManager.isRegistered(description)) {
|
||||
missing.add(line);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to read key bindings before options save", e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!missing.isEmpty()) {
|
||||
pendingRestoreLines = missing;
|
||||
}
|
||||
}
|
||||
|
||||
public static void onAfterSaveOptions() {
|
||||
final List<String> restore = pendingRestoreLines;
|
||||
pendingRestoreLines = null;
|
||||
|
||||
if (restore == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final File optionsFile = new File(CommonUtils.getMinecraftDir(), "options.txt");
|
||||
|
||||
try (FileWriter writer = new FileWriter(optionsFile, true)) {
|
||||
for (String line : restore) {
|
||||
writer.write(line);
|
||||
writer.write(System.lineSeparator());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
NEIClientConfig.logger.error("Failed to restore NEI key bindings after options save", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,16 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
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;
|
||||
import codechicken.nei.recipe.StackInfo;
|
||||
import codechicken.nei.util.NBTJson;
|
||||
|
||||
public class BookmarkItem {
|
||||
|
||||
@@ -245,6 +249,45 @@ public class BookmarkItem {
|
||||
return builder(groupId, stack).build();
|
||||
}
|
||||
|
||||
public static BookmarkItem of(JsonObject jsonObject) {
|
||||
final NBTTagCompound itemStackNBT = (NBTTagCompound) NBTJson.toNbt(jsonObject.get("item"));
|
||||
final ItemStack itemStack = StackInfo.loadFromNBT(itemStackNBT);
|
||||
|
||||
if (itemStack != null) {
|
||||
final int groupId = jsonObject.has("groupId") ? jsonObject.get("groupId").getAsInt()
|
||||
: BookmarkGrid.DEFAULT_GROUP_ID;
|
||||
final BookmarkItem.Builder builder = BookmarkItem.builder(groupId, itemStack);
|
||||
|
||||
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) {
|
||||
builder.recipeId(RecipeId.of(recipeJson));
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public BookmarkItem copyWithMultiplier(long multiplier) {
|
||||
return new BookmarkItem(
|
||||
this.groupId,
|
||||
@@ -364,4 +407,27 @@ public class BookmarkItem {
|
||||
return false;
|
||||
}
|
||||
|
||||
public JsonObject toJsonObject() {
|
||||
final JsonObject jsonObject = new JsonObject();
|
||||
|
||||
jsonObject.add("item", NBTJson.toJsonObject(StackInfo.itemStackToNBT(getItemStack())));
|
||||
jsonObject.add("multiplier", new JsonPrimitive(this.multiplier));
|
||||
jsonObject.add("factor", new JsonPrimitive(this.factor));
|
||||
jsonObject.add("type", new JsonPrimitive(this.type.toInt()));
|
||||
|
||||
if (this.groupId != BookmarkGrid.DEFAULT_GROUP_ID) {
|
||||
jsonObject.add("groupId", new JsonPrimitive(this.groupId));
|
||||
}
|
||||
|
||||
if (this.recipeId != null) {
|
||||
jsonObject.add("recipeId", this.recipeId.toJsonObject());
|
||||
}
|
||||
|
||||
if (this.chance != PositionedStack.CHANCE_FULL) {
|
||||
jsonObject.add("chance", new JsonPrimitive(this.chance));
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
package codechicken.nei.bookmark;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import codechicken.lib.gui.GuiDraw;
|
||||
import codechicken.nei.BookmarkPanel.BookmarkViewMode;
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.ItemQuantityField;
|
||||
import codechicken.nei.ItemStackSet;
|
||||
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.util.NBTJson;
|
||||
|
||||
public class BookmarkPayload {
|
||||
|
||||
private String linkType;
|
||||
private NBTTagCompound target;
|
||||
|
||||
private NBTTagCompound group;
|
||||
|
||||
private NBTTagList items = new NBTTagList();
|
||||
private NBTTagList recipes = new NBTTagList();
|
||||
|
||||
private BookmarkPayload(String linkType, ItemStack stack) {
|
||||
this.linkType = linkType;
|
||||
this.target = stack != null ? StackInfo.itemStackToNBT(stack) : null;
|
||||
}
|
||||
|
||||
public static BookmarkPayload of(NBTTagCompound nbt) {
|
||||
final BookmarkPayload payload = new BookmarkPayload(nbt.getString("linkType"), null);
|
||||
|
||||
if (nbt.hasKey("item")) {
|
||||
payload.target = nbt.getCompoundTag("item");
|
||||
}
|
||||
|
||||
if (nbt.hasKey("group")) {
|
||||
payload.group = nbt.getCompoundTag("group");
|
||||
}
|
||||
|
||||
payload.items = nbt.getTagList("items", 10);
|
||||
payload.recipes = nbt.getTagList("recipes", 10);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
public static BookmarkPayload of(BookmarkItem item) {
|
||||
final BookmarkPayload payload = new BookmarkPayload("recipe", item.getItemStack());
|
||||
final BookmarkGrid grid = ItemPanels.bookmarkPanel.getGrid();
|
||||
final Map<RecipeId, Integer> recipesIndexes = new HashMap<>();
|
||||
final RecipeId recipeId = item.recipeId;
|
||||
final int groupId = item.groupId;
|
||||
|
||||
payload.items = new NBTTagList();
|
||||
payload.recipes = new NBTTagList();
|
||||
|
||||
if (recipeId != null) {
|
||||
|
||||
for (int itemIndex = 0; itemIndex < grid.size(); itemIndex++) {
|
||||
final BookmarkItem currentItem = grid.getBookmarkItem(itemIndex);
|
||||
|
||||
if (currentItem != null && currentItem.groupId == groupId && recipeId.equals(currentItem.recipeId)) {
|
||||
addBookmarkItemToPayload(payload, currentItem, recipesIndexes);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
addBookmarkItemToPayload(payload, item, recipesIndexes);
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
public static BookmarkPayload of(Recipe recipe) {
|
||||
final BookmarkPayload payload = new BookmarkPayload("recipe", recipe.getResult());
|
||||
final Map<RecipeId, Integer> recipesIndexes = new HashMap<>();
|
||||
final ItemStackSet seenIngredients = new ItemStackSet();
|
||||
final ItemStackSet seenResults = new ItemStackSet();
|
||||
|
||||
for (RecipeIngredient result : recipe.getResults()) {
|
||||
ItemStack stack = result.getItemStack();
|
||||
if (!seenResults.contains(stack)) {
|
||||
final BookmarkItem item = BookmarkItem.builder(-1, stack, recipe, BookmarkItemType.RESULT).build();
|
||||
addBookmarkItemToPayload(payload, item, recipesIndexes);
|
||||
seenResults.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
for (RecipeIngredient ingr : recipe.getIngredients()) {
|
||||
ItemStack stack = ingr.getItemStack();
|
||||
if (!seenIngredients.contains(stack)) {
|
||||
final BookmarkItem item = BookmarkItem.builder(-1, stack, recipe, BookmarkItemType.INGREDIENT).build();
|
||||
addBookmarkItemToPayload(payload, item, recipesIndexes);
|
||||
seenIngredients.add(stack);
|
||||
}
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
public static BookmarkPayload of(int groupId) {
|
||||
final BookmarkPayload payload = new BookmarkPayload("group", null);
|
||||
final Map<RecipeId, Integer> recipesIndexes = new HashMap<>();
|
||||
final BookmarkGrid grid = ItemPanels.bookmarkPanel.getGrid();
|
||||
|
||||
for (int itemIndex = 0; itemIndex < grid.size(); itemIndex++) {
|
||||
final BookmarkItem item = grid.getBookmarkItem(itemIndex);
|
||||
|
||||
if (item != null && item.groupId == groupId) {
|
||||
addBookmarkItemToPayload(payload, item, recipesIndexes);
|
||||
}
|
||||
}
|
||||
|
||||
payload.group = generateGroup(grid.getGroup(groupId));
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
public static BookmarkPayload of(ItemStack stackover, RecipeId recipeId) {
|
||||
final BookmarkPayload payload = new BookmarkPayload("item", stackover);
|
||||
final Map<RecipeId, Integer> recipesIndexes = new HashMap<>();
|
||||
final Point mousePos = GuiDraw.getMousePosition();
|
||||
|
||||
if (ItemPanels.itemPanel.containsWithSubpanels(mousePos.x, mousePos.y)) {
|
||||
stackover = ItemQuantityField.prepareStackWithQuantity(stackover, 0);
|
||||
}
|
||||
|
||||
final BookmarkItem item = BookmarkItem.builder(-1, stackover).recipeId(recipeId).type(BookmarkItemType.ITEM)
|
||||
.build();
|
||||
|
||||
addBookmarkItemToPayload(payload, item, recipesIndexes);
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
private static NBTTagCompound generateGroup(BookmarkGroup group) {
|
||||
final NBTTagCompound groupTag = new NBTTagCompound();
|
||||
final NBTTagList collapsedRecipes = new NBTTagList();
|
||||
|
||||
groupTag.setString("viewmode", group.viewMode.toString());
|
||||
groupTag.setBoolean("crafting", group.crafting != null);
|
||||
groupTag.setBoolean("collapsed", group.collapsed);
|
||||
|
||||
for (RecipeId recipeId : group.collapsedRecipes) {
|
||||
collapsedRecipes.appendTag(NBTJson.toNbt(recipeId.toJsonObject()));
|
||||
}
|
||||
|
||||
groupTag.setTag("collapsedRecipes", collapsedRecipes);
|
||||
|
||||
return groupTag;
|
||||
}
|
||||
|
||||
private static void addBookmarkItemToPayload(BookmarkPayload payload, BookmarkItem item,
|
||||
Map<RecipeId, Integer> recipesIndexes) {
|
||||
final JsonObject itemTag = item.toJsonObject();
|
||||
itemTag.remove("groupId");
|
||||
|
||||
if (item.recipeId != null) {
|
||||
final int recipeIndex = recipesIndexes
|
||||
.computeIfAbsent(item.recipeId, recipeId -> addRecipeToPayload(payload, recipeId, recipesIndexes));
|
||||
itemTag.addProperty("recipeId", recipeIndex);
|
||||
}
|
||||
|
||||
payload.items.appendTag(NBTJson.toNbt(itemTag));
|
||||
}
|
||||
|
||||
private static int addRecipeToPayload(BookmarkPayload payload, RecipeId recipeId,
|
||||
Map<RecipeId, Integer> recipesIndexes) {
|
||||
final NBTTagCompound recipeTag = new NBTTagCompound();
|
||||
final int recipeIndex = payload.recipes.tagCount();
|
||||
|
||||
recipeTag.setTag("recipeId", NBTJson.toNbt(recipeId.toJsonObject()));
|
||||
recipeTag.setInteger("recipeIndex", recipeIndex);
|
||||
payload.recipes.appendTag(recipeTag);
|
||||
|
||||
return recipeIndex;
|
||||
}
|
||||
|
||||
public NBTTagCompound toNBT() {
|
||||
final NBTTagCompound payloadTag = new NBTTagCompound();
|
||||
payloadTag.setString("linkType", linkType);
|
||||
|
||||
if (target != null) {
|
||||
payloadTag.setTag("item", target);
|
||||
}
|
||||
|
||||
if (group != null) {
|
||||
payloadTag.setTag("group", group);
|
||||
}
|
||||
|
||||
payloadTag.setTag("items", items);
|
||||
payloadTag.setTag("recipes", recipes);
|
||||
|
||||
return payloadTag;
|
||||
}
|
||||
|
||||
public String getLinkType() {
|
||||
return this.linkType;
|
||||
}
|
||||
|
||||
public ItemStack getTargetStack() {
|
||||
return this.target != null ? StackInfo.loadFromNBT(this.target) : null;
|
||||
}
|
||||
|
||||
public BookmarkGroup getGroup() {
|
||||
if (this.group == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean crafting = this.group.hasKey("crafting") && this.group.getBoolean("crafting");
|
||||
final BookmarkViewMode viewMode;
|
||||
|
||||
if (this.group.hasKey("viewmode")) {
|
||||
viewMode = BookmarkViewMode.valueOf(this.group.getString("viewmode"));
|
||||
} else {
|
||||
viewMode = BookmarkViewMode.TODO_LIST;
|
||||
}
|
||||
|
||||
final BookmarkGroup group = new BookmarkGroup(viewMode, crafting);
|
||||
|
||||
if (this.group.hasKey("collapsed")) {
|
||||
group.collapsed = this.group.getBoolean("collapsed");
|
||||
}
|
||||
|
||||
if (this.group.hasKey("collapsedRecipes")) {
|
||||
final NBTTagList collapsedRecipes = this.group.getTagList("collapsedRecipes", 10);
|
||||
|
||||
for (int i = 0; i < collapsedRecipes.tagCount(); i++) {
|
||||
final NBTTagCompound recipeTag = collapsedRecipes.getCompoundTagAt(i);
|
||||
final RecipeId recipeId = RecipeId.of((JsonObject) NBTJson.toJsonObject(recipeTag));
|
||||
group.collapsedRecipes.add(recipeId);
|
||||
}
|
||||
}
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
public List<BookmarkItem> getBookmarkItems(int groupId) {
|
||||
final List<BookmarkItem> bookmarkItems = new ArrayList<>();
|
||||
final Map<Integer, RecipeId> recipesMap = new HashMap<>();
|
||||
|
||||
for (int i = 0; i < recipes.tagCount(); i++) {
|
||||
final NBTTagCompound recipeTag = recipes.getCompoundTagAt(i);
|
||||
final RecipeId recipeId = RecipeId
|
||||
.of((JsonObject) NBTJson.toJsonObject(recipeTag.getCompoundTag("recipeId")));
|
||||
recipesMap.put(recipeTag.getInteger("recipeIndex"), recipeId);
|
||||
}
|
||||
|
||||
for (int i = 0; i < items.tagCount(); i++) {
|
||||
final NBTTagCompound itemTag = items.getCompoundTagAt(i);
|
||||
RecipeId recipeId = null;
|
||||
|
||||
if (itemTag.hasKey("recipeId")) {
|
||||
recipeId = recipesMap.get(itemTag.getInteger("recipeId"));
|
||||
itemTag.removeTag("recipeId");
|
||||
}
|
||||
|
||||
final BookmarkItem item = BookmarkItem.of((JsonObject) NBTJson.toJsonObject(itemTag));
|
||||
|
||||
if (item != null) {
|
||||
item.groupId = groupId;
|
||||
item.recipeId = recipeId;
|
||||
bookmarkItems.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
return bookmarkItems;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@@ -25,10 +24,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;
|
||||
import codechicken.nei.util.NBTJson;
|
||||
|
||||
public class BookmarkStorage {
|
||||
@@ -199,7 +195,11 @@ public class BookmarkStorage {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!addItemToGrid(grid, parser.parse(itemStr).getAsJsonObject())) {
|
||||
final BookmarkItem item = BookmarkItem.of(parser.parse(itemStr).getAsJsonObject());
|
||||
|
||||
if (item != null) {
|
||||
grid.addItem(item, false);
|
||||
} else {
|
||||
wasError = true;
|
||||
NEIClientConfig.logger.warn(
|
||||
"Failed to load bookmarked ItemStack from json string, the item no longer exists:\n{}",
|
||||
@@ -238,53 +238,6 @@ public class BookmarkStorage {
|
||||
this.bookmarkFile = bookmarkFile;
|
||||
}
|
||||
|
||||
private boolean addItemToGrid(BookmarkGrid grid, JsonObject jsonObject) {
|
||||
NBTTagCompound itemStackNBT;
|
||||
|
||||
if (jsonObject.get("item") != null) {
|
||||
itemStackNBT = (NBTTagCompound) NBTJson.toNbt(jsonObject.get("item"));
|
||||
} else { // old format
|
||||
itemStackNBT = (NBTTagCompound) NBTJson.toNbt(jsonObject);
|
||||
}
|
||||
|
||||
ItemStack itemStack = StackInfo.loadFromNBT(itemStackNBT);
|
||||
|
||||
if (itemStack != null) {
|
||||
int groupId = jsonObject.has("groupId") && grid.groups.containsKey(jsonObject.get("groupId").getAsInt())
|
||||
? jsonObject.get("groupId").getAsInt()
|
||||
: BookmarkGrid.DEFAULT_GROUP_ID;
|
||||
final BookmarkItem.Builder builder = BookmarkItem.builder(groupId, itemStack);
|
||||
|
||||
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) {
|
||||
builder.recipeId(RecipeId.of(recipeJson));
|
||||
}
|
||||
|
||||
grid.addItem(builder.build(), false);
|
||||
}
|
||||
|
||||
return itemStack != null;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
|
||||
if (this.bookmarkFile == null) {
|
||||
@@ -325,26 +278,7 @@ public class BookmarkStorage {
|
||||
|
||||
for (BookmarkItem item : grid.bookmarkItems) {
|
||||
try {
|
||||
JsonObject row = new JsonObject();
|
||||
|
||||
row.add("item", NBTJson.toJsonObject(StackInfo.itemStackToNBT(item.getItemStack())));
|
||||
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) {
|
||||
row.add("groupId", new JsonPrimitive(item.groupId));
|
||||
}
|
||||
|
||||
if (item.recipeId != null) {
|
||||
row.add("recipeId", item.recipeId.toJsonObject());
|
||||
}
|
||||
|
||||
if (item.chance != PositionedStack.CHANCE_FULL) {
|
||||
row.add("chance", new JsonPrimitive(item.chance));
|
||||
}
|
||||
|
||||
strings.add(NBTJson.toJson(row));
|
||||
strings.add(NBTJson.toJson(item.toJsonObject()));
|
||||
} catch (JsonSyntaxException e) {
|
||||
NEIClientConfig.logger.error("Failed to stringify bookmarked ItemStack to json string");
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ public class BookmarksGridSlot extends ItemsGridSlot {
|
||||
|
||||
protected HandlerInfo getHandlerInfo() {
|
||||
if (this.bookmarkItem.recipeId != null && this.handlerInfo == null) {
|
||||
this.handlerInfo = GuiRecipeTab.getHandlerInfo(this.bookmarkItem.recipeId.getHandleName(), null);
|
||||
this.handlerInfo = GuiRecipeTab.getHandlerInfo(this.bookmarkItem.recipeId.getHandlerName(), null);
|
||||
}
|
||||
return this.handlerInfo;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,39 @@
|
||||
package codechicken.nei.commands;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.JsonToNBT;
|
||||
import net.minecraft.nbt.NBTException;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
|
||||
import codechicken.nei.ItemPanels;
|
||||
import codechicken.nei.LRUCache;
|
||||
import codechicken.nei.bookmark.BookmarkGrid;
|
||||
import codechicken.nei.bookmark.BookmarkGroup;
|
||||
import codechicken.nei.bookmark.BookmarkPayload;
|
||||
|
||||
public class CommandBookmarkAdd extends CommandBase {
|
||||
|
||||
private static final LRUCache<String, NBTTagCompound> PAYLOAD_CACHE = new LRUCache<>(64);
|
||||
|
||||
public static void cachePayload(String payloadId, NBTTagCompound payload) {
|
||||
if (payloadId == null || payloadId.isEmpty() || payload == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (PAYLOAD_CACHE) {
|
||||
PAYLOAD_CACHE.put(payloadId, (NBTTagCompound) payload.copy());
|
||||
}
|
||||
}
|
||||
|
||||
private static NBTTagCompound getCachedPayload(String payloadId) {
|
||||
synchronized (PAYLOAD_CACHE) {
|
||||
return PAYLOAD_CACHE.get(payloadId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return "nei_bookmark";
|
||||
@@ -20,7 +41,7 @@ public class CommandBookmarkAdd extends CommandBase {
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "/nei_bookmark <nbt>";
|
||||
return "/nei_bookmark <payloadId>";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -30,19 +51,37 @@ public class CommandBookmarkAdd extends CommandBase {
|
||||
|
||||
@Override
|
||||
public void processCommand(ICommandSender sender, String[] args) {
|
||||
|
||||
if (args.length < 1 || args[0].length() < 3) {
|
||||
sender.addChatMessage(new ChatComponentText("§c/nei_bookmark <nbt>"));
|
||||
if (args.length < 1) {
|
||||
sender.addChatMessage(new ChatComponentText("§c/nei_bookmark <payloadId>"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ItemPanels.bookmarkPanel.addItem(
|
||||
ItemStack.loadItemStackFromNBT((NBTTagCompound) JsonToNBT.func_150315_a(String.join(" ", args))));
|
||||
final String payloadId = String.join(" ", Arrays.copyOfRange(args, 0, args.length));
|
||||
final NBTTagCompound payload = getCachedPayload(payloadId);
|
||||
|
||||
if (payload == null) {
|
||||
throw new IllegalArgumentException("Missing cached payload");
|
||||
}
|
||||
|
||||
addBookmarkFromPayload((NBTTagCompound) payload.copy());
|
||||
sender.addChatMessage(new ChatComponentTranslation("nei.chat.bookmark_added.text"));
|
||||
} catch (NBTException e) {
|
||||
} catch (Exception e) {
|
||||
sender.addChatMessage(new ChatComponentText(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
private static void addBookmarkFromPayload(NBTTagCompound nbt) {
|
||||
final BookmarkPayload payload = BookmarkPayload.of(nbt);
|
||||
final BookmarkGrid grid = ItemPanels.bookmarkPanel.getGrid();
|
||||
final BookmarkGroup group = payload.getGroup();
|
||||
int groupId = BookmarkGrid.DEFAULT_GROUP_ID;
|
||||
|
||||
if (group != null) {
|
||||
groupId = grid.addGroup(group);
|
||||
}
|
||||
|
||||
payload.getBookmarkItems(groupId).forEach(item -> grid.addItem(item, true));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -85,11 +85,11 @@ public class RightPanel extends GuiWidget {
|
||||
setFocus(true);
|
||||
}
|
||||
|
||||
if (focused() && KeyManager.isHashDown("gui.getprevioussearch")) {
|
||||
if (focused() && KeyManager.isKeyDown("gui.getprevioussearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.PREVIOUS);
|
||||
}
|
||||
|
||||
if (focused() && KeyManager.isHashDown("gui.getnextsearch")) {
|
||||
if (focused() && KeyManager.isKeyDown("gui.getnextsearch")) {
|
||||
handleNavigateHistory(TextHistory.Direction.NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,12 @@ public class AllOthersRecipeFilter implements IRecipeFilter {
|
||||
}
|
||||
}
|
||||
|
||||
for (PositionedStack pStack : handler.getCatalystStacks(recipeIndex)) {
|
||||
if (!match(pStack)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,12 @@ public class AnyOthersRecipeFilter implements IRecipeFilter {
|
||||
}
|
||||
}
|
||||
|
||||
for (PositionedStack pStack : handler.getCatalystStacks(recipeIndex)) {
|
||||
if (match(pStack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,9 +48,7 @@ public class RecipeFilter implements IRecipeFilter {
|
||||
}
|
||||
|
||||
if (this.context == FilterContext.ANY || this.context == FilterContext.OUTPUT) {
|
||||
final PositionedStack result = handler.getResultStack(recipeIndex);
|
||||
|
||||
if (result != null && matchPositionedStack(result) == this.anyMatch) {
|
||||
if (matchPositionedStack(handler.getResultStacks(recipeIndex), this.anyMatch)) {
|
||||
return this.anyMatch;
|
||||
}
|
||||
|
||||
@@ -58,6 +56,10 @@ public class RecipeFilter implements IRecipeFilter {
|
||||
return this.anyMatch;
|
||||
}
|
||||
|
||||
if (matchPositionedStack(handler.getCatalystStacks(recipeIndex), this.anyMatch)) {
|
||||
return this.anyMatch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return !this.anyMatch;
|
||||
|
||||
@@ -625,7 +625,7 @@ public class GuiContainerManager {
|
||||
tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE);
|
||||
}
|
||||
|
||||
} else if (!tooltip.isEmpty()) {
|
||||
} else if (!tooltip.isEmpty() && !tooltip.get(0).startsWith(GuiDraw.TOOLTIP_HANDLER)) {
|
||||
tooltip.set(0, tooltip.get(0) + GuiDraw.TOOLTIP_LINESPACE);
|
||||
}
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@ public class DefaultOverlayHandler implements IOverlayHandler {
|
||||
|
||||
for (IngredientDistribution distrib : assignedIngredients) {
|
||||
if (distrib.slots.length == 0 || !slot.getHasStack() || !canStack(distrib.permutation, stack)) continue;
|
||||
int transferCap = Math.min(slotTransferCap, multiplier * distrib.permutation.stackSize);
|
||||
int transferCap = Math.min(slotTransferCap, Math.max(multiplier * distrib.permutation.stackSize, 1));
|
||||
int stackSize = slot.getStack().stackSize;
|
||||
boolean pickup = false;
|
||||
|
||||
|
||||
@@ -38,6 +38,11 @@ public class FuelRecipeHandler extends FurnaceRecipeHandler {
|
||||
public PositionedStack getOtherStack() {
|
||||
return fuel.stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PositionedStack getCatalyst() {
|
||||
return fuel.stack;
|
||||
}
|
||||
}
|
||||
|
||||
private final ArrayList<SmeltingPair> mfurnace = new ArrayList<>();
|
||||
|
||||
@@ -82,8 +82,8 @@ public class GuiCraftingRecipe extends GuiRecipe<ICraftingHandler> {
|
||||
} else if ("recipeId".equals(outputId)) {
|
||||
ItemStack stack = (ItemStack) results[0];
|
||||
RecipeId recipeId = (RecipeId) results[1];
|
||||
craftinghandlers = filterByHandlerName(craftinghandlers, recipeId.getHandleName());
|
||||
serialCraftingHandlers = filterByHandlerName(serialCraftingHandlers, recipeId.getHandleName());
|
||||
craftinghandlers = filterByHandlerName(craftinghandlers, recipeId.getHandlerName());
|
||||
serialCraftingHandlers = filterByHandlerName(serialCraftingHandlers, recipeId.getHandlerName());
|
||||
recipeHandlerFunction = h -> h.getRecipeHandler("item", stack);
|
||||
} else {
|
||||
recipeHandlerFunction = h -> h.getRecipeHandler(outputId, results);
|
||||
|
||||
@@ -230,7 +230,7 @@ public class GuiFavoriteButton extends GuiRecipeButton {
|
||||
}
|
||||
}
|
||||
|
||||
if (recipeId != null && FavoriteRecipes.FAVORITE_ITEM.contains(recipeId.getHandleName())) {
|
||||
if (recipeId != null && FavoriteRecipes.FAVORITE_ITEM.contains(recipeId.getHandlerName())) {
|
||||
items.add(stack);
|
||||
} else {
|
||||
Recipe recipe = Recipe.of(recipeId);
|
||||
|
||||
@@ -22,6 +22,7 @@ import codechicken.nei.NEIClientUtils;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.api.IOverlayHandler;
|
||||
import codechicken.nei.bookmark.BookmarkGrid;
|
||||
import codechicken.nei.bookmark.BookmarkPayload;
|
||||
import codechicken.nei.drawable.DrawableBuilder;
|
||||
import codechicken.nei.drawable.DrawableResource;
|
||||
import codechicken.nei.util.NEIMouseUtils;
|
||||
@@ -171,6 +172,10 @@ public class GuiOverlayButton extends GuiRecipeButton {
|
||||
KeyManager.getKeyName("bookmark.add", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("recipe.overlay.bookmarkRecipeAndCount"));
|
||||
|
||||
hotkeys.put(
|
||||
KeyManager.getKeyName("bookmark.chat_link", NEIClientUtils.SHIFT_HASH + NEIClientUtils.CTRL_HASH),
|
||||
NEIClientUtils.translate("recipe.overlay.sendRecipeToChat"));
|
||||
|
||||
return hotkeys;
|
||||
}
|
||||
|
||||
@@ -329,6 +334,10 @@ public class GuiOverlayButton extends GuiRecipeButton {
|
||||
if (KeyManager.isKeyDown("bookmark.add") && NEIClientUtils.shiftKey()) {
|
||||
saveRecipeInBookmark();
|
||||
}
|
||||
|
||||
if (KeyManager.isKeyDown("bookmark.chat_link") && NEIClientUtils.controlKey() && NEIClientUtils.shiftKey()) {
|
||||
sendRecipeChatLink();
|
||||
}
|
||||
}
|
||||
|
||||
public void saveRecipeInBookmark() {
|
||||
@@ -343,4 +352,7 @@ public class GuiOverlayButton extends GuiRecipeButton {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendRecipeChatLink() {
|
||||
NEIClientUtils.sendChatItemLink(BookmarkPayload.of(getRecipe()).toNBT());
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ import codechicken.nei.scroll.ScrollBar;
|
||||
import codechicken.nei.scroll.ScrollBar.OverflowType;
|
||||
import codechicken.nei.scroll.ScrollBar.ScrollPlace;
|
||||
import codechicken.nei.scroll.ScrollContainer;
|
||||
import codechicken.nei.util.EmptyContainer;
|
||||
import codechicken.nei.util.SlotInaccessible;
|
||||
|
||||
public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer implements IGuiContainerOverlay,
|
||||
@@ -181,7 +182,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
private boolean isHeightHackApplied = false;
|
||||
|
||||
protected GuiRecipe(GuiScreen prevgui) {
|
||||
super(new ContainerRecipe());
|
||||
super(new EmptyContainer());
|
||||
this.recipeTabs = new GuiRecipeTabs() {
|
||||
|
||||
@Override
|
||||
@@ -191,7 +192,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
|
||||
};
|
||||
this.recipeCatalyst = new GuiRecipeCatalyst();
|
||||
this.slotcontainer = (ContainerRecipe) this.inventorySlots;
|
||||
this.slotcontainer = (EmptyContainer) this.inventorySlots;
|
||||
|
||||
this.prevGui = prevgui;
|
||||
this.firstGuiGeneral = prevgui;
|
||||
@@ -476,7 +477,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
final H localHandler = this.currenthandlers.get(j);
|
||||
final HandlerInfo localHandlerInfo = GuiRecipeTab.getHandlerInfo(localHandler);
|
||||
|
||||
if (localHandlerInfo.getHandlerName().equals(this.recipeId.getHandleName())) {
|
||||
if (localHandlerInfo.getHandlerName().equals(this.recipeId.getHandlerName())) {
|
||||
recipetype = j;
|
||||
|
||||
if (!this.recipeId.getIngredients().isEmpty()) {
|
||||
@@ -526,7 +527,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
@Override
|
||||
public Slot getSlotAtPosition(int mousex, int mousey) {
|
||||
final Widget activeWidget = this.container.getWidgetUnderMouse(mousex, mousey);
|
||||
final ContainerRecipe slotcontainer = (ContainerRecipe) inventorySlots;
|
||||
final EmptyContainer slotcontainer = (EmptyContainer) inventorySlots;
|
||||
slotcontainer.setActiveStack(null);
|
||||
|
||||
if (activeWidget instanceof NEIRecipeWidget recipeWidget) {
|
||||
@@ -1033,7 +1034,7 @@ public abstract class GuiRecipe<H extends IRecipeHandler> extends GuiContainer i
|
||||
private GuiOverlayButton[] overlayButtons = new GuiOverlayButton[0];
|
||||
|
||||
@Deprecated
|
||||
public ContainerRecipe slotcontainer;
|
||||
public EmptyContainer slotcontainer;
|
||||
|
||||
@Deprecated
|
||||
public List<GuiButton> getOverlayButtons() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package codechicken.nei.recipe;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
@@ -82,15 +83,38 @@ public interface IRecipeHandler {
|
||||
* @return A list of the other {@link PositionedStack}s in this recipe relative to the top left corner of your
|
||||
* recipe drawing space. For example fuel in furnaces.
|
||||
*/
|
||||
default List<PositionedStack> getCatalystStacks(int recipe) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy API, define either {@link #getCatalystStacks(int)} or {@link #getResultStacks(int)}
|
||||
*
|
||||
* @param recipe The recipe index to get items for.
|
||||
* @return A list of the other {@link PositionedStack}s in this recipe relative to the top left corner of your
|
||||
* recipe drawing space. For example fuel in furnaces.
|
||||
*/
|
||||
List<PositionedStack> getOtherStacks(int recipe);
|
||||
|
||||
/**
|
||||
* Legacy API, use {@link #getResultStacks(int) getResultStacks.get(0)} if you want the primary result
|
||||
*
|
||||
* @param recipe The recipe index to get the result for.
|
||||
* @return The recipe result {@link PositionedStack} relative to the top left corner of your recipe drawing space.
|
||||
*/
|
||||
PositionedStack getResultStack(int recipe);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param recipe The recipe index to get the result for.
|
||||
* @return A list of the result {@link PositionedStack}s relative to the top left corner of your recipe drawing
|
||||
* space.
|
||||
*/
|
||||
default List<PositionedStack> getResultStacks(int recipe) {
|
||||
final PositionedStack result = getResultStack(recipe);
|
||||
return result != null ? Collections.singletonList(result) : Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* A tick function called for updating progress bars and cycling damage items.
|
||||
*/
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
@@ -36,6 +37,7 @@ import codechicken.nei.recipe.GuiRecipeButton.UpdateRecipeButtonsEvent;
|
||||
import codechicken.nei.recipe.Recipe.RecipeId;
|
||||
import codechicken.nei.recipe.debug.DebugHandlerWidget;
|
||||
import codechicken.nei.util.NEIMouseUtils;
|
||||
import it.unimi.dsi.fastutil.longs.LongArraySet;
|
||||
|
||||
public class NEIRecipeWidget extends Widget {
|
||||
|
||||
@@ -54,6 +56,9 @@ public class NEIRecipeWidget extends Widget {
|
||||
protected boolean showAsWidget = false;
|
||||
protected List<GuiRecipeButton> recipeButtons = null;
|
||||
|
||||
// Handles re-draws for catalysts-outputs duplication to preserve full backward compatibility for otherStacks
|
||||
private final Set<Long> drawnSlots = new LongArraySet();
|
||||
|
||||
public NEIRecipeWidget(RecipeHandlerRef handlerRef) {
|
||||
this.handlerRef = handlerRef;
|
||||
this.handlerInfo = GuiRecipeTab.getHandlerInfo(this.handlerRef.handler);
|
||||
@@ -193,28 +198,40 @@ public class NEIRecipeWidget extends Widget {
|
||||
|
||||
GuiContainerManager.enableMatrixStackLogging();
|
||||
|
||||
for (PositionedStack pStack : getInputs()) {
|
||||
final List<PositionedStack> inputs = getInputs();
|
||||
final List<PositionedStack> catalysts = getCatalysts();
|
||||
final List<PositionedStack> outputs = getOutputs();
|
||||
|
||||
if (!this.permutations.containsKey(pStack)) {
|
||||
updatePermutationsFor(pStack);
|
||||
}
|
||||
|
||||
drawItem(pStack, mouseX, mouseY, yShift, true);
|
||||
}
|
||||
|
||||
for (PositionedStack pStack : getCatalysts()) {
|
||||
|
||||
if (!this.permutations.containsKey(pStack)) {
|
||||
updatePermutationsFor(pStack);
|
||||
}
|
||||
|
||||
drawItem(pStack, mouseX, mouseY, yShift, true);
|
||||
}
|
||||
|
||||
for (PositionedStack pStack : getOutputs()) {
|
||||
drawnSlots.clear();
|
||||
for (PositionedStack pStack : inputs) {
|
||||
drawnSlots.add(slotKey(pStack));
|
||||
drawItem(pStack, mouseX, mouseY, yShift, false);
|
||||
}
|
||||
|
||||
for (PositionedStack pStack : catalysts) {
|
||||
if (!drawnSlots.add(slotKey(pStack))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.permutations.containsKey(pStack)) {
|
||||
updatePermutationsFor(pStack);
|
||||
}
|
||||
|
||||
drawItem(pStack, mouseX, mouseY, yShift, true);
|
||||
}
|
||||
|
||||
for (PositionedStack pStack : outputs) {
|
||||
if (!drawnSlots.add(slotKey(pStack))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this.permutations.containsKey(pStack)) {
|
||||
updatePermutationsFor(pStack);
|
||||
}
|
||||
|
||||
drawItem(pStack, mouseX, mouseY, yShift, true);
|
||||
}
|
||||
|
||||
GuiContainerManager.disableMatrixStackLogging();
|
||||
|
||||
this.handlerRef.handler.drawForeground(this.handlerRef.recipeIndex);
|
||||
@@ -246,6 +263,10 @@ public class NEIRecipeWidget extends Widget {
|
||||
DebugHandlerWidget.instance.drawGuiPlaceholder(this);
|
||||
}
|
||||
|
||||
private static long slotKey(PositionedStack pStack) {
|
||||
return ((long) pStack.relx << 32) ^ (pStack.rely & 0xFFFFFFFFL);
|
||||
}
|
||||
|
||||
protected void drawItem(PositionedStack pStack, int mouseX, int mouseY, int yShift, boolean input) {
|
||||
GuiContainerManager.drawItem(pStack.relx, pStack.rely, pStack.item);
|
||||
|
||||
@@ -656,13 +677,19 @@ public class NEIRecipeWidget extends Widget {
|
||||
}
|
||||
|
||||
protected List<PositionedStack> getOutputs() {
|
||||
final PositionedStack pStackResult = this.handlerRef.handler.getResultStack(this.handlerRef.recipeIndex);
|
||||
return pStackResult != null ? Arrays.asList(pStackResult)
|
||||
final List<PositionedStack> pStackResults = this.handlerRef.handler
|
||||
.getResultStacks(this.handlerRef.recipeIndex);
|
||||
return !pStackResults.isEmpty() ? pStackResults
|
||||
: this.handlerRef.handler.getOtherStacks(this.handlerRef.recipeIndex);
|
||||
}
|
||||
|
||||
protected List<PositionedStack> getCatalysts() {
|
||||
if (this.handlerRef.handler.getResultStack(this.handlerRef.recipeIndex) == null) {
|
||||
List<PositionedStack> catalysts = this.handlerRef.handler.getCatalystStacks(this.handlerRef.recipeIndex);
|
||||
if (!catalysts.isEmpty()) {
|
||||
return catalysts;
|
||||
}
|
||||
|
||||
if (this.handlerRef.handler.getResultStacks(this.handlerRef.recipeIndex).isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return this.handlerRef.handler.getOtherStacks(this.handlerRef.recipeIndex);
|
||||
|
||||
@@ -54,19 +54,26 @@ public class Recipe {
|
||||
public static RecipeId of(IRecipeHandler handler, int recipeIndex) {
|
||||
final List<PositionedStack> ingredients = handler.getIngredientStacks(recipeIndex);
|
||||
final String handlerName = GuiRecipeTab.getHandlerInfo(handler).getHandlerName();
|
||||
PositionedStack pStackResult = handler.getResultStack(recipeIndex);
|
||||
// Use getResultStacks even though getResult could work because if a handler, like GT for example, doesn't
|
||||
// return anything from getResult, but will define all the outputs in getResultStacks we can still pick up
|
||||
// the results here. If a handler still doesn't define getResultStacks, then it will naturally fall back to
|
||||
// getResult anyway
|
||||
List<PositionedStack> pStackResults = handler.getResultStacks(recipeIndex);
|
||||
|
||||
if (pStackResult == null) {
|
||||
if (pStackResults.isEmpty()) {
|
||||
for (PositionedStack otherStack : handler.getOtherStacks(recipeIndex)) {
|
||||
if (!FluidContainerRegistry.isContainer(otherStack.items[0])
|
||||
|| StackInfo.getFluid(otherStack.items[0]) != null) {
|
||||
pStackResult = otherStack;
|
||||
pStackResults.add(otherStack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new RecipeId(extractItem(pStackResult), handlerName, extractIngredients(ingredients));
|
||||
return new RecipeId(
|
||||
extractItem(!pStackResults.isEmpty() ? pStackResults.get(0) : null),
|
||||
handlerName,
|
||||
extractIngredients(ingredients));
|
||||
}
|
||||
|
||||
public static RecipeId of(JsonObject json) {
|
||||
@@ -89,7 +96,7 @@ public class Recipe {
|
||||
return new RecipeId(result, handlerName, ingredients);
|
||||
}
|
||||
|
||||
public String getHandleName() {
|
||||
public String getHandlerName() {
|
||||
return this.handlerName;
|
||||
}
|
||||
|
||||
@@ -389,8 +396,12 @@ public class Recipe {
|
||||
ingredients.add(RecipeIngredient.of(positionedStack));
|
||||
}
|
||||
|
||||
if (handler.getResultStack(recipeIndex) != null) {
|
||||
results.add(RecipeIngredient.of(handler.getResultStack(recipeIndex)));
|
||||
final List<PositionedStack> resultStacks = handler.getResultStacks(recipeIndex);
|
||||
|
||||
if (!resultStacks.isEmpty()) {
|
||||
for (PositionedStack positionedStack : resultStacks) {
|
||||
results.add(RecipeIngredient.of(positionedStack));
|
||||
}
|
||||
} else {
|
||||
for (PositionedStack positionedStack : handler.getOtherStacks(recipeIndex)) {
|
||||
results.add(RecipeIngredient.of(positionedStack));
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -132,7 +133,48 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
public abstract PositionedStack getResult();
|
||||
|
||||
/**
|
||||
* The ingredients required to produce the result Use this if you have more than one ingredient
|
||||
* The multiple items produced by this recipe, with position
|
||||
*
|
||||
* @return A list of positioned ingredient items.
|
||||
*/
|
||||
public List<PositionedStack> getResults() {
|
||||
ArrayList<PositionedStack> stacks = new ArrayList<>();
|
||||
try {
|
||||
PositionedStack stack = getResult();
|
||||
if (stack != null) stacks.add(stack);
|
||||
} catch (ArithmeticException e) {
|
||||
NEIClientConfig.logger.error("Error in getOtherStacks: " + e);
|
||||
}
|
||||
return stacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return extra items that are not directly involved in the ingredient->result relationship. Eg fuels.
|
||||
*
|
||||
* @return A list of positioned ingredient items.
|
||||
*/
|
||||
public List<PositionedStack> getCatalysts() {
|
||||
ArrayList<PositionedStack> stacks = new ArrayList<>();
|
||||
try {
|
||||
PositionedStack stack = getCatalyst();
|
||||
if (stack != null) stacks.add(stack);
|
||||
} catch (ArithmeticException e) {
|
||||
NEIClientConfig.logger.error("Error in getCatalysts: " + e);
|
||||
}
|
||||
return stacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple utility
|
||||
*
|
||||
* @return The another positioned stack
|
||||
*/
|
||||
public PositionedStack getCatalyst() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ingredients required to produce the result. Use this if you have more than one ingredient
|
||||
*
|
||||
* @return A list of positioned ingredient items.
|
||||
*/
|
||||
@@ -151,6 +193,8 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy API
|
||||
*
|
||||
* Return extra items that are not directly involved in the ingredient->result relationship. Eg fuels. Use this
|
||||
* if you have more than one other stack
|
||||
*
|
||||
@@ -289,9 +333,9 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode) {
|
||||
if (!canHandle(gui)) return false;
|
||||
|
||||
if (KeyManager.isHashDown("recipe.recipe")) {
|
||||
if (KeyManager.isKeyDown("recipe.recipe")) {
|
||||
return transferRect(gui, false);
|
||||
} else if (KeyManager.isHashDown("recipe.usage")) {
|
||||
} else if (KeyManager.isKeyDown("recipe.usage")) {
|
||||
return transferRect(gui, true);
|
||||
}
|
||||
|
||||
@@ -625,13 +669,23 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
}
|
||||
|
||||
public PositionedStack getResultStack(int recipe) {
|
||||
List<PositionedStack> results = getResultStacks(recipe);
|
||||
if (results == null || results.isEmpty()) return null;
|
||||
return results.get(0);
|
||||
}
|
||||
|
||||
public List<PositionedStack> getResultStacks(int recipe) {
|
||||
try {
|
||||
return arecipes.get(recipe).getResult();
|
||||
return arecipes.get(recipe).getResults();
|
||||
} catch (ArrayIndexOutOfBoundsException ignored) {
|
||||
return null;
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public List<PositionedStack> getCatalystStacks(int recipe) {
|
||||
return arecipes.get(recipe).getCatalysts();
|
||||
}
|
||||
|
||||
public List<PositionedStack> getOtherStacks(int recipe) {
|
||||
return arecipes.get(recipe).getOtherStacks();
|
||||
}
|
||||
@@ -673,9 +727,9 @@ public abstract class TemplateRecipeHandler implements ICraftingHandler, IUsageH
|
||||
@Override
|
||||
public boolean keyTyped(GuiRecipe<?> gui, char keyChar, int keyCode, int recipe) {
|
||||
|
||||
if (KeyManager.isHashDown("recipe.recipe")) {
|
||||
if (KeyManager.isKeyDown("recipe.recipe")) {
|
||||
return transferRect(gui, recipe, false);
|
||||
} else if (KeyManager.isHashDown("recipe.usage")) {
|
||||
} else if (KeyManager.isKeyDown("recipe.usage")) {
|
||||
return transferRect(gui, recipe, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,34 @@ import codechicken.nei.recipe.StackInfo;
|
||||
|
||||
public class RecipeChainMath {
|
||||
|
||||
public interface ChainVisitor {
|
||||
|
||||
void enterRecipe(RecipeId recipeId, long multiplier);
|
||||
|
||||
void addIngredient(BookmarkItem ingrItem, long requestedAmount);
|
||||
|
||||
void addIngredientFresh(BookmarkItem ingrItem, long freshAmount);
|
||||
|
||||
void leaveRecipe();
|
||||
|
||||
}
|
||||
|
||||
private static class EmptyChainVisitor implements ChainVisitor {
|
||||
|
||||
@Override
|
||||
public void enterRecipe(RecipeId recipeId, long multiplier) {}
|
||||
|
||||
@Override
|
||||
public void addIngredient(BookmarkItem ingrItem, long requestedAmount) {}
|
||||
|
||||
@Override
|
||||
public void addIngredientFresh(BookmarkItem ingrItem, long freshAmount) {}
|
||||
|
||||
@Override
|
||||
public void leaveRecipe() {}
|
||||
|
||||
}
|
||||
|
||||
private static class ContainerItemResult {
|
||||
|
||||
public ItemStack stack;
|
||||
@@ -38,6 +66,8 @@ public class RecipeChainMath {
|
||||
}
|
||||
}
|
||||
|
||||
private static final ChainVisitor EMPTY_CHAIN_VISITOR = new EmptyChainVisitor();
|
||||
|
||||
private static final ItemStack ROOT_ITEM = new ItemStack(Blocks.fire);
|
||||
private static final RecipeId ROOT_RECIPE_ID = RecipeId
|
||||
.of(ROOT_ITEM, "recipe-autocrafting", Collections.emptyList());
|
||||
@@ -298,6 +328,10 @@ public class RecipeChainMath {
|
||||
}
|
||||
|
||||
public RecipeChainMath refresh() {
|
||||
return refresh(EMPTY_CHAIN_VISITOR);
|
||||
}
|
||||
|
||||
public RecipeChainMath refresh(ChainVisitor visitor) {
|
||||
final boolean isPausedItemDamageSound = StackInfo.isPausedItemDamageSound();
|
||||
StackInfo.pauseItemDamageSound(true);
|
||||
|
||||
@@ -321,7 +355,7 @@ public class RecipeChainMath {
|
||||
}
|
||||
|
||||
this.preferredItems.put(prefItem, prefItem);
|
||||
calculateSuitableRecipe(prefItem, prefAmount, new ArrayList<>());
|
||||
calculateSuitableRecipe(prefItem, prefAmount, new ArrayList<>(), visitor);
|
||||
this.preferredItems.remove(prefItem);
|
||||
}
|
||||
}
|
||||
@@ -338,9 +372,12 @@ public class RecipeChainMath {
|
||||
return this;
|
||||
}
|
||||
|
||||
private void calculateSuitableRecipe(BookmarkItem ingrItem, long ingrAmount, List<RecipeId> visited) {
|
||||
private void calculateSuitableRecipe(BookmarkItem ingrItem, long ingrAmount, List<RecipeId> visited,
|
||||
ChainVisitor visitor) {
|
||||
final BookmarkItem prefItem = this.preferredItems.get(ingrItem);
|
||||
|
||||
visitor.addIngredient(prefItem != null ? prefItem : ingrItem, ingrAmount);
|
||||
|
||||
// calculate existing containers
|
||||
if (ingrAmount > 0) {
|
||||
for (ItemStack stack : ingrItem.permutations.values()) {
|
||||
@@ -358,7 +395,7 @@ public class RecipeChainMath {
|
||||
if (ingrAmount > 0) {
|
||||
for (BookmarkItem item : this.initialItems) {
|
||||
if (item.containsItems(ingrItem)
|
||||
&& (ingrAmount = addRequiredAmount(item, ingrAmount, item.getAmount())) == 0) {
|
||||
&& (ingrAmount = addRequiredAmount(item, ingrAmount, item.getAmount(), visitor)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -366,33 +403,37 @@ public class RecipeChainMath {
|
||||
|
||||
// shift amount
|
||||
if (prefItem == null) {
|
||||
addRequiredAmount(ingrItem, ingrAmount, Long.MAX_VALUE);
|
||||
addRequiredAmount(ingrItem, ingrAmount, Long.MAX_VALUE, visitor);
|
||||
} else if (visited.contains(prefItem.recipeId)) {
|
||||
addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE);
|
||||
addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE, visitor);
|
||||
} else {
|
||||
addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE);
|
||||
addRequiredAmount(prefItem, ingrAmount, Long.MAX_VALUE, visitor);
|
||||
final long multiplier = Math
|
||||
.max(0, prefItem.getMultiplierFromAmount(this.requiredAmount.get(prefItem)) - prefItem.multiplier);
|
||||
|
||||
if (multiplier > 0) {
|
||||
addShift(prefItem.recipeId, multiplier);
|
||||
visited.add(prefItem.recipeId);
|
||||
prepareIngredients(prefItem.recipeId, multiplier, visited);
|
||||
prepareIngredients(prefItem.recipeId, multiplier, visited, visitor);
|
||||
visited.remove(prefItem.recipeId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void prepareIngredients(RecipeId recipeId, long multiplier, List<RecipeId> visited) {
|
||||
private void prepareIngredients(RecipeId recipeId, long multiplier, List<RecipeId> visited, ChainVisitor visitor) {
|
||||
visitor.enterRecipe(recipeId, multiplier);
|
||||
|
||||
for (BookmarkItem item : this.recipeIngredients) {
|
||||
if (!item.emptyFactor() && recipeId.equals(item.recipeId)) {
|
||||
calculateSuitableRecipe(item, item.getAmount(multiplier), visited);
|
||||
calculateSuitableRecipe(item, item.getAmount(multiplier), visited, visitor);
|
||||
}
|
||||
}
|
||||
|
||||
visitor.leaveRecipe();
|
||||
}
|
||||
|
||||
private long addRequiredAmount(BookmarkItem prefItem, long ingrAmount, long maxAmount) {
|
||||
private long addRequiredAmount(BookmarkItem prefItem, long ingrAmount, long maxAmount, ChainVisitor visitor) {
|
||||
long shiftAmount = this.requiredAmount.getOrDefault(prefItem, 0L);
|
||||
|
||||
if (hasContainerItem(prefItem.itemStack)) {
|
||||
@@ -411,8 +452,9 @@ public class RecipeChainMath {
|
||||
final ContainerItemResult result = getToolsContainerItems(itemStack, steps);
|
||||
|
||||
if (result.stack == null) {
|
||||
multiplier = steps / (steps - result.leftSteps);
|
||||
steps = steps % (steps - result.leftSteps);
|
||||
final long stepsPerReplacement = steps - result.leftSteps;
|
||||
multiplier = Math.min(steps / stepsPerReplacement, maxAmount - shiftAmount);
|
||||
steps -= multiplier * stepsPerReplacement;
|
||||
} else {
|
||||
steps = result.leftSteps;
|
||||
}
|
||||
@@ -448,6 +490,7 @@ public class RecipeChainMath {
|
||||
ingrAmount -= initAmount;
|
||||
}
|
||||
|
||||
visitor.addIngredientFresh(prefItem, shiftAmount - this.requiredAmount.getOrDefault(prefItem, 0L));
|
||||
this.requiredAmount.put(prefItem, shiftAmount);
|
||||
|
||||
return ingrAmount;
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package codechicken.nei.recipe;
|
||||
package codechicken.nei.util;
|
||||
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.Container;
|
||||
@@ -8,7 +8,7 @@ import net.minecraft.item.ItemStack;
|
||||
import codechicken.nei.PositionedStack;
|
||||
import codechicken.nei.api.ShortcutInputHandler;
|
||||
|
||||
public class ContainerRecipe extends Container {
|
||||
public class EmptyContainer extends Container {
|
||||
|
||||
private ItemStack activeStack = null;
|
||||
|
||||
@@ -23,13 +23,13 @@ public class NEIKeyboardUtils {
|
||||
keyHashMap.put(Keyboard.KEY_RSHIFT, SHIFT_HASH);
|
||||
|
||||
keyHashMap.put(Keyboard.KEY_LCONTROL, CTRL_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_LCONTROL, CTRL_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_RCONTROL, CTRL_HASH);
|
||||
|
||||
keyHashMap.put(Keyboard.KEY_LMETA, CTRL_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_RMETA, CTRL_HASH);
|
||||
|
||||
keyHashMap.put(Keyboard.KEY_LMENU, ALT_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_LMENU, ALT_HASH);
|
||||
keyHashMap.put(Keyboard.KEY_RMENU, ALT_HASH);
|
||||
}
|
||||
|
||||
private NEIKeyboardUtils() {}
|
||||
@@ -67,7 +67,7 @@ public class NEIKeyboardUtils {
|
||||
}
|
||||
|
||||
if (keyID != Keyboard.CHAR_NONE || hashText.isEmpty()) {
|
||||
keyText.add(Keyboard.getKeyName(keyID));
|
||||
keyText.add(keyID < 0 ? NEIMouseUtils.getKeyName(keyID + 100) : Keyboard.getKeyName(keyID));
|
||||
}
|
||||
|
||||
return keyText.toString();
|
||||
|
||||
@@ -62,6 +62,27 @@ ICONST_0
|
||||
ICONST_1 #keep the destination alpha
|
||||
INVOKESTATIC net/minecraft/client/renderer/OpenGlHelper.func_148821_a (IIII)V
|
||||
|
||||
list m_keyBindingOnTickAll
|
||||
ILOAD 0
|
||||
INVOKESTATIC codechicken/nei/asm/KeyBindingFixHooks.onTickAll (I)V
|
||||
RETURN
|
||||
|
||||
list m_keyBindingSetStateAll
|
||||
ILOAD 0
|
||||
ILOAD 1
|
||||
INVOKESTATIC codechicken/nei/asm/KeyBindingFixHooks.setKeyBindStateAll (IZ)V
|
||||
RETURN
|
||||
|
||||
list saveOptionsHook
|
||||
INVOKESTATIC codechicken/nei/asm/SaveOptionsFixHooks.onBeforeSaveOptions ()V
|
||||
|
||||
list n_saveOptionsSendSettings
|
||||
ALOAD 0
|
||||
INVOKEVIRTUAL net/minecraft/client/settings/GameSettings.func_82879_c ()V
|
||||
|
||||
list saveOptionsRestoreHook
|
||||
INVOKESTATIC codechicken/nei/asm/SaveOptionsFixHooks.onAfterSaveOptions ()V
|
||||
|
||||
|
||||
#begin GuiContainer patches
|
||||
|
||||
@@ -383,4 +404,3 @@ INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.objectUnderMouse (II)Z
|
||||
IFEQ LCONT
|
||||
RETURN
|
||||
LCONT
|
||||
|
||||
@@ -32,7 +32,9 @@ nei.bookmark.group.pull_items=Pull all Items
|
||||
nei.bookmark.group.pull_items_shift=Pull missing Items
|
||||
nei.bookmark.group.craft_missing=Craft Missing Items
|
||||
nei.bookmark.group.craft_all=Craft Items
|
||||
nei.bookmark.group.chat_link=Send Bookmark Group to Chat
|
||||
nei.bookmark.item.sorting=Move Position
|
||||
nei.bookmark.item.chat_link=Send Item to Chat
|
||||
nei.bookmark.remove_recipe=Remove Recipe
|
||||
nei.bookmark.remove_item=Remove Item
|
||||
nei.bookmark.add_item=Add Bookmark
|
||||
@@ -42,6 +44,7 @@ nei.bookmark.add_item_with_count=Add Bookmark with Count
|
||||
nei.bookmark.change_quantity=Change Quantity
|
||||
nei.bookmark.change_quantity_step=Change Quantity with Multiplier
|
||||
nei.bookmark.recipe.toggle_collapse=Toggle Collapse/Expand
|
||||
nei.bookmark.recipe.chat_link=Send Recipe to Chat
|
||||
nei.bookmark.crafting_chain=Crafting Chain
|
||||
nei.bookmark.crafting_chain.input=Ingredients
|
||||
nei.bookmark.crafting_chain.missing=Missing Items
|
||||
@@ -68,6 +71,7 @@ nei.itempanel.infinite_item=Give Infinite Item
|
||||
nei.itempanel.copy_name=Copy Item Name
|
||||
nei.itempanel.copy_oredict=Copy Item OreDictionary
|
||||
nei.itempanel.copy_id=Copy Item ID
|
||||
|
||||
nei.itempanel.chat_link_item=Send item link to chat
|
||||
|
||||
nei.enchant=Enchant
|
||||
@@ -143,6 +147,9 @@ nei.chat.chunkoverlay.3=Chunk Overlay: GT Ore Veins
|
||||
nei.chat.moboverlay.0=Mob Spawning Overlay: §cOff
|
||||
nei.chat.moboverlay.1=Mob Spawning Overlay: §2On
|
||||
nei.chat.item_link.text=<%s> §6Click to add bookmark: %s
|
||||
nei.chat.item_link.item.text=Bookmark Item
|
||||
nei.chat.item_link.recipe.text=Bookmark Recipe
|
||||
nei.chat.item_link.group.text=Bookmark Group
|
||||
nei.chat.bookmark_added.text=Bookmark added!
|
||||
|
||||
nei.chat.recipeid.many_params=Too many parameters! Usage: %s
|
||||
@@ -194,6 +201,7 @@ 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.bookmark.chat_link=Send link to chat (Ctrl +)
|
||||
nei.options.keys.gui.overlay=Fill/Overlay Crafting Grid
|
||||
nei.options.keys.gui.getprevioussearch=Previous Search
|
||||
nei.options.keys.gui.getnextsearch=Next Search
|
||||
@@ -202,7 +210,6 @@ 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
|
||||
@@ -605,6 +612,7 @@ nei.recipe.overlay.overlayRecipe=Overlay Recipe
|
||||
nei.recipe.overlay.fillCraftingGrid=Fill Crafting Grid
|
||||
nei.recipe.overlay.bookmarkRecipe=Save with Recipe
|
||||
nei.recipe.overlay.bookmarkRecipeAndCount=Save with Recipe & Count
|
||||
nei.recipe.overlay.sendRecipeToChat=Send Recipe to Chat
|
||||
|
||||
nei.recipe.favorite=Favorite
|
||||
nei.recipe.favorite.bookmark_recipe=Save Recipe Tree
|
||||
|
||||
@@ -20,6 +20,7 @@ nei.bookmark.group.sorting=Сортировка
|
||||
nei.bookmark.group.remove_recipe=Удалить группу
|
||||
nei.bookmark.group.pull_items=Переместить все предметы
|
||||
nei.bookmark.group.pull_items_shift=Переместить недостающие предметы
|
||||
nei.bookmark.group.chat_link=Отправить группу в чат
|
||||
nei.bookmark.crafting_chain=Цепочка крафта
|
||||
nei.bookmark.crafting_chain.input=Ингредиенты
|
||||
nei.bookmark.crafting_chain.output=Результаты
|
||||
@@ -141,6 +142,7 @@ 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.bookmark.chat_link=Отправить ссылку в чат (Ctrl +)
|
||||
nei.options.keys.gui.overlay=Заполнить сетку крафта
|
||||
nei.options.keys.gui.getprevioussearch=Предыдущий поиск
|
||||
nei.options.keys.gui.getnextsearch=Следующий поиск
|
||||
@@ -149,7 +151,6 @@ nei.options.keys.copy.name=Скопировать название предме
|
||||
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=Увеличить предмет
|
||||
@@ -422,6 +423,7 @@ nei.recipe.overlay.missing=Отсутствует следующее
|
||||
nei.recipe.overlay.mismatch=Несоответствие сетки крафта
|
||||
nei.recipe.overlay.fillCraftingGrid=Заполнить сетку крафта
|
||||
nei.recipe.overlay.bookmarkRecipe=Сохранить с рецептом
|
||||
nei.recipe.overlay.sendRecipeToChat=Отправить рецепт в чат
|
||||
|
||||
nei.itemsort.minecraft=Minecraft
|
||||
nei.itemsort.minecraft.tip=Сортирует предметы из ванильного Minecraft первыми
|
||||
|
||||
Reference in new issue
Block a user