Skip to content

Commit 59a0fe5

Browse files
committed
Fix offset for recipes with reusable inputs, Closes #42
1 parent 50d5bc7 commit 59a0fe5

2 files changed

Lines changed: 186 additions & 1 deletion

File tree

loader-common/src/main/java/org/cyclops/structuredcrafting/craft/WorldCraftingMatrix.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ public boolean handleRemainingItems(Level level, Direction inputSide, boolean si
226226
int i = r * 3 + c;
227227

228228
ItemStack originalStack = inventoryCrafting.getItem(i);
229-
ItemStack remainingStack = r >= top && r < craftInput.width() && c >= left && c < craftInput.height() ? remainingStacks.get((r - top) * craftInput.height() + c - left) : ItemStack.EMPTY;
229+
ItemStack remainingStack = r >= top && r - top < craftInput.height() && c >= left && c - left < craftInput.width() ? remainingStacks.get((r - top) * craftInput.height() + c - left) : ItemStack.EMPTY;
230230
if(originalStack != null && !originalStack.isEmpty()) {
231231
if (providers[i] != null) {
232232
// Consume one item from input

loader-common/src/main/java/org/cyclops/structuredcrafting/gametest/GameTestsCommon.java

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22

33
import net.minecraft.core.BlockPos;
44
import net.minecraft.core.Direction;
5+
import net.minecraft.core.component.DataComponents;
6+
import net.minecraft.core.registries.Registries;
57
import net.minecraft.gametest.framework.GameTest;
68
import net.minecraft.gametest.framework.GameTestHelper;
79
import net.minecraft.world.InteractionHand;
810
import net.minecraft.world.entity.player.Player;
11+
import net.minecraft.world.item.DyeColor;
912
import net.minecraft.world.item.ItemStack;
1013
import net.minecraft.world.item.Items;
1114
import net.minecraft.world.level.GameType;
1215
import net.minecraft.world.level.block.Blocks;
16+
import net.minecraft.world.level.block.entity.BannerPatternLayers;
17+
import net.minecraft.world.level.block.entity.BannerPatterns;
1318
import net.minecraft.world.level.block.entity.ChestBlockEntity;
1419
import org.cyclops.structuredcrafting.Reference;
1520
import org.cyclops.structuredcrafting.RegistryEntries;
@@ -276,6 +281,186 @@ public void testCraftFromChestsToChestCakeReusable(GameTestHelper helper) {
276281
});
277282
}
278283

284+
@GameTest(template = TEMPLATE_EMPTY)
285+
public void testCraftFromChestsToChestBannerCopy1(GameTestHelper helper) {
286+
helper.setBlock(POS.offset(2, 2, 2), RegistryEntries.BLOCK_STRUCTURED_CRAFTER.value()
287+
.defaultBlockState()
288+
.setValue(BlockStructuredCrafter.FACING, Direction.NORTH));
289+
290+
ItemStack patternBanner = new ItemStack(Items.WHITE_BANNER);
291+
patternBanner.set(DataComponents.BANNER_PATTERNS, new BannerPatternLayers.Builder()
292+
.add(helper.getLevel().registryAccess().asGetterLookup().get(Registries.BANNER_PATTERN, BannerPatterns.FLOWER).get(), DyeColor.YELLOW)
293+
.build());
294+
295+
// Define inputs
296+
setChestWithItem(helper, POS.offset(3, 3, 3), new ItemStack(Items.WHITE_BANNER));
297+
setChestWithItem(helper, POS.offset(2, 3, 3), patternBanner.copy());
298+
setChestWithItem(helper, POS.offset(1, 3, 3), ItemStack.EMPTY);
299+
setChestWithItem(helper, POS.offset(3, 2, 3), ItemStack.EMPTY);
300+
setChestWithItem(helper, POS.offset(2, 2, 3), ItemStack.EMPTY);
301+
setChestWithItem(helper, POS.offset(1, 2, 3), ItemStack.EMPTY);
302+
setChestWithItem(helper, POS.offset(3, 1, 3), ItemStack.EMPTY);
303+
setChestWithItem(helper, POS.offset(2, 1, 3), ItemStack.EMPTY);
304+
setChestWithItem(helper, POS.offset(1, 1, 3), ItemStack.EMPTY);
305+
306+
// Set output chest
307+
helper.setBlock(POS.offset(2, 2, 1), Blocks.CHEST);
308+
309+
// Activate crafter
310+
helper.setBlock(POS.offset(1, 2, 2), Blocks.REDSTONE_BLOCK);
311+
312+
helper.succeedWhen(() -> {
313+
// Result
314+
assertChestContains(helper, POS.offset(2, 2, 1), patternBanner);
315+
316+
// Inputs must be consumed
317+
assertChestEmpty(helper, POS.offset(3, 3, 3));
318+
assertChestContains(helper, POS.offset(2, 3, 3), patternBanner);
319+
assertChestEmpty(helper, POS.offset(1, 3, 3));
320+
assertChestEmpty(helper, POS.offset(3, 2, 3));
321+
assertChestEmpty(helper, POS.offset(2, 2, 3));
322+
assertChestEmpty(helper, POS.offset(1, 2, 3));
323+
assertChestEmpty(helper, POS.offset(3, 1, 3));
324+
assertChestEmpty(helper, POS.offset(2, 1, 3));
325+
assertChestEmpty(helper, POS.offset(1, 1, 3));
326+
});
327+
}
328+
329+
@GameTest(template = TEMPLATE_EMPTY)
330+
public void testCraftFromChestsToChestBannerCopy2(GameTestHelper helper) {
331+
helper.setBlock(POS.offset(2, 2, 2), RegistryEntries.BLOCK_STRUCTURED_CRAFTER.value()
332+
.defaultBlockState()
333+
.setValue(BlockStructuredCrafter.FACING, Direction.NORTH));
334+
335+
ItemStack patternBanner = new ItemStack(Items.WHITE_BANNER);
336+
patternBanner.set(DataComponents.BANNER_PATTERNS, new BannerPatternLayers.Builder()
337+
.add(helper.getLevel().registryAccess().asGetterLookup().get(Registries.BANNER_PATTERN, BannerPatterns.FLOWER).get(), DyeColor.YELLOW)
338+
.build());
339+
340+
// Define inputs
341+
setChestWithItem(helper, POS.offset(3, 3, 3), ItemStack.EMPTY);
342+
setChestWithItem(helper, POS.offset(2, 3, 3), ItemStack.EMPTY);
343+
setChestWithItem(helper, POS.offset(1, 3, 3), ItemStack.EMPTY);
344+
setChestWithItem(helper, POS.offset(3, 2, 3), new ItemStack(Items.WHITE_BANNER));
345+
setChestWithItem(helper, POS.offset(2, 2, 3), patternBanner.copy());
346+
setChestWithItem(helper, POS.offset(1, 2, 3), ItemStack.EMPTY);
347+
setChestWithItem(helper, POS.offset(3, 1, 3), ItemStack.EMPTY);
348+
setChestWithItem(helper, POS.offset(2, 1, 3), ItemStack.EMPTY);
349+
setChestWithItem(helper, POS.offset(1, 1, 3), ItemStack.EMPTY);
350+
351+
// Set output chest
352+
helper.setBlock(POS.offset(2, 2, 1), Blocks.CHEST);
353+
354+
// Activate crafter
355+
helper.setBlock(POS.offset(1, 2, 2), Blocks.REDSTONE_BLOCK);
356+
357+
helper.succeedWhen(() -> {
358+
// Result
359+
assertChestContains(helper, POS.offset(2, 2, 1), patternBanner);
360+
361+
// Inputs must be consumed
362+
assertChestEmpty(helper, POS.offset(3, 3, 3));
363+
assertChestEmpty(helper, POS.offset(2, 3, 3));
364+
assertChestEmpty(helper, POS.offset(1, 3, 3));
365+
assertChestEmpty(helper, POS.offset(3, 2, 3));
366+
assertChestContains(helper, POS.offset(2, 2, 3), patternBanner);
367+
assertChestEmpty(helper, POS.offset(1, 2, 3));
368+
assertChestEmpty(helper, POS.offset(3, 1, 3));
369+
assertChestEmpty(helper, POS.offset(2, 1, 3));
370+
assertChestEmpty(helper, POS.offset(1, 1, 3));
371+
});
372+
}
373+
374+
@GameTest(template = TEMPLATE_EMPTY)
375+
public void testCraftFromChestsToChestBannerCopy3(GameTestHelper helper) {
376+
helper.setBlock(POS.offset(2, 2, 2), RegistryEntries.BLOCK_STRUCTURED_CRAFTER.value()
377+
.defaultBlockState()
378+
.setValue(BlockStructuredCrafter.FACING, Direction.NORTH));
379+
380+
ItemStack patternBanner = new ItemStack(Items.WHITE_BANNER);
381+
patternBanner.set(DataComponents.BANNER_PATTERNS, new BannerPatternLayers.Builder()
382+
.add(helper.getLevel().registryAccess().asGetterLookup().get(Registries.BANNER_PATTERN, BannerPatterns.FLOWER).get(), DyeColor.YELLOW)
383+
.build());
384+
385+
// Define inputs
386+
setChestWithItem(helper, POS.offset(3, 3, 3), ItemStack.EMPTY);
387+
setChestWithItem(helper, POS.offset(2, 3, 3), ItemStack.EMPTY);
388+
setChestWithItem(helper, POS.offset(1, 3, 3), ItemStack.EMPTY);
389+
setChestWithItem(helper, POS.offset(3, 2, 3), ItemStack.EMPTY);
390+
setChestWithItem(helper, POS.offset(2, 2, 3), ItemStack.EMPTY);
391+
setChestWithItem(helper, POS.offset(1, 2, 3), ItemStack.EMPTY);
392+
setChestWithItem(helper, POS.offset(3, 1, 3), new ItemStack(Items.WHITE_BANNER));
393+
setChestWithItem(helper, POS.offset(2, 1, 3), patternBanner.copy());
394+
setChestWithItem(helper, POS.offset(1, 1, 3), ItemStack.EMPTY);
395+
396+
// Set output chest
397+
helper.setBlock(POS.offset(2, 2, 1), Blocks.CHEST);
398+
399+
// Activate crafter
400+
helper.setBlock(POS.offset(1, 2, 2), Blocks.REDSTONE_BLOCK);
401+
402+
helper.succeedWhen(() -> {
403+
// Result
404+
assertChestContains(helper, POS.offset(2, 2, 1), patternBanner);
405+
406+
// Inputs must be consumed
407+
assertChestEmpty(helper, POS.offset(3, 3, 3));
408+
assertChestEmpty(helper, POS.offset(2, 3, 3));
409+
assertChestEmpty(helper, POS.offset(1, 3, 3));
410+
assertChestEmpty(helper, POS.offset(3, 2, 3));
411+
assertChestEmpty(helper, POS.offset(2, 2, 3));
412+
assertChestEmpty(helper, POS.offset(1, 2, 3));
413+
assertChestEmpty(helper, POS.offset(3, 1, 3));
414+
assertChestContains(helper, POS.offset(2, 1, 3), patternBanner);
415+
assertChestEmpty(helper, POS.offset(1, 1, 3));
416+
});
417+
}
418+
419+
@GameTest(template = TEMPLATE_EMPTY)
420+
public void testCraftFromChestsToChestBannerCopy4(GameTestHelper helper) {
421+
helper.setBlock(POS.offset(2, 2, 2), RegistryEntries.BLOCK_STRUCTURED_CRAFTER.value()
422+
.defaultBlockState()
423+
.setValue(BlockStructuredCrafter.FACING, Direction.NORTH));
424+
425+
ItemStack patternBanner = new ItemStack(Items.WHITE_BANNER);
426+
patternBanner.set(DataComponents.BANNER_PATTERNS, new BannerPatternLayers.Builder()
427+
.add(helper.getLevel().registryAccess().asGetterLookup().get(Registries.BANNER_PATTERN, BannerPatterns.FLOWER).get(), DyeColor.YELLOW)
428+
.build());
429+
430+
// Define inputs
431+
setChestWithItem(helper, POS.offset(3, 3, 3), ItemStack.EMPTY);
432+
setChestWithItem(helper, POS.offset(2, 3, 3), ItemStack.EMPTY);
433+
setChestWithItem(helper, POS.offset(1, 3, 3), ItemStack.EMPTY);
434+
setChestWithItem(helper, POS.offset(3, 2, 3), ItemStack.EMPTY);
435+
setChestWithItem(helper, POS.offset(2, 2, 3), ItemStack.EMPTY);
436+
setChestWithItem(helper, POS.offset(1, 2, 3), ItemStack.EMPTY);
437+
setChestWithItem(helper, POS.offset(3, 1, 3), ItemStack.EMPTY);
438+
setChestWithItem(helper, POS.offset(2, 1, 3), new ItemStack(Items.WHITE_BANNER));
439+
setChestWithItem(helper, POS.offset(1, 1, 3), patternBanner.copy());
440+
441+
// Set output chest
442+
helper.setBlock(POS.offset(2, 2, 1), Blocks.CHEST);
443+
444+
// Activate crafter
445+
helper.setBlock(POS.offset(1, 2, 2), Blocks.REDSTONE_BLOCK);
446+
447+
helper.succeedWhen(() -> {
448+
// Result
449+
assertChestContains(helper, POS.offset(2, 2, 1), patternBanner);
450+
451+
// Inputs must be consumed
452+
assertChestEmpty(helper, POS.offset(3, 3, 3));
453+
assertChestEmpty(helper, POS.offset(2, 3, 3));
454+
assertChestEmpty(helper, POS.offset(1, 3, 3));
455+
assertChestEmpty(helper, POS.offset(3, 2, 3));
456+
assertChestEmpty(helper, POS.offset(2, 2, 3));
457+
assertChestEmpty(helper, POS.offset(1, 2, 3));
458+
assertChestEmpty(helper, POS.offset(3, 1, 3));
459+
assertChestEmpty(helper, POS.offset(2, 1, 3));
460+
assertChestContains(helper, POS.offset(1, 1, 3), patternBanner);
461+
});
462+
}
463+
279464
protected void setChestWithItem(GameTestHelper helper, BlockPos pos, ItemStack itemStack) {
280465
helper.setBlock(pos, Blocks.CHEST);
281466
ChestBlockEntity chest = helper.getBlockEntity(pos);

0 commit comments

Comments
 (0)