diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/TestInput.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/TestInput.java index fa776fcd9f9..36c077a7ae9 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/TestInput.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/TestInput.java @@ -24,6 +24,7 @@ import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.Options; +import net.minecraft.core.BlockPos; /** * The client gametest input handler used to simulate inputs to the client. @@ -319,6 +320,23 @@ public interface TestInput { */ void holdMouseFor(int button, int ticks); + /** + * Sets the player view rotation to the given yaw and pitch. + * + * @param yaw The yaw to look at + * @param pitch The pitch to look at + * @see #lookAt(BlockPos) + */ + void lookAt(float yaw, float pitch); + + /** + * Sets the player view rotation to look at the center of the given block position. + * + * @param pos The block position to look at + * @see #lookAt(float, float) + */ + void lookAt(BlockPos pos); + /** * Types a code point (character). Useful for typing in text boxes. * diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/TestInputImpl.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/TestInputImpl.java index cea6f6f0968..6b5f87260c7 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/TestInputImpl.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/TestInputImpl.java @@ -31,7 +31,10 @@ import net.minecraft.client.input.CharacterEvent; import net.minecraft.client.input.KeyEvent; import net.minecraft.client.input.MouseButtonInfo; +import net.minecraft.commands.arguments.EntityAnchorArgument; +import net.minecraft.core.BlockPos; import net.minecraft.util.Util; +import net.minecraft.world.phys.Vec3; import net.fabricmc.fabric.api.client.gametest.v1.TestInput; import net.fabricmc.fabric.api.client.gametest.v1.context.ClientGameTestContext; @@ -279,6 +282,30 @@ public void holdMouseFor(int button, int ticks) { holdKeyFor(InputConstants.Type.MOUSE.getOrCreate(button), ticks); } + @Override + public void lookAt(float yaw, float pitch) { + ThreadingImpl.checkOnGametestThread("lookAt"); + Preconditions.checkArgument(Float.isFinite(yaw), "yaw must be finite"); + Preconditions.checkArgument(Float.isFinite(pitch), "pitch must be finite"); + + context.runOnClient(client -> { + Preconditions.checkState(client.player != null, "player must be present to look"); + client.player.setYRot(yaw); + client.player.setXRot(pitch); + }); + } + + @Override + public void lookAt(BlockPos pos) { + ThreadingImpl.checkOnGametestThread("lookAt"); + Preconditions.checkNotNull(pos, "pos"); + + context.runOnClient(client -> { + Preconditions.checkState(client.player != null, "player must be present to look"); + client.player.lookAt(EntityAnchorArgument.Anchor.EYES, Vec3.atCenterOf(pos)); + }); + } + @Override public void typeChar(int codePoint) { ThreadingImpl.checkOnGametestThread("typeChar"); diff --git a/fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/client/gametest/ClientGameTestTest.java b/fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/client/gametest/ClientGameTestTest.java index c789944590d..73d3707bd71 100644 --- a/fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/client/gametest/ClientGameTestTest.java +++ b/fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/client/gametest/ClientGameTestTest.java @@ -29,8 +29,11 @@ import net.minecraft.client.CameraType; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.inventory.ContainerScreen; import net.minecraft.client.gui.screens.multiplayer.ServerReconfigScreen; import net.minecraft.client.gui.screens.worldselection.WorldCreationUiState; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.Blocks; import net.fabricmc.fabric.api.client.gametest.v1.FabricClientGameTest; import net.fabricmc.fabric.api.client.gametest.v1.context.ClientGameTestContext; @@ -72,6 +75,17 @@ public void runTest(ClientGameTestContext context) { context.takeScreenshot("in_game_overworld"); } + { + BlockPos chestPos = context.computeOnClient(client -> BlockPos.containing(client.player.position()).east().east().above().above()); + singleplayer.getServer().runCommand("setblock %d %d %d minecraft:chest".formatted(chestPos.getX(), chestPos.getY(), chestPos.getZ())); + context.waitFor(client -> client.level.getBlockState(chestPos).is(Blocks.CHEST)); + context.getInput().lookAt(chestPos); + context.waitTick(); + context.getInput().pressKey(options -> options.keyUse); + context.waitForScreen(ContainerScreen.class); + context.setScreen(() -> null); + } + { context.getInput().pressKey(options -> options.keyChat); context.getInput().typeChars("Hello, World!");