1.21.8
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.straice.smoothdoors.client.anim;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2FloatOpenHashMap;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FenceGateBlock;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
@@ -12,8 +13,10 @@ import net.minecraft.client.render.model.BlockModelPart;
|
||||
import net.minecraft.client.render.model.BlockStateModel;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.RotationAxis;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -24,6 +27,10 @@ final class FenceGateAnimation {
|
||||
|
||||
private static final float POST_EDGE = 2.0f / 16.0f;
|
||||
private static final float EDGE_EPS = 1.0e-4f;
|
||||
private static final float ANGLE_EPS = 1.0e-3f;
|
||||
|
||||
private static final Long2FloatOpenHashMap GATE_SIGNS = new Long2FloatOpenHashMap();
|
||||
private static final Long2FloatOpenHashMap LAST_ANGLES = new Long2FloatOpenHashMap();
|
||||
|
||||
private FenceGateAnimation() {}
|
||||
|
||||
@@ -55,10 +62,13 @@ final class FenceGateAnimation {
|
||||
float rightPivotX = leftRightIsX ? (15.0f / 16.0f) : 0.5f;
|
||||
float rightPivotZ = leftRightIsX ? 0.5f : (15.0f / 16.0f);
|
||||
|
||||
long key = blockKey(mc, matrices);
|
||||
float signedAngle = angleDeg * resolveSign(mc, key, facing, leftRightIsX, angleDeg);
|
||||
|
||||
if (models.left != null) {
|
||||
matrices.push();
|
||||
matrices.translate(leftPivotX, 0.0f, leftPivotZ);
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-angleDeg));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-signedAngle));
|
||||
matrices.translate(-leftPivotX, 0.0f, -leftPivotZ);
|
||||
BlockModelRenderer.render(matrices.peek(), consumer, models.left, r, g, b, light, overlay);
|
||||
matrices.pop();
|
||||
@@ -67,13 +77,78 @@ final class FenceGateAnimation {
|
||||
if (models.right != null) {
|
||||
matrices.push();
|
||||
matrices.translate(rightPivotX, 0.0f, rightPivotZ);
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(angleDeg));
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(signedAngle));
|
||||
matrices.translate(-rightPivotX, 0.0f, -rightPivotZ);
|
||||
BlockModelRenderer.render(matrices.peek(), consumer, models.right, r, g, b, light, overlay);
|
||||
matrices.pop();
|
||||
}
|
||||
}
|
||||
|
||||
private static long blockKey(MinecraftClient mc, MatrixStack matrices) {
|
||||
Vec3d camPos = mc.gameRenderer.getCamera().getPos();
|
||||
var posMat = matrices.peek().getPositionMatrix();
|
||||
double worldX = camPos.x + posMat.m30();
|
||||
double worldY = camPos.y + posMat.m31();
|
||||
double worldZ = camPos.z + posMat.m32();
|
||||
int blockX = (int) Math.round(worldX);
|
||||
int blockY = (int) Math.round(worldY);
|
||||
int blockZ = (int) Math.round(worldZ);
|
||||
return BlockPos.asLong(blockX, blockY, blockZ);
|
||||
}
|
||||
|
||||
private static float resolveSign(MinecraftClient mc, long key, Direction facing,
|
||||
boolean leftRightIsX, float angleDeg) {
|
||||
float prevAngle = LAST_ANGLES.containsKey(key) ? LAST_ANGLES.get(key) : angleDeg;
|
||||
float sign = GATE_SIGNS.containsKey(key) ? GATE_SIGNS.get(key) : 0.0f;
|
||||
boolean opening = angleDeg > prevAngle + ANGLE_EPS;
|
||||
boolean closing = angleDeg < prevAngle - ANGLE_EPS;
|
||||
|
||||
if (sign == 0.0f && opening && mc.player != null) {
|
||||
sign = computeSign(mc, key, facing, leftRightIsX);
|
||||
GATE_SIGNS.put(key, sign);
|
||||
}
|
||||
|
||||
if (sign == 0.0f && angleDeg > ANGLE_EPS && mc.player != null) {
|
||||
sign = computeSign(mc, key, facing, leftRightIsX);
|
||||
GATE_SIGNS.put(key, sign);
|
||||
}
|
||||
|
||||
if (closing && angleDeg <= ANGLE_EPS) {
|
||||
GATE_SIGNS.remove(key);
|
||||
LAST_ANGLES.remove(key);
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
LAST_ANGLES.put(key, angleDeg);
|
||||
return (sign == 0.0f) ? 1.0f : sign;
|
||||
}
|
||||
|
||||
private static float computeSign(MinecraftClient mc, long key, Direction facing, boolean leftRightIsX) {
|
||||
if (mc.player == null) return 1.0f;
|
||||
|
||||
BlockPos pos = BlockPos.fromLong(key);
|
||||
double centerX = pos.getX() + 0.5;
|
||||
double centerZ = pos.getZ() + 0.5;
|
||||
double dx = mc.player.getX() - centerX;
|
||||
double dz = mc.player.getZ() - centerZ;
|
||||
|
||||
int facingX = facing.getOffsetX();
|
||||
int facingZ = facing.getOffsetZ();
|
||||
double dot = dx * facingX + dz * facingZ;
|
||||
float side;
|
||||
if (dot > 0.0) {
|
||||
side = 1.0f;
|
||||
} else if (dot < 0.0) {
|
||||
side = -1.0f;
|
||||
} else {
|
||||
Direction playerFacing = mc.player.getHorizontalFacing();
|
||||
int facingDot = playerFacing.getOffsetX() * facingX + playerFacing.getOffsetZ() * facingZ;
|
||||
side = (facingDot >= 0) ? 1.0f : -1.0f;
|
||||
}
|
||||
|
||||
return leftRightIsX ? -side * facingZ : side * facingX;
|
||||
}
|
||||
|
||||
private static FenceGateModels splitFenceGateModels(BlockStateModel model, boolean leftRightIsX) {
|
||||
List<BlockModelPart> parts = model.getParts(Random.create(42L));
|
||||
List<BlockModelPart> posts = new ArrayList<>();
|
||||
|
||||
Reference in New Issue
Block a user