Move head information to the render state

This commit is contained in:
Sollace 2024-12-17 12:24:06 +01:00
parent 808797689e
commit 50b0522a08
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
11 changed files with 100 additions and 67 deletions

View file

@ -12,6 +12,7 @@ import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.component.type.DyedColorComponent;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import net.minecraft.item.*;
import net.minecraft.item.equipment.EquipmentAsset;
import net.minecraft.item.equipment.trim.ArmorTrim;
@ -42,6 +43,12 @@ public interface ArmourRendererPlugin {
}
default ItemStack[] getArmorStacks(LivingEntity entity, EquipmentSlot armorSlot, EquipmentModel.LayerType layerType, ArmourType type) {
return new ItemStack[] {
entity.getEquippedStack(armorSlot)
};
}
default ItemStack[] getArmorStacks(BipedEntityRenderState state, EquipmentSlot armorSlot, EquipmentModel.LayerType layerType, ArmourType type) {
return new ItemStack[] { switch (armorSlot) {
case HEAD -> state.equippedHeadStack;

View file

@ -90,16 +90,16 @@ public class EquineRenderManager<
return DebugBoundingBoxRenderer.applyScale(scale, box);
}
public void updateState(T entity, S state, ModelAttributes.Mode mode, ItemModelManager modelManager) {
public void updateState(T entity, S state, ModelAttributes.Mode mode, ItemModelManager resolver) {
Pony pony = context.getEntityPony(entity);
models = modelsLookup.apply(pony.race());
context.setModel(models.body());
state.updateState(entity, models.body(), pony, mode);
state.updateState(resolver, entity, models.body(), pony, mode);
if (PonyConfig.getInstance().tpsmagic.get() && state.hasMagicGlow()) {
modelManager.updateForLivingEntity(
resolver.updateForLivingEntity(
state.glintlessRightHandItemState, getWithoutGlint(entity.getStackInArm(Arm.RIGHT)), ModelTransformationMode.THIRD_PERSON_RIGHT_HAND, false, entity
);
modelManager.updateForLivingEntity(
resolver.updateForLivingEntity(
state.glintlessLeftHandItemState, getWithoutGlint(entity.getStackInArm(Arm.LEFT)), ModelTransformationMode.THIRD_PERSON_LEFT_HAND, true, entity
);
} else {

View file

@ -7,10 +7,9 @@ import com.minelittlepony.client.model.armour.ArmourRendererPlugin;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.client.render.entity.*;
import com.minelittlepony.client.render.entity.state.PonyRenderState;
import com.minelittlepony.client.render.entity.state.PonyRenderState.EquippedHeadRenderState;
import net.minecraft.block.AbstractSkullBlock;
import net.minecraft.block.SkullBlock;
import net.minecraft.block.SkullBlock.SkullType;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.RenderLayer;
@ -21,11 +20,8 @@ import net.minecraft.client.render.block.entity.SkullBlockEntityRenderer;
import net.minecraft.client.render.entity.equipment.EquipmentModel;
import net.minecraft.client.render.entity.state.LivingEntityRenderState;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.ProfileComponent;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.ColorHelper;
@ -47,9 +43,6 @@ public class PonySkullRenderer {
private ISkull selectedSkull;
private Identifier selectedSkin;
boolean isBeingWorn;
boolean isPony;
public void reload() {
cache = new Cache();
}
@ -70,15 +63,11 @@ public class PonySkullRenderer {
}
}
public void renderSkull(MatrixStack matrices, VertexConsumerProvider provider, ItemStack stack, LivingEntityRenderState entity, float tickDelta, int light, boolean isPony) {
isBeingWorn = true;
this.isPony = isPony;
SkullType type = ((AbstractSkullBlock) ((BlockItem) stack.getItem()).getBlock()).getSkullType();
SkullBlockEntityModel skullBlockEntityModel = cache.headModels().apply(type);
RenderLayer renderLayer = SkullBlockEntityRenderer.getRenderLayer(type, stack.get(DataComponentTypes.PROFILE));
SkullBlockEntityRenderer.renderSkull(null, 180, entity.headItemAnimationProgress, matrices, provider, light, skullBlockEntityModel, renderLayer);
isBeingWorn = false;
this.isPony = false;
public void renderSkull(MatrixStack matrices, VertexConsumerProvider provider, EquippedHeadRenderState headState, LivingEntityRenderState entity, float tickDelta, int light, boolean isPony) {
SkullBlockEntityRenderer.renderSkull(null, 180, entity.headItemAnimationProgress, matrices, provider, light,
cache.headModels().apply(headState.skullType()),
SkullBlockEntityRenderer.getRenderLayer(headState.skullType(), headState.wearingSkullProfile())
);
}
public RenderLayer getSkullRenderLayer(SkullBlock.SkullType skullType, @Nullable ProfileComponent profile) {

View file

@ -7,6 +7,7 @@ import com.minelittlepony.util.MathUtil;
import java.util.function.Predicate;
import net.minecraft.client.item.ItemModelManager;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
@ -28,8 +29,8 @@ public class AquaticPlayerPonyRenderer extends FormChangingPlayerPonyRenderer {
class State extends PlayerPonyRenderState {
@Override
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(entity, model, pony, mode);
public void updateState(ItemModelManager resolver, LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(resolver, entity, model, pony, mode);
Identifier skinOverride = getSkinOverride((AbstractClientPlayerEntity)entity);
yOffset += skinOverride != null ? (0.6 + (isInSneakingPose ? 0.125 : 0)) : 0;
pose = EntityPose.STANDING;

View file

@ -16,7 +16,6 @@ import net.minecraft.util.math.*;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.model.ModelAttributes.Mode;
import com.minelittlepony.api.model.Models;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.SizePreset;

View file

@ -10,6 +10,7 @@ import com.minelittlepony.client.render.entity.feature.ClothingFeature;
import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier;
import com.minelittlepony.client.render.entity.state.PonyRenderState;
import net.minecraft.client.item.ItemModelManager;
import net.minecraft.client.model.Model.SinglePartModel;
import net.minecraft.client.render.*;
import net.minecraft.client.render.entity.EntityRendererFactory;
@ -109,8 +110,8 @@ public class SkeleponyRenderer<T extends AbstractSkeletonEntity, S extends Skele
public boolean sheared;
@Override
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(entity, model, pony, mode);
public void updateState(ItemModelManager resolver, LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(resolver, entity, model, pony, mode);
sheared = entity instanceof BoggedEntity bogged && bogged.isSheared();
}
}
@ -118,8 +119,8 @@ public class SkeleponyRenderer<T extends AbstractSkeletonEntity, S extends Skele
public static class State extends PonyRenderState {
public boolean isAttacking;
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(entity, model, pony, mode);
public void updateState(ItemModelManager resolver, LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(resolver, entity, model, pony, mode);
isAttacking = entity instanceof HostileEntity h && h.isAttacking();
race = entity.getUuid().getLeastSignificantBits() % 3 == 0 ? Race.EARTH : Race.UNICORN;
}

View file

@ -6,16 +6,14 @@ import com.minelittlepony.client.model.armour.ArmourRendererPlugin;
import com.minelittlepony.client.render.PonyRenderContext;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer;
import com.minelittlepony.client.render.entity.state.PonyRenderState;
import com.minelittlepony.client.render.entity.state.PonyRenderState.EquippedHeadRenderState;
import net.minecraft.block.AbstractSkullBlock;
import net.minecraft.client.item.ItemModelManager;
import net.minecraft.client.render.*;
import net.minecraft.client.render.entity.equipment.EquipmentModel;
import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer;
import net.minecraft.client.render.entity.feature.HeadFeatureRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.*;
public class SkullFeature<
S extends PonyRenderState,
@ -32,29 +30,8 @@ public class SkullFeature<
}
@Override
public void render(MatrixStack matrices, VertexConsumerProvider provider, int light, S state, float limbAngle, float limbDistance) {
ArmourRendererPlugin plugin = ArmourRendererPlugin.INSTANCE.get();
for (ItemStack stack : plugin.getArmorStacks(state, EquipmentSlot.HEAD, EquipmentModel.LayerType.HUMANOID, ArmourRendererPlugin.ArmourType.SKULL)) {
if (stack.isEmpty()) {
continue;
}
boolean isSkull = stack.getItem() instanceof BlockItem b && b.getBlock() instanceof AbstractSkullBlock;
if (!isSkull) {
if (!ArmorFeatureRenderer.hasModel(stack, EquipmentSlot.HEAD)) {
itemModelResolver.update(state.headItemRenderState, stack, ModelTransformationMode.HEAD, false, null, null, 0);
} else {
state.headItemRenderState.clear();
}
if (state.headItemRenderState.isEmpty()) {
continue;
}
}
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, S state, float limbAngle, float limbDistance) {
for (EquippedHeadRenderState headState : state.equippedHeads) {
matrices.push();
M model = getModelWrapper().body();
@ -65,21 +42,21 @@ public class SkullFeature<
float f = 1.1F;
matrices.scale(f, f, f);
if (isSkull) {
if (headState.skullType() != null) {
float n = 1.1875F;
matrices.scale(n, -n, -n);
matrices.translate(0, -0.1F, 0.1F);
matrices.translate(-0.5, 0, -0.5);
PonySkullRenderer.INSTANCE.renderSkull(matrices, provider, stack, state, state.age, light, true);
} else if (!ArmorFeatureRenderer.hasModel(stack, EquipmentSlot.HEAD)) {
PonySkullRenderer.INSTANCE.renderSkull(matrices, vertices, headState, state, state.age, light, true);
} else {
matrices.translate(0, 0.1F, -0.1F);
HeadFeatureRenderer.translate(matrices, headTransformation);
state.headItemRenderState.render(matrices, provider, light, OverlayTexture.DEFAULT_UV);
headState.item().render(matrices, vertices, light, OverlayTexture.DEFAULT_UV);
}
matrices.pop();
}
plugin.onArmourRendered(state, matrices, provider, EquipmentSlot.BODY, EquipmentModel.LayerType.HUMANOID, ArmourRendererPlugin.ArmourType.SKULL);
ArmourRendererPlugin.INSTANCE.get().onArmourRendered(state, matrices, vertices, EquipmentSlot.BODY, EquipmentModel.LayerType.HUMANOID, ArmourRendererPlugin.ArmourType.SKULL);
}
}

View file

@ -15,6 +15,7 @@ import com.minelittlepony.client.render.PonyRenderContext;
import com.minelittlepony.client.render.entity.PonyRenderer;
import com.minelittlepony.client.render.entity.feature.HeldItemFeature;
import net.minecraft.client.item.ItemModelManager;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.model.BipedEntityModel.ArmPose;
@ -86,8 +87,8 @@ public class IllagerPonyRenderer<
public static class State extends PonyRenderState {
public IllagerEntity.State state;
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(entity, model, pony, mode);
public void updateState(ItemModelManager resolver, LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(resolver, entity, model, pony, mode);
state = ((IllagerEntity)entity).getState();
}
}

View file

@ -1,5 +1,6 @@
package com.minelittlepony.client.render.entity.npc.textures;
import net.minecraft.client.item.ItemModelManager;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier;
import net.minecraft.village.*;
@ -40,8 +41,8 @@ public class SillyPonyTextureSupplier {
public boolean hasMuffinHat;
public boolean hasSaddlebags;
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(entity, model, pony, mode);
public void updateState(ItemModelManager resolver, LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(resolver, entity, model, pony, mode);
attributes.visualHeight += hasMuffinHat ? 0.3F : -0.1F;
isDerpy = SillyPonyTextureSupplier.isBestPony(entity);
isDinky = isDerpy && customName != null && "Dinky".equals(customName.getString());

View file

@ -1,5 +1,6 @@
package com.minelittlepony.client.render.entity.state;
import net.minecraft.client.item.ItemModelManager;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.util.SkinTextures;
import net.minecraft.entity.EntityAttachmentType;
@ -22,9 +23,9 @@ public class PlayerPonyRenderState extends PonyRenderState {
public double yOffset;
@Override
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
public void updateState(ItemModelManager resolver, LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
smallArms = ((AbstractClientPlayerEntity)entity).getSkinTextures().model() == SkinTextures.Model.SLIM;
super.updateState(entity, model, pony, mode);
super.updateState(resolver, entity, model, pony, mode);
yOffset = 0;
if (entity.hasVehicle()) {
Vec3d attachment = entity.getDimensions(entity.getPose()).attachments().getPointNullable(EntityAttachmentType.VEHICLE, 0, 0);

View file

@ -1,26 +1,39 @@
package com.minelittlepony.client.render.entity.state;
import net.minecraft.block.AbstractSkullBlock;
import net.minecraft.block.BedBlock;
import net.minecraft.block.SkullBlock.SkullType;
import net.minecraft.client.item.ItemModelManager;
import net.minecraft.client.render.entity.equipment.EquipmentModel;
import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.client.render.item.ItemRenderState;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.ProfileComponent;
import net.minecraft.entity.*;
import net.minecraft.entity.mob.AbstractPiglinEntity;
import net.minecraft.entity.mob.ZombifiedPiglinEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.*;
import net.minecraft.item.consume.UseAction;
import net.minecraft.registry.Registries;
import net.minecraft.util.Arm;
import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.events.PonyModelPrepareCallback;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.*;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.client.model.armour.ArmourRendererPlugin;
import com.minelittlepony.client.transform.PonyPosture;
import java.util.ArrayList;
import java.util.List;
public class PonyRenderState extends PlayerEntityRenderState implements PonyModel.AttributedHolder {
public final ModelAttributes attributes = new ModelAttributes();
@ -44,7 +57,9 @@ public class PonyRenderState extends PlayerEntityRenderState implements PonyMode
public final ItemRenderState glintlessRightHandItemState = new ItemRenderState();
public final ItemRenderState glintlessLeftHandItemState = new ItemRenderState();
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
public final List<EquippedHeadRenderState> equippedHeads = new ArrayList<>();
public void updateState(ItemModelManager resolver, LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
this.equippedHeadStack = entity.getEquippedStack(EquipmentSlot.HEAD);
this.pony = pony;
attributes.updateLivingState(entity, pony, mode);
@ -79,6 +94,16 @@ public class PonyRenderState extends PlayerEntityRenderState implements PonyMode
// capeRoll
field_53538 *= 3F;
ArmourRendererPlugin plugin = ArmourRendererPlugin.INSTANCE.get();
equippedHeads.clear();
for (ItemStack stack : plugin.getArmorStacks(entity, EquipmentSlot.HEAD, EquipmentModel.LayerType.HUMANOID, ArmourRendererPlugin.ArmourType.SKULL)) {
EquippedHeadRenderState state = EquippedHeadRenderState.of(resolver, stack, entity);
if (!state.isEmpty()) {
equippedHeads.add(state);
}
}
PonyPosture.of(attributes).updateState(entity, this);
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(attributes, model, ModelAttributes.Mode.OTHER);
}
@ -159,4 +184,35 @@ public class PonyRenderState extends PlayerEntityRenderState implements PonyMode
forwardFacing = PonyConfig.getInstance().forwardHoldingItems.get().contains(Registries.ITEM.getId(stack.getItem()));
}
}
public record EquippedHeadRenderState(
ItemRenderState item,
@Nullable SkullType skullType,
@Nullable ProfileComponent wearingSkullProfile) {
static final EquippedHeadRenderState EMPTY = new EquippedHeadRenderState(new ItemRenderState(), null, null);
public static EquippedHeadRenderState of(ItemModelManager resolver, ItemStack stack, LivingEntity entity) {
if (stack.isEmpty()) {
return EMPTY;
}
if (stack.getItem() instanceof BlockItem b && b.getBlock() instanceof AbstractSkullBlock skullBlock) {
return new EquippedHeadRenderState(EMPTY.item(), skullBlock.getSkullType(), stack.get(DataComponentTypes.PROFILE));
}
if (!ArmorFeatureRenderer.hasModel(stack, EquipmentSlot.HEAD)) {
ItemRenderState item = new ItemRenderState();
resolver.updateForLivingEntity(item, stack, ModelTransformationMode.HEAD, false, entity);
if (!item.isEmpty()) {
return new EquippedHeadRenderState(item, null, null);
}
}
return EMPTY;
}
public boolean isEmpty() {
return item.isEmpty() && skullType == null;
}
}
}