11package org .cyclops .structuredcrafting .craft ;
22
33import com .google .common .collect .Lists ;
4+ import com .google .common .collect .Maps ;
45import net .minecraft .item .ItemStack ;
56import net .minecraft .item .crafting .CraftingManager ;
67import net .minecraft .item .crafting .IRecipe ;
1516import org .cyclops .structuredcrafting .craft .provider .IItemStackProviderRegistry ;
1617
1718import java .util .List ;
19+ import java .util .Map ;
1820
1921/**
2022 * A crafting matrix represented with blockstates.
2123 * @author rubensworks
2224 */
2325public class WorldCraftingMatrix {
2426
25- private static final WorldInventoryCrafting INVENTORY_CRAFTING = new WorldInventoryCrafting ();
26-
2727 private final World world ;
2828 private final BlockPos centerPos ;
2929 private final EnumFacing .Axis axis ;
@@ -56,13 +56,14 @@ protected List<IItemStackProvider> getItemStackProviders() {
5656 getRegistry (IItemStackProviderRegistry .class ).getProviders ();
5757 }
5858
59- protected Pair <ItemStack , IItemStackProvider > determineItemStackProviderForInput (World world , BlockPos pos , EnumFacing side ) {
59+ protected Map <ItemStack , IItemStackProvider > determineItemStackProviderForInput (World world , BlockPos pos , EnumFacing side ) {
60+ Map <ItemStack , IItemStackProvider > providers = Maps .newHashMap ();
6061 for (IItemStackProvider provider : getItemStackProviders ()) {
6162 if (provider .hasItemStack (world , pos , side )) {
62- return Pair . of (provider .getItemStack (world , pos , side ), provider );
63+ providers . put (provider .getItemStack (world , pos , side ), provider );
6364 }
6465 }
65- return null ;
66+ return providers ;
6667 }
6768
6869 protected boolean addItemStackForOutput (World world , BlockPos pos , EnumFacing side , List <IItemStackProvider > outputProviders , ItemStack itemStack , boolean simulate ) {
@@ -86,45 +87,113 @@ public boolean craft(boolean simulate) {
8687 return false ;
8788 }
8889
89- BlockPos [] positions = new BlockPos [9 ];
90- IItemStackProvider [] providers = new IItemStackProvider [9 ];
91- ItemStack itemStack = ItemStack .EMPTY ;
90+ CraftingPossibility chosenPossibility = null ;
91+ ItemStack itemStack = null ;
9292 for (int k = 0 ; k < 3 ; k ++) {
9393 // Set crafting grid
94- if (itemStack .isEmpty ()) {
94+ if (chosenPossibility == null ) {
95+ List <CraftingPossibility > possibilities = Lists .newArrayList (new CraftingPossibility ());
9596 for (int i = -1 ; i < 2 ; i ++) {
9697 for (int j = -1 ; j < 2 ; j ++) {
97- int arrayIndex = (j + 1 ) * 3 + (i + 1 );
9898 BlockPos pos = addInAxis (centerPos , axis , i , j );
99- Pair <ItemStack , IItemStackProvider > result = determineItemStackProviderForInput (world , pos , inputSide );
100- ItemStack itemStackInput = result != null ? result .getLeft () : ItemStack .EMPTY ;
101- if (!itemStackInput .isEmpty ()) {
102- itemStackInput = itemStackInput .copy ();
103- itemStackInput .setCount (1 );
99+ Map <ItemStack , IItemStackProvider > results = determineItemStackProviderForInput (world , pos , inputSide );
100+ boolean processedSingleResult = false ;
101+ List <CraftingPossibility > possibilitiesAtStart = Lists .newArrayList (possibilities );
102+ for (Map .Entry <ItemStack , IItemStackProvider > result : results .entrySet ()) {
103+ ItemStack itemStackInput = result .getKey ();
104+ if (!itemStackInput .isEmpty ()) {
105+ itemStackInput = itemStackInput .copy ();
106+ itemStackInput .setCount (1 );
107+ }
108+
109+ if (!processedSingleResult ) {
110+ // The first result we process, just add position to all existing possibilities
111+ for (CraftingPossibility possibility : possibilities ) {
112+ possibility .setPosition (i , j , k , pos , result .getValue (), result .getKey ());
113+ }
114+ processedSingleResult = true ;
115+ } else {
116+ // We have more than one possibility!
117+ // Duplicate all existing possibilities.
118+ for (CraftingPossibility possibility : possibilitiesAtStart ) {
119+ possibility = possibility .clone ();
120+ possibility .setPosition (i , j , k , pos , result .getValue (), result .getKey ());
121+ possibilities .add (possibility );
122+ }
123+ }
104124 }
105- // This makes sure we can also accept recipes which are rotated, mirroring is already supported by Vanilla.
106- if (k == 0 ) {
107- INVENTORY_CRAFTING .setItemStack (i + 1 , j + 1 , itemStackInput );
108- } else if (k == 1 ) {
109- INVENTORY_CRAFTING .setItemStack (j + 1 , i + 1 , itemStackInput );
110- } else if (k == 2 ) {
111- INVENTORY_CRAFTING .setItemStack (i + 1 , 2 - (j + 1 ), itemStackInput );
125+
126+ // No valid result was found, add an empty slot to all possibilities
127+ if (!processedSingleResult ) {
128+ for (CraftingPossibility possibility : possibilities ) {
129+ possibility .setPosition (i , j , k , pos , null , ItemStack .EMPTY );
130+ }
112131 }
113- positions [arrayIndex ] = pos ;
114- providers [arrayIndex ] = result != null ? result .getRight () : null ;
115132 }
116133 }
117- IRecipe recipe = CraftingManager .findMatchingRecipe (INVENTORY_CRAFTING , world );
118- if (recipe != null ) {
119- itemStack = recipe .getCraftingResult (INVENTORY_CRAFTING );
134+ for (CraftingPossibility possibility : possibilities ) {
135+ if (!(itemStack = possibility .getOutput (world )).isEmpty ()) {
136+ chosenPossibility = possibility ;
137+ break ;
138+ }
120139 }
121140 }
122141 }
123142
124143 // Determine output
125- if (!itemStack .isEmpty () && addItemStackForOutput (world , targetPos , targetSide , outputProviders , itemStack , simulate )) {
126- // Handle remaining container items: place blocks and drop items
127- NonNullList <ItemStack > remainingStacks = CraftingManager .getRemainingItems (INVENTORY_CRAFTING , world );
144+ if (chosenPossibility != null && !itemStack .isEmpty ()
145+ && addItemStackForOutput (world , targetPos , targetSide , outputProviders , itemStack , simulate )) {
146+ chosenPossibility .handleRemainingItems (world , inputSide , simulate );
147+ return true ;
148+ }
149+ return false ;
150+ }
151+
152+ public static WorldCraftingMatrix deriveMatrix (World world , BlockPos centerPos ) {
153+ EnumFacing side = (world .getBlockState (centerPos ).getValue (BlockStructuredCrafter .FACING )).getOpposite ();
154+ return new WorldCraftingMatrix (world , centerPos .offset (side ), side .getAxis (),
155+ centerPos .offset (side .getOpposite ()), side .getOpposite ());
156+ }
157+
158+ public static class CraftingPossibility {
159+ private final WorldInventoryCrafting inventoryCrafting = new WorldInventoryCrafting ();
160+ private final BlockPos [] positions = new BlockPos [9 ];
161+ private final IItemStackProvider [] providers = new IItemStackProvider [9 ];
162+
163+ public CraftingPossibility () {
164+
165+ }
166+
167+ public void setPosition (int i , int j , int rotation , BlockPos pos , IItemStackProvider itemStackProvider , ItemStack itemStack ) {
168+ int arrayIndex = (j + 1 ) * 3 + (i + 1 );
169+ // This makes sure we can also accept recipes which are rotated, mirroring is already supported by Vanilla.
170+ if (rotation == 0 ) {
171+ inventoryCrafting .setItemStack (i + 1 , j + 1 , itemStack );
172+ } else if (rotation == 1 ) {
173+ inventoryCrafting .setItemStack (j + 1 , i + 1 , itemStack );
174+ } else if (rotation == 2 ) {
175+ inventoryCrafting .setItemStack (i + 1 , 2 - (j + 1 ), itemStack );
176+ }
177+ positions [arrayIndex ] = pos ;
178+ providers [arrayIndex ] = itemStackProvider ;
179+ }
180+
181+ public ItemStack getOutput (World world ) {
182+ IRecipe recipe = CraftingManager .findMatchingRecipe (inventoryCrafting , world );
183+ if (recipe != null ) {
184+ return recipe .getCraftingResult (inventoryCrafting );
185+ }
186+ return ItemStack .EMPTY ;
187+ }
188+
189+ /**
190+ * Handle remaining container items: place blocks and drop items
191+ * @param world The world.
192+ * @param inputSide The crafting side.
193+ * @param simulate If the crafting should be simulated.
194+ */
195+ public void handleRemainingItems (World world , EnumFacing inputSide , boolean simulate ) {
196+ NonNullList <ItemStack > remainingStacks = CraftingManager .getRemainingItems (inventoryCrafting , world );
128197 for (int i = 0 ; i < remainingStacks .size (); i ++) {
129198 ItemStack remainingStack = remainingStacks .get (i );
130199 if (providers [i ] != null ) {
@@ -134,15 +203,17 @@ public boolean craft(boolean simulate) {
134203 }
135204 }
136205 }
137- return true ;
138206 }
139- return false ;
140- }
141207
142- public static WorldCraftingMatrix deriveMatrix (World world , BlockPos centerPos ) {
143- EnumFacing side = (world .getBlockState (centerPos ).getValue (BlockStructuredCrafter .FACING )).getOpposite ();
144- return new WorldCraftingMatrix (world , centerPos .offset (side ), side .getAxis (),
145- centerPos .offset (side .getOpposite ()), side .getOpposite ());
208+ public CraftingPossibility clone () {
209+ CraftingPossibility craftingPossibility = new CraftingPossibility ();
210+ for (int i = 0 ; i < this .inventoryCrafting .getSizeInventory (); i ++) {
211+ craftingPossibility .inventoryCrafting .setInventorySlotContents (i , this .inventoryCrafting .getStackInSlot (i ));
212+ }
213+ System .arraycopy (this .positions , 0 , craftingPossibility .positions , 0 , this .positions .length );
214+ System .arraycopy (this .providers , 0 , craftingPossibility .providers , 0 , this .providers .length );
215+ return craftingPossibility ;
216+ }
146217 }
147218
148219}
0 commit comments