214 lines
9.4 KiB
Java
214 lines
9.4 KiB
Java
|
package com.progwml6.ironchest.client.render;
|
||
|
|
||
|
import com.google.common.primitives.SignedBytes;
|
||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||
|
import com.progwml6.ironchest.IronChestsClientEvents;
|
||
|
import com.progwml6.ironchest.client.model.IronChestsModels;
|
||
|
import com.progwml6.ironchest.client.model.inventory.ModelItem;
|
||
|
import com.progwml6.ironchest.common.block.AbstractIronChestBlock;
|
||
|
import com.progwml6.ironchest.common.block.entity.CrystalChestBlockEntity;
|
||
|
import com.progwml6.ironchest.common.block.IronChestsTypes;
|
||
|
import com.progwml6.ironchest.common.block.entity.AbstractIronChestBlockEntity;
|
||
|
import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
|
||
|
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||
|
import net.minecraft.client.model.geom.PartPose;
|
||
|
import net.minecraft.client.model.geom.builders.CubeListBuilder;
|
||
|
import net.minecraft.client.model.geom.builders.LayerDefinition;
|
||
|
import net.minecraft.client.model.geom.builders.MeshDefinition;
|
||
|
import net.minecraft.client.model.geom.builders.PartDefinition;
|
||
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
|
||
|
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
|
||
|
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||
|
import net.minecraft.world.level.block.Block;
|
||
|
import net.minecraft.world.level.block.state.BlockState;
|
||
|
import net.minecraft.client.Minecraft;
|
||
|
import net.minecraft.client.renderer.Sheets;
|
||
|
import net.minecraft.client.renderer.MultiBufferSource;
|
||
|
import net.minecraft.client.renderer.RenderType;
|
||
|
import net.minecraft.client.renderer.entity.ItemEntityRenderer;
|
||
|
import net.minecraft.client.model.geom.ModelPart;
|
||
|
import net.minecraft.client.resources.model.Material;
|
||
|
import net.minecraft.client.renderer.blockentity.BrightnessCombiner;
|
||
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
|
||
|
import net.minecraft.world.entity.EntityType;
|
||
|
import net.minecraft.world.entity.item.ItemEntity;
|
||
|
import net.minecraft.world.item.ItemStack;
|
||
|
import net.minecraft.world.level.block.entity.LidBlockEntity;
|
||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||
|
import net.minecraft.world.level.block.DoubleBlockCombiner;
|
||
|
import net.minecraft.core.Direction;
|
||
|
import net.minecraft.world.phys.Vec3;
|
||
|
import com.mojang.math.Vector3f;
|
||
|
import net.minecraft.world.level.Level;
|
||
|
import net.minecraftforge.api.distmarker.Dist;
|
||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||
|
|
||
|
import java.util.Arrays;
|
||
|
import java.util.List;
|
||
|
|
||
|
@OnlyIn(Dist.CLIENT)
|
||
|
public class IronChestRenderer<T extends BlockEntity & LidBlockEntity> implements BlockEntityRenderer<T> {
|
||
|
|
||
|
private final ModelPart lid;
|
||
|
private final ModelPart bottom;
|
||
|
private final ModelPart lock;
|
||
|
|
||
|
private static ItemEntity customItem;
|
||
|
private static ItemEntityRenderer itemRenderer;
|
||
|
private final BlockEntityRenderDispatcher renderer;
|
||
|
|
||
|
private static final List<ModelItem> MODEL_ITEMS = Arrays.asList(
|
||
|
new ModelItem(new Vector3f(0.3F, 0.45F, 0.3F), 3.0F),
|
||
|
new ModelItem(new Vector3f(0.7F, 0.45F, 0.3F), 3.0F),
|
||
|
new ModelItem(new Vector3f(0.3F, 0.45F, 0.7F), 3.0F),
|
||
|
new ModelItem(new Vector3f(0.7F, 0.45F, 0.7F), 3.0F),
|
||
|
new ModelItem(new Vector3f(0.3F, 0.1F, 0.3F), 3.0F),
|
||
|
new ModelItem(new Vector3f(0.7F, 0.1F, 0.3F), 3.0F),
|
||
|
new ModelItem(new Vector3f(0.3F, 0.1F, 0.7F), 3.0F),
|
||
|
new ModelItem(new Vector3f(0.7F, 0.1F, 0.7F), 3.0F),
|
||
|
new ModelItem(new Vector3f(0.5F, 0.32F, 0.5F), 3.0F)
|
||
|
);
|
||
|
|
||
|
public IronChestRenderer(BlockEntityRendererProvider.Context context) {
|
||
|
ModelPart modelPart = context.bakeLayer(IronChestsClientEvents.IRON_CHEST);
|
||
|
|
||
|
this.renderer = context.getBlockEntityRenderDispatcher();
|
||
|
this.bottom = modelPart.getChild("iron_bottom");
|
||
|
this.lid = modelPart.getChild("iron_lid");
|
||
|
this.lock = modelPart.getChild("iron_lock");
|
||
|
}
|
||
|
|
||
|
public static LayerDefinition createBodyLayer() {
|
||
|
MeshDefinition meshDefinition = new MeshDefinition();
|
||
|
PartDefinition partDefinition = meshDefinition.getRoot();
|
||
|
|
||
|
partDefinition.addOrReplaceChild("iron_bottom", CubeListBuilder.create().texOffs(0, 19).addBox(1.0F, 0.0F, 1.0F, 14.0F, 10.0F, 14.0F), PartPose.ZERO);
|
||
|
partDefinition.addOrReplaceChild("iron_lid", CubeListBuilder.create().texOffs(0, 0).addBox(1.0F, 0.0F, 0.0F, 14.0F, 5.0F, 14.0F), PartPose.offset(0.0F, 9.0F, 1.0F));
|
||
|
partDefinition.addOrReplaceChild("iron_lock", CubeListBuilder.create().texOffs(0, 0).addBox(7.0F, -1.0F, 15.0F, 2.0F, 4.0F, 1.0F), PartPose.offset(0.0F, 8.0F, 0.0F));
|
||
|
|
||
|
return LayerDefinition.create(meshDefinition, 64, 64);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void render(T tileEntityIn, float partialTicks, PoseStack poseStack, MultiBufferSource bufferSource, int combinedLightIn, int combinedOverlayIn) {
|
||
|
AbstractIronChestBlockEntity tileEntity = (AbstractIronChestBlockEntity) tileEntityIn;
|
||
|
|
||
|
Level level = tileEntity.getLevel();
|
||
|
boolean useTileEntityBlockState = level != null;
|
||
|
|
||
|
BlockState blockState = useTileEntityBlockState ? tileEntity.getBlockState() : (BlockState) tileEntity.getBlockToUse().defaultBlockState().setValue(AbstractIronChestBlock.FACING, Direction.SOUTH);
|
||
|
Block block = blockState.getBlock();
|
||
|
IronChestsTypes chestType = IronChestsTypes.IRON;
|
||
|
IronChestsTypes actualType = AbstractIronChestBlock.getTypeFromBlock(block);
|
||
|
|
||
|
if (actualType != null) {
|
||
|
chestType = actualType;
|
||
|
}
|
||
|
|
||
|
if (block instanceof AbstractIronChestBlock abstractChestBlock) {
|
||
|
poseStack.pushPose();
|
||
|
|
||
|
float f = blockState.getValue(AbstractIronChestBlock.FACING).toYRot();
|
||
|
|
||
|
poseStack.translate(0.5D, 0.5D, 0.5D);
|
||
|
poseStack.mulPose(Vector3f.YP.rotationDegrees(-f));
|
||
|
poseStack.translate(-0.5D, -0.5D, -0.5D);
|
||
|
|
||
|
DoubleBlockCombiner.NeighborCombineResult<? extends AbstractIronChestBlockEntity> neighborCombineResult;
|
||
|
|
||
|
if (useTileEntityBlockState) {
|
||
|
neighborCombineResult = abstractChestBlock.combine(blockState, level, tileEntityIn.getBlockPos(), true);
|
||
|
} else {
|
||
|
neighborCombineResult = DoubleBlockCombiner.Combiner::acceptNone;
|
||
|
}
|
||
|
|
||
|
float openness = neighborCombineResult.<Float2FloatFunction>apply(AbstractIronChestBlock.opennessCombiner(tileEntity)).get(partialTicks);
|
||
|
openness = 1.0F - openness;
|
||
|
openness = 1.0F - openness * openness * openness;
|
||
|
|
||
|
int brightness = neighborCombineResult.<Int2IntFunction>apply(new BrightnessCombiner<>()).applyAsInt(combinedLightIn);
|
||
|
|
||
|
Material material = new Material(Sheets.CHEST_SHEET, IronChestsModels.chooseChestTexture(chestType));
|
||
|
|
||
|
VertexConsumer vertexConsumer = material.buffer(bufferSource, RenderType::entityCutout);
|
||
|
|
||
|
this.render(poseStack, vertexConsumer, this.lid, this.lock, this.bottom, openness, brightness, combinedOverlayIn);
|
||
|
|
||
|
poseStack.popPose();
|
||
|
|
||
|
if (chestType.isTransparent() && tileEntity instanceof CrystalChestBlockEntity crystalChestTileEntity && Vec3.atCenterOf(tileEntityIn.getBlockPos()).closerThan(this.renderer.camera.getPosition(), 128d)) {
|
||
|
float rotation = (float) (360D * (System.currentTimeMillis() & 0x3FFFL) / 0x3FFFL) - partialTicks;
|
||
|
|
||
|
if (customItem == null) {
|
||
|
assert level != null;
|
||
|
customItem = new ItemEntity(EntityType.ITEM, level);
|
||
|
}
|
||
|
|
||
|
for (int j = 0; j < MODEL_ITEMS.size() - 1; j++) {
|
||
|
renderItem(poseStack, bufferSource, crystalChestTileEntity.getTopItems().get(j), MODEL_ITEMS.get(j), rotation, combinedLightIn, partialTicks);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void render(PoseStack poseStack, VertexConsumer vertexConsumer, ModelPart lid, ModelPart lock, ModelPart bottom, float openness, int brightness, int combinedOverlayIn) {
|
||
|
lid.xRot = -(openness * ((float) Math.PI / 2F));
|
||
|
lock.xRot = lid.xRot;
|
||
|
|
||
|
lid.render(poseStack, vertexConsumer, brightness, combinedOverlayIn);
|
||
|
lock.render(poseStack, vertexConsumer, brightness, combinedOverlayIn);
|
||
|
bottom.render(poseStack, vertexConsumer, brightness, combinedOverlayIn);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Renders a single item in a TESR
|
||
|
*
|
||
|
* @param matrices Matrix stack instance
|
||
|
* @param buffer Buffer instance
|
||
|
* @param item Item to render
|
||
|
* @param modelItem Model items for render information
|
||
|
* @param light Model light
|
||
|
*/
|
||
|
public static void renderItem(PoseStack matrices, MultiBufferSource buffer, ItemStack item, ModelItem modelItem, float rotation, int light, float partialTicks) {
|
||
|
// if no stack, skip
|
||
|
if (item.isEmpty()) return;
|
||
|
|
||
|
customItem.setItem(item);
|
||
|
|
||
|
// start rendering
|
||
|
matrices.pushPose();
|
||
|
Vector3f center = modelItem.getCenter();
|
||
|
matrices.translate(center.x(), center.y(), center.z());
|
||
|
|
||
|
matrices.mulPose(Vector3f.YP.rotation(rotation));
|
||
|
|
||
|
// scale
|
||
|
float scale = modelItem.getSizeScaled();
|
||
|
matrices.scale(scale, scale, scale);
|
||
|
|
||
|
// render the actual item
|
||
|
if (itemRenderer == null) {
|
||
|
itemRenderer = new ItemEntityRenderer(new EntityRendererProvider.Context(Minecraft.getInstance().getEntityRenderDispatcher(), Minecraft.getInstance().getItemRenderer(), Minecraft.getInstance().getResourceManager(), Minecraft.getInstance().getEntityModels(), Minecraft.getInstance().font)) {
|
||
|
@Override
|
||
|
public int getRenderAmount(ItemStack stack) {
|
||
|
return SignedBytes.saturatedCast(Math.min(stack.getCount() / 32, 15) + 1);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean shouldBob() {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean shouldSpreadItems() {
|
||
|
return true;
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
itemRenderer.render(customItem, 0F, partialTicks, matrices, buffer, light);
|
||
|
matrices.popPose();
|
||
|
}
|
||
|
}
|