diff --git a/src/main/java/com/minecrafttas/tasmod/gui/InfoHud.java b/src/main/java/com/minecrafttas/tasmod/gui/InfoHud.java
index 2296e035..7cc413c3 100644
--- a/src/main/java/com/minecrafttas/tasmod/gui/InfoHud.java
+++ b/src/main/java/com/minecrafttas/tasmod/gui/InfoHud.java
@@ -350,18 +350,18 @@ public boolean checkInit() {
// return String.format("Mouse Cursor: " + TASmodClient.virtual.getNextMouse().getPath().get(0).cursorX + " " + TASmodClient.virtual.getNextMouse().getPath().get(0).cursorY);
// })); TODO Remove?
- title = "trajectories";
- y += 14;
- if (configuration.getProperty(title + "_x", "err").equals("err")) setDefaults(title, y);
- lists.add(new InfoLabel(title, Integer.parseInt(configuration.getProperty(title + "_x")), Integer.parseInt(configuration.getProperty(title + "_y")), Boolean.parseBoolean(configuration.getProperty(title + "_visible")), Boolean.parseBoolean(configuration.getProperty(title + "_rect")), () -> {
- if (Minecraft.getMinecraft().currentScreen == this) return "Trajectories";
- String message = "Invalid Item";
- Vec3d vec = TrajectoriesCalculator.calculate();
- if (vec != null) {
- message = String.format("%.3f %.3f %.3f", vec.x, vec.y, vec.z);
- }
- return String.format("Trajectories: " + message);
- }));
+// title = "trajectories";
+// y += 14;
+// if (configuration.getProperty(title + "_x", "err").equals("err")) setDefaults(title, y);
+// lists.add(new InfoLabel(title, Integer.parseInt(configuration.getProperty(title + "_x")), Integer.parseInt(configuration.getProperty(title + "_y")), Boolean.parseBoolean(configuration.getProperty(title + "_visible")), Boolean.parseBoolean(configuration.getProperty(title + "_rect")), () -> {
+// if (Minecraft.getMinecraft().currentScreen == this) return "Trajectories";
+// String message = "Invalid Item";
+// Vec3d vec = TrajectoriesCalculator.calculate();
+// if (vec != null) {
+// message = String.format("%.3f %.3f %.3f", vec.x, vec.y, vec.z);
+// }
+// return String.format("Trajectories: " + message);
+// }));
title = "velocity";
y += 14;
diff --git a/src/main/java/com/minecrafttas/tasmod/handlers/LoadingScreenHandler.java b/src/main/java/com/minecrafttas/tasmod/handlers/LoadingScreenHandler.java
index 47e983e9..92bcb00b 100644
--- a/src/main/java/com/minecrafttas/tasmod/handlers/LoadingScreenHandler.java
+++ b/src/main/java/com/minecrafttas/tasmod/handlers/LoadingScreenHandler.java
@@ -63,7 +63,7 @@ public void onDoneLoadingWorld() {
LOGGER.debug(LoggerMarkers.Event, "Finished loading the world on the client");
loadingScreenDelay = 1;
- TASmodClient.virtual.unpress();
+ TASmodClient.virtual.clear();
}
}
diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/playbackhooks/MixinEntityRenderer.java b/src/main/java/com/minecrafttas/tasmod/mixin/playbackhooks/MixinEntityRenderer.java
index ee4263b0..7fff25e5 100644
--- a/src/main/java/com/minecrafttas/tasmod/mixin/playbackhooks/MixinEntityRenderer.java
+++ b/src/main/java/com/minecrafttas/tasmod/mixin/playbackhooks/MixinEntityRenderer.java
@@ -1,27 +1,33 @@
package com.minecrafttas.tasmod.mixin.playbackhooks;
+import org.apache.commons.lang3.tuple.Triple;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.ModifyArg;
+import org.spongepowered.asm.mixin.injection.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalFloatRef;
import com.minecrafttas.tasmod.TASmodClient;
import com.minecrafttas.tasmod.util.Ducks.SubtickDuck;
import com.minecrafttas.tasmod.virtual.VirtualInput;
+
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.util.math.MathHelper;
-import org.apache.commons.lang3.tuple.Triple;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Shadow;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.ModifyArg;
-import org.spongepowered.asm.mixin.injection.Redirect;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Redirects the camera to use {@link VirtualInput.VirtualCameraAngleInput}.
- * Also conforms the camera to 20tps as
+ * To support handling the camera in TASes and to avoid desyncs via lag,
+ * it was decided to only update the camera every tick.
+ *
+ * To achieve this, some parts of the vanilla code were disabled, but get called every tick in {@link #runUpdate(float)}
+ *
+ * @author Scribble, Pancake
*/
@Mixin(EntityRenderer.class)
public class MixinEntityRenderer implements SubtickDuck {
@@ -45,7 +51,7 @@ public void playback_injectAtStartSection(float partialTicks, long nanoTime, Cal
float f = this.mc.gameSettings.mouseSensitivity * 0.6F + 0.2F;
float f1 = f * f * f * 8.0F;
- if (this.mc.currentScreen == null) { // No Gui
+ if (this.mc.currentScreen == null && !TASmodClient.controller.isPlayingback() && mc.player != null) { // No Gui
mc.mouseHelper.mouseXYChange();
mc.getTutorial().handleMouse(mc.mouseHelper);
TASmodClient.virtual.CAMERA_ANGLE.updateNextCameraAngle((float) -(mc.mouseHelper.deltaY * f1 * 0.15D), (float) (mc.mouseHelper.deltaX * f1 * 0.15D));
@@ -64,11 +70,19 @@ public void runUpdate(float partialTicks) {
if(mc.player == null){
return;
}
+ TASmodClient.virtual.CAMERA_ANGLE.nextCameraTick();
+
float prevPitch = mc.player.rotationPitch;
float prevYaw = mc.player.rotationYaw;
- TASmodClient.virtual.CAMERA_ANGLE.nextCameraTick();
- mc.player.rotationPitch = TASmodClient.virtual.CAMERA_ANGLE.getCurrentPitch();
- mc.player.rotationYaw = TASmodClient.virtual.CAMERA_ANGLE.getCurrentYaw();
+ Float newPitch = TASmodClient.virtual.CAMERA_ANGLE.getCurrentPitch();
+ Float newYaw = TASmodClient.virtual.CAMERA_ANGLE.getCurrentYaw();
+
+ if(newPitch == null) {
+ TASmodClient.virtual.CAMERA_ANGLE.setCamera(prevPitch, prevYaw);
+ return;
+ }
+ mc.player.rotationPitch = newPitch;
+ mc.player.rotationYaw = newYaw;
mc.player.prevRotationPitch = prevPitch;
mc.player.prevRotationYaw = prevYaw;
diff --git a/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java b/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java
index b734f08f..64247e25 100644
--- a/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java
+++ b/src/main/java/com/minecrafttas/tasmod/playback/PlaybackControllerClient.java
@@ -232,7 +232,7 @@ public String setTASStateClient(TASstate stateIn, boolean verbose) {
return verbose ? TextFormatting.GREEN + "Pausing a recording" : "";
case NONE:
LOGGER.debug(LoggerMarkers.Playback, "Stopping a recording");
- TASmodClient.virtual.unpress();
+ TASmodClient.virtual.clear();
state = TASstate.NONE;
return verbose ? TextFormatting.GREEN + "Stopping the recording" : "";
}
@@ -246,12 +246,12 @@ public String setTASStateClient(TASstate stateIn, boolean verbose) {
LOGGER.debug(LoggerMarkers.Playback, "Pausing a playback");
state = TASstate.PAUSED;
tempPause = TASstate.PLAYBACK;
- TASmodClient.virtual.unpress();
+ TASmodClient.virtual.clear();
return verbose ? TextFormatting.GREEN + "Pausing a playback" : "";
case NONE:
LOGGER.debug(LoggerMarkers.Playback, "Stopping a playback");
Minecraft.getMinecraft().gameSettings.chatLinks = true;
- TASmodClient.virtual.unpress();
+ TASmodClient.virtual.clear();
state = TASstate.NONE;
return verbose ? TextFormatting.GREEN + "Stopping the playback" : "";
}
diff --git a/src/main/java/com/minecrafttas/tasmod/util/Ducks.java b/src/main/java/com/minecrafttas/tasmod/util/Ducks.java
index 5b785a6a..533affea 100644
--- a/src/main/java/com/minecrafttas/tasmod/util/Ducks.java
+++ b/src/main/java/com/minecrafttas/tasmod/util/Ducks.java
@@ -81,6 +81,10 @@ public static interface GuiScreenDuck {
* Quacks the subtick
*/
public static interface SubtickDuck {
+ /**
+ * Custom updating method for EntityRenderer, updating the player rotation
+ * @param partialTicks The partial ticks from the vanilla Minecraft timer
+ */
void runUpdate(float partialTicks);
}
diff --git a/src/main/java/com/minecrafttas/tasmod/util/FileThread.java b/src/main/java/com/minecrafttas/tasmod/util/FileThread.java
index cdf61425..759c5af1 100644
--- a/src/main/java/com/minecrafttas/tasmod/util/FileThread.java
+++ b/src/main/java/com/minecrafttas/tasmod/util/FileThread.java
@@ -9,12 +9,17 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * Thread for writing files to disc
+ *
+ * @author Pancake
+ */
public class FileThread extends Thread {
- private PrintWriter stream;
+ private final PrintWriter stream;
private boolean end = false;
- private List output = new ArrayList();
+ private final List output = new ArrayList<>();
public FileThread(File fileLocation, boolean append) throws FileNotFoundException {
stream = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileLocation, append), StandardCharsets.UTF_8));
diff --git a/src/main/java/com/minecrafttas/tasmod/util/PointerNormalizer.java b/src/main/java/com/minecrafttas/tasmod/util/PointerNormalizer.java
index e9136f0d..12a6d2a2 100644
--- a/src/main/java/com/minecrafttas/tasmod/util/PointerNormalizer.java
+++ b/src/main/java/com/minecrafttas/tasmod/util/PointerNormalizer.java
@@ -5,37 +5,41 @@
import net.minecraft.client.gui.GuiWorldSelection;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.gui.inventory.GuiContainer;
-import net.minecraft.client.gui.inventory.GuiContainerCreative;
/**
- * Adjusts the pointer/cursor of the playback to different gui scalings.
- *
- * This was the work of many hours of trial and error.
- *
- * Out of despair I reached out to Darkmoon to help me with this problem...
- *
- * @author ScribbleLP, Darkmoon
+ * Normalizes the cursor to be independent of gui scalings.
+ * That way, a TAS recorded in e.g. Gui Scale "Large" can also be played back on Gui Scale "Small"
*
+ * @author Scribble, Darkmoon
*/
public class PointerNormalizer {
+ /**
+ * Mathematically removes scaling from the x coordinate
+ * @param pointerX The current pointer coordinate
+ * @return The normalized x coordinate
+ */
public static int getNormalizedX(int pointerX) {
Minecraft mc = Minecraft.getMinecraft();
ScaledResolution scaled = new ScaledResolution(mc);
- int out = (int) (pointerX - (scaled.getScaledWidth() / 2D));
- return out;
+ return (int) (pointerX - (scaled.getScaledWidth() / 2D));
}
+ /**
+ * Mathematically removes scaling from the y coordinate
+ * @param pointerY The current pointer coordinate
+ * @return The normalized y coordinate
+ */
public static int getNormalizedY(int pointerY) {
Minecraft mc = Minecraft.getMinecraft();
ScaledResolution scaled = new ScaledResolution(mc);
int out = pointerY;
- if (mc.currentScreen instanceof GuiContainer || mc.currentScreen instanceof GuiContainerCreative) {
+ if (mc.currentScreen instanceof GuiContainer) {
out = (int) (pointerY - (scaled.getScaledHeight() / 2D));
} else if (mc.currentScreen instanceof GuiWorldSelection|| mc.currentScreen instanceof GuiMultiplayer) {
-
+ // TODO Figure out what to do here
} else {
out = (int) (pointerY - (scaled.getScaledHeight() / 4 + 72 + -16));
}
@@ -43,62 +47,62 @@ public static int getNormalizedY(int pointerY) {
return out;
}
- public static int getCoordsX(int normalizedX) {
+ /**
+ * Reapplies gui scaling to the normalized pointer x coordinate
+ * @param normalizedX The normalized pointer coordinate
+ * @return The scaled coordinate
+ */
+ public static int reapplyScalingX(int normalizedX) {
Minecraft mc = Minecraft.getMinecraft();
ScaledResolution scaled = new ScaledResolution(mc);
int out = (int) Math.round(normalizedX + (scaled.getScaledWidth() / 2D));
- return limiterX(out, scaled);
+ return clamp(out, 0, scaled.getScaledWidth());
}
- public static int getCoordsY(int normalizedY) {
+ /**
+ * Reapplies gui scaling to the normalized pointer y coordinate
+ * @param normalizedY The normalized pointer coordinate
+ * @return The scaled coordinate
+ */
+ public static int reapplyScalingY(int normalizedY) {
Minecraft mc = Minecraft.getMinecraft();
ScaledResolution scaled = new ScaledResolution(mc);
int out = normalizedY;
- if (mc.currentScreen instanceof GuiContainer || mc.currentScreen instanceof GuiContainerCreative) {
+ if (mc.currentScreen instanceof GuiContainer) {
out = (int) Math.round(normalizedY + (scaled.getScaledHeight() / 2D));
} else if (mc.currentScreen instanceof GuiWorldSelection || mc.currentScreen instanceof GuiMultiplayer) {
-
+ // TODO Figure out what to do here
} else {
out = (int) (normalizedY + (scaled.getScaledHeight() / 4 + 72 + -16));
}
- return limiterY(out, scaled);
- }
-
- private static int limiterX(int out, ScaledResolution scaled) {
- int width = scaled.getScaledWidth();
- if (out > width) {
- out = width;
- } else if (out < 0)
- out = 0;
- return out;
- }
-
- private static int limiterY(int out, ScaledResolution scaled) {
- int height = scaled.getScaledHeight();
- if (out > height) {
- out = height;
- } else if (out < 0)
- out = 0;
- return out;
+ return clamp(out, 0, scaled.getScaledHeight());
}
- private static int gcd(int a, int b) {
- return (b == 0) ? a : gcd(b, a % b);
+ private static int clamp(int value, int lower, int upper) {
+ if (value < lower) {
+ return lower;
+ } else {
+ return Math.min(value, upper);
+ }
}
public static void printAspectRatio() {
int height = Minecraft.getMinecraft().displayHeight;
int width = Minecraft.getMinecraft().displayWidth;
- int gcd = gcd(width, height);
+ int gcd = greatestCommonDivisor(width, height);
if (gcd == 0) {
System.out.println(gcd);
} else {
System.out.println(width / gcd + ":" + height / gcd);
}
}
-
+
+ private static int greatestCommonDivisor(int a, int b) {
+ return (b == 0) ? a : greatestCommonDivisor(b, a % b);
+ }
+
/*
* Here lies 10 hours of work for something I didn't even use. This code
* normalizes the pointers coordinates and scales it depending on the screen
diff --git a/src/main/java/com/minecrafttas/tasmod/util/Scheduler.java b/src/main/java/com/minecrafttas/tasmod/util/Scheduler.java
index fd13454b..9e462b3a 100644
--- a/src/main/java/com/minecrafttas/tasmod/util/Scheduler.java
+++ b/src/main/java/com/minecrafttas/tasmod/util/Scheduler.java
@@ -7,7 +7,6 @@
* A simple scheduling interface
*
* @author Scribble
- *
*/
public class Scheduler {
diff --git a/src/main/java/com/minecrafttas/tasmod/util/ShieldDownloader.java b/src/main/java/com/minecrafttas/tasmod/util/ShieldDownloader.java
index 4f514c1e..2588c4e1 100644
--- a/src/main/java/com/minecrafttas/tasmod/util/ShieldDownloader.java
+++ b/src/main/java/com/minecrafttas/tasmod/util/ShieldDownloader.java
@@ -30,6 +30,11 @@
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;
+/**
+ * Downloads shield textures from
+ *
+ * Similar to {@link VirtualKeyboard} and {@link VirtualMouse} with the difference,
+ * that no difference calculation is applied and only the absolute camera coordinates are used.
+ * This makes the playback desync proof to different mouse sensitivity across PCs.
+ *
+ */
public class VirtualCameraAngle extends Subtickable implements Serializable {
- private float pitch;
- private float yaw;
-
+ /**
+ * Controls the up/down coordinate of the camera. Clamped between -90 and +90
+ */
+ private Float pitch;
+ /**
+ * Controls the left/right coordinate of the camera. In this case the camera is clamped between -180 and +180
+ */
+ private Float yaw;
+
+ /**
+ * Creates an empty camera angle with pitch and yaw = 0
+ */
public VirtualCameraAngle() {
- this(0, 0, new ArrayList<>(), true);
+ this(null, null, new ArrayList<>(), true);
}
- public VirtualCameraAngle(float pitch, float yaw) {
+ /**
+ * Creates a subtick camera angle with {@link Subtickable#subtickList} uninitialized
+ * @param pitch {@link #pitch}
+ * @param yaw {@link #yaw}
+ */
+ public VirtualCameraAngle(Float pitch, Float yaw) {
this(pitch, yaw, null);
}
- public VirtualCameraAngle(float pitch, float yaw, List subtickList) {
+ /**
+ * Creates a parent camera angle
+ * @param pitch {@link #pitch}
+ * @param yaw {@link #yaw}
+ * @param ignoreFirstUpdate {@link Subtickable#ignoreFirstUpdate}
+ */
+ public VirtualCameraAngle(Float pitch, Float yaw, boolean ignoreFirstUpdate) {
+ this(pitch, yaw, new ArrayList<>(), ignoreFirstUpdate);
+ }
+
+ /**
+ * Creates a camera angle with existing values
+ * @param pitch {@link #pitch}
+ * @param yaw {@link #yaw}
+ * @param subtickList {@link Subtickable#subtickList}
+ */
+ public VirtualCameraAngle(Float pitch, Float yaw, List subtickList) {
this(pitch, yaw, subtickList, false);
}
-
- public VirtualCameraAngle(float pitch, float yaw, List subtickList, boolean ignoreFirstUpdate) {
+
+ /**
+ * Creates a camera angle with initialized values
+ * @param pitch {@link VirtualCameraAngle#pitch}
+ * @param yaw {@link VirtualCameraAngle#yaw}
+ * @param subtickList {@link Subtickable#subtickList}
+ * @param ignoreFirstUpdate {@link Subtickable#ignoreFirstUpdate}
+ */
+ public VirtualCameraAngle(Float pitch, Float yaw, List subtickList, boolean ignoreFirstUpdate) {
super(subtickList, ignoreFirstUpdate);
this.pitch = pitch;
this.yaw = yaw;
}
- public void update(float pitch, float yaw) {
+ /**
+ * Updates the camera angle.
+ * @param pitchDelta The difference between absolute coordinates of the pitch, is added to {@link VirtualCameraAngle#pitch}
+ * @param yawDelta The difference between absolute coordinates of the yaw, is added to {@link VirtualCameraAngle#yaw}
+ */
+ public void update(float pitchDelta, float yawDelta) {
+ if(pitch==null || yaw == null) {
+ return;
+ }
if(isParent() && !ignoreFirstUpdate()) {
addSubtick(clone());
}
- this.pitch += pitch;
- this.pitch = MathHelper.clamp(this.pitch, -90.0F, 90.0F);
- this.yaw += yaw;
+ this.pitch = MathHelper.clamp(this.pitch + pitchDelta, -90.0F, 90.0F);
+ this.yaw += yawDelta;
}
+ public void set(float pitch, float yaw) {
+ this.pitch = pitch;
+ this.yaw = yaw;
+ }
+
+ /**
+ * A list of all camera states in this VirtualCameraAngle.
+ * It consists of: {@link Subtickable#subtickList} + this
+ * @param reference A list of VirtualCameraAngles with the newest being the current camera angle
+ */
public void getStates(List reference) {
if (isParent()) {
reference.addAll(subtickList);
@@ -44,6 +107,10 @@ public void getStates(List reference) {
}
}
+ /**
+ * Copies the data from another camera angle into this camera without creating a new object.
+ * @param camera The camera to move from
+ */
public void copyFrom(VirtualCameraAngle camera) {
this.pitch = camera.pitch;
this.yaw = camera.yaw;
@@ -52,6 +119,14 @@ public void copyFrom(VirtualCameraAngle camera) {
camera.subtickList.clear();
}
+ public void clear() {
+ this.pitch = null;
+ this.yaw = null;
+ }
+
+ /**
+ * Creates a clone of this object as a subtick
+ */
@Override
public VirtualCameraAngle clone() {
return new VirtualCameraAngle(pitch, yaw);
@@ -61,21 +136,36 @@ public VirtualCameraAngle clone() {
public boolean equals(Object obj) {
if (obj instanceof VirtualCameraAngle) {
VirtualCameraAngle angle = (VirtualCameraAngle) obj;
- return pitch == angle.pitch && yaw == angle.yaw;
+ return (pitch != null && pitch.equals(angle.pitch)) && (yaw != null && yaw.equals(angle.yaw));
}
return super.equals(obj);
}
@Override
public String toString() {
+ if(isParent()) {
+ return getAll().stream().map(VirtualCameraAngle::toString2).collect(Collectors.joining("\n"));
+ } else {
+ return toString2();
+ }
+ }
+
+ private String toString2() {
return String.format("%s;%s", pitch, yaw);
}
- public float getPitch() {
+ /**
+ * @return {@link #pitch}
+ */
+ public Float getPitch() {
return pitch;
}
- public float getYaw() {
+ /**
+ * @return {@link #yaw}
+ */
+ public Float getYaw() {
return yaw;
}
+
}
diff --git a/src/main/java/com/minecrafttas/tasmod/virtual/VirtualInput.java b/src/main/java/com/minecrafttas/tasmod/virtual/VirtualInput.java
index 7ed018c0..9d55fe88 100644
--- a/src/main/java/com/minecrafttas/tasmod/virtual/VirtualInput.java
+++ b/src/main/java/com/minecrafttas/tasmod/virtual/VirtualInput.java
@@ -5,7 +5,6 @@
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
-import com.minecrafttas.tasmod.TASmodClient;
import org.apache.commons.lang3.tuple.Triple;
import org.apache.logging.log4j.Logger;
import org.lwjgl.input.Keyboard;
@@ -16,7 +15,6 @@
import com.minecrafttas.tasmod.util.Ducks;
import com.minecrafttas.tasmod.util.LoggerMarkers;
import com.minecrafttas.tasmod.util.PointerNormalizer;
-import com.minecrafttas.tasmod.virtual.event.VirtualCameraAngleEvent;
import com.minecrafttas.tasmod.virtual.event.VirtualKeyboardEvent;
import com.minecrafttas.tasmod.virtual.event.VirtualMouseEvent;
@@ -130,9 +128,10 @@ public boolean willKeyBeDown(int keycode) {
/**
* Unpresses all keys in {@link VirtualKeyboardInput#nextKeyboard} and {@link VirtualMouseInput#nextMouse}
*/
- public void unpress() {
+ public void clear() {
KEYBOARD.nextKeyboard.clear();
MOUSE.nextMouse.clear();
+ CAMERA_ANGLE.nextCameraAngle.clear();
}
/**
@@ -385,7 +384,7 @@ public VirtualMouseInput(VirtualMouse preloadedMouse) {
* @see VirtualInput#update(GuiScreen)
* @param keycode The keycode of this event
* @param keystate The keystate of this event
- * @param scrollwheel The scrollWheel of this event
+ * @param scrollwheel The scrollwheel direction of this event
* @param cursorX The x coordinate of the cursor of this event
* @param cursorY The y coordinate of the cursot of this event
*/
@@ -443,14 +442,14 @@ public int getEventMouseScrollWheel() {
* @return The x coordinate of the cursor of {@link #currentMouseEvent}
*/
public int getEventCursorX() {
- return PointerNormalizer.getCoordsX(currentMouseEvent.getCursorX());
+ return PointerNormalizer.reapplyScalingX(currentMouseEvent.getCursorX());
}
/**
* @return The y coordinate of the cursor of {@link #currentMouseEvent}
*/
public int getEventCursorY() {
- return PointerNormalizer.getCoordsY(currentMouseEvent.getCursorY());
+ return PointerNormalizer.reapplyScalingY(currentMouseEvent.getCursorY());
}
/**
@@ -474,15 +473,37 @@ public boolean willKeyBeDown(int keycode) {
}
+ /**
+ * Subclass of {@link VirtualInput} handling camera angle logic.
+ *
+ * Unlike {@link VirtualKeyboardInput} or {@link VirtualMouseInput} no subtick behaviour is implemented,
+ * making this a simple pitch and yaw storing class, allowing for redirection.
+ *
+ * In theory, subtick behaviour is possible, but only useful for interpolation,
+ * as the camera angle is only updated every tick (see {@link com.minecrafttas.tasmod.mixin.playbackhooks.MixinEntityRenderer}).
+ */
public class VirtualCameraAngleInput {
+ /**
+ * The current camera angle
+ */
private final VirtualCameraAngle currentCameraAngle;
private final VirtualCameraAngle nextCameraAngle = new VirtualCameraAngle();
private final List cameraAngleInterpolationStates = new ArrayList<>();
-
+
+ /**
+ * Constructor to preload the {@link #currentCameraAngle} with an existing camera angle
+ * @param preloadedCamera The new {@link #currentCameraAngle}
+ */
public VirtualCameraAngleInput(VirtualCameraAngle preloadedCamera) {
currentCameraAngle = preloadedCamera;
}
-
+
+ /**
+ * Update the camera angle
+ * @see com.minecrafttas.tasmod.mixin.playbackhooks.MixinEntityRenderer#runUpdate(float);
+ * @param pitch Absolute rotationPitch of the player
+ * @param yaw Absolute rotationYaw of the player
+ */
public void updateNextCameraAngle(float pitch, float yaw) {
// LOGGER.debug("Pitch: {}, Yaw: {}", pitch, yaw);
nextCameraAngle.update(pitch, yaw);
@@ -493,17 +514,21 @@ public void nextCameraTick() {
currentCameraAngle.copyFrom(nextCameraAngle);
}
- public float getCurrentPitch() {
+ public void setCamera(Float pitch, Float yaw) {
+ nextCameraAngle.set(pitch, yaw);
+ }
+
+ public Float getCurrentPitch() {
return currentCameraAngle.getPitch();
}
- public float getCurrentYaw() {
+ public Float getCurrentYaw() {
return currentCameraAngle.getYaw();
}
public Triple getInterpolatedState(float partialTick, float pitch, float yaw, boolean enable){
if(!enable) {
- return Triple.of(TASmodClient.virtual.CAMERA_ANGLE.nextCameraAngle.getPitch(), TASmodClient.virtual.CAMERA_ANGLE.nextCameraAngle.getYaw()+180, 0f);
+ return Triple.of(nextCameraAngle.getPitch()==null ? pitch : nextCameraAngle.getPitch(), nextCameraAngle.getYaw()==null? pitch : nextCameraAngle.getYaw()+180, 0f);
}
float interpolatedPitch = 0f;
diff --git a/src/main/java/com/minecrafttas/tasmod/virtual/VirtualKeyboard.java b/src/main/java/com/minecrafttas/tasmod/virtual/VirtualKeyboard.java
index ae96365d..d12bea00 100644
--- a/src/main/java/com/minecrafttas/tasmod/virtual/VirtualKeyboard.java
+++ b/src/main/java/com/minecrafttas/tasmod/virtual/VirtualKeyboard.java
@@ -252,7 +252,7 @@ public void addChar(char character, boolean repeatEventsEnabled) {
}
@Override
- protected void clear(){
+ public void clear(){
super.clear();
charList.clear();
}
diff --git a/src/main/java/com/minecrafttas/tasmod/virtual/VirtualMouse.java b/src/main/java/com/minecrafttas/tasmod/virtual/VirtualMouse.java
index fe1cca43..4329fc05 100644
--- a/src/main/java/com/minecrafttas/tasmod/virtual/VirtualMouse.java
+++ b/src/main/java/com/minecrafttas/tasmod/virtual/VirtualMouse.java
@@ -6,6 +6,15 @@
import java.util.*;
import java.util.stream.Collectors;
+/**
+ * Stores the mouse specific values in a given timeframe
+ *
+ * Similar to {@link VirtualKeyboard}, but instead of a list of characters,
+ * it stores the state of the scroll wheel and the cursors x and y coordinate on screen.
+ *
+ * @author Scribble
+ * @see VirtualInput.VirtualMouseInput
+ */
public class VirtualMouse extends VirtualPeripheral implements Serializable {
/**
@@ -123,25 +132,25 @@ public void getVirtualEvents(VirtualMouse nextMouse, Queue re
* the one from tick 16
* @param reference The queue to fill. Passed in by reference.
*/
- public void getDifference(VirtualMouse nextPeripheral, Queue reference) {
+ public void getDifference(VirtualMouse nextMouse, Queue reference) {
/*
* Checks if pressedKeys are the same...
*/
- if(pressedKeys.equals(nextPeripheral.pressedKeys)){
+ if(pressedKeys.equals(nextMouse.pressedKeys)){
- /**
+ /*
* ...but scrollWheel, cursorX or cursorY are different.
* Without this, the scrollWheel would only work if a mouse button is pressed at the same time.
*/
- if(!equals(nextPeripheral)) {
- reference.add(new VirtualMouseEvent(VirtualKey.MOUSEMOVED.getKeycode(), false, nextPeripheral.scrollWheel, nextPeripheral.cursorX, nextPeripheral.cursorY));
+ if(!equals(nextMouse)) {
+ reference.add(new VirtualMouseEvent(VirtualKey.MOUSEMOVED.getKeycode(), false, nextMouse.scrollWheel, nextMouse.cursorX, nextMouse.cursorY));
}
return;
}
- int scrollWheelCopy = nextPeripheral.scrollWheel;
- int cursorXCopy = nextPeripheral.cursorX;
- int cursorYCopy = nextPeripheral.cursorY;
+ int scrollWheelCopy = nextMouse.scrollWheel;
+ int cursorXCopy = nextMouse.cursorX;
+ int cursorYCopy = nextMouse.cursorY;
/* Calculate symmetric difference of keycodes */
@@ -153,7 +162,7 @@ public void getDifference(VirtualMouse nextPeripheral, Queue
RC <- unpressed
*/
for(int keycode : pressedKeys) {
- if (!nextPeripheral.getPressedKeys().contains(keycode)) {
+ if (!nextMouse.getPressedKeys().contains(keycode)) {
reference.add(new VirtualMouseEvent(keycode, false, scrollWheelCopy, cursorXCopy, cursorYCopy));
scrollWheelCopy = 0;
cursorXCopy = 0;
@@ -168,7 +177,7 @@ public void getDifference(VirtualMouse nextPeripheral, Queue
-------------
MC <- pressed
*/
- for(int keycode : nextPeripheral.getPressedKeys()) {
+ for(int keycode : nextMouse.getPressedKeys()) {
if (!this.pressedKeys.contains(keycode)) {
reference.add(new VirtualMouseEvent(keycode, true, scrollWheelCopy, cursorXCopy, cursorYCopy));
}
@@ -176,7 +185,7 @@ public void getDifference(VirtualMouse nextPeripheral, Queue
}
@Override
- protected void clear() {
+ public void clear() {
super.clear();
clearMouseData();
}
diff --git a/src/test/java/tasmod/virtual/VirtualCameraAngleTest.java b/src/test/java/tasmod/virtual/VirtualCameraAngleTest.java
new file mode 100644
index 00000000..1809c867
--- /dev/null
+++ b/src/test/java/tasmod/virtual/VirtualCameraAngleTest.java
@@ -0,0 +1,144 @@
+package tasmod.virtual;
+
+import com.minecrafttas.tasmod.virtual.VirtualCameraAngle;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+public class VirtualCameraAngleTest {
+
+ /**
+ * Test the empty constructor
+ */
+ @Test
+ void testEmptyConstructor(){
+ VirtualCameraAngle actual = new VirtualCameraAngle();
+ assertEquals(null, actual.getPitch());
+ assertEquals(null, actual.getYaw());
+ assertTrue(actual.isParent());
+ }
+
+ /**
+ * Test subtick constructor with premade pitch and value
+ */
+ @Test
+ void testSubtickConstructor(){
+ float x = 1f;
+ float y = 2f;
+
+ VirtualCameraAngle actual = new VirtualCameraAngle(x, y);
+ assertEquals(1f, actual.getPitch());
+ assertEquals(2f, actual.getYaw());
+ assertFalse(actual.isParent());
+ }
+
+ /**
+ * Testing update function
+ */
+ @Test
+ void testUpdate(){
+ float x = 1f;
+ float y = 2f;
+
+ VirtualCameraAngle actual = new VirtualCameraAngle(0f, 0f, true);
+
+ actual.update(x, y);
+
+ assertEquals(1f, actual.getPitch());
+ assertEquals(2f, actual.getYaw());
+ }
+
+ /**
+ * Testing update function, but with a pitch higher/lower than 90/-90
+ */
+ @Test
+ void testUpdateWithBadPitch() {
+ VirtualCameraAngle actual = new VirtualCameraAngle(0f, 0f, true);
+
+ actual.update(-100f, 0f);
+
+ assertEquals(-90f, actual.getPitch());
+
+ actual.update(360f, 0f);
+
+ assertEquals(90f, actual.getPitch());
+ }
+
+ /**
+ * Test copyfrom method
+ */
+ @Test
+ void copyFrom() {
+ VirtualCameraAngle actual = new VirtualCameraAngle();
+ actual.update(1f, 2f);
+ actual.update(3f, 4f);
+ }
+
+ /**
+ * Test the toString method without subticks
+ */
+ @Test
+ void testToString() {
+ float x = 1f;
+ float y = 2f;
+
+ VirtualCameraAngle actual = new VirtualCameraAngle(x, y);
+
+ assertEquals("1.0;2.0", actual.toString());
+ }
+
+ /**
+ * Test the toString method with subticks
+ */
+ @Test
+ void testToStringSubticks() {
+
+ VirtualCameraAngle actual = new VirtualCameraAngle(0f, 0f, true);
+ actual.update(1f, 2f);
+ actual.update(3f, 4f);
+ actual.update(5f, 6f);
+
+ assertEquals("1.0;2.0\n4.0;6.0\n9.0;12.0", actual.toString());
+ }
+
+ /**
+ * Test cloning the camera angle
+ */
+ @Test
+ void testClone(){
+ float x = 1f;
+ float y = 2f;
+
+ VirtualCameraAngle test = new VirtualCameraAngle(x, y);
+
+ VirtualCameraAngle actual = test.clone();
+
+ assertEquals(1f, actual.getPitch());
+ assertEquals(2f, actual.getYaw());
+ }
+
+ /**
+ * Test equals
+ */
+ @Test
+ void testEquals(){
+ float x = 1f;
+ float y = 2f;
+
+ VirtualCameraAngle test = new VirtualCameraAngle(x, y);
+ VirtualCameraAngle test2 = new VirtualCameraAngle(x, y);
+
+ assertEquals(test, test2);
+ }
+
+ /**
+ * Test where equals will fail
+ */
+ @Test
+ void testNotEquals(){
+
+ VirtualCameraAngle test = new VirtualCameraAngle(1f, 2f);
+ VirtualCameraAngle test2 = new VirtualCameraAngle(3f, 4f);
+
+ assertNotEquals(test, test2);
+ }
+}
diff --git a/src/test/java/tasmod/virtual/VirtualInputTest.java b/src/test/java/tasmod/virtual/VirtualInputTest.java
index bf184b57..30ce0947 100644
--- a/src/test/java/tasmod/virtual/VirtualInputTest.java
+++ b/src/test/java/tasmod/virtual/VirtualInputTest.java
@@ -35,7 +35,7 @@ void testConstructor() {
void testPreloadedConstructor() {
VirtualKeyboard preloadedKeyboard = new VirtualKeyboard();
VirtualMouse preloadedMouse = new VirtualMouse();
- VirtualCameraAngle preloadedCameraAngle = new VirtualCameraAngle();
+ VirtualCameraAngle preloadedCameraAngle = new VirtualCameraAngle(0f, 0f);
preloadedKeyboard.update(VirtualKey.W.getKeycode(), true, 'w');
preloadedMouse.update(VirtualKey.LC.getKeycode(), true, 15, 0, 0);