mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 13:42:59 +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:
		| @@ -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; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jonathan Coates
					Jonathan Coates