-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
308 additions
and
324 deletions.
There are no files selected for viewing
19 changes: 19 additions & 0 deletions
19
common/src/main/java/juuxel/adorn/client/renderer/InvisibleEntityRenderer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Entity> { | ||
private static final Identifier TEXTURE = new Identifier("missingno"); | ||
|
||
public InvisibleEntityRenderer(EntityRendererFactory.Context ctx) { | ||
super(ctx); | ||
} | ||
|
||
@Override | ||
public Identifier getTexture(Entity entity) { | ||
return TEXTURE; | ||
} | ||
} |
118 changes: 118 additions & 0 deletions
118
common/src/main/java/juuxel/adorn/client/renderer/KitchenSinkRenderer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<T extends KitchenSinkBlockEntity> implements BlockEntityRenderer<T> { | ||
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); | ||
} |
80 changes: 80 additions & 0 deletions
80
common/src/main/java/juuxel/adorn/client/renderer/ShelfRenderer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<ShelfBlockEntity> { | ||
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(); | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
common/src/main/java/juuxel/adorn/client/renderer/TradingStationRenderer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<TradingStationBlockEntity> { | ||
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(); | ||
} | ||
} | ||
|
||
|
||
} |
15 changes: 0 additions & 15 deletions
15
common/src/main/kotlin/juuxel/adorn/client/renderer/InvisibleEntityRenderer.kt
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.