superb-warfare/src/main/java/com/atsuishio/superbwarfare/client/renderer/CustomGunRenderer.java
2025-06-06 00:08:49 +08:00

214 lines
11 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.atsuishio.superbwarfare.client.renderer;
import com.atsuishio.superbwarfare.client.model.item.CustomGunModel;
import com.atsuishio.superbwarfare.config.client.DisplayConfig;
import com.atsuishio.superbwarfare.item.gun.GunItem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f;
import software.bernie.geckolib.animatable.GeoAnimatable;
import software.bernie.geckolib.cache.object.BakedGeoModel;
import software.bernie.geckolib.cache.object.GeoBone;
import software.bernie.geckolib.model.GeoModel;
import software.bernie.geckolib.renderer.GeoItemRenderer;
import software.bernie.geckolib.util.Color;
import software.bernie.geckolib.util.RenderUtil;
public class CustomGunRenderer<T extends GunItem & GeoAnimatable> extends GeoItemRenderer<T> {
public static final float SCALE_RECIPROCAL = 1.0f / 16.0f;
public static final int LOD_DISTANCE = 100;
protected T animatable;
protected boolean renderArms = false;
protected MultiBufferSource currentBuffer;
protected RenderType renderType;
public ItemDisplayContext transformType;
public CustomGunRenderer(GeoModel<T> model) {
super(model);
}
@Override
public void actuallyRender(PoseStack matrixStackIn, T animatable, BakedGeoModel model, RenderType type, MultiBufferSource renderTypeBuffer, VertexConsumer vertexBuilder, boolean isRenderer, float partialTicks, int packedLightIn,
int packedOverlayIn, int color) {
this.currentBuffer = renderTypeBuffer;
this.renderType = type;
this.animatable = animatable;
super.actuallyRender(matrixStackIn, animatable, model, type, renderTypeBuffer, vertexBuilder, isRenderer, partialTicks, packedLightIn, packedOverlayIn, color);
if (this.renderArms) {
this.renderArms = false;
}
}
@Override
public RenderType getRenderType(T animatable, ResourceLocation texture, MultiBufferSource bufferSource, float partialTick) {
return RenderType.entityTranslucent(texture);
}
@Override
public ResourceLocation getTextureLocation(T animatable) {
var geoModel = getGeoModel();
if (renderPerspective != ItemDisplayContext.FIRST_PERSON_RIGHT_HAND
&& DisplayConfig.ENABLE_GUN_LOD.get()
&& geoModel instanceof CustomGunModel<T> gunModel
) {
return gunModel.getLODTextureResource(animatable);
}
return geoModel.getTextureResource(animatable, null);
}
public ResourceLocation getTextureLocation(T animatable, PoseStack poseStack) {
var geoModel = getGeoModel();
if (renderPerspective != ItemDisplayContext.FIRST_PERSON_RIGHT_HAND
&& DisplayConfig.ENABLE_GUN_LOD.get()
&& geoModel instanceof CustomGunModel<T> gunModel
) {
var player = Minecraft.getInstance().player;
if (player != null) {
Vec3 pos = new Vec3(poseStack.last().pose().m30(), poseStack.last().pose().m31(), poseStack.last().pose().m32());
if (pos.lengthSqr() >= LOD_DISTANCE) {
return gunModel.getLODTextureResource(animatable);
} else {
return geoModel.getTextureResource(animatable, null);
}
}
return gunModel.getLODTextureResource(animatable);
}
return geoModel.getTextureResource(animatable, null);
}
@Override
public void renderByItem(ItemStack stack, ItemDisplayContext transformType, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
this.animatable = (T) stack.getItem();
this.currentItemStack = stack;
this.renderPerspective = transformType;
if (transformType == ItemDisplayContext.GUI) {
renderInGui(transformType, poseStack, bufferSource, packedLight, packedOverlay, Minecraft.getInstance().getTimer().getRealtimeDeltaTicks());
} else {
RenderType renderType = getRenderType(this.animatable, getTextureLocation(this.animatable, poseStack), bufferSource, Minecraft.getInstance().getTimer().getRealtimeDeltaTicks());
VertexConsumer buffer = ItemRenderer.getFoilBufferDirect(bufferSource, renderType, false, this.currentItemStack != null && this.currentItemStack.hasFoil());
defaultRender(poseStack, this.animatable, bufferSource, renderType, buffer,
0, Minecraft.getInstance().getTimer().getRealtimeDeltaTicks(), packedLight);
}
}
@Override
public void defaultRender(PoseStack poseStack, T animatable, MultiBufferSource bufferSource, @Nullable RenderType renderType, @Nullable VertexConsumer buffer, float yaw, float partialTick, int packedLight) {
poseStack.pushPose();
Color renderColor = getRenderColor(animatable, partialTick, packedLight);
int packedOverlay = getPackedOverlay(animatable, 0, partialTick);
var player = Minecraft.getInstance().player;
ResourceLocation modelLocation;
var geoModel = getGeoModel();
if (renderPerspective != ItemDisplayContext.FIRST_PERSON_RIGHT_HAND
&& DisplayConfig.ENABLE_GUN_LOD.get()
&& geoModel instanceof CustomGunModel<T> gunModel
) {
if (player != null) {
Vec3 pos = new Vec3(poseStack.last().pose().m30(), poseStack.last().pose().m31(), poseStack.last().pose().m32());
if (pos.lengthSqr() >= LOD_DISTANCE) {
modelLocation = gunModel.getLODModelResource(animatable);
} else {
// TODO 这个地方有问题如果是在这里使用了高模会导致custom animation无法分离
modelLocation = geoModel.getModelResource(animatable, null);
}
} else {
modelLocation = gunModel.getLODModelResource(animatable);
}
} else {
modelLocation = geoModel.getModelResource(animatable, null);
}
BakedGeoModel model = geoModel.getBakedModel(modelLocation);
if (renderType == null)
renderType = getRenderType(animatable, getTextureLocation(animatable, poseStack), bufferSource, partialTick);
if (buffer == null)
buffer = bufferSource.getBuffer(renderType);
preRender(poseStack, animatable, model, bufferSource, buffer, false, partialTick, packedLight, packedOverlay, renderColor.argbInt());
if (firePreRenderEvent(poseStack, model, bufferSource, partialTick, packedLight)) {
preApplyRenderLayers(poseStack, animatable, model, renderType, bufferSource, buffer, packedLight, packedLight, packedOverlay);
actuallyRender(poseStack, animatable, model, renderType,
bufferSource, buffer, false, partialTick, packedLight, packedOverlay, renderColor.argbInt());
this.renderIlluminatedBones(model, poseStack, bufferSource, animatable, renderType, buffer, partialTick, packedLight, packedOverlay, renderColor.argbInt());
postRender(poseStack, animatable, model, bufferSource, buffer, false, partialTick, packedLight, packedOverlay, renderColor.argbInt());
firePostRenderEvent(poseStack, model, bufferSource, partialTick, packedLight);
}
poseStack.popPose();
renderFinal(poseStack, animatable, model, bufferSource, buffer, partialTick, packedLight, packedOverlay, renderColor.argbInt());
}
public void renderIlluminatedBones(BakedGeoModel model, PoseStack poseStack, MultiBufferSource bufferSource, T animatable,
RenderType renderType, VertexConsumer buffer, float partialTick,
int packedLight, int packedOverlay, int color) {
poseStack.pushPose();
preRender(poseStack, animatable, model, bufferSource, buffer, true, partialTick, packedLight, packedOverlay, color);
this.modelRenderTranslations = new Matrix4f(poseStack.last().pose());
updateAnimatedTextureFrame(animatable);
for (GeoBone bone : model.topLevelBones()) {
this.illuminatedRender(poseStack, animatable, bone, renderType, bufferSource, buffer,
partialTick, packedLight, packedOverlay, color);
}
postRender(poseStack, animatable, model, bufferSource, buffer, true, partialTick, packedLight, packedOverlay, color);
poseStack.popPose();
}
public void illuminatedRender(PoseStack poseStack, T animatable, GeoBone bone, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer, float partialTick, int packedLight,
int packedOverlay, int color) {
if (bone.isTrackingMatrices()) {
Matrix4f poseState = new Matrix4f(poseStack.last().pose());
bone.setModelSpaceMatrix(RenderUtil.invertAndMultiplyMatrices(poseState, this.modelRenderTranslations));
bone.setLocalSpaceMatrix(RenderUtil.invertAndMultiplyMatrices(poseState, this.itemRenderTranslations));
}
poseStack.pushPose();
RenderUtil.prepMatrixForBone(poseStack, bone);
if (bone.getName().endsWith("_illuminated")) {
renderCubesOfBone(poseStack, bone, bufferSource.getBuffer(ModRenderTypes.ILLUMINATED.apply(this.getTextureLocation(animatable, poseStack))),
packedLight, OverlayTexture.NO_OVERLAY, color);
}
this.illuminatedRenderChildBones(poseStack, animatable, bone, renderType, bufferSource, buffer, partialTick, packedLight, packedOverlay, color);
poseStack.popPose();
}
public void illuminatedRenderChildBones(PoseStack poseStack, T animatable, GeoBone bone, RenderType renderType, MultiBufferSource bufferSource, VertexConsumer buffer,
float partialTick, int packedLight, int packedOverlay, int color) {
if (bone.isHidingChildren())
return;
for (GeoBone childBone : bone.getChildBones()) {
illuminatedRender(poseStack, animatable, childBone, renderType, bufferSource, buffer, partialTick, packedLight, packedOverlay, color);
}
}
}