|
1 | 1 | package com.minecolonies.core.client.render; |
2 | 2 |
|
3 | 3 | import com.minecolonies.api.blocks.ModBlocks; |
| 4 | +import com.minecolonies.core.client.render.worldevent.ColonyWorldRenderMacros; |
| 5 | +import com.minecolonies.core.client.render.worldevent.WorldEventContext; |
4 | 6 | import com.minecolonies.core.tileentities.TileEntityColonySign; |
5 | 7 | import com.mojang.blaze3d.vertex.PoseStack; |
6 | 8 | import com.mojang.math.Axis; |
7 | 9 | import net.minecraft.client.Minecraft; |
8 | 10 | import net.minecraft.client.renderer.block.BlockRenderDispatcher; |
9 | 11 | import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider; |
| 12 | +import net.minecraft.client.renderer.entity.EntityRenderDispatcher; |
10 | 13 | import net.minecraft.client.resources.model.BakedModel; |
| 14 | +import net.minecraft.core.BlockPos; |
11 | 15 | import net.minecraft.network.chat.Component; |
12 | 16 | import net.minecraft.network.chat.FormattedText; |
| 17 | +import net.minecraft.network.chat.MutableComponent; |
13 | 18 | import net.minecraft.util.RandomSource; |
14 | 19 | import net.minecraft.world.level.block.state.BlockState; |
15 | 20 | import net.minecraft.client.gui.Font; |
16 | 21 | import net.minecraft.client.renderer.MultiBufferSource; |
17 | 22 | import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; |
18 | 23 | import net.minecraft.util.FormattedCharSequence; |
19 | 24 | import net.minecraft.network.chat.Style; |
| 25 | +import net.minecraft.world.phys.AABB; |
| 26 | +import net.minecraft.world.phys.BlockHitResult; |
| 27 | +import net.minecraft.world.phys.HitResult; |
20 | 28 | import net.minecraftforge.api.distmarker.Dist; |
21 | 29 | import net.minecraftforge.api.distmarker.OnlyIn; |
22 | 30 | import net.minecraftforge.client.model.data.ModelData; |
23 | 31 | import org.jetbrains.annotations.NotNull; |
| 32 | +import org.joml.Matrix4f; |
24 | 33 |
|
25 | 34 | import java.util.List; |
26 | 35 |
|
| 36 | +import static com.minecolonies.api.util.constant.TranslationConstants.NEXT; |
| 37 | +import static com.minecolonies.api.util.constant.TranslationConstants.PREVIOUS; |
27 | 38 | import static com.minecolonies.core.blocks.BlockColonySign.CONNECTED; |
28 | 39 |
|
29 | 40 | @OnlyIn(Dist.CLIENT) |
@@ -57,51 +68,66 @@ public void render( |
57 | 68 | final int combinedLight, |
58 | 69 | final int combinedOverlay) |
59 | 70 | { |
60 | | - if (tileEntity != null) |
| 71 | + final float relativeRotationToColony = tileEntity.getRelativeRotation(); |
| 72 | + final BlockState state = tileEntity.getBlockState(); |
| 73 | + if (state.getBlock() == ModBlocks.blockColonySign) |
61 | 74 | { |
62 | | - final float relativeRotationToColony = tileEntity.getRelativeRotation(); |
63 | | - final BlockState state = tileEntity.getLevel().getBlockState(tileEntity.getBlockPos()); |
64 | | - if (state.getBlock() == ModBlocks.blockColonySign) |
| 75 | + matrixStack.pushPose(); |
| 76 | + matrixStack.translate(0.5, 0.5, 0.5); |
| 77 | + matrixStack.mulPose(Axis.YP.rotationDegrees(relativeRotationToColony)); |
| 78 | + matrixStack.translate(-0.5, -0.5, -0.5); |
| 79 | + renderSingleBlock(state, matrixStack, buffer, combinedLight, combinedOverlay, tileEntity.getTargetColonyId() != tileEntity.getCachedSignAboveColony()); |
| 80 | + matrixStack.popPose(); |
| 81 | + |
| 82 | + renderTextOnSide(matrixStack, relativeRotationToColony, tileEntity, buffer, combinedLight, true); |
| 83 | + renderTextOnSide(matrixStack, relativeRotationToColony, tileEntity, buffer, combinedLight, false); |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + /** |
| 88 | + * Render the text on the sign and handle rotation etc. |
| 89 | + * @param matrixStack the matrix stack. |
| 90 | + * @param relativeRotationToColony the relative rotation. |
| 91 | + * @param tileEntity the block entity. |
| 92 | + * @param buffer the buffer. |
| 93 | + * @param combinedLight the light. |
| 94 | + * @param mirrored if mirrored or not. |
| 95 | + */ |
| 96 | + private void renderTextOnSide(final PoseStack matrixStack, final float relativeRotationToColony, final @NotNull TileEntityColonySign tileEntity, final @NotNull MultiBufferSource buffer, final int combinedLight, final boolean mirrored) |
| 97 | + { |
| 98 | + matrixStack.pushPose(); |
| 99 | + matrixStack.translate(0.5f, 0.5F, 0.5f); |
| 100 | + matrixStack.mulPose(Axis.YP.rotationDegrees(relativeRotationToColony)); |
| 101 | + if (mirrored) |
| 102 | + { |
| 103 | + matrixStack.mulPose(Axis.YP.rotationDegrees(180)); |
| 104 | + } |
| 105 | + matrixStack.translate(-0.0f, -0.1F, 0.2f); |
| 106 | + |
| 107 | + matrixStack.scale(0.007F, -0.007F, 0.007F); |
| 108 | + |
| 109 | + final String colonyName = tileEntity.getColonyName(); |
| 110 | + final int distance = tileEntity.getColonyDistance(); |
| 111 | + if (colonyName.isEmpty()) |
| 112 | + { |
| 113 | + renderText(matrixStack, buffer, combinedLight, "Unknown Colony", 0, 0); |
| 114 | + renderText(matrixStack, buffer, combinedLight, Component.translatable("com.minecolonies.coremod.dist.blocks",distance).getString(), 3, 0); |
| 115 | + } |
| 116 | + else |
| 117 | + { |
| 118 | + final String targetColonyName = tileEntity.getTargetColonyName(); |
| 119 | + if (!targetColonyName.isEmpty() && tileEntity.getTargetColonyId() != tileEntity.getCachedSignAboveColony()) |
65 | 120 | { |
66 | | - matrixStack.pushPose(); |
67 | | - matrixStack.translate(0.5, 0.5, 0.5); |
68 | | - matrixStack.mulPose(Axis.YP.rotationDegrees(relativeRotationToColony)); |
69 | | - matrixStack.translate(-0.5, -0.5, -0.5); |
70 | | - renderSingleBlock(state, matrixStack, buffer, combinedLight, combinedOverlay, tileEntity.getTargetColonyId() != -1); |
71 | | - matrixStack.popPose(); |
72 | | - |
73 | | - matrixStack.pushPose(); |
74 | | - matrixStack.translate(0.5f, 0.5F, 0.5f); |
75 | | - matrixStack.mulPose(Axis.YP.rotationDegrees(relativeRotationToColony)); |
76 | | - matrixStack.mulPose(Axis.YP.rotationDegrees(180)); |
77 | | - matrixStack.translate(-0.0f, -0.1F, 0.2f); |
78 | | - |
79 | | - matrixStack.scale(0.007F, -0.007F, 0.007F); |
80 | | - |
81 | | - final String colonyName = tileEntity.getColonyName(); |
82 | | - final int distance = tileEntity.getColonyDistance(); |
83 | | - if (colonyName.isEmpty()) |
84 | | - { |
85 | | - renderText(matrixStack, buffer, combinedLight, "Unknown Colony", 0, 0); |
86 | | - renderText(matrixStack, buffer, combinedLight, Component.translatable("com.minecolonies.coremod.dist.blocks",distance).getString(), 3, 0); |
87 | | - } |
88 | | - else |
89 | | - { |
90 | | - final String targetColonyName = tileEntity.getTargetColonyName(); |
91 | | - if (!targetColonyName.isEmpty()) |
92 | | - { |
93 | | - final int targetColonyDistance = tileEntity.getTargetColonyDistance(); |
94 | | - renderColonyNameOnSign(colonyName, matrixStack, buffer, combinedLight, distance, -10); |
95 | | - renderColonyNameOnSign(targetColonyName, matrixStack, buffer, combinedLight, targetColonyDistance, -60); |
96 | | - } |
97 | | - else |
98 | | - { |
99 | | - renderColonyNameOnSign(colonyName, matrixStack, buffer, combinedLight, distance, 0); |
100 | | - } |
101 | | - } |
102 | | - matrixStack.popPose(); |
| 121 | + final int targetColonyDistance = tileEntity.getTargetColonyDistance(); |
| 122 | + renderColonyNameOnSign(colonyName, matrixStack, buffer, combinedLight, distance, -10); |
| 123 | + renderColonyNameOnSign(targetColonyName, matrixStack, buffer, combinedLight, targetColonyDistance, -60); |
| 124 | + } |
| 125 | + else |
| 126 | + { |
| 127 | + renderColonyNameOnSign(colonyName, matrixStack, buffer, combinedLight, distance, -35); |
103 | 128 | } |
104 | 129 | } |
| 130 | + matrixStack.popPose(); |
105 | 131 | } |
106 | 132 |
|
107 | 133 | /** |
@@ -193,4 +219,95 @@ public boolean shouldRenderOffScreen(TileEntityColonySign tileEntityMBE21) |
193 | 219 | { |
194 | 220 | return false; |
195 | 221 | } |
| 222 | + |
| 223 | + public static void renderSignHover(final WorldEventContext context) |
| 224 | + { |
| 225 | + final HitResult rayTraceResult = Minecraft.getInstance().hitResult; |
| 226 | + if (!(rayTraceResult instanceof final BlockHitResult blockRayTraceResult) || blockRayTraceResult.getType() == HitResult.Type.MISS) |
| 227 | + return; |
| 228 | + |
| 229 | + final BlockPos posAtCamera = blockRayTraceResult.getBlockPos(); |
| 230 | + if (context.clientLevel.getBlockState(posAtCamera).getBlock() != ModBlocks.blockColonySign) |
| 231 | + { |
| 232 | + return; |
| 233 | + } |
| 234 | + |
| 235 | + if (context.clientLevel.getBlockEntity(posAtCamera) instanceof TileEntityColonySign tileEntityColonySign) |
| 236 | + { |
| 237 | + if (!BlockPos.ZERO.equals(tileEntityColonySign.getPreviousPos())) |
| 238 | + { |
| 239 | + renderTextBoxAtPos(context, tileEntityColonySign.getPreviousPos(), List.of(Component.translatable(PREVIOUS).getString())); |
| 240 | + } |
| 241 | + if (!BlockPos.ZERO.equals(tileEntityColonySign.getNextPosition())) |
| 242 | + { |
| 243 | + renderTextBoxAtPos(context, tileEntityColonySign.getNextPosition(), List.of(Component.translatable(NEXT).getString())); |
| 244 | + } |
| 245 | + } |
| 246 | + } |
| 247 | + |
| 248 | + private static void renderTextBoxAtPos(final WorldEventContext context, final BlockPos pos, final List<String> text) |
| 249 | + { |
| 250 | + final MultiBufferSource.BufferSource buffer = Minecraft.getInstance().renderBuffers().bufferSource(); |
| 251 | + ColonyWorldRenderMacros.renderLineBox(context.poseStack, buffer, new AABB(pos), 0.05f, 0xffffffff, true); |
| 252 | + renderDebugText(pos, text, context.poseStack, true, 3, 2.5f, buffer); |
| 253 | + ColonyWorldRenderMacros.endRenderLineBox(buffer); |
| 254 | + buffer.endBatch(); |
| 255 | + } |
| 256 | + |
| 257 | + public static void renderDebugText(final BlockPos renderPos, |
| 258 | + final List<String> text, |
| 259 | + final PoseStack matrixStack, |
| 260 | + final boolean forceWhite, |
| 261 | + final int mergeEveryXListElements, |
| 262 | + final float scale, |
| 263 | + final MultiBufferSource buffer) |
| 264 | + { |
| 265 | + if (mergeEveryXListElements < 1) |
| 266 | + { |
| 267 | + throw new IllegalArgumentException("mergeEveryXListElements is less than 1"); |
| 268 | + } |
| 269 | + |
| 270 | + final EntityRenderDispatcher erm = Minecraft.getInstance().getEntityRenderDispatcher(); |
| 271 | + final int cap = text.size(); |
| 272 | + if (cap > 0) |
| 273 | + { |
| 274 | + final Font fontrenderer = Minecraft.getInstance().font; |
| 275 | + |
| 276 | + matrixStack.pushPose(); |
| 277 | + matrixStack.translate(renderPos.getX() + 0.5d, renderPos.getY() + 0.6d, renderPos.getZ() + 0.5d); |
| 278 | + matrixStack.mulPose(erm.cameraOrientation()); |
| 279 | + matrixStack.scale(-0.014f, -0.014f, 0.014f); |
| 280 | + |
| 281 | + final float backgroundTextOpacity = Minecraft.getInstance().options.getBackgroundOpacity(0.25F); |
| 282 | + final int alphaMask = (int) (backgroundTextOpacity * 255.0F) << 24; |
| 283 | + |
| 284 | + final Matrix4f rawPosMatrix = matrixStack.last().pose(); |
| 285 | + rawPosMatrix.scale(scale, scale, scale); |
| 286 | + |
| 287 | + for (int i = 0; i < cap; i += mergeEveryXListElements) |
| 288 | + { |
| 289 | + final MutableComponent renderText = Component.literal( |
| 290 | + mergeEveryXListElements == 1 ? text.get(i) : text.subList(i, Math.min(i + mergeEveryXListElements, cap)).toString()); |
| 291 | + final float textCenterShift = (float) (-fontrenderer.width(renderText) / 2); |
| 292 | + |
| 293 | + fontrenderer.drawInBatch(renderText, |
| 294 | + textCenterShift, |
| 295 | + 0, |
| 296 | + forceWhite ? 0xffffffff : 0x20ffffff, |
| 297 | + false, |
| 298 | + rawPosMatrix, |
| 299 | + buffer, |
| 300 | + Font.DisplayMode.SEE_THROUGH, |
| 301 | + alphaMask, |
| 302 | + 0x00f000f0); |
| 303 | + if (!forceWhite) |
| 304 | + { |
| 305 | + fontrenderer.drawInBatch(renderText, textCenterShift, 0, 0xffffffff, false, rawPosMatrix, buffer, Font.DisplayMode.NORMAL, 0, 0x00f000f0); |
| 306 | + } |
| 307 | + matrixStack.translate(0.0d, fontrenderer.lineHeight + 1, 0.0d); |
| 308 | + } |
| 309 | + |
| 310 | + matrixStack.popPose(); |
| 311 | + } |
| 312 | + } |
196 | 313 | } |
0 commit comments