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