From 8869dc4087835257b5a0637e3d1d0586e55df78b Mon Sep 17 00:00:00 2001 From: TGGamesYT Date: Wed, 25 Mar 2026 18:33:10 +0100 Subject: [PATCH] fix blueprint lighting --- gradle.properties | 2 +- .../client/BlueprintBlockEntityRenderer.java | 102 +++-------- .../szar/client/BlueprintWrappedModel.java | 165 ++++++++++++++++++ .../assets/szar/textures/block/blueprint.png | Bin 873 -> 880 bytes src/main/resources/szar.accesswidener | 3 +- 5 files changed, 193 insertions(+), 79 deletions(-) create mode 100644 src/client/java/dev/tggamesyt/szar/client/BlueprintWrappedModel.java diff --git a/gradle.properties b/gradle.properties index 2c62248..eed3948 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.10 loader_version=0.18.3 # Mod Properties -mod_version=26.3.25.1 +mod_version=26.3.25.2 maven_group=dev.tggamesyt archives_base_name=szar # Dependencies diff --git a/src/client/java/dev/tggamesyt/szar/client/BlueprintBlockEntityRenderer.java b/src/client/java/dev/tggamesyt/szar/client/BlueprintBlockEntityRenderer.java index ef43a74..d0146e5 100644 --- a/src/client/java/dev/tggamesyt/szar/client/BlueprintBlockEntityRenderer.java +++ b/src/client/java/dev/tggamesyt/szar/client/BlueprintBlockEntityRenderer.java @@ -4,10 +4,13 @@ import dev.tggamesyt.szar.BlueprintBlockEntity; import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.LightmapTextureManager; import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.render.block.BlockRenderManager; import net.minecraft.client.render.block.entity.BlockEntityRenderer; import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; +import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.registry.Registries; import net.minecraft.util.Identifier; @@ -21,6 +24,7 @@ public class BlueprintBlockEntityRenderer implements BlockEntityRenderer getQuads(BlockState state, Direction face, Random random) { + List original = blueprint.getQuads(blueprintState, face, random); + List result = new ArrayList<>(original.size()); + + for (BakedQuad quad : original) { + int[] data = quad.getVertexData().clone(); + + Direction quadFace = quad.getFace(); + Sprite target = getSpriteForFace(stored, storedState, quadFace); + + remapUVs(data, quad.getSprite(), target); + + BlockPos pos = entity.getPos(); + Camera camera = MinecraftClient.getInstance().gameRenderer.getCamera(); + Vec3d camPos = camera.getPos(); + double dx = pos.getX() + 0.5 - camPos.x; + double dy = pos.getY() + 0.5 - camPos.y; + double dz = pos.getZ() + 0.5 - camPos.z; + double distance = Math.sqrt(dx*dx + dy*dy + dz*dz); + float offsetAmount = 0.0001f + (float)distance * 1e-5f; + offsetAmount = Math.min(offsetAmount, 0.001f); // clamp max + offsetVertsAlongNormal(data, quad.getFace(), offsetAmount); + + result.add(new BakedQuad( + data, + quad.getColorIndex(), + quadFace, + target, + quad.hasShade() + )); + } + + return result; + } + + // --- IMPORTANT: delegate everything else properly --- + + @Override + public boolean useAmbientOcclusion() { + return stored.useAmbientOcclusion(); // important for lighting + } + + @Override + public boolean hasDepth() { + return stored.hasDepth(); + } + + @Override + public boolean isSideLit() { + return stored.isSideLit(); + } + + @Override + public boolean isBuiltin() { + return false; + } + + @Override + public Sprite getParticleSprite() { + return stored.getParticleSprite(); + } + + @Override + public ModelTransformation getTransformation() { + return stored.getTransformation(); + } + + @Override + public ModelOverrideList getOverrides() { + return stored.getOverrides(); + } + + // --- helpers --- + + private Sprite getSpriteForFace(BakedModel model, BlockState state, Direction face) { + Random rand = Random.create(42L); + + List quads = model.getQuads(state, face, rand); + if (!quads.isEmpty()) return quads.get(0).getSprite(); + + quads = model.getQuads(state, null, rand); + for (BakedQuad q : quads) { + if (q.getFace() == face) return q.getSprite(); + } + + return model.getParticleSprite(); + } + + private void remapUVs(int[] vertexData, Sprite from, Sprite to) { + int stride = 8; + + for (int i = 0; i < 4; i++) { + int uvIndex = i * stride + 4; + + float u = Float.intBitsToFloat(vertexData[uvIndex]); + float v = Float.intBitsToFloat(vertexData[uvIndex + 1]); + + float nu = (u - from.getMinU()) / (from.getMaxU() - from.getMinU()); + float nv = (v - from.getMinV()) / (from.getMaxV() - from.getMinV()); + + float newU = to.getMinU() + nu * (to.getMaxU() - to.getMinU()); + float newV = to.getMinV() + nv * (to.getMaxV() - to.getMinV()); + + vertexData[uvIndex] = Float.floatToRawIntBits(newU); + vertexData[uvIndex + 1] = Float.floatToRawIntBits(newV); + } + } + + private void offsetVertsAlongNormal(int[] vertexData, Direction face, float amount) { + if (face == null) return; // skip general quads + + float dx = face.getOffsetX() * amount; + float dy = face.getOffsetY() * amount; + float dz = face.getOffsetZ() * amount; + + int vertexSize = 8; // X,Y,Z,COLOR,U,V,UV2,NORMAL + for (int i = 0; i < 4; i++) { + int base = i * vertexSize; + float x = Float.intBitsToFloat(vertexData[base]); + float y = Float.intBitsToFloat(vertexData[base + 1]); + float z = Float.intBitsToFloat(vertexData[base + 2]); + + vertexData[base] = Float.floatToRawIntBits(x + dx); + vertexData[base + 1] = Float.floatToRawIntBits(y + dy); + vertexData[base + 2] = Float.floatToRawIntBits(z + dz); + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/textures/block/blueprint.png b/src/main/resources/assets/szar/textures/block/blueprint.png index e05ab79ed7b3bc2a105a5757f1429f8c7cd243e5..a21f2116f932965a954ae87531fe53e7af9ec6f1 100644 GIT binary patch delta 870 zcmV-s1DX8k2Ji-u7k>~41^@s6AM^iV0009eNkl87GrE zv8~z(IJ6}SD1a)2!~!9K#F`xf_AJ=L76}k5c8Db)A@Nwis;D5*s!>rvsPj7i2 z|JL^2`eNO?{Nc5L^X^xhUh2Ic0#54vpFFO9=I=8p${BmQPtzwn$eqF~rtnkOR zbw2;>Yc_Z5nC&h%HXd^Q&I8O^jcz_zh_J_j9$4M_P;eSbfNC@AB`2FSvrw0#lCll0o93`p|Qo_g&Y9zv-S)*Cn!z}Gm+PKZp z{tkBQ1ncy1BJujGYm%!3WY2X;X0m9B1aV`I>C`+%;R>lstE5+7LQCaHUwW3*Gb@B5 zF?8&Gg8v26INC9 z`32JXJhK;b7}+dSa~GJ5$IPTN=&2NHG#Vtp^AK;o{1lC9H7MJ2CitDVt#b~`WugI5 zrCmFM$$yA`r;X!!!L4~R*iSCTj*H!HNrD|L>-dOXy^14sH!BqyyLWNzez4cC9nfji z>DFsFeK`l7i!gMl#dA;-v!t&)kG@#o>F3tC{Nf8F(`kq%KqzPzvgr9`Qn?%nc{`es z!8b88KaXEZP?9_mX~WT&rrD9%8ieIsFd3u9Vt?qm&S*5kYPABXl8V^b+n4AuvAQ(= zE7Gmp=cu@iS>D63I!yW|ghHI3ol)H{(yrHWtrq7}D$+!)X`#)`VJs~NL!##kM05ib z6(ycTo69hLafxi9fRSH(jLWM`Wpel?5^+@~2oaHEo1C5^F2`920j?t}=t>DuCi0zF zmS2SuR`D?&(}-xAACI_SIb(4ANOt=l?%lZ+pnX~eXBe#hVTr*>MZSf9X%_DWSl#-Y wR(U5l;C}!B0RR6$uCK`e000I_L_t&o0A^HzXo*HvegFUf07*qoM6N<$f^+Plt^fc4 literal 873 zcmeAS@N?(olHy`uVBq!ia0vp^0zk~q!3HGX7W?Z1DaPU;cPEB*=VV?2IV|apzK#qG z8~eHcB(eheoCO|{#S9F5he4R}c>anMpoaF$kcg59UmvUF{9L`nl>DSry^7odplSvN z8~cia#N_PM5{0DH^vpb4_4m8?t1D!t*s6z{`WpBaIHzW0dQ=sq23ProBv)l8Tc)Vn z+wpSQR9FE`$W1LtRH(?!$t$+1uvG#ZYz1V4g!Pr|Y>HCStb$zJpeleoTcwPWk^(Dz z{qpj1y>er{{GxPyLrY6beFGzXBO_g)3fd$_#E`lw^ClIEGmGmrmNBbtpij-9GkR5i2K)C_87w1hIA} z$L)N2vcI`xe<{`W*g3~9bT*%w*JQz=$Y|&|iR+}0xb+d?{7K((zR&wScmMulpS$b% z4w;7S_O3T!NZ9_dqn|PGNpbn_mgo9`UdHqMxa1u~ewySi4{iSbaGH)c3h7d))=rMV=LBc{nS$Y;8$_uwP`%0ioAFy&GcK z>vJR0ShAQVM<~QE+Ud~v{oyu~V$m?K=T;UwJUQ8Jv`0_5WE$Z!C34QimhjK6FXt@d zTXOkh2~$DnB2I57z2!!w0arO49;bb(yLQXT=b732{8=yAf3Qw9=Mr9|r(F$7@1CxH JF6*2UngF%bLbLz? diff --git a/src/main/resources/szar.accesswidener b/src/main/resources/szar.accesswidener index e1ec0a4..a7d420d 100644 --- a/src/main/resources/szar.accesswidener +++ b/src/main/resources/szar.accesswidener @@ -6,4 +6,5 @@ accessible class net/minecraft/client/gui/hud/InGameHud$HeartType accessible field net/minecraft/server/network/ServerPlayerInteractionManager player Lnet/minecraft/server/network/ServerPlayerEntity; accessible method net/minecraft/client/render/entity/LivingEntityRenderer addFeature (Lnet/minecraft/client/render/entity/feature/FeatureRenderer;)Z accessible field net/minecraft/client/render/entity/EntityRenderDispatcher renderers Ljava/util/Map; -accessible method net/minecraft/world/GameRules$BooleanRule create (ZLjava/util/function/BiConsumer;)Lnet/minecraft/world/GameRules$Type; \ No newline at end of file +accessible method net/minecraft/world/GameRules$BooleanRule create (ZLjava/util/function/BiConsumer;)Lnet/minecraft/world/GameRules$Type; +accessible method net/minecraft/client/render/block/BlockModelRenderer renderQuad (Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/client/render/VertexConsumer;Lnet/minecraft/client/util/math/MatrixStack$Entry;Lnet/minecraft/client/render/model/BakedQuad;FFFFIIIII)V \ No newline at end of file