forked from cpw/ironchest
-
Notifications
You must be signed in to change notification settings - Fork 87
/
IronChestRenderer.java
186 lines (149 loc) · 8.52 KB
/
IronChestRenderer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package com.progwml6.ironchest.client.render;
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.regular.AbstractIronChestBlock;
import com.progwml6.ironchest.common.block.IronChestsTypes;
import com.progwml6.ironchest.common.block.regular.entity.AbstractIronChestBlockEntity;
import com.progwml6.ironchest.common.block.entity.ICrystalChest;
import com.progwml6.ironchest.common.block.trapped.entity.AbstractTrappedIronChestBlockEntity;
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.block.model.ItemTransforms;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.client.renderer.texture.OverlayTexture;
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.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.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 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);
boolean trapped = tileEntityIn instanceof AbstractTrappedIronChestBlockEntity;
Material material = new Material(Sheets.CHEST_SHEET, IronChestsModels.chooseChestTexture(chestType, trapped));
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 ICrystalChest crystalChest && Vec3.atCenterOf(tileEntityIn.getBlockPos()).closerThan(this.renderer.camera.getPosition(), 128d)) {
float rotation = (float) (360D * (System.currentTimeMillis() & 0x3FFFL) / 0x3FFFL) - partialTicks;
for (int j = 0; j < MODEL_ITEMS.size() - 1; j++) {
renderItem(poseStack, bufferSource, crystalChest.getTopItems().get(j), MODEL_ITEMS.get(j), rotation, combinedLightIn);
}
}
}
}
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) {
// if no stack, skip
if (item.isEmpty()) return;
// 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
Minecraft.getInstance().getItemRenderer().renderStatic(item, ItemTransforms.TransformType.NONE, light, OverlayTexture.NO_OVERLAY, matrices, buffer, 0);
matrices.popPose();
}
}