Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #4253: Just transfer the recipe id instead of every ingredient. #4689

Merged
merged 6 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ forge_version=33.0.22
# Provided APIs #
#########################################################
jei_minecraft_version=1.16.2
jei_version=7.1.1.15
jei_version=7.3.2.25
top_version=3.0.3-beta-6
hwyla_version=1.10.8-B72_1.15.2
ctm_version=MC1.15.2-1.1.0.9
Expand Down
357 changes: 254 additions & 103 deletions src/main/java/appeng/core/sync/packets/JEIRecipePacket.java

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/main/java/appeng/integration/abstraction/IJEI.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,19 @@

package appeng.integration.abstraction;

import mezz.jei.api.runtime.IJeiRuntime;

import appeng.integration.IIntegrationModule;

/**
* Abstracts access to the JEI API functionality.
*/
public interface IJEI extends IIntegrationModule {

default IJeiRuntime getRuntime() {
return null;
}

default String getSearchText() {
return "";
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2020 Team Appliedenergistics, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/

package appeng.integration.modules.jei;

import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.ResourceLocation;

import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.recipe.transfer.IRecipeTransferError;
import mezz.jei.api.recipe.transfer.IRecipeTransferHandlerHelper;

import appeng.container.implementations.CraftingTermContainer;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.JEIRecipePacket;

public class CraftingRecipeTransferHandler extends RecipeTransferHandler<CraftingTermContainer> {

CraftingRecipeTransferHandler(Class<CraftingTermContainer> containerClass, IRecipeTransferHandlerHelper helper) {
super(containerClass, helper);
}

@Override
protected IRecipeTransferError doTransferRecipe(CraftingTermContainer container, IRecipe<?> recipe,
IRecipeLayout recipeLayout, PlayerEntity player, boolean maxTransfer) {
return null;
}

@Override
protected boolean isCrafting() {
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ private ShapedRecipe make(ItemStack textureItem, ItemStack cableAnchor, ItemStac
ingredients.set(7, Ingredient.fromStacks(cableAnchor));
ingredients.set(4, Ingredient.fromStacks(textureItem));

result.setCount(4);

return new ShapedRecipe(id, "", 3, 3, ingredients, result);
}

Expand Down
12 changes: 8 additions & 4 deletions src/main/java/appeng/integration/modules/jei/JEIPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,15 @@ public void registerCategories(IRecipeCategoryRegistration registry) {

@Override
public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) {
// Allow recipe transfer from JEI to crafting and pattern terminal
registration.addRecipeTransferHandler(new RecipeTransferHandler<>(CraftingTermContainer.class),
VanillaRecipeCategoryUid.CRAFTING);
registration.addRecipeTransferHandler(new RecipeTransferHandler<>(PatternTermContainer.class),

// Allow vanilla crafting recipe transfer from JEI to crafting terminal
registration.addRecipeTransferHandler(
new CraftingRecipeTransferHandler(CraftingTermContainer.class, registration.getTransferHelper()),
VanillaRecipeCategoryUid.CRAFTING);

// Universal handler for processing to try and handle all IRecipe
registration.addUniversalRecipeTransferHandler(
new PatternRecipeTransferHandler(PatternTermContainer.class, registration.getTransferHelper()));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public boolean isEnabled() {
return true;
}

public IJeiRuntime getRuntime() {
return runtime;
}

@Override
public String getSearchText() {
return Strings.nullToEmpty(this.runtime.getIngredientFilter().getFilterText());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2020 Team Appliedenergistics, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/

package appeng.integration.modules.jei;

import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.util.ResourceLocation;

import mezz.jei.api.constants.VanillaRecipeCategoryUid;
import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.recipe.transfer.IRecipeTransferError;
import mezz.jei.api.recipe.transfer.IRecipeTransferHandlerHelper;

import appeng.container.implementations.PatternTermContainer;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.JEIRecipePacket;

public class PatternRecipeTransferHandler extends RecipeTransferHandler<PatternTermContainer> {

PatternRecipeTransferHandler(Class<PatternTermContainer> containerClass, IRecipeTransferHandlerHelper helper) {
super(containerClass, helper);
}

protected IRecipeTransferError doTransferRecipe(PatternTermContainer container, IRecipe<?> recipe,
IRecipeLayout recipeLayout, PlayerEntity player, boolean maxTransfer) {
if (container.isCraftingMode()
&& recipeLayout.getRecipeCategory().getUid() != VanillaRecipeCategoryUid.CRAFTING) {
return this.helper
.createUserErrorWithTooltip(I18n.format("jei.appliedenergistics2.requires_processing_mode"));
}

if (recipe.getRecipeOutput().isEmpty()) {
return this.helper.createUserErrorWithTooltip(I18n.format("jei.appliedenergistics2.no_output"));
}

return null;
}

@Override
protected boolean isCrafting() {
return false;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,101 +18,128 @@

package appeng.integration.modules.jei;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;

import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.item.crafting.ShapelessRecipe;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;

import mezz.jei.api.gui.IRecipeLayout;
import mezz.jei.api.gui.ingredient.IGuiIngredient;
import mezz.jei.api.recipe.transfer.IRecipeTransferError;
import mezz.jei.api.recipe.transfer.IRecipeTransferHandler;
import mezz.jei.api.recipe.transfer.IRecipeTransferHandlerHelper;

import appeng.container.slot.CraftingMatrixSlot;
import appeng.container.slot.FakeCraftingMatrixSlot;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.JEIRecipePacket;
import appeng.util.Platform;
import appeng.helpers.IContainerCraftingPacket;

class RecipeTransferHandler<T extends Container> implements IRecipeTransferHandler<T> {
abstract class RecipeTransferHandler<T extends Container & IContainerCraftingPacket>
implements IRecipeTransferHandler<T> {

private final Class<T> containerClass;
protected final IRecipeTransferHandlerHelper helper;

RecipeTransferHandler(Class<T> containerClass) {
RecipeTransferHandler(Class<T> containerClass, IRecipeTransferHandlerHelper helper) {
this.containerClass = containerClass;
this.helper = helper;
}

@Override
public Class<T> getContainerClass() {
public final Class<T> getContainerClass() {
return this.containerClass;
}

@Nullable
@Override
public IRecipeTransferError transferRecipe(T container, IRecipeLayout recipeLayout, PlayerEntity player,
boolean maxTransfer, boolean doTransfer) {
if (!doTransfer) {
return null;
public final IRecipeTransferError transferRecipe(T container, Object recipe, IRecipeLayout recipeLayout,
PlayerEntity player, boolean maxTransfer, boolean doTransfer) {
if (!(recipe instanceof IRecipe)) {
return this.helper.createInternalError();
}
final IRecipe<?> irecipe = (IRecipe<?>) recipe;
final ResourceLocation recipeId = irecipe.getId();

Map<Integer, ? extends IGuiIngredient<ItemStack>> ingredients = recipeLayout.getItemStacks()
.getGuiIngredients();

final CompoundNBT recipe = new CompoundNBT();
if (recipeId == null) {
return this.helper.createUserErrorWithTooltip(I18n.format("jei.appliedenergistics2.missing_id"));
}

int slotIndex = 0;
for (Map.Entry<Integer, ? extends IGuiIngredient<ItemStack>> ingredientEntry : ingredients.entrySet()) {
IGuiIngredient<ItemStack> ingredient = ingredientEntry.getValue();
if (!ingredient.isInput()) {
continue;
// Check that the recipe can actually be looked up via the manager, i.e. our
// facade recipes
// have an ID, but are never registered with the recipe manager.
boolean canSendReference = true;
if (!player.getEntityWorld().getRecipeManager().getRecipe(recipeId).isPresent()) {
// Validate that the recipe is a shapeless or shapedrecipe, since we can
// serialize those
if (!(recipe instanceof ShapedRecipe) && !(recipe instanceof ShapelessRecipe)) {
return this.helper.createUserErrorWithTooltip(I18n.format("jei.appliedenergistics2.missing_id"));
}
canSendReference = false;
}

for (final Slot slot : container.inventorySlots) {
if (slot instanceof CraftingMatrixSlot || slot instanceof FakeCraftingMatrixSlot) {
if (slot.getSlotIndex() == slotIndex) {
final ListNBT tags = new ListNBT();
final List<ItemStack> list = new ArrayList<>();
final ItemStack displayed = ingredient.getDisplayedIngredient();
if (!irecipe.canFit(3, 3)) {
return this.helper.createUserErrorWithTooltip(I18n.format("jei.appliedenergistics2.recipe_too_large"));
}

// prefer currently displayed item
if (displayed != null && !displayed.isEmpty()) {
list.add(displayed);
}
final IRecipeTransferError error = doTransferRecipe(container, irecipe, recipeLayout, player, maxTransfer);

// prefer pure crystals.
for (ItemStack stack : ingredient.getAllIngredients()) {
if (Platform.isRecipePrioritized(stack)) {
list.add(0, stack);
} else {
list.add(stack);
}
}
if (error != null) {
return error;
}

for (final ItemStack is : list) {
final CompoundNBT tag = new CompoundNBT();
is.write(tag);
tags.add(tag);
}
if (doTransfer) {
if (canSendReference) {
NetworkHandler.instance().sendToServer(new JEIRecipePacket(recipeId, isCrafting()));
} else {
// To avoid earlier problems of too large packets being sent that crashed the
// client,
// as a fallback when the recipe ID could not be resolved, we'll just send the
// displayed
// items.
NonNullList<Ingredient> flatIngredients = NonNullList.withSize(9, Ingredient.EMPTY);
ItemStack output = ItemStack.EMPTY;

// Determine the first JEI slot that has an actual input, we'll use this to
// offset the
// crafting grid target slot
int firstInputSlot = recipeLayout.getItemStacks().getGuiIngredients().entrySet().stream()
.filter(e -> e.getValue().isInput()).mapToInt(Map.Entry::getKey).min().orElse(0);

// Now map the actual ingredients into the output/input
for (Map.Entry<Integer, ? extends IGuiIngredient<ItemStack>> entry : recipeLayout.getItemStacks()
.getGuiIngredients().entrySet()) {
IGuiIngredient<ItemStack> item = entry.getValue();
if (item.getDisplayedIngredient() == null) {
continue;
}

recipe.put("#" + slot.getSlotIndex(), tags);
break;
int inputIndex = entry.getKey() - firstInputSlot;
if (item.isInput() && inputIndex < flatIngredients.size()) {
ItemStack displayedIngredient = item.getDisplayedIngredient();
if (displayedIngredient != null) {
flatIngredients.set(inputIndex, Ingredient.fromStacks(displayedIngredient));
}
} else if (!item.isInput() && output.isEmpty()) {
output = item.getDisplayedIngredient();
}
}
}

slotIndex++;
ShapedRecipe fallbackRecipe = new ShapedRecipe(recipeId, "", 3, 3, flatIngredients, output);
NetworkHandler.instance().sendToServer(new JEIRecipePacket(fallbackRecipe, isCrafting()));
}
}

NetworkHandler.instance().sendToServer(new JEIRecipePacket(recipe));

return null;
}

protected abstract IRecipeTransferError doTransferRecipe(T container, IRecipe<?> recipe, IRecipeLayout recipeLayout,
PlayerEntity player, boolean maxTransfer);

protected abstract boolean isCrafting();
}
Original file line number Diff line number Diff line change
Expand Up @@ -705,5 +705,9 @@
"waila.appliedenergistics2.P2POutput": "Linked (Output Side)",
"waila.appliedenergistics2.P2PUnlinked": "Unlinked",
"waila.appliedenergistics2.Showing": "Showing",
"waila.appliedenergistics2.Unlocked": "Unlocked"
"waila.appliedenergistics2.Unlocked": "Unlocked",
"jei.appliedenergistics2.missing_id": "Cannot identify recipe",
"jei.appliedenergistics2.recipe_too_large": "Recipe larger than 3x3",
"jei.appliedenergistics2.requires_processing_mode": "Requires processing mode",
"jei.appliedenergistics2.no_output": "Recipe has no output"
}