1.21.8
This commit is contained in:
@@ -2,302 +2,287 @@ package com.straice.smoothdoors.client.anim;
|
||||
|
||||
import com.straice.smoothdoors.config.SddConfig;
|
||||
import com.straice.smoothdoors.config.SddConfigManager;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.DoorBlock;
|
||||
import net.minecraft.block.FenceGateBlock;
|
||||
import net.minecraft.block.TrapdoorBlock;
|
||||
import net.minecraft.block.enums.BlockHalf;
|
||||
import net.minecraft.block.enums.DoorHinge;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.OverlayTexture;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.WorldRenderer;
|
||||
import net.minecraft.client.render.block.BlockRenderManager;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.state.property.Properties;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public final class SddAnimator {
|
||||
|
||||
private static final Long2ObjectOpenHashMap<Anim> ANIMS = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
private SddAnimator() {}
|
||||
|
||||
private enum Kind { DOOR, TRAPDOOR, FENCE_GATE }
|
||||
|
||||
private static final class Anim {
|
||||
final BlockPos pos;
|
||||
final long startNanos;
|
||||
final long durationNanos;
|
||||
final float fromDeg;
|
||||
final float toDeg;
|
||||
|
||||
Anim(BlockPos pos, long startNanos, long durationNanos, float fromDeg, float toDeg) {
|
||||
this.pos = pos;
|
||||
this.startNanos = startNanos;
|
||||
this.durationNanos = durationNanos;
|
||||
this.fromDeg = fromDeg;
|
||||
this.toDeg = toDeg;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isAnimating(BlockPos pos) {
|
||||
return ANIMS.containsKey(pos.asLong());
|
||||
}
|
||||
|
||||
/** Called on client when a block state update happens. */
|
||||
public static void onBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState) {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
if (client.world == null) return;
|
||||
|
||||
Kind kind = getKind(oldState, newState);
|
||||
if (kind == null) return;
|
||||
|
||||
SddConfig cfg = SddConfigManager.get();
|
||||
if (!isAnimEnabled(cfg, kind)) return;
|
||||
|
||||
// Only animate OPEN changes
|
||||
Boolean oldOpen = getOpenNullable(oldState);
|
||||
Boolean newOpen = getOpenNullable(newState);
|
||||
if (oldOpen == null || newOpen == null) return;
|
||||
if (oldOpen.equals(newOpen)) return;
|
||||
|
||||
float from = targetAngleDeg(kind, oldState);
|
||||
float to = targetAngleDeg(kind, newState);
|
||||
private static final Map<BlockPos, Anim> ANIMS = new HashMap<>();
|
||||
private static long lastNs = -1;
|
||||
|
||||
private static float frameDtSeconds() {
|
||||
long now = System.nanoTime();
|
||||
long dur = (long) (baseDurationSeconds(kind) / getSpeed(cfg, kind) * 1_000_000_000L);
|
||||
if (dur < 30_000_000L) dur = 30_000_000L; // 30ms min
|
||||
|
||||
ANIMS.put(pos.asLong(), new Anim(pos.toImmutable(), now, dur, from, to));
|
||||
|
||||
// Force rerender so the chunk can "forget" the vanilla block draw (we'll hide it)
|
||||
client.worldRenderer.scheduleBlockRenders(pos.getX(), pos.getY(), pos.getZ(), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
/** Used by BlockRenderManagerMixin to hide the vanilla block while animating. */
|
||||
public static boolean shouldHideInChunk(BlockPos pos, BlockState state) {
|
||||
if (!isAnimating(pos)) return false;
|
||||
|
||||
Kind k = getKind(state, state);
|
||||
if (k == null) return false;
|
||||
|
||||
SddConfig cfg = SddConfigManager.get();
|
||||
return isAnimEnabled(cfg, k);
|
||||
}
|
||||
|
||||
/** Render all active animations (called each frame from WorldRendererMixin). */
|
||||
public static void renderAll(Vec3d cameraPos, float tickDeltaIgnored) {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
if (client.world == null) {
|
||||
ANIMS.clear();
|
||||
return;
|
||||
if (lastNs < 0) {
|
||||
lastNs = now;
|
||||
return 0f;
|
||||
}
|
||||
if (ANIMS.isEmpty()) return;
|
||||
long d = now - lastNs;
|
||||
lastNs = now;
|
||||
|
||||
VertexConsumerProvider.Immediate consumers = client.getBufferBuilders().getEntityVertexConsumers();
|
||||
BlockRenderManager brm = client.getBlockRenderManager();
|
||||
|
||||
long now = System.nanoTime();
|
||||
ArrayList<Long> done = new ArrayList<>();
|
||||
|
||||
for (var e : ANIMS.long2ObjectEntrySet()) {
|
||||
long key = e.getLongKey();
|
||||
Anim anim = e.getValue();
|
||||
|
||||
BlockState state = client.world.getBlockState(anim.pos);
|
||||
Kind kind = getKind(state, state);
|
||||
if (kind == null) {
|
||||
done.add(key);
|
||||
continue;
|
||||
}
|
||||
|
||||
SddConfig cfg = SddConfigManager.get();
|
||||
if (!isAnimEnabled(cfg, kind)) {
|
||||
done.add(key);
|
||||
client.worldRenderer.scheduleBlockRenders(anim.pos.getX(), anim.pos.getY(), anim.pos.getZ(),
|
||||
anim.pos.getX(), anim.pos.getY(), anim.pos.getZ());
|
||||
continue;
|
||||
}
|
||||
|
||||
float t = (float) (now - anim.startNanos) / (float) anim.durationNanos;
|
||||
if (t >= 1.0f) {
|
||||
done.add(key);
|
||||
client.worldRenderer.scheduleBlockRenders(anim.pos.getX(), anim.pos.getY(), anim.pos.getZ(),
|
||||
anim.pos.getX(), anim.pos.getY(), anim.pos.getZ());
|
||||
continue;
|
||||
}
|
||||
|
||||
float eased = smoothstep(clamp01(t));
|
||||
float angle = lerp(anim.fromDeg, anim.toDeg, eased);
|
||||
|
||||
// Render the "closed" state model and rotate it ourselves
|
||||
BlockState renderState = forceClosed(state);
|
||||
|
||||
int light = WorldRenderer.getLightmapCoordinates(client.world, anim.pos);
|
||||
|
||||
MatrixStack ms = new MatrixStack();
|
||||
ms.push();
|
||||
|
||||
ms.translate(anim.pos.getX() - cameraPos.x, anim.pos.getY() - cameraPos.y, anim.pos.getZ() - cameraPos.z);
|
||||
applyTransform(ms, renderState, kind, angle);
|
||||
|
||||
brm.renderBlockAsEntity(renderState, ms, consumers, light, OverlayTexture.DEFAULT_UV);
|
||||
|
||||
ms.pop();
|
||||
}
|
||||
|
||||
consumers.draw();
|
||||
|
||||
for (Long k : done) ANIMS.remove(k.longValue());
|
||||
float dt = d / 1_000_000_000f;
|
||||
if (dt > 0.1f) dt = 0.1f;
|
||||
if (dt < 0f) dt = 0f;
|
||||
return dt;
|
||||
}
|
||||
|
||||
// =================== helpers ===================
|
||||
private static boolean isDoor(BlockState s) { return s.getBlock() instanceof DoorBlock; }
|
||||
private static boolean isTrapdoor(BlockState s) { return s.getBlock() instanceof TrapdoorBlock; }
|
||||
private static boolean isFenceGate(BlockState s) { return s.getBlock() instanceof FenceGateBlock; }
|
||||
|
||||
private static float clamp01(float v) { return v < 0 ? 0 : (v > 1 ? 1 : v); }
|
||||
private static float lerp(float a, float b, float t) { return a + (b - a) * t; }
|
||||
private static float smoothstep(float t) { return t * t * (3f - 2f * t); }
|
||||
private static Kind kindOf(BlockState s) {
|
||||
if (isDoor(s)) return Kind.DOOR;
|
||||
if (isTrapdoor(s)) return Kind.TRAPDOOR;
|
||||
if (isFenceGate(s)) return Kind.FENCE_GATE;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean isAnimEnabled(SddConfig cfg, Kind k) {
|
||||
return switch (k) {
|
||||
private static boolean getOpen(BlockState s) {
|
||||
return s.contains(Properties.OPEN) && s.get(Properties.OPEN);
|
||||
}
|
||||
|
||||
private static BlockState withOpen(BlockState s, boolean open) {
|
||||
return s.contains(Properties.OPEN) ? s.with(Properties.OPEN, open) : s;
|
||||
}
|
||||
|
||||
private static float getSpeed(SddConfig cfg, Kind kind) {
|
||||
return switch (kind) {
|
||||
case DOOR -> cfg.doorSpeed;
|
||||
case TRAPDOOR -> cfg.trapdoorSpeed;
|
||||
case FENCE_GATE -> cfg.fenceGateSpeed;
|
||||
};
|
||||
}
|
||||
|
||||
private static boolean isEnabled(SddConfig cfg, Kind kind) {
|
||||
return switch (kind) {
|
||||
case DOOR -> cfg.animateDoors;
|
||||
case TRAPDOOR -> cfg.animateTrapdoors;
|
||||
case FENCE_GATE -> cfg.animateFenceGates;
|
||||
};
|
||||
}
|
||||
|
||||
private static float getSpeed(SddConfig cfg, Kind k) {
|
||||
float v = switch (k) {
|
||||
case DOOR -> cfg.doorSpeed;
|
||||
case TRAPDOOR -> cfg.trapdoorSpeed;
|
||||
case FENCE_GATE -> cfg.fenceGateSpeed;
|
||||
};
|
||||
if (v < 0.2f) v = 0.2f;
|
||||
if (v > 3.0f) v = 3.0f;
|
||||
return v;
|
||||
public static void onBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState) {
|
||||
SddConfig cfg = SddConfigManager.get();
|
||||
Kind kind = kindOf(newState);
|
||||
if (kind == null) return;
|
||||
if (!isEnabled(cfg, kind)) return;
|
||||
|
||||
Block oldB = oldState.getBlock();
|
||||
Block newB = newState.getBlock();
|
||||
if (oldB != newB) return;
|
||||
|
||||
boolean oldOpen = getOpen(oldState);
|
||||
boolean newOpen = getOpen(newState);
|
||||
if (oldOpen == newOpen) return;
|
||||
|
||||
BlockState baseClosed = withOpen(newState, false);
|
||||
ANIMS.put(pos.toImmutable(), new Anim(kind, pos.toImmutable(), baseClosed, newOpen));
|
||||
}
|
||||
|
||||
private static float baseDurationSeconds(Kind k) {
|
||||
return switch (k) {
|
||||
case DOOR -> 0.18f;
|
||||
case TRAPDOOR -> 0.16f;
|
||||
case FENCE_GATE -> 0.18f;
|
||||
};
|
||||
public static boolean shouldHideInChunk(BlockPos pos, BlockState state) {
|
||||
Anim a = ANIMS.get(pos);
|
||||
if (a == null) return false;
|
||||
|
||||
SddConfig cfg = SddConfigManager.get();
|
||||
if (!isEnabled(cfg, a.kind)) return false;
|
||||
|
||||
return kindOf(state) == a.kind;
|
||||
}
|
||||
|
||||
private static Kind getKind(BlockState a, BlockState b) {
|
||||
if (a.getBlock() instanceof DoorBlock || b.getBlock() instanceof DoorBlock) return Kind.DOOR;
|
||||
if (a.getBlock() instanceof TrapdoorBlock || b.getBlock() instanceof TrapdoorBlock) return Kind.TRAPDOOR;
|
||||
if (a.getBlock() instanceof FenceGateBlock || b.getBlock() instanceof FenceGateBlock) return Kind.FENCE_GATE;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Boolean getOpenNullable(BlockState s) {
|
||||
Block b = s.getBlock();
|
||||
if ((b instanceof DoorBlock || b instanceof TrapdoorBlock || b instanceof FenceGateBlock) && s.contains(Properties.OPEN)) {
|
||||
return s.get(Properties.OPEN);
|
||||
public static void renderAll(Vec3d camPos) {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
if (client.world == null) {
|
||||
ANIMS.clear();
|
||||
lastNs = -1;
|
||||
return;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static BlockState forceClosed(BlockState s) {
|
||||
if (s.contains(Properties.OPEN)) return s.with(Properties.OPEN, false);
|
||||
return s;
|
||||
}
|
||||
float dt = frameDtSeconds();
|
||||
if (dt <= 0f && ANIMS.isEmpty()) return;
|
||||
|
||||
/** Target angle for the given state (0 or +/- 90 degrees). */
|
||||
private static float targetAngleDeg(Kind k, BlockState state) {
|
||||
Boolean open = getOpenNullable(state);
|
||||
if (open == null || !open) return 0f;
|
||||
SddConfig cfg = SddConfigManager.get();
|
||||
var consumers = client.getBufferBuilders().getEntityVertexConsumers();
|
||||
BlockRenderManager brm = client.getBlockRenderManager();
|
||||
|
||||
return switch (k) {
|
||||
case DOOR -> {
|
||||
DoorHinge hinge = state.get(Properties.DOOR_HINGE);
|
||||
yield (hinge == DoorHinge.LEFT) ? -90f : 90f;
|
||||
Iterator<Map.Entry<BlockPos, Anim>> it = ANIMS.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Anim a = it.next().getValue();
|
||||
|
||||
if (!isEnabled(cfg, a.kind)) {
|
||||
it.remove();
|
||||
continue;
|
||||
}
|
||||
case FENCE_GATE -> -90f;
|
||||
case TRAPDOOR -> trapdoorOpenAngle(state);
|
||||
|
||||
float speed = getSpeed(cfg, a.kind);
|
||||
float baseDuration = switch (a.kind) {
|
||||
case DOOR -> 0.18f;
|
||||
case TRAPDOOR -> 0.16f;
|
||||
case FENCE_GATE -> 0.16f;
|
||||
};
|
||||
float dur = baseDuration / Math.max(0.05f, speed);
|
||||
|
||||
a.time += dt;
|
||||
float t = (dur <= 0f) ? 1f : (a.time / dur);
|
||||
if (t > 1f) t = 1f;
|
||||
|
||||
float eased = smoothStep(t);
|
||||
float open01 = a.toOpen ? eased : (1f - eased);
|
||||
|
||||
renderOne(client, brm, consumers, camPos, a, open01);
|
||||
|
||||
if (t >= 1f) it.remove();
|
||||
}
|
||||
|
||||
consumers.draw();
|
||||
}
|
||||
|
||||
private static float smoothStep(float t) {
|
||||
return t * t * (3f - 2f * t);
|
||||
}
|
||||
|
||||
private static void renderOne(MinecraftClient client,
|
||||
BlockRenderManager brm,
|
||||
net.minecraft.client.render.VertexConsumerProvider.Immediate consumers,
|
||||
Vec3d camPos,
|
||||
Anim a,
|
||||
float open01) {
|
||||
|
||||
BlockState worldState = client.world.getBlockState(a.pos);
|
||||
if (kindOf(worldState) != a.kind) return;
|
||||
|
||||
MatrixStack matrices = new MatrixStack();
|
||||
|
||||
double rx = a.pos.getX() - camPos.x;
|
||||
double ry = a.pos.getY() - camPos.y;
|
||||
double rz = a.pos.getZ() - camPos.z;
|
||||
matrices.translate(rx, ry, rz);
|
||||
|
||||
int light = WorldRenderer.getLightmapCoordinates(client.world, a.pos);
|
||||
|
||||
switch (a.kind) {
|
||||
case DOOR -> applyDoorTransform(matrices, worldState, open01);
|
||||
case TRAPDOOR -> applyTrapdoorTransform(matrices, worldState, open01);
|
||||
case FENCE_GATE -> applyFenceGateTransform(matrices, worldState, open01);
|
||||
}
|
||||
|
||||
brm.renderBlockAsEntity(a.baseClosed, matrices, consumers, light, OverlayTexture.DEFAULT_UV);
|
||||
}
|
||||
|
||||
private static void applyDoorTransform(MatrixStack matrices, BlockState worldState, float open01) {
|
||||
float angle = 90f * open01;
|
||||
|
||||
var facing = worldState.get(Properties.HORIZONTAL_FACING);
|
||||
var hinge = worldState.get(Properties.DOOR_HINGE);
|
||||
|
||||
float dir = (hinge == net.minecraft.block.enums.DoorHinge.LEFT) ? 1f : -1f;
|
||||
|
||||
float pivotX = 0f;
|
||||
float pivotZ = 0f;
|
||||
|
||||
// FIX: switch completo para Direction (incluye UP/DOWN)
|
||||
switch (facing) {
|
||||
case NORTH -> pivotX = (hinge == net.minecraft.block.enums.DoorHinge.LEFT) ? 0f : 1f;
|
||||
case SOUTH -> pivotX = (hinge == net.minecraft.block.enums.DoorHinge.LEFT) ? 1f : 0f;
|
||||
case EAST -> pivotZ = (hinge == net.minecraft.block.enums.DoorHinge.LEFT) ? 0f : 1f;
|
||||
case WEST -> pivotZ = (hinge == net.minecraft.block.enums.DoorHinge.LEFT) ? 1f : 0f;
|
||||
case UP, DOWN -> {
|
||||
// No debería ocurrir en puertas, pero evita warning del compilador
|
||||
}
|
||||
}
|
||||
|
||||
matrices.translate(pivotX, 0.0, pivotZ);
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(dir * angle));
|
||||
matrices.translate(-pivotX, 0.0, -pivotZ);
|
||||
}
|
||||
|
||||
private static void applyTrapdoorTransform(MatrixStack matrices, BlockState worldState, float open01) {
|
||||
float angle = 90f * open01;
|
||||
|
||||
var facing = worldState.get(Properties.HORIZONTAL_FACING);
|
||||
var half = worldState.get(Properties.BLOCK_HALF); // TOP/BOTTOM
|
||||
|
||||
float sign = (half == net.minecraft.block.enums.BlockHalf.BOTTOM) ? -1f : 1f;
|
||||
float pivotY = (half == net.minecraft.block.enums.BlockHalf.BOTTOM) ? 0f : 1f;
|
||||
|
||||
// Ya estaba completo, lo dejo igual
|
||||
switch (facing) {
|
||||
case NORTH -> {
|
||||
float pivotZ = 0f;
|
||||
matrices.translate(0, pivotY, pivotZ);
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(sign * angle));
|
||||
matrices.translate(0, -pivotY, -pivotZ);
|
||||
}
|
||||
case SOUTH -> {
|
||||
float pivotZ = 1f;
|
||||
matrices.translate(0, pivotY, pivotZ);
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(-sign * angle));
|
||||
matrices.translate(0, -pivotY, -pivotZ);
|
||||
}
|
||||
case WEST -> {
|
||||
float pivotX = 0f;
|
||||
matrices.translate(pivotX, pivotY, 0);
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-sign * angle));
|
||||
matrices.translate(-pivotX, -pivotY, 0);
|
||||
}
|
||||
case EAST -> {
|
||||
float pivotX = 1f;
|
||||
matrices.translate(pivotX, pivotY, 0);
|
||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(sign * angle));
|
||||
matrices.translate(-pivotX, -pivotY, 0);
|
||||
}
|
||||
case UP, DOWN -> {
|
||||
// No aplicable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyFenceGateTransform(MatrixStack matrices, BlockState worldState, float open01) {
|
||||
float angle = 90f * open01;
|
||||
var facing = worldState.get(Properties.HORIZONTAL_FACING);
|
||||
|
||||
// FIX: switch completo para Direction (incluye UP/DOWN)
|
||||
float dir = switch (facing) {
|
||||
case NORTH, EAST -> 1f;
|
||||
case SOUTH, WEST -> -1f;
|
||||
case UP, DOWN -> 1f; // no debería ocurrir
|
||||
};
|
||||
|
||||
matrices.translate(0.5, 0.0, 0.5);
|
||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(dir * angle));
|
||||
matrices.translate(-0.5, 0.0, -0.5);
|
||||
}
|
||||
|
||||
private static float trapdoorOpenAngle(BlockState state) {
|
||||
Direction f = state.get(Properties.HORIZONTAL_FACING);
|
||||
BlockHalf half = state.get(Properties.BLOCK_HALF);
|
||||
private static final class Anim {
|
||||
final Kind kind;
|
||||
final BlockPos pos;
|
||||
final BlockState baseClosed;
|
||||
final boolean toOpen;
|
||||
float time = 0f;
|
||||
|
||||
float angle;
|
||||
switch (f) {
|
||||
case NORTH -> angle = -90f;
|
||||
case SOUTH -> angle = 90f;
|
||||
case WEST -> angle = 90f;
|
||||
case EAST -> angle = -90f;
|
||||
default -> angle = 90f;
|
||||
Anim(Kind kind, BlockPos pos, BlockState baseClosed, boolean toOpen) {
|
||||
this.kind = kind;
|
||||
this.pos = pos;
|
||||
this.baseClosed = baseClosed;
|
||||
this.toOpen = toOpen;
|
||||
}
|
||||
|
||||
if (half == BlockHalf.TOP) angle = -angle;
|
||||
return angle;
|
||||
}
|
||||
|
||||
private static void applyTransform(MatrixStack ms, BlockState state, Kind kind, float angleDeg) {
|
||||
switch (kind) {
|
||||
case DOOR -> applyDoorTransform(ms, state, angleDeg);
|
||||
case TRAPDOOR -> applyTrapdoorTransform(ms, state, angleDeg);
|
||||
case FENCE_GATE -> applyFenceGateTransform(ms, state, angleDeg);
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyDoorTransform(MatrixStack ms, BlockState state, float angleDeg) {
|
||||
Direction facing = state.get(Properties.HORIZONTAL_FACING);
|
||||
DoorHinge hinge = state.get(Properties.DOOR_HINGE);
|
||||
|
||||
Direction hingeDir = (hinge == DoorHinge.LEFT) ? facing.rotateYCounterclockwise() : facing.rotateYClockwise();
|
||||
|
||||
double px = 0.5;
|
||||
double pz = 0.5;
|
||||
if (hingeDir == Direction.WEST) px = 0.0;
|
||||
if (hingeDir == Direction.EAST) px = 1.0;
|
||||
if (hingeDir == Direction.NORTH) pz = 0.0;
|
||||
if (hingeDir == Direction.SOUTH) pz = 1.0;
|
||||
|
||||
ms.translate(px, 0.0, pz);
|
||||
ms.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(angleDeg));
|
||||
ms.translate(-px, 0.0, -pz);
|
||||
}
|
||||
|
||||
private static void applyFenceGateTransform(MatrixStack ms, BlockState state, float angleDeg) {
|
||||
ms.translate(0.5, 0.0, 0.5);
|
||||
ms.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(angleDeg));
|
||||
ms.translate(-0.5, 0.0, -0.5);
|
||||
}
|
||||
|
||||
private static void applyTrapdoorTransform(MatrixStack ms, BlockState state, float angleDeg) {
|
||||
Direction f = state.get(Properties.HORIZONTAL_FACING);
|
||||
BlockHalf half = state.get(Properties.BLOCK_HALF);
|
||||
|
||||
double py = (half == BlockHalf.TOP) ? 1.0 : 0.0;
|
||||
|
||||
double px = 0.5;
|
||||
double pz = 0.5;
|
||||
|
||||
if (f == Direction.NORTH) pz = 0.0;
|
||||
if (f == Direction.SOUTH) pz = 1.0;
|
||||
if (f == Direction.WEST) px = 0.0;
|
||||
if (f == Direction.EAST) px = 1.0;
|
||||
|
||||
ms.translate(px, py, pz);
|
||||
|
||||
if (f == Direction.NORTH || f == Direction.SOUTH) {
|
||||
ms.multiply(RotationAxis.POSITIVE_X.rotationDegrees(angleDeg));
|
||||
} else {
|
||||
ms.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(angleDeg));
|
||||
}
|
||||
|
||||
ms.translate(-px, -py, -pz);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.straice.smoothdoors.mixin.client;
|
||||
|
||||
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||
import com.straice.smoothdoors.client.anim.SddAnimator;
|
||||
import net.minecraft.client.render.Camera;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import net.minecraft.client.render.RenderTickCounter;
|
||||
import net.minecraft.client.render.WorldRenderer;
|
||||
import net.minecraft.client.util.ObjectAllocator;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector4f;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@@ -16,12 +16,26 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
@Mixin(WorldRenderer.class)
|
||||
public class WorldRendererMixin {
|
||||
|
||||
@Inject(method = "render", at = @At("TAIL"))
|
||||
private void sdd$renderTail(ObjectAllocator allocator, RenderTickCounter tickCounter, boolean renderBlockOutline,
|
||||
Camera camera, GameRenderer gameRenderer, Matrix4f positionMatrix, Matrix4f projectionMatrix,
|
||||
@Inject(
|
||||
method = "render(Lnet/minecraft/client/util/ObjectAllocator;" +
|
||||
"Lnet/minecraft/client/render/RenderTickCounter;" +
|
||||
"ZLnet/minecraft/client/render/Camera;" +
|
||||
"Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;" +
|
||||
"Lcom/mojang/blaze3d/buffers/GpuBufferSlice;" +
|
||||
"Lorg/joml/Vector4f;Z)V",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void sdd$renderTail(ObjectAllocator allocator,
|
||||
RenderTickCounter tickCounter,
|
||||
boolean renderBlockOutline,
|
||||
Camera camera,
|
||||
Matrix4f positionMatrix,
|
||||
Matrix4f projectionMatrix,
|
||||
GpuBufferSlice slice,
|
||||
Vector4f fogColor,
|
||||
boolean bl,
|
||||
CallbackInfo ci) {
|
||||
Vec3d camPos = camera.getPos();
|
||||
float tickDelta = tickCounter.getTickProgress(true);
|
||||
SddAnimator.renderAll(camPos, tickDelta);
|
||||
|
||||
SddAnimator.renderAll(camera.getPos());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user