mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-04-15 07:13:13 +00:00
Create a new CraftingInput for each craft
It's not actually safe to reuse this, as we need to recompute the internal StackedContents each time the inventory changes, otherwise ShapelessRecipe.matches will continue to return true, even if the actual inventory doesn't include the required items. Fixes #2094
This commit is contained in:
parent
9bb62b047a
commit
74f707aaea
@ -39,7 +39,7 @@ public final class TurtleInventoryCrafting {
|
||||
}
|
||||
}
|
||||
|
||||
var input = CraftingInput.ofPositioned(WIDTH, HEIGHT, new AbstractList<>() {
|
||||
List<ItemStack> items = new AbstractList<>() {
|
||||
@Override
|
||||
public ItemStack get(int index) {
|
||||
var x = xStart + index % WIDTH;
|
||||
@ -53,9 +53,10 @@ public final class TurtleInventoryCrafting {
|
||||
public int size() {
|
||||
return WIDTH * HEIGHT;
|
||||
}
|
||||
});
|
||||
var recipe = level.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, input.input(), level).orElse(null);
|
||||
return recipe == null ? null : new FoundRecipe(recipe.value(), input.input(), input.left() + xStart, input.top() + yStart);
|
||||
};
|
||||
var input = CraftingInput.of(WIDTH, HEIGHT, items);
|
||||
var recipe = level.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, input, level).orElse(null);
|
||||
return recipe == null ? null : new FoundRecipe(recipe.value(), items, xStart, yStart);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -76,18 +77,24 @@ public final class TurtleInventoryCrafting {
|
||||
if (maxCount == 0) return List.of();
|
||||
|
||||
var recipe = candidate.recipe();
|
||||
var input = candidate.input();
|
||||
var xStart = candidate.xStart();
|
||||
var yStart = candidate.yStart();
|
||||
var items = candidate.items();
|
||||
|
||||
var results = new ArrayList<ItemStack>();
|
||||
for (var i = 0; i < maxCount && recipe.matches(input, level); i++) {
|
||||
for (var i = 0; i < maxCount; i++) {
|
||||
var offsetInput = CraftingInput.ofPositioned(WIDTH, HEIGHT, items);
|
||||
var input = offsetInput.input();
|
||||
|
||||
if (!recipe.matches(input, level)) break;
|
||||
|
||||
var result = recipe.assemble(input, level.registryAccess());
|
||||
if (result.isEmpty()) break;
|
||||
results.add(result);
|
||||
|
||||
result.onCraftedBySystem(level);
|
||||
|
||||
// Remove items from the inventory, and add back the remainders.
|
||||
var xStart = candidate.xStart() + offsetInput.left();
|
||||
var yStart = candidate.yStart() + offsetInput.top();
|
||||
var remainders = recipe.getRemainingItems(input);
|
||||
for (var y = 0; y < input.height(); y++) {
|
||||
for (var x = 0; x < input.width(); x++) {
|
||||
@ -118,6 +125,6 @@ public final class TurtleInventoryCrafting {
|
||||
return Collections.unmodifiableList(results);
|
||||
}
|
||||
|
||||
private record FoundRecipe(Recipe<CraftingInput> recipe, CraftingInput input, int xStart, int yStart) {
|
||||
private record FoundRecipe(Recipe<CraftingInput> recipe, List<ItemStack> items, int xStart, int yStart) {
|
||||
}
|
||||
}
|
||||
|
@ -835,6 +835,29 @@ class Turtle_Test {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `turtle.craft` works on shapeless recipes
|
||||
*
|
||||
* @see [#2094](https://github.com/cc-tweaked/CC-Tweaked/issues/2094)
|
||||
*/
|
||||
@GameTest
|
||||
fun Craft_shapeless(helper: GameTestHelper) = helper.sequence {
|
||||
thenExecute {
|
||||
val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get())
|
||||
assertTrue(TurtleCraftCommand(64).execute(turtle.access).isSuccess, "Crafting succeeded")
|
||||
|
||||
helper.assertContainerExactly(
|
||||
BlockPos(2, 2, 2),
|
||||
listOf(
|
||||
ItemStack(Items.ENDER_EYE, 1), ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY,
|
||||
ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY,
|
||||
ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY,
|
||||
ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY, ItemStack.EMPTY,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `turtle.craft` leaves a remainder
|
||||
*
|
||||
|
137
projects/common/src/testMod/resources/data/cctest/structures/turtle_test.craft_shapeless.snbt
generated
Normal file
137
projects/common/src/testMod/resources/data/cctest/structures/turtle_test.craft_shapeless.snbt
generated
Normal file
@ -0,0 +1,137 @@
|
||||
{
|
||||
DataVersion: 3465,
|
||||
size: [5, 5, 5],
|
||||
data: [
|
||||
{pos: [0, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [1, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [2, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [3, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 0], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 1], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 2], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 3], state: "minecraft:polished_andesite"},
|
||||
{pos: [4, 0, 4], state: "minecraft:polished_andesite"},
|
||||
{pos: [0, 1, 0], state: "minecraft:air"},
|
||||
{pos: [0, 1, 1], state: "minecraft:air"},
|
||||
{pos: [0, 1, 2], state: "minecraft:air"},
|
||||
{pos: [0, 1, 3], state: "minecraft:air"},
|
||||
{pos: [0, 1, 4], state: "minecraft:air"},
|
||||
{pos: [1, 1, 0], state: "minecraft:air"},
|
||||
{pos: [1, 1, 1], state: "minecraft:air"},
|
||||
{pos: [1, 1, 2], state: "minecraft:air"},
|
||||
{pos: [1, 1, 3], state: "minecraft:air"},
|
||||
{pos: [1, 1, 4], state: "minecraft:air"},
|
||||
{pos: [2, 1, 0], state: "minecraft:air"},
|
||||
{pos: [2, 1, 1], state: "minecraft:air"},
|
||||
{pos: [2, 1, 2], state: "computercraft:turtle_normal{facing:north,waterlogged:false}", nbt: {ComputerId: 1, Fuel: 0, Items: [{Count: 1b, Slot: 0b, id: "minecraft:ender_pearl"}, {Count: 1b, Slot: 1b, id: "minecraft:blaze_powder"}], Label: "turtle_test.craft_shapeless", LeftUpgrade: "minecraft:crafting_table", LeftUpgradeNbt: {}, On: 1b, Slot: 0, id: "computercraft:turtle_normal"}},
|
||||
{pos: [2, 1, 3], state: "minecraft:air"},
|
||||
{pos: [2, 1, 4], state: "minecraft:air"},
|
||||
{pos: [3, 1, 0], state: "minecraft:air"},
|
||||
{pos: [3, 1, 1], state: "minecraft:air"},
|
||||
{pos: [3, 1, 2], state: "minecraft:air"},
|
||||
{pos: [3, 1, 3], state: "minecraft:air"},
|
||||
{pos: [3, 1, 4], state: "minecraft:air"},
|
||||
{pos: [4, 1, 0], state: "minecraft:air"},
|
||||
{pos: [4, 1, 1], state: "minecraft:air"},
|
||||
{pos: [4, 1, 2], state: "minecraft:air"},
|
||||
{pos: [4, 1, 3], state: "minecraft:air"},
|
||||
{pos: [4, 1, 4], state: "minecraft:air"},
|
||||
{pos: [0, 2, 0], state: "minecraft:air"},
|
||||
{pos: [0, 2, 1], state: "minecraft:air"},
|
||||
{pos: [0, 2, 2], state: "minecraft:air"},
|
||||
{pos: [0, 2, 3], state: "minecraft:air"},
|
||||
{pos: [0, 2, 4], state: "minecraft:air"},
|
||||
{pos: [1, 2, 0], state: "minecraft:air"},
|
||||
{pos: [1, 2, 1], state: "minecraft:air"},
|
||||
{pos: [1, 2, 2], state: "minecraft:air"},
|
||||
{pos: [1, 2, 3], state: "minecraft:air"},
|
||||
{pos: [1, 2, 4], state: "minecraft:air"},
|
||||
{pos: [2, 2, 0], state: "minecraft:air"},
|
||||
{pos: [2, 2, 1], state: "minecraft:air"},
|
||||
{pos: [2, 2, 2], state: "minecraft:air"},
|
||||
{pos: [2, 2, 3], state: "minecraft:air"},
|
||||
{pos: [2, 2, 4], state: "minecraft:air"},
|
||||
{pos: [3, 2, 0], state: "minecraft:air"},
|
||||
{pos: [3, 2, 1], state: "minecraft:air"},
|
||||
{pos: [3, 2, 2], state: "minecraft:air"},
|
||||
{pos: [3, 2, 3], state: "minecraft:air"},
|
||||
{pos: [3, 2, 4], state: "minecraft:air"},
|
||||
{pos: [4, 2, 0], state: "minecraft:air"},
|
||||
{pos: [4, 2, 1], state: "minecraft:air"},
|
||||
{pos: [4, 2, 2], state: "minecraft:air"},
|
||||
{pos: [4, 2, 3], state: "minecraft:air"},
|
||||
{pos: [4, 2, 4], state: "minecraft:air"},
|
||||
{pos: [0, 3, 0], state: "minecraft:air"},
|
||||
{pos: [0, 3, 1], state: "minecraft:air"},
|
||||
{pos: [0, 3, 2], state: "minecraft:air"},
|
||||
{pos: [0, 3, 3], state: "minecraft:air"},
|
||||
{pos: [0, 3, 4], state: "minecraft:air"},
|
||||
{pos: [1, 3, 0], state: "minecraft:air"},
|
||||
{pos: [1, 3, 1], state: "minecraft:air"},
|
||||
{pos: [1, 3, 2], state: "minecraft:air"},
|
||||
{pos: [1, 3, 3], state: "minecraft:air"},
|
||||
{pos: [1, 3, 4], state: "minecraft:air"},
|
||||
{pos: [2, 3, 0], state: "minecraft:air"},
|
||||
{pos: [2, 3, 1], state: "minecraft:air"},
|
||||
{pos: [2, 3, 2], state: "minecraft:air"},
|
||||
{pos: [2, 3, 3], state: "minecraft:air"},
|
||||
{pos: [2, 3, 4], state: "minecraft:air"},
|
||||
{pos: [3, 3, 0], state: "minecraft:air"},
|
||||
{pos: [3, 3, 1], state: "minecraft:air"},
|
||||
{pos: [3, 3, 2], state: "minecraft:air"},
|
||||
{pos: [3, 3, 3], state: "minecraft:air"},
|
||||
{pos: [3, 3, 4], state: "minecraft:air"},
|
||||
{pos: [4, 3, 0], state: "minecraft:air"},
|
||||
{pos: [4, 3, 1], state: "minecraft:air"},
|
||||
{pos: [4, 3, 2], state: "minecraft:air"},
|
||||
{pos: [4, 3, 3], state: "minecraft:air"},
|
||||
{pos: [4, 3, 4], state: "minecraft:air"},
|
||||
{pos: [0, 4, 0], state: "minecraft:air"},
|
||||
{pos: [0, 4, 1], state: "minecraft:air"},
|
||||
{pos: [0, 4, 2], state: "minecraft:air"},
|
||||
{pos: [0, 4, 3], state: "minecraft:air"},
|
||||
{pos: [0, 4, 4], state: "minecraft:air"},
|
||||
{pos: [1, 4, 0], state: "minecraft:air"},
|
||||
{pos: [1, 4, 1], state: "minecraft:air"},
|
||||
{pos: [1, 4, 2], state: "minecraft:air"},
|
||||
{pos: [1, 4, 3], state: "minecraft:air"},
|
||||
{pos: [1, 4, 4], state: "minecraft:air"},
|
||||
{pos: [2, 4, 0], state: "minecraft:air"},
|
||||
{pos: [2, 4, 1], state: "minecraft:air"},
|
||||
{pos: [2, 4, 2], state: "minecraft:air"},
|
||||
{pos: [2, 4, 3], state: "minecraft:air"},
|
||||
{pos: [2, 4, 4], state: "minecraft:air"},
|
||||
{pos: [3, 4, 0], state: "minecraft:air"},
|
||||
{pos: [3, 4, 1], state: "minecraft:air"},
|
||||
{pos: [3, 4, 2], state: "minecraft:air"},
|
||||
{pos: [3, 4, 3], state: "minecraft:air"},
|
||||
{pos: [3, 4, 4], state: "minecraft:air"},
|
||||
{pos: [4, 4, 0], state: "minecraft:air"},
|
||||
{pos: [4, 4, 1], state: "minecraft:air"},
|
||||
{pos: [4, 4, 2], state: "minecraft:air"},
|
||||
{pos: [4, 4, 3], state: "minecraft:air"},
|
||||
{pos: [4, 4, 4], state: "minecraft:air"}
|
||||
],
|
||||
entities: [],
|
||||
palette: [
|
||||
"minecraft:polished_andesite",
|
||||
"minecraft:air",
|
||||
"computercraft:turtle_normal{facing:north,waterlogged:false}"
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user