Skip to content
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