diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/ClientGameTestContext.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/ClientGameTestContext.java new file mode 100644 index 0000000000..65d5efea7b --- /dev/null +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/ClientGameTestContext.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.gametest.v1; + +import org.apache.commons.lang3.function.FailableConsumer; +import org.apache.commons.lang3.function.FailableFunction; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; + +/** + * Context for a client gametest containing various helpful functions and functions to access the game. + */ +@ApiStatus.NonExtendable +public interface ClientGameTestContext { + void waitTick(); + void waitTicks(int ticks); + + void setScreen(@Nullable Screen screen); + void clickScreenButton(String translationKey); + boolean tryClickScreenButton(String translationKey); + + void runOnClient(FailableConsumer action) throws E; + T computeOnClient(FailableFunction function) throws E; +} diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/FabricClientGameTest.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/FabricClientGameTest.java new file mode 100644 index 0000000000..f59de17b5b --- /dev/null +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/FabricClientGameTest.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.client.gametest.v1; + +/** + * The client game test entrypoint interface. See the package documentation. + */ +public interface FabricClientGameTest { + /** + * Runs the gametest. + */ + void runTest(ClientGameTestContext context); +} diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/package-info.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/package-info.java new file mode 100644 index 0000000000..79497dca5d --- /dev/null +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/api/client/gametest/v1/package-info.java @@ -0,0 +1,25 @@ +/** + * Provides support for client gametests. To register a client gametest, add an entry to the + * {@code fabric-client-gametest} entrypoint in your {@code fabric.mod.json}. Your gametest class should implement + * {@link net.fabricmc.fabric.api.client.gametest.v1.FabricClientGameTest FabricClientGameTest}. + * + *

Lifecycle

+ * Client gametests are run sequentially. When a gametest ends, the game will be + * returned to the title screen. When all gametests have been run, the game will be closed. + * + *

Threading

+ * + *

Client gametests run on the client gametest thread. Use the functions inside + * {@link net.fabricmc.fabric.api.client.gametest.v1.ClientGameTestContext ClientGameTestContext} and other test helper + * classes to run code on the correct thread. The game remains paused unless you explicitly unpause it using various + * waiting functions such as + * {@link net.fabricmc.fabric.api.client.gametest.v1.ClientGameTestContext#waitTick() ClientGameTestContext.waitTick()}. + * + *

A few changes have been made to how the vanilla game threads run, to make tests more reproducible. Notably, there + * is exactly one server tick per client tick while a server is running (singleplayer or multiplayer). On singleplayer, + * packets will always arrive on a consistent tick. + */ +@ApiStatus.Experimental +package net.fabricmc.fabric.api.client.gametest.v1; + +import org.jetbrains.annotations.ApiStatus; diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/ClientGameTestContextImpl.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/ClientGameTestContextImpl.java new file mode 100644 index 0000000000..b110b95218 --- /dev/null +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/ClientGameTestContextImpl.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.client.gametest; + +import com.google.common.base.Preconditions; +import org.apache.commons.lang3.function.FailableConsumer; +import org.apache.commons.lang3.function.FailableFunction; +import org.apache.commons.lang3.mutable.MutableObject; +import org.jetbrains.annotations.Nullable; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.Drawable; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.gui.widget.ClickableWidget; +import net.minecraft.client.gui.widget.CyclingButtonWidget; +import net.minecraft.client.gui.widget.PressableWidget; +import net.minecraft.client.gui.widget.Widget; +import net.minecraft.text.Text; +import net.minecraft.util.Nullables; + +import net.fabricmc.fabric.api.client.gametest.v1.ClientGameTestContext; +import net.fabricmc.fabric.mixin.client.gametest.CyclingButtonWidgetAccessor; +import net.fabricmc.fabric.mixin.client.gametest.ScreenAccessor; + +public final class ClientGameTestContextImpl implements ClientGameTestContext { + @Override + public void waitTick() { + ThreadingImpl.runTick(); + } + + @Override + public void waitTicks(int ticks) { + Preconditions.checkArgument(ticks >= 0, "ticks cannot be negative"); + + for (int i = 0; i < ticks; i++) { + ThreadingImpl.runTick(); + } + } + + @Override + public void setScreen(@Nullable Screen screen) { + runOnClient(client -> client.setScreen(screen)); + } + + @Override + public void clickScreenButton(String translationKey) { + Preconditions.checkNotNull(translationKey, "translationKey"); + + runOnClient(client -> { + if (!tryClickScreenButtonImpl(client.currentScreen, translationKey)) { + throw new AssertionError("Could not find button '%s' in screen '%s'".formatted( + translationKey, + Nullables.map(client.currentScreen, screen -> screen.getClass().getName()) + )); + } + }); + } + + @Override + public boolean tryClickScreenButton(String translationKey) { + Preconditions.checkNotNull(translationKey, "translationKey"); + + return computeOnClient(client -> tryClickScreenButtonImpl(client.currentScreen, translationKey)); + } + + private static boolean tryClickScreenButtonImpl(@Nullable Screen screen, String translationKey) { + if (screen == null) { + return false; + } + + final String buttonText = Text.translatable(translationKey).getString(); + final ScreenAccessor screenAccessor = (ScreenAccessor) screen; + + for (Drawable drawable : screenAccessor.getDrawables()) { + if (drawable instanceof PressableWidget pressableWidget && pressMatchingButton(pressableWidget, buttonText)) { + return true; + } + + if (drawable instanceof Widget widget) { + widget.forEachChild(clickableWidget -> pressMatchingButton(clickableWidget, buttonText)); + } + } + + // Was unable to find the button to press + return false; + } + + private static boolean pressMatchingButton(ClickableWidget widget, String text) { + if (widget instanceof ButtonWidget buttonWidget) { + if (text.equals(buttonWidget.getMessage().getString())) { + buttonWidget.onPress(); + return true; + } + } + + if (widget instanceof CyclingButtonWidget buttonWidget) { + CyclingButtonWidgetAccessor accessor = (CyclingButtonWidgetAccessor) buttonWidget; + + if (text.equals(accessor.getOptionText().getString())) { + buttonWidget.onPress(); + return true; + } + } + + return false; + } + + @Override + public void runOnClient(FailableConsumer action) throws E { + Preconditions.checkNotNull(action, "action"); + + ThreadingImpl.runOnClient(() -> action.accept(MinecraftClient.getInstance())); + } + + @Override + public T computeOnClient(FailableFunction function) throws E { + Preconditions.checkNotNull(function, "function"); + + MutableObject result = new MutableObject<>(); + ThreadingImpl.runOnClient(() -> result.setValue(function.apply(MinecraftClient.getInstance()))); + return result.getValue(); + } +} diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/ClientGameTestMixinConfigPlugin.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/ClientGameTestMixinConfigPlugin.java similarity index 97% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/ClientGameTestMixinConfigPlugin.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/ClientGameTestMixinConfigPlugin.java index 79c0c68778..f0e6511dbe 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/ClientGameTestMixinConfigPlugin.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/ClientGameTestMixinConfigPlugin.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.fabric.impl.gametest.client; +package net.fabricmc.fabric.impl.client.gametest; import java.util.List; import java.util.Set; diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/FabricClientGameTestRunner.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/FabricClientGameTestRunner.java new file mode 100644 index 0000000000..bf16be7f97 --- /dev/null +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/FabricClientGameTestRunner.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.impl.client.gametest; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.minecraft.client.gui.screen.TitleScreen; + +import net.fabricmc.fabric.api.client.gametest.v1.ClientGameTestContext; +import net.fabricmc.fabric.api.client.gametest.v1.FabricClientGameTest; +import net.fabricmc.loader.api.FabricLoader; + +public class FabricClientGameTestRunner { + private static final Logger LOGGER = LoggerFactory.getLogger("fabric-client-gametest-api-v1"); + private static final String ENTRYPOINT_KEY = "fabric-client-gametest"; + + public static void start() { + List gameTests = FabricLoader.getInstance().getEntrypoints(ENTRYPOINT_KEY, FabricClientGameTest.class); + ThreadingImpl.runTestThread(() -> { + ClientGameTestContext context = new ClientGameTestContextImpl(); + boolean failed = false; + + for (FabricClientGameTest gameTest : gameTests) { + try { + gameTest.runTest(context); + } catch (Throwable e) { + LOGGER.error("Failed test {}", gameTest.getClass().getName(), e); + failed = true; + } finally { + // Open the title screen to reset the state for the next gametest. + // If the gametest API was used correctly, we should be in the menus somewhere because any test + // world should have been closed at the end of a try-with-resources statement. + context.setScreen(new TitleScreen()); + } + } + + if (failed) { + throw new AssertionError("There were failing client gametests"); + } + + context.clickScreenButton("menu.quit"); + }); + } +} diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/FabricClientTestHelper.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/FabricClientTestHelper.java similarity index 96% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/FabricClientTestHelper.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/FabricClientTestHelper.java index 299663fffd..dcb7d08e1f 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/FabricClientTestHelper.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/FabricClientTestHelper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.fabric.impl.gametest.client; +package net.fabricmc.fabric.impl.client.gametest; import java.util.Objects; import java.util.function.Function; @@ -45,9 +45,9 @@ import net.minecraft.client.util.ScreenshotRecorder; import net.minecraft.text.Text; -import net.fabricmc.fabric.mixin.gametest.client.CyclingButtonWidgetAccessor; -import net.fabricmc.fabric.mixin.gametest.client.ScreenAccessor; -import net.fabricmc.fabric.mixin.gametest.client.TitleScreenAccessor; +import net.fabricmc.fabric.mixin.client.gametest.CyclingButtonWidgetAccessor; +import net.fabricmc.fabric.mixin.client.gametest.ScreenAccessor; +import net.fabricmc.fabric.mixin.client.gametest.TitleScreenAccessor; import net.fabricmc.loader.api.FabricLoader; public final class FabricClientTestHelper { diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/TestDedicatedServer.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/TestDedicatedServer.java similarity index 98% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/TestDedicatedServer.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/TestDedicatedServer.java index 7cc62379c6..8d6105e4b8 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/TestDedicatedServer.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/TestDedicatedServer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.fabric.impl.gametest.client; +package net.fabricmc.fabric.impl.client.gametest; import java.io.Closeable; import java.io.IOException; diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/ThreadingImpl.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/ThreadingImpl.java similarity index 99% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/ThreadingImpl.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/ThreadingImpl.java index 87da7f9264..a739cbc0dc 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/gametest/client/ThreadingImpl.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/impl/client/gametest/ThreadingImpl.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.fabric.impl.gametest.client; +package net.fabricmc.fabric.impl.client.gametest; import java.util.concurrent.Phaser; import java.util.concurrent.Semaphore; diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/CyclingButtonWidgetAccessor.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/CyclingButtonWidgetAccessor.java similarity index 94% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/CyclingButtonWidgetAccessor.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/CyclingButtonWidgetAccessor.java index 2b8fd4a9d6..539107be24 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/CyclingButtonWidgetAccessor.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/CyclingButtonWidgetAccessor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.fabric.mixin.gametest.client; +package net.fabricmc.fabric.mixin.client.gametest; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/MinecraftClientMixin.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/MinecraftClientMixin.java similarity index 88% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/MinecraftClientMixin.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/MinecraftClientMixin.java index d5ddd343cb..cf1d7ffceb 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/MinecraftClientMixin.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/MinecraftClientMixin.java @@ -14,12 +14,14 @@ * limitations under the License. */ -package net.fabricmc.fabric.mixin.gametest.client; +package net.fabricmc.fabric.mixin.client.gametest; import com.google.common.base.Preconditions; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -27,18 +29,26 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Overlay; import net.minecraft.client.gui.screen.Screen; import net.minecraft.resource.ResourcePackManager; import net.minecraft.server.SaveLoader; import net.minecraft.world.level.storage.LevelStorage; -import net.fabricmc.fabric.impl.gametest.client.ThreadingImpl; +import net.fabricmc.fabric.impl.client.gametest.FabricClientGameTestRunner; +import net.fabricmc.fabric.impl.client.gametest.ThreadingImpl; @Mixin(MinecraftClient.class) public class MinecraftClientMixin { + @Unique + private boolean startedClientGametests = false; @Unique private Runnable deferredTask = null; + @Shadow + @Nullable + private Overlay overlay; + @WrapMethod(method = "run") private void onRun(Operation original) { if (ThreadingImpl.isClientRunning) { @@ -57,6 +67,14 @@ private void onRun(Operation original) { } } + @Inject(method = "tick", at = @At("HEAD")) + private void onTick(CallbackInfo ci) { + if (!startedClientGametests && overlay == null) { + startedClientGametests = true; + FabricClientGameTestRunner.start(); + } + } + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;runTasks()V")) private void preRunTasks(CallbackInfo ci) { ThreadingImpl.enterPhase(ThreadingImpl.PHASE_SERVER_TASKS); diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/MinecraftDedicatedServerMixin.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/MinecraftDedicatedServerMixin.java similarity index 94% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/MinecraftDedicatedServerMixin.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/MinecraftDedicatedServerMixin.java index c5e7ece359..19575f6069 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/MinecraftDedicatedServerMixin.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/MinecraftDedicatedServerMixin.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.fabric.mixin.gametest.client; +package net.fabricmc.fabric.mixin.client.gametest; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; @@ -25,7 +25,7 @@ import net.minecraft.server.dedicated.MinecraftDedicatedServer; -import net.fabricmc.fabric.impl.gametest.client.TestDedicatedServer; +import net.fabricmc.fabric.impl.client.gametest.TestDedicatedServer; @Mixin(MinecraftDedicatedServer.class) public abstract class MinecraftDedicatedServerMixin { diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/MinecraftServerMixin.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/MinecraftServerMixin.java similarity index 95% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/MinecraftServerMixin.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/MinecraftServerMixin.java index 702cd87efe..3f6c0e827f 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/MinecraftServerMixin.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/MinecraftServerMixin.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.fabric.mixin.gametest.client; +package net.fabricmc.fabric.mixin.client.gametest; import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; @@ -25,7 +25,7 @@ import net.minecraft.server.MinecraftServer; -import net.fabricmc.fabric.impl.gametest.client.ThreadingImpl; +import net.fabricmc.fabric.impl.client.gametest.ThreadingImpl; @Mixin(MinecraftServer.class) public class MinecraftServerMixin { diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/ScreenAccessor.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/ScreenAccessor.java similarity index 94% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/ScreenAccessor.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/ScreenAccessor.java index 7497af6df1..b0236a09ed 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/ScreenAccessor.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/ScreenAccessor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.fabric.mixin.gametest.client; +package net.fabricmc.fabric.mixin.client.gametest; import java.util.List; diff --git a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/TitleScreenAccessor.java b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/TitleScreenAccessor.java similarity index 94% rename from fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/TitleScreenAccessor.java rename to fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/TitleScreenAccessor.java index f621101e6d..654a0092f4 100644 --- a/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/gametest/client/TitleScreenAccessor.java +++ b/fabric-client-gametest-api-v1/src/client/java/net/fabricmc/fabric/mixin/client/gametest/TitleScreenAccessor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.fabricmc.fabric.mixin.gametest.client; +package net.fabricmc.fabric.mixin.client.gametest; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; diff --git a/fabric-client-gametest-api-v1/src/client/resources/fabric-client-gametest-api-v1.mixins.json b/fabric-client-gametest-api-v1/src/client/resources/fabric-client-gametest-api-v1.mixins.json index e7d83cfb49..f8521bfacf 100644 --- a/fabric-client-gametest-api-v1/src/client/resources/fabric-client-gametest-api-v1.mixins.json +++ b/fabric-client-gametest-api-v1/src/client/resources/fabric-client-gametest-api-v1.mixins.json @@ -1,12 +1,12 @@ { "required": true, - "package": "net.fabricmc.fabric.mixin.gametest.client", + "package": "net.fabricmc.fabric.mixin.client.gametest", "compatibilityLevel": "JAVA_21", "mixins": [ "MinecraftDedicatedServerMixin", "MinecraftServerMixin" ], - "plugin": "net.fabricmc.fabric.impl.gametest.client.ClientGameTestMixinConfigPlugin", + "plugin": "net.fabricmc.fabric.impl.client.gametest.ClientGameTestMixinConfigPlugin", "injectors": { "defaultRequire": 1 }, diff --git a/fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/gametest/client/ClientGameTestTestMod.java b/fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/gametest/client/ClientGameTestTest.java similarity index 76% rename from fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/gametest/client/ClientGameTestTestMod.java rename to fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/gametest/client/ClientGameTestTest.java index aafa68b94e..361aa3ac4b 100644 --- a/fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/gametest/client/ClientGameTestTestMod.java +++ b/fabric-client-gametest-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/gametest/client/ClientGameTestTest.java @@ -16,20 +16,19 @@ package net.fabricmc.fabric.test.gametest.client; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.clickScreenButton; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.closeScreen; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.computeOnClient; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.connectToServer; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.enableDebugHud; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.openGameMenu; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.openInventory; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.setPerspective; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.takeScreenshot; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.waitForLoadingComplete; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.waitForScreen; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.waitForServerStop; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.waitForTitleScreenFade; -import static net.fabricmc.fabric.impl.gametest.client.FabricClientTestHelper.waitForWorldTicks; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.clickScreenButton; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.closeScreen; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.computeOnClient; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.connectToServer; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.enableDebugHud; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.openGameMenu; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.openInventory; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.setPerspective; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.takeScreenshot; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.waitForScreen; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.waitForServerStop; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.waitForTitleScreenFade; +import static net.fabricmc.fabric.impl.client.gametest.FabricClientTestHelper.waitForWorldTicks; import java.io.IOException; import java.io.UncheckedIOException; @@ -50,26 +49,13 @@ import net.minecraft.client.gui.screen.world.SelectWorldScreen; import net.minecraft.client.option.Perspective; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.impl.gametest.client.TestDedicatedServer; -import net.fabricmc.fabric.impl.gametest.client.ThreadingImpl; +import net.fabricmc.fabric.api.client.gametest.v1.ClientGameTestContext; +import net.fabricmc.fabric.api.client.gametest.v1.FabricClientGameTest; +import net.fabricmc.fabric.impl.client.gametest.TestDedicatedServer; import net.fabricmc.loader.api.FabricLoader; -public class ClientGameTestTestMod implements ClientModInitializer { - public static final boolean ENABLED = System.getProperty("fabric.client.gametest") != null; - - @Override - public void onInitializeClient() { - if (!ENABLED) { - return; - } - - ThreadingImpl.runTestThread(this::runTest); - } - - private void runTest() { - waitForLoadingComplete(); - +public class ClientGameTestTest implements FabricClientGameTest { + public void runTest(ClientGameTestContext context) { final boolean onboardAccessibility = computeOnClient(client -> client.options.onboardAccessibility); if (onboardAccessibility) { diff --git a/fabric-client-gametest-api-v1/src/testmodClient/resources/fabric.mod.json b/fabric-client-gametest-api-v1/src/testmodClient/resources/fabric.mod.json index c2f5ca1eb0..e1e761f4bb 100644 --- a/fabric-client-gametest-api-v1/src/testmodClient/resources/fabric.mod.json +++ b/fabric-client-gametest-api-v1/src/testmodClient/resources/fabric.mod.json @@ -6,8 +6,8 @@ "environment": "*", "license": "Apache-2.0", "entrypoints": { - "client": [ - "net.fabricmc.fabric.test.gametest.client.ClientGameTestTestMod" + "fabric-client-gametest": [ + "net.fabricmc.fabric.test.gametest.client.ClientGameTestTest" ] } }