diff --git a/src/main/java/io/singularitynet/Client/VereyaModClient.java b/src/main/java/io/singularitynet/Client/VereyaModClient.java index 85d28f80..769e55d4 100644 --- a/src/main/java/io/singularitynet/Client/VereyaModClient.java +++ b/src/main/java/io/singularitynet/Client/VereyaModClient.java @@ -7,12 +7,15 @@ import io.singularitynet.mixin.MinecraftClientMixin; import io.singularitynet.mixin.MouseAccessorMixin; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.minecraft.client.Keyboard; import net.minecraft.client.MinecraftClient; import net.minecraft.client.Mouse; import net.minecraft.entity.mob.MobEntity; import net.minecraft.client.gui.screen.*; +import net.minecraft.text.Text; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.NotNull; @@ -25,8 +28,7 @@ public class VereyaModClient implements ClientModInitializer, IMalmoModClient, ScreenEvents { public static final String CONTROLLABLE = "ControlledMobs"; - - boolean hybridMode = false; + private long timeSwitchHybrid = 0; public static final String AGENT_DEAD_QUIT_CODE = "MALMO_AGENT_DIED"; public static final String AGENT_UNRESPONSIVE_CODE = "MALMO_AGENT_NOT_RESPONDING"; @@ -88,15 +90,26 @@ public void lockCursor(){ @Override public boolean isCursorLocked() { + MissionBehaviour behaviour = VereyaModClient.this.stateMachine.currentMissionBehaviour(); + // This stops Minecraft from doing the annoying thing of stealing your mouse. - if(VereyaModClient.this.inputType == InputType.AI) { + // do not let to lock if we are overriding inputs + if (behaviour != null && behaviour.commandHandler.isOverriding()) { return true; } return super.isCursorLocked(); } + public void onMouseUsed(){ + if (VereyaModClient.this.inputType == InputType.HYBRID){ + setOverrideHybrid(false); + } + } + public boolean shouldUpdate(){ - return VereyaModClient.this.inputType == InputType.HUMAN; + MissionBehaviour behaviour = VereyaModClient.this.stateMachine.currentMissionBehaviour(); + // If AI is not overriding we should update the mouse + return behaviour == null || !behaviour.commandHandler.isOverriding(); } @Override @@ -146,6 +159,19 @@ public void setup(){ Mouse mouse = new MyMouse(MinecraftClient.getInstance()); mouse.setup(MinecraftClient.getInstance().getWindow().getHandle()); ((MinecraftClientMixin)MinecraftClient.getInstance()).setMouse(mouse); + // register callback to run each frame + ClientTickEvents.END_CLIENT_TICK.register(client -> this.checkHybrideOverrides()); + } + + private void checkHybrideOverrides() { + if (this.getInputType() == InputType.HYBRID) { + MissionBehaviour behaviour = this.stateMachine.currentMissionBehaviour(); + if (behaviour != null && !behaviour.commandHandler.isOverriding()) { + long currentTime = System.currentTimeMillis(); + if (currentTime - timeSwitchHybrid > 1000) + setOverrideHybrid(true); + } + } } @Override @@ -156,7 +182,7 @@ public InputType getInputType() { // Control overriding: enum InputType { - HUMAN, AI; + HUMAN, AI, HYBRID; private static final InputType[] vals = values(); public InputType next() { @@ -192,10 +218,13 @@ public void setInputType(InputType input) LOGGER.debug("commandHandler is null, returning"); return; } - this.stateMachine.currentMissionBehaviour().commandHandler.setOverriding(input == InputType.AI); + + this.stateMachine.currentMissionBehaviour().commandHandler.setOverriding(input == InputType.AI || input == InputType.HYBRID); this.inputType = input; - if (input == InputType.HUMAN) + // send chat message + MinecraftClient.getInstance().player.sendMessage(Text.of("input type set to: " + input.name()), true); + if (input == InputType.HUMAN || input == InputType.HYBRID) { MinecraftClient.getInstance().mouse.lockCursor(); } @@ -206,7 +235,7 @@ public void setInputType(InputType input) } private void onKey(long window, int key, int scancode, int action, int modifiers) { - + // do default thing if any screen is open Screen screen = MinecraftClient.getInstance().currentScreen; if (screen != null) { if (screen instanceof ChatScreen) { @@ -214,21 +243,21 @@ private void onKey(long window, int key, int scancode, int action, int modifiers } } - if ((key == GLFW.GLFW_KEY_F6) && (action == GLFW.GLFW_PRESS)) - { - hybridMode = ! hybridMode; - } - if ((hybridMode) && (inputType == InputType.AI)) { - if ((action == GLFW.GLFW_PRESS)) { - MinecraftClient.getInstance().mouse.lockCursor(); - this.stateMachine.currentMissionBehaviour().commandHandler.setOverriding(false); - } else if ((action == GLFW.GLFW_RELEASE)) { - MinecraftClient.getInstance().mouse.unlockCursor(); - this.stateMachine.currentMissionBehaviour().commandHandler.setOverriding(true); - } + if (inputType == InputType.HYBRID && action == GLFW.GLFW_PRESS) { + // human controls the inputs + setOverrideHybrid(false); } if ((key == GLFW.GLFW_KEY_ENTER) && (action != GLFW.GLFW_RELEASE)) setInputType(inputType.next()); } + + private void setOverrideHybrid(boolean override) { + MissionBehaviour behaviour = this.stateMachine.currentMissionBehaviour(); + if (behaviour == null) { + return; + } + timeSwitchHybrid = System.currentTimeMillis(); + behaviour.commandHandler.setOverriding(override); + } } \ No newline at end of file diff --git a/src/main/java/io/singularitynet/mixin/MouseMixin.java b/src/main/java/io/singularitynet/mixin/MouseMixin.java index 985294d3..f28eb5ac 100644 --- a/src/main/java/io/singularitynet/mixin/MouseMixin.java +++ b/src/main/java/io/singularitynet/mixin/MouseMixin.java @@ -3,17 +3,21 @@ import io.singularitynet.Client.VereyaModClient; import net.minecraft.client.Mouse; -import org.apache.logging.log4j.LogManager; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - @Mixin(Mouse.class) public class MouseMixin { + @Inject(method="onMouseButton", at = @At("HEAD")) + private void onOnMouseButton(long window, int button, int action, int mods, CallbackInfo ci) { + if(VereyaModClient.MyMouse.class.isInstance(this)){ + VereyaModClient.MyMouse myMouse = ((VereyaModClient.MyMouse)((Object)this)); + myMouse.onMouseUsed(); + } + } + /** * Cancellable injection, note that we set the "cancellable" * flag to "true" in the injector annotation @@ -21,10 +25,9 @@ public class MouseMixin { @Inject(method = "onCursorPos", at = @At("HEAD"), cancellable = true) private void onOnCursorPos(long window, double x, double y, CallbackInfo ci) { if(VereyaModClient.MyMouse.class.isInstance(this)){ - // it's not possible to cast 'this' to MyMouse - // one way is to cast this to Object and then object to MyMouse - // or use class.getDeclaredMethod etc - boolean result = ((VereyaModClient.MyMouse)((Object)this)).shouldUpdate(); + VereyaModClient.MyMouse myMouse = ((VereyaModClient.MyMouse)((Object)this)); + myMouse.onMouseUsed(); + boolean result = myMouse.shouldUpdate(); if (result) return; ci.cancel();