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

Misc. improvements to roomscale controls #328

Open
wants to merge 11 commits into
base: Multiloader-1.18
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.vivecraft.client_vr.extensions;

import net.minecraft.world.phys.Vec3;

public interface BoatExtension {

Vec3[] vivecraft$getPaddleAngles();
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ public boolean isNotched() {
}

public boolean isCharged() {
return Util.getMillis() - this.startDrawTime >= MAX_DRAW_MILLIS;
if (!ClientNetworking.SERVER_WANTS_DATA) {
return Util.getMillis() - this.startDrawTime >= MAX_DRAW_MILLIS;
} else {
return false;
}
}

public static boolean isBow(ItemStack itemStack) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@

import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.phys.Vec3;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.vivecraft.client_vr.ClientDataHolderVR;
import org.vivecraft.client_vr.provider.ControllerType;
import org.vivecraft.common.utils.MathUtils;

public class RowTracker extends Tracker {
private static final double TRANSMISSION_EFFICIENCY = 0.9D;
private static final double TRANSMISSION_EFFICIENCY = 1.0D;

public double[] forces = new double[]{0.0D, 0.0D};
public float LOar;
public float ROar;
public float FOar;

private final Vec3[] lastUWPs = new Vec3[2];
public Vec3[] paddleAngles = new Vec3[]{null, null};
public boolean[] paddleInWater = new boolean[]{false, false};
private int[] hands = new int[2];

public RowTracker(Minecraft mc, ClientDataHolderVR dh) {
super(mc, dh);
Expand All @@ -45,64 +44,51 @@ public boolean isActive(LocalPlayer player) {
}

public boolean isRowing() {
return this.ROar + this.LOar + this.FOar > 0.0F;
return this.paddleAngles[0] != null || this.paddleAngles[1] != null;
}

@Override
public void reset(LocalPlayer player) {
this.LOar = 0.0F;
this.ROar = 0.0F;
this.FOar = 0.0F;
this.forces[0] = 0.0D;
this.forces[1] = 0.0D;
this.paddleAngles[0] = null;
this.paddleAngles[1] = null;
this.paddleInWater[0] = false;
this.paddleInWater[1] = false;
}

@Override
public void doProcess(LocalPlayer player) {
float c0Move = this.dh.vr.controllerHistory[0].averageSpeed(0.5D);
float c1Move = this.dh.vr.controllerHistory[1].averageSpeed(0.5D);

final float minSpeed = 0.5F;
final float maxSpeed = 2.0F;

this.ROar = Math.max(c0Move - minSpeed, 0.0F);
this.LOar = Math.max(c1Move - minSpeed, 0.0F);

this.FOar = this.ROar > 0.0F && this.LOar > 0.0F ? (this.ROar + this.LOar) / 2.0F : 0.0F;

if (this.FOar > maxSpeed) {
this.FOar = maxSpeed;
}

if (this.ROar > maxSpeed) {
this.ROar = maxSpeed;
}

if (this.LOar > maxSpeed) {
this.LOar = maxSpeed;
}

// TODO: Backwards paddlin'
}

public void doProcessFinaltransmithastofixthis(LocalPlayer player) {
Boat boat = (Boat) player.getVehicle();
Quaternionf boatRot = new Quaternionf().rotationYXZ(
Mth.DEG_TO_RAD * -(boat.getYRot() % 360.0F),
Mth.DEG_TO_RAD * boat.getXRot(),
0.0F).normalize();

Vector3f hand0 = boatRot.transformInverse(MathUtils.subtractToVector3f(this.getAbsArmPos(0), boat.position()));
Vector3f hand1 = boatRot.transformInverse(MathUtils.subtractToVector3f(this.getAbsArmPos(1), boat.position()));
if (hand0.x > hand1.x) {
hands[0] = 0;
hands[1] = 1;
} else {
hands[0] = 1;
hands[1] = 0;
}

for (int paddle = 0; paddle <= 1; paddle++) {
if (this.isPaddleUnderWater(paddle, boat)) {
Vec3 arm2Pad = this.getArmToPaddleVector(paddle, boat);
Vec3 arm2Pad = this.getArmToPaddleVector(paddle, hands[paddle], boat);
this.paddleAngles[paddle] = MathUtils.toMcVec3(boatRot.transformInverse(new Vector3f((float) arm2Pad.x, (float) arm2Pad.y, (float) arm2Pad.z)));

boolean inWater;
if (this.isPaddleUnderWater(paddle, hands[paddle], boat)) {
inWater = true;

Vec3 attach = this.getAttachmentPoint(paddle, boat);
Vec3 underWaterPoint = attach.add(arm2Pad.normalize()).subtract(boat.position());
Vec3 underWaterPoint = attach.add(arm2Pad.normalize());

if (this.lastUWPs[paddle] != null) {
Vector3f forceVector = MathUtils.subtractToVector3f(this.lastUWPs[paddle],
underWaterPoint); // intentionally reverse
forceVector = forceVector.sub(
(float) boat.getDeltaMovement().x,
(float) boat.getDeltaMovement().y,
(float) boat.getDeltaMovement().z);

Vector3f forward = boatRot.transform(MathUtils.FORWARD, new Vector3f());

Expand All @@ -118,15 +104,35 @@ public void doProcessFinaltransmithastofixthis(LocalPlayer player) {

this.lastUWPs[paddle] = underWaterPoint;
} else {
inWater = false;

this.forces[paddle] = 0.0D;
this.lastUWPs[paddle] = null;
}

if (inWater) {
if (!this.paddleInWater[paddle]) {
this.dh.vr.triggerHapticPulse(ControllerType.values()[hands[paddle]], 0.05F, 100.0F, 0.8F);
} else {
float strength = (float) (Math.abs(this.forces[paddle]) / 0.1D);
if (strength > 0.05F) {
strength = strength * 0.7F + 0.3F;
this.dh.vr.triggerHapticPulse(ControllerType.values()[hands[paddle]], 0.05F, 100.0F, strength);
}
}
} else {
if (this.paddleInWater[paddle]) {
this.dh.vr.triggerHapticPulse(ControllerType.values()[hands[paddle]], 0.05F, 100.0F, 0.2F);
}
}

this.paddleInWater[paddle] = inWater;
}
}

private Vec3 getArmToPaddleVector(int paddle, Boat boat) {
private Vec3 getArmToPaddleVector(int paddle, int hand, Boat boat) {
Vec3 attachAbs = this.getAttachmentPoint(paddle, boat);
Vec3 armAbs = this.getAbsArmPos(paddle == 0 ? 1 : 0);
Vec3 armAbs = this.getAbsArmPos(hand);
return attachAbs.subtract(armAbs);
}

Expand All @@ -146,10 +152,10 @@ private Vec3 getAbsArmPos(int side) {
return this.dh.vrPlayer.roomOrigin.add(arm.x, arm.y, arm.z);
}

private boolean isPaddleUnderWater(int paddle, Boat boat) {
private boolean isPaddleUnderWater(int paddle, int hand, Boat boat) {
Vec3 attachAbs = this.getAttachmentPoint(paddle, boat);
Vec3 armToPaddle = this.getArmToPaddleVector(paddle, boat).normalize();
BlockPos blockPos = new BlockPos(attachAbs.add(armToPaddle));
return boat.level.getBlockState(blockPos).getMaterial().isLiquid();
Vec3 armToPaddle = this.getArmToPaddleVector(paddle, hand, boat).normalize();
Vec3 blockPos = attachAbs.add(armToPaddle);
return blockPos.subtract(boat.position()).y < 0.2F;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.phys.Vec3;
import org.joml.Vector3f;
import org.vivecraft.client_vr.ClientDataHolderVR;
import org.vivecraft.client_vr.settings.AutoCalibration;
import org.vivecraft.common.utils.MathUtils;

public class SwimTracker extends Tracker {
private static final float FRICTION = 0.9F;
private static final float RISE_SPEED = 0.005F;
private static final float SWIM_SPEED = 1.3F;
private static final float FRICTION = 0.85F;
private static final float RISE_SPEED = 0.0015F;
private static final float SWIM_SPEED = 1.0F;

private Vector3f motion = new Vector3f();
private double lastDist;
Expand Down Expand Up @@ -67,6 +69,10 @@ public void doProcess(LocalPlayer player) {
this.motion = this.motion.add(velocity);
}

if (player.getFluidHeight(FluidTags.WATER) > AutoCalibration.getPlayerHeight() - 0.1F) {
this.motion = this.motion.add(0.0f, RISE_SPEED, 0.0f);
}

this.lastDist = distance;
player.setSwimming(this.motion.length() > 0.3D);
player.setSprinting(this.motion.length() > 1.0D);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ public void reset(LocalPlayer player) {
}

public double getVehicleFloor(Entity vehicle, double original) {
// if (vehicle instanceof AbstractHorse) {
return original; // horses are fine.
// } else {
// return vehicle.getY();
// }
if (vehicle instanceof Boat) {
return original + 0.6f;
} else {
return original;
}
}

public static Vector3f getSteeringDirection(LocalPlayer player) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.vivecraft.mixin.client_vr.model;

import net.minecraft.client.model.BoatModel;
import net.minecraft.client.model.geom.ModelPart;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.phys.Vec3;
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 org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import org.vivecraft.client_vr.extensions.BoatExtension;

@Mixin(BoatModel.class)
public abstract class BoatModelMixin {
@Inject(at = @At(value = "HEAD"), method = "animatePaddle(Lnet/minecraft/world/entity/vehicle/Boat;ILnet/minecraft/client/model/geom/ModelPart;F)V", locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
private static void vivecraft$animatePaddle(Boat boat, int paddle, ModelPart mp, float f, CallbackInfo ci) {
Vec3 paddleAngle = ((BoatExtension) boat).vivecraft$getPaddleAngles()[paddle];
if (paddleAngle != null) {
mp.xRot = (float) Math.atan2(paddleAngle.y, Math.sqrt(paddleAngle.x * paddleAngle.x + paddleAngle.z * paddleAngle.z));
mp.yRot = (float) Math.atan2(paddleAngle.z, paddleAngle.x);
ci.cancel();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.vehicle.Boat;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
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.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.vivecraft.client_vr.ClientDataHolderVR;
import org.vivecraft.client_vr.VRState;
import org.vivecraft.client_vr.extensions.BoatExtension;
import org.vivecraft.client_vr.settings.VRSettings;

@Mixin(Boat.class)
public abstract class BoatMixin extends Entity {
public abstract class BoatMixin extends Entity implements BoatExtension {

@Shadow
private float deltaRotation;
Expand All @@ -26,11 +30,16 @@ public abstract class BoatMixin extends Entity {
@Shadow
private boolean inputUp;

@Shadow
public abstract void setPaddleState(boolean pLeft, boolean pRight);

public Vec3[] paddleAngles = new Vec3[]{null, null};

public BoatMixin(EntityType<?> entityType, Level level) {
super(entityType, level);
}

@ModifyExpressionValue(method = "controlBoat", at = @At(value = "CONSTANT", args = "floatValue=1F", ordinal = 0))
@ModifyExpressionValue(method = "controlBoatq", at = @At(value = "CONSTANT", args = "floatValue=1F", ordinal = 0))
private float vivecraft$inputLeft(float leftInput) {
return VRState.VR_RUNNING ? Minecraft.getInstance().player.input.leftImpulse : leftInput;
}
Expand Down Expand Up @@ -89,36 +98,30 @@ public BoatMixin(EntityType<?> entityType, Level level) {
} else if (dataHolder.rowTracker.isRowing()) {
// roomscale rowing

this.deltaRotation += dataHolder.rowTracker.LOar / 1.5F;
this.deltaRotation -= dataHolder.rowTracker.ROar / 1.5F;

/*
this.deltaRotation += dataHolder.rowTracker.forces[0] * 50;
this.deltaRotation -= dataHolder.rowTracker.forces[1] * 50;
*/

if (this.deltaRotation < 0F) {
this.inputLeft = true;
}
if (this.deltaRotation > 0F) {
this.inputRight = true;
}

// clamp to vanilla speed
acceleration = Math.min(0.04F, 0.06F * dataHolder.rowTracker.FOar);
if (acceleration > 0F) {
this.inputUp = true;
}

/*
acceleration = (float) (dataHolder.rowTracker.forces[0] + dataHolder.rowTracker.forces[1]);
if (acceleration > 0.005F) {
this.inputUp = true;
}
*/

this.inputLeft = dataHolder.rowTracker.paddleInWater[0] && !dataHolder.rowTracker.paddleInWater[1];
this.inputRight = dataHolder.rowTracker.paddleInWater[1] && !dataHolder.rowTracker.paddleInWater[0];
this.inputUp = dataHolder.rowTracker.paddleInWater[0] || dataHolder.rowTracker.paddleInWater[1];

this.paddleAngles[0] = dataHolder.rowTracker.paddleAngles[0];
this.paddleAngles[1] = dataHolder.rowTracker.paddleAngles[1];
}
}
return acceleration;
}

@Inject(at = @At(value = "HEAD"), method = "tick()V")
private void vivecraft$clearPaddleAngles(CallbackInfo ci) {
this.paddleAngles[0] = null;
this.paddleAngles[1] = null;
}

@Override
public Vec3[] vivecraft$getPaddleAngles() {
return this.paddleAngles;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.AbstractArrow;
import net.minecraft.world.item.BowItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.PotionUtils;
Expand Down Expand Up @@ -110,6 +111,19 @@ protected ServerPlayerMixin(EntityType<? extends LivingEntity> entityType, Level
}
}

@Override
public void releaseUsingItem() {
ServerVivePlayer serverVivePlayer = vivecraft$getVivePlayer();
if (serverVivePlayer != null && serverVivePlayer.isVR()) {
if (serverVivePlayer.draw > 0.0F) {
if (!this.useItem.isEmpty()) {
this.useItemRemaining = Math.max(this.useItem.getUseDuration() - (int) (BowItem.MAX_DRAW_DURATION * serverVivePlayer.draw), 0);
}
}
}
super.releaseUsingItem();
}

/**
* inject into {@link Player#attack}
*/
Expand Down
Loading