ironbarrels/src/main/java/com/progwml6/ironchest/client/render/IronChestRenderer.java

214 lines
9.4 KiB
Java
Raw Normal View History

2021-07-28 19:38:12 +02:00
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();
}
}