Skip to content

Commit 51b6a38

Browse files
committed
Fix conflicting handling of recipes that use inventories and blocks, Closes #6
Different possibilities are now checked in parallel.
1 parent 00c5136 commit 51b6a38

1 file changed

Lines changed: 105 additions & 35 deletions

File tree

src/main/java/org/cyclops/structuredcrafting/craft/WorldCraftingMatrix.java

Lines changed: 105 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.cyclops.structuredcrafting.craft;
22

33
import com.google.common.collect.Lists;
4+
import com.google.common.collect.Maps;
45
import net.minecraft.item.ItemStack;
56
import net.minecraft.item.crafting.CraftingManager;
67
import net.minecraft.util.NonNullList;
@@ -14,15 +15,14 @@
1415
import org.cyclops.structuredcrafting.craft.provider.IItemStackProviderRegistry;
1516

1617
import java.util.List;
18+
import java.util.Map;
1719

1820
/**
1921
* A crafting matrix represented with blockstates.
2022
* @author rubensworks
2123
*/
2224
public 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

Comments
 (0)