More cleanup work

This commit is contained in:
Sollace 2024-11-22 17:22:41 +00:00
parent 3517e3150b
commit f635d2e38f
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
29 changed files with 280 additions and 344 deletions

View file

@ -455,7 +455,7 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
* @param entity The entity we are being called for. * @param entity The entity we are being called for.
*/ */
protected final void swingItem(T state) { protected final void swingItem(T state) {
if (state.getSwingAmount() > 0 && !state.attributes.isLyingDown) { if (state.handSwingProgress > 0 && !state.attributes.isLyingDown) {
swingArm(state, getArm(state.preferredArm)); swingArm(state, getArm(state.preferredArm));
} }
} }
@ -466,10 +466,10 @@ public abstract class AbstractPonyModel<T extends PonyRenderState> extends Clien
* @param arm The arm to swing * @param arm The arm to swing
*/ */
protected final void swingArm(T state, ModelPart arm) { protected final void swingArm(T state, ModelPart arm) {
float swing = 1 - (float)Math.pow(1 - state.getSwingAmount(), 3); float swing = 1 - (float)Math.pow(1 - state.handSwingProgress, 3);
float deltaX = MathHelper.sin(swing * MathHelper.PI); float deltaX = MathHelper.sin(swing * MathHelper.PI);
float deltaZ = MathHelper.sin(state.getSwingAmount() * MathHelper.PI); float deltaZ = MathHelper.sin(state.handSwingProgress * MathHelper.PI);
float deltaAim = deltaZ * (0.7F - head.pitch) * 0.75F; float deltaAim = deltaZ * (0.7F - head.pitch) * 0.75F;

View file

@ -2,7 +2,6 @@ package com.minelittlepony.client.model;
import net.minecraft.client.model.Model; import net.minecraft.client.model.Model;
import net.minecraft.client.model.ModelPart; import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.entity.model.ArmorStandEntityModel;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import com.minelittlepony.api.model.BodyPart; import com.minelittlepony.api.model.BodyPart;
@ -48,7 +47,7 @@ public final class ModelType {
public static final ModelKey<PonyElytra<?>> ELYTRA = register("elytra", PonyElytra::new); public static final ModelKey<PonyElytra<?>> ELYTRA = register("elytra", PonyElytra::new);
public static final ModelKey<ArmorStandEntityModel> ARMOUR_STAND = register("armour_stand", PonyArmourStandModel::new); public static final ModelKey<PonyArmourStandModel> ARMOUR_STAND = register("armour_stand", PonyArmourStandModel::new);
public static final ModelKey<PonyArmourModel<?>> INNER_VANILLA_ARMOR = register("armor/inner_vanilla_armor", PonyArmourModel::new); public static final ModelKey<PonyArmourModel<?>> INNER_VANILLA_ARMOR = register("armor/inner_vanilla_armor", PonyArmourModel::new);
public static final ModelKey<PonyArmourModel<?>> OUTER_VANILLA_ARMOR = register("armor/outer_vanilla_armor", PonyArmourModel::new); public static final ModelKey<PonyArmourModel<?>> OUTER_VANILLA_ARMOR = register("armor/outer_vanilla_armor", PonyArmourModel::new);
public static final ModelKey<PonyArmourModel<?>> INNER_PONY_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new); public static final ModelKey<PonyArmourModel<?>> INNER_PONY_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new);

View file

@ -25,8 +25,8 @@ public class IllagerPonyModel<S extends IllagerPonyRenderer.State> extends Alico
if (pose == IllagerEntity.State.ATTACKING) { if (pose == IllagerEntity.State.ATTACKING) {
// vindicator attacking // vindicator attacking
float f = MathHelper.sin(state.getSwingAmount() * (float) Math.PI); float f = MathHelper.sin(state.handSwingProgress * (float) Math.PI);
float f1 = MathHelper.sin((1 - (1 - state.getSwingAmount()) * (1 - state.getSwingAmount())) * (float) Math.PI); float f1 = MathHelper.sin((1 - (1 - state.handSwingProgress) * (1 - state.handSwingProgress)) * (float) Math.PI);
float cos = MathHelper.cos(state.age * 0.09F) * 0.05F + 0.05F; float cos = MathHelper.cos(state.age * 0.09F) * 0.05F + 0.05F;
float sin = MathHelper.sin(state.age * 0.067F) * 0.05F; float sin = MathHelper.sin(state.age * 0.067F) * 0.05F;

View file

@ -2,11 +2,11 @@ package com.minelittlepony.client.model.entity;
import com.minelittlepony.api.model.MobPosingHelper; import com.minelittlepony.api.model.MobPosingHelper;
import com.minelittlepony.client.model.entity.race.AlicornModel; import com.minelittlepony.client.model.entity.race.AlicornModel;
import com.minelittlepony.client.render.entity.ZomponyRenderer; import com.minelittlepony.client.render.entity.state.PonyRenderState;
import net.minecraft.client.model.ModelPart; import net.minecraft.client.model.ModelPart;
public class ZomponyModel<T extends ZomponyRenderer.State> extends AlicornModel<T> { public class ZomponyModel<T extends PonyRenderState> extends AlicornModel<T> {
public ZomponyModel(ModelPart tree) { public ZomponyModel(ModelPart tree) {
super(tree, false); super(tree, false);
} }

View file

@ -20,7 +20,7 @@ public class AlicornModel<T extends PonyRenderState> extends UnicornModel<T> imp
public void init(ModelView context) { public void init(ModelView context) {
super.init(context); super.init(context);
wings = addPart(context.findByName("wings")); wings = addPart(context.findByName("wings"));
bodyRenderList.add(forPart(this::getWings).checked(() -> currentState.getRace().hasWings())); bodyRenderList.add(forPart(this::getWings).checked(() -> currentState.race.hasWings()));
} }
@Override @Override

View file

@ -34,7 +34,7 @@ public class UnicornModel<T extends PonyRenderState> extends EarthPonyModel<T> i
public void init(ModelView context) { public void init(ModelView context) {
super.init(context); super.init(context);
horn = addPart(context.findByName("horn")); horn = addPart(context.findByName("horn"));
headRenderList.add(RenderList.of().add(head::rotate).add(forPart(horn)).checked(() -> currentState.getRace().hasHorn())); headRenderList.add(RenderList.of().add(head::rotate).add(forPart(horn)).checked(() -> currentState.race.hasHorn()));
this.mainRenderList.add(withStage(BodyPart.HEAD, RenderList.of().add(head::rotate).add((stack, vertices, overlay, light, color) -> { this.mainRenderList.add(withStage(BodyPart.HEAD, RenderList.of().add(head::rotate).add((stack, vertices, overlay, light, color) -> {
horn.renderMagic(stack, vertices, currentState.attributes.metadata.glowColor()); horn.renderMagic(stack, vertices, currentState.attributes.metadata.glowColor());
})).checked(() -> currentState.hasMagicGlow() && isCasting(currentState))); })).checked(() -> currentState.hasMagicGlow() && isCasting(currentState)));

View file

@ -57,8 +57,8 @@ public class PonyEars implements SubModel<PonyRenderState>, MsonModel {
@Override @Override
public void setVisible(boolean visible, PonyRenderState state) { public void setVisible(boolean visible, PonyRenderState state) {
right.visible = visible && !state.getRace().isHuman(); right.visible = visible && !state.race.isHuman();
left.visible = visible && !state.getRace().isHuman(); left.visible = visible && !state.race.isHuman();
if (state.attributes.isHorsey) { if (state.attributes.isHorsey) {
left.pivotX = -1; left.pivotX = -1;

View file

@ -50,19 +50,18 @@ public class PonyWings<S extends PonyRenderState> implements SubModel<S>, MsonMo
public Wing<S> getRight(S state) { public Wing<S> getRight(S state) {
return ( return (
state.isEmbedded(Wearable.SADDLE_BAGS_BOTH) state.getAttributes().isEmbedded(Wearable.SADDLE_BAGS_BOTH)
|| state.isEmbedded(Wearable.SADDLE_BAGS_LEFT) || state.getAttributes().isEmbedded(Wearable.SADDLE_BAGS_LEFT)
|| state.isEmbedded(Wearable.SADDLE_BAGS_RIGHT) || state.getAttributes().isEmbedded(Wearable.SADDLE_BAGS_RIGHT)
) ? legacyWing : rightWing; ) ? legacyWing : rightWing;
} }
@Override @Override
public void setPartAngles(S state, float bodySwing) { public void setPartAngles(S state, float bodySwing) {
float flap = 0; float flap = 0;
float progress = state.getSwingAmount();
if (progress > 0) { if (state.handSwingProgress > 0) {
flap = MathHelper.sin(MathHelper.sqrt(progress) * MathHelper.TAU); flap = MathHelper.sin(MathHelper.sqrt(state.handSwingProgress) * MathHelper.TAU);
} else { } else {
float pi = MathHelper.PI * (float) Math.pow(state.limbAmplitudeMultiplier, 16); float pi = MathHelper.PI * (float) Math.pow(state.limbAmplitudeMultiplier, 16);
@ -92,9 +91,9 @@ public class PonyWings<S extends PonyRenderState> implements SubModel<S>, MsonMo
boolean bags = !extended && state.isWearing(Wearable.SADDLE_BAGS_BOTH); boolean bags = !extended && state.isWearing(Wearable.SADDLE_BAGS_BOTH);
boolean useLegacyWing = ( boolean useLegacyWing = (
state.isEmbedded(Wearable.SADDLE_BAGS_BOTH) state.getAttributes().isEmbedded(Wearable.SADDLE_BAGS_BOTH)
|| state.isEmbedded(Wearable.SADDLE_BAGS_LEFT) || state.getAttributes().isEmbedded(Wearable.SADDLE_BAGS_LEFT)
|| state.isEmbedded(Wearable.SADDLE_BAGS_RIGHT) || state.getAttributes().isEmbedded(Wearable.SADDLE_BAGS_RIGHT)
); );
leftWing.open = extended; leftWing.open = extended;
@ -156,12 +155,12 @@ public class PonyWings<S extends PonyRenderState> implements SubModel<S>, MsonMo
extended.visible = open; extended.visible = open;
folded.visible = !open; folded.visible = !open;
folded.yaw = swing * walkingRotationSpeed; folded.yaw = swing * walkingRotationSpeed;
if (state.getRace().hasBugWings()) { if (state.race.hasBugWings()) {
extended.yaw = folded.yaw; extended.yaw = folded.yaw;
} }
extended.roll = roll; extended.roll = roll;
if (state.getRace().hasBugWings()) { if (state.race.hasBugWings()) {
folded.roll = roll; folded.roll = roll;
} }
} }

View file

@ -37,10 +37,26 @@ public final class DebugBoundingBoxRenderer {
} }
public static Box getBoundingBox(PonyRenderState state) { public static Box getBoundingBox(PonyRenderState state) {
final float scale = state.size.scaleFactor(); return getBoundingBox(state.x, state.y, state.z, state.size.scaleFactor(), state.width, state.height);
final float width = state.width * scale; }
final float height = state.height * scale;
return new Box(-width, 0, -width, width, height, width).offset(state.x, state.y, state.z); public static Box getBoundingBox(double x, double y, double z, float scale, float width, float height) {
width *= scale;
height *= scale;
return new Box(x - width, y, z - width, x + width, y + height, z + width);
}
public static Box applyScale(float scale, Box box) {
double w = (box.maxX - box.minX) * 0.5F,
h = (box.maxY - box.minY),
d = (box.maxZ - box.minZ) * 0.5F,
x = box.minX + w,
z = box.minZ + d;
w *= scale;
d *= scale;
return new Box(
x - w, box.minY, z - d,
x + w, box.minY + h * scale, z + d
);
} }
} }

View file

@ -6,6 +6,8 @@ import com.minelittlepony.api.events.PonyDataCallback;
import com.minelittlepony.api.model.*; import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.Pony; import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData; import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.SizePreset;
import com.minelittlepony.client.PonyDataLoader; import com.minelittlepony.client.PonyDataLoader;
import com.minelittlepony.client.model.ClientPonyModel; import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.client.render.entity.state.PonyRenderState; import com.minelittlepony.client.render.entity.state.PonyRenderState;
@ -19,12 +21,13 @@ import java.util.function.Supplier;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.entity.model.EntityModel; import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Util;
import net.minecraft.util.math.Box;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -35,19 +38,23 @@ public class EquineRenderManager<
private Models<M> models; private Models<M> models;
private Function<S, Models<M>> modelsLookup = s -> models; private Function<Race, Models<M>> modelsLookup = race -> models;
private final PonyRenderContext<T, S, M> context; private final PonyRenderContext<T, S, M> context;
private final Transformer<? super S> transformer; private final Transformer<? super S> transformer;
private final FrustrumCheck<S> frustrum = new FrustrumCheck<>();
private final MinecraftClient client = MinecraftClient.getInstance();
public static void disableModelRenderProfile() { public static void disableModelRenderProfile() {
RenderSystem.disableBlend(); RenderSystem.disableBlend();
} }
public EquineRenderManager(PonyRenderContext<T, S, M> context, Transformer<? super S> transformer, Function<Race, Models<M>> modelsLookup) {
this.context = context;
this.transformer = transformer;
setModelsLookup(modelsLookup);
this.models = this.modelsLookup.apply(Race.EARTH);
context.setModel(models.body());
}
public EquineRenderManager(PonyRenderContext<T, S, M> context, Transformer<? super S> transformer, Models<M> models) { public EquineRenderManager(PonyRenderContext<T, S, M> context, Transformer<? super S> transformer, Models<M> models) {
this.context = context; this.context = context;
this.transformer = transformer; this.transformer = transformer;
@ -60,30 +67,30 @@ public class EquineRenderManager<
this(context, transformer, new Models(key)); this(context, transformer, new Models(key));
} }
public void setModelsLookup(Function<S, Models<M>> modelsLookup) { public void setModelsLookup(Function<Race, Models<M>> modelsLookup) {
this.modelsLookup = modelsLookup; this.modelsLookup = Util.memoize(modelsLookup);
} }
public Models<M> getModels() { public Models<M> getModels() {
return models; return models;
} }
public Frustum getFrustrum(T entity, Frustum vanilla) { public Box getBoundingBox(T entity, Box box) {
if (RenderPass.getCurrent() == RenderPass.HUD) {
return FrustrumCheck.ALWAYS_VISIBLE;
}
if (entity.isSleeping() || !PonyConfig.getInstance().frustrum.get()) { if (entity.isSleeping() || !PonyConfig.getInstance().frustrum.get()) {
return vanilla; return box;
} }
return frustrum.withCamera(context.getVanillaRenderer().getAndUpdateRenderState(entity, client.getRenderTickCounter().getTickDelta(false)), vanilla); Pony pony = context.getEntityPony(entity);
float scale = (entity.isBaby() ? SizePreset.FOAL : pony.size()).scaleFactor();
return DebugBoundingBoxRenderer.applyScale(scale, box);
} }
public void updateState(T entity, S state, ModelAttributes.Mode mode) { public void updateState(T entity, S state, ModelAttributes.Mode mode) {
models = modelsLookup.apply(state); Pony pony = context.getEntityPony(entity);
models = modelsLookup.apply(pony.race());
context.setModel(models.body()); context.setModel(models.body());
state.updateState(entity, models.body(), context.getEntityPony(entity), mode); state.updateState(entity, models.body(), pony, mode);
} }
public void setupTransforms(S state, MatrixStack stack, float animationProgress, float bodyYaw) { public void setupTransforms(S state, MatrixStack stack, float animationProgress, float bodyYaw) {

View file

@ -1,36 +1,49 @@
package com.minelittlepony.client.render; package com.minelittlepony.client.render;
import net.minecraft.client.render.Frustum; import net.minecraft.client.render.Frustum;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.math.Box; import net.minecraft.util.math.Box;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import com.minelittlepony.client.render.entity.state.PonyRenderState; import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.SizePreset;
public class FrustrumCheck<T extends PonyRenderState> extends Frustum { @Deprecated
public final class FrustrumCheck<T extends LivingEntity> extends Frustum {
public static final Frustum ALWAYS_VISIBLE = new Frustum(new Matrix4f(), new Matrix4f()) { public static final Frustum ALWAYS_VISIBLE = new Frustum(new Matrix4f(), new Matrix4f()) {
public boolean isVisible(Box bounds) { public boolean isVisible(Box bounds) {
return true; return true;
} }
}; };
private T entity;
private Frustum vanilla; private Frustum vanilla;
@Nullable
private Box boxOverride;
public FrustrumCheck() { public FrustrumCheck() {
super(new Matrix4f(), new Matrix4f()); super(new Matrix4f(), new Matrix4f());
} }
public Frustum withCamera(T entity, Frustum vanillaFrustrum) { public Frustum withCamera(PonyRenderContext<T, ?, ?> context, T entity, Frustum vanillaFrustrum) {
this.entity = entity;
vanilla = vanillaFrustrum; vanilla = vanillaFrustrum;
Pony pony = context.getEntityPony(entity);
boolean baby = entity.isBaby();
boxOverride = DebugBoundingBoxRenderer.getBoundingBox(
entity.getX(), entity.getY(), entity.getZ(),
(baby ? SizePreset.FOAL : pony.size()).scaleFactor(),
entity.getWidth(),
entity.getHeight()
);
return this; return this;
} }
@Override @Override
public boolean isVisible(Box bounds) { public boolean isVisible(Box bounds) {
return vanilla.isVisible(DebugBoundingBoxRenderer.getBoundingBox(entity)); return vanilla.isVisible(boxOverride == null ? bounds : boxOverride);
} }
@Override @Override

View file

@ -62,7 +62,7 @@ public record MobRenderers (String name, BiConsumer<MobRenderers, EntityRenderer
registry.registerEntityRenderer(EntityType.ENDERMAN, state, EnderStallionRenderer::new); registry.registerEntityRenderer(EntityType.ENDERMAN, state, EnderStallionRenderer::new);
}); });
public static final MobRenderers INANIMATE = register("inanimates", (state, registry) -> { public static final MobRenderers INANIMATE = register("inanimates", (state, registry) -> {
registry.registerEntityRenderer(EntityType.ARMOR_STAND, state, PonyStandRenderer::new); registry.registerEntityRenderer(EntityType.ARMOR_STAND, e -> state.option().get() && PonyStandRenderer.isPonyStand(e), PonyStandRenderer::new);
}); });
public static final MobRenderers STRIDER = register("striders", (state, registry) -> { public static final MobRenderers STRIDER = register("striders", (state, registry) -> {
registry.registerEntityRenderer(EntityType.STRIDER, state, StriderRenderer::new); registry.registerEntityRenderer(EntityType.STRIDER, state, StriderRenderer::new);

View file

@ -2,6 +2,7 @@ package com.minelittlepony.client.render;
import com.minelittlepony.api.model.gear.Gear; import com.minelittlepony.api.model.gear.Gear;
import com.minelittlepony.api.pony.Pony; import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.model.ClientPonyModel; import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.client.render.entity.state.PonyRenderState; import com.minelittlepony.client.render.entity.state.PonyRenderState;
@ -10,6 +11,7 @@ import net.minecraft.client.render.entity.feature.FeatureRendererContext;
import net.minecraft.client.render.entity.model.EntityModel; import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.render.entity.state.EntityRenderState; import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -21,9 +23,16 @@ public interface PonyRenderContext<
Pony getEntityPony(T entity); Pony getEntityPony(T entity);
EquineRenderManager<T, S, M> getInternalRenderer(); EquineRenderManager<T, S, M> getEquineManager();
void setModel(M model); default void setModel(M model) {
}
@Override
default Identifier getDefaultTexture(S entity, Wearable wearable) {
return wearable.getDefaultTexture();
}
@Nullable @Nullable
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View file

@ -15,8 +15,6 @@ import com.minelittlepony.mson.api.ModelKey;
import java.util.*; import java.util.*;
import java.util.function.*; import java.util.function.*;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.MobEntityRenderer; import net.minecraft.client.render.entity.MobEntityRenderer;
@ -24,9 +22,13 @@ import net.minecraft.client.render.entity.feature.FeatureRenderer;
import net.minecraft.client.render.entity.feature.HeadFeatureRenderer; import net.minecraft.client.render.entity.feature.HeadFeatureRenderer;
import net.minecraft.client.render.entity.state.PlayerEntityRenderState; import net.minecraft.client.render.entity.state.PlayerEntityRenderState;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.MobEntity;
import net.minecraft.item.Items;
import net.minecraft.resource.ResourceManager;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.Box;
public abstract class AbstractPonyRenderer< public abstract class AbstractPonyRenderer<
T extends MobEntity, T extends MobEntity,
@ -36,10 +38,12 @@ public abstract class AbstractPonyRenderer<
protected final EquineRenderManager<T, S, M> manager; protected final EquineRenderManager<T, S, M> manager;
private final Map<Wearable, Identifier> wearableTextures = new EnumMap<>(Wearable.class); private final Map<Identifier, Identifier> wearableTextures = new HashMap<>();
private final TextureSupplier<T> texture; private final TextureSupplier<T> texture;
private final ResourceManager resources;
private final float scale; private final float scale;
public AbstractPonyRenderer(EntityRendererFactory.Context context, ModelKey<? super M> key, TextureSupplier<T> texture, float scale) { public AbstractPonyRenderer(EntityRendererFactory.Context context, ModelKey<? super M> key, TextureSupplier<T> texture, float scale) {
@ -47,6 +51,7 @@ public abstract class AbstractPonyRenderer<
this.manager = new EquineRenderManager<T, S, M>(this, super::setupTransforms, key); this.manager = new EquineRenderManager<T, S, M>(this, super::setupTransforms, key);
this.texture = texture; this.texture = texture;
this.scale = scale; this.scale = scale;
resources = context.getResourceManager();
addFeatures(context); addFeatures(context);
} }
@ -97,8 +102,16 @@ public abstract class AbstractPonyRenderer<
} }
@Override @Override
public boolean shouldRender(T entity, Frustum visibleRegion, double camX, double camY, double camZ) { protected final Box getBoundingBox(T entity) {
return super.shouldRender(entity, manager.getFrustrum(entity, visibleRegion), camX, camY, camZ); Box box = manager.getBoundingBox(entity, getUnscaledBoundingBox(entity));
if (entity.getEquippedStack(EquipmentSlot.HEAD).isOf(Items.DRAGON_HEAD)) {
return box.expand(0.5, 0.5, 0.5);
}
return box;
}
protected Box getUnscaledBoundingBox(T entity) {
return entity.getBoundingBox();
} }
@Override @Override
@ -130,14 +143,8 @@ public abstract class AbstractPonyRenderer<
@Override @Override
public Identifier getDefaultTexture(S state, Wearable wearable) { public Identifier getDefaultTexture(S state, Wearable wearable) {
return wearableTextures.computeIfAbsent(wearable, w -> {
Identifier texture = getTexture(state).withPath(path -> path.split("\\.")[0] + "_" + wearable.name().toLowerCase(Locale.ROOT) + ".png"); Identifier texture = getTexture(state).withPath(path -> path.split("\\.")[0] + "_" + wearable.name().toLowerCase(Locale.ROOT) + ".png");
return wearableTextures.computeIfAbsent(texture, t -> resources.getResource(t).isPresent() ? t : wearable.getDefaultTexture());
if (MinecraftClient.getInstance().getResourceManager().getResource(texture).isPresent()) {
return texture;
}
return wearable.getDefaultTexture();
});
} }
@Override @Override
@ -146,7 +153,7 @@ public abstract class AbstractPonyRenderer<
} }
@Override @Override
public EquineRenderManager<T, S, M> getInternalRenderer() { public EquineRenderManager<T, S, M> getEquineManager() {
return manager; return manager;
} }

View file

@ -1,7 +1,6 @@
package com.minelittlepony.client.render.entity; package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.model.*; import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.Race; import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType; import com.minelittlepony.client.model.ModelType;
@ -16,7 +15,6 @@ import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.feature.StuckArrowsFeatureRenderer; import net.minecraft.client.render.entity.feature.StuckArrowsFeatureRenderer;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.EndermanEntity; import net.minecraft.entity.mob.EndermanEntity;
import net.minecraft.util.Arm; import net.minecraft.util.Arm;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -36,11 +34,6 @@ public class EnderStallionRenderer extends PonyRenderer<EndermanEntity, EnderSta
super(context, ModelType.ENDERMAN, TextureSupplier.of(ENDERMAN)); super(context, ModelType.ENDERMAN, TextureSupplier.of(ENDERMAN));
} }
@Override
public State createRenderState() {
return new State();
}
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
@Override @Override
protected void addFeatures(EntityRendererFactory.Context context) { protected void addFeatures(EntityRendererFactory.Context context) {
@ -49,6 +42,31 @@ public class EnderStallionRenderer extends PonyRenderer<EndermanEntity, EnderSta
addPonyFeature(new GlowingEyesFeature<EnderStallionRenderer.State, EnderStallionModel>(this)); addPonyFeature(new GlowingEyesFeature<EnderStallionRenderer.State, EnderStallionModel>(this));
} }
@Override
public State createRenderState() {
return new State();
}
@Override
public void updateRenderState(EndermanEntity entity, State state, float tickDelta) {
super.updateRenderState(entity, state, tickDelta);
boolean isAlicorn = entity.getUuid().getLeastSignificantBits() % 3 == 0;
state.isBoss = !isAlicorn && entity.getUuid().getLeastSignificantBits() % 90 == 0;
state.race = isAlicorn ? (state.attributes.metadata.race().hasHorn() ? Race.ALICORN : Race.PEGASUS) : state.attributes.metadata.race();
state.angry = entity.isAngry();
state.carriedBlock = entity.getCarriedBlock();
if (state.carriedBlock != null) {
if (state.mainArm == Arm.RIGHT) {
state.rightHandStack = state.carriedBlock.getBlock().asItem().getDefaultStack();
} else {
state.leftHandStack = state.carriedBlock.getBlock().asItem().getDefaultStack();
}
}
state.attributes.wingsSpread = state.isAttacking;
state.attributes.wingAngle = MathHelper.sin(state.age) + WingedPonyModel.WINGS_HALF_SPREAD_ANGLE;
}
@Override @Override
protected HeldItemFeature<State, EnderStallionModel> createHeldItemFeature(EntityRendererFactory.Context context) { protected HeldItemFeature<State, EnderStallionModel> createHeldItemFeature(EntityRendererFactory.Context context) {
return new HeldItemFeature<State, EnderStallionModel>(this, context.getItemRenderer()); return new HeldItemFeature<State, EnderStallionModel>(this, context.getItemRenderer());
@ -72,34 +90,6 @@ public class EnderStallionRenderer extends PonyRenderer<EndermanEntity, EnderSta
public boolean angry; public boolean angry;
@Nullable @Nullable
public BlockState carriedBlock; public BlockState carriedBlock;
public boolean isAlicorn;
public boolean isBoss; public boolean isBoss;
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(entity, model, pony, mode);
isUnicorn = true;
isAlicorn = entity.getUuid().getLeastSignificantBits() % 3 == 0;
isBoss = !isAlicorn && entity.getUuid().getLeastSignificantBits() % 90 == 0;
angry = ((EndermanEntity)entity).isAngry();
carriedBlock = ((EndermanEntity)entity).getCarriedBlock();
if (carriedBlock != null) {
if (mainArm == Arm.RIGHT) {
rightHandStack = carriedBlock.getBlock().asItem().getDefaultStack();
} else {
leftHandStack = carriedBlock.getBlock().asItem().getDefaultStack();
}
}
attributes.wingsSpread = isAttacking;
attributes.wingAngle = MathHelper.sin(age) + WingedPonyModel.WINGS_HALF_SPREAD_ANGLE;
}
@Override
public Race getRace() {
return isAlicorn ? (super.getRace().hasHorn() ? Race.ALICORN : Race.PEGASUS) : super.getRace();
}
} }
} }

View file

@ -1,9 +1,7 @@
package com.minelittlepony.client.render.entity; package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.model.ModelAttributes; import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.model.Models;
import com.minelittlepony.api.pony.Pony; import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.Wearable; import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.model.*; import com.minelittlepony.client.model.*;
import com.minelittlepony.client.render.DebugBoundingBoxRenderer; import com.minelittlepony.client.render.DebugBoundingBoxRenderer;
@ -14,11 +12,9 @@ import com.minelittlepony.client.render.entity.state.PonyRenderState;
import com.minelittlepony.common.util.render.RenderLayerUtil; import com.minelittlepony.common.util.render.RenderLayerUtil;
import java.util.*; import java.util.*;
import java.util.function.Function;
import com.minelittlepony.client.render.EquineRenderManager; import com.minelittlepony.client.render.EquineRenderManager;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.AbstractClientPlayerEntity; import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.render.*; import net.minecraft.client.render.*;
import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.render.entity.EntityRendererFactory;
@ -29,8 +25,7 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EntityPose; import net.minecraft.entity.EntityPose;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.*;
import net.minecraft.util.math.Vec3d;
public class PlayerPonyRenderer public class PlayerPonyRenderer
extends PlayerEntityRenderer extends PlayerEntityRenderer
@ -39,21 +34,15 @@ public class PlayerPonyRenderer
PlayerPonyRenderState, PlayerPonyRenderState,
ClientPonyModel<PlayerPonyRenderState> ClientPonyModel<PlayerPonyRenderState>
> { > {
private final Function<Race, Models<ClientPonyModel<PlayerPonyRenderState>>> modelsCache;
protected final EquineRenderManager<AbstractClientPlayerEntity, PlayerPonyRenderState, ClientPonyModel<PlayerPonyRenderState>> manager; protected final EquineRenderManager<AbstractClientPlayerEntity, PlayerPonyRenderState, ClientPonyModel<PlayerPonyRenderState>> manager;
private ModelAttributes.Mode mode = ModelAttributes.Mode.THIRD_PERSON; private ModelAttributes.Mode mode = ModelAttributes.Mode.THIRD_PERSON;
@SuppressWarnings({"unchecked", "rawtypes"})
public PlayerPonyRenderer(EntityRendererFactory.Context context, boolean slim) { public PlayerPonyRenderer(EntityRendererFactory.Context context, boolean slim) {
super(context, slim); super(context, slim);
modelsCache = Util.memoize(race -> ModelType.getPlayerModel(race).create(slim)); manager = new EquineRenderManager<>(this, super::setupTransforms, race -> ModelType.getPlayerModel(race).create(slim));
manager = new EquineRenderManager<>(this, super::setupTransforms, modelsCache.apply(Race.EARTH));
manager.setModelsLookup(entity -> modelsCache.apply(getPlayerRace(entity)));
addPonyFeatures(context);
}
@SuppressWarnings({"unchecked", "rawtypes"})
protected void addPonyFeatures(EntityRendererFactory.Context context) {
// remove vanilla features (keep modded ones) // remove vanilla features (keep modded ones)
features.removeIf(feature -> { features.removeIf(feature -> {
return feature instanceof ArmorFeatureRenderer return feature instanceof ArmorFeatureRenderer
@ -129,11 +118,6 @@ public class PlayerPonyRenderer
stack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yaw)); stack.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(yaw));
} }
*/ */
}
protected Race getPlayerRace(PlayerPonyRenderState state) {
return state.getRace();
} }
@Override @Override
@ -142,12 +126,8 @@ public class PlayerPonyRenderer
} }
@Override @Override
public boolean shouldRender(AbstractClientPlayerEntity entity, Frustum camera, double camX, double camY, double camZ) { protected Box getBoundingBox(AbstractClientPlayerEntity entity) {
if (entity.isSleeping() && entity == MinecraftClient.getInstance().player) { return manager.getBoundingBox(entity, entity.getBoundingBox());
return !MinecraftClient.getInstance().options.getPerspective().isFirstPerson()
&& super.shouldRender(entity, camera, camX, camY, camZ);
}
return super.shouldRender(entity, manager.getFrustrum(entity, camera), camX, camY, camZ);
} }
@Override @Override
@ -205,7 +185,7 @@ public class PlayerPonyRenderer
} }
@Override @Override
public EquineRenderManager<AbstractClientPlayerEntity, PlayerPonyRenderState, ClientPonyModel<PlayerPonyRenderState>> getInternalRenderer() { public EquineRenderManager<AbstractClientPlayerEntity, PlayerPonyRenderState, ClientPonyModel<PlayerPonyRenderState>> getEquineManager() {
return manager; return manager;
} }
@ -225,7 +205,7 @@ public class PlayerPonyRenderer
return state.wearabledTextures.get(wearable); return state.wearabledTextures.get(wearable);
} }
if (wearable.isSaddlebags() && state.getRace().supportsLegacySaddlebags()) { if (wearable.isSaddlebags() && state.race.supportsLegacySaddlebags()) {
return getTexture(state); return getTexture(state);
} }

View file

@ -8,6 +8,7 @@ import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType; import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.PiglinPonyModel; import com.minelittlepony.client.model.entity.PiglinPonyModel;
import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier; import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier;
import com.minelittlepony.client.render.entity.state.PonyRenderState;
public class PonyPiglinRenderer extends PonyRenderer<HostileEntity, PonyPiglinRenderer.State, PiglinPonyModel> { public class PonyPiglinRenderer extends PonyRenderer<HostileEntity, PonyPiglinRenderer.State, PiglinPonyModel> {
public static final Identifier PIGLIN = MineLittlePony.id("textures/entity/piglin/piglin_pony.png"); public static final Identifier PIGLIN = MineLittlePony.id("textures/entity/piglin/piglin_pony.png");
@ -39,16 +40,10 @@ public class PonyPiglinRenderer extends PonyRenderer<HostileEntity, PonyPiglinRe
super.updateRenderState(entity, state, tickDelta); super.updateRenderState(entity, state, tickDelta);
state.zombified = entity instanceof ZombifiedPiglinEntity; state.zombified = entity instanceof ZombifiedPiglinEntity;
state.activity = entity instanceof AbstractPiglinEntity piglin ? piglin.getActivity() : PiglinActivity.DEFAULT; state.activity = entity instanceof AbstractPiglinEntity piglin ? piglin.getActivity() : PiglinActivity.DEFAULT;
state.shouldZombify = entity instanceof AbstractPiglinEntity piglin && piglin.shouldZombify(); state.shaking |= entity instanceof AbstractPiglinEntity piglin && piglin.shouldZombify();
} }
@Override public static class State extends PonyRenderState {
protected boolean isShaking(State state) {
return super.isShaking(state) || state.shouldZombify;
}
public static class State extends ZomponyRenderer.State {
public boolean shouldZombify;
public boolean zombified; public boolean zombified;
public PiglinActivity activity; public PiglinActivity activity;
} }

View file

@ -1,21 +1,24 @@
package com.minelittlepony.client.render.entity; package com.minelittlepony.client.render.entity;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.*; import net.minecraft.client.render.entity.*;
import net.minecraft.client.render.entity.feature.*; import net.minecraft.client.render.entity.feature.*;
import net.minecraft.client.render.entity.model.ArmorStandArmorEntityModel; import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.client.render.entity.state.ArmorStandEntityRenderState; import net.minecraft.client.render.entity.state.ArmorStandEntityRenderState;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.model.ModelAttributes.Mode; import com.minelittlepony.api.model.ModelAttributes.Mode;
import com.minelittlepony.api.model.Models;
import com.minelittlepony.api.pony.Pony; import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData; import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.model.ModelType; import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.armour.PonifiedEquipmentRenderer;
import com.minelittlepony.client.model.entity.PonyArmourStandModel; import com.minelittlepony.client.model.entity.PonyArmourStandModel;
import com.minelittlepony.client.model.entity.race.EarthPonyModel; import com.minelittlepony.client.model.entity.race.EarthPonyModel;
import com.minelittlepony.client.render.EquineRenderManager; import com.minelittlepony.client.render.EquineRenderManager;
@ -24,115 +27,114 @@ import com.minelittlepony.client.render.entity.feature.*;
import com.minelittlepony.client.render.entity.state.PonyRenderState; import com.minelittlepony.client.render.entity.state.PonyRenderState;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
public class PonyStandRenderer extends ArmorStandEntityRenderer implements PonyRenderContext<ArmorStandEntity, PonyRenderState, EarthPonyModel<PonyRenderState>> { public class PonyStandRenderer extends LivingEntityRenderer<ArmorStandEntity, PonyStandRenderer.State, PonyArmourStandModel> {
static final Pony PONY = new Pony(Identifier.ofVanilla("null"), () -> Optional.of(PonyData.NULL)); static final Pony PONY = new Pony(Identifier.ofVanilla("null"), () -> Optional.of(PonyData.NULL));
private final PonyArmourStandModel pony = ModelType.ARMOUR_STAND.createModel();
private final Models<EarthPonyModel<PonyRenderState>> models = ModelType.EARTH_PONY.create(false);
private final ArmorStandArmorEntityModel human; private final PonifiedContext context = new PonifiedContext();
private final EquineRenderManager<ArmorStandEntity, PonyRenderState, EarthPonyModel<PonyRenderState>> manager; public static boolean isPonyStand(Entity entity) {
return entity.hasCustomName() && "Ponita".equals(entity.getCustomName().getString());
}
public PonyStandRenderer(EntityRendererFactory.Context context) { public PonyStandRenderer(EntityRendererFactory.Context context) {
super(context); super(context, ModelType.ARMOUR_STAND.createModel(), 0);
human = model; addFeature(new PonifiedFeature(this, new ArmourFeature<>(this.context, context.getEquipmentModelLoader())));
this.manager = new EquineRenderManager<>(this, (state, stack, progress, yaw) -> {}, models); addFeature(new PonifiedFeature(this, new HeldItemFeature<>(this.context, context.getItemRenderer())));
addFeature(new PonifiedFeature(this, new ElytraFeature<>(this.context, context.getEquipmentRenderer())));
Predicate<ArmorStandEntityRenderState> swapPredicate = state -> ((State)state).hasPonyForm; addFeature(new PonifiedFeature(this, new SkullFeature<>(this.context, context.getModelLoader(), context.getItemRenderer(), HeadFeatureRenderer.HeadTransformation.DEFAULT, false)));
Function<ArmorStandEntityRenderState, PonyRenderState> converter = state -> ((State)state).ponyState;
for (int i = 0; i < features.size(); i++) {
var feature = features.get(i);
if (feature instanceof ArmorFeatureRenderer) {
features.set(i, new SwappableFeature<>(this, feature, new Armour(context), swapPredicate, converter));
} }
if (feature instanceof ElytraFeatureRenderer) {
features.set(i, new SwappableFeature<>(this,
feature,
new ElytraFeature<>(() -> models.body(), context.getEquipmentRenderer()), swapPredicate, converter));
}
if (feature instanceof HeadFeatureRenderer) {
features.set(i, new SwappableFeature<>(this,
feature,
new SkullFeature<PonyRenderState, EarthPonyModel<PonyRenderState>>(
this,
context.getModelLoader(),
context.getItemRenderer(),
HeadFeatureRenderer.HeadTransformation.DEFAULT,
false
), swapPredicate, converter));
}
}
}
@Override @Override
public Identifier getDefaultTexture(PonyRenderState entity, Wearable wearable) { public State createRenderState() {
return wearable.getDefaultTexture(); return new State();
} }
@Override
public Identifier getTexture(State state) {
return ArmorStandEntityRenderer.TEXTURE;
}
public void updateRenderState(ArmorStandEntity entity, State state, float tickDelta) {
super.updateRenderState(entity, state, tickDelta);
BipedEntityRenderer.updateBipedRenderState(entity, state.ponyState, tickDelta);
context.manager.updateState(entity, state.ponyState, Mode.OTHER);
state.pitch = MathHelper.RADIANS_PER_DEGREE * entity.getHeadRotation().getPitch();
state.yawDegrees = MathHelper.RADIANS_PER_DEGREE * entity.getHeadRotation().getYaw();
}
@Override
protected void setupTransforms(State state, MatrixStack matrices, float animationProgress, float bodyYaw) {
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - animationProgress));
if (state.timeSinceLastHit < 5) {
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(MathHelper.sin(state.timeSinceLastHit / 1.5F * (float) Math.PI) * 3.0F));
}
matrices.translate(0, 0, state.baseScale * -4/16F);
}
@Override
protected boolean hasLabel(ArmorStandEntity entity, double squaredDistanceToCamera) {
return entity.isCustomNameVisible();
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
@Nullable
protected RenderLayer getRenderLayer(State state, boolean showBody, boolean translucent, boolean showOutline) {
if (context.getModel() instanceof BipedEntityModel bipedModel) {
bipedModel.copyTransforms((BipedEntityModel)model);
}
if (!state.marker) {
return super.getRenderLayer(state, showBody, translucent, showOutline);
}
Identifier identifier = getTexture(state);
if (translucent) {
return RenderLayer.getEntityTranslucent(identifier, false);
}
return showBody ? RenderLayer.getEntityCutoutNoCull(identifier, false) : null;
}
private class PonifiedContext implements
FeatureRendererContext<PonyRenderState, EarthPonyModel<PonyRenderState>>,
PonyRenderContext<ArmorStandEntity, PonyRenderState, EarthPonyModel<PonyRenderState>> {
private final EquineRenderManager<ArmorStandEntity, PonyRenderState, EarthPonyModel<PonyRenderState>> manager
= new EquineRenderManager<>(this, (state, stack, progress, yaw) -> {}, ModelType.EARTH_PONY.create(false));
@Override @Override
public Pony getEntityPony(ArmorStandEntity entity) { public Pony getEntityPony(ArmorStandEntity entity) {
return PONY; return PONY;
} }
@Override @Override
public EquineRenderManager<ArmorStandEntity, PonyRenderState, EarthPonyModel<PonyRenderState>> getInternalRenderer() { public EquineRenderManager<ArmorStandEntity, PonyRenderState, EarthPonyModel<PonyRenderState>> getEquineManager() {
return manager; return manager;
} }
@Override @Override
public void setModel(EarthPonyModel<PonyRenderState> model) { } public EarthPonyModel<PonyRenderState> getModel() {
return manager.getModels().body();
}
}
private class PonifiedFeature extends FeatureRenderer<PonyStandRenderer.State, PonyArmourStandModel> {
private final FeatureRenderer<?, ?> feature;
public PonifiedFeature(FeatureRendererContext<PonyStandRenderer.State, PonyArmourStandModel> context,
FeatureRenderer<?, ?> feature) {
super(context);
this.feature = feature;
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Override @Override
public ArmorStandEntityRenderState createRenderState() { public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, PonyStandRenderer.State state, float limbAngle, float limbDistance) {
return new State(); ((FeatureRenderer)feature).render(matrices, vertices, light, state.ponyState, limbAngle, limbDistance);
}
public void updateRenderState(ArmorStandEntity entity, ArmorStandEntityRenderState state, float tickDelta) {
boolean ponified = entity.hasCustomName() && "Ponita".equals(entity.getCustomName().getString());
super.updateRenderState(entity, state, tickDelta);
((State)state).hasPonyForm = ponified;
if (ponified) {
BipedEntityRenderer.updateBipedRenderState(entity, ((State)state).ponyState, tickDelta);
manager.updateState(entity, ((State)state).ponyState, Mode.OTHER);
state.pitch = 0.017453292F * entity.getHeadRotation().getPitch();
state.yawDegrees = 0.017453292F * entity.getHeadRotation().getYaw();
}
}
@Override
protected void setupTransforms(ArmorStandEntityRenderState state, MatrixStack stack, float animationProgress, float bodyYaw) {
super.setupTransforms(state, stack, animationProgress, bodyYaw);
if (((State)state).hasPonyForm) {
stack.translate(0, 0, state.baseScale * -4/16F);
this.model = pony;
} else {
this.model = human;
}
}
class Armour extends FeatureRenderer<PonyRenderState, EarthPonyModel<PonyRenderState>> {
private final PonifiedEquipmentRenderer equipmentRenderer;
public Armour(EntityRendererFactory.Context context) {
super(() -> models.body());
equipmentRenderer = new PonifiedEquipmentRenderer(context.getEquipmentModelLoader());
}
@Override
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, PonyRenderState state, float limbAngle, float limbDistance) {
getContextModel().setAngles(state);
ArmourFeature.renderArmor(models, matrices, vertices, light, state, limbDistance, limbAngle, equipmentRenderer);
} }
} }
public static final class State extends ArmorStandEntityRenderState { public static final class State extends ArmorStandEntityRenderState {
public boolean hasPonyForm;
public PonyRenderState ponyState = new PonyRenderState(); public PonyRenderState ponyState = new PonyRenderState();
} }
} }

View file

@ -67,19 +67,13 @@ public class SkeleponyRenderer<T extends AbstractSkeletonEntity> extends PonyRen
} }
public static class State extends PonyRenderState { public static class State extends PonyRenderState {
public boolean isUnicorn;
public boolean isWithered;
public boolean isAttacking; public boolean isAttacking;
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) { public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
isUnicorn = entity.getUuid().getLeastSignificantBits() % 3 != 0;
isWithered = entity instanceof WitherSkeletonEntity;
isAttacking = entity instanceof HostileEntity h && h.isAttacking(); isAttacking = entity instanceof HostileEntity h && h.isAttacking();
if (entity.getUuid().getLeastSignificantBits() % 3 == 0) {
race = Race.EARTH;
} }
@Override
public Race getRace() {
return isUnicorn ? super.getRace() : Race.EARTH;
} }
@Override @Override

View file

@ -1,8 +1,5 @@
package com.minelittlepony.client.render.entity; package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.Wearable; import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType; import com.minelittlepony.client.model.ModelType;
@ -11,7 +8,6 @@ import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier;
import com.minelittlepony.client.render.entity.state.PonyRenderState; import com.minelittlepony.client.render.entity.state.PonyRenderState;
import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.WitchEntity; import net.minecraft.entity.mob.WitchEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -27,19 +23,16 @@ public class WitchRenderer extends PonyRenderer<WitchEntity, WitchRenderer.State
return new State(); return new State();
} }
public void updateRenderState(WitchEntity entity, State state, float tickDelta) {
super.updateRenderState(entity, state, tickDelta);
state.drinking = entity instanceof WitchEntity w && w.isDrinking();
state.attributes.visualHeight += 0.5F;
state.baby |= state.customName != null && "Filly".equals(state.customName.getString());
}
public static class State extends PonyRenderState { public static class State extends PonyRenderState {
public boolean drinking; public boolean drinking;
@Override
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(entity, model, pony, mode);
drinking = entity instanceof WitchEntity w && w.isDrinking();
attributes.visualHeight += 0.5F;
if (customName != null && "Filly".equals(customName.getString())) {
baby = true;
}
}
@Override @Override
public boolean isWearing(Wearable wearable) { public boolean isWearing(Wearable wearable) {
return wearable == Wearable.HAT || super.isWearing(wearable); return wearable == Wearable.HAT || super.isWearing(wearable);

View file

@ -5,9 +5,6 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.*; import net.minecraft.entity.mob.*;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.Race; import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType; import com.minelittlepony.client.model.ModelType;
@ -15,7 +12,7 @@ import com.minelittlepony.client.model.entity.ZomponyModel;
import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier; import com.minelittlepony.client.render.entity.npc.textures.TextureSupplier;
import com.minelittlepony.client.render.entity.state.PonyRenderState; import com.minelittlepony.client.render.entity.state.PonyRenderState;
public class ZomponyRenderer<T extends HostileEntity> extends PonyRenderer<T, ZomponyRenderer.State, ZomponyModel<ZomponyRenderer.State>> { public class ZomponyRenderer<T extends HostileEntity> extends PonyRenderer<T, PonyRenderState, ZomponyModel<PonyRenderState>> {
public static final Identifier ZOMBIE = MineLittlePony.id("textures/entity/zombie/zombie_pony.png"); public static final Identifier ZOMBIE = MineLittlePony.id("textures/entity/zombie/zombie_pony.png");
public static final Identifier HUSK = MineLittlePony.id("textures/entity/zombie/husk_pony.png"); public static final Identifier HUSK = MineLittlePony.id("textures/entity/zombie/husk_pony.png");
public static final Identifier DROWNED = MineLittlePony.id("textures/entity/zombie/drowned_pony.png"); public static final Identifier DROWNED = MineLittlePony.id("textures/entity/zombie/drowned_pony.png");
@ -27,8 +24,14 @@ public class ZomponyRenderer<T extends HostileEntity> extends PonyRenderer<T, Zo
} }
@Override @Override
public State createRenderState() { public PonyRenderState createRenderState() {
return new State(); return new PonyRenderState();
}
@Override
public void updateRenderState(T entity, PonyRenderState state, float tickDelta) {
super.updateRenderState(entity, state, tickDelta);
state.race = isWinged(entity) ? (state.race.hasHorn() ? Race.ALICORN : Race.PEGASUS) : state.race;
} }
public static ZomponyRenderer<ZombieEntity> zombie(EntityRendererFactory.Context context) { public static ZomponyRenderer<ZombieEntity> zombie(EntityRendererFactory.Context context) {
@ -51,19 +54,7 @@ public class ZomponyRenderer<T extends HostileEntity> extends PonyRenderer<T, Zo
return entity.isBaby() && entity.getUuid().getLeastSignificantBits() % 160 == 0; return entity.isBaby() && entity.getUuid().getLeastSignificantBits() % 160 == 0;
} }
public static class State extends PonyRenderState { static boolean isWinged(LivingEntity entity) {
public boolean isWinged; return entity.getUuid().getLeastSignificantBits() % 30 == 0;
public boolean isCozyGlow;
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
super.updateState(entity, model, pony, mode);
isCozyGlow = isCozyGlow(entity);
isWinged = entity.getUuid().getLeastSignificantBits() % 30 == 0;
}
@Override
public Race getRace() {
return isWinged ? (super.getRace().hasHorn() ? Race.ALICORN : Race.PEGASUS) : super.getRace();
}
} }
} }

View file

@ -28,10 +28,10 @@ public abstract class AbstractPonyFeature<
@Override @Override
public final M getContextModel() { public final M getContextModel() {
return context.getInternalRenderer().getModels().body(); return context.getEquineManager().getModels().body();
} }
protected Models<M> getModelWrapper() { protected Models<M> getModelWrapper() {
return context.getInternalRenderer().getModels(); return context.getEquineManager().getModels();
} }
} }

View file

@ -29,7 +29,7 @@ public class CapeFeature extends CapeFeatureRenderer {
@Override @Override
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, PlayerEntityRenderState player, float limbAngle, float limbDistance) { public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, PlayerEntityRenderState player, float limbAngle, float limbDistance) {
ClientPonyModel<PlayerPonyRenderState> model = context.getInternalRenderer().getModels().body(); ClientPonyModel<PlayerPonyRenderState> model = context.getEquineManager().getModels().body();
if (!player.invisible && player.capeVisible) { if (!player.invisible && player.capeVisible) {
ArmourRendererPlugin plugin = ArmourRendererPlugin.INSTANCE.get(); ArmourRendererPlugin plugin = ArmourRendererPlugin.INSTANCE.get();

View file

@ -69,7 +69,7 @@ public class ElytraFeature<
if (state instanceof PonyRenderState ponyState && context instanceof PonyRenderContext context) { if (state instanceof PonyRenderState ponyState && context instanceof PonyRenderContext context) {
stack.translate(0, ponyState.riderOffset, 0.125); stack.translate(0, ponyState.riderOffset, 0.125);
((ClientPonyModel<PonyRenderState>)context.getInternalRenderer().getModels().body()).transform(ponyState, BodyPart.BODY, stack); ((ClientPonyModel<PonyRenderState>)context.getEquineManager().getModels().body()).transform(ponyState, BodyPart.BODY, stack);
} }
} }

View file

@ -29,7 +29,7 @@ public class HeldItemFeature<
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, S state, float limbAngle, float limbDistance) { public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, S state, float limbAngle, float limbDistance) {
if (!state.leftHandStack.isEmpty() || !state.rightHandStack.isEmpty()) { if (!state.leftHandStack.isEmpty() || !state.rightHandStack.isEmpty()) {
M model = context.getInternalRenderer().getModels().body(); M model = context.getEquineManager().getModels().body();
matrices.push(); matrices.push();
model.transform(state, BodyPart.LEGS, matrices); model.transform(state, BodyPart.LEGS, matrices);

View file

@ -32,7 +32,6 @@ public class PassengerFeature<
parrotState.parrotPose = ParrotEntityModel.Pose.ON_SHOULDER; parrotState.parrotPose = ParrotEntityModel.Pose.ON_SHOULDER;
} }
@Override @Override
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, S state, float limbAngle, float limbDistance) { public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, S state, float limbAngle, float limbDistance) {
if (state.leftShoulderParrotVariant != null) { if (state.leftShoulderParrotVariant != null) {

View file

@ -1,48 +0,0 @@
package com.minelittlepony.client.render.entity.feature;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.feature.FeatureRenderer;
import net.minecraft.client.render.entity.feature.FeatureRendererContext;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.render.entity.state.EntityRenderState;
import net.minecraft.client.util.math.MatrixStack;
import java.util.function.Function;
import java.util.function.Predicate;
public final class SwappableFeature<
S extends EntityRenderState,
M extends EntityModel<? super S>,
P extends EntityRenderState,
N extends EntityModel<? super P>
> extends FeatureRenderer<S, M> {
private final FeatureRenderer<S, M> normal;
private final FeatureRenderer<P, N> swapped;
private final Predicate<S> swapCondition;
private final Function<S, P> stateConverter;
public SwappableFeature(
FeatureRendererContext<S, M> context,
FeatureRenderer<S, M> normal,
FeatureRenderer<P, N> swapped,
Predicate<S> swapCondition,
Function<S, P> stateConverter
) {
super(context);
this.normal = normal;
this.swapped = swapped;
this.swapCondition = swapCondition;
this.stateConverter = stateConverter;
}
@Override
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, S state, float limbAngle, float limbDistance) {
if (swapCondition.test(state)) {
swapped.render(matrices, vertices, light, stateConverter.apply(state), limbAngle, limbDistance);
} else {
normal.render(matrices, vertices, light, state, limbAngle, limbDistance);
}
}
}

View file

@ -3,10 +3,8 @@ package com.minelittlepony.client.render.entity.npc;
import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.entity.mob.MobEntity; import net.minecraft.entity.mob.MobEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.village.*; import net.minecraft.village.*;
import com.minelittlepony.api.model.*;
import com.minelittlepony.api.model.gear.Gear; import com.minelittlepony.api.model.gear.Gear;
import com.minelittlepony.api.pony.meta.Race; import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.Wearable; import com.minelittlepony.api.pony.meta.Wearable;
@ -14,24 +12,21 @@ import com.minelittlepony.client.model.*;
import com.minelittlepony.client.render.entity.PonyRenderer; import com.minelittlepony.client.render.entity.PonyRenderer;
import com.minelittlepony.client.render.entity.npc.textures.*; import com.minelittlepony.client.render.entity.npc.textures.*;
import java.util.function.Function;
abstract class AbstractNpcRenderer< abstract class AbstractNpcRenderer<
T extends MobEntity & VillagerDataContainer, T extends MobEntity & VillagerDataContainer,
S extends SillyPonyTextureSupplier.State S extends SillyPonyTextureSupplier.State
> extends PonyRenderer<T, S, ClientPonyModel<S>> { > extends PonyRenderer<T, S, ClientPonyModel<S>> {
private final NpcClothingFeature<T, S, ClientPonyModel<S>, AbstractNpcRenderer<T, S>> clothing; private final NpcClothingFeature<T, S, ClientPonyModel<S>, AbstractNpcRenderer<T, S>> clothing;
private final Function<Race, Models<ClientPonyModel<S>>> models = Util.memoize(race -> {
public AbstractNpcRenderer(EntityRendererFactory.Context context, String type, TextureSupplier<T> textureSupplier, TextureSupplier<String> formatter) {
super(context, ModelType.getPlayerModel(Race.EARTH).getKey(false), SillyPonyTextureSupplier.create(textureSupplier, formatter));
clothing = new NpcClothingFeature<>(this, type);
this.manager.setModelsLookup(race -> {
if (race.isHuman()) { if (race.isHuman()) {
race = Race.EARTH; race = Race.EARTH;
} }
return ModelType.getPlayerModel(race).create(false, this::initializeModel); return ModelType.getPlayerModel(race).create(false, this::initializeModel);
}); });
public AbstractNpcRenderer(EntityRendererFactory.Context context, String type, TextureSupplier<T> textureSupplier, TextureSupplier<String> formatter) {
super(context, ModelType.getPlayerModel(Race.EARTH).getKey(false), SillyPonyTextureSupplier.create(textureSupplier, formatter));
clothing = new NpcClothingFeature<>(this, type);
this.manager.setModelsLookup(entity -> models.apply(entity.getRace()));
addFeature(clothing); addFeature(clothing);
} }

View file

@ -33,6 +33,7 @@ public class PonyRenderState extends PlayerEntityRenderState implements PonyMode
public Pony pony; public Pony pony;
public Size size; public Size size;
public Race race;
public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) { public void updateState(LivingEntity entity, PonyModel<?> model, Pony pony, ModelAttributes.Mode mode) {
this.pony = pony; this.pony = pony;
@ -45,7 +46,7 @@ public class PonyRenderState extends PlayerEntityRenderState implements PonyMode
isInSneakingPose = attributes.isCrouching && !attributes.isLyingDown; isInSneakingPose = attributes.isCrouching && !attributes.isLyingDown;
sleepingInBed = entity.getSleepingPosition().isPresent() && entity.getEntityWorld().getBlockState(entity.getSleepingPosition().get()).getBlock() instanceof BedBlock; sleepingInBed = entity.getSleepingPosition().isPresent() && entity.getEntityWorld().getBlockState(entity.getSleepingPosition().get()).getBlock() instanceof BedBlock;
submergedInWater = entity.isSubmergedInWater(); submergedInWater = entity.isSubmergedInWater();
wobbleAmount = handSwingProgress <= 0 ? 0 : MathHelper.sin(MathHelper.sqrt(getSwingAmount()) * MathHelper.PI * 2) * 0.04F; wobbleAmount = handSwingProgress <= 0 ? 0 : MathHelper.sin(MathHelper.sqrt(handSwingProgress) * MathHelper.PI * 2) * 0.04F;
if (attributes.isSitting) { if (attributes.isSitting) {
pose = EntityPose.SITTING; pose = EntityPose.SITTING;
} }
@ -57,23 +58,25 @@ public class PonyRenderState extends PlayerEntityRenderState implements PonyMode
) && entity.hasCustomName() && entity.getCustomName().getString().equalsIgnoreCase("technoblade") ) && entity.hasCustomName() && entity.getCustomName().getString().equalsIgnoreCase("technoblade")
); );
size = baby ? SizePreset.FOAL : PonyConfig.getEffectiveSize(attributes.metadata.size()); size = baby ? SizePreset.FOAL : PonyConfig.getEffectiveSize(attributes.metadata.size());
race = PonyConfig.getEffectiveRace(attributes.metadata.race());
PonyPosture.of(attributes).updateState(entity, this); PonyPosture.of(attributes).updateState(entity, this);
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(attributes, model, ModelAttributes.Mode.OTHER); PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(attributes, model, ModelAttributes.Mode.OTHER);
} }
@Override @Override
public Race getRace() { public final Race getRace() {
return PonyConfig.getEffectiveRace(attributes.metadata.race()); return race;
} }
public boolean hasMagicGlow() { public boolean hasMagicGlow() {
return getRace().hasHorn() && attributes.metadata.glowColor() != 0; return race.hasHorn() && attributes.metadata.glowColor() != 0;
} }
/** /**
* Gets the current leg swing amount. * Gets the current leg swing amount.
*/ */
@Override
public float getSwingAmount() { public float getSwingAmount() {
return this.handSwingProgress; return this.handSwingProgress;
} }
@ -101,15 +104,7 @@ public class PonyRenderState extends PlayerEntityRenderState implements PonyMode
* Tests if this model is wearing the given piece of gear. * Tests if this model is wearing the given piece of gear.
*/ */
public boolean isWearing(Wearable wearable) { public boolean isWearing(Wearable wearable) {
return isEmbedded(wearable) || attributes.featureSkins.contains(wearable.getId()) || isTechnoblade && wearable == Wearable.CROWN; return attributes.isEmbedded(wearable) || attributes.featureSkins.contains(wearable.getId()) || isTechnoblade && wearable == Wearable.CROWN;
}
/**
* Tests if the chosen piece of gear is sourcing its texture from the main skin.
* i.e. Used to change wing rendering when using saddlebags.
*/
public boolean isEmbedded(Wearable wearable) {
return attributes.metadata.gear().matches(wearable);
} }
private float getNamePlateYOffset(LivingEntity entity) { private float getNamePlateYOffset(LivingEntity entity) {