diff --git a/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java b/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java index 5d44c02..57471ee 100644 --- a/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java +++ b/src/java/mmm/core/api/recipes/I_CraftingRecipeWrapper.java @@ -8,6 +8,8 @@ import net.minecraft.item.ItemStack; public interface I_CraftingRecipeWrapper { + public String getIdentifier( ); + public String getName( ); diff --git a/src/java/mmm/recipes/RCraftingWrappers.java b/src/java/mmm/recipes/RCraftingWrappers.java index 1d2ba12..c1c2110 100644 --- a/src/java/mmm/recipes/RCraftingWrappers.java +++ b/src/java/mmm/recipes/RCraftingWrappers.java @@ -3,6 +3,7 @@ package mmm.recipes; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import mmm.core.api.recipes.I_CraftingRecipeWrapper; import mmm.core.api.recipes.I_CraftingRecipeWrapperFactory; @@ -14,7 +15,8 @@ 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 final ArrayList< I_CraftingRecipeWrapper > RECIPES = new ArrayList<>( ); + public static final HashMap< String , I_CraftingRecipeWrapper > IDENTIFIERS = new HashMap<>( ); public static void register( final I_CraftingRecipeWrapperFactory factory ) @@ -39,10 +41,18 @@ public class RCraftingWrappers System.err.println( "unsupported recipe class " + recipe.getClass( ) ); continue; } - RCraftingWrappers.RECIPES.addAll( factory.createWrappers( recipe ) ); + final List< I_CraftingRecipeWrapper > wrappers = factory.createWrappers( recipe ); + for ( final I_CraftingRecipeWrapper wrapper : wrappers ) { + final String identifier = wrapper.getIdentifier( ); + if ( RCraftingWrappers.IDENTIFIERS.containsKey( identifier ) ) { + throw new IllegalStateException( "duplicate wrapper ID " + identifier ); + } + RCraftingWrappers.IDENTIFIERS.put( identifier , wrapper ); + } + RCraftingWrappers.RECIPES.addAll( wrappers ); } - System.err.println( "wrapped " + RCraftingWrappers.RECIPES.size( ) + " recipes" ); + System.err.println( "generated " + RCraftingWrappers.RECIPES.size( ) + " recipe wrappers" ); } diff --git a/src/java/mmm/recipes/RShapedOreRecipeWrapper.java b/src/java/mmm/recipes/RShapedOreRecipeWrapper.java index d06bce3..ca1de7e 100644 --- a/src/java/mmm/recipes/RShapedOreRecipeWrapper.java +++ b/src/java/mmm/recipes/RShapedOreRecipeWrapper.java @@ -7,6 +7,7 @@ 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.OreDictionary; import net.minecraftforge.oredict.ShapedOreRecipe; @@ -27,6 +28,31 @@ public class RShapedOreRecipeWrapper } + @Override + public String getIdentifier( ) + { + final StringBuilder sb = new StringBuilder( "SHAPED_ORE;" ); + final ItemStack recipeOutput = this.recipe.getRecipeOutput( ); + sb.append( recipeOutput.getItem( ).getRegistryName( ) ).append( ',' ).append( recipeOutput.getMetadata( ) ); + final Object[] input = this.recipe.getInput( ); + for ( final Object inObject : input ) { + ItemStack stack; + sb.append( ';' ); + if ( inObject instanceof ItemStack ) { + stack = (ItemStack) inObject; + } else if ( inObject instanceof List && ! ( (List< ? >) inObject ).isEmpty( ) ) { + stack = (ItemStack) ( (List< ? >) inObject ).get( 0 ); + } else { + stack = null; + } + if ( stack != null ) { + sb.append( stack.getItem( ).getRegistryName( ) ).append( ',' ).append( stack.getMetadata( ) ); + } + } + return sb.toString( ); + } + + @Override public String getName( ) { @@ -50,7 +76,7 @@ public class RShapedOreRecipeWrapper final Object inObj = input[ i + j * this.width ]; if ( inObj instanceof ItemStack ) { - displayInventory.setInventorySlotContents( i + j * 3 , ( (ItemStack) inObj ).copy( ) ); + RShapedOreRecipeWrapper.setSlot( displayInventory , i + j * 3 , (ItemStack) inObj ); } else if ( inObj instanceof List ) { @SuppressWarnings( "unchecked" ) @@ -58,13 +84,24 @@ public class RShapedOreRecipeWrapper if ( oreList.isEmpty( ) ) { continue; } - displayInventory.setInventorySlotContents( i + j * 3 , oreList.get( 0 ).copy( ) ); + RShapedOreRecipeWrapper.setSlot( displayInventory , i + j * 3 , oreList.get( 0 ) ); } } } } + private static void setSlot( final IInventory inventory , final int index , ItemStack stack ) + { + if ( stack.getMetadata( ) == OreDictionary.WILDCARD_VALUE ) { + stack = new ItemStack( stack.getItem( ) , 1 , 0 ); + } else { + stack = stack.copy( ); + } + inventory.setInventorySlotContents( index , stack ); + } + + @Override public boolean canCraft( final IInventory inventory ) { diff --git a/src/java/mmm/recipes/RShapedRecipeWrapper.java b/src/java/mmm/recipes/RShapedRecipeWrapper.java index 097ca62..1cf6b3d 100644 --- a/src/java/mmm/recipes/RShapedRecipeWrapper.java +++ b/src/java/mmm/recipes/RShapedRecipeWrapper.java @@ -5,6 +5,7 @@ import mmm.core.api.recipes.I_CraftingRecipeWrapper; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.ShapedRecipes; +import net.minecraftforge.oredict.OreDictionary; @@ -20,6 +21,22 @@ public class RShapedRecipeWrapper } + @Override + public String getIdentifier( ) + { + final StringBuilder sb = new StringBuilder( "SHAPED;" ); + final ItemStack recipeOutput = this.recipe.getRecipeOutput( ); + sb.append( recipeOutput.getItem( ).getRegistryName( ) ).append( ',' ).append( recipeOutput.getMetadata( ) ); + for ( final ItemStack stack : this.recipe.recipeItems ) { + sb.append( ';' ); + if ( stack != null ) { + sb.append( stack.getItem( ).getRegistryName( ) ).append( ',' ).append( stack.getMetadata( ) ); + } + } + return sb.toString( ); + } + + @Override public String getName( ) { @@ -39,15 +56,26 @@ public class RShapedRecipeWrapper { 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 ]; + final ItemStack itemStack = this.recipe.recipeItems[ i + j * this.recipe.recipeWidth ]; if ( itemStack != null ) { - displayInventory.setInventorySlotContents( i + j * 3 , itemStack.copy( ) ); + RShapedRecipeWrapper.setSlot( displayInventory , i + 3 * j , itemStack ); } } } } + private static void setSlot( final IInventory inventory , final int index , ItemStack stack ) + { + if ( stack.getMetadata( ) == OreDictionary.WILDCARD_VALUE ) { + stack = new ItemStack( stack.getItem( ) , 1 , 0 ); + } else { + stack = stack.copy( ); + } + inventory.setInventorySlotContents( index , stack ); + } + + @Override public boolean canCraft( final IInventory inventory ) { diff --git a/src/java/mmm/recipes/RShapelessOreRecipeWrapper.java b/src/java/mmm/recipes/RShapelessOreRecipeWrapper.java index 10091d0..790f54d 100644 --- a/src/java/mmm/recipes/RShapelessOreRecipeWrapper.java +++ b/src/java/mmm/recipes/RShapelessOreRecipeWrapper.java @@ -50,6 +50,31 @@ public class RShapelessOreRecipeWrapper } + @Override + public String getIdentifier( ) + { + final StringBuilder sb = new StringBuilder( "SHAPELESS_ORE;" ); + final ItemStack recipeOutput = this.recipe.getRecipeOutput( ); + sb.append( recipeOutput.getItem( ).getRegistryName( ) ).append( ',' ).append( recipeOutput.getMetadata( ) ); + final ArrayList< Object > input = this.recipe.getInput( ); + for ( final Object inObject : input ) { + ItemStack stack; + sb.append( ';' ); + if ( inObject instanceof ItemStack ) { + stack = (ItemStack) inObject; + } else if ( inObject instanceof List && ! ( (List< ? >) inObject ).isEmpty( ) ) { + stack = (ItemStack) ( (List< ? >) inObject ).get( 0 ); + } else { + stack = null; + } + if ( stack != null ) { + sb.append( stack.getItem( ).getRegistryName( ) ).append( ',' ).append( stack.getMetadata( ) ); + } + } + return sb.toString( ); + } + + @Override public String getName( ) { @@ -69,19 +94,32 @@ public class RShapelessOreRecipeWrapper { int i = 0; for ( final ItemStack stack : this.combinedInputStacks ) { - displayInventory.setInventorySlotContents( i++ , stack.copy( ) ); + RShapelessOreRecipeWrapper.setSlot( displayInventory , i++ , stack , stack.stackSize ); } 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 ); + + final ItemStack stack = oreList.get( 0 ); + RShapelessOreRecipeWrapper.setSlot( displayInventory , i++ , stack , + this.combinedInputOreLists.get( oreList ) ); } } + private static void setSlot( final IInventory inventory , final int index , ItemStack stack , final int size ) + { + if ( stack.getMetadata( ) == OreDictionary.WILDCARD_VALUE ) { + stack = new ItemStack( stack.getItem( ) , 1 , 0 ); + } else { + stack = stack.copy( ); + } + stack.stackSize = size; + inventory.setInventorySlotContents( index , stack ); + } + + @Override public boolean canCraft( final IInventory inventory ) { diff --git a/src/java/mmm/recipes/RShapelessRecipeWrapper.java b/src/java/mmm/recipes/RShapelessRecipeWrapper.java index 6638bed..f2d7f1a 100644 --- a/src/java/mmm/recipes/RShapelessRecipeWrapper.java +++ b/src/java/mmm/recipes/RShapelessRecipeWrapper.java @@ -37,6 +37,22 @@ public class RShapelessRecipeWrapper } + @Override + public String getIdentifier( ) + { + final StringBuilder sb = new StringBuilder( "SHAPELESS;" ); + final ItemStack recipeOutput = this.recipe.getRecipeOutput( ); + sb.append( recipeOutput.getItem( ).getRegistryName( ) ).append( ',' ).append( recipeOutput.getMetadata( ) ); + for ( final ItemStack stack : this.recipe.recipeItems ) { + sb.append( ';' ); + if ( stack != null ) { + sb.append( stack.getItem( ).getRegistryName( ) ).append( ',' ).append( stack.getMetadata( ) ); + } + } + return sb.toString( ); + } + + @Override public String getName( ) { @@ -55,12 +71,28 @@ public class RShapelessRecipeWrapper public void addInputsToDisplay( final IInventory displayInventory ) { int i = 0; - for ( final ItemStack stack : this.combinedInputs ) { - displayInventory.setInventorySlotContents( i++ , stack.copy( ) ); + for ( ItemStack stack : this.combinedInputs ) { + if ( stack.getMetadata( ) == OreDictionary.WILDCARD_VALUE ) { + stack = new ItemStack( stack.getItem( ) , 1 , 0 ); + } else { + stack = stack.copy( ); + } + RShapelessRecipeWrapper.setSlot( displayInventory , i++ , stack ); } } + private static void setSlot( final IInventory inventory , final int index , ItemStack stack ) + { + if ( stack.getMetadata( ) == OreDictionary.WILDCARD_VALUE ) { + stack = new ItemStack( stack.getItem( ) , 1 , 0 ); + } else { + stack = stack.copy( ); + } + inventory.setInventorySlotContents( index , stack ); + } + + @Override public boolean canCraft( final IInventory inventory ) { diff --git a/src/java/mmm/tech/base/workbench/TBWBContainer.java b/src/java/mmm/tech/base/workbench/TBWBContainer.java index fb4ff6a..7887522 100644 --- a/src/java/mmm/tech/base/workbench/TBWBContainer.java +++ b/src/java/mmm/tech/base/workbench/TBWBContainer.java @@ -2,7 +2,10 @@ package mmm.tech.base.workbench; import mmm.MmmTech; +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import mmm.utils.UInventoryDisplay; import mmm.utils.gui.UGContainer; +import mmm.utils.gui.UGSlotDisplay; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Slot; @@ -17,6 +20,7 @@ public class TBWBContainer public final TBWBTileEntity tileEntity; public final World world; public final BlockPos position; + public final UInventoryDisplay recipe; public TBWBContainer( final InventoryPlayer playerInv , final TBWBTileEntity tileEntity ) @@ -26,8 +30,16 @@ public class TBWBContainer this.position = tileEntity.getPos( ); this.addPlayerInventory( Slot::new , playerInv , 28 , 119 ); + this.slotGroups.nextGroup( ); this.addGrid( Slot::new , tileEntity.storage , 8 , 15 ); + + this.slotGroups.nextGroup( ); + this.recipe = new UInventoryDisplay( "Recipe" , 10 ); + this.addGrid( UGSlotDisplay::new , this.recipe , // + 3 , 3 , 0 , 86 , 32 ); + this.addSlotToContainer( new UGSlotDisplay( this.recipe , 9 , 174 , 50 ) ); + this.slotGroups.endGroups( ); } @@ -40,4 +52,21 @@ public class TBWBContainer this.position.getZ( ) + .5 ) <= 64.; } + + public void setCurrentRecipe( final I_CraftingRecipeWrapper wrapper , final boolean setDefault ) + { + this.recipe.clear( ); + if ( wrapper == null ) { + // XXX log if confirm is set + return; + } + + wrapper.addInputsToDisplay( this.recipe ); + this.recipe.setInventorySlotContents( 9 , wrapper.getOutput( ) ); + + if ( setDefault ) { + // this.tileEntity.setDefaultRecipe( wrapper.getIdentifier( ) ); + } + } + } diff --git a/src/java/mmm/tech/base/workbench/TBWBGui.java b/src/java/mmm/tech/base/workbench/TBWBGui.java index 3f2856b..9d0f568 100644 --- a/src/java/mmm/tech/base/workbench/TBWBGui.java +++ b/src/java/mmm/tech/base/workbench/TBWBGui.java @@ -2,8 +2,12 @@ package mmm.tech.base.workbench; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import mmm.Mmm; +import mmm.core.api.recipes.I_CraftingRecipeWrapper; +import mmm.recipes.RCraftingWrappers; import mmm.utils.gui.A_UGContainerScreen; import mmm.utils.gui.UGArrowButton; import net.minecraft.client.gui.GuiButton; @@ -27,6 +31,10 @@ public class TBWBGui private UGArrowButton bNext; private GuiButton bSetDefault; + private String searchString; + private List< I_CraftingRecipeWrapper > recipes; + private int currentRecipe; + public TBWBGui( final InventoryPlayer inventoryPlayer , final TBWBTileEntity tileEntity ) { @@ -34,6 +42,10 @@ public class TBWBGui this.container.slotGroups.showAll( ); this.xSize = 216; this.ySize = 200; + + this.searchString = ""; + this.recipes = RCraftingWrappers.RECIPES; + this.setRecipe( -1 ); } @@ -60,6 +72,8 @@ public class TBWBGui this.buttonList.add( this.bPrevious ); this.buttonList.add( this.bNext ); this.buttonList.add( this.bSetDefault ); + + this.enableButtons( ); } @@ -90,7 +104,9 @@ public class TBWBGui protected void keyTyped( final char typedChar , final int keyCode ) throws IOException { - if ( !this.tfSearch.textboxKeyTyped( typedChar , keyCode ) ) { + if ( this.tfSearch.textboxKeyTyped( typedChar , keyCode ) ) { + this.handleFiltering( this.tfSearch.getText( ) ); + } else { super.keyTyped( typedChar , keyCode ); } } @@ -100,7 +116,78 @@ public class TBWBGui protected void actionPerformed( final GuiButton button ) throws IOException { - // TODO + if ( button == this.bNext && this.currentRecipe < this.recipes.size( ) - 1 ) { + this.setRecipe( this.currentRecipe + 1 ); + } else if ( button == this.bPrevious && this.currentRecipe > 0 ) { + this.setRecipe( this.currentRecipe - 1 ); + } + } + + + private void setRecipe( int index ) + { + if ( index == -1 && !this.recipes.isEmpty( ) ) { + index = 0; + } + this.currentRecipe = index; + this.container.setCurrentRecipe( index == -1 ? null : this.recipes.get( index ) , false ); + // CNetwork.sendToServer( new TBAFMessage( rName , false ) ); + this.enableButtons( ); + } + + + private void enableButtons( ) + { + if ( this.bNext != null ) { + this.bNext.enabled = !this.recipes.isEmpty( ) && this.currentRecipe < this.recipes.size( ) - 1; + this.bPrevious.enabled = !this.recipes.isEmpty( ) && this.currentRecipe > 0; + } + } + + + private void handleFiltering( final String input ) + { + final String newText = input.trim( ).toLowerCase( ); + if ( this.searchString.equals( newText ) ) { + return; + } + + final I_CraftingRecipeWrapper selected = this.currentRecipe == -1 + ? null + : this.recipes.get( this.currentRecipe ); + final ArrayList< I_CraftingRecipeWrapper > fullList = RCraftingWrappers.RECIPES; + this.searchString = newText; + if ( "".equals( newText ) ) { + this.recipes = fullList; + } else { + if ( this.recipes == fullList ) { + this.recipes = new ArrayList<>( ); + } else { + this.recipes.clear( ); + } + + final int nRecipes = fullList.size( ); + for ( int i = 0 ; i < nRecipes ; i++ ) { + final I_CraftingRecipeWrapper recipe = fullList.get( i ); + if ( I18n.format( recipe.getName( ) ).toLowerCase( ).contains( newText ) ) { + this.recipes.add( recipe ); + } + } + } + + if ( selected == null && !this.recipes.isEmpty( ) ) { + this.setRecipe( 0 ); + } else if ( selected != null ) { + this.setRecipe( this.getRecipeIndex( selected ) ); + } else { + this.setRecipe( -1 ); + } + } + + + private int getRecipeIndex( I_CraftingRecipeWrapper selected ) + { + return this.recipes.indexOf( selected ); } }