diff --git a/src/java/mmm/Mmm.java b/src/java/mmm/Mmm.java index e19d758..0e61d99 100644 --- a/src/java/mmm/Mmm.java +++ b/src/java/mmm/Mmm.java @@ -5,6 +5,7 @@ import mmm.core.CProxyCommon; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.SidedProxy; import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; @@ -44,4 +45,11 @@ public class Mmm Mmm.proxy.init( event ); } + + @Mod.EventHandler + public void postInit( FMLPostInitializationEvent event ) + { + Mmm.proxy.postInit( event ); + } + } diff --git a/src/java/mmm/core/CProxyCommon.java b/src/java/mmm/core/CProxyCommon.java index c1a80dc..ff54c36 100644 --- a/src/java/mmm/core/CProxyCommon.java +++ b/src/java/mmm/core/CProxyCommon.java @@ -6,7 +6,9 @@ import mmm.MmmFood; import mmm.MmmMaterials; import mmm.MmmTech; import mmm.MmmWorld; +import mmm.recipes.RCraftingWrappers; import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; @@ -16,6 +18,7 @@ public class CProxyCommon public void preInit( final FMLPreInitializationEvent event ) { + RCraftingWrappers.preInit( ); CAccessors.preInit( ); MmmMaterials.preInit( ); @@ -34,4 +37,10 @@ public class CProxyCommon MmmDeco.init( ); } + + public void postInit( final FMLPostInitializationEvent event ) + { + RCraftingWrappers.wrapRecipes( ); + } + } \ No newline at end of file diff --git a/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java b/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java new file mode 100644 index 0000000..5d44c02 --- /dev/null +++ b/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java @@ -0,0 +1,26 @@ +package mmm.core.api.recipes; + + +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + + + +public interface I_CraftingRecipeWrapper +{ + + public String getName( ); + + + public ItemStack getOutput( ); + + + public void addInputsToDisplay( IInventory displayInventory ); + + + public boolean canCraft( IInventory inventory ); + + + public void craft( IInventory input , IInventory output , int quantity ); + +} diff --git a/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapperFactory.java b/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapperFactory.java new file mode 100644 index 0000000..16a12ab --- /dev/null +++ b/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapperFactory.java @@ -0,0 +1,17 @@ +package mmm.core.api.recipes; + + +import java.util.List; + +import net.minecraft.item.crafting.IRecipe; + + + +public interface I_CraftingRecipeWrapperFactory +{ + public Class< ? extends IRecipe > getRecipeClass( ); + + + public List< I_CraftingRecipeWrapper > createWrappers( IRecipe recipe ); + +} diff --git a/src/java/mmm/recipes/RCraftingWrappers.java b/src/java/mmm/recipes/RCraftingWrappers.java new file mode 100644 index 0000000..1d2ba12 --- /dev/null +++ b/src/java/mmm/recipes/RCraftingWrappers.java @@ -0,0 +1,56 @@ +package mmm.recipes; + + +import java.util.ArrayList; +import java.util.HashMap; + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import mmm.core.api.recipes.I_CraftingRecipeWrapperFactory; +import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.item.crafting.IRecipe; + + + +public class RCraftingWrappers +{ + private static final HashMap< Class< ? > , I_CraftingRecipeWrapperFactory > FACTORIES = new HashMap<>( ); + private static final ArrayList< I_CraftingRecipeWrapper > RECIPES = new ArrayList<>( ); + + + public static void register( final I_CraftingRecipeWrapperFactory factory ) + { + final Class< ? extends IRecipe > rc = factory.getRecipeClass( ); + if ( RCraftingWrappers.FACTORIES.containsKey( rc ) ) { + throw new IllegalArgumentException( "duplicate recipe wrapper factory for type " + rc ); + } + RCraftingWrappers.FACTORIES.put( rc , factory ); + } + + + public static void wrapRecipes( ) + { + if ( !RCraftingWrappers.RECIPES.isEmpty( ) ) { + throw new IllegalStateException( "already initialized" ); + } + + for ( final IRecipe recipe : CraftingManager.getInstance( ).getRecipeList( ) ) { + final I_CraftingRecipeWrapperFactory factory = RCraftingWrappers.FACTORIES.get( recipe.getClass( ) ); + if ( factory == null ) { + System.err.println( "unsupported recipe class " + recipe.getClass( ) ); + continue; + } + RCraftingWrappers.RECIPES.addAll( factory.createWrappers( recipe ) ); + } + + System.err.println( "wrapped " + RCraftingWrappers.RECIPES.size( ) + " recipes" ); + } + + + public static void preInit( ) + { + RCraftingWrappers.register( new RShapelessRecipeWrapperFactory( ) ); + RCraftingWrappers.register( new RShapelessOreRecipeWrapperFactory( ) ); + RCraftingWrappers.register( new RShapedRecipeWrapperFactory( ) ); + RCraftingWrappers.register( new RShapedOreRecipeWrapperFactory( ) ); + } +} diff --git a/src/java/mmm/recipes/RShapedOreRecipeWrapper.java b/src/java/mmm/recipes/RShapedOreRecipeWrapper.java new file mode 100644 index 0000000..d06bce3 --- /dev/null +++ b/src/java/mmm/recipes/RShapedOreRecipeWrapper.java @@ -0,0 +1,83 @@ +package mmm.recipes; + + +import java.util.List; + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import net.minecraftforge.oredict.ShapedOreRecipe; + + + +public class RShapedOreRecipeWrapper + implements I_CraftingRecipeWrapper +{ + private final ShapedOreRecipe recipe; + private final int width; + private final int height; + + + public RShapedOreRecipeWrapper( final ShapedOreRecipe recipe ) + { + this.recipe = recipe; + this.width = ObfuscationReflectionHelper.getPrivateValue( ShapedOreRecipe.class , this.recipe , "width" ); + this.height = ObfuscationReflectionHelper.getPrivateValue( ShapedOreRecipe.class , this.recipe , "height" ); + } + + + @Override + public String getName( ) + { + return this.recipe.getRecipeOutput( ).getUnlocalizedName( ); + } + + + @Override + public ItemStack getOutput( ) + { + return this.recipe.getRecipeOutput( ); + } + + + @Override + public void addInputsToDisplay( final IInventory displayInventory ) + { + final Object[] input = this.recipe.getInput( ); + for ( int i = 0 ; i < this.width ; i++ ) { + for ( int j = 0 ; j < this.height ; j++ ) { + final Object inObj = input[ i + j * this.width ]; + + if ( inObj instanceof ItemStack ) { + displayInventory.setInventorySlotContents( i + j * 3 , ( (ItemStack) inObj ).copy( ) ); + + } else if ( inObj instanceof List ) { + @SuppressWarnings( "unchecked" ) + final List< ItemStack > oreList = (List< ItemStack >) inObj; + if ( oreList.isEmpty( ) ) { + continue; + } + displayInventory.setInventorySlotContents( i + j * 3 , oreList.get( 0 ).copy( ) ); + } + } + } + } + + + @Override + public boolean canCraft( final IInventory inventory ) + { + // TODO Auto-generated method stub + return false; + } + + + @Override + public void craft( final IInventory input , final IInventory output , final int quantity ) + { + // TODO Auto-generated method stub + + } + +} diff --git a/src/java/mmm/recipes/RShapedOreRecipeWrapperFactory.java b/src/java/mmm/recipes/RShapedOreRecipeWrapperFactory.java new file mode 100644 index 0000000..54fc982 --- /dev/null +++ b/src/java/mmm/recipes/RShapedOreRecipeWrapperFactory.java @@ -0,0 +1,32 @@ +package mmm.recipes; + + +import java.util.Arrays; +import java.util.List; + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import mmm.core.api.recipes.I_CraftingRecipeWrapperFactory; +import net.minecraft.item.crafting.IRecipe; +import net.minecraftforge.oredict.ShapedOreRecipe; + + + +public class RShapedOreRecipeWrapperFactory + implements I_CraftingRecipeWrapperFactory +{ + + @Override + public Class< ? extends IRecipe > getRecipeClass( ) + { + return ShapedOreRecipe.class; + } + + + @Override + public List< I_CraftingRecipeWrapper > createWrappers( final IRecipe recipe ) + { + final ShapedOreRecipe r = (ShapedOreRecipe) recipe; + return Arrays.asList( new RShapedOreRecipeWrapper( r ) ); + } + +} diff --git a/src/java/mmm/recipes/RShapedRecipeWrapper.java b/src/java/mmm/recipes/RShapedRecipeWrapper.java new file mode 100644 index 0000000..097ca62 --- /dev/null +++ b/src/java/mmm/recipes/RShapedRecipeWrapper.java @@ -0,0 +1,66 @@ +package mmm.recipes; + + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ShapedRecipes; + + + +public class RShapedRecipeWrapper + implements I_CraftingRecipeWrapper +{ + private final ShapedRecipes recipe; + + + public RShapedRecipeWrapper( final ShapedRecipes recipe ) + { + this.recipe = recipe; + } + + + @Override + public String getName( ) + { + return this.recipe.getRecipeOutput( ).getUnlocalizedName( ); + } + + + @Override + public ItemStack getOutput( ) + { + return this.recipe.getRecipeOutput( ); + } + + + @Override + public void addInputsToDisplay( final IInventory displayInventory ) + { + for ( int i = 0 ; i < this.recipe.recipeWidth ; i++ ) { + for ( int j = 0 ; j < this.recipe.recipeHeight ; j++ ) { + ItemStack itemStack = this.recipe.recipeItems[ i + j * this.recipe.recipeWidth ]; + if ( itemStack != null ) { + displayInventory.setInventorySlotContents( i + j * 3 , itemStack.copy( ) ); + } + } + } + } + + + @Override + public boolean canCraft( final IInventory inventory ) + { + // TODO Auto-generated method stub + return false; + } + + + @Override + public void craft( final IInventory input , final IInventory output , final int quantity ) + { + // TODO Auto-generated method stub + + } + +} diff --git a/src/java/mmm/recipes/RShapedRecipeWrapperFactory.java b/src/java/mmm/recipes/RShapedRecipeWrapperFactory.java new file mode 100644 index 0000000..a945769 --- /dev/null +++ b/src/java/mmm/recipes/RShapedRecipeWrapperFactory.java @@ -0,0 +1,36 @@ +package mmm.recipes; + + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import mmm.core.api.recipes.I_CraftingRecipeWrapperFactory; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.ShapedRecipes; + + + +public class RShapedRecipeWrapperFactory + implements I_CraftingRecipeWrapperFactory +{ + + @Override + public Class< ? extends IRecipe > getRecipeClass( ) + { + return ShapedRecipes.class; + } + + + @Override + public List< I_CraftingRecipeWrapper > createWrappers( IRecipe recipe ) + { + ShapedRecipes r = (ShapedRecipes) recipe; + if ( r.recipeHeight > 3 || r.recipeWidth > 3 ) { + return Collections.emptyList( ); + } + return Arrays.asList( new RShapedRecipeWrapper( r ) ); + } + +} diff --git a/src/java/mmm/recipes/RShapelessOreRecipeWrapper.java b/src/java/mmm/recipes/RShapelessOreRecipeWrapper.java new file mode 100644 index 0000000..10091d0 --- /dev/null +++ b/src/java/mmm/recipes/RShapelessOreRecipeWrapper.java @@ -0,0 +1,100 @@ +package mmm.recipes; + + +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.List; + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; +import net.minecraftforge.oredict.ShapelessOreRecipe; + + + +public class RShapelessOreRecipeWrapper + implements I_CraftingRecipeWrapper +{ + private final ShapelessOreRecipe recipe; + private final List< ItemStack > combinedInputStacks; + private final IdentityHashMap< List< ItemStack > , Integer > combinedInputOreLists; + + + public RShapelessOreRecipeWrapper( final ShapelessOreRecipe recipe ) + { + this.recipe = recipe; + this.combinedInputStacks = new ArrayList<>( ); + this.combinedInputOreLists = new IdentityHashMap<>( ); + + OUTER: for ( final Object input : this.recipe.getInput( ) ) { + if ( input instanceof ItemStack ) { + final ItemStack invStack = (ItemStack) input; + for ( final ItemStack ciStack : this.combinedInputStacks ) { + if ( OreDictionary.itemMatches( ciStack , invStack , true ) ) { + ciStack.stackSize += invStack.stackSize; + continue OUTER; + } + } + this.combinedInputStacks.add( invStack.copy( ) ); + } else if ( input instanceof List ) { + @SuppressWarnings( "unchecked" ) + final List< ItemStack > oreList = (List< ItemStack >) input; + if ( this.combinedInputOreLists.containsKey( oreList ) ) { + this.combinedInputOreLists.put( oreList , this.combinedInputOreLists.get( oreList ) + 1 ); + } else { + this.combinedInputOreLists.put( oreList , 1 ); + } + } + } + } + + + @Override + public String getName( ) + { + return this.recipe.getRecipeOutput( ).getUnlocalizedName( ); + } + + + @Override + public ItemStack getOutput( ) + { + return this.recipe.getRecipeOutput( ); + } + + + @Override + public void addInputsToDisplay( final IInventory displayInventory ) + { + int i = 0; + for ( final ItemStack stack : this.combinedInputStacks ) { + displayInventory.setInventorySlotContents( i++ , stack.copy( ) ); + } + for ( final List< ItemStack > oreList : this.combinedInputOreLists.keySet( ) ) { + if ( oreList.isEmpty( ) ) { + continue; + } + final ItemStack stack = oreList.get( 0 ).copy( ); + stack.stackSize = this.combinedInputOreLists.get( oreList ); + displayInventory.setInventorySlotContents( i++ , stack ); + } + } + + + @Override + public boolean canCraft( final IInventory inventory ) + { + // TODO Auto-generated method stub + return false; + } + + + @Override + public void craft( final IInventory input , final IInventory output , final int quantity ) + { + // TODO Auto-generated method stub + + } + +} diff --git a/src/java/mmm/recipes/RShapelessOreRecipeWrapperFactory.java b/src/java/mmm/recipes/RShapelessOreRecipeWrapperFactory.java new file mode 100644 index 0000000..242b8be --- /dev/null +++ b/src/java/mmm/recipes/RShapelessOreRecipeWrapperFactory.java @@ -0,0 +1,31 @@ +package mmm.recipes; + + +import java.util.Arrays; +import java.util.List; + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import mmm.core.api.recipes.I_CraftingRecipeWrapperFactory; +import net.minecraft.item.crafting.IRecipe; +import net.minecraftforge.oredict.ShapelessOreRecipe; + + + +public class RShapelessOreRecipeWrapperFactory + implements I_CraftingRecipeWrapperFactory +{ + + @Override + public Class< ? extends IRecipe > getRecipeClass( ) + { + return ShapelessOreRecipe.class; + } + + + @Override + public List< I_CraftingRecipeWrapper > createWrappers( final IRecipe recipe ) + { + return Arrays.asList( new RShapelessOreRecipeWrapper( (ShapelessOreRecipe) recipe ) ); + } + +} diff --git a/src/java/mmm/recipes/RShapelessRecipeWrapper.java b/src/java/mmm/recipes/RShapelessRecipeWrapper.java new file mode 100644 index 0000000..6638bed --- /dev/null +++ b/src/java/mmm/recipes/RShapelessRecipeWrapper.java @@ -0,0 +1,95 @@ +package mmm.recipes; + + +import java.util.ArrayList; +import java.util.List; + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ShapelessRecipes; +import net.minecraftforge.oredict.OreDictionary; + + + +public class RShapelessRecipeWrapper + implements I_CraftingRecipeWrapper +{ + + private final ShapelessRecipes recipe; + private final List< ItemStack > combinedInputs; + + + public RShapelessRecipeWrapper( final ShapelessRecipes recipe ) + { + this.recipe = recipe; + + this.combinedInputs = new ArrayList<>( ); + OUTER: for ( final ItemStack invStack : this.recipe.recipeItems ) { + for ( final ItemStack ciStack : this.combinedInputs ) { + if ( OreDictionary.itemMatches( ciStack , invStack , true ) ) { + ciStack.stackSize += invStack.stackSize; + continue OUTER; + } + } + this.combinedInputs.add( invStack.copy( ) ); + } + } + + + @Override + public String getName( ) + { + return this.recipe.getRecipeOutput( ).getUnlocalizedName( ); + } + + + @Override + public ItemStack getOutput( ) + { + return this.recipe.getRecipeOutput( ); + } + + + @Override + public void addInputsToDisplay( final IInventory displayInventory ) + { + int i = 0; + for ( final ItemStack stack : this.combinedInputs ) { + displayInventory.setInventorySlotContents( i++ , stack.copy( ) ); + } + } + + + @Override + public boolean canCraft( final IInventory inventory ) + { + final int nInputs = this.combinedInputs.size( ); + final int nInvItems = inventory.getSizeInventory( ); + for ( int i = 0 ; i < nInputs ; i++ ) { + final ItemStack rStack = this.combinedInputs.get( i ); + int nLeft = rStack.stackSize; + + for ( int j = 0 ; j < nInvItems && nLeft > 0 ; j++ ) { + final ItemStack invStack = inventory.getStackInSlot( j ); + if ( OreDictionary.itemMatches( rStack , invStack , false ) ) { + nLeft -= invStack.stackSize; + } + } + + if ( nLeft > 0 ) { + return false; + } + } + return true; + } + + + @Override + public void craft( final IInventory input , final IInventory output , final int quantity ) + { + // TODO Auto-generated method stub + + } + +} diff --git a/src/java/mmm/recipes/RShapelessRecipeWrapperFactory.java b/src/java/mmm/recipes/RShapelessRecipeWrapperFactory.java new file mode 100644 index 0000000..a98b99d --- /dev/null +++ b/src/java/mmm/recipes/RShapelessRecipeWrapperFactory.java @@ -0,0 +1,32 @@ +package mmm.recipes; + + +import mmm.core.api.recipes.I_CraftingRecipeWrapperFactory; + +import java.util.Arrays; +import java.util.List; + +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.ShapelessRecipes; + + + +public class RShapelessRecipeWrapperFactory + implements I_CraftingRecipeWrapperFactory +{ + + @Override + public Class< ShapelessRecipes > getRecipeClass( ) + { + return ShapelessRecipes.class; + } + + + @Override + public List< I_CraftingRecipeWrapper > createWrappers( final IRecipe recipe ) + { + return Arrays.asList( new RShapelessRecipeWrapper( (ShapelessRecipes) recipe ) ); + } + +}