1
0
forked from Clones/Controlify

registry for screenop

This commit is contained in:
isXander
2023-03-27 19:11:11 +01:00
parent b426312a8e
commit 8f5d42e5aa
13 changed files with 370 additions and 106 deletions

View File

@ -1,17 +1,13 @@
package dev.isxander.controlify.test;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import dev.isxander.controlify.bindings.ControllerBindings;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerConfig;
import dev.isxander.controlify.controller.ControllerState;
import dev.isxander.controlify.controller.ControllerType;
import net.minecraft.client.Minecraft;
import net.minecraft.client.Screenshot;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.function.Predicate;
@ -52,86 +48,21 @@ public class ClientTestHelper {
return submit(function).join();
}
public static Controller<?, ?> createFakeController() {
return new Controller<>() {
private final ControllerBindings<ControllerState> bindings = new ControllerBindings<>(this);
private final ControllerConfig config = new ControllerConfig() {
@Override
public void setDeadzone(int axis, float deadzone) {
public static void takeScreenshot(String name) {
AtomicBoolean returned = new AtomicBoolean(false);
submitAndWait(mc -> {
Screenshot.grab(mc.gameDirectory, name+".png", mc.getMainRenderTarget(), text -> returned.set(true));
return true;
});
waitFor("Screenshot to be taken", mc -> returned.get(), Duration.ofSeconds(2));
}
}
@Override
public float getDeadzone(int axis) {
return 0;
}
};
@Override
public String uid() {
return "FAKE";
}
@Override
public int joystickId() {
return -1;
}
@Override
public ControllerBindings<ControllerState> bindings() {
return bindings;
}
@Override
public ControllerConfig config() {
return config;
}
@Override
public ControllerConfig defaultConfig() {
return config;
}
@Override
public void resetConfig() {
}
@Override
public void setConfig(Gson gson, JsonElement json) {
}
@Override
public ControllerType type() {
return ControllerType.UNKNOWN;
}
@Override
public String name() {
return "FAKE CONTROLLER";
}
@Override
public ControllerState state() {
return ControllerState.EMPTY;
}
@Override
public ControllerState prevState() {
return ControllerState.EMPTY;
}
@Override
public void updateState() {
}
@Override
public void clearState() {
}
};
public static FakeController createAndUseDummyController() {
var controller = new FakeController();
Controller.CONTROLLERS.put(controller.uid(), controller);
controller.use();
return controller;
}
}

View File

@ -10,7 +10,7 @@ import java.util.List;
import static dev.isxander.controlify.test.ClientTestHelper.*;
public class ControlifyAutoTestClient implements ClientModInitializer {
private static final Logger LOGGER = LoggerFactory.getLogger("Controlify Auto Test");
public static final Logger LOGGER = LoggerFactory.getLogger("Controlify Auto Test");
@Override
public void onInitializeClient() {
@ -36,8 +36,8 @@ public class ControlifyAutoTestClient implements ClientModInitializer {
for (var method : methods) {
method.setAccessible(true);
Test.PreLoad preLoad = method.getAnnotation(Test.PreLoad.class);
if (preLoad != null) {
Test.Entrypoint entrypoint = method.getAnnotation(Test.Entrypoint.class);
if (entrypoint != null) {
if (method.getParameterCount() > 0)
throw new RuntimeException("PreLoad test method " + method.getName() + " has parameters!");
@ -47,11 +47,11 @@ public class ControlifyAutoTestClient implements ClientModInitializer {
} catch (Exception e) {
throw new RuntimeException(e);
}
}, preLoad.value()));
}, entrypoint.value()));
}
Test.PostLoad postLoad = method.getAnnotation(Test.PostLoad.class);
if (postLoad != null) {
Test.TitleScreen titleScreen = method.getAnnotation(Test.TitleScreen.class);
if (titleScreen != null) {
if (method.getParameterCount() > 0)
throw new RuntimeException("PostLoad test method " + method.getName() + " has parameters!");
@ -61,7 +61,7 @@ public class ControlifyAutoTestClient implements ClientModInitializer {
} catch (Exception e) {
throw new RuntimeException(e);
}
}, postLoad.value()));
}, titleScreen.value()));
}
}
@ -88,11 +88,13 @@ public class ControlifyAutoTestClient implements ClientModInitializer {
private boolean wrapTestExecution(Test test) {
LOGGER.info("\u001b[36mRunning test " + test.name() + "...");
try {
test.method().run();
test.runTest();
LOGGER.info("\u001b[32mPassed test " + test.name() + "!");
takeScreenshot(test.name());
return true;
} catch (Throwable t) {
LOGGER.error("\u001b[31mFailed test " + test.name() + "!", t);
takeScreenshot(test.name());
return false;
}
}

View File

@ -6,6 +6,10 @@ import dev.isxander.controlify.api.bind.ControlifyBindingsApi;
import dev.isxander.controlify.api.event.ControlifyEvents;
import dev.isxander.controlify.bindings.BindingSupplier;
import dev.isxander.controlify.bindings.GamepadBinds;
import dev.isxander.controlify.screenop.ScreenProcessor;
import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.resources.ResourceLocation;
import java.util.concurrent.atomic.AtomicBoolean;
@ -15,8 +19,9 @@ import static dev.isxander.controlify.test.ClientTestHelper.*;
public class ControlifyTests {
BindingSupplier binding = null;
boolean titleScreenProcessorPresent = false;
@Test.PreLoad("Binding registry test")
@Test.Entrypoint("Binding registry test")
void bindingRegistryTest() {
var registry = ControlifyBindingsApi.get();
assertNotNull(registry, "Binding registry is null");
@ -24,13 +29,14 @@ public class ControlifyTests {
assertNotNull(binding, "Bind registry failed - BindingSupplier is null");
}
@Test.PostLoad("BindingSupplier getter test")
@Test.TitleScreen("BindingSupplier getter test")
void bindingSupplierGetterTest() {
var controller = createFakeController();
var controller = createAndUseDummyController();
assertNotNull(binding.get(controller), "Bind registry failed - Bind for fake controller is null");
controller.finish();
}
@Test.PostLoad("Input mode changed event test")
@Test.TitleScreen("Input mode changed event test")
void checkInputModeChangedEvent() {
var api = ControlifyApi.get();
@ -42,4 +48,20 @@ public class ControlifyTests {
assertTrue(called.get(), "Input mode changed event was not called");
}
@Test.Entrypoint("Screen component registry setup test")
void setupScreenComponentRegistry() {
ScreenProcessorProvider.REGISTRY.register(TitleScreen.class, ts -> new ScreenProcessor<>(ts){
@Override
public void onWidgetRebuild() {
super.onWidgetRebuild();
titleScreenProcessorPresent = true;
}
});
}
@Test.TitleScreen("Screen component registry test")
void checkScreenComponentRegistry() {
assertTrue(titleScreenProcessorPresent, "Screen processor was not called");
}
}

View File

@ -0,0 +1,10 @@
package dev.isxander.controlify.test;
import java.util.List;
public record DiscoveredTests(List<Test> entrypointTests, List<Test> titleScreenTests) {
public boolean hasRanAllTests() {
return entrypointTests.stream().allMatch(Test::hasRan)
&& titleScreenTests.stream().allMatch(Test::hasRan);
}
}

View File

@ -0,0 +1,178 @@
package dev.isxander.controlify.test;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.bindings.ControllerBindings;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerType;
import dev.isxander.controlify.controller.joystick.JoystickConfig;
import dev.isxander.controlify.controller.joystick.JoystickController;
import dev.isxander.controlify.controller.joystick.JoystickState;
import dev.isxander.controlify.controller.joystick.mapping.JoystickMapping;
import dev.isxander.controlify.controller.joystick.mapping.UnmappedJoystickMapping;
import java.util.List;
public class FakeController implements JoystickController<JoystickConfig> {
public static int JOYSTICK_COUNT = 0;
private final String uid;
private final int id;
private final ControllerBindings<JoystickState> bindings;
private final JoystickConfig config;
private JoystickState state = JoystickState.EMPTY, prevState = JoystickState.EMPTY;
private float axisState;
private boolean shouldClearAxisNextTick;
private boolean buttonState, shouldButtonPressNextTick;
private JoystickState.HatState hatState = JoystickState.HatState.CENTERED;
private boolean shouldCenterHatNextTick;
public FakeController() {
this.uid = "FAKE-" + JOYSTICK_COUNT++;
this.id = -JOYSTICK_COUNT;
this.bindings = new ControllerBindings<>(this);
this.config = new JoystickConfig(this);
this.config.calibrated = true;
}
@Override
public String uid() {
return uid;
}
@Override
public int joystickId() {
return id;
}
@Override
public ControllerBindings<JoystickState> bindings() {
return bindings;
}
@Override
public JoystickState state() {
return state;
}
@Override
public JoystickState prevState() {
return prevState;
}
@Override
public JoystickConfig config() {
return config;
}
@Override
public JoystickConfig defaultConfig() {
return config;
}
@Override
public void resetConfig() {
throw new UnsupportedOperationException();
}
@Override
public void setConfig(Gson gson, JsonElement json) {
throw new UnsupportedOperationException();
}
@Override
public ControllerType type() {
return ControllerType.UNKNOWN;
}
@Override
public String name() {
return "Fake Controller";
}
@Override
public void updateState() {
buttonState = shouldButtonPressNextTick;
shouldButtonPressNextTick = false;
state = new FakeControllerState(mapping(), axisState, buttonState, hatState);
if (shouldClearAxisNextTick) {
shouldClearAxisNextTick = false;
axisState = 0f;
}
if (shouldCenterHatNextTick) {
shouldCenterHatNextTick = false;
hatState = JoystickState.HatState.CENTERED;
}
}
@Override
public void clearState() {
state = JoystickState.EMPTY;
}
@Override
public JoystickMapping mapping() {
return UnmappedJoystickMapping.INSTANCE;
}
@Override
public int axisCount() {
return 1;
}
@Override
public int buttonCount() {
return 1;
}
@Override
public int hatCount() {
return 1;
}
public void setAxis(float axis, boolean clearNextTick) {
this.axisState = axis;
this.shouldClearAxisNextTick = clearNextTick;
}
public void clearAxisNextTick() {
this.shouldClearAxisNextTick = true;
}
public void pressButtonNextTick() {
this.shouldButtonPressNextTick = true;
}
public void setHat(JoystickState.HatState hatState, boolean clearNextTick) {
this.hatState = hatState;
this.shouldCenterHatNextTick = clearNextTick;
}
public void clearHatNextTick() {
this.shouldCenterHatNextTick = true;
}
public void use() {
Controlify.instance().setCurrentController(this);
}
public void finish() {
Controlify.instance().setCurrentController(null);
Controller.CONTROLLERS.remove(uid, this);
}
@Override
public boolean canBeUsed() {
return true;
}
public static class FakeControllerState extends JoystickState {
protected FakeControllerState(JoystickMapping mapping, float axis, boolean button, HatState hat) {
super(mapping, List.of(axis), List.of(axis), List.of(button), List.of(hat));
}
}
}

View File

@ -4,17 +4,66 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Objects;
public final class Test {
private final Runnable method;
private final String name;
private boolean hasRan;
public Test(Runnable method, String name) {
this.method = method;
this.name = name;
}
public void runTest() {
if (hasRan)
throw new IllegalStateException("Test `" + name + "` cannot run twice.");
method.run();
hasRan = true;
}
public String name() {
return name;
}
public boolean hasRan() {
return hasRan;
}
@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj == null || obj.getClass() != this.getClass()) return false;
var that = (Test) obj;
return Objects.equals(this.method, that.method) &&
Objects.equals(this.name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(method, name);
}
@Override
public String toString() {
return "Test[" +
"method=" + method + ", " +
"name=" + name + ']';
}
public record Test(Runnable method, String name) {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PreLoad {
public @interface Entrypoint {
String value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PostLoad {
public @interface TitleScreen {
String value();
}
}