Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fab52cc
Start migrating actions to use context parameters
ErrorCraft Mar 13, 2026
993e401
Migrate the sequence action
ErrorCraft Mar 13, 2026
3a09a6a
Migrate the damage_item action
ErrorCraft Mar 15, 2026
0cba404
Migrate the prime_tnt action
ErrorCraft Mar 15, 2026
e9262b2
Migrate more actions
ErrorCraft Mar 15, 2026
7cb5e96
Migrate even more actions
ErrorCraft Mar 16, 2026
aa0617a
Migrate more actions
ErrorCraft Mar 17, 2026
d524027
Migrate the remaining actions
ErrorCraft Mar 20, 2026
fb7d665
Add a position target to the location_check predicate
ErrorCraft Mar 20, 2026
0ee6286
Use ItemStackExchanger for more dynamic results
ErrorCraft Mar 21, 2026
df3d3e3
Remove the previous action execute method
ErrorCraft Mar 21, 2026
fe30bc1
Add the dispensed item and block entity to dispense actions
ErrorCraft Mar 22, 2026
88d69be
Move away from entity initialisers in item behaviour and actions
ErrorCraft Mar 23, 2026
cdcfee3
Fix the bugs for the remaining game tests
ErrorCraft Mar 23, 2026
c3f3276
Add a predicate to item stack exchangers
ErrorCraft Mar 23, 2026
03944a6
Start cleaning up
ErrorCraft Mar 24, 2026
0d6531f
Add a few more game tests related to placement
ErrorCraft Mar 25, 2026
b3308a1
Rename interacted_position position target to interacted
ErrorCraft Mar 25, 2026
9f68242
More cleanup
ErrorCraft Mar 25, 2026
c9a6ee2
Add optional entity and position targets to the run_function action
ErrorCraft Mar 25, 2026
02542b5
Return false if the position is not found in the wax_block action
ErrorCraft Mar 25, 2026
227781d
Correct the item field name in the exchange_item action
ErrorCraft Mar 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package net.errorcraft.itematic.gametest.item.component;

import net.errorcraft.itematic.gametest.Assert;
import net.errorcraft.itematic.gametest.TestUtil;
import net.errorcraft.itematic.item.ItemKeys;
import net.minecraft.block.Blocks;
import net.minecraft.command.argument.EntityAnchorArgumentType;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.test.GameTest;
import net.minecraft.test.GameTestException;
import net.minecraft.test.TestContext;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameMode;

public class BucketItemComponentTestSuite {
private static final BlockPos SPAWN_POSITION = new BlockPos(1, 2, 0);
private static final BlockPos FACE_POSITION = new BlockPos(1, 1, 1);
private static final BlockPos PLACED_POSITION = FACE_POSITION;

@GameTest(templateName = "itematic:item.component.bucket.platform.water")
public void usingBucketOnWaterTakesWaterAndGivesWaterBucket(TestContext context) {
ServerWorld world = context.getWorld();
ItemStack stack = world.itematic$createStack(ItemKeys.BUCKET);
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
TestUtil.setEntityPos(context, player, SPAWN_POSITION);
player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION)));
player.setStackInHand(Hand.MAIN_HAND, stack);
world.spawnEntity(player);
ActionResult result = stack.use(world, player, Hand.MAIN_HAND);
context.addInstantFinalTask(() -> {
Assert.fluidIsOf(context, Fluids.EMPTY, PLACED_POSITION);
if (!(result instanceof ActionResult.Success successResult)) {
throw new GameTestException("Expected bucket usage to be successful");
}

Assert.itemStackIsOf(successResult.getNewHandStack(), ItemKeys.WATER_BUCKET);
});
}

@GameTest(templateName = "itematic:item.component.bucket.platform.powder_snow")
public void usingBucketOnPowderSnowTakesWaterAndGivesPowderSnowBucket(TestContext context) {
ServerWorld world = context.getWorld();
ItemStack stack = world.itematic$createStack(ItemKeys.BUCKET);
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
TestUtil.setEntityPos(context, player, SPAWN_POSITION);
player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION)));
player.setStackInHand(Hand.MAIN_HAND, stack);
world.spawnEntity(player);
ActionResult result = stack.use(world, player, Hand.MAIN_HAND);
context.addInstantFinalTask(() -> {
Assert.fluidIsOf(context, Fluids.EMPTY, PLACED_POSITION);
if (!(result instanceof ActionResult.Success successResult)) {
throw new GameTestException("Expected bucket usage to be successful");
}

Assert.itemStackIsOf(successResult.getNewHandStack(), ItemKeys.POWDER_SNOW_BUCKET);
});
}

@GameTest(templateName = "itematic:item.component.bucket.platform")
public void usingWaterBucketOnGroundPlacesWater(TestContext context) {
ServerWorld world = context.getWorld();
ItemStack stack = world.itematic$createStack(ItemKeys.WATER_BUCKET);
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
TestUtil.setEntityPos(context, player, SPAWN_POSITION);
player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION)));
player.setStackInHand(Hand.MAIN_HAND, stack);
world.spawnEntity(player);
stack.use(world, player, Hand.MAIN_HAND);
context.addInstantFinalTask(() -> Assert.fluidIsOf(context, Fluids.WATER, PLACED_POSITION));
}

@GameTest(templateName = "itematic:item.component.bucket.platform")
public void usingPowderSnowBucketOnGroundPlacesPowderSnow(TestContext context) {
ServerWorld world = context.getWorld();
ItemStack stack = world.itematic$createStack(ItemKeys.POWDER_SNOW_BUCKET);
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
TestUtil.setEntityPos(context, player, SPAWN_POSITION);
player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION)));
player.setStackInHand(Hand.MAIN_HAND, stack);
world.spawnEntity(player);
stack.use(world, player, Hand.MAIN_HAND);
context.addInstantFinalTask(() -> context.expectBlock(Blocks.POWDER_SNOW, PLACED_POSITION));
}

@GameTest(templateName = "itematic:item.component.bucket.platform")
public void usingPufferfishBucketOnGroundPlacesWaterAndPufferfish(TestContext context) {
ServerWorld world = context.getWorld();
ItemStack stack = world.itematic$createStack(ItemKeys.PUFFERFISH_BUCKET);
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
TestUtil.setEntityPos(context, player, SPAWN_POSITION);
player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, Vec3d.ofBottomCenter(context.getAbsolutePos(FACE_POSITION)));
player.setStackInHand(Hand.MAIN_HAND, stack);
world.spawnEntity(player);
stack.use(world, player, Hand.MAIN_HAND);
context.addInstantFinalTask(() -> {
Assert.fluidIsOf(context, Fluids.WATER, PLACED_POSITION);
context.expectEntityAt(EntityType.PUFFERFISH, PLACED_POSITION);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package net.errorcraft.itematic.gametest.item.component;

import net.errorcraft.itematic.gametest.TestUtil;
import net.errorcraft.itematic.item.ItemKeys;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.test.GameTest;
import net.minecraft.test.TestContext;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.GameMode;

public class EntityItemComponentTestSuite {
private static final BlockPos GROUND_POSITION = new BlockPos(1, 0, 0);
private static final BlockPos PLACED_ENTITY_POSITION = GROUND_POSITION.add(0, 1, 0);

@GameTest(templateName = "itematic:item.component.entity.platform")
public void usingOakBoatOnGroundPlacesOakBoat(TestContext context) {
ServerWorld world = context.getWorld();
ItemStack stack = world.itematic$createStack(ItemKeys.OAK_BOAT);
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
player.setStackInHand(Hand.MAIN_HAND, stack);
world.spawnEntity(player);
TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP);
context.addInstantFinalTask(() -> context.expectEntityAt(EntityType.OAK_BOAT, PLACED_ENTITY_POSITION));
}

@GameTest(templateName = "itematic:item.component.entity.platform")
public void usingPigSpawnEggOnGroundPlacesPig(TestContext context) {
ServerWorld world = context.getWorld();
ItemStack stack = world.itematic$createStack(ItemKeys.PIG_SPAWN_EGG);
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
player.setStackInHand(Hand.MAIN_HAND, stack);
world.spawnEntity(player);
TestUtil.useStackOnBlockInside(context, player, stack, GROUND_POSITION, Direction.UP);
context.addInstantFinalTask(() -> context.expectEntityAt(EntityType.PIG, PLACED_ENTITY_POSITION));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import net.errorcraft.itematic.gametest.Assert;
import net.errorcraft.itematic.gametest.TestUtil;
import net.errorcraft.itematic.inventory.StackReferenceUtil;
import net.errorcraft.itematic.inventory.SimpleStackReference;
import net.errorcraft.itematic.item.ItemKeys;
import net.errorcraft.itematic.item.component.ItemComponentTypes;
import net.fabricmc.fabric.api.gametest.v1.FabricGameTest;
Expand All @@ -29,15 +29,15 @@ public void rightClickingOnStackWithItemHolderAddsStackToItemHolder(TestContext
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
ServerWorld world = context.getWorld();
PlayerInventory inventory = player.getInventory();
ItemStack stack = world.itematic$createStack(ItemKeys.BUNDLE);
ItemStack bundle = world.itematic$createStack(ItemKeys.BUNDLE);
inventory.insertStack(SLOT, world.itematic$createStack(ItemKeys.STICK));
Slot slot = new Slot(inventory, SLOT, 0, 0);
world.spawnEntity(player);
boolean success = stack.onStackClicked(slot, ClickType.RIGHT, player);
boolean success = bundle.onStackClicked(slot, ClickType.RIGHT, player);
context.addInstantFinalTask(() -> {
context.assertTrue(success, "Expected right clicking with item holder to be successful");
Assert.itemStackIsEmpty(inventory.getStack(SLOT));
Assert.itemStackHasDataComponent(stack, DataComponentTypes.BUNDLE_CONTENTS,
Assert.itemStackHasDataComponent(bundle, DataComponentTypes.BUNDLE_CONTENTS,
component -> Assert.itemStackIsOf(component.get(0), ItemKeys.STICK)
);
});
Expand All @@ -48,16 +48,16 @@ public void rightClickingOnEmptySlotPlacesLastStackFromItemHolderInSlot(TestCont
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
ServerWorld world = context.getWorld();
PlayerInventory inventory = player.getInventory();
ItemStack stack = world.itematic$createStack(ItemKeys.BUNDLE);
ItemStack bundle = world.itematic$createStack(ItemKeys.BUNDLE);
ItemStack stackToRemove = world.itematic$createStack(ItemKeys.STICK);
addToBundleContentsComponent(stack, stackToRemove);
addToBundleContentsComponent(bundle, stackToRemove);
Slot slot = new Slot(inventory, SLOT, 0, 0);
world.spawnEntity(player);
boolean success = stack.onStackClicked(slot, ClickType.RIGHT, player);
boolean success = bundle.onStackClicked(slot, ClickType.RIGHT, player);
context.addInstantFinalTask(() -> {
context.assertTrue(success, "Expected right clicking with item holder to be successful");
Assert.itemStackIsOf(inventory.getStack(SLOT), ItemKeys.STICK);
Assert.itemStackHasDataComponent(stack, DataComponentTypes.BUNDLE_CONTENTS,
Assert.itemStackHasDataComponent(bundle, DataComponentTypes.BUNDLE_CONTENTS,
component -> context.assertTrue(component.isEmpty(), "Expected item holder to be empty")
);
});
Expand All @@ -69,12 +69,12 @@ public void rightClickingOnItemHolderWithStackAddsStackToItemHolder(TestContext
ServerWorld world = context.getWorld();
PlayerInventory inventory = player.getInventory();
inventory.insertStack(SLOT, world.itematic$createStack(ItemKeys.BUNDLE));
ItemStack stack = inventory.getStack(SLOT);
ItemStack bundle = inventory.getStack(SLOT);
ItemStack stackToAdd = world.itematic$createStack(ItemKeys.STICK);
StackReference cursorStack = StackReferenceUtil.of(stackToAdd);
StackReference cursorStack = SimpleStackReference.of(stackToAdd);
Slot slot = new Slot(inventory, SLOT, 0, 0);
world.spawnEntity(player);
boolean success = stack.onClicked(stackToAdd, slot, ClickType.RIGHT, player, cursorStack);
boolean success = bundle.onClicked(stackToAdd, slot, ClickType.RIGHT, player, cursorStack);
context.addInstantFinalTask(() -> {
context.assertTrue(success, "Expected right clicking on item holder to be successful");
Assert.itemStackIsEmpty(cursorStack.get());
Expand All @@ -89,15 +89,14 @@ public void rightClickingOnItemHolderRemovesStackFromItemHolder(TestContext cont
PlayerEntity player = context.createMockPlayer(GameMode.SURVIVAL);
ServerWorld world = context.getWorld();
PlayerInventory inventory = player.getInventory();
ItemStack stack = world.itematic$createStack(ItemKeys.BUNDLE);
inventory.insertStack(SLOT, world.itematic$createStack(ItemKeys.BUNDLE));
ItemStack bundle = inventory.getStack(SLOT);
ItemStack stackToRemove = world.itematic$createStack(ItemKeys.STICK);
addToBundleContentsComponent(stack, stackToRemove);
inventory.insertStack(SLOT, stack);
stack = inventory.getStack(SLOT);
StackReference cursorStack = StackReferenceUtil.of(ItemStack.EMPTY);
addToBundleContentsComponent(bundle, stackToRemove);
StackReference cursorStack = SimpleStackReference.of(ItemStack.EMPTY);
Slot slot = new Slot(inventory, SLOT, 0, 0);
world.spawnEntity(player);
boolean success = stack.onClicked(ItemStack.EMPTY, slot, ClickType.RIGHT, player, cursorStack);
boolean success = bundle.onClicked(ItemStack.EMPTY, slot, ClickType.RIGHT, player, cursorStack);
context.addInstantFinalTask(() -> {
context.assertTrue(success, "Expected right clicking on item holder to be successful");
Assert.itemStackIsOf(cursorStack.get(), ItemKeys.STICK);
Expand All @@ -107,11 +106,11 @@ public void rightClickingOnItemHolderRemovesStackFromItemHolder(TestContext cont
});
}

private static void addToBundleContentsComponent(ItemStack origin, ItemStack stackToAdd) {
private static void addToBundleContentsComponent(ItemStack bundle, ItemStack stackToAdd) {
BundleContentsComponent.Builder builder = Objects.requireNonNull(
TestUtil.getItemBehavior(origin, ItemComponentTypes.ITEM_HOLDER).createBuilder(origin)
TestUtil.getItemBehavior(bundle, ItemComponentTypes.ITEM_HOLDER).createBuilder(bundle)
);
builder.add(stackToAdd);
origin.set(DataComponentTypes.BUNDLE_CONTENTS, builder.build());
bundle.set(DataComponentTypes.BUNDLE_CONTENTS, builder.build());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
DataVersion: 3826,
size: [3, 3, 3],
DataVersion: 4189,
size: [3, 4, 3],
data: [
{pos: [0, 0, 0], state: "minecraft:bedrock"},
{pos: [0, 0, 1], state: "minecraft:bedrock"},
Expand Down Expand Up @@ -28,7 +28,16 @@
{pos: [1, 2, 2], 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, 2], 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: [1, 3, 0], state: "minecraft:air"},
{pos: [1, 3, 1], state: "minecraft:air"},
{pos: [1, 3, 2], state: "minecraft:air"},
{pos: [2, 3, 0], state: "minecraft:air"},
{pos: [2, 3, 1], state: "minecraft:air"},
{pos: [2, 3, 2], state: "minecraft:air"}
],
entities: [],
palette: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
DataVersion: 3826,
size: [3, 3, 3],
DataVersion: 4189,
size: [3, 4, 3],
data: [
{pos: [0, 0, 0], state: "minecraft:bedrock"},
{pos: [0, 0, 1], state: "minecraft:bedrock"},
Expand All @@ -11,15 +11,15 @@
{pos: [2, 0, 0], state: "minecraft:bedrock"},
{pos: [2, 0, 1], state: "minecraft:bedrock"},
{pos: [2, 0, 2], state: "minecraft:bedrock"},
{pos: [0, 1, 0], state: "minecraft:air"},
{pos: [0, 1, 1], state: "minecraft:air"},
{pos: [0, 1, 2], state: "minecraft:air"},
{pos: [1, 1, 0], state: "minecraft:air"},
{pos: [0, 1, 0], state: "minecraft:bedrock"},
{pos: [0, 1, 1], state: "minecraft:bedrock"},
{pos: [0, 1, 2], state: "minecraft:bedrock"},
{pos: [1, 1, 0], state: "minecraft:bedrock"},
{pos: [1, 1, 1], state: "minecraft:air"},
{pos: [1, 1, 2], state: "minecraft:air"},
{pos: [2, 1, 0], state: "minecraft:air"},
{pos: [2, 1, 1], state: "minecraft:air"},
{pos: [2, 1, 2], state: "minecraft:air"},
{pos: [1, 1, 2], state: "minecraft:bedrock"},
{pos: [2, 1, 0], state: "minecraft:bedrock"},
{pos: [2, 1, 1], state: "minecraft:bedrock"},
{pos: [2, 1, 2], state: "minecraft:bedrock"},
{pos: [0, 2, 0], state: "minecraft:air"},
{pos: [0, 2, 1], state: "minecraft:air"},
{pos: [0, 2, 2], state: "minecraft:air"},
Expand All @@ -28,7 +28,16 @@
{pos: [1, 2, 2], 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, 2], 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: [1, 3, 0], state: "minecraft:air"},
{pos: [1, 3, 1], state: "minecraft:air"},
{pos: [1, 3, 2], state: "minecraft:air"},
{pos: [2, 3, 0], state: "minecraft:air"},
{pos: [2, 3, 1], state: "minecraft:air"},
{pos: [2, 3, 2], state: "minecraft:air"}
],
entities: [],
palette: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
DataVersion: 3826,
size: [3, 3, 3],
DataVersion: 4189,
size: [3, 4, 3],
data: [
{pos: [0, 0, 0], state: "minecraft:bedrock"},
{pos: [0, 0, 1], state: "minecraft:bedrock"},
Expand Down Expand Up @@ -28,7 +28,16 @@
{pos: [1, 2, 2], 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, 2], 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: [1, 3, 0], state: "minecraft:air"},
{pos: [1, 3, 1], state: "minecraft:air"},
{pos: [1, 3, 2], state: "minecraft:air"},
{pos: [2, 3, 0], state: "minecraft:air"},
{pos: [2, 3, 1], state: "minecraft:air"},
{pos: [2, 3, 2], state: "minecraft:air"}
],
entities: [],
palette: [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
DataVersion: 4189,
size: [3, 3, 3],
data: [
{pos: [0, 0, 0], state: "minecraft:bedrock"},
{pos: [0, 0, 1], state: "minecraft:bedrock"},
{pos: [0, 0, 2], state: "minecraft:bedrock"},
{pos: [1, 0, 0], state: "minecraft:bedrock"},
{pos: [1, 0, 1], state: "minecraft:bedrock"},
{pos: [1, 0, 2], state: "minecraft:bedrock"},
{pos: [2, 0, 0], state: "minecraft:bedrock"},
{pos: [2, 0, 1], state: "minecraft:bedrock"},
{pos: [2, 0, 2], state: "minecraft:bedrock"},
{pos: [0, 1, 0], state: "minecraft:air"},
{pos: [0, 1, 1], state: "minecraft:air"},
{pos: [0, 1, 2], 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: [2, 1, 0], state: "minecraft:air"},
{pos: [2, 1, 1], state: "minecraft:air"},
{pos: [2, 1, 2], 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: [1, 2, 0], state: "minecraft:air"},
{pos: [1, 2, 1], state: "minecraft:air"},
{pos: [1, 2, 2], state: "minecraft:air"},
{pos: [2, 2, 0], state: "minecraft:air"},
{pos: [2, 2, 1], state: "minecraft:air"},
{pos: [2, 2, 2], state: "minecraft:air"}
],
entities: [],
palette: [
"minecraft:bedrock",
"minecraft:air"
]
}
Loading
Loading