Skip to content

Commit e45d791

Browse files
committed
Merge branch 'master-1.11' into master-1.12
Conflicts: build.properties src/main/java/org/cyclops/structuredcrafting/craft/WorldCraftingMatrix.java
2 parents abb1d40 + c21c1aa commit e45d791

2 files changed

Lines changed: 113 additions & 37 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
As always, don't forget to backup your world before updating!
2+
Requires CyclopsCore version 0.10.6 or higher.
3+
4+
Fixes:
5+
* Fix conflicting handling of recipes that use inventories and blocks, Closes #6. Different possibilities are now checked in parallel.

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

Lines changed: 108 additions & 37 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.item.crafting.IRecipe;
@@ -15,15 +16,14 @@
1516
import org.cyclops.structuredcrafting.craft.provider.IItemStackProviderRegistry;
1617

1718
import java.util.List;
19+
import java.util.Map;
1820

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

Comments
 (0)