Skip to content

Commit

Permalink
[VirtualInput] More documentation and tests
Browse files Browse the repository at this point in the history
- [Util] Added documentation
- [Util] Refactored PointerNormalizer
- [Gui] Disabled trajectories from InfoHud
- [VirtualInput] Refactored MixinEntityRenderer
- [VirtualInput] Fixed camera angle resetting to 0 on restart
  • Loading branch information
ScribbleTAS committed Feb 15, 2024
1 parent 2e3da8b commit 5681cd8
Show file tree
Hide file tree
Showing 15 changed files with 411 additions and 112 deletions.
24 changes: 12 additions & 12 deletions src/main/java/com/minecrafttas/tasmod/gui/InfoHud.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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}.<br>
* Also conforms the camera to 20tps as
* To support handling the camera in TASes and to avoid desyncs via lag,<br>
* it was decided to only update the camera every tick.<br>
* <br>
* 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 {
Expand All @@ -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));
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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" : "";
}
Expand All @@ -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" : "";
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/minecrafttas/tasmod/util/Ducks.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
9 changes: 7 additions & 2 deletions src/main/java/com/minecrafttas/tasmod/util/FileThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> output = new ArrayList<String>();
private final List<String> output = new ArrayList<>();

public FileThread(File fileLocation, boolean append) throws FileNotFoundException {
stream = new PrintWriter(new OutputStreamWriter(new FileOutputStream(fileLocation, append), StandardCharsets.UTF_8));
Expand Down
84 changes: 44 additions & 40 deletions src/main/java/com/minecrafttas/tasmod/util/PointerNormalizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,100 +5,104 @@
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.<br>
* 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));
}

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
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/minecrafttas/tasmod/util/Scheduler.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* A simple scheduling interface
*
* @author Scribble
*
*/
public class Scheduler {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;

/**
* Downloads shield textures from <a href="https://minecrafttas.com/>https://minecrafttas.com</a>
*
* @author Scribble
*/
public class ShieldDownloader implements EventPlayerJoinedClientSide, EventOtherPlayerJoinedClientSide{
private final ResourceLocation bottleshield = new ResourceLocation("tasmod:textures/shields/bottleshield.png");
private final String defaultshield = "bottleshield";
Expand Down
Loading

0 comments on commit 5681cd8

Please sign in to comment.