diff --git a/src/main/java/org/saturnclient/modules/ModManager.java b/src/main/java/org/saturnclient/modules/ModManager.java index 13d82f7..6ac6e2a 100644 --- a/src/main/java/org/saturnclient/modules/ModManager.java +++ b/src/main/java/org/saturnclient/modules/ModManager.java @@ -19,6 +19,7 @@ public class ModManager { new Fps(), new PotionDisplay(), new Coordinates(), + new Freelook() }; public static void init() { diff --git a/src/main/java/org/saturnclient/modules/README.md b/src/main/java/org/saturnclient/modules/README.md new file mode 100644 index 0000000..0eb81ca --- /dev/null +++ b/src/main/java/org/saturnclient/modules/README.md @@ -0,0 +1,6 @@ +# Credits +### Freelook +- https://github.com/Celibistrial/freelook +- https://modrinth.com/mod/freelook + +**The other mods are coded by us, if you have a concern or we missed something feel free to submit a issue with the credits tag** \ No newline at end of file diff --git a/src/main/java/org/saturnclient/modules/mods/Freelook.java b/src/main/java/org/saturnclient/modules/mods/Freelook.java new file mode 100644 index 0000000..d3a33c4 --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/Freelook.java @@ -0,0 +1,71 @@ +package org.saturnclient.modules.mods; + +import org.lwjgl.glfw.GLFW; +import org.saturnclient.modules.Module; +import org.saturnclient.modules.ModuleDetails; +import org.saturnclient.saturnclient.SaturnClient; +import org.saturnclient.saturnclient.config.Property; + +import net.minecraft.client.option.Perspective; + +public class Freelook extends Module { + private static Property enabled = Property.bool(false); + private static Property toggle = Property.bool(true); + public static Property freelookKey = Property.keybinding(GLFW.GLFW_KEY_H); + public static boolean isFreeLooking = false; + private static boolean was1stPerson = false; + + public Freelook() { + super( + new ModuleDetails("Freelook", "freelook") + .description("Allows you to look around freely without moving your character") + .tags("Movement", "Camera") + .version("0.1.0"), + enabled.named("Enabled"), + toggle.named("Toggle freelook"), + freelookKey.named("Freelook Keybinding") + ); + } + + @Override + public void tick() { + if (toggle.value) { + if (freelookKey.wasKeyPressed()) { + if (isFreeLooking) { + stopFreelook(); + } else { + startFreelook(); + } + } + } else if (freelookKey.isKeyPressed()) { + if (!isFreeLooking) { + startFreelook(); + } + } else if (isFreeLooking) { + stopFreelook(); + } + } + + private void startFreelook() { + isFreeLooking = true; + was1stPerson = SaturnClient.client.options.getPerspective() == Perspective.FIRST_PERSON; + SaturnClient.client.options.setPerspective(Perspective.THIRD_PERSON_BACK); + } + + private void stopFreelook() { + if (was1stPerson) { + SaturnClient.client.options.setPerspective(Perspective.FIRST_PERSON); + } + isFreeLooking = false; + } + + @Override + public void setEnabled(boolean e) { + enabled.value = e; + } + + @Override + public boolean isEnabled() { + return enabled.value; + } +} diff --git a/src/main/java/org/saturnclient/modules/mods/mixins/CameraMixin.java b/src/main/java/org/saturnclient/modules/mods/mixins/CameraMixin.java new file mode 100644 index 0000000..7c2cabc --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/mixins/CameraMixin.java @@ -0,0 +1,44 @@ +package org.saturnclient.modules.mods.mixins; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.render.Camera; +import net.minecraft.entity.Entity; +import net.minecraft.world.BlockView; + +import org.saturnclient.modules.mods.Freelook; +import org.saturnclient.modules.mods.utils.CameraOverriddenEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Camera.class) +public abstract class CameraMixin { + @Unique + boolean firstTime = true; + + @Shadow + protected abstract void setRotation(float yaw, float pitch); + + @Inject(method = "update", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/Camera;setRotation(FF)V", ordinal = 1, shift = At.Shift.AFTER)) + public void lockRotation(BlockView focusedBlock, Entity cameraEntity, boolean isThirdPerson, boolean isFrontFacing, float tickDelta, CallbackInfo ci) { + if (Freelook.isFreeLooking && cameraEntity instanceof ClientPlayerEntity) { + CameraOverriddenEntity cameraOverriddenEntity = (CameraOverriddenEntity) cameraEntity; + + if (firstTime && MinecraftClient.getInstance().player != null) { + cameraOverriddenEntity.freelook$setCameraPitch(MinecraftClient.getInstance().player.getPitch()); + cameraOverriddenEntity.freelook$setCameraYaw(MinecraftClient.getInstance().player.getYaw()); + firstTime = false; + } + this.setRotation(cameraOverriddenEntity.freelook$getCameraYaw(), cameraOverriddenEntity.freelook$getCameraPitch()); + + } + if (!Freelook.isFreeLooking && cameraEntity instanceof ClientPlayerEntity) { + firstTime = true; + } + } + +} \ No newline at end of file diff --git a/src/main/java/org/saturnclient/modules/mods/mixins/EntityMixin.java b/src/main/java/org/saturnclient/modules/mods/mixins/EntityMixin.java new file mode 100644 index 0000000..8442b43 --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/mixins/EntityMixin.java @@ -0,0 +1,62 @@ +package org.saturnclient.modules.mods.mixins; + + +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.MathHelper; + +import org.saturnclient.modules.mods.Freelook; +import org.saturnclient.modules.mods.utils.CameraOverriddenEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Entity.class) +public class EntityMixin implements CameraOverriddenEntity { + @Unique + private float cameraPitch; + + @Unique + private float cameraYaw; + + @Inject(method = "changeLookDirection", at = @At("HEAD"), cancellable = true) + public void changeCameraLookDirection(double xDelta, double yDelta, CallbackInfo ci) { + //noinspection ConstantValue// IntelliJ is incorrect here, this code block is reachable + if (Freelook.isFreeLooking && (Object) this instanceof ClientPlayerEntity) { + double pitchDelta = (yDelta * 0.15); + double yawDelta = (xDelta * 0.15); + + this.cameraPitch = MathHelper.clamp(this.cameraPitch + (float) pitchDelta, -90.0f, 90.0f); + this.cameraYaw += (float) yawDelta; + + ci.cancel(); + + } + } + + @Override + @Unique + public float freelook$getCameraPitch() { + return this.cameraPitch; + } + + @Override + @Unique + public float freelook$getCameraYaw() { + return this.cameraYaw; + } + + @Override + @Unique + public void freelook$setCameraPitch(float pitch) { + this.cameraPitch = pitch; + } + + @Override + @Unique + public void freelook$setCameraYaw(float yaw) { + this.cameraYaw = yaw; + } +} \ No newline at end of file diff --git a/src/main/java/org/saturnclient/modules/mods/utils/CameraOverriddenEntity.java b/src/main/java/org/saturnclient/modules/mods/utils/CameraOverriddenEntity.java new file mode 100644 index 0000000..169608f --- /dev/null +++ b/src/main/java/org/saturnclient/modules/mods/utils/CameraOverriddenEntity.java @@ -0,0 +1,9 @@ +package org.saturnclient.modules.mods.utils; + +public interface CameraOverriddenEntity { + float freelook$getCameraPitch(); + float freelook$getCameraYaw(); + + void freelook$setCameraPitch(float pitch); + void freelook$setCameraYaw(float yaw); +} \ No newline at end of file diff --git a/src/main/java/org/saturnclient/saturnclient/config/Property.java b/src/main/java/org/saturnclient/saturnclient/config/Property.java index 7dbd876..0940b70 100644 --- a/src/main/java/org/saturnclient/saturnclient/config/Property.java +++ b/src/main/java/org/saturnclient/saturnclient/config/Property.java @@ -26,6 +26,7 @@ public class Property { private T defaultValue; private String[] availableValues; private PropertyType type; + private boolean wasPressedLastTick = false; private Property(T value, PropertyType type) { this.value = value; @@ -198,4 +199,16 @@ public class Property { public boolean isKeyPressed() { return (Integer) value == -1 ? false : GLFW.glfwGetKey(SaturnClient.client.getWindow().getHandle(), (Integer) (Object) value) == GLFW.GLFW_PRESS; } + + public boolean wasKeyPressed() { + long window = SaturnClient.client.getWindow().getHandle(); + int key = (Integer) value; + + boolean isPressed = key != -1 && GLFW.glfwGetKey(window, key) == GLFW.GLFW_PRESS; + + boolean wasJustPressed = isPressed && !wasPressedLastTick; + wasPressedLastTick = isPressed; + + return wasJustPressed; + } } diff --git a/src/main/resources/mods.mixins.json b/src/main/resources/mods.mixins.json index d8b2ab9..fdda500 100644 --- a/src/main/resources/mods.mixins.json +++ b/src/main/resources/mods.mixins.json @@ -3,7 +3,10 @@ "minVersion": "0.8", "package": "org.saturnclient.modules.mods.mixins", "compatibilityLevel": "JAVA_21", - "client": [], + "client": [ + "CameraMixin", + "EntityMixin" + ], "injectors": { "defaultRequire": 1 }