diff --git a/common/src/main/java/juuxel/adorn/client/renderer/InvisibleEntityRenderer.java b/common/src/main/java/juuxel/adorn/client/renderer/InvisibleEntityRenderer.java new file mode 100644 index 000000000..820bbe94b --- /dev/null +++ b/common/src/main/java/juuxel/adorn/client/renderer/InvisibleEntityRenderer.java @@ -0,0 +1,19 @@ +package juuxel.adorn.client.renderer; + +import net.minecraft.client.render.entity.EntityRenderer; +import net.minecraft.client.render.entity.EntityRendererFactory; +import net.minecraft.entity.Entity; +import net.minecraft.util.Identifier; + +public final class InvisibleEntityRenderer extends EntityRenderer { + private static final Identifier TEXTURE = new Identifier("missingno"); + + public InvisibleEntityRenderer(EntityRendererFactory.Context ctx) { + super(ctx); + } + + @Override + public Identifier getTexture(Entity entity) { + return TEXTURE; + } +} diff --git a/common/src/main/java/juuxel/adorn/client/renderer/KitchenSinkRenderer.java b/common/src/main/java/juuxel/adorn/client/renderer/KitchenSinkRenderer.java new file mode 100644 index 000000000..96fa6ae8d --- /dev/null +++ b/common/src/main/java/juuxel/adorn/client/renderer/KitchenSinkRenderer.java @@ -0,0 +1,118 @@ +package juuxel.adorn.client.renderer; + +import juuxel.adorn.block.AbstractKitchenCounterBlock; +import juuxel.adorn.block.entity.KitchenSinkBlockEntity; +import juuxel.adorn.client.FluidRenderingBridge; +import juuxel.adorn.util.Logging; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; +import net.minecraft.client.texture.MissingSprite; +import net.minecraft.client.texture.Sprite; +import net.minecraft.client.texture.SpriteAtlasTexture; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RotationAxis; +import org.slf4j.Logger; + +public abstract class KitchenSinkRenderer implements BlockEntityRenderer { + private static final Logger LOGGER = Logging.logger(); + private static final float PX = 1 / 16f; + private static final float X_START = 2 * PX; + private static final float X_END = 13 * PX; + private static final float Z_START = 2 * PX; + private static final float Z_END = 14 * PX; + private static final float Y_START = 7 * PX; + private static final float Y_END = 15 * PX; + private static final double LITRES_PER_BLOCK = 1000.0; + + // Wave period in ms + private static final float WAVE_PERIOD = 12_000f; + private static final float WAVE_HEIGHT = PX; + private static final float MS_PER_TICK = 50f; + + private static float getRotation(Direction facing) { + return switch (facing) { + case EAST -> 0f; + case NORTH -> 90f; + case WEST -> 180f; + case SOUTH -> 270f; + // Vertical orientations + default -> 0f; + }; + } + + protected KitchenSinkRenderer(BlockEntityRendererFactory.Context context) { + } + + @Override + public void render(T entity, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { + // Skip if there's nothing to render + if (isEmpty(entity)) return; + + var sprite = getFluidSprite(entity); + var buffer = vertexConsumers.getBuffer(RenderLayer.getEntityTranslucent(sprite.getAtlasId())); + float u0 = MathHelper.lerp(2 * PX, sprite.getMinU(), sprite.getMaxU()); + float u1 = MathHelper.lerp(14 * PX, sprite.getMinU(), sprite.getMaxU()); + float v0 = MathHelper.lerp(2 * PX, sprite.getMinV(), sprite.getMaxV()); + float v1 = MathHelper.lerp(13 * PX, sprite.getMinV(), sprite.getMaxV()); + + matrices.push(); + // Rotate because the model depends on the facing property + matrices.translate(0.5, 0.0, 0.5); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(getRotation(entity.getCachedState().get(AbstractKitchenCounterBlock.FACING)))); + matrices.translate(-0.5, 0.0, -0.5); + + // Move vertically to correct level + double fluidLevel = getFluidLevel(entity) / LITRES_PER_BLOCK; + matrices.translate(0.0, MathHelper.lerp(fluidLevel, Y_START, Y_END), 0.0); + + // Draw the sprite + + var positionMatrix = matrices.peek().getPositionMatrix(); + var normalMatrix = matrices.peek().getNormalMatrix(); + var color = getFluidColor(entity); + buffer.vertex(positionMatrix, X_START, computeY(X_START, Z_END), Z_END) + .color(color).texture(u0, v0).overlay(overlay).light(light).normal(normalMatrix, 0f, 1f, 0f).next(); + buffer.vertex(positionMatrix, X_END, computeY(X_END, Z_END), Z_END) + .color(color).texture(u0, v1).overlay(overlay).light(light).normal(normalMatrix, 0f, 1f, 0f).next(); + buffer.vertex(positionMatrix, X_END, computeY(X_END, Z_START), Z_START) + .color(color).texture(u1, v1).overlay(overlay).light(light).normal(normalMatrix, 0f, 1f, 0f).next(); + buffer.vertex(positionMatrix, X_START, computeY(X_START, Z_START), Z_START) + .color(color).texture(u1, v0).overlay(overlay).light(light).normal(normalMatrix, 0f, 1f, 0f).next(); + matrices.pop(); + } + + private static float computeY(float x, float z) { + var time = (MinecraftClient.getInstance().player.age * MS_PER_TICK) % WAVE_PERIOD; + var t = time * MathHelper.TAU / WAVE_PERIOD; + return MathHelper.sin(t + x + z) * WAVE_HEIGHT / 2; + } + + private Sprite getFluidSprite(T entity) { + var sprite = FluidRenderingBridge.get().getStillSprite(entity.getFluidReference()); + + if (sprite == null) { + LOGGER.error("Could not find sprite for fluid reference {} when rendering kitchen sink at {}", entity.getFluidReference(), entity.getPos()); + return MinecraftClient.getInstance() + .getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE) + .apply(MissingSprite.getMissingSpriteId()); + } + + return sprite; + } + + /** Gets the entity's fluid's color. */ + private int getFluidColor(T entity) { + return FluidRenderingBridge.get().getColor(entity.getFluidReference(), entity.getWorld(), entity.getPos()); + } + + /** Gets the fluid level from the entity in litres. */ + protected abstract double getFluidLevel(T entity); + + /** Tests whether the [entity] has no fluid inside. */ + protected abstract boolean isEmpty(T entity); +} diff --git a/common/src/main/java/juuxel/adorn/client/renderer/ShelfRenderer.java b/common/src/main/java/juuxel/adorn/client/renderer/ShelfRenderer.java new file mode 100644 index 000000000..12016c833 --- /dev/null +++ b/common/src/main/java/juuxel/adorn/client/renderer/ShelfRenderer.java @@ -0,0 +1,80 @@ +package juuxel.adorn.client.renderer; + +import juuxel.adorn.block.ShelfBlock; +import juuxel.adorn.block.entity.ShelfBlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; +import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.RotationAxis; + +public final class ShelfRenderer implements BlockEntityRenderer { + private static final float ITEM_SCALE = 0.5f; + private static final float ITEM_1_Y_ROT = 10f; + private static final float ITEM_2_Y_ROT = -17f; + + public ShelfRenderer(BlockEntityRendererFactory.Context context) { + } + + @Override + public void render(ShelfBlockEntity be, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { + Direction facing = be.getCachedState().get(ShelfBlock.FACING); + + // For first item + double tx1 = switch (facing) { + case SOUTH, WEST -> 12 / 16.0; + default -> 4 / 16.0; + }; + double tz1 = switch (facing) { + case NORTH, WEST -> 12 / 16.0; + default -> 4 / 16.0; + }; + + // For second item + double tx2 = switch (facing) { + case NORTH, WEST -> 12 / 16.0; + default -> 4 / 16.0; + }; + double tz2 = switch (facing) { + case NORTH, EAST -> 12 / 16.0; + default -> 4 / 16.0; + }; + + var itemRenderer = MinecraftClient.getInstance().getItemRenderer(); + + matrices.push(); + matrices.translate(tx1, 9.6 / 16.0, tz1); + matrices.scale(ITEM_SCALE, ITEM_SCALE, ITEM_SCALE); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(ITEM_1_Y_ROT + 180 - facing.asRotation())); + itemRenderer.renderItem( + be.getStack(0), + ModelTransformationMode.FIXED, + light, + overlay, + matrices, + vertexConsumers, + be.getWorld(), + 0 // seed + ); + matrices.pop(); + + matrices.push(); + matrices.translate(tx2, 9.6 / 16.0, tz2); + matrices.scale(ITEM_SCALE, ITEM_SCALE, ITEM_SCALE); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(ITEM_2_Y_ROT + 180 - facing.asRotation())); + itemRenderer.renderItem( + be.getStack(1), + ModelTransformationMode.FIXED, + light, + overlay, + matrices, + vertexConsumers, + be.getWorld(), + 0 // seed + ); + matrices.pop(); + } +} diff --git a/common/src/main/java/juuxel/adorn/client/renderer/TradingStationRenderer.java b/common/src/main/java/juuxel/adorn/client/renderer/TradingStationRenderer.java new file mode 100644 index 000000000..142bcf1d7 --- /dev/null +++ b/common/src/main/java/juuxel/adorn/client/renderer/TradingStationRenderer.java @@ -0,0 +1,91 @@ +package juuxel.adorn.client.renderer; + +import juuxel.adorn.block.entity.TradingStationBlockEntity; +import juuxel.adorn.config.ConfigManager; +import juuxel.adorn.util.Colors; +import juuxel.adorn.util.ColorsKt; +import juuxel.adorn.util.ExtensionsKt; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; +import net.minecraft.client.render.block.entity.BlockEntityRenderer; +import net.minecraft.client.render.block.entity.BlockEntityRendererFactory; +import net.minecraft.client.render.model.json.ModelTransformationMode; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.hit.HitResult; +import net.minecraft.util.math.RotationAxis; + +public final class TradingStationRenderer implements BlockEntityRenderer { + private static final float SELLING_ROTATION_MULTIPLIER = 1.2f; + private static final String OWNER_LABEL = "block.adorn.trading_station.label.owner"; + private static final String SELLING_LABEL = "block.adorn.trading_station.label.selling"; + private static final String PRICE_LABEL = "block.adorn.trading_station.label.price"; + + private final BlockEntityRenderDispatcher dispatcher; + private final TextRenderer textRenderer; + + public TradingStationRenderer(BlockEntityRendererFactory.Context context) { + dispatcher = context.getRenderDispatcher(); + textRenderer = context.getTextRenderer(); + } + + @Override + public void render(TradingStationBlockEntity be, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay) { + var hitResult = dispatcher.crosshairTarget; + var lookingAtBlock = hitResult != null && hitResult.getType() == HitResult.Type.BLOCK && be.getPos().equals(((BlockHitResult) hitResult).getBlockPos()); + var trade = be.getTrade(); + + if (!trade.isEmpty()) { + matrices.push(); + matrices.translate(0.5, 1.2, 0.5); + int playerAge = MinecraftClient.getInstance().player.age; + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees((playerAge + tickDelta) * SELLING_ROTATION_MULTIPLIER)); + matrices.scale(0.6f, 0.6f, 0.6f); + matrices.translate(0.0, 0.3, 0.0); + var itemRenderer = MinecraftClient.getInstance().getItemRenderer(); + itemRenderer.renderItem(trade.getSelling(), ModelTransformationMode.FIXED, light, overlay, matrices, vertexConsumers, be.getWorld(), 0); + matrices.pop(); + } + + if (lookingAtBlock && ConfigManager.config().client.showTradingStationTooltips) { + Text label1 = Text.translatable(OWNER_LABEL, be.getOwnerName().copy().formatted(Formatting.GOLD)); + renderLabel(be, label1, 0.0, 0.9, 0.0, 12, matrices, vertexConsumers, light); + if (!be.getTrade().isEmpty()) { + Text label2 = Text.translatable(SELLING_LABEL, ExtensionsKt.toTextWithCount(be.getTrade().getSelling())); + Text label3 = Text.translatable(PRICE_LABEL, ExtensionsKt.toTextWithCount(be.getTrade().getPrice())); + renderLabel(be, label2, 0.0, 0.9 - 0.25, 0.0, 12, matrices, vertexConsumers, light); + renderLabel(be, label3, 0.0, 0.9 - 0.5, 0.0, 12, matrices, vertexConsumers, light); + } + } + } + + private void renderLabel( + BlockEntity be, Text label, double x, double y, double z, + int maxDistance, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light + ) { + var camera = dispatcher.camera; + + double dist = be.getPos().getSquaredDistanceFromCenter(camera.getPos().x, camera.getPos().y, camera.getPos().z); + if (dist < maxDistance * maxDistance) { + matrices.push(); + matrices.translate(x + 0.5, y + 1.5, z + 0.5); + matrices.multiply(camera.getRotation()); + matrices.scale(-0.025f, -0.025f, +0.025f); + + var positionMatrix = matrices.peek().getPositionMatrix(); + float opacity = MinecraftClient.getInstance().options.getTextBackgroundOpacity(0.25f); + int backgroundColor = ColorsKt.color(0x000000, opacity); + var textX = -textRenderer.getWidth(label) * 0.5f; + textRenderer.draw(label, textX, 0f, Colors.WHITE, false, positionMatrix, vertexConsumers, TextRenderer.TextLayerType.NORMAL, backgroundColor, light); + + matrices.pop(); + } + } + + +} diff --git a/common/src/main/kotlin/juuxel/adorn/client/renderer/InvisibleEntityRenderer.kt b/common/src/main/kotlin/juuxel/adorn/client/renderer/InvisibleEntityRenderer.kt deleted file mode 100644 index a895ee4b3..000000000 --- a/common/src/main/kotlin/juuxel/adorn/client/renderer/InvisibleEntityRenderer.kt +++ /dev/null @@ -1,15 +0,0 @@ -package juuxel.adorn.client.renderer - -import net.minecraft.client.render.entity.EntityRenderer -import net.minecraft.client.render.entity.EntityRendererFactory -import net.minecraft.entity.Entity -import net.minecraft.util.Identifier - -class InvisibleEntityRenderer(context: EntityRendererFactory.Context) : EntityRenderer(context) { - override fun getTexture(entity: Entity) = - TEXTURE - - companion object { - private val TEXTURE = Identifier("missingno") - } -} diff --git a/common/src/main/kotlin/juuxel/adorn/client/renderer/KitchenSinkRenderer.kt b/common/src/main/kotlin/juuxel/adorn/client/renderer/KitchenSinkRenderer.kt deleted file mode 100644 index 221a39961..000000000 --- a/common/src/main/kotlin/juuxel/adorn/client/renderer/KitchenSinkRenderer.kt +++ /dev/null @@ -1,116 +0,0 @@ -package juuxel.adorn.client.renderer - -import juuxel.adorn.block.AbstractKitchenCounterBlock -import juuxel.adorn.block.entity.KitchenSinkBlockEntity -import juuxel.adorn.client.FluidRenderingBridge -import juuxel.adorn.util.logger -import net.fabricmc.api.EnvType -import net.fabricmc.api.Environment -import net.minecraft.client.MinecraftClient -import net.minecraft.client.render.RenderLayer -import net.minecraft.client.render.VertexConsumerProvider -import net.minecraft.client.render.block.entity.BlockEntityRenderer -import net.minecraft.client.render.block.entity.BlockEntityRendererFactory -import net.minecraft.client.texture.MissingSprite -import net.minecraft.client.texture.Sprite -import net.minecraft.client.texture.SpriteAtlasTexture -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.util.math.Direction -import net.minecraft.util.math.MathHelper -import net.minecraft.util.math.RotationAxis - -@Environment(EnvType.CLIENT) -abstract class KitchenSinkRenderer(context: BlockEntityRendererFactory.Context) : BlockEntityRenderer { - override fun render(entity: T, tickDelta: Float, matrices: MatrixStack, vertexConsumers: VertexConsumerProvider, light: Int, overlay: Int) { - // Skip if there's nothing to render - if (isEmpty(entity)) return - - val sprite = getFluidSprite(entity) - val buffer = vertexConsumers.getBuffer(RenderLayer.getEntityTranslucent(sprite.atlasId)) - val u0 = MathHelper.lerp(2 * PX, sprite.minU, sprite.maxU) - val u1 = MathHelper.lerp(14 * PX, sprite.minU, sprite.maxU) - val v0 = MathHelper.lerp(2 * PX, sprite.minV, sprite.maxV) - val v1 = MathHelper.lerp(13 * PX, sprite.minV, sprite.maxV) - - matrices.push() - // Rotate because the model depends on the facing property - matrices.translate(0.5, 0.0, 0.5) - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(getRotation(entity.cachedState[AbstractKitchenCounterBlock.FACING]))) - matrices.translate(-0.5, 0.0, -0.5) - - // Move vertically to correct level - val fluidLevel = getFluidLevel(entity) / LITRES_PER_BLOCK - matrices.translate(0.0, MathHelper.lerp(fluidLevel, Y_START.toDouble(), Y_END.toDouble()), 0.0) - - // Draw the sprite - fun y(x: Float, z: Float): Float { - val time = (MinecraftClient.getInstance().player!!.age * MS_PER_TICK) % WAVE_PERIOD - val t = time * MathHelper.TAU / WAVE_PERIOD - return MathHelper.sin(t + x + z) * WAVE_HEIGHT / 2 - } - - val positionMatrix = matrices.peek().positionMatrix - val normalMatrix = matrices.peek().normalMatrix - val color = getFluidColor(entity) - buffer.vertex(positionMatrix, X_START, y(X_START, Z_END), Z_END) - .color(color).texture(u0, v0).overlay(overlay).light(light).normal(normalMatrix, 0f, 1f, 0f).next() - buffer.vertex(positionMatrix, X_END, y(X_END, Z_END), Z_END) - .color(color).texture(u0, v1).overlay(overlay).light(light).normal(normalMatrix, 0f, 1f, 0f).next() - buffer.vertex(positionMatrix, X_END, y(X_END, Z_START), Z_START) - .color(color).texture(u1, v1).overlay(overlay).light(light).normal(normalMatrix, 0f, 1f, 0f).next() - buffer.vertex(positionMatrix, X_START, y(X_START, Z_START), Z_START) - .color(color).texture(u1, v0).overlay(overlay).light(light).normal(normalMatrix, 0f, 1f, 0f).next() - matrices.pop() - } - - /** Gets the [entity]'s fluid's sprite. */ - private fun getFluidSprite(entity: T): Sprite { - val sprite = FluidRenderingBridge.get().getStillSprite(entity.fluidReference) - - if (sprite == null) { - LOGGER.error("Could not find sprite for fluid reference {} when rendering kitchen sink at {}", entity.fluidReference, entity.pos) - return MinecraftClient.getInstance() - .getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE) - .apply(MissingSprite.getMissingSpriteId()) - } - - return sprite - } - - /** Gets the [entity]'s fluid's color. */ - private fun getFluidColor(entity: T): Int = - FluidRenderingBridge.get().getColor(entity.fluidReference, entity.world, entity.pos) - - /** Gets the fluid level from the [entity] in litres. */ - protected abstract fun getFluidLevel(entity: T): Double - - /** Tests whether the [entity] has no fluid inside. */ - protected abstract fun isEmpty(entity: T): Boolean - - companion object { - private val LOGGER = logger() - private const val PX = 1 / 16f - private const val X_START = 2 * PX - private const val X_END = 13 * PX - private const val Z_START = 2 * PX - private const val Z_END = 14 * PX - private const val Y_START = 7 * PX - private const val Y_END = 15 * PX - private const val LITRES_PER_BLOCK: Double = 1000.0 - - // Wave period in ms - private const val WAVE_PERIOD: Float = 12_000f - private const val WAVE_HEIGHT: Float = PX - private const val MS_PER_TICK: Float = 50f - - private fun getRotation(facing: Direction): Float = - when (facing) { - Direction.EAST -> 0f - Direction.NORTH -> 90f - Direction.WEST -> 180f - Direction.SOUTH -> 270f - // Vertical orientations - else -> 0f - } - } -} diff --git a/common/src/main/kotlin/juuxel/adorn/client/renderer/ShelfRenderer.kt b/common/src/main/kotlin/juuxel/adorn/client/renderer/ShelfRenderer.kt deleted file mode 100644 index f40332af3..000000000 --- a/common/src/main/kotlin/juuxel/adorn/client/renderer/ShelfRenderer.kt +++ /dev/null @@ -1,86 +0,0 @@ -package juuxel.adorn.client.renderer - -import juuxel.adorn.block.ShelfBlock -import juuxel.adorn.block.entity.ShelfBlockEntity -import net.fabricmc.api.EnvType -import net.fabricmc.api.Environment -import net.minecraft.client.MinecraftClient -import net.minecraft.client.render.VertexConsumerProvider -import net.minecraft.client.render.block.entity.BlockEntityRenderer -import net.minecraft.client.render.block.entity.BlockEntityRendererFactory -import net.minecraft.client.render.model.json.ModelTransformationMode -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.util.math.Direction -import net.minecraft.util.math.RotationAxis - -@Environment(EnvType.CLIENT) -class ShelfRenderer(context: BlockEntityRendererFactory.Context) : BlockEntityRenderer { - override fun render( - be: ShelfBlockEntity, tickDelta: Float, - matrices: MatrixStack, vertexConsumers: VertexConsumerProvider, light: Int, overlay: Int - ) { - // TODO: Do the seeds here need extra attention - - val facing = be.cachedState[ShelfBlock.FACING] - - // For first item - val tx1 = when (facing) { - Direction.SOUTH, Direction.WEST -> 12 / 16.0 - else -> 4 / 16.0 - } - val tz1 = when (facing) { - Direction.NORTH, Direction.WEST -> 12 / 16.0 - else -> 4 / 16.0 - } - - // For second item - val tx2 = when (facing) { - Direction.NORTH, Direction.WEST -> 12 / 16.0 - else -> 4 / 16.0 - } - val tz2 = when (facing) { - Direction.NORTH, Direction.EAST -> 12 / 16.0 - else -> 4 / 16.0 - } - - val itemRenderer = MinecraftClient.getInstance().itemRenderer - - matrices.push() - matrices.translate(tx1, 9.6 / 16.0, tz1) - matrices.scale(ITEM_SCALE, ITEM_SCALE, ITEM_SCALE) - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(ITEM_1_Y_ROT + 180 - facing.asRotation())) - itemRenderer.renderItem( - be.getStack(0), - ModelTransformationMode.FIXED, - light, - overlay, - matrices, - vertexConsumers, - be.world, - 0 // seed - ) - matrices.pop() - - matrices.push() - matrices.translate(tx2, 9.6 / 16.0, tz2) - matrices.scale(ITEM_SCALE, ITEM_SCALE, ITEM_SCALE) - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(ITEM_2_Y_ROT + 180 - facing.asRotation())) - itemRenderer.renderItem( - be.getStack(1), - ModelTransformationMode.FIXED, - light, - overlay, - matrices, - vertexConsumers, - be.world, - 0 // seed - ) - matrices.pop() - } - - companion object { - private const val ITEM_SCALE: Float = 0.5f - private const val ITEM_1_Y_ROT: Float = 10f - private const val ITEM_2_Y_ROT: Float = -17f - } -} diff --git a/common/src/main/kotlin/juuxel/adorn/client/renderer/TradingStationRenderer.kt b/common/src/main/kotlin/juuxel/adorn/client/renderer/TradingStationRenderer.kt deleted file mode 100644 index d2fc6ccad..000000000 --- a/common/src/main/kotlin/juuxel/adorn/client/renderer/TradingStationRenderer.kt +++ /dev/null @@ -1,107 +0,0 @@ -package juuxel.adorn.client.renderer - -import juuxel.adorn.block.entity.TradingStationBlockEntity -import juuxel.adorn.config.ConfigManager -import juuxel.adorn.util.Colors -import juuxel.adorn.util.color -import juuxel.adorn.util.getSquaredDistance -import juuxel.adorn.util.toTextWithCount -import net.fabricmc.api.EnvType -import net.fabricmc.api.Environment -import net.minecraft.block.entity.BlockEntity -import net.minecraft.client.MinecraftClient -import net.minecraft.client.font.TextRenderer -import net.minecraft.client.render.VertexConsumerProvider -import net.minecraft.client.render.block.entity.BlockEntityRenderer -import net.minecraft.client.render.block.entity.BlockEntityRendererFactory -import net.minecraft.client.render.model.json.ModelTransformationMode -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.Text -import net.minecraft.util.Formatting -import net.minecraft.util.hit.BlockHitResult -import net.minecraft.util.hit.HitResult -import net.minecraft.util.math.RotationAxis - -@Environment(EnvType.CLIENT) -class TradingStationRenderer(context: BlockEntityRendererFactory.Context) : BlockEntityRenderer { - private val dispatcher = context.renderDispatcher - private val textRenderer = context.textRenderer - - override fun render( - be: TradingStationBlockEntity, tickDelta: Float, - matrices: MatrixStack, vertexConsumers: VertexConsumerProvider, light: Int, overlay: Int - ) { - val hitResult = dispatcher.crosshairTarget - val lookingAtBlock = hitResult != null && - hitResult.type == HitResult.Type.BLOCK && - be.pos == (hitResult as BlockHitResult).blockPos - - val trade = be.trade - if (!trade.isEmpty()) { - matrices.push() - matrices.translate(0.5, 1.2, 0.5) - val playerAge = MinecraftClient.getInstance().player!!.age - - matrices.push() - matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees((playerAge + tickDelta) * SELLING_ROTATION_MULTIPLIER)) - matrices.scale(0.6f, 0.6f, 0.6f) - matrices.translate(0.0, 0.3, 0.0) - val itemRenderer = MinecraftClient.getInstance().itemRenderer - itemRenderer.renderItem(trade.selling, ModelTransformationMode.FIXED, light, overlay, matrices, vertexConsumers, be.world, 0) - matrices.pop() - - /*if (lookingAtBlock) { - GlStateManager.rotatef((playerAge + tickDelta) * PRICE_ROTATION_MULTIPLIER, 0f, 1f, 0f) - GlStateManager.translatef(0.55f, 0f, 0f) - itemRenderer.renderItem(trade.price, ModelTransformation.Type.GROUND) - }*/ - - matrices.pop() - } - - if (lookingAtBlock && ConfigManager.config().client.showTradingStationTooltips) { - val label1 = Text.translatable(OWNER_LABEL, be.ownerName.copy().formatted(Formatting.GOLD)) - renderLabel(be, label1, 0.0, 0.9, 0.0, 12, matrices, vertexConsumers, light) - if (!be.trade.isEmpty()) { - val label2 = Text.translatable(SELLING_LABEL, be.trade.selling.toTextWithCount()) - val label3 = Text.translatable(PRICE_LABEL, be.trade.price.toTextWithCount()) - renderLabel(be, label2, 0.0, 0.9 - 0.25, 0.0, 12, matrices, vertexConsumers, light) - renderLabel(be, label3, 0.0, 0.9 - 0.5, 0.0, 12, matrices, vertexConsumers, light) - } - } - } - - private fun renderLabel( - be: BlockEntity, label: Text, - x: Double, y: Double, z: Double, - maxDistance: Int, - matrices: MatrixStack, vertexConsumers: VertexConsumerProvider, light: Int - ) { - val camera = dispatcher.camera - - val dist = be.getSquaredDistance(camera.pos.x, camera.pos.y, camera.pos.z) - if (dist < maxDistance * maxDistance) { - matrices.push() - matrices.translate(x + 0.5, y + 1.5, z + 0.5) - matrices.multiply(camera.rotation) - matrices.scale(-0.025f, -0.025f, +0.025f) - - val positionMatrix = matrices.peek().positionMatrix - val opacity = MinecraftClient.getInstance().options.getTextBackgroundOpacity(0.25f) - val backgroundColor = color(0x000000, opacity) - val textX = -textRenderer.getWidth(label) * 0.5f - textRenderer.draw(label, textX, 0f, Colors.WHITE, false, positionMatrix, vertexConsumers, TextRenderer.TextLayerType.NORMAL, backgroundColor, light) - - matrices.pop() - } - } - - companion object { - private const val SELLING_ROTATION_MULTIPLIER = 1.2f - // private const val PRICE_ROTATION_MULTIPLIER = -2.5f - - private const val OWNER_LABEL = "block.adorn.trading_station.label.owner" - private const val SELLING_LABEL = "block.adorn.trading_station.label.selling" - private const val PRICE_LABEL = "block.adorn.trading_station.label.price" - } -}