Villagers now use the same models as the player

This commit is contained in:
Sollace 2022-07-06 12:53:31 +02:00
parent aecc80669c
commit 5d15c64fa0
14 changed files with 131 additions and 180 deletions

View file

@ -13,6 +13,7 @@ import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer; import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.Vec3f; import net.minecraft.util.math.Vec3f;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Arm; import net.minecraft.util.Arm;
@ -80,6 +81,10 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
shakeBody(move, swing, getWobbleAmount(), ticks); shakeBody(move, swing, getWobbleAmount(), ticks);
rotateLegs(move, swing, ticks, entity); rotateLegs(move, swing, ticks, entity);
if (onSetModelAngles != null) {
onSetModelAngles.poseModel(this, move, swing, ticks, entity);
}
if (!attributes.isSwimming && !attributes.isGoingFast) { if (!attributes.isSwimming && !attributes.isGoingFast) {
holdItem(swing); holdItem(swing);
} }

View file

@ -2,10 +2,13 @@ package com.minelittlepony.client.model;
import net.minecraft.client.model.ModelPart; import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.entity.model.BipedEntityModel; import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.client.render.entity.model.ModelWithHat;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Arm; import net.minecraft.util.Arm;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.model.ModelAttributes; import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.model.fabric.PonyModelPrepareCallback; import com.minelittlepony.api.model.fabric.PonyModelPrepareCallback;
import com.minelittlepony.api.pony.IPony; import com.minelittlepony.api.pony.IPony;
@ -22,7 +25,7 @@ import com.minelittlepony.mson.api.model.biped.MsonPlayer;
* *
* Modders can extend this class to make their own pony models if they wish. * Modders can extend this class to make their own pony models if they wish.
*/ */
public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer<T> implements IPonyModel<T> { public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer<T> implements IPonyModel<T>, ModelWithHat {
/** /**
* The model attributes. * The model attributes.
@ -34,10 +37,17 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
*/ */
protected IPonyData metadata = PonyData.NULL; protected IPonyData metadata = PonyData.NULL;
@Nullable
protected PosingCallback<T> onSetModelAngles;
public ClientPonyModel(ModelPart tree) { public ClientPonyModel(ModelPart tree) {
super(tree); super(tree);
} }
public void onSetModelAngles(PosingCallback<T> callback) {
onSetModelAngles = callback;
}
protected Arm getPreferredArm(T livingEntity) { protected Arm getPreferredArm(T livingEntity) {
Arm arm = livingEntity.getMainArm(); Arm arm = livingEntity.getMainArm();
return livingEntity.preferredHand == Hand.MAIN_HAND ? arm : arm.getOpposite(); return livingEntity.preferredHand == Hand.MAIN_HAND ? arm : arm.getOpposite();
@ -114,4 +124,13 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
((ClientPonyModel<T>)model).metadata = metadata; ((ClientPonyModel<T>)model).metadata = metadata;
} }
} }
@Override
public void setHatVisible(boolean visible) {
}
public interface PosingCallback<T extends LivingEntity> {
void poseModel(ClientPonyModel<T> model, float move, float swing, float ticks, T entity);
}
} }

View file

@ -1,15 +1,16 @@
package com.minelittlepony.client.model; package com.minelittlepony.client.model;
import net.minecraft.client.model.ModelPart; import net.minecraft.client.model.ModelPart;
import net.minecraft.util.Arm;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.model.PonyModelConstants; import com.minelittlepony.api.model.PonyModelConstants;
import com.minelittlepony.mson.util.PartUtil;
/** /**
* Common interface for all undead enemies. * Common interface for all undead enemies.
*/ */
public interface IMobModel { public interface IMobModel {
/** /**
* Rotates the provided arm to the correct orientation for holding an item. * Rotates the provided arm to the correct orientation for holding an item.
* *
@ -18,7 +19,7 @@ public interface IMobModel {
* @param swingProgress How far we are through the current swing * @param swingProgress How far we are through the current swing
* @param ticks Render partial ticks * @param ticks Render partial ticks
*/ */
default void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) { static void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
float swing = MathHelper.sin(swingProgress * PonyModelConstants.PI); float swing = MathHelper.sin(swingProgress * PonyModelConstants.PI);
float roll = MathHelper.sin((1 - (1 - swingProgress) * (1 - swingProgress)) * PonyModelConstants.PI); float roll = MathHelper.sin((1 - (1 - swingProgress) * (1 - swingProgress)) * PonyModelConstants.PI);
@ -32,4 +33,21 @@ public interface IMobModel {
arm.yaw = direction * (0.1F - swing * 0.6F); arm.yaw = direction * (0.1F - swing * 0.6F);
arm.roll = cos; arm.roll = cos;
} }
static void rotateUndeadArms(ClientPonyModel<?> model, float move, float ticks) {
ModelPart leftArm = model.getArm(Arm.LEFT);
ModelPart rightArm = model.getArm(Arm.RIGHT);
if (islookAngleRight(move)) {
IMobModel.rotateArmHolding(rightArm, 1, model.getSwingAmount(), ticks);
PartUtil.shift(rightArm, 0.5F, 1.5F, 3);
} else {
IMobModel.rotateArmHolding(leftArm, -1, model.getSwingAmount(), ticks);
PartUtil.shift(leftArm, -0.5F, 1.5F, 3);
}
}
static boolean islookAngleRight(float move) {
return MathHelper.sin(move / 20) < 0;
}
} }

View file

@ -5,8 +5,7 @@ import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.entity.model.ArmorStandEntityModel; import net.minecraft.client.render.entity.model.ArmorStandEntityModel;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.VexEntity; import net.minecraft.entity.mob.VexEntity;
import net.minecraft.entity.passive.AllayEntity; import net.minecraft.entity.passive.*;
import net.minecraft.entity.passive.StriderEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.gear.IGear; import com.minelittlepony.api.model.gear.IGear;
@ -36,11 +35,9 @@ public final class ModelType {
public static final ModelKey<DJPon3EarsModel> DJ_PON_3 = register("dj_pon_three", DJPon3EarsModel::new); public static final ModelKey<DJPon3EarsModel> DJ_PON_3 = register("dj_pon_three", DJPon3EarsModel::new);
public static final ModelKey<VillagerPonyModel<?>> VILLAGER = register("villager", VillagerPonyModel::new);
public static final ModelKey<WitchPonyModel> WITCH = register("witch", WitchPonyModel::new); public static final ModelKey<WitchPonyModel> WITCH = register("witch", WitchPonyModel::new);
public static final ModelKey<ZomponyModel<?>> ZOMBIE = register("zombie", ZomponyModel::new); public static final ModelKey<ZomponyModel<?>> ZOMBIE = register("zombie", ZomponyModel::new);
public static final ModelKey<PiglinPonyModel> PIGLIN = register("piglin", PiglinPonyModel::new); public static final ModelKey<PiglinPonyModel> PIGLIN = register("piglin", PiglinPonyModel::new);
public static final ModelKey<ZomponyVillagerModel> ZOMBIE_VILLAGER = register("zombie_villager", ZomponyVillagerModel::new);
public static final ModelKey<SkeleponyModel<?>> SKELETON = register("skeleton", SkeleponyModel::new); public static final ModelKey<SkeleponyModel<?>> SKELETON = register("skeleton", SkeleponyModel::new);
public static final ModelKey<SkeleponyModel<?>> SKELETON_CLOTHES = register("skeleton_clothes", SkeleponyModel::new); public static final ModelKey<SkeleponyModel<?>> SKELETON_CLOTHES = register("skeleton_clothes", SkeleponyModel::new);
public static final ModelKey<PillagerPonyModel<?>> PILLAGER = register("pillager", PillagerPonyModel::new); public static final ModelKey<PillagerPonyModel<?>> PILLAGER = register("pillager", PillagerPonyModel::new);

View file

@ -2,12 +2,16 @@ package com.minelittlepony.client.model;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.model.IModel; import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.IModelWrapper; import com.minelittlepony.api.model.IModelWrapper;
import com.minelittlepony.api.model.armour.IArmour; import com.minelittlepony.api.model.armour.IArmour;
import com.minelittlepony.api.pony.IPonyData; import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.mson.api.ModelKey; import com.minelittlepony.mson.api.ModelKey;
import java.util.function.Consumer;
/** /**
* Container class for the various models and their associated piece of armour. * Container class for the various models and their associated piece of armour.
*/ */
@ -19,8 +23,13 @@ public record ModelWrapper<T extends LivingEntity, M extends IModel> (
* Creates a new model wrapper to contain the given pony. * Creates a new model wrapper to contain the given pony.
*/ */
public static <T extends LivingEntity, M extends IModel> ModelWrapper<T, M> of(ModelKey<?> key) { public static <T extends LivingEntity, M extends IModel> ModelWrapper<T, M> of(ModelKey<?> key) {
return of(key, null);
}
public static <T extends LivingEntity, M extends IModel> ModelWrapper<T, M> of(ModelKey<?> key, @Nullable Consumer<M> initializer) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
M body = (M)key.createModel(); M body = (M)key.createModel();
if (initializer != null) initializer.accept(body);
IArmour<?> armor = body.createArmour(); IArmour<?> armor = body.createArmour();
armor.applyMetadata(body.getMetadata()); armor.applyMetadata(body.getMetadata());
return new ModelWrapper<>(body, armor); return new ModelWrapper<>(body, armor);

View file

@ -73,6 +73,10 @@ public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> imp
} }
} }
protected void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
IMobModel.rotateArmHolding(arm, direction, swingProgress, ticks);
}
@Override @Override
public boolean canCast() { public boolean canCast() {
return isUnicorn; return isUnicorn;

View file

@ -1,95 +0,0 @@
package com.minelittlepony.client.model.entity;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.entity.model.ModelWithHat;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.passive.MerchantEntity;
import net.minecraft.util.math.MathHelper;
import net.minecraft.village.VillagerDataContainer;
import net.minecraft.village.VillagerProfession;
import com.minelittlepony.api.model.IPart;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.model.entity.race.AlicornModel;
import com.minelittlepony.client.render.entity.npc.PonyTextures;
import com.minelittlepony.mson.api.ModelContext;
public class VillagerPonyModel<T extends LivingEntity & VillagerDataContainer> extends AlicornModel<T> implements ModelWithHat {
private final ModelPart apron;
private IPart batWings;
private IPart batEars;
public VillagerPonyModel(ModelPart tree) {
super(tree, false);
apron = tree.getChild("apron");
}
@Override
public void init(ModelContext context) {
super.init(context);
batWings = context.findByName("bat_wings");
batEars = context.findByName("bat_ears");
}
@Override
public void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode) {
super.updateLivingState(entity, pony, mode);
ears.setVisible(pony.getMetadata().getRace() != Race.BATPONY);
batEars.setVisible(pony.getMetadata().getRace() == Race.BATPONY);
}
@Override
public IPart getWings() {
if (getMetadata().getRace() == Race.BATPONY) {
return batWings;
}
return super.getWings();
}
@Override
protected void shakeBody(float move, float swing, float bodySwing, float ticks) {
super.shakeBody(move, swing, bodySwing, ticks);
apron.yaw = bodySwing;
}
@Override
public void animateModel(T entity, float limbSwing, float limbSwingAmount, float partialTickTime) {
boolean special = PonyTextures.isBestPony(entity);
VillagerProfession profession = entity.getVillagerData().getProfession();
attributes.visualHeight += PonyTextures.isCrownPony(entity) ? 0.3F : -0.1F;
apron.visible = !special && profession == VillagerProfession.BUTCHER;
}
@Override
protected void renderBody(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha) {
super.renderBody(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
apron.render(stack, vertices, overlayUv, lightUv, red, green, blue, alpha);
}
@Override
public void setHatVisible(boolean visible) {
}
@Override
public void setModelAngles(T entity, float move, float swing, float ticks, float headYaw, float headPitch) {
super.setModelAngles(entity, move, swing, ticks, headYaw, headPitch);
boolean isHeadRolling = entity instanceof MerchantEntity && ((MerchantEntity)entity).getHeadRollingTimeLeft() > 0;
if (isHeadRolling) {
head.roll = 0.3F * MathHelper.sin(0.45F * ticks);
head.pitch = 0.4F;
} else {
head.roll = 0;
}
}
}

View file

@ -2,11 +2,8 @@ package com.minelittlepony.client.model.entity;
import com.minelittlepony.client.model.IMobModel; import com.minelittlepony.client.model.IMobModel;
import com.minelittlepony.client.model.entity.race.AlicornModel; import com.minelittlepony.client.model.entity.race.AlicornModel;
import com.minelittlepony.mson.util.PartUtil;
import net.minecraft.client.model.ModelPart; import net.minecraft.client.model.ModelPart;
import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.util.math.MathHelper;
public class ZomponyModel<Zombie extends HostileEntity> extends AlicornModel<Zombie> implements IMobModel { public class ZomponyModel<Zombie extends HostileEntity> extends AlicornModel<Zombie> implements IMobModel {
@ -25,28 +22,17 @@ public class ZomponyModel<Zombie extends HostileEntity> extends AlicornModel<Zom
@Override @Override
protected void rotateLegs(float move, float swing, float ticks, Zombie entity) { protected void rotateLegs(float move, float swing, float ticks, Zombie entity) {
super.rotateLegs(move, swing, ticks, entity); super.rotateLegs(move, swing, ticks, entity);
if (isZombified(entity)) { if (isZombified(entity)) {
if (islookAngleRight(move)) { IMobModel.rotateUndeadArms(this, move, ticks);
rotateArmHolding(rightArm, 1, getSwingAmount(), ticks);
PartUtil.shift(rightArm, 0.5F, 1.5F, 3);
} else {
rotateArmHolding(leftArm, -1, getSwingAmount(), ticks);
PartUtil.shift(leftArm, -0.5F, 1.5F, 3);
}
} }
} }
protected boolean isZombified(Zombie entity) {
return rightArmPose == ArmPose.EMPTY;
}
public boolean islookAngleRight(float move) {
return MathHelper.sin(move / 20) < 0;
}
@Override @Override
public boolean canFly() { public boolean canFly() {
return isPegasus; return isPegasus;
} }
protected boolean isZombified(Zombie entity) {
return rightArmPose == ArmPose.EMPTY;
}
} }

View file

@ -1,34 +0,0 @@
package com.minelittlepony.client.model.entity;
import net.minecraft.client.model.ModelPart;
import net.minecraft.entity.mob.ZombieVillagerEntity;
import net.minecraft.util.math.MathHelper;
import com.minelittlepony.client.model.IMobModel;
import com.minelittlepony.mson.util.PartUtil;
public class ZomponyVillagerModel extends VillagerPonyModel<ZombieVillagerEntity> implements IMobModel {
public ZomponyVillagerModel(ModelPart tree) {
super(tree);
}
@Override
protected void rotateLegs(float move, float swing, float ticks, ZombieVillagerEntity entity) {
super.rotateLegs(move, swing, ticks, entity);
if (rightArmPose == ArmPose.EMPTY) {
if (islookAngleRight(move)) {
rotateArmHolding(rightArm, 1, getSwingAmount(), ticks);
PartUtil.shift(rightArm, 0.5F, 1.5F, 3);
} else {
rotateArmHolding(leftArm, -1, getSwingAmount(), ticks);
PartUtil.shift(leftArm, -0.5F, 1.5F, 3);
}
}
}
public boolean islookAngleRight(float move) {
return MathHelper.sin(move / 20) < 0;
}
}

View file

@ -80,7 +80,7 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
return rotationYaw; return rotationYaw;
} }
protected void translateRider(T entity, MatrixStack stack, float ticks) { private void translateRider(T entity, MatrixStack stack, float ticks) {
if (entity.hasVehicle() && entity.getVehicle() instanceof LivingEntity) { if (entity.hasVehicle() && entity.getVehicle() instanceof LivingEntity) {
LivingEntity ridingEntity = (LivingEntity) entity.getVehicle(); LivingEntity ridingEntity = (LivingEntity) entity.getVehicle();
@ -137,8 +137,7 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
} }
public ModelWrapper<T, M> setModel(ModelKey<?> key) { public ModelWrapper<T, M> setModel(ModelKey<?> key) {
playerModel = ModelWrapper.of(key); return setModel(ModelWrapper.of(key));
return playerModel;
} }
public ModelWrapper<T, M> setModel(ModelWrapper<T, M> wrapper) { public ModelWrapper<T, M> setModel(ModelWrapper<T, M> wrapper) {

View file

@ -1,6 +1,5 @@
package com.minelittlepony.client.render.entity; package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.model.IUnicorn;
import com.minelittlepony.api.pony.IPony; import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.client.MineLittlePony; import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ClientPonyModel; import com.minelittlepony.client.model.ClientPonyModel;
@ -127,7 +126,7 @@ public abstract class PonyRenderer<T extends MobEntity, M extends EntityModel<T>
return MineLittlePony.getInstance().getManager().getPony(findTexture(entity)); return MineLittlePony.getInstance().getManager().getPony(findTexture(entity));
} }
public abstract static class Caster<T extends MobEntity, M extends ClientPonyModel<T> & IUnicorn> extends PonyRenderer<T, M> { public abstract static class Caster<T extends MobEntity, M extends ClientPonyModel<T>> extends PonyRenderer<T, M> {
public Caster(EntityRendererFactory.Context context, ModelKey<? super M> key) { public Caster(EntityRendererFactory.Context context, ModelKey<? super M> key) {
super(context, key); super(context, key);

View file

@ -1,37 +1,38 @@
package com.minelittlepony.client.render.entity.npc; package com.minelittlepony.client.render.entity.npc;
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.model.ModelWithHat; import net.minecraft.client.util.math.MatrixStack;
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.village.VillagerDataContainer; import net.minecraft.village.VillagerDataContainer;
import net.minecraft.village.VillagerProfession; import net.minecraft.village.VillagerProfession;
import com.minelittlepony.api.model.IUnicorn;
import com.minelittlepony.api.model.gear.IGear; import com.minelittlepony.api.model.gear.IGear;
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.ClientPonyModel; import com.minelittlepony.client.model.*;
import com.minelittlepony.client.render.entity.PonyRenderer; import com.minelittlepony.client.render.entity.PonyRenderer;
import com.minelittlepony.mson.api.ModelKey; import java.util.HashMap;
import java.util.Map;
abstract class AbstractNpcRenderer< abstract class AbstractNpcRenderer<T extends MobEntity & VillagerDataContainer> extends PonyRenderer.Caster<T, ClientPonyModel<T>> {
T extends MobEntity & VillagerDataContainer,
M extends ClientPonyModel<T> & IUnicorn & ModelWithHat> extends PonyRenderer.Caster<T, M> {
private final TextureSupplier<T> baseTextures; private final TextureSupplier<T> baseTextures;
private final String entityType; private final String entityType;
public AbstractNpcRenderer(EntityRendererFactory.Context context, ModelKey<? super M> key, String type, TextureSupplier<String> formatter) { private final Map<Race, ModelWrapper<T, ClientPonyModel<T>>> models = new HashMap<>();
super(context, key);
public AbstractNpcRenderer(EntityRendererFactory.Context context, String type, TextureSupplier<String> formatter) {
super(context, ModelType.getPlayerModel(Race.EARTH).getKey(false));
entityType = type; entityType = type;
baseTextures = new PonyTextures<>(formatter); baseTextures = new PonyTextures<>(formatter);
addFeature(new NpcClothingFeature<>(this, entityType)); addFeature(new NpcClothingFeature<>(this, entityType));
} }
@Override @Override
public boolean shouldRender(M model, T entity, Wearable wearable, IGear gear) { public boolean shouldRender(ClientPonyModel<T> model, T entity, Wearable wearable, IGear gear) {
boolean special = PonyTextures.isBestPony(entity); boolean special = PonyTextures.isBestPony(entity);
@ -52,6 +53,20 @@ abstract class AbstractNpcRenderer<
return super.shouldRender(model, entity, wearable, gear); return super.shouldRender(model, entity, wearable, gear);
} }
public void render(T entity, float entityYaw, float tickDelta, MatrixStack stack, VertexConsumerProvider renderContext, int lightUv) {
model = manager.setModel(models.computeIfAbsent(getEntityPony(entity).getRace(false), this::createModel)).body();
super.render(entity, entityYaw, tickDelta, stack, renderContext, lightUv);
}
private ModelWrapper<T, ClientPonyModel<T>> createModel(Race race) {
return ModelWrapper.<T, ClientPonyModel<T>>of(ModelType.getPlayerModel(race).getKey(false), this::initializeModel);
}
protected void initializeModel(ClientPonyModel<T> model) {
}
@Override @Override
public Identifier getDefaultTexture(T villager, Wearable wearable) { public Identifier getDefaultTexture(T villager, Wearable wearable) {
if (wearable == Wearable.SADDLE_BAGS) { if (wearable == Wearable.SADDLE_BAGS) {

View file

@ -1,19 +1,36 @@
package com.minelittlepony.client.render.entity.npc; package com.minelittlepony.client.render.entity.npc;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.VillagerPonyModel;
import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.passive.MerchantEntity;
import net.minecraft.entity.passive.VillagerEntity; import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.util.math.MathHelper;
public class VillagerPonyRenderer extends AbstractNpcRenderer<VillagerEntity, VillagerPonyModel<VillagerEntity>> { import com.minelittlepony.client.model.ClientPonyModel;
public class VillagerPonyRenderer extends AbstractNpcRenderer<VillagerEntity> {
private static final String TYPE = "villager"; private static final String TYPE = "villager";
private static final TextureSupplier<String> FORMATTER = TextureSupplier.formatted("minelittlepony", "textures/entity/villager/%s.png"); private static final TextureSupplier<String> FORMATTER = TextureSupplier.formatted("minelittlepony", "textures/entity/villager/%s.png");
public VillagerPonyRenderer(EntityRendererFactory.Context context) { public VillagerPonyRenderer(EntityRendererFactory.Context context) {
super(context, ModelType.VILLAGER, TYPE, FORMATTER); super(context, TYPE, FORMATTER);
}
@Override
protected void initializeModel(ClientPonyModel<VillagerEntity> model) {
model.onSetModelAngles((m, move, swing, ticks, entity) -> {
m.getAttributes().visualHeight += PonyTextures.isCrownPony(entity) ? 0.3F : -0.1F;
boolean isHeadRolling = entity instanceof MerchantEntity && ((MerchantEntity)entity).getHeadRollingTimeLeft() > 0;
if (isHeadRolling) {
m.head.roll = 0.3F * MathHelper.sin(0.45F * ticks);
m.head.pitch = 0.4F;
} else {
m.head.roll = 0;
}
});
} }
@Override @Override

View file

@ -1,19 +1,31 @@
package com.minelittlepony.client.render.entity.npc; package com.minelittlepony.client.render.entity.npc;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.entity.ZomponyVillagerModel;
import net.minecraft.client.render.entity.EntityRendererFactory; import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.model.BipedEntityModel.ArmPose;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.mob.ZombieVillagerEntity; import net.minecraft.entity.mob.ZombieVillagerEntity;
public class ZomponyVillagerRenderer extends AbstractNpcRenderer<ZombieVillagerEntity, ZomponyVillagerModel> { import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.client.model.IMobModel;
public class ZomponyVillagerRenderer extends AbstractNpcRenderer<ZombieVillagerEntity> {
private static final String TYPE = "zombie_villager"; private static final String TYPE = "zombie_villager";
private static final TextureSupplier<String> FORMATTER = TextureSupplier.formatted("minelittlepony", "textures/entity/zombie_villager/zombie_%s.png"); private static final TextureSupplier<String> FORMATTER = TextureSupplier.formatted("minelittlepony", "textures/entity/zombie_villager/zombie_%s.png");
public ZomponyVillagerRenderer(EntityRendererFactory.Context context) { public ZomponyVillagerRenderer(EntityRendererFactory.Context context) {
super(context, ModelType.ZOMBIE_VILLAGER, TYPE, FORMATTER); super(context, TYPE, FORMATTER);
}
@Override
protected void initializeModel(ClientPonyModel<ZombieVillagerEntity> model) {
model.onSetModelAngles((m, move, swing, ticks, entity) -> {
m.getAttributes().visualHeight += PonyTextures.isCrownPony(entity) ? 0.3F : -0.1F;
if (m.rightArmPose == ArmPose.EMPTY) {
IMobModel.rotateUndeadArms(m, move, ticks);
}
});
} }
@Override @Override