diff --git a/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java b/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java index febdfe5ee8..50aba8ecc5 100644 --- a/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java +++ b/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java @@ -16,4 +16,5 @@ public interface IComputerItem int getComputerID( @Nonnull ItemStack stack ); String getLabel( @Nonnull ItemStack stack ); ComputerFamily getFamily( @Nonnull ItemStack stack ); + ItemStack withFamily(@Nonnull ItemStack stack, @Nonnull ComputerFamily family); } diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java index a8c6cbe09b..4d43c39e10 100644 --- a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java @@ -27,7 +27,7 @@ public class ItemComputer extends ItemComputerBase { public static int HIGHEST_DAMAGE_VALUE_ID = 16382; - + public ItemComputer( Block block ) { super( block ); @@ -87,7 +87,7 @@ public boolean placeBlockAt( @Nonnull ItemStack stack, @Nonnull EntityPlayer pla TileEntity tile = world.getTileEntity( pos ); if( tile != null && tile instanceof IComputerTile ) { - IComputerTile computer = (IComputerTile)tile; + IComputerTile computer = (IComputerTile) tile; setupComputerAfterPlacement( stack, computer ); } return true; @@ -146,10 +146,16 @@ public int getComputerID( @Nonnull ItemStack stack ) else { int damage = stack.getItemDamage() & 0x3fff; - return ( damage - 1 ); + return (damage - 1); } } + @Override + public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) + { + return ComputerItemFactory.create( getComputerID( stack ), getLabel( stack ), family ); + } + @Override public ComputerFamily getFamily( int damage ) { diff --git a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java new file mode 100644 index 0000000000..5d38379600 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java @@ -0,0 +1,66 @@ +package dan200.computercraft.shared.computer.recipe; + +import dan200.computercraft.shared.computer.items.IComputerItem; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.item.crafting.ShapedRecipes; +import net.minecraft.world.World; +import net.minecraftforge.common.crafting.CraftingHelper; + +import javax.annotation.Nonnull; + +/** + * Represents a recipe which converts a computer from one form into another. + */ +public abstract class ComputerConvertRecipe extends ShapedRecipes +{ + public ComputerConvertRecipe( String group, @Nonnull CraftingHelper.ShapedPrimer primer, @Nonnull ItemStack result ) + { + super( group, primer.width, primer.height, primer.input, result ); + } + + @Nonnull + protected abstract ItemStack convert( @Nonnull ItemStack stack ); + + @Override + public boolean matches( @Nonnull InventoryCrafting inventory, @Nonnull World world ) + { + // See if we match the recipe, and extract the input computercraft ID + ItemStack computerStack = null; + for( int y = 0; y < 3; ++y ) + { + for( int x = 0; x < 3; ++x ) + { + ItemStack stack = inventory.getStackInRowAndColumn( x, y ); + Ingredient target = getIngredients().get( x + y * 3 ); + + // First verify we match the ingredient + if( !target.apply( stack ) ) return false; + + // We want to ensure we have a computer item somewhere in the recipe + if( stack.getItem() instanceof IComputerItem ) computerStack = stack; + } + } + + return computerStack != null; + } + + @Nonnull + @Override + public ItemStack getCraftingResult( @Nonnull InventoryCrafting inventory ) + { + for( int y = 0; y < 3; ++y ) + { + for( int x = 0; x < 3; ++x ) + { + ItemStack item = inventory.getStackInRowAndColumn( x, y ); + + // If we're a computer, convert! + if( item.getItem() instanceof IComputerItem ) return convert( item ); + } + } + + return ItemStack.EMPTY; + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java new file mode 100644 index 0000000000..3232092292 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java @@ -0,0 +1,47 @@ +package dan200.computercraft.shared.computer.recipe; + +import com.google.gson.JsonObject; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.items.IComputerItem; +import dan200.computercraft.shared.util.RecipeUtil; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.util.JsonUtils; +import net.minecraftforge.common.crafting.CraftingHelper; +import net.minecraftforge.common.crafting.IRecipeFactory; +import net.minecraftforge.common.crafting.JsonContext; + +import javax.annotation.Nonnull; + +public class ComputerFamilyRecipe extends ComputerConvertRecipe +{ + private final ComputerFamily family; + + public ComputerFamilyRecipe( String group, @Nonnull CraftingHelper.ShapedPrimer primer, @Nonnull ItemStack result, ComputerFamily family ) + { + super( group, primer, result ); + this.family = family; + } + + @Nonnull + @Override + protected ItemStack convert( @Nonnull ItemStack stack ) + { + return ((IComputerItem) stack.getItem()).withFamily( stack, family ); + } + + public static class Factory implements IRecipeFactory + { + @Override + public IRecipe parse( JsonContext context, JsonObject json ) + { + String group = JsonUtils.getString( json, "group", "" ); + ComputerFamily family = RecipeUtil.getFamily( json, "family" ); + + CraftingHelper.ShapedPrimer primer = RecipeUtil.getPrimer( context, json ); + ItemStack result = deserializeItem( JsonUtils.getJsonObject( json, "result" ), false ); + + return new ComputerFamilyRecipe( group, primer, result, family ); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerIngredient.java b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerIngredient.java new file mode 100644 index 0000000000..e044fc5523 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerIngredient.java @@ -0,0 +1,66 @@ +package dan200.computercraft.shared.computer.recipe; + +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.computer.items.IComputerItem; +import dan200.computercraft.shared.util.RecipeUtil; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.JsonUtils; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.crafting.IIngredientFactory; +import net.minecraftforge.common.crafting.JsonContext; +import net.minecraftforge.fml.common.registry.ForgeRegistries; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +/** + * Represents an ingredient which requires an item to have a specific + * computer family. This allows us to have operations which only work + * on normal or + */ +public class ComputerIngredient extends Ingredient +{ + private final IComputerItem item; + private final ComputerFamily family; + + public ComputerIngredient( T item, int data, ComputerFamily family ) + { + super( new ItemStack( item, 1, data ) ); + + this.item = item; + this.family = family; + } + + @Override + public boolean apply( @Nullable ItemStack stack ) + { + return stack != null && stack.getItem() == item && item.getFamily( stack ) == family; + } + + public static class Factory implements IIngredientFactory + { + @Nonnull + @Override + public Ingredient parse( JsonContext context, JsonObject json ) + { + String itemName = context.appendModId( JsonUtils.getString( json, "item" ) ); + int data = JsonUtils.getInt( json, "data", 0 ); + ComputerFamily family = RecipeUtil.getFamily( json, "family" ); + + Item item = ForgeRegistries.ITEMS.getValue( new ResourceLocation( itemName ) ); + + if( item == null ) throw new JsonSyntaxException( "Unknown item '" + itemName + "'" ); + if( !(item instanceof IComputerItem) ) + { + throw new JsonSyntaxException( "Item '" + itemName + "' is not a computer item" ); + } + + + return new ComputerIngredient( (Item & IComputerItem) item, data, family ); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java index c998e1daeb..7df7f2e152 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java @@ -371,6 +371,15 @@ public ComputerFamily getFamily( @Nonnull ItemStack stack ) } } + @Override + public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) + { + return PocketComputerItemFactory.create( + getComputerID( stack ), getLabel( stack ), getColour( stack ), + family, getUpgrade( stack ) + ); + } + // IMedia @Override diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleBase.java b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleBase.java index 94ef5f11f0..6245721f7e 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleBase.java +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtleBase.java @@ -170,6 +170,17 @@ else if( right != null ) } } + @Override + public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) + { + return TurtleItemFactory.create( + getComputerID( stack ), getLabel( stack ), + getColour( stack ), family, + getUpgrade( stack, TurtleSide.Left ), getUpgrade( stack, TurtleSide.Right ), + getFuelLevel( stack ), getOverlay( stack ) + ); + } + @Override public ItemStack setColour( ItemStack stack, int colour ) { diff --git a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java index 1cf7031851..56585dfd28 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java +++ b/src/main/java/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java @@ -7,82 +7,41 @@ package dan200.computercraft.shared.turtle.recipes; import com.google.gson.JsonObject; -import com.google.gson.JsonSyntaxException; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.items.IComputerItem; +import dan200.computercraft.shared.computer.recipe.ComputerConvertRecipe; import dan200.computercraft.shared.turtle.items.TurtleItemFactory; import dan200.computercraft.shared.util.RecipeUtil; -import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; -import net.minecraft.item.crafting.Ingredient; -import net.minecraft.item.crafting.ShapedRecipes; import net.minecraft.util.JsonUtils; -import net.minecraft.util.NonNullList; -import net.minecraft.world.World; import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.common.crafting.IRecipeFactory; import net.minecraftforge.common.crafting.JsonContext; import javax.annotation.Nonnull; -public class TurtleRecipe extends ShapedRecipes +public class TurtleRecipe extends ComputerConvertRecipe { - private final NonNullList m_recipe; - private final ComputerFamily m_family; + private final ComputerFamily family; - public TurtleRecipe( String group, int width, int height, NonNullList recipe, ComputerFamily family ) + public TurtleRecipe( String group, @Nonnull CraftingHelper.ShapedPrimer primer, ComputerFamily family ) { - super( group, width, height, recipe, TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null ) ); - m_recipe = recipe; - m_family = family; - } - - @Override - public boolean matches( @Nonnull InventoryCrafting _inventory, @Nonnull World world ) - { - return !getCraftingResult( _inventory ).isEmpty(); + super( group, primer, TurtleItemFactory.create( -1, null, -1, family, null, null, 0, null ) ); + this.family = family; } @Nonnull @Override - public ItemStack getCraftingResult( @Nonnull InventoryCrafting inventory ) + protected ItemStack convert( @Nonnull ItemStack stack ) { - // See if we match the recipe, and extract the input computercraft ID - int computerID = -1; - String label = null; - for( int y = 0; y < 3; ++y ) - { - for( int x = 0; x < 3; ++x ) - { - ItemStack item = inventory.getStackInRowAndColumn( x, y ); - Ingredient target = m_recipe.get( x + y * 3 ); - - if( item.getItem() instanceof IComputerItem ) - { - IComputerItem itemComputer = (IComputerItem) item.getItem(); - if( itemComputer.getFamily( item ) != m_family ) return ItemStack.EMPTY; + IComputerItem item = (IComputerItem) stack.getItem(); + int computerID = item.getComputerID( stack ); + String label = item.getLabel( stack ); - computerID = itemComputer.getComputerID( item ); - label = itemComputer.getLabel( item ); - } - else if( !target.apply( item ) ) - { - return ItemStack.EMPTY; - } - } - } + if( family == ComputerFamily.Beginners ) computerID = -1; - // Build a turtle with the same ID the computer had - // Construct the new stack - if( m_family != ComputerFamily.Beginners ) - { - return TurtleItemFactory.create( computerID, label, -1, m_family, null, null, 0, null ); - } - else - { - return TurtleItemFactory.create( -1, label, -1, m_family, null, null, 0, null ); - } + return TurtleItemFactory.create( computerID, label, -1, family, null, null, 0, null ); } public static class Factory implements IRecipeFactory @@ -91,20 +50,10 @@ public static class Factory implements IRecipeFactory public IRecipe parse( JsonContext context, JsonObject json ) { String group = JsonUtils.getString( json, "group", "" ); - - String familyName = JsonUtils.getString( json, "family" ); - ComputerFamily family; - try - { - family = ComputerFamily.valueOf( familyName ); - } - catch( IllegalArgumentException e ) - { - throw new JsonSyntaxException( "Unknown computer family '" + familyName + "'" ); - } - + ComputerFamily family = RecipeUtil.getFamily( json, "family" ); CraftingHelper.ShapedPrimer primer = RecipeUtil.getPrimer( context, json ); - return new TurtleRecipe( group, primer.width, primer.height, primer.input, family ); + + return new TurtleRecipe( group, primer, family ); } } } diff --git a/src/main/java/dan200/computercraft/shared/util/RecipeUtil.java b/src/main/java/dan200/computercraft/shared/util/RecipeUtil.java index e222a06ccd..64ca2dfc04 100644 --- a/src/main/java/dan200/computercraft/shared/util/RecipeUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/RecipeUtil.java @@ -9,6 +9,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.gson.*; +import dan200.computercraft.shared.computer.core.ComputerFamily; import net.minecraft.item.crafting.Ingredient; import net.minecraft.util.JsonUtils; import net.minecraft.util.NonNullList; @@ -102,4 +103,17 @@ public static NonNullList getIngredients( JsonContext context, JsonO return ings; } + + public static ComputerFamily getFamily( JsonObject json, String name ) + { + String familyName = JsonUtils.getString( json, name ); + try + { + return ComputerFamily.valueOf( familyName ); + } + catch( IllegalArgumentException e ) + { + throw new JsonSyntaxException( "Unknown computer family '" + familyName + "' for field " + name ); + } + } } diff --git a/src/main/resources/assets/computercraft/recipes/_factories.json b/src/main/resources/assets/computercraft/recipes/_factories.json index 8f525a27ac..c9a49396fe 100644 --- a/src/main/resources/assets/computercraft/recipes/_factories.json +++ b/src/main/resources/assets/computercraft/recipes/_factories.json @@ -2,6 +2,10 @@ "recipes" : { "impostor_shaped" : "dan200.computercraft.shared.util.ImpostorRecipe$Factory", "impostor_shapeless" : "dan200.computercraft.shared.util.ImpostorShapelessRecipe$Factory", - "turtle" : "dan200.computercraft.shared.turtle.recipes.TurtleRecipe$Factory" + "turtle" : "dan200.computercraft.shared.turtle.recipes.TurtleRecipe$Factory", + "computer_upgrade" : "dan200.computercraft.shared.computer.recipe.ComputerFamilyRecipe$Factory" + }, + "ingredients": { + "computer": "dan200.computercraft.shared.computer.recipe.ComputerIngredient$Factory" } } diff --git a/src/main/resources/assets/computercraft/recipes/advanced_computer_upgrade.json b/src/main/resources/assets/computercraft/recipes/advanced_computer_upgrade.json new file mode 100644 index 0000000000..417aecd50d --- /dev/null +++ b/src/main/resources/assets/computercraft/recipes/advanced_computer_upgrade.json @@ -0,0 +1,14 @@ +{ + "type": "computercraft:computer_upgrade", + "pattern": [ + "###", + "#C#", + "# #" + ], + "key": { + "#": { "type": "forge:ore_dict", "ore": "ingotGold" }, + "C": { "type": "computercraft:computer", "item": "computercraft:computer", "family": "Normal" } + }, + "family": "Advanced", + "result": { "item": "computercraft:computer", "data": 16384 } +} diff --git a/src/main/resources/assets/computercraft/recipes/advanced_pocket_computer_upgrade.json b/src/main/resources/assets/computercraft/recipes/advanced_pocket_computer_upgrade.json new file mode 100644 index 0000000000..2528451b0a --- /dev/null +++ b/src/main/resources/assets/computercraft/recipes/advanced_pocket_computer_upgrade.json @@ -0,0 +1,14 @@ +{ + "type": "computercraft:computer_upgrade", + "pattern": [ + "###", + "#C#", + "# #" + ], + "key": { + "#": { "type": "forge:ore_dict", "ore": "ingotGold" }, + "C": { "item": "computercraft:pocket_computer", "data": 0 } + }, + "family": "Advanced", + "result": { "item": "computercraft:pocket_computer", "data": 1 } +} diff --git a/src/main/resources/assets/computercraft/recipes/advanced_turtle.json b/src/main/resources/assets/computercraft/recipes/advanced_turtle.json index ec2fa8c0fd..deea8336cd 100644 --- a/src/main/resources/assets/computercraft/recipes/advanced_turtle.json +++ b/src/main/resources/assets/computercraft/recipes/advanced_turtle.json @@ -7,7 +7,7 @@ ], "key": { "#": { "item": "minecraft:gold_ingot" }, - "C": { "item": "computercraft:computer", "data": 16384 }, + "C": { "type": "computercraft:computer", "item": "computercraft:computer", "data": 16384, "family": "Advanced" }, "I": { "item": "minecraft:chest" } }, "family": "Advanced" diff --git a/src/main/resources/assets/computercraft/recipes/advanced_turtle_upgrade.json b/src/main/resources/assets/computercraft/recipes/advanced_turtle_upgrade.json new file mode 100644 index 0000000000..15791665dc --- /dev/null +++ b/src/main/resources/assets/computercraft/recipes/advanced_turtle_upgrade.json @@ -0,0 +1,18 @@ +{ + "type": "computercraft:computer_upgrade", + "pattern": [ + "###", + "#C#", + " B " + ], + "key": { + "#": { "type": "forge:ore_dict", "ore": "ingotGold" }, + "B": { "type": "forge:ore_dict", "ore": "blockGold" }, + "C": [ + { "type": "computercraft:computer", "item": "computercraft:turtle", "family": "Normal" }, + { "item": "computercraft:turtle_expanded", "data": 0 } + ] + }, + "family": "Advanced", + "result": { "item": "computercraft:turtle_advanced", "data": 0 } +} diff --git a/src/main/resources/assets/computercraft/recipes/normal_turtle.json b/src/main/resources/assets/computercraft/recipes/normal_turtle.json index 2962f2cc4b..12efe33b26 100644 --- a/src/main/resources/assets/computercraft/recipes/normal_turtle.json +++ b/src/main/resources/assets/computercraft/recipes/normal_turtle.json @@ -7,7 +7,7 @@ ], "key": { "#": { "item": "minecraft:iron_ingot" }, - "C": { "item": "computercraft:computer", "data": 0 }, + "C": { "type": "computercraft:computer", "item": "computercraft:computer", "family": "Normal" }, "I": { "item": "minecraft:chest" } }, "family": "Normal"