mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-14 04:00:30 +00:00
Refactor out our JEI plugin into reusable components
Pretty useless right now, but either useful for CC:R or our eventual multi-loader support.
This commit is contained in:
parent
f45614175a
commit
562f224c01
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.shared.integration;
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.shared.PocketUpgrades;
|
||||||
|
import dan200.computercraft.shared.TurtleUpgrades;
|
||||||
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
|
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
|
||||||
|
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities for recipe mod plugins (such as JEI).
|
||||||
|
*/
|
||||||
|
public final class RecipeModHelpers
|
||||||
|
{
|
||||||
|
static final List<ComputerFamily> MAIN_FAMILIES = Arrays.asList( ComputerFamily.NORMAL, ComputerFamily.ADVANCED );
|
||||||
|
|
||||||
|
private RecipeModHelpers()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if a recipe should be hidden. This should be used in conjunction with {@link UpgradeRecipeGenerator}
|
||||||
|
* to hide our upgrade crafting recipes.
|
||||||
|
*
|
||||||
|
* @param id The recipe ID.
|
||||||
|
* @return Whether it should be removed.
|
||||||
|
*/
|
||||||
|
public static boolean shouldRemoveRecipe( ResourceLocation id )
|
||||||
|
{
|
||||||
|
if( !id.getNamespace().equals( ComputerCraft.MOD_ID ) ) return false;
|
||||||
|
|
||||||
|
String path = id.getPath();
|
||||||
|
return path.startsWith( "turtle_normal/" ) || path.startsWith( "turtle_advanced/" )
|
||||||
|
|| path.startsWith( "pocket_normal/" ) || path.startsWith( "pocket_advanced/" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get additional ComputerCraft-related items which may not be visible in a creative tab. This includes upgraded
|
||||||
|
* turtle and pocket computers for each upgrade.
|
||||||
|
*
|
||||||
|
* @return The additional stacks to show.
|
||||||
|
*/
|
||||||
|
public static List<ItemStack> getExtraStacks()
|
||||||
|
{
|
||||||
|
List<ItemStack> upgradeItems = new ArrayList<>();
|
||||||
|
for( ComputerFamily family : MAIN_FAMILIES )
|
||||||
|
{
|
||||||
|
TurtleUpgrades.getUpgrades().forEach( upgrade -> {
|
||||||
|
upgradeItems.add( TurtleItemFactory.create( -1, null, -1, family, null, upgrade, 0, null ) );
|
||||||
|
} );
|
||||||
|
|
||||||
|
PocketUpgrades.getUpgrades().forEach( upgrade -> {
|
||||||
|
upgradeItems.add( PocketComputerItemFactory.create( -1, null, -1, family, upgrade ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
return upgradeItems;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,338 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||||
|
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||||
|
* Send enquiries to dratcliffe@gmail.com
|
||||||
|
*/
|
||||||
|
package dan200.computercraft.shared.integration;
|
||||||
|
|
||||||
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
import dan200.computercraft.api.IUpgradeBase;
|
||||||
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
|
import dan200.computercraft.shared.PocketUpgrades;
|
||||||
|
import dan200.computercraft.shared.TurtleUpgrades;
|
||||||
|
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||||
|
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||||
|
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
|
||||||
|
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
||||||
|
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.crafting.ICraftingRecipe;
|
||||||
|
import net.minecraft.item.crafting.Ingredient;
|
||||||
|
import net.minecraft.item.crafting.ShapedRecipe;
|
||||||
|
import net.minecraft.util.NonNullList;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static dan200.computercraft.shared.integration.RecipeModHelpers.MAIN_FAMILIES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides dynamic recipe and usage information for upgraded turtle and pocket computers. This is intended to be
|
||||||
|
* consumed by our recipe mod plugins (for example JEI).
|
||||||
|
*
|
||||||
|
* @param <T> The type the recipe mod uses for recipes.
|
||||||
|
* @see RecipeModHelpers
|
||||||
|
*/
|
||||||
|
public class UpgradeRecipeGenerator<T>
|
||||||
|
{
|
||||||
|
private static final ResourceLocation TURTLE_UPGRADE = new ResourceLocation( ComputerCraft.MOD_ID, "turtle_upgrade" );
|
||||||
|
private static final ResourceLocation POCKET_UPGRADE = new ResourceLocation( ComputerCraft.MOD_ID, "pocket_upgrade" );
|
||||||
|
|
||||||
|
private final Function<ICraftingRecipe, T> wrap;
|
||||||
|
|
||||||
|
private final Map<Item, List<UpgradeInfo>> upgradeItemLookup = new HashMap<>();
|
||||||
|
private final List<UpgradeInfo> pocketUpgrades = new ArrayList<>();
|
||||||
|
private final List<UpgradeInfo> turtleUpgrades = new ArrayList<>();
|
||||||
|
private boolean initialised = false;
|
||||||
|
|
||||||
|
public UpgradeRecipeGenerator( Function<ICraftingRecipe, T> wrap )
|
||||||
|
{
|
||||||
|
this.wrap = wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a cache of items which are used for turtle and pocket computer upgrades.
|
||||||
|
*/
|
||||||
|
private void setupCache()
|
||||||
|
{
|
||||||
|
if( initialised ) return;
|
||||||
|
initialised = true;
|
||||||
|
|
||||||
|
TurtleUpgrades.getUpgrades().forEach( upgrade -> {
|
||||||
|
net.minecraft.item.ItemStack stack = upgrade.getCraftingItem();
|
||||||
|
if( stack.isEmpty() ) return;
|
||||||
|
|
||||||
|
UpgradeInfo info = new UpgradeInfo( stack, upgrade );
|
||||||
|
upgradeItemLookup.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( info );
|
||||||
|
turtleUpgrades.add( info );
|
||||||
|
} );
|
||||||
|
|
||||||
|
PocketUpgrades.getUpgrades().forEach( upgrade -> {
|
||||||
|
ItemStack stack = upgrade.getCraftingItem();
|
||||||
|
if( stack.isEmpty() ) return;
|
||||||
|
|
||||||
|
UpgradeInfo info = new UpgradeInfo( stack, upgrade );
|
||||||
|
upgradeItemLookup.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( info );
|
||||||
|
pocketUpgrades.add( info );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this item is usable as a turtle or pocket computer upgrade.
|
||||||
|
*
|
||||||
|
* @param stack The stack to check.
|
||||||
|
* @return Whether the item is an upgrade.
|
||||||
|
*/
|
||||||
|
public boolean isUpgrade( ItemStack stack )
|
||||||
|
{
|
||||||
|
if( stack.isEmpty() ) return false;
|
||||||
|
|
||||||
|
setupCache();
|
||||||
|
List<UpgradeInfo> upgrades = upgradeItemLookup.get( stack.getItem() );
|
||||||
|
if( upgrades == null ) return false;
|
||||||
|
|
||||||
|
for( UpgradeInfo upgrade : upgrades )
|
||||||
|
{
|
||||||
|
ItemStack craftingStack = upgrade.stack;
|
||||||
|
if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && upgrade.upgrade.isItemSuitable( stack ) )
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all usages of the given stack.
|
||||||
|
*
|
||||||
|
* @param stack The stack to find usages of.
|
||||||
|
* @return All upgrade recipes which take the current stack as an input.
|
||||||
|
*/
|
||||||
|
public List<T> findRecipesWithInput( ItemStack stack )
|
||||||
|
{
|
||||||
|
setupCache();
|
||||||
|
|
||||||
|
if( stack.getItem() instanceof ItemTurtle )
|
||||||
|
{
|
||||||
|
ItemTurtle item = (ItemTurtle) stack.getItem();
|
||||||
|
|
||||||
|
// Suggest possible upgrades which can be applied to this turtle
|
||||||
|
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.LEFT );
|
||||||
|
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.RIGHT );
|
||||||
|
if( left != null && right != null ) return Collections.emptyList();
|
||||||
|
|
||||||
|
List<T> recipes = new ArrayList<>();
|
||||||
|
Ingredient ingredient = Ingredient.of( stack );
|
||||||
|
for( UpgradeInfo upgrade : turtleUpgrades )
|
||||||
|
{
|
||||||
|
// The turtle is facing towards us, so upgrades on the left are actually crafted on the right.
|
||||||
|
if( left == null )
|
||||||
|
{
|
||||||
|
recipes.add( turtle( ingredient, upgrade.ingredient, turtleWith( stack, upgrade.turtle, right ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( right == null )
|
||||||
|
{
|
||||||
|
recipes.add( turtle( upgrade.ingredient, ingredient, turtleWith( stack, left, upgrade.turtle ) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList( recipes );
|
||||||
|
}
|
||||||
|
else if( stack.getItem() instanceof ItemPocketComputer )
|
||||||
|
{
|
||||||
|
// Suggest possible upgrades which can be applied to this turtle
|
||||||
|
IPocketUpgrade back = ItemPocketComputer.getUpgrade( stack );
|
||||||
|
if( back != null ) return Collections.emptyList();
|
||||||
|
|
||||||
|
List<T> recipes = new ArrayList<>();
|
||||||
|
Ingredient ingredient = Ingredient.of( stack );
|
||||||
|
for( UpgradeInfo upgrade : pocketUpgrades )
|
||||||
|
{
|
||||||
|
recipes.add( pocket( upgrade.ingredient, ingredient, pocketWith( stack, upgrade.pocket ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList( recipes );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If this item is usable as an upgrade, find all possible recipes.
|
||||||
|
List<UpgradeInfo> upgrades = upgradeItemLookup.get( stack.getItem() );
|
||||||
|
if( upgrades == null ) return Collections.emptyList();
|
||||||
|
|
||||||
|
List<T> recipes = null;
|
||||||
|
boolean multiple = false;
|
||||||
|
for( UpgradeInfo upgrade : upgrades )
|
||||||
|
{
|
||||||
|
ItemStack craftingStack = upgrade.stack;
|
||||||
|
if( craftingStack.isEmpty() || craftingStack.getItem() != stack.getItem() || !upgrade.upgrade.isItemSuitable( stack ) )
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( recipes == null )
|
||||||
|
{
|
||||||
|
recipes = upgrade.getRecipes();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( !multiple )
|
||||||
|
{
|
||||||
|
multiple = true;
|
||||||
|
recipes = new ArrayList<>( recipes );
|
||||||
|
}
|
||||||
|
recipes.addAll( upgrade.getRecipes() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return recipes == null ? Collections.emptyList() : Collections.unmodifiableList( recipes );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all recipes for the given stack.
|
||||||
|
*
|
||||||
|
* @param stack The stack to find recipes of.
|
||||||
|
* @return All upgrade recipes which produce the stack as an output.
|
||||||
|
*/
|
||||||
|
public List<T> findRecipesWithOutput( ItemStack stack )
|
||||||
|
{
|
||||||
|
// Find which upgrade this item currently has, and so how we could build it.
|
||||||
|
if( stack.getItem() instanceof ItemTurtle )
|
||||||
|
{
|
||||||
|
ItemTurtle item = (ItemTurtle) stack.getItem();
|
||||||
|
List<T> recipes = new ArrayList<>( 0 );
|
||||||
|
|
||||||
|
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.LEFT );
|
||||||
|
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.RIGHT );
|
||||||
|
|
||||||
|
// The turtle is facing towards us, so upgrades on the left are actually crafted on the right.
|
||||||
|
if( left != null )
|
||||||
|
{
|
||||||
|
recipes.add( turtle(
|
||||||
|
Ingredient.of( turtleWith( stack, null, right ) ),
|
||||||
|
Ingredient.of( left.getCraftingItem() ),
|
||||||
|
stack
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( right != null )
|
||||||
|
{
|
||||||
|
recipes.add( turtle(
|
||||||
|
Ingredient.of( right.getCraftingItem() ),
|
||||||
|
Ingredient.of( turtleWith( stack, left, null ) ),
|
||||||
|
stack
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList( recipes );
|
||||||
|
}
|
||||||
|
else if( stack.getItem() instanceof ItemPocketComputer )
|
||||||
|
{
|
||||||
|
List<T> recipes = new ArrayList<>( 0 );
|
||||||
|
|
||||||
|
IPocketUpgrade back = ItemPocketComputer.getUpgrade( stack );
|
||||||
|
if( back != null )
|
||||||
|
{
|
||||||
|
recipes.add( pocket( Ingredient.of( back.getCraftingItem() ), Ingredient.of( pocketWith( stack, null ) ), stack ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableList( recipes );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ItemStack turtleWith( ItemStack stack, @Nullable ITurtleUpgrade left, @Nullable ITurtleUpgrade right )
|
||||||
|
{
|
||||||
|
ItemTurtle item = (ItemTurtle) stack.getItem();
|
||||||
|
return TurtleItemFactory.create(
|
||||||
|
item.getComputerID( stack ), item.getLabel( stack ), item.getColour( stack ), item.getFamily(),
|
||||||
|
left, right, item.getFuelLevel( stack ), item.getOverlay( stack )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ItemStack pocketWith( ItemStack stack, @Nullable IPocketUpgrade back )
|
||||||
|
{
|
||||||
|
ItemPocketComputer item = (ItemPocketComputer) stack.getItem();
|
||||||
|
return PocketComputerItemFactory.create(
|
||||||
|
item.getComputerID( stack ), item.getLabel( stack ), item.getColour( stack ), item.getFamily(),
|
||||||
|
back
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private T pocket( Ingredient upgrade, Ingredient pocketComputer, ItemStack result )
|
||||||
|
{
|
||||||
|
return wrap.apply( new ShapedRecipe( POCKET_UPGRADE, "", 1, 2, NonNullList.of( Ingredient.EMPTY, upgrade, pocketComputer ), result ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private T turtle( Ingredient left, Ingredient right, ItemStack result )
|
||||||
|
{
|
||||||
|
return wrap.apply( new ShapedRecipe( TURTLE_UPGRADE, "", 2, 1, NonNullList.of( Ingredient.EMPTY, left, right ), result ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private class UpgradeInfo
|
||||||
|
{
|
||||||
|
final ItemStack stack;
|
||||||
|
final Ingredient ingredient;
|
||||||
|
final @Nullable ITurtleUpgrade turtle;
|
||||||
|
final @Nullable IPocketUpgrade pocket;
|
||||||
|
final IUpgradeBase upgrade;
|
||||||
|
private @Nullable ArrayList<T> recipes;
|
||||||
|
|
||||||
|
UpgradeInfo( ItemStack stack, ITurtleUpgrade turtle )
|
||||||
|
{
|
||||||
|
this.stack = stack;
|
||||||
|
ingredient = Ingredient.of( stack );
|
||||||
|
upgrade = this.turtle = turtle;
|
||||||
|
pocket = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpgradeInfo( ItemStack stack, IPocketUpgrade pocket )
|
||||||
|
{
|
||||||
|
this.stack = stack;
|
||||||
|
ingredient = Ingredient.of( stack );
|
||||||
|
turtle = null;
|
||||||
|
upgrade = this.pocket = pocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<T> getRecipes()
|
||||||
|
{
|
||||||
|
ArrayList<T> recipes = this.recipes;
|
||||||
|
if( recipes != null ) return recipes;
|
||||||
|
|
||||||
|
recipes = this.recipes = new ArrayList<>( 4 );
|
||||||
|
for( ComputerFamily family : MAIN_FAMILIES )
|
||||||
|
{
|
||||||
|
if( turtle != null )
|
||||||
|
{
|
||||||
|
recipes.add( turtle(
|
||||||
|
ingredient, // Right upgrade, recipe on left
|
||||||
|
Ingredient.of( TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null ) ),
|
||||||
|
TurtleItemFactory.create( -1, null, -1, family, null, turtle, 0, null )
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pocket != null )
|
||||||
|
{
|
||||||
|
recipes.add( pocket(
|
||||||
|
ingredient,
|
||||||
|
Ingredient.of( PocketComputerItemFactory.create( -1, null, -1, family, null ) ),
|
||||||
|
PocketComputerItemFactory.create( -1, null, -1, family, pocket )
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recipes.trimToSize();
|
||||||
|
return recipes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,15 +9,11 @@ import dan200.computercraft.ComputerCraft;
|
|||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
import dan200.computercraft.api.turtle.TurtleSide;
|
||||||
import dan200.computercraft.shared.PocketUpgrades;
|
|
||||||
import dan200.computercraft.shared.Registry;
|
import dan200.computercraft.shared.Registry;
|
||||||
import dan200.computercraft.shared.TurtleUpgrades;
|
import dan200.computercraft.shared.integration.RecipeModHelpers;
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
|
||||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||||
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
|
|
||||||
import dan200.computercraft.shared.turtle.items.ITurtleItem;
|
import dan200.computercraft.shared.turtle.items.ITurtleItem;
|
||||||
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
|
|
||||||
import mezz.jei.api.IModPlugin;
|
import mezz.jei.api.IModPlugin;
|
||||||
import mezz.jei.api.JeiPlugin;
|
import mezz.jei.api.JeiPlugin;
|
||||||
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
|
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
|
||||||
@ -34,11 +30,8 @@ import net.minecraft.item.crafting.IRecipe;
|
|||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static dan200.computercraft.shared.integration.jei.RecipeResolver.MAIN_FAMILIES;
|
|
||||||
|
|
||||||
@JeiPlugin
|
@JeiPlugin
|
||||||
public class JEIComputerCraft implements IModPlugin
|
public class JEIComputerCraft implements IModPlugin
|
||||||
{
|
{
|
||||||
@ -73,22 +66,12 @@ public class JEIComputerCraft implements IModPlugin
|
|||||||
IRecipeManager registry = runtime.getRecipeManager();
|
IRecipeManager registry = runtime.getRecipeManager();
|
||||||
|
|
||||||
// Register all turtles/pocket computers (not just vanilla upgrades) as upgrades on JEI.
|
// Register all turtles/pocket computers (not just vanilla upgrades) as upgrades on JEI.
|
||||||
List<ItemStack> upgradeItems = new ArrayList<>();
|
List<ItemStack> upgradeItems = RecipeModHelpers.getExtraStacks();
|
||||||
for( ComputerFamily family : MAIN_FAMILIES )
|
if( !upgradeItems.isEmpty() )
|
||||||
{
|
{
|
||||||
TurtleUpgrades.getUpgrades()
|
runtime.getIngredientManager().addIngredientsAtRuntime( VanillaTypes.ITEM, upgradeItems );
|
||||||
.filter( x -> TurtleUpgrades.suitableForFamily( family, x ) )
|
|
||||||
.map( x -> TurtleItemFactory.create( -1, null, -1, family, null, x, 0, null ) )
|
|
||||||
.forEach( upgradeItems::add );
|
|
||||||
|
|
||||||
for( IPocketUpgrade upgrade : PocketUpgrades.getUpgrades() )
|
|
||||||
{
|
|
||||||
upgradeItems.add( PocketComputerItemFactory.create( -1, null, -1, family, upgrade ) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime.getIngredientManager().addIngredientsAtRuntime( VanillaTypes.ITEM, upgradeItems );
|
|
||||||
|
|
||||||
// Hide all upgrade recipes
|
// Hide all upgrade recipes
|
||||||
IRecipeCategory<?> category = registry.getRecipeCategory( VanillaRecipeCategoryUid.CRAFTING );
|
IRecipeCategory<?> category = registry.getRecipeCategory( VanillaRecipeCategoryUid.CRAFTING );
|
||||||
if( category != null )
|
if( category != null )
|
||||||
@ -96,12 +79,7 @@ public class JEIComputerCraft implements IModPlugin
|
|||||||
for( Object wrapper : registry.getRecipes( category ) )
|
for( Object wrapper : registry.getRecipes( category ) )
|
||||||
{
|
{
|
||||||
if( !(wrapper instanceof IRecipe) ) continue;
|
if( !(wrapper instanceof IRecipe) ) continue;
|
||||||
ResourceLocation id = ((IRecipe<?>) wrapper).getId();
|
if( RecipeModHelpers.shouldRemoveRecipe( ((IRecipe<?>) wrapper).getId() ) )
|
||||||
if( !id.getNamespace().equals( ComputerCraft.MOD_ID ) ) continue;
|
|
||||||
|
|
||||||
String path = id.getPath();
|
|
||||||
if( path.startsWith( "turtle_normal/" ) || path.startsWith( "turtle_advanced/" )
|
|
||||||
|| path.startsWith( "pocket_normal/" ) || path.startsWith( "pocket_advanced/" ) )
|
|
||||||
{
|
{
|
||||||
registry.hideRecipe( wrapper, VanillaRecipeCategoryUid.CRAFTING );
|
registry.hideRecipe( wrapper, VanillaRecipeCategoryUid.CRAFTING );
|
||||||
}
|
}
|
||||||
|
@ -5,110 +5,41 @@
|
|||||||
*/
|
*/
|
||||||
package dan200.computercraft.shared.integration.jei;
|
package dan200.computercraft.shared.integration.jei;
|
||||||
|
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.shared.integration.UpgradeRecipeGenerator;
|
||||||
import dan200.computercraft.api.IUpgradeBase;
|
|
||||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
|
||||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
|
||||||
import dan200.computercraft.api.turtle.TurtleSide;
|
|
||||||
import dan200.computercraft.shared.PocketUpgrades;
|
|
||||||
import dan200.computercraft.shared.TurtleUpgrades;
|
|
||||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
|
||||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||||
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
|
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
||||||
import dan200.computercraft.shared.turtle.items.ITurtleItem;
|
|
||||||
import dan200.computercraft.shared.turtle.items.TurtleItemFactory;
|
|
||||||
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
|
import mezz.jei.api.constants.VanillaRecipeCategoryUid;
|
||||||
import mezz.jei.api.recipe.IFocus;
|
import mezz.jei.api.recipe.IFocus;
|
||||||
import mezz.jei.api.recipe.advanced.IRecipeManagerPlugin;
|
import mezz.jei.api.recipe.advanced.IRecipeManagerPlugin;
|
||||||
import mezz.jei.api.recipe.category.IRecipeCategory;
|
import mezz.jei.api.recipe.category.IRecipeCategory;
|
||||||
import net.minecraft.item.Item;
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.crafting.IRecipeSerializer;
|
import net.minecraft.item.crafting.ICraftingRecipe;
|
||||||
import net.minecraft.item.crafting.Ingredient;
|
|
||||||
import net.minecraft.item.crafting.ShapedRecipe;
|
|
||||||
import net.minecraft.util.NonNullList;
|
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.util.*;
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import static net.minecraft.item.crafting.Ingredient.of;
|
|
||||||
import static net.minecraft.util.NonNullList.of;
|
|
||||||
|
|
||||||
class RecipeResolver implements IRecipeManagerPlugin
|
class RecipeResolver implements IRecipeManagerPlugin
|
||||||
{
|
{
|
||||||
static final ComputerFamily[] MAIN_FAMILIES = new ComputerFamily[] { ComputerFamily.NORMAL, ComputerFamily.ADVANCED };
|
private final UpgradeRecipeGenerator<ICraftingRecipe> resolver = new UpgradeRecipeGenerator<>( x -> x );
|
||||||
|
|
||||||
private final Map<Item, List<UpgradeInfo>> upgradeItemLookup = new HashMap<>();
|
|
||||||
private final List<UpgradeInfo> pocketUpgrades = new ArrayList<>();
|
|
||||||
private final List<UpgradeInfo> turtleUpgrades = new ArrayList<>();
|
|
||||||
private boolean initialised = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a cache of items which are used for turtle and pocket computer upgrades.
|
|
||||||
*/
|
|
||||||
private void setupCache()
|
|
||||||
{
|
|
||||||
if( initialised ) return;
|
|
||||||
initialised = true;
|
|
||||||
|
|
||||||
TurtleUpgrades.getUpgrades().forEach( upgrade -> {
|
|
||||||
ItemStack stack = upgrade.getCraftingItem();
|
|
||||||
if( stack.isEmpty() ) return;
|
|
||||||
|
|
||||||
UpgradeInfo info = new UpgradeInfo( stack, upgrade );
|
|
||||||
upgradeItemLookup.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( info );
|
|
||||||
turtleUpgrades.add( info );
|
|
||||||
} );
|
|
||||||
|
|
||||||
for( IPocketUpgrade upgrade : PocketUpgrades.getUpgrades() )
|
|
||||||
{
|
|
||||||
ItemStack stack = upgrade.getCraftingItem();
|
|
||||||
if( stack.isEmpty() ) continue;
|
|
||||||
|
|
||||||
UpgradeInfo info = new UpgradeInfo( stack, upgrade );
|
|
||||||
upgradeItemLookup.computeIfAbsent( stack.getItem(), k -> new ArrayList<>( 1 ) ).add( info );
|
|
||||||
pocketUpgrades.add( info );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasUpgrade( @Nonnull ItemStack stack )
|
|
||||||
{
|
|
||||||
if( stack.isEmpty() ) return false;
|
|
||||||
|
|
||||||
setupCache();
|
|
||||||
List<UpgradeInfo> upgrades = upgradeItemLookup.get( stack.getItem() );
|
|
||||||
if( upgrades == null ) return false;
|
|
||||||
|
|
||||||
for( UpgradeInfo upgrade : upgrades )
|
|
||||||
{
|
|
||||||
ItemStack craftingStack = upgrade.stack;
|
|
||||||
if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && upgrade.upgrade.isItemSuitable( stack ) )
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public <V> List<ResourceLocation> getRecipeCategoryUids( @Nonnull IFocus<V> focus )
|
public <V> List<ResourceLocation> getRecipeCategoryUids( IFocus<V> focus )
|
||||||
{
|
{
|
||||||
V value = focus.getValue();
|
Object value = focus.getValue();
|
||||||
if( !(value instanceof ItemStack) ) return Collections.emptyList();
|
if( !(value instanceof ItemStack) ) return Collections.emptyList();
|
||||||
|
|
||||||
ItemStack stack = (ItemStack) value;
|
ItemStack stack = (ItemStack) value;
|
||||||
switch( focus.getMode() )
|
switch( focus.getMode() )
|
||||||
{
|
{
|
||||||
case INPUT:
|
case INPUT:
|
||||||
return stack.getItem() instanceof ITurtleItem || stack.getItem() instanceof ItemPocketComputer ||
|
return stack.getItem() instanceof ItemTurtle || stack.getItem() instanceof ItemPocketComputer || resolver.isUpgrade( stack )
|
||||||
hasUpgrade( stack )
|
|
||||||
? Collections.singletonList( VanillaRecipeCategoryUid.CRAFTING )
|
? Collections.singletonList( VanillaRecipeCategoryUid.CRAFTING )
|
||||||
: Collections.emptyList();
|
: Collections.emptyList();
|
||||||
case OUTPUT:
|
case OUTPUT:
|
||||||
return stack.getItem() instanceof ITurtleItem || stack.getItem() instanceof ItemPocketComputer
|
return stack.getItem() instanceof ItemTurtle || stack.getItem() instanceof ItemPocketComputer
|
||||||
? Collections.singletonList( VanillaRecipeCategoryUid.CRAFTING )
|
? Collections.singletonList( VanillaRecipeCategoryUid.CRAFTING )
|
||||||
: Collections.emptyList();
|
: Collections.emptyList();
|
||||||
default:
|
default:
|
||||||
@ -118,20 +49,19 @@ class RecipeResolver implements IRecipeManagerPlugin
|
|||||||
|
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public <T, V> List<T> getRecipes( @Nonnull IRecipeCategory<T> recipeCategory, @Nonnull IFocus<V> focus )
|
public <T, V> List<T> getRecipes( @Nonnull IRecipeCategory<T> recipeCategory, IFocus<V> focus )
|
||||||
{
|
{
|
||||||
if( !(focus.getValue() instanceof ItemStack) || !recipeCategory.getUid().equals( VanillaRecipeCategoryUid.CRAFTING ) )
|
if( !(focus.getValue() instanceof ItemStack) || !recipeCategory.getUid().equals( VanillaRecipeCategoryUid.CRAFTING ) )
|
||||||
{
|
{
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemStack stack = (ItemStack) focus.getValue();
|
|
||||||
switch( focus.getMode() )
|
switch( focus.getMode() )
|
||||||
{
|
{
|
||||||
case INPUT:
|
case INPUT:
|
||||||
return cast( findRecipesWithInput( stack ) );
|
return cast( resolver.findRecipesWithInput( (ItemStack) focus.getValue() ) );
|
||||||
case OUTPUT:
|
case OUTPUT:
|
||||||
return cast( findRecipesWithOutput( stack ) );
|
return cast( resolver.findRecipesWithOutput( (ItemStack) focus.getValue() ) );
|
||||||
default:
|
default:
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
@ -144,241 +74,10 @@ class RecipeResolver implements IRecipeManagerPlugin
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private List<Shaped> findRecipesWithInput( @Nonnull ItemStack stack )
|
|
||||||
{
|
|
||||||
setupCache();
|
|
||||||
|
|
||||||
if( stack.getItem() instanceof ITurtleItem )
|
|
||||||
{
|
|
||||||
// Suggest possible upgrades which can be applied to this turtle
|
|
||||||
ITurtleItem item = (ITurtleItem) stack.getItem();
|
|
||||||
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.LEFT );
|
|
||||||
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.RIGHT );
|
|
||||||
if( left != null && right != null ) return Collections.emptyList();
|
|
||||||
|
|
||||||
List<Shaped> recipes = new ArrayList<>();
|
|
||||||
Ingredient ingredient = of( stack );
|
|
||||||
for( UpgradeInfo upgrade : turtleUpgrades )
|
|
||||||
{
|
|
||||||
// The turtle is facing towards us, so upgrades on the left are actually crafted on the right.
|
|
||||||
if( left == null )
|
|
||||||
{
|
|
||||||
recipes.add( horizontal( of( Ingredient.EMPTY, ingredient, upgrade.ingredient ), turtleWith( stack, upgrade.turtle, right ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( right == null )
|
|
||||||
{
|
|
||||||
recipes.add( horizontal( of( Ingredient.EMPTY, upgrade.ingredient, ingredient ), turtleWith( stack, left, upgrade.turtle ) ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cast( recipes );
|
|
||||||
}
|
|
||||||
else if( stack.getItem() instanceof ItemPocketComputer )
|
|
||||||
{
|
|
||||||
// Suggest possible upgrades which can be applied to this turtle
|
|
||||||
IPocketUpgrade back = ItemPocketComputer.getUpgrade( stack );
|
|
||||||
if( back != null ) return Collections.emptyList();
|
|
||||||
|
|
||||||
List<Shaped> recipes = new ArrayList<>();
|
|
||||||
Ingredient ingredient = of( stack );
|
|
||||||
for( UpgradeInfo upgrade : pocketUpgrades )
|
|
||||||
{
|
|
||||||
recipes.add( vertical( of( Ingredient.EMPTY, ingredient, upgrade.ingredient ), pocketWith( stack, upgrade.pocket ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return recipes;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
List<UpgradeInfo> upgrades = upgradeItemLookup.get( stack.getItem() );
|
|
||||||
if( upgrades == null ) return Collections.emptyList();
|
|
||||||
|
|
||||||
List<Shaped> recipes = null;
|
|
||||||
boolean multiple = false;
|
|
||||||
for( UpgradeInfo upgrade : upgrades )
|
|
||||||
{
|
|
||||||
ItemStack craftingStack = upgrade.stack;
|
|
||||||
if( craftingStack.isEmpty() || craftingStack.getItem() != stack.getItem() || !upgrade.upgrade.isItemSuitable( stack ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( recipes == null )
|
|
||||||
{
|
|
||||||
recipes = upgrade.getRecipes();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( !multiple )
|
|
||||||
{
|
|
||||||
multiple = true;
|
|
||||||
recipes = new ArrayList<>( recipes );
|
|
||||||
}
|
|
||||||
recipes.addAll( upgrade.getRecipes() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return recipes == null ? Collections.emptyList() : recipes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
private static List<Shaped> findRecipesWithOutput( @Nonnull ItemStack stack )
|
|
||||||
{
|
|
||||||
// Find which upgrade this item currently has, an so how we could build it.
|
|
||||||
if( stack.getItem() instanceof ITurtleItem )
|
|
||||||
{
|
|
||||||
ITurtleItem item = (ITurtleItem) stack.getItem();
|
|
||||||
List<Shaped> recipes = new ArrayList<>( 0 );
|
|
||||||
|
|
||||||
ITurtleUpgrade left = item.getUpgrade( stack, TurtleSide.LEFT );
|
|
||||||
ITurtleUpgrade right = item.getUpgrade( stack, TurtleSide.RIGHT );
|
|
||||||
|
|
||||||
// The turtle is facing towards us, so upgrades on the left are actually crafted on the right.
|
|
||||||
if( left != null )
|
|
||||||
{
|
|
||||||
recipes.add( horizontal(
|
|
||||||
of( Ingredient.EMPTY, of( turtleWith( stack, null, right ) ), of( left.getCraftingItem() ) ),
|
|
||||||
stack
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( right != null )
|
|
||||||
{
|
|
||||||
recipes.add( horizontal(
|
|
||||||
of( Ingredient.EMPTY, of( right.getCraftingItem() ), of( turtleWith( stack, left, null ) ) ),
|
|
||||||
stack
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return cast( recipes );
|
|
||||||
}
|
|
||||||
else if( stack.getItem() instanceof ItemPocketComputer )
|
|
||||||
{
|
|
||||||
List<Shaped> recipes = new ArrayList<>( 0 );
|
|
||||||
|
|
||||||
IPocketUpgrade back = ItemPocketComputer.getUpgrade( stack );
|
|
||||||
if( back != null )
|
|
||||||
{
|
|
||||||
recipes.add( vertical(
|
|
||||||
of( Ingredient.EMPTY, of( back.getCraftingItem() ), of( pocketWith( stack, null ) ) ),
|
|
||||||
stack
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return cast( recipes );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||||
private static <T, U> List<T> cast( List<U> from )
|
private static <T, U> List<T> cast( List<U> from )
|
||||||
{
|
{
|
||||||
return (List) from;
|
return (List) from;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ItemStack turtleWith( ItemStack stack, ITurtleUpgrade left, ITurtleUpgrade right )
|
|
||||||
{
|
|
||||||
ITurtleItem item = (ITurtleItem) stack.getItem();
|
|
||||||
return TurtleItemFactory.create(
|
|
||||||
item.getComputerID( stack ), item.getLabel( stack ), item.getColour( stack ), item.getFamily(),
|
|
||||||
left, right, item.getFuelLevel( stack ), item.getOverlay( stack )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ItemStack pocketWith( ItemStack stack, IPocketUpgrade back )
|
|
||||||
{
|
|
||||||
ItemPocketComputer item = (ItemPocketComputer) stack.getItem();
|
|
||||||
return PocketComputerItemFactory.create(
|
|
||||||
item.getComputerID( stack ), item.getLabel( stack ), item.getColour( stack ), item.getFamily(),
|
|
||||||
back
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Shaped vertical( NonNullList<Ingredient> input, ItemStack result )
|
|
||||||
{
|
|
||||||
return new Shaped( 1, input.size(), input, result );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Shaped horizontal( NonNullList<Ingredient> input, ItemStack result )
|
|
||||||
{
|
|
||||||
return new Shaped( input.size(), 1, input, result );
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class Shaped extends ShapedRecipe
|
|
||||||
{
|
|
||||||
private static final ResourceLocation ID = new ResourceLocation( ComputerCraft.MOD_ID, "impostor" );
|
|
||||||
|
|
||||||
Shaped( int width, int height, NonNullList<Ingredient> input, ItemStack output )
|
|
||||||
{
|
|
||||||
super( ID, null, width, height, input, output );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public IRecipeSerializer<?> getSerializer()
|
|
||||||
{
|
|
||||||
throw new IllegalStateException( "Should not serialise the JEI recipe" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class UpgradeInfo
|
|
||||||
{
|
|
||||||
final ItemStack stack;
|
|
||||||
final Ingredient ingredient;
|
|
||||||
final ITurtleUpgrade turtle;
|
|
||||||
final IPocketUpgrade pocket;
|
|
||||||
final IUpgradeBase upgrade;
|
|
||||||
ArrayList<Shaped> recipes;
|
|
||||||
|
|
||||||
UpgradeInfo( ItemStack stack, ITurtleUpgrade turtle )
|
|
||||||
{
|
|
||||||
this.stack = stack;
|
|
||||||
ingredient = of( stack );
|
|
||||||
upgrade = this.turtle = turtle;
|
|
||||||
pocket = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpgradeInfo( ItemStack stack, IPocketUpgrade pocket )
|
|
||||||
{
|
|
||||||
this.stack = stack;
|
|
||||||
ingredient = of( stack );
|
|
||||||
turtle = null;
|
|
||||||
upgrade = this.pocket = pocket;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Shaped> getRecipes()
|
|
||||||
{
|
|
||||||
ArrayList<Shaped> recipes = this.recipes;
|
|
||||||
if( recipes != null ) return recipes;
|
|
||||||
|
|
||||||
recipes = this.recipes = new ArrayList<>( 4 );
|
|
||||||
for( ComputerFamily family : MAIN_FAMILIES )
|
|
||||||
{
|
|
||||||
if( turtle != null && TurtleUpgrades.suitableForFamily( family, turtle ) )
|
|
||||||
{
|
|
||||||
recipes.add( horizontal(
|
|
||||||
of( Ingredient.EMPTY, ingredient, of( TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null ) ) ),
|
|
||||||
TurtleItemFactory.create( -1, null, -1, family, null, turtle, 0, null )
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( pocket != null )
|
|
||||||
{
|
|
||||||
recipes.add( vertical(
|
|
||||||
of( Ingredient.EMPTY, ingredient, of( PocketComputerItemFactory.create( -1, null, -1, family, null ) ) ),
|
|
||||||
PocketComputerItemFactory.create( -1, null, -1, family, pocket )
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
recipes.trimToSize();
|
|
||||||
return recipes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user