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 .util .NonNullList ;
1415import org .cyclops .structuredcrafting .craft .provider .IItemStackProviderRegistry ;
1516
1617import java .util .List ;
18+ import java .util .Map ;
1719
1820/**
1921 * A crafting matrix represented with blockstates.
2022 * @author rubensworks
2123 */
2224public class WorldCraftingMatrix {
2325
24- private static final WorldInventoryCrafting INVENTORY_CRAFTING = new WorldInventoryCrafting ();
25-
2626 private final World world ;
2727 private final BlockPos centerPos ;
2828 private final EnumFacing .Axis axis ;
@@ -55,13 +55,14 @@ protected List<IItemStackProvider> getItemStackProviders() {
5555 getRegistry (IItemStackProviderRegistry .class ).getProviders ();
5656 }
5757
58- protected Pair <ItemStack , IItemStackProvider > determineItemStackProviderForInput (World world , BlockPos pos , EnumFacing side ) {
58+ protected Map <ItemStack , IItemStackProvider > determineItemStackProviderForInput (World world , BlockPos pos , EnumFacing side ) {
59+ Map <ItemStack , IItemStackProvider > providers = Maps .newHashMap ();
5960 for (IItemStackProvider provider : getItemStackProviders ()) {
6061 if (provider .hasItemStack (world , pos , side )) {
61- return Pair . of (provider .getItemStack (world , pos , side ), provider );
62+ providers . put (provider .getItemStack (world , pos , side ), provider );
6263 }
6364 }
64- return null ;
65+ return providers ;
6566 }
6667
6768 protected boolean addItemStackForOutput (World world , BlockPos pos , EnumFacing side , List <IItemStackProvider > outputProviders , ItemStack itemStack , boolean simulate ) {
@@ -85,42 +86,109 @@ public boolean craft(boolean simulate) {
8586 return false ;
8687 }
8788
88- BlockPos [] positions = new BlockPos [9 ];
89- IItemStackProvider [] providers = new IItemStackProvider [9 ];
90- ItemStack itemStack = ItemStack .EMPTY ;
89+ CraftingPossibility chosenPossibility = null ;
90+ ItemStack itemStack = null ;
9191 for (int k = 0 ; k < 3 ; k ++) {
9292 // Set crafting grid
93- if (itemStack .isEmpty ()) {
93+ if (chosenPossibility == null ) {
94+ List <CraftingPossibility > possibilities = Lists .newArrayList (new CraftingPossibility ());
9495 for (int i = -1 ; i < 2 ; i ++) {
9596 for (int j = -1 ; j < 2 ; j ++) {
96- int arrayIndex = (j + 1 ) * 3 + (i + 1 );
9797 BlockPos pos = addInAxis (centerPos , axis , i , j );
98- Pair <ItemStack , IItemStackProvider > result = determineItemStackProviderForInput (world , pos , inputSide );
99- ItemStack itemStackInput = result != null ? result .getLeft () : ItemStack .EMPTY ;
100- if (!itemStackInput .isEmpty ()) {
101- itemStackInput = itemStackInput .copy ();
102- itemStackInput .setCount (1 );
98+ Map <ItemStack , IItemStackProvider > results = determineItemStackProviderForInput (world , pos , inputSide );
99+ boolean processedSingleResult = false ;
100+ List <CraftingPossibility > possibilitiesAtStart = Lists .newArrayList (possibilities );
101+ for (Map .Entry <ItemStack , IItemStackProvider > result : results .entrySet ()) {
102+ ItemStack itemStackInput = result .getKey ();
103+ if (!itemStackInput .isEmpty ()) {
104+ itemStackInput = itemStackInput .copy ();
105+ itemStackInput .setCount (1 );
106+ }
107+
108+ if (!processedSingleResult ) {
109+ // The first result we process, just add position to all existing possibilities
110+ for (CraftingPossibility possibility : possibilities ) {
111+ possibility .setPosition (i , j , k , pos , result .getValue (), result .getKey ());
112+ }
113+ processedSingleResult = true ;
114+ } else {
115+ // We have more than one possibility!
116+ // Duplicate all existing possibilities.
117+ for (CraftingPossibility possibility : possibilitiesAtStart ) {
118+ possibility = possibility .clone ();
119+ possibility .setPosition (i , j , k , pos , result .getValue (), result .getKey ());
120+ possibilities .add (possibility );
121+ }
122+ }
103123 }
104- // This makes sure we can also accept recipes which are rotated, mirroring is already supported by Vanilla.
105- if (k == 0 ) {
106- INVENTORY_CRAFTING .setItemStack (i + 1 , j + 1 , itemStackInput );
107- } else if (k == 1 ) {
108- INVENTORY_CRAFTING .setItemStack (j + 1 , i + 1 , itemStackInput );
109- } else if (k == 2 ) {
110- INVENTORY_CRAFTING .setItemStack (i + 1 , 2 - (j + 1 ), itemStackInput );
124+
125+ // No valid result was found, add an empty slot to all possibilities
126+ if (!processedSingleResult ) {
127+ for (CraftingPossibility possibility : possibilities ) {
128+ possibility .setPosition (i , j , k , pos , null , ItemStack .EMPTY );
129+ }
111130 }
112- positions [arrayIndex ] = pos ;
113- providers [arrayIndex ] = result != null ? result .getRight () : null ;
114131 }
115132 }
116- itemStack = CraftingManager .getInstance ().findMatchingRecipe (INVENTORY_CRAFTING , world );
133+ for (CraftingPossibility possibility : possibilities ) {
134+ if (!(itemStack = possibility .getOutput (world )).isEmpty ()) {
135+ chosenPossibility = possibility ;
136+ break ;
137+ }
138+ }
117139 }
118140 }
119141
120142 // Determine output
121- if (!itemStack .isEmpty () && addItemStackForOutput (world , targetPos , targetSide , outputProviders , itemStack , simulate )) {
122- // Handle remaining container items: place blocks and drop items
123- NonNullList <ItemStack > remainingStacks = CraftingManager .getInstance ().getRemainingItems (INVENTORY_CRAFTING , world );
143+ if (chosenPossibility != null && !itemStack .isEmpty ()
144+ && addItemStackForOutput (world , targetPos , targetSide , outputProviders , itemStack , simulate )) {
145+ chosenPossibility .handleRemainingItems (world , inputSide , simulate );
146+ return true ;
147+ }
148+ return false ;
149+ }
150+
151+ public static WorldCraftingMatrix deriveMatrix (World world , BlockPos centerPos ) {
152+ EnumFacing side = (world .getBlockState (centerPos ).getValue (BlockStructuredCrafter .FACING )).getOpposite ();
153+ return new WorldCraftingMatrix (world , centerPos .offset (side ), side .getAxis (),
154+ centerPos .offset (side .getOpposite ()), side .getOpposite ());
155+ }
156+
157+ public static class CraftingPossibility {
158+ private final WorldInventoryCrafting inventoryCrafting = new WorldInventoryCrafting ();
159+ private final BlockPos [] positions = new BlockPos [9 ];
160+ private final IItemStackProvider [] providers = new IItemStackProvider [9 ];
161+
162+ public CraftingPossibility () {
163+
164+ }
165+
166+ public void setPosition (int i , int j , int rotation , BlockPos pos , IItemStackProvider itemStackProvider , ItemStack itemStack ) {
167+ int arrayIndex = (j + 1 ) * 3 + (i + 1 );
168+ // This makes sure we can also accept recipes which are rotated, mirroring is already supported by Vanilla.
169+ if (rotation == 0 ) {
170+ inventoryCrafting .setItemStack (i + 1 , j + 1 , itemStack );
171+ } else if (rotation == 1 ) {
172+ inventoryCrafting .setItemStack (j + 1 , i + 1 , itemStack );
173+ } else if (rotation == 2 ) {
174+ inventoryCrafting .setItemStack (i + 1 , 2 - (j + 1 ), itemStack );
175+ }
176+ positions [arrayIndex ] = pos ;
177+ providers [arrayIndex ] = itemStackProvider ;
178+ }
179+
180+ public ItemStack getOutput (World world ) {
181+ return CraftingManager .getInstance ().findMatchingRecipe (inventoryCrafting , world );
182+ }
183+
184+ /**
185+ * Handle remaining container items: place blocks and drop items
186+ * @param world The world.
187+ * @param inputSide The crafting side.
188+ * @param simulate If the crafting should be simulated.
189+ */
190+ public void handleRemainingItems (World world , EnumFacing inputSide , boolean simulate ) {
191+ NonNullList <ItemStack > remainingStacks = CraftingManager .getInstance ().getRemainingItems (inventoryCrafting , world );
124192 for (int i = 0 ; i < remainingStacks .size (); i ++) {
125193 ItemStack remainingStack = remainingStacks .get (i );
126194 if (providers [i ] != null ) {
@@ -130,15 +198,17 @@ public boolean craft(boolean simulate) {
130198 }
131199 }
132200 }
133- return true ;
134201 }
135- return false ;
136- }
137202
138- public static WorldCraftingMatrix deriveMatrix (World world , BlockPos centerPos ) {
139- EnumFacing side = (world .getBlockState (centerPos ).getValue (BlockStructuredCrafter .FACING )).getOpposite ();
140- return new WorldCraftingMatrix (world , centerPos .offset (side ), side .getAxis (),
141- centerPos .offset (side .getOpposite ()), side .getOpposite ());
203+ public CraftingPossibility clone () {
204+ CraftingPossibility craftingPossibility = new CraftingPossibility ();
205+ for (int i = 0 ; i < this .inventoryCrafting .getSizeInventory (); i ++) {
206+ craftingPossibility .inventoryCrafting .setInventorySlotContents (i , this .inventoryCrafting .getStackInSlot (i ));
207+ }
208+ System .arraycopy (this .positions , 0 , craftingPossibility .positions , 0 , this .positions .length );
209+ System .arraycopy (this .providers , 0 , craftingPossibility .providers , 0 , this .providers .length );
210+ return craftingPossibility ;
211+ }
142212 }
143213
144214}
0 commit comments