feat: render GeckoLib cosmetics on player bodies
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package de.fullrisk.citrusDev.client.cosmetic;
|
||||
|
||||
import com.geckolib.model.GeoModel;
|
||||
import com.geckolib.renderer.base.GeoRenderState;
|
||||
import net.minecraft.resources.Identifier;
|
||||
|
||||
public final class PlayerCosmeticModel extends GeoModel<PlayerCosmetic> {
|
||||
private static final Identifier MODEL = Identifier.fromNamespaceAndPath(
|
||||
"citrus-dev", "geckolib/models/player/backpack.geo.json");
|
||||
private static final Identifier TEXTURE = Identifier.fromNamespaceAndPath(
|
||||
"citrus-dev", "textures/cosmetic/backpack.png");
|
||||
private static final Identifier ANIMATION = Identifier.fromNamespaceAndPath(
|
||||
"citrus-dev", "geckolib/animations/backpack.animation.json");
|
||||
|
||||
@Override
|
||||
public Identifier getModelResource(GeoRenderState renderState) {
|
||||
return MODEL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getTextureResource(GeoRenderState renderState) {
|
||||
return TEXTURE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getAnimationResource(PlayerCosmetic animatable) {
|
||||
return ANIMATION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package de.fullrisk.citrusDev.client.cosmetic;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.model.player.PlayerModel;
|
||||
import net.minecraft.client.renderer.SubmitNodeCollector;
|
||||
import net.minecraft.client.renderer.entity.RenderLayerParent;
|
||||
import net.minecraft.client.renderer.entity.layers.RenderLayer;
|
||||
import net.minecraft.client.renderer.entity.state.AvatarRenderState;
|
||||
import net.minecraft.client.renderer.state.level.CameraRenderState;
|
||||
|
||||
public final class PlayerCosmeticRenderLayer extends RenderLayer<AvatarRenderState, PlayerModel> {
|
||||
// Blockbench uses Minecraft model units around the vanilla body origin; no corrective transform is needed.
|
||||
private static final float MODEL_SCALE = 1.0F;
|
||||
|
||||
private final PlayerCosmeticRenderer renderer = new PlayerCosmeticRenderer();
|
||||
|
||||
public PlayerCosmeticRenderLayer(RenderLayerParent<AvatarRenderState, PlayerModel> parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void submit(
|
||||
PoseStack poseStack,
|
||||
SubmitNodeCollector nodeCollector,
|
||||
int packedLight,
|
||||
AvatarRenderState state,
|
||||
float limbAngle,
|
||||
float limbDistance
|
||||
) {
|
||||
CosmeticRenderData renderData = state.getData(CosmeticRenderStateKeys.COSMETIC);
|
||||
CameraRenderState cameraRenderState = state.getData(CosmeticRenderStateKeys.CAMERA);
|
||||
|
||||
if (renderData == null || cameraRenderState == null || state.isInvisible || state.isSpectator
|
||||
|| !renderData.cosmetic().visible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerCosmetic animatable = PlayerCosmeticManager.getOrCreateAnimatable(renderData.playerId());
|
||||
poseStack.pushPose();
|
||||
|
||||
try {
|
||||
getParentModel().body.translateAndRotate(poseStack);
|
||||
poseStack.scale(MODEL_SCALE, MODEL_SCALE, MODEL_SCALE);
|
||||
renderer.performRenderPass(
|
||||
animatable,
|
||||
renderData,
|
||||
poseStack,
|
||||
nodeCollector,
|
||||
cameraRenderState,
|
||||
packedLight,
|
||||
renderData.partialTick()
|
||||
);
|
||||
} finally {
|
||||
poseStack.popPose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package de.fullrisk.citrusDev.client.cosmetic;
|
||||
|
||||
import com.geckolib.renderer.GeoObjectRenderer;
|
||||
import com.geckolib.renderer.base.GeoRenderState;
|
||||
import com.geckolib.renderer.base.RenderPassInfo;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class PlayerCosmeticRenderer extends GeoObjectRenderer<
|
||||
PlayerCosmetic, CosmeticRenderData, GeoRenderState> {
|
||||
|
||||
public PlayerCosmeticRenderer() {
|
||||
super(new PlayerCosmeticModel());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getInstanceId(PlayerCosmetic animatable, CosmeticRenderData data) {
|
||||
UUID uuid = data.playerId();
|
||||
return uuid.getMostSignificantBits() ^ uuid.getLeastSignificantBits();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustRenderPose(RenderPassInfo<GeoRenderState> renderPassInfo) {
|
||||
// The layer already supplies a body-local pose; omit GeoObjectRenderer's block-centering offset.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user