Improve bucket fix accuracy and correct head pitch when receiving a look update from the server. Fixes #201

This commit is contained in:
Sollace 2022-06-10 12:12:41 +02:00
parent cd29726076
commit f145c59726
3 changed files with 69 additions and 9 deletions

View file

@ -1,15 +1,28 @@
package com.minelittlepony.client; package com.minelittlepony.client;
import net.minecraft.block.Material;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.HitResult; import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import com.minelittlepony.api.pony.IPony; import com.minelittlepony.api.pony.IPony;
public class HorseCam { public class HorseCam {
private static float lastOriginalPitch;
private static float lastComputedPitch;
/**
* Restores the previous camera (unadjusted) angle for the client when the server sends an update.
* This is to prevent issues caused by the server updating our pitch whenever the player leaves a portal.
*/
public static float transformIncomingServerCameraAngle(float serverPitch) {
if (MathHelper.approximatelyEquals(serverPitch, lastComputedPitch)) {
return lastOriginalPitch;
}
return serverPitch;
}
/** /**
* Transforms the client pony's pitch to the corresponding angle for a human character. * Transforms the client pony's pitch to the corresponding angle for a human character.
*/ */
@ -19,12 +32,28 @@ public class HorseCam {
return pitch; return pitch;
} }
if (pitch != 0) {
lastOriginalPitch = pitch;
lastComputedPitch = pitch;
}
PlayerEntity player = MinecraftClient.getInstance().player; PlayerEntity player = MinecraftClient.getInstance().player;
// noop
// Only run when the player has an item in their hands. Can't check for buckets specifically since mods exist.
if (player.getMainHandStack().isEmpty() && player.getOffHandStack().isEmpty()) {
return pitch;
}
IPony pony = MineLittlePony.getInstance().getManager().getPony(player); IPony pony = MineLittlePony.getInstance().getManager().getPony(player);
if (!pony.getRace(false).isHuman()) { if (!pony.getRace(false).isHuman()) {
float factor = pony.getMetadata().getSize().getEyeHeightFactor(); float factor = pony.getMetadata().getSize().getEyeHeightFactor();
return rescaleCameraPitch(player.getStandingEyeHeight() / factor, pitch); pitch = rescaleCameraPitch(player.getStandingEyeHeight() / factor, pitch);
}
if (lastOriginalPitch != 0) {
lastComputedPitch = pitch;
} }
return pitch; return pitch;
@ -78,19 +107,19 @@ public class HorseCam {
MinecraftClient client = MinecraftClient.getInstance(); MinecraftClient client = MinecraftClient.getInstance();
PlayerEntity player = client.player; PlayerEntity player = client.player;
client.gameRenderer.updateTargetedEntity(1); client.gameRenderer.updateTargetedEntity(client.getTickDelta());
HitResult hit = client.crosshairTarget; HitResult hit = client.crosshairTarget;
if (client.targetedEntity != null) {
return originalPitch;
}
// noop // noop
// Ignore misses, helps with bows, arrows, and projectiles // Ignore misses, helps with bows, arrows, and projectiles
if (hit == null || hit.getType() != HitResult.Type.BLOCK || player == null) { if (hit == null || hit.getType() != HitResult.Type.BLOCK || player == null) {
return originalPitch; return originalPitch;
} }
if (hit instanceof BlockHitResult && player.world.getBlockState(((BlockHitResult)hit).getBlockPos()).getMaterial() == Material.PORTAL) {
return originalPitch;
}
Vec3d hitPos = hit.getPos(); Vec3d hitPos = hit.getPos();
Vec3d pos = player.getPos(); Vec3d pos = player.getPos();

View file

@ -0,0 +1,30 @@
package com.minelittlepony.client.mixin;
import com.minelittlepony.client.HorseCam;
import java.util.Set;
import net.minecraft.network.*;
import net.minecraft.network.listener.ClientPlayPacketListener;
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket.Flag;
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.callback.CallbackInfo;
@Mixin(PlayerPositionLookS2CPacket.class)
abstract class MixinPlayerPositionLookS2CPacket implements Packet<ClientPlayPacketListener> {
@Shadow @Mutable
private @Final float pitch;
private @Final Set<Flag> flags;
@Inject(method = "apply(Lnet/minecraft/network/listener/ClientPlayPacketListener;)V",
at = @At("HEAD"))
private void onApply(ClientPlayPacketListener clientPlayPacketListener, CallbackInfo info) {
if (!flags.contains(PlayerPositionLookS2CPacket.Flag.Y_ROT)) {
pitch = HorseCam.transformIncomingServerCameraAngle(pitch);
}
}
}

View file

@ -16,6 +16,7 @@
"MixinTexturedRenderLayers", "MixinTexturedRenderLayers",
"MixinSpriteIdentifier", "MixinSpriteIdentifier",
"MixinClientPlayerEntity", "MixinClientPlayerEntity",
"MixinPlayerMoveC2SPacket" "MixinPlayerMoveC2SPacket",
"MixinPlayerPositionLookS2CPacket"
] ]
} }