Skip to content

Commit 8272ba2

Browse files
committed
Backported changes from the CC: Tweaked Gametest framework present in the 1.20.x branch
This was mainly done to allow the execution of client tests
1 parent 4b49523 commit 8272ba2

File tree

18 files changed

+729
-179
lines changed

18 files changed

+729
-179
lines changed

src/testMod/java/dan200/computercraft/gametest/core/CCTestCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ private static Path getWorldComputerPath(MinecraftServer server) {
107107
}
108108

109109
private static Path getSourceComputerPath() {
110-
return TestHooks.sourceDir.resolve("computer");
110+
return TestHooks.getSourceDir().resolve("computer");
111111
}
112112

113113
private static int error(CommandSourceStack source, String message) {

src/testMod/java/dan200/computercraft/gametest/core/ClientHooks.java

Lines changed: 0 additions & 49 deletions
This file was deleted.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* This file is part of ComputerCraft - http://www.computercraft.info
3+
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
4+
* Send enquiries to dratcliffe@gmail.com
5+
*/
6+
package dan200.computercraft.gametest.core;
7+
8+
import net.minecraft.client.Minecraft;
9+
10+
/**
11+
* Extensions to {@link Minecraft}, injected via mixin.
12+
*/
13+
public interface MinecraftExtensions {
14+
boolean computercraft$isRenderingStable();
15+
}

src/testMod/java/dan200/computercraft/gametest/core/TestAPI.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
import de.srendi.advancedperipherals.common.util.LuaConverter;
1717
import net.minecraft.gametest.framework.GameTestSequence;
1818
import net.minecraftforge.server.ServerLifecycleHooks;
19+
import org.slf4j.Logger;
20+
import org.slf4j.LoggerFactory;
1921

22+
import javax.annotation.Nullable;
2023
import java.util.Optional;
2124

2225
/**
@@ -27,8 +30,10 @@
2730
* @see TestExtensionsKt#thenComputerOk(GameTestSequence, String, String) To check tests on the computer have passed.
2831
*/
2932
public class TestAPI extends ComputerState implements ILuaAPI {
33+
private static final Logger LOG = LoggerFactory.getLogger(TestAPI.class);
34+
3035
private final IComputerSystem system;
31-
private String label;
36+
private @Nullable String label;
3237

3338
TestAPI(IComputerSystem system) {
3439
this.system = system;
@@ -39,30 +44,29 @@ public void startup() {
3944
if (label == null) label = system.getLabel();
4045
if (label == null) {
4146
label = "#" + system.getID();
42-
ComputerCraft.log.warn("Computer {} has no label", label);
47+
LOG.warn("Computer {} has no label", label);
4348
}
4449

45-
ComputerCraft.log.info("Computer '{}' has turned on.", label);
50+
LOG.info("Computer '{}' has turned on.", label);
4651
markers.clear();
4752
error = null;
4853
lookup.put(label, this);
4954
}
5055

5156
@Override
5257
public void shutdown() {
53-
ComputerCraft.log.info("Computer '{}' has shut down.", label);
54-
if (lookup.get(label) == this)
55-
lookup.remove(label);
58+
LOG.info("Computer '{}' has shut down.", label);
59+
if (lookup.get(label) == this) lookup.remove(label);
5660
}
5761

5862
@Override
5963
public String[] getNames() {
60-
return new String[]{"test"};
64+
return new String[]{ "test" };
6165
}
6266

6367
@LuaFunction
6468
public final void fail(String message) throws LuaException {
65-
ComputerCraft.log.error("Computer '{}' failed with {}", label, message);
69+
LOG.error("Computer '{}' failed with {}", label, message);
6670
if (markers.contains(ComputerState.DONE)) throw new LuaException("Cannot call fail/ok multiple times.");
6771
markers.add(ComputerState.DONE);
6872
error = message;
@@ -71,7 +75,7 @@ public final void fail(String message) throws LuaException {
7175

7276
@LuaFunction
7377
public final void ok(Optional<String> marker) throws LuaException {
74-
String actualMarker = marker.orElse(ComputerState.DONE);
78+
var actualMarker = marker.orElse(ComputerState.DONE);
7579
if (markers.contains(ComputerState.DONE) || markers.contains(actualMarker)) {
7680
throw new LuaException("Cannot call fail/ok multiple times.");
7781
}
@@ -81,7 +85,7 @@ public final void ok(Optional<String> marker) throws LuaException {
8185

8286
@LuaFunction
8387
public final void log(String message) {
84-
ComputerCraft.log.info("[Computer '{}'] {}", label, message);
88+
LOG.info("[Computer '{}'] {}", label, message);
8589
}
8690

8791
@LuaFunction

src/testMod/java/dan200/computercraft/gametest/core/TestHooks.java

Lines changed: 0 additions & 57 deletions
This file was deleted.

src/testMod/java/dan200/computercraft/gametest/core/TestMod.java

Lines changed: 17 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77

88
import dan200.computercraft.export.Exporter;
99
import dan200.computercraft.gametest.api.GameTestHolder;
10-
import net.minecraft.gametest.framework.GameTest;
11-
import net.minecraft.gametest.framework.GameTestRegistry;
12-
import net.minecraft.gametest.framework.StructureUtils;
13-
import net.minecraft.gametest.framework.TestFunction;
14-
import net.minecraft.resources.ResourceLocation;
10+
import net.minecraftforge.api.distmarker.Dist;
1511
import net.minecraftforge.client.event.RegisterClientCommandsEvent;
12+
import net.minecraftforge.client.event.ScreenEvent;
1613
import net.minecraftforge.common.MinecraftForge;
1714
import net.minecraftforge.event.RegisterCommandsEvent;
1815
import net.minecraftforge.event.RegisterGameTestsEvent;
16+
import net.minecraftforge.event.TickEvent;
1917
import net.minecraftforge.event.server.ServerStartedEvent;
2018
import net.minecraftforge.eventbus.api.EventPriority;
19+
import net.minecraftforge.fml.DistExecutor;
2120
import net.minecraftforge.fml.ModList;
2221
import net.minecraftforge.fml.common.Mod;
2322
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
@@ -43,7 +42,7 @@ public TestMod() {
4342
var bus = MinecraftForge.EVENT_BUS;
4443
bus.addListener(EventPriority.LOW, (ServerStartedEvent e) -> TestHooks.onServerStarted(e.getServer()));
4544
bus.addListener((RegisterCommandsEvent e) -> CCTestCommand.register(e.getDispatcher()));
46-
bus.addListener((RegisterClientCommandsEvent e) -> Exporter.register(e.getDispatcher()));
45+
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> TestMod::onInitializeClient);
4746

4847
var modBus = FMLJavaModLoadingContext.get().getModEventBus();
4948
modBus.addListener((RegisterGameTestsEvent event) -> {
@@ -56,6 +55,17 @@ public TestMod() {
5655
});
5756
}
5857

58+
private static void onInitializeClient() {
59+
var bus = MinecraftForge.EVENT_BUS;
60+
61+
bus.addListener((TickEvent.ServerTickEvent e) -> {
62+
if (e.phase == TickEvent.Phase.START) ClientTestHooks.onServerTick(e.getServer());
63+
});
64+
bus.addListener((ScreenEvent.Opening e) -> {
65+
if (ClientTestHooks.onOpenScreen(e.getScreen())) e.setCanceled(true);
66+
});
67+
bus.addListener((RegisterClientCommandsEvent e) -> Exporter.register(e.getDispatcher()));
68+
}
5969

6070
private static Class<?> loadClass(String name) {
6171
try {
@@ -68,60 +78,7 @@ private static Class<?> loadClass(String name) {
6878
private static void registerClass(String className, Consumer<Method> fallback) {
6979
var klass = loadClass(className);
7080
for (var method : klass.getDeclaredMethods()) {
71-
var testInfo = method.getAnnotation(GameTest.class);
72-
if (testInfo == null) {
73-
fallback.accept(method);
74-
continue;
75-
}
76-
77-
GameTestRegistry.getAllTestFunctions().add(turnMethodIntoTestFunction(method, testInfo));
78-
GameTestRegistry.getAllTestClassNames().add(className);
81+
TestHooks.registerTest(klass, method, fallback);
7982
}
8083
}
81-
82-
/**
83-
* Custom implementation of {@link GameTestRegistry#turnMethodIntoTestFunction(Method)} which makes
84-
* {@link GameTest#template()} behave the same as Fabric, namely in that it points to a {@link ResourceLocation},
85-
* rather than a test-class-specific structure.
86-
* <p>
87-
* This effectively acts as a global version of {@link PrefixGameTestTemplate}, just one which doesn't require Forge
88-
* to be present.
89-
*
90-
* @param method The method to register.
91-
* @param testInfo The test info.
92-
* @return The constructed test function.
93-
*/
94-
private static TestFunction turnMethodIntoTestFunction(Method method, GameTest testInfo) {
95-
var className = method.getDeclaringClass().getSimpleName().toLowerCase(Locale.ROOT);
96-
var testName = className + "." + method.getName().toLowerCase(Locale.ROOT);
97-
return new TestFunction(
98-
testInfo.batch(),
99-
testName,
100-
testInfo.template().isEmpty() ? testName : testInfo.template(),
101-
StructureUtils.getRotationForRotationSteps(testInfo.rotationSteps()), testInfo.timeoutTicks(), testInfo.setupTicks(),
102-
testInfo.required(), testInfo.requiredSuccesses(), testInfo.attempts(),
103-
turnMethodIntoConsumer(method)
104-
);
105-
}
106-
107-
private static <T> Consumer<T> turnMethodIntoConsumer(Method method) {
108-
return value -> {
109-
try {
110-
Object instance = null;
111-
if (!Modifier.isStatic(method.getModifiers())) {
112-
instance = method.getDeclaringClass().getConstructor().newInstance();
113-
}
114-
115-
method.invoke(instance, value);
116-
} catch (InvocationTargetException e) {
117-
if (e.getCause() instanceof RuntimeException) {
118-
throw (RuntimeException) e.getCause();
119-
} else {
120-
throw new RuntimeException(e.getCause());
121-
}
122-
} catch (ReflectiveOperationException e) {
123-
throw new RuntimeException(e);
124-
}
125-
};
126-
}
12784
}

src/testMod/java/dan200/computercraft/mixin/gametest/GameTestSequenceMixin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public void tickAndContinue(long ticks) {
3737
parent.fail(e);
3838
} catch (Exception e) {
3939
// Fail the test, rather than crashing the server.
40-
TestHooks.LOGGER.error("{} threw unexpected exception", parent.getTestName(), e);
40+
TestHooks.LOG.error("{} threw unexpected exception", parent.getTestName(), e);
4141
parent.fail(e);
4242
}
4343
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package dan200.computercraft.mixin.gametest.client;
2+
3+
import net.minecraft.world.level.storage.LevelSummary;
4+
import org.spongepowered.asm.mixin.Mixin;
5+
import org.spongepowered.asm.mixin.Overwrite;
6+
7+
/**
8+
* Used to suppress the "Worlds using Experimental Settings are not supported" warning
9+
* when loading a world in GameTest.
10+
*/
11+
@Mixin(LevelSummary.class)
12+
public class LevelSummaryMixin {
13+
14+
@Overwrite
15+
public boolean isExperimental() {
16+
return false;
17+
}
18+
19+
}

0 commit comments

Comments
 (0)