From ff56a749a264fcb115937356a910ff8d351f0918 Mon Sep 17 00:00:00 2001 From: DekinDev Date: Mon, 26 Jan 2026 17:23:08 +0100 Subject: [PATCH] 1 --- _tmp_sdd_yarn_1 | 1 + aa.png | Bin 0 -> 49791 bytes aaaa.b | 0 .../java/com/straice/TemplateModClient.java | 5 +- .../mixin/client/BlockModelRendererMixin.java | 61 +++ .../mixin/client/BlockRenderManagerMixin.java | 33 ++ .../client/ChunkRendererRegionMixin.java | 23 + .../mixin/client/ClientWorldMixin.java | 19 + .../mixin/client/ExampleClientMixin.java | 2 +- .../client/anim/DoorAnimation.java | 78 +++ .../client/anim/FenceGateAnimation.java | 374 ++++++++++++++ .../smoothdoors/client/anim/SddAnimator.java | 469 ++++++++++++++++++ .../client/anim/TrapdoorAnimation.java | 87 ++++ .../mixin/client/BlockModelRendererMixin.java | 61 +++ .../mixin/client/BlockRenderManagerMixin.java | 33 ++ .../client/ChunkRendererRegionMixin.java | 23 + .../mixin/client/ClientWorldMixin.java | 19 + .../resources/template-mod.client.mixins.json | 7 +- src/main/java/com/straice/TemplateMod.java | 11 +- .../straice/smoothdoors/config/SddConfig.java | 20 + .../smoothdoors/config/SddConfigManager.java | 40 ++ .../smoothdoors/mixin/DoorBlockMixin.java | 68 +++ .../mixin/FenceGateBlockMixin.java | 66 +++ .../smoothdoors/mixin/TrapdoorBlockMixin.java | 66 +++ .../smoothdoors/util/ConnectedUtil.java | 125 +++++ .../straice/smoothdoors/util/SyncGuard.java | 16 + src/main/resources/template-mod.mixins.json | 5 +- tt.png | Bin 0 -> 155620 bytes 28 files changed, 1699 insertions(+), 13 deletions(-) create mode 160000 _tmp_sdd_yarn_1 create mode 100644 aa.png create mode 100644 aaaa.b create mode 100644 src/client/java/com/straice/mixin/client/BlockModelRendererMixin.java create mode 100644 src/client/java/com/straice/mixin/client/BlockRenderManagerMixin.java create mode 100644 src/client/java/com/straice/mixin/client/ChunkRendererRegionMixin.java create mode 100644 src/client/java/com/straice/mixin/client/ClientWorldMixin.java create mode 100644 src/client/java/com/straice/smoothdoors/client/anim/DoorAnimation.java create mode 100644 src/client/java/com/straice/smoothdoors/client/anim/FenceGateAnimation.java create mode 100644 src/client/java/com/straice/smoothdoors/client/anim/SddAnimator.java create mode 100644 src/client/java/com/straice/smoothdoors/client/anim/TrapdoorAnimation.java create mode 100644 src/client/java/com/straice/smoothdoors/mixin/client/BlockModelRendererMixin.java create mode 100644 src/client/java/com/straice/smoothdoors/mixin/client/BlockRenderManagerMixin.java create mode 100644 src/client/java/com/straice/smoothdoors/mixin/client/ChunkRendererRegionMixin.java create mode 100644 src/client/java/com/straice/smoothdoors/mixin/client/ClientWorldMixin.java create mode 100644 src/main/java/com/straice/smoothdoors/config/SddConfig.java create mode 100644 src/main/java/com/straice/smoothdoors/config/SddConfigManager.java create mode 100644 src/main/java/com/straice/smoothdoors/mixin/DoorBlockMixin.java create mode 100644 src/main/java/com/straice/smoothdoors/mixin/FenceGateBlockMixin.java create mode 100644 src/main/java/com/straice/smoothdoors/mixin/TrapdoorBlockMixin.java create mode 100644 src/main/java/com/straice/smoothdoors/util/ConnectedUtil.java create mode 100644 src/main/java/com/straice/smoothdoors/util/SyncGuard.java create mode 100644 tt.png diff --git a/_tmp_sdd_yarn_1 b/_tmp_sdd_yarn_1 new file mode 160000 index 0000000..49f5c0d --- /dev/null +++ b/_tmp_sdd_yarn_1 @@ -0,0 +1 @@ +Subproject commit 49f5c0d13935b5e0f3ba86bf6f3f8561888ab5bb diff --git a/aa.png b/aa.png new file mode 100644 index 0000000000000000000000000000000000000000..050ac2d1a65c03879d1535bc9bfcd62d07e5d1ab GIT binary patch literal 49791 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 literal 0 HcmV?d00001 diff --git a/aaaa.b b/aaaa.b new file mode 100644 index 0000000..e69de29 diff --git a/src/client/java/com/straice/TemplateModClient.java b/src/client/java/com/straice/TemplateModClient.java index 25d31e2..e92f05b 100644 --- a/src/client/java/com/straice/TemplateModClient.java +++ b/src/client/java/com/straice/TemplateModClient.java @@ -1,10 +1,11 @@ package com.straice; +import com.straice.smoothdoors.client.anim.SddAnimator; import net.fabricmc.api.ClientModInitializer; public class TemplateModClient implements ClientModInitializer { @Override public void onInitializeClient() { - // This entrypoint is suitable for setting up client-specific logic, such as rendering. + SddAnimator.initClientHooks(); } -} \ No newline at end of file +} diff --git a/src/client/java/com/straice/mixin/client/BlockModelRendererMixin.java b/src/client/java/com/straice/mixin/client/BlockModelRendererMixin.java new file mode 100644 index 0000000..f6024c4 --- /dev/null +++ b/src/client/java/com/straice/mixin/client/BlockModelRendererMixin.java @@ -0,0 +1,61 @@ +package com.straice.mixin.client; + +import com.straice.smoothdoors.client.anim.SddAnimator; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.renderer.block.ModelBlockRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.util.RandomSource; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +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; + +@Mixin(ModelBlockRenderer.class) +public class BlockModelRendererMixin { + + @Inject( + method = "tesselateBlock", + at = @At("HEAD"), + cancellable = true, + require = 0 + ) + private void sdd$tesselateBlock(BlockAndTintGetter world, BakedModel model, BlockState state, BlockPos pos, + PoseStack matrices, VertexConsumer vertices, boolean cull, RandomSource random, + long seed, int overlay, CallbackInfo ci) { + if (SddAnimator.shouldHideInChunk(pos, state)) { + ci.cancel(); + } + } + + @Inject( + method = "tesselateWithAO", + at = @At("HEAD"), + cancellable = true, + require = 0 + ) + private void sdd$tesselateWithAo(BlockAndTintGetter world, BakedModel model, BlockState state, BlockPos pos, + PoseStack matrices, VertexConsumer vertices, boolean cull, RandomSource random, + long seed, int overlay, CallbackInfo ci) { + if (SddAnimator.shouldHideInChunk(pos, state)) { + ci.cancel(); + } + } + + @Inject( + method = "tesselateWithoutAO", + at = @At("HEAD"), + cancellable = true, + require = 0 + ) + private void sdd$tesselateWithoutAo(BlockAndTintGetter world, BakedModel model, BlockState state, BlockPos pos, + PoseStack matrices, VertexConsumer vertices, boolean cull, RandomSource random, + long seed, int overlay, CallbackInfo ci) { + if (SddAnimator.shouldHideInChunk(pos, state)) { + ci.cancel(); + } + } +} diff --git a/src/client/java/com/straice/mixin/client/BlockRenderManagerMixin.java b/src/client/java/com/straice/mixin/client/BlockRenderManagerMixin.java new file mode 100644 index 0000000..167e5c7 --- /dev/null +++ b/src/client/java/com/straice/mixin/client/BlockRenderManagerMixin.java @@ -0,0 +1,33 @@ +package com.straice.mixin.client; + +import com.straice.smoothdoors.client.anim.SddAnimator; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +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; + +@Mixin(BlockRenderDispatcher.class) +public class BlockRenderManagerMixin { + + @Inject( + method = "renderBatched", + at = @At("HEAD"), + cancellable = true, + require = 0 + ) + private void sdd$renderBatched(BlockState state, BlockPos pos, BlockAndTintGetter world, + PoseStack matrices, VertexConsumer vertexConsumer, + boolean cull, RandomSource random, + CallbackInfo ci) { + if (SddAnimator.shouldHideInChunk(pos, state)) { + ci.cancel(); + } + } +} diff --git a/src/client/java/com/straice/mixin/client/ChunkRendererRegionMixin.java b/src/client/java/com/straice/mixin/client/ChunkRendererRegionMixin.java new file mode 100644 index 0000000..3c800d2 --- /dev/null +++ b/src/client/java/com/straice/mixin/client/ChunkRendererRegionMixin.java @@ -0,0 +1,23 @@ +package com.straice.mixin.client; + +import com.straice.smoothdoors.client.anim.SddAnimator; +import net.minecraft.client.renderer.chunk.RenderChunkRegion; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +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.CallbackInfoReturnable; + +@Mixin(RenderChunkRegion.class) +public class ChunkRendererRegionMixin { + + @Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true) + private void sdd$getBlockState(BlockPos pos, CallbackInfoReturnable cir) { + if (SddAnimator.isAnimatingAt(pos)) { + cir.setReturnValue(Blocks.AIR.defaultBlockState()); + cir.cancel(); + } + } +} diff --git a/src/client/java/com/straice/mixin/client/ClientWorldMixin.java b/src/client/java/com/straice/mixin/client/ClientWorldMixin.java new file mode 100644 index 0000000..285f51c --- /dev/null +++ b/src/client/java/com/straice/mixin/client/ClientWorldMixin.java @@ -0,0 +1,19 @@ +package com.straice.mixin.client; + +import com.straice.smoothdoors.client.anim.SddAnimator; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +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; + +@Mixin(ClientLevel.class) +public class ClientWorldMixin { + + @Inject(method = "sendBlockUpdated", at = @At("TAIL")) + private void sdd$updateListeners(BlockPos pos, BlockState oldState, BlockState newState, int flags, CallbackInfo ci) { + SddAnimator.onBlockUpdate(pos, oldState, newState); + } +} diff --git a/src/client/java/com/straice/mixin/client/ExampleClientMixin.java b/src/client/java/com/straice/mixin/client/ExampleClientMixin.java index 2c88d92..d087552 100644 --- a/src/client/java/com/straice/mixin/client/ExampleClientMixin.java +++ b/src/client/java/com/straice/mixin/client/ExampleClientMixin.java @@ -12,4 +12,4 @@ public class ExampleClientMixin { private void init(CallbackInfo info) { // This code is injected into the start of Minecraft.run()V } -} \ No newline at end of file +} diff --git a/src/client/java/com/straice/smoothdoors/client/anim/DoorAnimation.java b/src/client/java/com/straice/smoothdoors/client/anim/DoorAnimation.java new file mode 100644 index 0000000..270b5cd --- /dev/null +++ b/src/client/java/com/straice/smoothdoors/client/anim/DoorAnimation.java @@ -0,0 +1,78 @@ +package com.straice.smoothdoors.client.anim; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.DoorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.DoorHingeSide; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.shapes.CollisionContext; + +final class DoorAnimation { + + private DoorAnimation() {} + + static void apply(BlockState state, float angleDeg, PoseStack matrices, BlockGetter world) { + if (world == null) return; + + Direction facing = state.getValue(DoorBlock.FACING); + DoorHingeSide hinge = state.getValue(DoorBlock.HINGE); + + Direction hingeSide = (hinge == DoorHingeSide.RIGHT) + ? facing.getClockWise() + : facing.getCounterClockWise(); + + AABB bb = state.getShape(world, BlockPos.ZERO, CollisionContext.empty()).bounds(); + + float cx = (float) ((bb.minX + bb.maxX) * 0.5); + float cz = (float) ((bb.minZ + bb.maxZ) * 0.5); + + float pivotX = cx; + float pivotZ = cz; + + switch (hingeSide) { + case EAST -> pivotX = (float) bb.maxX; + case WEST -> pivotX = (float) bb.minX; + case SOUTH -> pivotZ = (float) bb.maxZ; + case NORTH -> pivotZ = (float) bb.minZ; + default -> { + pivotX = cx; + pivotZ = cz; + } + } + + float thickness = (facing == Direction.NORTH || facing == Direction.SOUTH) + ? (float) (bb.maxZ - bb.minZ) + : (float) (bb.maxX - bb.minX); + float halfT = thickness * 0.5f; + + float dX = 0.0f; + float dZ = 0.0f; + switch (facing) { + case NORTH -> dZ = halfT; + case SOUTH -> dZ = -halfT; + case WEST -> dX = halfT; + case EAST -> dX = -halfT; + default -> { + dX = 0.0f; + dZ = 0.0f; + } + } + + double rad = Math.toRadians(angleDeg); + float cos = (float) Math.cos(rad); + float sin = (float) Math.sin(rad); + float rotDX = dX * cos - dZ * sin; + float rotDZ = dX * sin + dZ * cos; + float shiftX = dX - rotDX; + float shiftZ = dZ - rotDZ; + + matrices.translate(shiftX, 0.0f, shiftZ); + matrices.translate(pivotX, 0.0f, pivotZ); + matrices.mulPose(Axis.YP.rotationDegrees(angleDeg)); + matrices.translate(-pivotX, 0.0f, -pivotZ); + } +} diff --git a/src/client/java/com/straice/smoothdoors/client/anim/FenceGateAnimation.java b/src/client/java/com/straice/smoothdoors/client/anim/FenceGateAnimation.java new file mode 100644 index 0000000..65eb0c3 --- /dev/null +++ b/src/client/java/com/straice/smoothdoors/client/anim/FenceGateAnimation.java @@ -0,0 +1,374 @@ +package com.straice.smoothdoors.client.anim; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import com.mojang.math.Axis; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ItemBlockRenderTypes; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.block.ModelBlockRenderer; +import net.minecraft.client.renderer.block.model.BakedQuad; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.core.Direction; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.block.FenceGateBlock; +import net.minecraft.world.level.block.state.BlockState; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; + +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 Method RENDER_TYPE_ONE_ARG; + private static final Method RENDER_TYPE_TWO_ARG; + private static final Method QUAD_LIGHT_EMISSION; + private static final Constructor QUAD_CTOR_5; + private static final Constructor QUAD_CTOR_6; + + static { + Method oneArg = null; + Method twoArg = null; + Method lightEmission = null; + Constructor ctor5 = null; + Constructor ctor6 = null; + try { + oneArg = ItemBlockRenderTypes.class.getMethod("getRenderType", BlockState.class); + } catch (Throwable ignored) { + // Older API. + } + try { + twoArg = ItemBlockRenderTypes.class.getMethod("getRenderType", BlockState.class, boolean.class); + } catch (Throwable ignored) { + // Newer API. + } + if (oneArg == null) { + oneArg = findRenderTypeMethod(BlockState.class); + } + if (twoArg == null) { + twoArg = findRenderTypeMethod(BlockState.class, boolean.class); + } + try { + lightEmission = BakedQuad.class.getMethod("getLightEmission"); + } catch (Throwable ignored) { + // Older quad API. + } + try { + ctor5 = BakedQuad.class.getConstructor(int[].class, int.class, Direction.class, TextureAtlasSprite.class, boolean.class); + } catch (Throwable ignored) { + // Newer quad API. + } + try { + ctor6 = BakedQuad.class.getConstructor(int[].class, int.class, Direction.class, TextureAtlasSprite.class, boolean.class, int.class); + } catch (Throwable ignored) { + // Older quad API. + } + RENDER_TYPE_ONE_ARG = oneArg; + RENDER_TYPE_TWO_ARG = twoArg; + QUAD_LIGHT_EMISSION = lightEmission; + QUAD_CTOR_5 = ctor5; + QUAD_CTOR_6 = ctor6; + } + + private FenceGateAnimation() {} + + static void render(BlockState state, float angleDeg, PoseStack matrices, + MultiBufferSource consumers, int light, int overlay) { + Minecraft mc = Minecraft.getInstance(); + if (mc.level == null) return; + + Direction facing = state.getValue(FenceGateBlock.FACING); + boolean leftRightIsX = facing.getAxis() == Direction.Axis.Z; + + BakedModel baseModel = mc.getBlockRenderer().getBlockModel(state); + FenceGateModels models = splitFenceGateModels(state, baseModel, leftRightIsX); + if (models.isEmpty()) return; + + int tint = mc.getBlockColors().getColor(state, null, null, 0); + float r = ((tint >> 16) & 0xFF) / 255.0f; + float g = ((tint >> 8) & 0xFF) / 255.0f; + float b = (tint & 0xFF) / 255.0f; + + RenderType renderType = getRenderTypeCompat(state); + VertexConsumer consumer = consumers.getBuffer(renderType); + ModelBlockRenderer renderer = mc.getBlockRenderer().getModelRenderer(); + + if (models.posts != null) { + renderer.renderModel(matrices.last(), consumer, state, models.posts, r, g, b, light, overlay); + } + + float leftPivotX = leftRightIsX ? (1.0f / 16.0f) : 0.5f; + float leftPivotZ = leftRightIsX ? 0.5f : (1.0f / 16.0f); + float rightPivotX = leftRightIsX ? (15.0f / 16.0f) : 0.5f; + float rightPivotZ = leftRightIsX ? 0.5f : (15.0f / 16.0f); + + float leftAngle = -angleDeg; + float rightAngle = angleDeg; + + if (models.left != null) { + matrices.pushPose(); + matrices.translate(leftPivotX, 0.0f, leftPivotZ); + matrices.mulPose(Axis.YP.rotationDegrees(leftAngle)); + matrices.translate(-leftPivotX, 0.0f, -leftPivotZ); + renderer.renderModel(matrices.last(), consumer, state, models.left, r, g, b, light, overlay); + matrices.popPose(); + } + + if (models.right != null) { + matrices.pushPose(); + matrices.translate(rightPivotX, 0.0f, rightPivotZ); + matrices.mulPose(Axis.YP.rotationDegrees(rightAngle)); + matrices.translate(-rightPivotX, 0.0f, -rightPivotZ); + renderer.renderModel(matrices.last(), consumer, state, models.right, r, g, b, light, overlay); + matrices.popPose(); + } + } + + private static FenceGateModels splitFenceGateModels(BlockState state, BakedModel model, boolean leftRightIsX) { + List posts = new ArrayList<>(); + List left = new ArrayList<>(); + List right = new ArrayList<>(); + + for (Direction dir : Direction.values()) { + addFenceGateQuads(state, model, dir, leftRightIsX, posts, left, right); + } + addFenceGateQuads(state, model, null, leftRightIsX, posts, left, right); + + return new FenceGateModels( + posts.isEmpty() ? null : buildStaticModel(model, buildFaces(posts), model.useAmbientOcclusion(), model.getParticleIcon()), + left.isEmpty() ? null : buildStaticModel(model, buildFaces(left), model.useAmbientOcclusion(), model.getParticleIcon()), + right.isEmpty() ? null : buildStaticModel(model, buildFaces(right), model.useAmbientOcclusion(), model.getParticleIcon()) + ); + } + + private static FaceBuckets buildFaces(List quads) { + EnumMap> faces = new EnumMap<>(Direction.class); + List unculled = new ArrayList<>(); + + for (BakedQuad quad : quads) { + Direction face = quad.getDirection(); + if (face == null) { + unculled.add(quad); + } else { + faces.computeIfAbsent(face, k -> new ArrayList<>()).add(quad); + } + } + + return new FaceBuckets(faces, unculled); + } + + private static void addFenceGateQuads(BlockState state, BakedModel model, Direction dir, boolean leftRightIsX, + List posts, List left, List right) { + RandomSource random = RandomSource.create(42L); + List quads = model.getQuads(state, dir, random); + if (quads.isEmpty()) return; + + for (BakedQuad quad : quads) { + FenceGateSection section = classifyFenceGateQuad(quad, leftRightIsX); + switch (section) { + case POSTS -> posts.add(quad); + case LEFT -> { + left.add(quad); + left.add(reverseQuad(quad)); + } + case RIGHT -> { + right.add(quad); + right.add(reverseQuad(quad)); + } + } + } + } + + private static FenceGateSection classifyFenceGateQuad(BakedQuad quad, boolean leftRightIsX) { + int[] data = quad.getVertices(); + if (data.length < 8) return FenceGateSection.LEFT; + + int stride = data.length / 4; + float min = Float.POSITIVE_INFINITY; + float max = Float.NEGATIVE_INFINITY; + int coordOffset = leftRightIsX ? 0 : 2; + + for (int i = 0; i < 4; i++) { + int base = i * stride + coordOffset; + float coord = Float.intBitsToFloat(data[base]); + min = Math.min(min, coord); + max = Math.max(max, coord); + } + + float scale = (max > 1.001f) ? 16.0f : 1.0f; + float postEdge = POST_EDGE * scale; + float edgeEps = EDGE_EPS * scale; + float one = 1.0f * scale; + + if (max <= postEdge + edgeEps || min >= (one - postEdge) - edgeEps) { + return FenceGateSection.POSTS; + } + + float center = (min + max) * 0.5f; + return center <= (0.5f * scale) ? FenceGateSection.LEFT : FenceGateSection.RIGHT; + } + + private enum FenceGateSection { POSTS, LEFT, RIGHT } + + private static BakedQuad reverseQuad(BakedQuad quad) { + int[] data = quad.getVertices(); + int stride = data.length / 4; + int[] flipped = new int[data.length]; + + for (int v = 0; v < 4; v++) { + int src = (3 - v) * stride; + int dst = v * stride; + System.arraycopy(data, src, flipped, dst, stride); + } + + Direction face = quad.getDirection(); + Direction opposite = (face == null) ? null : face.getOpposite(); + return newQuadCompat(flipped, quad.getTintIndex(), opposite, quad.getSprite(), quad.isShade(), quad); + } + + private static RenderType getRenderTypeCompat(BlockState state) { + try { + if (RENDER_TYPE_TWO_ARG != null) { + return (RenderType) RENDER_TYPE_TWO_ARG.invoke(null, state, true); + } + if (RENDER_TYPE_ONE_ARG != null) { + return (RenderType) RENDER_TYPE_ONE_ARG.invoke(null, state); + } + } catch (Throwable e) { + throw new IllegalStateException("Failed to resolve ItemBlockRenderTypes#getRenderType", e); + } + throw new IllegalStateException("No compatible ItemBlockRenderTypes#getRenderType found"); + } + + private static Method findRenderTypeMethod(Class... params) { + for (Method method : ItemBlockRenderTypes.class.getDeclaredMethods()) { + if (!Modifier.isStatic(method.getModifiers())) continue; + if (!RenderType.class.isAssignableFrom(method.getReturnType())) continue; + Class[] types = method.getParameterTypes(); + if (types.length != params.length) continue; + boolean match = true; + for (int i = 0; i < types.length; i++) { + if (types[i] != params[i]) { + match = false; + break; + } + } + if (match) { + method.setAccessible(true); + return method; + } + } + return null; + } + + private static final class FenceGateModels { + final BakedModel posts; + final BakedModel left; + final BakedModel right; + + FenceGateModels(BakedModel posts, BakedModel left, BakedModel right) { + this.posts = posts; + this.left = left; + this.right = right; + } + + boolean isEmpty() { + return posts == null && left == null && right == null; + } + } + + private static BakedModel buildStaticModel(BakedModel base, FaceBuckets buckets, + boolean useAo, TextureAtlasSprite particleIcon) { + return (BakedModel) Proxy.newProxyInstance( + BakedModel.class.getClassLoader(), + new Class[]{BakedModel.class}, + (proxy, method, args) -> { + String name = method.getName(); + switch (name) { + case "getQuads" -> { + Direction face = (Direction) args[1]; + if (face == null) return buckets.unculled; + List quads = buckets.faces.get(face); + return (quads == null) ? List.of() : quads; + } + case "useAmbientOcclusion" -> { + return useAo; + } + case "isGui3d" -> { + return base.isGui3d(); + } + case "usesBlockLight" -> { + return base.usesBlockLight(); + } + case "isCustomRenderer" -> { + return invokeBoolean(base, "isCustomRenderer", false); + } + case "getParticleIcon" -> { + return particleIcon; + } + case "getTransforms" -> { + return base.getTransforms(); + } + case "getOverrides", "overrides" -> { + return method.invoke(base, args); + } + default -> { + return method.invoke(base, args); + } + } + } + ); + } + + private static boolean invokeBoolean(Object target, String methodName, boolean fallback) { + try { + Method method = target.getClass().getMethod(methodName); + Object result = method.invoke(target); + return (result instanceof Boolean) ? (Boolean) result : fallback; + } catch (Throwable ignored) { + return fallback; + } + } + + private static final class FaceBuckets { + final EnumMap> faces; + final List unculled; + + FaceBuckets(EnumMap> faces, List unculled) { + this.faces = faces; + this.unculled = unculled; + } + } + + private static BakedQuad newQuadCompat(int[] vertices, int tintIndex, Direction face, + TextureAtlasSprite sprite, boolean shade, BakedQuad source) { + int lightEmission = 0; + if (QUAD_LIGHT_EMISSION != null) { + try { + lightEmission = (int) QUAD_LIGHT_EMISSION.invoke(source); + } catch (Throwable ignored) { + lightEmission = 0; + } + } + try { + if (QUAD_CTOR_6 != null) { + return QUAD_CTOR_6.newInstance(vertices, tintIndex, face, sprite, shade, lightEmission); + } + if (QUAD_CTOR_5 != null) { + return QUAD_CTOR_5.newInstance(vertices, tintIndex, face, sprite, shade); + } + } catch (Throwable e) { + throw new IllegalStateException("Failed to construct BakedQuad", e); + } + throw new IllegalStateException("No compatible BakedQuad constructor found"); + } +} diff --git a/src/client/java/com/straice/smoothdoors/client/anim/SddAnimator.java b/src/client/java/com/straice/smoothdoors/client/anim/SddAnimator.java new file mode 100644 index 0000000..65f4605 --- /dev/null +++ b/src/client/java/com/straice/smoothdoors/client/anim/SddAnimator.java @@ -0,0 +1,469 @@ +package com.straice.smoothdoors.client.anim; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.straice.smoothdoors.config.SddConfig; +import com.straice.smoothdoors.config.SddConfigManager; +import com.straice.smoothdoors.util.ConnectedUtil; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.core.BlockPos; +import net.minecraft.core.SectionPos; +import net.minecraft.util.Mth; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.DoorBlock; +import net.minecraft.world.level.block.FenceGateBlock; +import net.minecraft.world.level.block.TrapDoorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.DoorHingeSide; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; +import net.minecraft.world.phys.Vec3; +import java.lang.reflect.Field; + +public final class SddAnimator { + + private static final Minecraft MC = Minecraft.getInstance(); + + // Base duration (seconds) at speed = 1.0x + private static final float BASE_DURATION_S = 0.35f; + private static final double END_GRACE_TICKS = 2.0; + + private static final Long2ObjectOpenHashMap ANIMS = new Long2ObjectOpenHashMap<>(); + private static boolean hooksInit = false; + + private SddAnimator() {} + + /** Llamar desde SmoothDoubleDoorsClient#onInitializeClient(). */ + public static void initClientHooks() { + if (hooksInit) return; + hooksInit = true; + WorldRenderEvents.AFTER_ENTITIES.register(context -> { + if (MC.level == null || ANIMS.isEmpty()) return; + float tickDelta = MC.getFrameTime(); + PoseStack matrices = context.matrixStack(); + MultiBufferSource consumers = context.consumers(); + if (matrices == null || consumers == null) return; + Vec3 camPos = context.camera().getPosition(); + renderAll(tickDelta, matrices, consumers, camPos); + }); + } + + // === API usada por mixins === + + /** Oculta el bloque vanilla mientras animamos (evita doble puerta). */ + public static boolean shouldHideInChunk(BlockPos pos, BlockState state) { + synchronized (ANIMS) { + if (isHiddenByAnim(pos)) return true; + + if (state.getBlock() instanceof DoorBlock && state.hasProperty(DoorBlock.HALF)) { + DoubleBlockHalf half = state.getValue(DoorBlock.HALF); + BlockPos other = (half == DoubleBlockHalf.LOWER) ? pos.above() : pos.below(); + return isHiddenByAnim(other); + } + + return false; + } + } + + public static boolean isAnimatingAt(BlockPos pos) { + synchronized (ANIMS) { + return isHiddenByAnim(pos); + } + } + + /** Se llama cuando cambia el bloque (abrir/cerrar). */ + public static void onBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState) { + if (MC.level == null) return; + + Kind kind = kindOf(oldState, newState); + if (kind == null) { + synchronized (ANIMS) { + ANIMS.remove(pos.asLong()); + } + return; + } + + if (!isKindBlock(kind, newState)) { + removeKindAt(pos, kind); + return; + } + + // DOOR: si llega update de la mitad UPPER, arrancamos desde abajo usando el estado superior. + if (kind == Kind.DOOR && newState.hasProperty(DoorBlock.HALF)) { + if (newState.getValue(DoorBlock.HALF) == DoubleBlockHalf.UPPER) { + BlockPos lowerPos = pos.below(); + if (isAnimatingAt(lowerPos) || isAnimatingAt(pos)) return; + + boolean oldOpen = isOpen(oldState); + boolean newOpen = isOpen(newState); + if (oldOpen == newOpen) return; + + SddConfig cfg = SddConfigManager.get(); + if (!isAnimationEnabled(cfg, kind)) { + removeKindAt(pos, kind); + return; + } + + float speed = speedFor(cfg, kind); + if (speed <= 0.001f) speed = 1.0f; + + long startTick = MC.level.getGameTime(); + BlockState lowerNew = MC.level.getBlockState(lowerPos); + if (!lowerNew.hasProperty(DoorBlock.HALF)) { + lowerNew = newState; + } + if (lowerNew.hasProperty(DoorBlock.OPEN)) { + lowerNew = lowerNew.setValue(DoorBlock.OPEN, newOpen); + } + lowerNew = lowerNew.setValue(DoorBlock.HALF, DoubleBlockHalf.LOWER); + startDoorAnimBothHalves(lowerPos, lowerNew, oldOpen, newOpen, speed, startTick); + startPairedDoorAnimIfAny(lowerPos, lowerNew, oldOpen, newOpen, speed, startTick, cfg); + return; + } + } + + boolean oldOpen = isOpen(oldState); + boolean newOpen = isOpen(newState); + if (oldOpen == newOpen) return; + + SddConfig cfg = SddConfigManager.get(); + if (!isAnimationEnabled(cfg, kind)) { + removeKindAt(pos, kind); + return; + } + + float speed = speedFor(cfg, kind); + if (speed <= 0.001f) speed = 1.0f; + + long startTick = MC.level.getGameTime(); + + if (kind == Kind.DOOR) { + if (isAnimatingAt(pos) || isAnimatingAt(pos.above())) return; + startDoorAnimBothHalves(pos, newState, oldOpen, newOpen, speed, startTick); + startPairedDoorAnimIfAny(pos, newState, oldOpen, newOpen, speed, startTick, cfg); + } else { + BlockState base = forceClosedModel(newState, kind); + synchronized (ANIMS) { + ANIMS.put(pos.asLong(), new Anim(pos, base, kind, oldOpen, newOpen, speed, startTick)); + } + requestRerender(pos); + } + } + + // === Render === + + private static void renderAll(float tickDelta, PoseStack matrices, MultiBufferSource consumers, Vec3 camPos) { + if (MC.level == null || ANIMS.isEmpty()) return; + + long worldTick = MC.level.getGameTime(); + double nowTick = worldTick + (double) Mth.clamp(tickDelta, 0.0f, 1.0f); + + Anim[] snapshot; + synchronized (ANIMS) { + snapshot = ANIMS.values().toArray(new Anim[0]); + } + for (Anim a : snapshot) { + float t = a.progress01(nowTick); + renderOne(a, t, camPos, matrices, consumers); + } + cleanupFinished(nowTick); + } + + private static void cleanupFinished(double nowTick) { + synchronized (ANIMS) { + var it = ANIMS.long2ObjectEntrySet().iterator(); + while (it.hasNext()) { + var entry = it.next(); + Anim anim = entry.getValue(); + if (anim.hasEnded(nowTick) && anim.hideVanilla) { + anim.hideVanilla = false; + requestRerender(anim.pos); + } + if (anim.isFinished(nowTick)) { + it.remove(); + requestRerender(anim.pos); + } + } + } + } + + private static void startPairedDoorAnimIfAny(BlockPos lowerPos, BlockState lowerState, + boolean oldOpen, boolean newOpen, + float speed, long startTick, SddConfig cfg) { + if (MC.level == null) return; + if (!cfg.connectDoors) return; + + BlockPos lower = ConnectedUtil.getDoorLowerPos(lowerPos, lowerState); + BlockState lowerNow = MC.level.getBlockState(lower); + if (!(lowerNow.getBlock() instanceof DoorBlock)) return; + + BlockPos mateLower = ConnectedUtil.findPairedDoorLower(MC.level, lower, lowerNow); + if (mateLower == null) return; + if (isHiddenByAnim(mateLower) || isHiddenByAnim(mateLower.above())) return; + + BlockState mateLowerState = MC.level.getBlockState(mateLower); + if (!(mateLowerState.getBlock() instanceof DoorBlock)) return; + if (mateLowerState.hasProperty(DoorBlock.OPEN)) { + mateLowerState = mateLowerState.setValue(DoorBlock.OPEN, newOpen); + } + mateLowerState = mateLowerState.setValue(DoorBlock.HALF, DoubleBlockHalf.LOWER); + + startDoorAnimBothHalves(mateLower, mateLowerState, oldOpen, newOpen, speed, startTick); + } + + private static void renderOne(Anim anim, float t, Vec3 camPos, PoseStack matrices, + MultiBufferSource consumers) { + if (MC.level == null) return; + + BlockPos pos = anim.pos; + BlockState state = anim.baseState; + + matrices.pushPose(); + + // Coordenadas relativas a camara (requerido por WorldRenderEvents consumidores) + matrices.translate( + pos.getX() - camPos.x, + pos.getY() - camPos.y, + pos.getZ() - camPos.z + ); + + float eased = easeInOut(t); + float angleDeg = lerpAngleDeg(anim.fromOpen, anim.toOpen, eased, anim.kind, state); + + int light = LevelRenderer.getLightColor((BlockAndTintGetter) MC.level, pos); + if (anim.kind == Kind.FENCE_GATE) { + FenceGateAnimation.render(state, angleDeg, matrices, consumers, light, OverlayTexture.NO_OVERLAY); + } else { + applyTransform(anim.kind, state, angleDeg, matrices); + renderBlockAsEntity(state, matrices, consumers, light, OverlayTexture.NO_OVERLAY); + } + + matrices.popPose(); + } + + // === DOOR (dos mitades) === + + private static void startDoorAnimBothHalves(BlockPos lowerPos, BlockState lowerNewState, boolean oldOpen, boolean newOpen, + float speed, long startTick) { + BlockState baseLower = forceClosedModel( + lowerNewState.setValue(DoorBlock.HALF, DoubleBlockHalf.LOWER), + Kind.DOOR + ); + + BlockPos upperPos = lowerPos.above(); + BlockState baseUpper = baseLower.setValue(DoorBlock.HALF, DoubleBlockHalf.UPPER); + + Anim aLower = new Anim(lowerPos, baseLower, Kind.DOOR, oldOpen, newOpen, speed, startTick); + Anim aUpper = new Anim(upperPos, baseUpper, Kind.DOOR, oldOpen, newOpen, speed, startTick); + + synchronized (ANIMS) { + ANIMS.put(lowerPos.asLong(), aLower); + ANIMS.put(upperPos.asLong(), aUpper); + } + requestRerender(lowerPos); + requestRerender(upperPos); + } + + private static void removeKindAt(BlockPos pos, Kind kind) { + synchronized (ANIMS) { + ANIMS.remove(pos.asLong()); + if (kind == Kind.DOOR) { + ANIMS.remove(pos.above().asLong()); + ANIMS.remove(pos.below().asLong()); + } + } + } + + // === Angulos y transforms === + + private static float lerpAngleDeg(boolean fromOpen, boolean toOpen, float t, Kind kind, BlockState state) { + float a = angleFor(kind, state, fromOpen); + float b = angleFor(kind, state, toOpen); + return Mth.lerp(t, a, b); + } + + private static float angleFor(Kind kind, BlockState state, boolean open) { + if (!open) return 0.0f; + + return switch (kind) { + case DOOR -> { + DoorHingeSide hinge = state.getValue(DoorBlock.HINGE); + yield (hinge == DoorHingeSide.RIGHT) ? -90.0f : 90.0f; + } + case TRAPDOOR -> 90.0f; + case FENCE_GATE -> 90.0f; + }; + } + + private static void applyTransform(Kind kind, BlockState state, float angleDeg, PoseStack matrices) { + switch (kind) { + case DOOR -> DoorAnimation.apply(state, angleDeg, matrices, MC.level); + case TRAPDOOR -> TrapdoorAnimation.apply(state, angleDeg, matrices, MC.level); + case FENCE_GATE -> { + } + } + } + + private static void renderBlockAsEntity(BlockState state, PoseStack matrices, + MultiBufferSource consumers, int light, int overlay) { + MC.getBlockRenderer().renderSingleBlock(state, matrices, consumers, light, overlay); + } + + // === Utilidades === + + private static BlockState forceClosedModel(BlockState s, Kind kind) { + return switch (kind) { + case DOOR -> s.setValue(DoorBlock.OPEN, false); + case TRAPDOOR -> s.setValue(TrapDoorBlock.OPEN, false); + case FENCE_GATE -> s.setValue(FenceGateBlock.OPEN, false); + }; + } + + private static boolean isKindBlock(Kind kind, BlockState state) { + Block b = state.getBlock(); + return switch (kind) { + case DOOR -> b instanceof DoorBlock; + case TRAPDOOR -> b instanceof TrapDoorBlock; + case FENCE_GATE -> b instanceof FenceGateBlock; + }; + } + + private static void requestRerender(BlockPos pos) { + if (MC.levelRenderer == null || MC.level == null) return; + BlockState st = MC.level.getBlockState(pos); + MC.levelRenderer.blockChanged(MC.level, pos, st, st, 0); + MC.levelRenderer.setBlocksDirty( + pos.getX(), pos.getY(), pos.getZ(), + pos.getX(), pos.getY(), pos.getZ() + ); + MC.levelRenderer.setSectionDirty( + SectionPos.blockToSectionCoord(pos.getX()), + SectionPos.blockToSectionCoord(pos.getY()), + SectionPos.blockToSectionCoord(pos.getZ()) + ); + } + + private static boolean isOpen(BlockState s) { + Block b = s.getBlock(); + if (b instanceof DoorBlock) return s.getValue(DoorBlock.OPEN); + if (b instanceof TrapDoorBlock) return s.getValue(TrapDoorBlock.OPEN); + if (b instanceof FenceGateBlock) return s.getValue(FenceGateBlock.OPEN); + return false; + } + + private static Kind kindOf(BlockState oldState, BlockState newState) { + Block b = newState.getBlock(); + if (b instanceof DoorBlock) return Kind.DOOR; + if (b instanceof TrapDoorBlock) return Kind.TRAPDOOR; + if (b instanceof FenceGateBlock) return Kind.FENCE_GATE; + + b = oldState.getBlock(); + if (b instanceof DoorBlock) return Kind.DOOR; + if (b instanceof TrapDoorBlock) return Kind.TRAPDOOR; + if (b instanceof FenceGateBlock) return Kind.FENCE_GATE; + + return null; + } + + private static boolean isAnimationEnabled(SddConfig cfg, Kind kind) { + return switch (kind) { + case DOOR -> cfg.animateDoors; + case TRAPDOOR -> cfg.animateTrapdoors; + case FENCE_GATE -> getBool(cfg, "animateFenceGates", false); + }; + } + + private static float speedFor(SddConfig cfg, Kind kind) { + return switch (kind) { + case DOOR -> cfg.doorSpeed; + case TRAPDOOR -> cfg.trapdoorSpeed; + case FENCE_GATE -> getFloat(cfg, "fenceGateSpeed", 1.0f); + }; + } + + private static float easeInOut(float t) { + return t * t * (3.0f - 2.0f * t); + } + + private static boolean isHiddenByAnim(BlockPos pos) { + Anim anim = ANIMS.get(pos.asLong()); + return anim != null && anim.hideVanilla; + } + + // === Reflect helpers (por si el campo no existe) === + + private static boolean getBool(Object obj, String field, boolean def) { + try { + Field f = obj.getClass().getDeclaredField(field); + f.setAccessible(true); + Object v = f.get(obj); + return (v instanceof Boolean) ? (Boolean) v : def; + } catch (Throwable ignored) { + return def; + } + } + + private static float getFloat(Object obj, String field, float def) { + try { + Field f = obj.getClass().getDeclaredField(field); + f.setAccessible(true); + Object v = f.get(obj); + if (v instanceof Float) return (Float) v; + if (v instanceof Double) return ((Double) v).floatValue(); + if (v instanceof Number) return ((Number) v).floatValue(); + return def; + } catch (Throwable ignored) { + return def; + } + } + + // === Tipos === + + public enum Kind { DOOR, TRAPDOOR, FENCE_GATE } + + private static final class Anim { + final BlockPos pos; + final BlockState baseState; + final Kind kind; + final boolean fromOpen; + final boolean toOpen; + boolean hideVanilla = true; + + final double startTick; + final double durationTicks; + + Anim(BlockPos pos, BlockState baseState, Kind kind, boolean fromOpen, boolean toOpen, + float speed, long startTick) { + this.pos = pos; + this.baseState = baseState; + this.kind = kind; + this.fromOpen = fromOpen; + this.toOpen = toOpen; + + double durS = BASE_DURATION_S / speed; + if (durS < 0.05) durS = 0.05; + + this.startTick = (double) startTick; + this.durationTicks = Math.max(1.0, durS * 20.0); + } + + float progress01(double nowTick) { + double t = (nowTick - startTick) / durationTicks; + if (t <= 0.0) return 0.0f; + if (t >= 1.0) return 1.0f; + return (float) t; + } + + boolean hasEnded(double nowTick) { + return (nowTick - startTick) >= durationTicks; + } + + boolean isFinished(double nowTick) { + return (nowTick - startTick) >= (durationTicks + END_GRACE_TICKS); + } + } +} diff --git a/src/client/java/com/straice/smoothdoors/client/anim/TrapdoorAnimation.java b/src/client/java/com/straice/smoothdoors/client/anim/TrapdoorAnimation.java new file mode 100644 index 0000000..fe69f0c --- /dev/null +++ b/src/client/java/com/straice/smoothdoors/client/anim/TrapdoorAnimation.java @@ -0,0 +1,87 @@ +package com.straice.smoothdoors.client.anim; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.math.Axis; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.BlockGetter; +import net.minecraft.world.level.block.TrapDoorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.Half; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.world.phys.shapes.VoxelShape; + +final class TrapdoorAnimation { + + private TrapdoorAnimation() {} + + static void apply(BlockState state, float baseAngleDeg, PoseStack matrices, BlockGetter world) { + if (world == null) return; + + Direction facing = state.getValue(TrapDoorBlock.FACING); + Half half = state.getValue(TrapDoorBlock.HALF); + + VoxelShape collShape = state.getCollisionShape(world, BlockPos.ZERO, CollisionContext.empty()); + AABB bb = collShape.isEmpty() + ? state.getShape(world, BlockPos.ZERO, CollisionContext.empty()).bounds() + : collShape.bounds(); + + Direction hingeSide = facing.getOpposite(); + + float pivotX = (float) ((bb.minX + bb.maxX) * 0.5); + float pivotZ = (float) ((bb.minZ + bb.maxZ) * 0.5); + switch (hingeSide) { + case NORTH -> pivotZ = (float) bb.minZ; + case SOUTH -> pivotZ = (float) bb.maxZ; + case WEST -> pivotX = (float) bb.minX; + case EAST -> pivotX = (float) bb.maxX; + default -> { + pivotX = (float) ((bb.minX + bb.maxX) * 0.5); + pivotZ = (float) ((bb.minZ + bb.maxZ) * 0.5); + } + } + float pivotY = (half == Half.TOP) ? (float) bb.maxY : (float) bb.minY; + + float angle; + switch (hingeSide) { + case NORTH, EAST -> angle = -baseAngleDeg; + case SOUTH, WEST -> angle = baseAngleDeg; + default -> angle = baseAngleDeg; + } + if (half == Half.TOP) angle = -angle; + + float thickness = (float) (bb.maxY - bb.minY); + float halfT = thickness > 0.0f ? thickness * 0.5f : (3.0f / 32.0f); + float dY = (half == Half.TOP) ? -halfT : halfT; + + double rad = Math.toRadians(angle); + float cos = (float) Math.cos(rad); + float sin = (float) Math.sin(rad); + + float shiftX = 0.0f; + float shiftY = 0.0f; + float shiftZ = 0.0f; + if (hingeSide == Direction.NORTH || hingeSide == Direction.SOUTH) { + float rotY = dY * cos; + float rotZ = dY * sin; + shiftY = dY - rotY; + shiftZ = -rotZ; + } else { + float rotX = -dY * sin; + float rotY = dY * cos; + shiftX = -rotX; + shiftY = dY - rotY; + } + + matrices.translate(shiftX, shiftY, shiftZ); + matrices.translate(pivotX, pivotY, pivotZ); + if (hingeSide == Direction.NORTH || hingeSide == Direction.SOUTH) { + matrices.mulPose(Axis.XP.rotationDegrees(angle)); + } else { + matrices.mulPose(Axis.ZP.rotationDegrees(angle)); + } + matrices.translate(-pivotX, -pivotY, -pivotZ); + matrices.translate(-shiftX, -shiftY, -shiftZ); + } +} diff --git a/src/client/java/com/straice/smoothdoors/mixin/client/BlockModelRendererMixin.java b/src/client/java/com/straice/smoothdoors/mixin/client/BlockModelRendererMixin.java new file mode 100644 index 0000000..b3d994b --- /dev/null +++ b/src/client/java/com/straice/smoothdoors/mixin/client/BlockModelRendererMixin.java @@ -0,0 +1,61 @@ +package com.straice.smoothdoors.mixin.client; + +import com.straice.smoothdoors.client.anim.SddAnimator; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.renderer.block.ModelBlockRenderer; +import net.minecraft.client.resources.model.BakedModel; +import net.minecraft.util.RandomSource; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +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; + +@Mixin(ModelBlockRenderer.class) +public class BlockModelRendererMixin { + + @Inject( + method = "tesselateBlock", + at = @At("HEAD"), + cancellable = true, + require = 0 + ) + private void sdd$tesselateBlock(BlockAndTintGetter world, BakedModel model, BlockState state, BlockPos pos, + PoseStack matrices, VertexConsumer vertices, boolean cull, RandomSource random, + long seed, int overlay, CallbackInfo ci) { + if (SddAnimator.shouldHideInChunk(pos, state)) { + ci.cancel(); + } + } + + @Inject( + method = "tesselateWithAO", + at = @At("HEAD"), + cancellable = true, + require = 0 + ) + private void sdd$tesselateWithAo(BlockAndTintGetter world, BakedModel model, BlockState state, BlockPos pos, + PoseStack matrices, VertexConsumer vertices, boolean cull, RandomSource random, + long seed, int overlay, CallbackInfo ci) { + if (SddAnimator.shouldHideInChunk(pos, state)) { + ci.cancel(); + } + } + + @Inject( + method = "tesselateWithoutAO", + at = @At("HEAD"), + cancellable = true, + require = 0 + ) + private void sdd$tesselateWithoutAo(BlockAndTintGetter world, BakedModel model, BlockState state, BlockPos pos, + PoseStack matrices, VertexConsumer vertices, boolean cull, RandomSource random, + long seed, int overlay, CallbackInfo ci) { + if (SddAnimator.shouldHideInChunk(pos, state)) { + ci.cancel(); + } + } +} diff --git a/src/client/java/com/straice/smoothdoors/mixin/client/BlockRenderManagerMixin.java b/src/client/java/com/straice/smoothdoors/mixin/client/BlockRenderManagerMixin.java new file mode 100644 index 0000000..24ea944 --- /dev/null +++ b/src/client/java/com/straice/smoothdoors/mixin/client/BlockRenderManagerMixin.java @@ -0,0 +1,33 @@ +package com.straice.smoothdoors.mixin.client; + +import com.straice.smoothdoors.client.anim.SddAnimator; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.minecraft.client.renderer.block.BlockRenderDispatcher; +import net.minecraft.core.BlockPos; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.BlockAndTintGetter; +import net.minecraft.world.level.block.state.BlockState; +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; + +@Mixin(BlockRenderDispatcher.class) +public class BlockRenderManagerMixin { + + @Inject( + method = "renderBatched", + at = @At("HEAD"), + cancellable = true, + require = 0 + ) + private void sdd$renderBatched(BlockState state, BlockPos pos, BlockAndTintGetter world, + PoseStack matrices, VertexConsumer vertexConsumer, + boolean cull, RandomSource random, + CallbackInfo ci) { + if (SddAnimator.shouldHideInChunk(pos, state)) { + ci.cancel(); + } + } +} diff --git a/src/client/java/com/straice/smoothdoors/mixin/client/ChunkRendererRegionMixin.java b/src/client/java/com/straice/smoothdoors/mixin/client/ChunkRendererRegionMixin.java new file mode 100644 index 0000000..48e7b67 --- /dev/null +++ b/src/client/java/com/straice/smoothdoors/mixin/client/ChunkRendererRegionMixin.java @@ -0,0 +1,23 @@ +package com.straice.smoothdoors.mixin.client; + +import com.straice.smoothdoors.client.anim.SddAnimator; +import net.minecraft.client.renderer.chunk.RenderChunkRegion; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +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.CallbackInfoReturnable; + +@Mixin(RenderChunkRegion.class) +public class ChunkRendererRegionMixin { + + @Inject(method = "getBlockState", at = @At("HEAD"), cancellable = true) + private void sdd$getBlockState(BlockPos pos, CallbackInfoReturnable cir) { + if (SddAnimator.isAnimatingAt(pos)) { + cir.setReturnValue(Blocks.AIR.defaultBlockState()); + cir.cancel(); + } + } +} diff --git a/src/client/java/com/straice/smoothdoors/mixin/client/ClientWorldMixin.java b/src/client/java/com/straice/smoothdoors/mixin/client/ClientWorldMixin.java new file mode 100644 index 0000000..0809d05 --- /dev/null +++ b/src/client/java/com/straice/smoothdoors/mixin/client/ClientWorldMixin.java @@ -0,0 +1,19 @@ +package com.straice.smoothdoors.mixin.client; + +import com.straice.smoothdoors.client.anim.SddAnimator; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.state.BlockState; +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; + +@Mixin(ClientLevel.class) +public class ClientWorldMixin { + + @Inject(method = "sendBlockUpdated", at = @At("TAIL")) + private void sdd$updateListeners(BlockPos pos, BlockState oldState, BlockState newState, int flags, CallbackInfo ci) { + SddAnimator.onBlockUpdate(pos, oldState, newState); + } +} diff --git a/src/client/resources/template-mod.client.mixins.json b/src/client/resources/template-mod.client.mixins.json index 26d75db..8122fb5 100644 --- a/src/client/resources/template-mod.client.mixins.json +++ b/src/client/resources/template-mod.client.mixins.json @@ -1,9 +1,12 @@ { "required": true, - "package": "com.straice.mixin.client", + "package": "com.straice.smoothdoors.mixin.client", "compatibilityLevel": "JAVA_17", "client": [ - "ExampleClientMixin" + "BlockModelRendererMixin", + "BlockRenderManagerMixin", + "ChunkRendererRegionMixin", + "ClientWorldMixin" ], "injectors": { "defaultRequire": 1 diff --git a/src/main/java/com/straice/TemplateMod.java b/src/main/java/com/straice/TemplateMod.java index 1f53723..9904e55 100644 --- a/src/main/java/com/straice/TemplateMod.java +++ b/src/main/java/com/straice/TemplateMod.java @@ -5,6 +5,8 @@ import net.fabricmc.api.ModInitializer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.straice.smoothdoors.config.SddConfigManager; + public class TemplateMod implements ModInitializer { public static final String MOD_ID = "template-mod"; @@ -15,10 +17,7 @@ public class TemplateMod implements ModInitializer { @Override public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. - - LOGGER.info("Hello Fabric world!"); + SddConfigManager.load(); + LOGGER.info("Smooth Double Doors loaded"); } -} \ No newline at end of file +} diff --git a/src/main/java/com/straice/smoothdoors/config/SddConfig.java b/src/main/java/com/straice/smoothdoors/config/SddConfig.java new file mode 100644 index 0000000..4015704 --- /dev/null +++ b/src/main/java/com/straice/smoothdoors/config/SddConfig.java @@ -0,0 +1,20 @@ +package com.straice.smoothdoors.config; + +public class SddConfig { + public boolean connectDoors = true; + public boolean redstoneDoubleDoors = true; + + public boolean connectTrapdoors = false; + public boolean redstoneDoubleTrapdoors = false; + + public boolean connectFenceGates = false; + public boolean redstoneDoubleFenceGates = false; + + public boolean animateDoors = true; + public boolean animateTrapdoors = true; + public boolean animateFenceGates = true; + + public float doorSpeed = 1.0f; + public float trapdoorSpeed = 1.0f; + public float fenceGateSpeed = 1.0f; +} diff --git a/src/main/java/com/straice/smoothdoors/config/SddConfigManager.java b/src/main/java/com/straice/smoothdoors/config/SddConfigManager.java new file mode 100644 index 0000000..9213773 --- /dev/null +++ b/src/main/java/com/straice/smoothdoors/config/SddConfigManager.java @@ -0,0 +1,40 @@ +package com.straice.smoothdoors.config; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import net.fabricmc.loader.api.FabricLoader; + +import java.nio.file.Files; +import java.nio.file.Path; + +public final class SddConfigManager { + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + private static final Path PATH = FabricLoader.getInstance().getConfigDir().resolve("smooth-double-doors.json"); + + private static SddConfig config = new SddConfig(); + + private SddConfigManager() {} + + public static SddConfig get() { return config; } + + public static void load() { + try { + if (Files.exists(PATH)) { + String json = Files.readString(PATH); + SddConfig read = GSON.fromJson(json, SddConfig.class); + if (read != null) config = read; + } else { + save(); + } + } catch (Exception ignored) { + // si falla, usamos defaults + } + } + + public static void save() { + try { + Files.createDirectories(PATH.getParent()); + Files.writeString(PATH, GSON.toJson(config)); + } catch (Exception ignored) {} + } +} diff --git a/src/main/java/com/straice/smoothdoors/mixin/DoorBlockMixin.java b/src/main/java/com/straice/smoothdoors/mixin/DoorBlockMixin.java new file mode 100644 index 0000000..3c0be87 --- /dev/null +++ b/src/main/java/com/straice/smoothdoors/mixin/DoorBlockMixin.java @@ -0,0 +1,68 @@ +package com.straice.smoothdoors.mixin; + +import com.straice.smoothdoors.config.SddConfigManager; +import com.straice.smoothdoors.util.ConnectedUtil; +import com.straice.smoothdoors.util.SyncGuard; +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.DoorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.phys.BlockHitResult; +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.CallbackInfoReturnable; + +@Mixin(DoorBlock.class) +public class DoorBlockMixin { + + private void sdd$handleUse(BlockState state, Level level, BlockPos pos) { + if (level.isClientSide()) return; + if (!SddConfigManager.get().connectDoors) return; + if (SyncGuard.isIn()) return; + + BlockPos lower = ConnectedUtil.getDoorLowerPos(pos, state); + BlockState lowerNow = level.getBlockState(lower); + if (!lowerNow.hasProperty(DoorBlock.OPEN)) return; + + boolean openNow = lowerNow.getValue(DoorBlock.OPEN); + BlockPos mateLower = ConnectedUtil.findPairedDoorLower(level, lower, lowerNow); + if (mateLower == null) return; + + SyncGuard.run(() -> ConnectedUtil.setDoorOpen(level, mateLower, openNow)); + } + + @Inject(method = "use", at = @At("TAIL")) + private void sdd$use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult hit, CallbackInfoReturnable cir) { + sdd$handleUse(state, level, pos); + } + + private void sdd$handleNeighborUpdate(BlockState state, Level level, BlockPos pos) { + if (level.isClientSide()) return; + if (!SddConfigManager.get().connectDoors) return; + if (!SddConfigManager.get().redstoneDoubleDoors) return; + if (SyncGuard.isIn()) return; + + BlockPos lower = ConnectedUtil.getDoorLowerPos(pos, state); + BlockState lowerNow = level.getBlockState(lower); + if (!lowerNow.hasProperty(DoorBlock.OPEN)) return; + + boolean openNow = lowerNow.getValue(DoorBlock.OPEN); + BlockPos mateLower = ConnectedUtil.findPairedDoorLower(level, lower, lowerNow); + if (mateLower == null) return; + + SyncGuard.run(() -> ConnectedUtil.setDoorOpen(level, mateLower, openNow)); + } + + @Inject(method = "neighborChanged", at = @At("TAIL")) + private void sdd$neighborChanged(BlockState state, Level level, BlockPos pos, Block block, + BlockPos fromPos, boolean notify, CallbackInfo ci) { + sdd$handleNeighborUpdate(state, level, pos); + } +} diff --git a/src/main/java/com/straice/smoothdoors/mixin/FenceGateBlockMixin.java b/src/main/java/com/straice/smoothdoors/mixin/FenceGateBlockMixin.java new file mode 100644 index 0000000..df1c985 --- /dev/null +++ b/src/main/java/com/straice/smoothdoors/mixin/FenceGateBlockMixin.java @@ -0,0 +1,66 @@ +package com.straice.smoothdoors.mixin; + +import com.straice.smoothdoors.config.SddConfigManager; +import com.straice.smoothdoors.util.ConnectedUtil; +import com.straice.smoothdoors.util.SyncGuard; +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.FenceGateBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.phys.BlockHitResult; +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.CallbackInfoReturnable; + +@Mixin(FenceGateBlock.class) +public class FenceGateBlockMixin { + + private void sdd$handleUse(BlockState state, Level level, BlockPos pos) { + if (level.isClientSide()) return; + if (!SddConfigManager.get().connectFenceGates) return; + if (SyncGuard.isIn()) return; + + BlockState now = level.getBlockState(pos); + if (!now.hasProperty(FenceGateBlock.OPEN)) return; + + boolean openNow = now.getValue(FenceGateBlock.OPEN); + BlockPos mate = ConnectedUtil.findPairedFenceGate(level, pos, now); + if (mate == null) return; + + SyncGuard.run(() -> ConnectedUtil.setFenceGateOpen(level, mate, openNow)); + } + + @Inject(method = "use", at = @At("TAIL")) + private void sdd$use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult hit, CallbackInfoReturnable cir) { + sdd$handleUse(state, level, pos); + } + + private void sdd$handleNeighborUpdate(BlockState state, Level level, BlockPos pos) { + if (level.isClientSide()) return; + if (!SddConfigManager.get().connectFenceGates) return; + if (!SddConfigManager.get().redstoneDoubleFenceGates) return; + if (SyncGuard.isIn()) return; + + BlockState now = level.getBlockState(pos); + if (!now.hasProperty(FenceGateBlock.OPEN)) return; + + boolean openNow = now.getValue(FenceGateBlock.OPEN); + BlockPos mate = ConnectedUtil.findPairedFenceGate(level, pos, now); + if (mate == null) return; + + SyncGuard.run(() -> ConnectedUtil.setFenceGateOpen(level, mate, openNow)); + } + + @Inject(method = "neighborChanged", at = @At("TAIL")) + private void sdd$neighborChanged(BlockState state, Level level, BlockPos pos, Block block, + BlockPos fromPos, boolean notify, CallbackInfo ci) { + sdd$handleNeighborUpdate(state, level, pos); + } +} diff --git a/src/main/java/com/straice/smoothdoors/mixin/TrapdoorBlockMixin.java b/src/main/java/com/straice/smoothdoors/mixin/TrapdoorBlockMixin.java new file mode 100644 index 0000000..50bb207 --- /dev/null +++ b/src/main/java/com/straice/smoothdoors/mixin/TrapdoorBlockMixin.java @@ -0,0 +1,66 @@ +package com.straice.smoothdoors.mixin; + +import com.straice.smoothdoors.config.SddConfigManager; +import com.straice.smoothdoors.util.ConnectedUtil; +import com.straice.smoothdoors.util.SyncGuard; +import net.minecraft.core.BlockPos; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.TrapDoorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.phys.BlockHitResult; +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.CallbackInfoReturnable; + +@Mixin(TrapDoorBlock.class) +public class TrapdoorBlockMixin { + + private void sdd$handleUse(BlockState state, Level level, BlockPos pos) { + if (level.isClientSide()) return; + if (!SddConfigManager.get().connectTrapdoors) return; + if (SyncGuard.isIn()) return; + + BlockState now = level.getBlockState(pos); + if (!now.hasProperty(TrapDoorBlock.OPEN)) return; + + boolean openNow = now.getValue(TrapDoorBlock.OPEN); + BlockPos mate = ConnectedUtil.findPairedTrapdoor(level, pos, now); + if (mate == null) return; + + SyncGuard.run(() -> ConnectedUtil.setTrapdoorOpen(level, mate, openNow)); + } + + @Inject(method = "use", at = @At("TAIL")) + private void sdd$use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, + BlockHitResult hit, CallbackInfoReturnable cir) { + sdd$handleUse(state, level, pos); + } + + private void sdd$handleNeighborUpdate(BlockState state, Level level, BlockPos pos) { + if (level.isClientSide()) return; + if (!SddConfigManager.get().connectTrapdoors) return; + if (!SddConfigManager.get().redstoneDoubleTrapdoors) return; + if (SyncGuard.isIn()) return; + + BlockState now = level.getBlockState(pos); + if (!now.hasProperty(TrapDoorBlock.OPEN)) return; + + boolean openNow = now.getValue(TrapDoorBlock.OPEN); + BlockPos mate = ConnectedUtil.findPairedTrapdoor(level, pos, now); + if (mate == null) return; + + SyncGuard.run(() -> ConnectedUtil.setTrapdoorOpen(level, mate, openNow)); + } + + @Inject(method = "neighborChanged", at = @At("TAIL")) + private void sdd$neighborChanged(BlockState state, Level level, BlockPos pos, Block block, + BlockPos fromPos, boolean notify, CallbackInfo ci) { + sdd$handleNeighborUpdate(state, level, pos); + } +} diff --git a/src/main/java/com/straice/smoothdoors/util/ConnectedUtil.java b/src/main/java/com/straice/smoothdoors/util/ConnectedUtil.java new file mode 100644 index 0000000..30ebff2 --- /dev/null +++ b/src/main/java/com/straice/smoothdoors/util/ConnectedUtil.java @@ -0,0 +1,125 @@ +package com.straice.smoothdoors.util; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.DoorBlock; +import net.minecraft.world.level.block.FenceGateBlock; +import net.minecraft.world.level.block.TrapDoorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.DoorHingeSide; +import net.minecraft.world.level.block.state.properties.DoubleBlockHalf; +import net.minecraft.world.level.block.state.properties.Half; + +public final class ConnectedUtil { + private ConnectedUtil() {} + + // ===== DOORS ===== + + public static BlockPos getDoorLowerPos(BlockPos pos, BlockState state) { + DoubleBlockHalf half = state.getValue(DoorBlock.HALF); + return half == DoubleBlockHalf.LOWER ? pos : pos.below(); + } + + public static BlockPos findPairedDoorLower(Level world, BlockPos lowerPos, BlockState lowerState) { + if (!(lowerState.getBlock() instanceof DoorBlock)) return null; + + Direction facing = lowerState.getValue(DoorBlock.FACING); + DoorHingeSide hinge = lowerState.getValue(DoorBlock.HINGE); + + Direction side = (hinge == DoorHingeSide.LEFT) + ? facing.getClockWise() + : facing.getCounterClockWise(); + + BlockPos otherLower = lowerPos.relative(side); + BlockState other = world.getBlockState(otherLower); + + if (other.getBlock() != lowerState.getBlock()) return null; + if (!(other.getBlock() instanceof DoorBlock)) return null; + if (other.getValue(DoorBlock.HALF) != DoubleBlockHalf.LOWER) return null; + if (other.getValue(DoorBlock.FACING) != facing) return null; + if (other.getValue(DoorBlock.HINGE) == hinge) return null; + + return otherLower; + } + + public static void setDoorOpen(Level world, BlockPos doorLower, boolean open) { + BlockState lower = world.getBlockState(doorLower); + if (!(lower.getBlock() instanceof DoorBlock)) return; + + BlockPos upperPos = doorLower.above(); + BlockState upper = world.getBlockState(upperPos); + + world.setBlock(doorLower, lower.setValue(DoorBlock.OPEN, open), Block.UPDATE_ALL); + + if (upper.getBlock() == lower.getBlock()) { + world.setBlock(upperPos, upper.setValue(DoorBlock.OPEN, open), Block.UPDATE_ALL); + } + } + + // ===== TRAPDOORS ===== + + public static BlockPos findPairedTrapdoor(Level world, BlockPos pos, BlockState state) { + if (!(state.getBlock() instanceof TrapDoorBlock)) return null; + + Direction facing = state.getValue(TrapDoorBlock.FACING); + Half half = state.getValue(TrapDoorBlock.HALF); + + BlockPos left = pos.relative(facing.getCounterClockWise()); + BlockPos right = pos.relative(facing.getClockWise()); + + BlockPos mate = matchTrapdoor(world, state, left, facing, half); + if (mate != null) return mate; + return matchTrapdoor(world, state, right, facing, half); + } + + private static BlockPos matchTrapdoor(Level world, BlockState a, BlockPos candidate, Direction facing, Half half) { + BlockState b = world.getBlockState(candidate); + if (b.getBlock() != a.getBlock()) return null; + if (!(b.getBlock() instanceof TrapDoorBlock)) return null; + + if (b.getValue(TrapDoorBlock.FACING) != facing) return null; + if (b.getValue(TrapDoorBlock.HALF) != half) return null; + + return candidate; + } + + public static void setTrapdoorOpen(Level world, BlockPos pos, boolean open) { + BlockState st = world.getBlockState(pos); + if (!(st.getBlock() instanceof TrapDoorBlock)) return; + + world.setBlock(pos, st.setValue(TrapDoorBlock.OPEN, open), Block.UPDATE_ALL); + } + + // ===== FENCE GATES ===== + + public static BlockPos findPairedFenceGate(Level world, BlockPos pos, BlockState state) { + if (!(state.getBlock() instanceof FenceGateBlock)) return null; + + Direction facing = state.getValue(FenceGateBlock.FACING); + + BlockPos left = pos.relative(facing.getCounterClockWise()); + BlockPos right = pos.relative(facing.getClockWise()); + + BlockPos mate = matchFenceGate(world, state, left, facing); + if (mate != null) return mate; + return matchFenceGate(world, state, right, facing); + } + + private static BlockPos matchFenceGate(Level world, BlockState a, BlockPos candidate, Direction facing) { + BlockState b = world.getBlockState(candidate); + if (b.getBlock() != a.getBlock()) return null; + if (!(b.getBlock() instanceof FenceGateBlock)) return null; + + if (b.getValue(FenceGateBlock.FACING) != facing) return null; + return candidate; + } + + public static void setFenceGateOpen(Level world, BlockPos pos, boolean open) { + BlockState st = world.getBlockState(pos); + if (!(st.getBlock() instanceof FenceGateBlock)) return; + + world.setBlock(pos, st.setValue(FenceGateBlock.OPEN, open), Block.UPDATE_ALL); + } +} diff --git a/src/main/java/com/straice/smoothdoors/util/SyncGuard.java b/src/main/java/com/straice/smoothdoors/util/SyncGuard.java new file mode 100644 index 0000000..a8e5305 --- /dev/null +++ b/src/main/java/com/straice/smoothdoors/util/SyncGuard.java @@ -0,0 +1,16 @@ +package com.straice.smoothdoors.util; + +public final class SyncGuard { + private static final ThreadLocal IN = ThreadLocal.withInitial(() -> false); + + private SyncGuard() {} + + public static boolean isIn() { return IN.get(); } + + public static void run(Runnable r) { + if (isIn()) return; + IN.set(true); + try { r.run(); } + finally { IN.set(false); } + } +} diff --git a/src/main/resources/template-mod.mixins.json b/src/main/resources/template-mod.mixins.json index 4e5c87e..1196547 100644 --- a/src/main/resources/template-mod.mixins.json +++ b/src/main/resources/template-mod.mixins.json @@ -1,10 +1,11 @@ { "required": true, - "package": "com.straice.mixin", + "package": "com.straice.smoothdoors.mixin", "compatibilityLevel": "JAVA_17", "mixins": [ "DoorBlockMixin", - "ExampleMixin" + "FenceGateBlockMixin", + "TrapdoorBlockMixin" ], "injectors": { "defaultRequire": 1 diff --git a/tt.png b/tt.png new file mode 100644 index 0000000000000000000000000000000000000000..63a55e0be5fb964c2676bcd39da104459346beb4 GIT binary patch literal 155620 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 rnQ9pw9sTtaCAD}4jDMj`^>cZiZ