Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version v0.3.0 #37

Merged
merged 18 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,33 @@
- Fixed incorrect rolling when looking certain directions
- Now compatible with [do a barrel roll](https://modrinth.com/mod/do-a-barrel-roll) and hopefully other camera roll kinds of mods.
- The third-person camera while seated on a train is now improved. [View issue.](https://github.com/der-fruhling-entertainment/create-train-perspective/issues/24)
Major update to fix major problems. The mod is in a pretty good state now.

Known issues:
- The mod's leaning is a bit jittery. [View issue.](https://github.com/der-fruhling-entertainment/create-train-perspective/issues/22)
- This is probably more of a limitation of Minecraft itself. It might be fixable with a config option to emulate pitch, but that wouldn't make the player appear correctly to other players.
- Update: it's most definitely possible to fix this up.
- The easing back to normal posture after jumping off a train on a slope could use some work. [View issue.](https://github.com/der-fruhling-entertainment/create-train-perspective/issues/23)
The scoops:
- Players now look at their perceived down (e.g. the seat they're sitting in) rather than the real ground. [View issue.](https://github.com/der-fruhling-entertainment/create-train-perspective/issues/32)
- Fixed jittery leaning. [View issue.](https://github.com/der-fruhling-entertainment/create-train-perspective/issues/22)
- When targetting a block with the crosshair, the mod now makes some adjustments to target the block you should be looking at instead of the block the game thinks you're looking at. [View issue.](https://github.com/der-fruhling-entertainment/create-train-perspective/issues/35)
- This is probably incompatible with anti-cheat mods/plugins.
- The feature is also still _ever so slightly_ janky, but for most purposes it should be very usable.
- Fixed jittering of hand when traveling along the negative X axis.
- Fabric only: added a contact email.

[View full change log.](https://github.com/der-fruhling/create-train-perspective/compare/v0.2.2...v0.2.3)
[View full change log.](https://github.com/der-fruhling/create-train-perspective/compare/v0.2.3...v0.3.0)

---

In 0.1.2, I decided that the mod was basically ready and marked it as a Release version.

On second thought, I have realized the state of the mod and decided that Beta better describes its current state.
I have marked versions 0.2.2+ as Beta and all versions before that as Alpha to better represent this.

Of course, this does not mean that the mod is unusable or is going to break _everything_.
It just doesn't hold all the qualities I want it to.
In my opinion, A full Release version should be highly functional and configurable,
while retaining good compatibility with popular mods.

On that note, this version is _quality_ enough to be a release candidate,
and would be if it weren't for the missing things below:
- Configuration. [View issue.](https://github.com/der-fruhling-entertainment/create-train-perspective/issues/36)
- More accurate perspective. For a mod called "Create: _Train Perspective_", this is an important issue. [View issue.](https://github.com/der-fruhling-entertainment/create-train-perspective/issues/38)
- Some sound system and fog issues. Nothing major, but slightly annoying. [View issue.](https://github.com/der-fruhling-entertainment/create-train-perspective/issues/39)

---

Expand Down
21 changes: 10 additions & 11 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
Minor update to fix some issues.
Major update to fix major problems. The mod is in a pretty good state now.

- Fixed incorrect rolling when looking certain directions
- Now compatible with [do a barrel roll] and hopefully other camera roll kinds of mods.
- The third-person camera while seated on a train is now improved. https://github.com/der-fruhling-entertainment/create-train-perspective/issues/24
[Changelog]
- Players now look at their perceived down (e.g. the seat they're sitting in) rather than the real ground. https://github.com/der-fruhling-entertainment/create-train-perspective/issues/32
- Fixed jittery leaning. https://github.com/der-fruhling-entertainment/create-train-perspective/issues/22
- When targetting a block with the crosshair, the mod now makes some adjustments to target the block you should be looking at instead of the block the game thinks you're looking at. https://github.com/der-fruhling-entertainment/create-train-perspective/issues/35
- This is probably incompatible with anti-cheat mods/plugins.
- The feature is also still *ever so slightly* janky, but for most purposes it should be very usable.
- Fixed jittering of hand when traveling along the negative X axis.
- Fabric only: added a contact email.

Known issues:
- The mod's leaning is a bit jittery. https://github.com/der-fruhling-entertainment/create-train-perspective/issues/22
- This is probably more of a limitation of Minecraft itself. It might be fixable with a config option to emulate pitch, but that wouldn't make the player appear correctly to other players.
- Update: it's most definitely possible to fix this up.
- The easing back to normal posture after jumping off a train on a slope could use some work. https://github.com/der-fruhling-entertainment/create-train-perspective/issues/23

https://github.com/der-fruhling/create-train-perspective/compare/v0.2.2...v0.2.3
Commits: https://github.com/der-fruhling/create-train-perspective/compare/v0.2.3...v0.3.0

---

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

public interface Camera3D {
float getZRot();
float getExtraYRot();
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
import org.apache.commons.lang3.mutable.MutableInt;
import org.slf4j.Logger;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.*;

// The value here should match an entry in the META-INF/mods.toml file
public class CreateTrainPerspectiveMod {
Expand All @@ -30,7 +28,10 @@ public CreateTrainPerspectiveMod() {
private static class RotationState {
public final CarriageContraptionEntity entity;
private float lastYaw;
public boolean standingState, isMounted, shouldTickState = true;
public boolean standingState;
public boolean isMounted;
public boolean shouldTickState = true;
public int ticksSinceLastUpdate = 0;

public RotationState(CarriageContraptionEntity entity, boolean standingState, boolean isMounted) {
this.entity = entity;
Expand All @@ -40,6 +41,14 @@ public RotationState(CarriageContraptionEntity entity, boolean standingState, bo
}

public float getYawDelta() {
while (entity.yaw - lastYaw < -180.0f) {
lastYaw -= 360.0f;
}

while (entity.yaw - lastYaw >= 180.0f) {
lastYaw += 360.0f;
}

var rotation = entity.yaw - lastYaw;
lastYaw = entity.yaw;
return rotation;
Expand All @@ -60,40 +69,31 @@ public void onEntityMount(boolean isMounting, Entity entityMounting, Entity enti
states.put(entityMounting.getUUID(), state);
persp.enable(state.entity.pitch, state.entity.yaw);
} else {
states.get(entityMounting.getUUID()).isMounted = true;
var state = states.get(entityMounting.getUUID());
state.isMounted = true;
state.shouldTickState = true;
}
} else {
if(states.containsKey(entityMounting.getUUID())) {
if(states.get(entityMounting.getUUID()).standingState) {
states.get(entityMounting.getUUID()).isMounted = false;
} else {
states.remove(entityMounting.getUUID());
persp.disable();
}
states.remove(entityMounting.getUUID());
persp.disable();
}
}
}
}

public void tickStandingPlayers(final CarriageContraptionEntity contraption) {
for(Map.Entry<Entity, MutableInt> entry : contraption.collidingEntities.entrySet()) {
var entity = entry.getKey();
var ticks = entry.getValue();
if(entity instanceof LocalPlayer player) {
if(player.getVehicle() != null) continue;

var state = states.get(player.getUUID());
if (state == null) {
var persp = (Perspective) Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(player);
state = new RotationState(contraption, true, false);
states.put(player.getUUID(), state);
persp.enable(state.entity.pitch, state.entity.yaw);
} else if(ticks.getValue() >= 2) {
state.shouldTickState = false;
} else if(!state.shouldTickState) {
state.shouldTickState = true;
}
}
public void tickStandingPlayer(final CarriageContraptionEntity contraption, final Player player) {
if(player.getVehicle() != null) return;

var state = states.get(player.getUUID());

if (state == null || !Objects.equals(state.entity, contraption)) {
var persp = (Perspective) Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(player);
state = new RotationState(contraption, true, false);
states.put(player.getUUID(), state);
persp.enable(state.entity.pitch, state.entity.yaw);
} else {
state.ticksSinceLastUpdate = 0;
}
}

Expand All @@ -104,6 +104,14 @@ private void tickState(LocalPlayer player) {
persp.setYaw(state.entity.yaw);
player.setYRot(player.getYRot() + state.getYawDelta());
player.setYBodyRot(player.getYRot());

if(state.standingState && !state.isMounted) {
state.ticksSinceLastUpdate += 1;

if(state.ticksSinceLastUpdate > 5) {
state.shouldTickState = false;
}
}
}

public void onTickPlayer(final Player player) {
Expand All @@ -115,12 +123,11 @@ public void onTickPlayer(final Player player) {
} else {
var persp = (Perspective) Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(player);
persp.diminish();
}

if(localPlayer.onGround() && state.standingState) {
var persp = (Perspective) Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(player);
states.remove(player.getUUID());
persp.disable();
if(persp.diminished()) {
states.remove(player.getUUID());
persp.disable();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
package net.derfruhling.minecraft.create.trainperspective;

import net.minecraft.client.Camera;
import net.minecraft.util.Mth;

public class MixinUtil {
private MixinUtil() {}

public static Camera3D asCamera3D(Camera camera) {
return (Camera3D) camera;
}

private static float invCos(float x) {
return Mth.cos(x + Mth.PI);
}

public static float applyDirectionXRotChange(Perspective persp, float xRot, float yRot, float f) {
return xRot - persp.getLean(f) * Mth.sin((persp.getYaw(f) - yRot) * Mth.DEG_TO_RAD);
}

public static float getExtraYRot(Perspective persp, float xRot, float yRot, float f) {
return persp.getLean(f) * (xRot / 90.0f) * invCos((persp.getYaw(f) - yRot) * Mth.DEG_TO_RAD);
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
package net.derfruhling.minecraft.create.trainperspective;

import net.minecraft.util.Mth;

public interface Perspective {
void enable(float initialLean, float initialYaw);
void disable();
boolean isEnabled();
void setLean(float lean);
void setYaw(float yaw);
float getLean();
float getYaw();
float getLean(float f);
float getYaw(float f);

default void diminish() {
setLean(getLean() * 0.97f);
setYaw(getYaw() * 0.97f);
setLean(getLean(1.0f) * 0.9f);
}

default boolean diminished() {
return Mth.abs(getLean(1.0f)) < 0.01f;
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
package net.derfruhling.minecraft.create.trainperspective.mixin;

import com.simibubi.create.content.contraptions.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.ContraptionCollider;
import com.simibubi.create.content.trains.entity.CarriageContraptionEntity;
import net.derfruhling.minecraft.create.trainperspective.CreateTrainPerspectiveMod;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
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;

@Mixin(ContraptionCollider.class)
public class ContraptionColliderMixin {
@Inject(method = "collideEntities", at = @At("HEAD"), remap = false)
private static void saveClientPlayerFromClipping(
AbstractContraptionEntity contraptionEntity,
@Mixin(AbstractContraptionEntity.class)
@Environment(EnvType.CLIENT)
public class AbstractContraptionEntityMixin {
@SuppressWarnings({"ConstantValue", "UnreachableCode"})
@Inject(method = "registerColliding", at = @At("TAIL"), remap = false)
private void onRegisterColliding(
Entity entity,
CallbackInfo ci
) {
if(contraptionEntity instanceof CarriageContraptionEntity carriage) {
CreateTrainPerspectiveMod.INSTANCE.tickStandingPlayers(carriage);
if((Object) this instanceof CarriageContraptionEntity carriage && entity instanceof Player player) {
CreateTrainPerspectiveMod.INSTANCE.tickStandingPlayer(carriage, player);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,72 @@

import com.llamalad7.mixinextras.sugar.Local;
import net.derfruhling.minecraft.create.trainperspective.Camera3D;
import net.derfruhling.minecraft.create.trainperspective.MixinUtil;
import net.derfruhling.minecraft.create.trainperspective.Perspective;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import org.joml.Quaternionf;
import org.spongepowered.asm.mixin.*;
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;

@Mixin(Camera.class)
@Implements({@Interface(iface = Camera3D.class, prefix = "c3d$")})
@Environment(EnvType.CLIENT)
public abstract class CameraMixin {
@Shadow private Entity entity;
@Unique private float ctp$zRot;
@Unique private float ctp$extraYRot;

@Shadow protected abstract void setRotation(float f, float g);

@Shadow @Final private Quaternionf rotation;

@ModifyArg(method = "setRotation", at = @At(value = "INVOKE", target = "Lorg/joml/Quaternionf;rotationYXZ(FFF)Lorg/joml/Quaternionf;"), index = 2)
private float modifyRoll(float original) {
return original + ctp$zRot;
}

@Inject(method = "setRotation", at = @At(value = "INVOKE", target = "Lorg/joml/Quaternionf;rotationYXZ(FFF)Lorg/joml/Quaternionf;", shift = At.Shift.AFTER))
private void modifyQuaternion(float f, float g, CallbackInfo ci) {
this.rotation.rotateY(ctp$extraYRot);
}

@Unique
public float c3d$getZRot() {
return this.ctp$zRot;
}

@Unique
public float c3d$getExtraYRot() {
return this.ctp$extraYRot;
}

@Redirect(method = "setup", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Camera;setRotation(FF)V"))
public void modifyRotationsPrimary(Camera instance, float y, float x, @Local(argsOnly = true, ordinal = 1) boolean isThirdPerson) {
public void modifyRotationsPrimary(Camera instance,
float y,
float x,
@Local(argsOnly = true, ordinal = 0) boolean isThirdPerson,
@Local(argsOnly = true) float f) {
if(entity instanceof LocalPlayer player && !isThirdPerson) {
var persp = (Perspective) Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(player);
ctp$zRot = persp.getLean() * Mth.cos((persp.getYaw() - y) * Mth.DEG_TO_RAD);
setRotation(y, x - persp.getLean() * Mth.sin((persp.getYaw() - y) * Mth.DEG_TO_RAD));
ctp$zRot = persp.getLean(f) * Mth.cos((persp.getYaw(f) - y) * Mth.DEG_TO_RAD);
ctp$extraYRot = MixinUtil.getExtraYRot(persp, x, y, f);
setRotation(
y,
MixinUtil.applyDirectionXRotChange(persp, x, y, f)
);
} else {
ctp$zRot = 0;
ctp$extraYRot = 0;
setRotation(y, x);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package net.derfruhling.minecraft.create.trainperspective.mixin;

import com.simibubi.create.foundation.utility.RaycastHelper;
import net.derfruhling.minecraft.create.trainperspective.MixinUtil;
import net.derfruhling.minecraft.create.trainperspective.Perspective;
import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;

@Mixin(RaycastHelper.class)
public class CreateRaycastHelperMixin {
@ModifyVariable(method = "getTraceTarget", at = @At("STORE"), index = 4)
private static float modifyXRot(float value, Player player) {
if(Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(player) instanceof Perspective persp) {
return MixinUtil.applyDirectionXRotChange(persp, value, player.getYRot(), 1.0f);
} else return value;
}

@ModifyVariable(method = "getTraceTarget", at = @At("STORE"), index = 5)
private static float modifyYRot(float value, Player player) {
if(Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(player) instanceof Perspective persp) {
return value + MixinUtil.getExtraYRot(persp, player.getXRot(), value, 1.0f);
} else return value;
}
}
Loading
Loading