Rewrite pretty much everything to make more effective use of java's Records

This commit is contained in:
Sollace 2023-09-25 21:07:09 +01:00
parent 8eca1796e1
commit 0d226b51f9
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
110 changed files with 821 additions and 1142 deletions

View file

@ -2,8 +2,7 @@ package com.minelittlepony.api.config;
import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.Sizes;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.common.util.GamePaths;
import com.minelittlepony.common.util.settings.*;
@ -131,4 +130,18 @@ public class PonyConfig extends Config {
return race;
}
public static Size getEffectiveSize(Size size) {
Sizes sz = instance.sizeOverride.get();
if (sz != Sizes.UNSET) {
return sz;
}
if (size == Sizes.UNSET || !instance.sizes.get()) {
return Sizes.NORMAL;
}
return size;
}
}

View file

@ -0,0 +1,17 @@
package com.minelittlepony.api.model;
import net.minecraft.entity.LivingEntity;
public interface HornedPonyModel<T extends LivingEntity> extends PonyModel<T> {
/**
* Returns true if this model is being applied to a race that can use magic.
*/
default boolean hasMagic() {
return getRace().hasHorn() && getAttributes().metadata.glowColor() != 0;
}
/**
* Returns true if this model is currently using magic (horn is lit).
*/
boolean isCasting();
}

View file

@ -1,11 +0,0 @@
package com.minelittlepony.api.model;
/**
* Interface for models that have a head.
*/
public interface ICapitated<T> {
/**
* Gets the head of this capitated object.
*/
T getHead();
}

View file

@ -1,10 +1,10 @@
package com.minelittlepony.api.model;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.PonyData;
public interface IModelWrapper {
/**
* Updates metadata values to this wrapper's contained models.
*/
IModelWrapper applyMetadata(IPonyData meta);
IModelWrapper applyMetadata(PonyData meta);
}

View file

@ -1,30 +0,0 @@
package com.minelittlepony.api.model;
public interface IUnicorn extends IModel {
/**
* Returns true if this model is being applied to a race that can use magic.
*/
default boolean hasMagic() {
return hasHorn() && getMagicColor() != 0;
}
/**
* Returns true if this model has an visible horns.
*/
default boolean hasHorn() {
return getRace().hasHorn();
}
/**
* Returns true if this model is currently using magic (horn is lit).
* @return
*/
boolean isCasting();
/**
* Gets the preferred magic color for this mode.
*/
default int getMagicColor() {
return getMetadata().glowColor();
}
}

View file

@ -1,15 +1,16 @@
package com.minelittlepony.client.model;
package com.minelittlepony.api.model;
import net.minecraft.client.model.ModelPart;
import net.minecraft.util.Arm;
import net.minecraft.util.math.MathHelper;
import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.mson.util.PartUtil;
/**
* Common interface for all undead enemies.
*/
public interface IMobModel {
public final class MobPosingHelper {
/**
* 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 ticks Render partial ticks
*/
static void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
public static void rotateArmHolding(ModelPart arm, float direction, float swingProgress, float ticks) {
float swing = MathHelper.sin(swingProgress * MathHelper.PI);
float roll = MathHelper.sin((1 - (1 - swingProgress) * (1 - swingProgress)) * MathHelper.PI);
@ -33,20 +34,20 @@ public interface IMobModel {
arm.roll = cos;
}
static void rotateUndeadArms(ClientPonyModel<?> model, float move, float ticks) {
public 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);
rotateArmHolding(rightArm, 1, model.getSwingAmount(), ticks);
PartUtil.shift(rightArm, 0.5F, 1.5F, 3);
} else {
IMobModel.rotateArmHolding(leftArm, -1, model.getSwingAmount(), ticks);
rotateArmHolding(leftArm, -1, model.getSwingAmount(), ticks);
PartUtil.shift(leftArm, -0.5F, 1.5F, 3);
}
}
static boolean islookAngleRight(float move) {
public static boolean islookAngleRight(float move) {
return MathHelper.sin(move / 20) < 0;
}
}

View file

@ -2,7 +2,6 @@ package com.minelittlepony.api.model;
import com.minelittlepony.api.pony.*;
import com.minelittlepony.client.*;
import com.minelittlepony.client.pony.PonyData;
import com.minelittlepony.common.util.animation.Interpolator;
import com.minelittlepony.util.MathUtil;
@ -108,7 +107,7 @@ public class ModelAttributes {
/**
* Contains the skin metadata associated with this model.
*/
public IPonyData metadata = PonyData.NULL;
public PonyData metadata = PonyData.NULL;
public Arm mainArm;
public Hand activeHand;
@ -118,11 +117,11 @@ public class ModelAttributes {
/**
* Checks flying and speed conditions and sets rainboom to true if we're a species with wings and is going faaast.
*/
public void checkRainboom(LivingEntity entity, boolean hasWings, float ticks) {
public void checkRainboom(LivingEntity entity, PonyModel<?> model, float ticks) {
Vec3d motion = entity.getVelocity();
double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
isGoingFast = (isFlying && hasWings) || isGliding;
isGoingFast = (isFlying && model instanceof WingedPonyModel) || isGliding;
isGoingFast &= zMotion > 0.4F;
isGoingFast |= entity.isUsingRiptide();
isGoingFast |= entity.isFallFlying();
@ -137,12 +136,12 @@ public class ModelAttributes {
return (MathHelper.sin(ticks * 0.136f) / 2) + MathUtil.Angles._270_DEG;
}
if (isFlying) {
return MathHelper.sin(ticks * 0.536f) + IPegasus.WINGS_FULL_SPREAD_ANGLE;
return MathHelper.sin(ticks * 0.536f) + WingedPonyModel.WINGS_FULL_SPREAD_ANGLE;
}
return IPegasus.WINGS_RAISED_ANGLE;
return WingedPonyModel.WINGS_RAISED_ANGLE;
}
public void updateLivingState(LivingEntity entity, IPony pony, Mode mode) {
public void updateLivingState(LivingEntity entity, Pony pony, Mode mode) {
visualHeight = entity.getHeight() + 0.125F;
isSitting = PonyPosture.isSitting(entity);
isCrouching = !isSitting && mode == Mode.THIRD_PERSON && PonyPosture.isCrouching(pony, entity);
@ -153,7 +152,7 @@ public class ModelAttributes {
isSwimmingRotated = isSwimming;
isRiptide = entity.isUsingRiptide();
isRidingInteractive = PonyPosture.isRidingAPony(entity);
if (!(entity instanceof IPreviewModel)) {
if (!(entity instanceof PreviewModel)) {
interpolatorId = entity.getUuid();
}
isLeftHanded = entity.getMainArm() == Arm.LEFT;

View file

@ -1,66 +1,49 @@
package com.minelittlepony.api.model;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.entity.model.*;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.mson.api.MsonModel;
public interface PonyModel<T extends LivingEntity> extends MsonModel, ModelWithArms, ModelWithHat, ModelWithHead {
void copyAttributes(BipedEntityModel<T> other);
void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode);
ModelPart getBodyPart(BodyPart part);
public interface IModel {
/**
* Applies a transform particular to a certain body part.
*/
void transform(BodyPart part, MatrixStack stack);
/**
* Gets the active scaling profile used to lay out this model's parts.
*/
Size getSize();
/**
* Gets the transitive properties of this model.
*/
ModelAttributes getAttributes();
/**
* Gets the skin metadata associated with this model.
*/
default IPonyData getMetadata() {
return getAttributes().metadata;
}
/**
* Sets the pony metadata object associated with this model.
*/
void setMetadata(IPonyData meta);
void setMetadata(PonyData meta);
/**
* Returns true if the model is flying.
* Gets the active scaling profile used to lay out this model's parts.
*/
default boolean isFlying() {
return getAttributes().isFlying && canFly();
}
/**
* Returns true if this model is riding a boat, horse, or other animals.
*
* @deprecated User model#getAttributes().isSitting
*/
@Deprecated
default boolean isRiding() {
return getAttributes().isSitting;
default Size getSize() {
return PonyConfig.getEffectiveSize(getAttributes().metadata.size());
}
default Race getRace() {
return PonyConfig.getEffectiveRace(getMetadata().race());
}
/**
* Returns true if this model is being applied to a race that has wings.
*/
default boolean canFly() {
return getRace().hasWings();
return PonyConfig.getEffectiveRace(getAttributes().metadata.race());
}
/**
@ -72,7 +55,6 @@ public interface IModel {
* Gets the step wobble used for various hair bits and animations.
*/
default float getWobbleAmount() {
if (getSwingAmount() <= 0) {
return 0;
}
@ -97,6 +79,7 @@ public interface IModel {
* i.e. Used to change wing rendering when using saddlebags.
*/
default boolean isEmbedded(Wearable wearable) {
return getMetadata().isWearing(wearable);
return getAttributes().metadata.isWearing(wearable);
}
}

View file

@ -1,10 +1,12 @@
package com.minelittlepony.api.model;
import net.minecraft.entity.LivingEntity;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.util.MathUtil;
public interface IPegasus extends IModel {
public interface WingedPonyModel<T extends LivingEntity> extends PonyModel<T> {
public static final float WINGS_HALF_SPREAD_ANGLE = MathUtil.Angles._270_DEG;
public static final float WINGS_FULL_SPREAD_ANGLE = MathUtil.Angles._270_DEG + 0.4F;
public static final float WINGS_RAISED_ANGLE = 4;
@ -13,12 +15,14 @@ public interface IPegasus extends IModel {
* Returns true if the wings are spread.
*/
default boolean wingsAreOpen() {
return (getAttributes().isSwimming || isFlying() || getAttributes().isCrouching)
return (getAttributes().isSwimming || getAttributes().isFlying || getAttributes().isCrouching)
&& (MineLittlePony.getInstance().getConfig().flappyElytras.get() || !getAttributes().isGliding);
}
default boolean isBurdened() {
return isWearing(Wearable.SADDLE_BAGS_BOTH) || isWearing(Wearable.SADDLE_BAGS_LEFT) || isWearing(Wearable.SADDLE_BAGS_RIGHT);
return isWearing(Wearable.SADDLE_BAGS_BOTH)
|| isWearing(Wearable.SADDLE_BAGS_LEFT)
|| isWearing(Wearable.SADDLE_BAGS_RIGHT);
}
/**

View file

@ -3,7 +3,7 @@ package com.minelittlepony.api.model.armour;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.api.model.PonyModel;
public interface IArmourModel<T extends LivingEntity> {
/**
@ -13,5 +13,5 @@ public interface IArmourModel<T extends LivingEntity> {
*/
boolean poseModel(T entity, float limbAngle, float limbDistance, float age, float headYaw, float headPitch,
EquipmentSlot slot, ArmourLayer layer,
IPonyModel<T> mainModel);
PonyModel<T> mainModel);
}

View file

@ -4,7 +4,7 @@ import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.Entity;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.ModelAttributes;
public interface PonyModelPrepareCallback {
@ -15,5 +15,5 @@ public interface PonyModelPrepareCallback {
}
});
void onPonyModelPrepared(Entity entity, IModel model, ModelAttributes.Mode mode);
void onPonyModelPrepared(Entity entity, PonyModel<?> model, ModelAttributes.Mode mode);
}

View file

@ -1,4 +1,4 @@
package com.minelittlepony.client.model.gear;
package com.minelittlepony.api.model.gear;
import net.minecraft.client.model.Model;
import net.minecraft.client.model.ModelPart;
@ -6,22 +6,24 @@ import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import com.minelittlepony.api.model.gear.IGear;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
public abstract class AbstractGear extends Model implements IGear {
public abstract class AbstractGearModel extends Model implements Gear {
private final List<ModelPart> parts = new ArrayList<>();
public AbstractGear() {
private final float stackingHeight;
public AbstractGearModel(float stackingHeight) {
super(RenderLayer::getEntitySolid);
this.stackingHeight = stackingHeight;
}
public void addPart(ModelPart t) {
public AbstractGearModel addPart(ModelPart t) {
parts.add(t);
return this;
}
@Override
@ -35,4 +37,14 @@ public abstract class AbstractGear extends Model implements IGear {
part.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
});
}
@Override
public boolean isStackable() {
return stackingHeight > 0;
}
@Override
public float getStackingHeight() {
return stackingHeight;
}
}

View file

@ -7,10 +7,8 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.render.entity.feature.GearFeature;
import java.util.UUID;
@ -19,13 +17,13 @@ import java.util.function.Supplier;
/**
* Interface for an accessory on a pony's body.
*/
public interface IGear {
public interface Gear {
/**
* Registers a custom gear to be used with the mod.
* <p>
* This would be awesome for creating socks.
*/
static Supplier<IGear> register(Supplier<IGear> gear) {
static Supplier<Gear> register(Supplier<Gear> gear) {
GearFeature.addModGear(gear);
return gear;
}
@ -38,13 +36,26 @@ public interface IGear {
*
* @return True to render this wearable
*/
boolean canRender(IModel model, Entity entity);
boolean canRender(PonyModel<?> model, Entity entity);
/**
* Gets the body location that this wearable appears on.
*/
BodyPart getGearLocation();
default boolean isStackable() {
return false;
}
/**
* The vertical height of this gear when present in a stack.
*
* Any gear rendered after this one will be shifted to sit on top of it.
*/
default float getStackingHeight() {
return 0;
}
/**
* Gets the texture to use for this wearable.
*
@ -62,7 +73,7 @@ public interface IGear {
/**
* Applies body transformations for this wearable
*/
default <M extends EntityModel<?> & IPonyModel<?>> void transform(M model, MatrixStack matrices) {
default <M extends EntityModel<?> & PonyModel<?>> void transform(M model, MatrixStack matrices) {
BodyPart part = getGearLocation();
model.transform(part, matrices);
model.getBodyPart(part).rotate(matrices);
@ -73,23 +84,10 @@ public interface IGear {
*
* See {@link AbstractPonyMode.setRotationAndAngle} for an explanation of the various parameters.
*/
default void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
setModelAttributes(model, entity);
pose(rainboom, interpolatorId, move, swing, bodySwing, ticks);
default void pose(PonyModel<?> model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
}
/**
* @deprecated Use pose(model, entity, rainboom, interpolatorId, move, swing, bodySwing, ticks) instead
*/
@Deprecated(forRemoval = true)
default void setModelAttributes(IModel model, Entity entity) { }
/**
* @deprecated Use pose(model, entity, rainboom, interpolatorId, move, swing, bodySwing, ticks) instead
*/
@Deprecated(forRemoval = true)
default void pose(boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) { }
/**
* Renders this model component.
*/
@ -101,7 +99,7 @@ public interface IGear {
* @param <T> The type of entity being rendered.
* @param <M> The type of the entity's primary model.
*/
public interface Context<T extends Entity, M extends IModel> {
public interface Context<T extends Entity, M extends PonyModel<?>> {
/**
* The empty context.
*/
@ -110,7 +108,7 @@ public interface IGear {
/**
* Checks whether the given wearable and gear are able to render for this specific entity and its renderer.
*/
default boolean shouldRender(M model, T entity, Wearable wearable, IGear gear) {
default boolean shouldRender(M model, T entity, Wearable wearable, Gear gear) {
return gear.canRender(model, entity);
}

View file

@ -1,14 +0,0 @@
package com.minelittlepony.api.model.gear;
/**
* Interface for any gear that changes its position based on where it is in the hat stack.
*/
public interface IStackable {
/**
* The vertical height of this gear when present in a stack.
*
* Any gear rendered after this one will be shifted to sit on top of it.
*/
float getStackingHeight();
}

View file

@ -1,18 +1,19 @@
package com.minelittlepony.client.model.gear;
package com.minelittlepony.api.model.gear;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.meta.Wearable;
public abstract class AbstractWearableGear extends AbstractGear {
public class WearableGear extends AbstractGearModel {
protected final Wearable wearable;
protected final BodyPart location;
protected AbstractWearableGear(Wearable wearable, BodyPart location) {
public WearableGear(Wearable wearable, BodyPart location, float stackingHeight) {
super(stackingHeight);
this.wearable = wearable;
this.location = location;
}
@ -23,7 +24,7 @@ public abstract class AbstractWearableGear extends AbstractGear {
}
@Override
public boolean canRender(IModel model, Entity entity) {
public boolean canRender(PonyModel<?> model, Entity entity) {
return model.isWearing(wearable);
}

View file

@ -28,7 +28,7 @@ public final class DefaultPonySkinHelper {
public static String getModelType(UUID id) {
SkinTextures textures = DefaultSkinHelper.getTexture(id);
return getModelType(IPony.getManager().getPony(textures.texture(), id).race(), textures.model());
return getModelType(Pony.getManager().getPony(textures.texture(), id).race(), textures.model());
}
public static String getModelType(Race race, SkinTextures.Model armShape) {

View file

@ -1,82 +0,0 @@
package com.minelittlepony.api.pony;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ComparisonChain;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.common.util.animation.Interpolator;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
/**
* Metadata for a pony.
*/
public interface IPonyData extends Comparable<IPonyData> {
/**
* Gets this pony's race.
*
* This is the actual race value. For the effective race, prefer going through {@link IPony#race}
*/
Race race();
/**
* Gets the length of the pony's tail.
*/
TailLength tailLength();
/**
* Gets the shape of the pony's tail.
*/
TailShape tailShape();
/**
* Get the pony's gender (usually female).
*/
Gender gender();
/**
* Gets the current pony size.
*/
Size size();
/**
* Gets the magical glow colour for magic-casting races. Returns 0 otherwise.
*/
int glowColor();
/**
* Returns an array of wearables that this pony is carrying.
*/
Wearable[] gear();
/**
* Checks it this pony is wearing the given accessory.
*/
boolean isWearing(Wearable wearable);
/**
* Gets an interpolator for interpolating values.
*/
default Interpolator getInterpolator(UUID interpolatorId) {
return Interpolator.linear(interpolatorId);
}
/**
* Gets the trigger pixel values as they appeared in the underlying image.
*/
Map<String, TriggerPixelType<?>> attributes();
@Override
default int compareTo(@Nullable IPonyData o) {
return o == this ? 0 : o == null ? 1 : ComparisonChain.start()
.compare(race(), o.race())
.compare(tailLength(), o.tailLength())
.compare(gender(), o.gender())
.compare(size().ordinal(), o.size().ordinal())
.compare(glowColor(), o.glowColor())
.compare(0, Arrays.compare(gear(), o.gear()))
.result();
}
}

View file

@ -7,64 +7,64 @@ import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ComparisonChain;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.Size;
public interface IPony extends Comparable<IPony> {
import java.util.Optional;
import java.util.function.Supplier;
public record Pony (
/**
* Gets the texture used for rendering this pony.
*/
Identifier texture,
Supplier<Optional<PonyData>> metadataGetter
) implements Comparable<Pony> {
/**
* Gets the global pony manager instance.
*/
static IPonyManager getManager() {
return IPonyManager.Instance.instance;
public static PonyManager getManager() {
return PonyManager.Instance.instance;
}
/**
* Gets or creates a new pony associated with the provided resource location.
* The results of this method should not be cached.
*
* @deprecated User IPony.getManager().getPony(texture) instead
* Gets the metadata associated with this pony's model texture.
*/
@Deprecated
static IPony forResource(Identifier texture) {
return getManager().getPony(texture);
public PonyData metadata() {
return metadataGetter().get().orElse(PonyData.NULL);
}
/**
* Returns whether this is one of the default ponies assigned to a player without a custom skin.
*/
boolean defaulted();
/**
* Returns whether this pony's metadata block has been initialized.
*/
boolean hasMetadata();
public boolean hasMetadata() {
return metadataGetter().get().isPresent();
}
public Pony immutableCopy() {
final Optional<PonyData> metadata = metadataGetter().get();
return new Pony(texture(), () -> metadata);
}
/**
* Gets the race associated with this pony.
*/
default Race race() {
public Race race() {
return PonyConfig.getEffectiveRace(metadata().race());
}
public Size size() {
return PonyConfig.getEffectiveSize(metadata().size());
}
/**
* Returns true if and only if this metadata represents a pony that can cast magic.
*/
default boolean hasMagic() {
public boolean hasMagic() {
return race().hasHorn() && metadata().glowColor() != 0;
}
/**
* Gets the texture used for rendering this pony.
*/
Identifier texture();
/**
* Gets the metadata associated with this pony's model texture.
*/
IPonyData metadata();
@Override
default int compareTo(@Nullable IPony o) {
public int compareTo(@Nullable Pony o) {
return o == this ? 0 : o == null ? 1 : ComparisonChain.start()
.compare(texture(), o.texture())
.compare(metadata(), o.metadata())

View file

@ -0,0 +1,127 @@
package com.minelittlepony.api.pony;
import net.minecraft.util.Util;
import org.jetbrains.annotations.Nullable;
import com.google.common.collect.ComparisonChain;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.common.util.animation.Interpolator;
import java.util.*;
import java.util.function.Function;
/**
* Metadata for a pony.
*/
public record PonyData (
/**
* Gets this pony's race.
*
* This is the actual race value. For the effective race, prefer going through {@link Pony#race}
*/
Race race,
/**
* Gets the length of the pony's tail.
*/
TailLength tailLength,
/**
* Gets the shape of the pony's tail.
*/
TailShape tailShape,
/**
* Get the pony's gender (usually female).
*/
Gender gender,
/**
* Gets the current pony size.
*/
Size size,
/**
* Gets the magical glow colour for magic-casting races. Returns 0 otherwise.
*/
int glowColor,
/**
* Returns an array of wearables that this pony is carrying.
*/
Flags<Wearable> gear,
/**
* Indicates whether this pony data corresponds to one of the default/built-in skins
* rather than a user-uploaded one.
*/
boolean noSkin,
/**
* Gets the trigger pixel values as they appeared in the underlying image.
*/
Map<String, TriggerPixelType<?>> attributes
) implements Comparable<PonyData> {
private static final Function<Race, PonyData> OF_RACE = Util.memoize(race -> {
return new PonyData(race, TailLength.FULL, TailShape.STRAIGHT, Gender.MARE, Sizes.NORMAL, 0x4444aa, Wearable.EMPTY_FLAGS, true, Util.make(new TreeMap<>(), attributes -> {
attributes.put("race", race);
attributes.put("tailLength", TailLength.FULL);
attributes.put("tailShape", TailShape.STRAIGHT);
attributes.put("gender", Gender.MARE);
attributes.put("size", Sizes.NORMAL);
attributes.put("magic", TriggerPixelType.of(0x4444aa));
attributes.put("gear", TriggerPixelType.of(0));
}));
});
public static final PonyData NULL = OF_RACE.apply(Race.HUMAN);
public static PonyData emptyOf(Race race) {
return OF_RACE.apply(race);
}
public PonyData(Race race, TailLength tailLength, TailShape tailShape, Gender gender, Size size, int glowColor, boolean noSkin, Flags<Wearable> wearables) {
this(race, tailLength, tailShape, gender, size, glowColor, wearables, noSkin, Util.make(new TreeMap<>(), map -> {
map.put("race", race);
map.put("tailLength", tailLength);
map.put("tailShape", tailShape);
map.put("gender", gender);
map.put("size", size);
map.put("magic", TriggerPixelType.of(glowColor));
map.put("gear", TriggerPixelType.of(wearables.colorCode()));
}));
}
public PonyData(Race race, TailLength tailLength, TailShape tailShape, Gender gender, Size size, int glowColor, TriggerPixelType.Multiple<Wearable> wearables, boolean noSkin) {
this(race, tailLength, tailShape, gender, size, glowColor,
Flags.of(Wearable.class, wearables.colorCode(), wearables.value()),
noSkin, Util.make(new TreeMap<>(), map -> {
map.put("race", race);
map.put("tailLength", tailLength);
map.put("tailShape", tailShape);
map.put("gender", gender);
map.put("size", size);
map.put("magic", TriggerPixelType.of(glowColor));
map.put("gear", wearables);
})
);
}
/**
* Checks it this pony is wearing the given accessory.
*/
public boolean isWearing(Wearable wearable) {
return gear().includes(wearable);
}
/**
* Gets an interpolator for interpolating values.
*/
public Interpolator getInterpolator(UUID interpolatorId) {
return Interpolator.linear(interpolatorId);
}
@Override
public int compareTo(@Nullable PonyData o) {
return o == this ? 0 : o == null ? 1 : ComparisonChain.start()
.compare(race(), o.race())
.compare(tailLength(), o.tailLength())
.compare(gender(), o.gender())
.compare(size().ordinal(), o.size().ordinal())
.compare(glowColor(), o.glowColor())
.compare(0, gear().compareTo(o.gear()))
.result();
}
}

View file

@ -13,13 +13,13 @@ import java.util.UUID;
* The PonyManager is responsible for reading and recoding all the pony data associated with an entity of skin.
*
*/
public interface IPonyManager {
public interface PonyManager {
/**
* Gets a pony representation of the passed in entity.
*
* If the supplied entity is null or can't be determined to be a pony, returns the empty optional.
*/
Optional<IPony> getPony(@Nullable Entity entity);
Optional<Pony> getPony(@Nullable Entity entity);
/**
* Gets or creates a pony for the given player.
@ -27,14 +27,14 @@ public interface IPonyManager {
*
* @param player the player
*/
IPony getPony(PlayerEntity player);
Pony getPony(PlayerEntity player);
/**
* Gets or creates a pony for the given skin resource and vanilla model type.
*
* @param resource A texture resource
*/
IPony getPony(Identifier resource);
Pony getPony(Identifier resource);
/**
* Gets or creates a pony for the given skin resource and entity id.
@ -46,7 +46,7 @@ public interface IPonyManager {
* @param resource A texture resource
* @param uuid id of a player
*/
IPony getPony(Identifier resource, UUID uuid);
Pony getPony(Identifier resource, UUID uuid);
/**
* Gets a random background pony determined by the given uuid.
@ -55,16 +55,18 @@ public interface IPonyManager {
*
* @param uuid A UUID. Either a user or an entity.
*/
IPony getBackgroundPony(UUID uuid);
Pony getBackgroundPony(UUID uuid);
/**
* De-registers a pony from the cache.
*/
void removePony(Identifier resource);
void clearCache();
interface ForcedPony {}
final class Instance {
public static IPonyManager instance;
public static PonyManager instance;
}
}

View file

@ -1,7 +1,7 @@
package com.minelittlepony.api.pony;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.IPreviewModel;
import com.minelittlepony.client.PreviewModel;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.render.entity.AquaticPlayerPonyRenderer;
@ -17,13 +17,13 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public final class PonyPosture {
public static Optional<IPony> getMountPony(LivingEntity entity) {
public static Optional<Pony> getMountPony(LivingEntity entity) {
return entity.getVehicle() instanceof LivingEntity mount
? IPony.getManager().getPony(mount)
? Pony.getManager().getPony(mount)
: Optional.empty();
}
public static boolean isCrouching(IPony pony, LivingEntity entity) {
public static boolean isCrouching(Pony pony, LivingEntity entity) {
boolean isSneak = entity.isInSneakingPose();
boolean isFlying = isFlying(entity);
boolean isSwimming = isSwimming(entity);
@ -31,7 +31,7 @@ public final class PonyPosture {
return !isPerformingRainboom(pony, entity) && !isSwimming && isSneak && !isFlying;
}
private static boolean isPerformingRainboom(IPony pony, LivingEntity entity) {
private static boolean isPerformingRainboom(Pony pony, LivingEntity entity) {
Vec3d motion = entity.getVelocity();
double zMotion = Math.sqrt(motion.x * motion.x + motion.z * motion.z);
@ -85,21 +85,21 @@ public final class PonyPosture {
}
public static boolean isRidingAPony(LivingEntity entity) {
return isSitting(entity) && getMountPony(entity).map(IPony::race).orElse(Race.HUMAN) != Race.HUMAN;
return isSitting(entity) && getMountPony(entity).map(Pony::race).orElse(Race.HUMAN) != Race.HUMAN;
}
public static boolean isSeaponyModifier(LivingEntity entity) {
if (entity instanceof IPreviewModel preview) {
if (entity instanceof PreviewModel preview) {
return preview.forceSeapony();
}
return hasSeaponyForm(entity) && isPartiallySubmerged(entity);
}
public static boolean hasSeaponyForm(LivingEntity entity) {
if (entity instanceof IPreviewModel preview) {
if (entity instanceof PreviewModel preview) {
return preview.forceSeapony();
}
return IPony.getManager().getPony(entity).filter(pony -> {
return Pony.getManager().getPony(entity).filter(pony -> {
return (pony.race() == Race.SEAPONY
|| (entity instanceof AbstractClientPlayerEntity player && SkinsProxy.instance.getSkin(AquaticPlayerPonyRenderer.SKIN_TYPE_ID, player).isPresent())
);

View file

@ -0,0 +1,53 @@
package com.minelittlepony.api.pony.meta;
import net.minecraft.network.PacketByteBuf;
import java.util.*;
public record Flags<T extends Enum<T>> (
boolean[] flags,
List<T> values,
int colorCode
) implements Comparable<Flags<T>> {
public static <T extends Enum<T>> Flags<T> of(Class<T> type) {
return new Flags<>(new boolean[type.getEnumConstants().length], List.<T>of(), 0);
}
public static <T extends Enum<T>> Flags<T> of(Class<T> type, int colorCode, boolean...flags) {
return new Flags<>(flags, flags(type.getEnumConstants(), flags), colorCode);
}
public static <T extends Enum<T>> Flags<T> read(Class<T> type, PacketByteBuf buffer) {
int length = buffer.readVarInt();
List<T> values = new ArrayList<>();
T[] all = type.getEnumConstants();
boolean[] flags = new boolean[all.length];
for (int i = 0; i < length; i++) {
values.add(all[buffer.readInt()]);
flags[i] = true;
}
return new Flags<>(flags, values, buffer.readInt());
}
public static <T> List<T> flags(T[] values, boolean[] flags) {
List<T> wears = new ArrayList<>();
for (int i = 0; i < values.length; i++) {
if (flags[i]) wears.add(values[i]);
}
return wears;
}
public boolean includes(T t) {
return flags[t.ordinal()];
}
public int compareTo(Flags<T> other) {
return Arrays.compare(flags, other.flags);
}
public void write(PacketByteBuf buffer) {
buffer.writeCollection(values, (buf, value) -> buf.writeInt(value.ordinal()));
buffer.writeInt(colorCode);
}
}

View file

@ -1,7 +1,5 @@
package com.minelittlepony.api.pony.meta;
import com.minelittlepony.api.pony.TriggerPixelType;
public enum Gender implements TriggerPixelType<Gender> {
MARE(0),
STALLION(0xffffff),

View file

@ -1,7 +1,5 @@
package com.minelittlepony.api.pony.meta;
import com.minelittlepony.api.pony.TriggerPixelType;
import java.util.*;
public enum Race implements TriggerPixelType<Race> {

View file

@ -1,7 +1,5 @@
package com.minelittlepony.api.pony.meta;
import com.minelittlepony.api.pony.TriggerPixelType;
/**
* Represents the different model sizes that are possible.
*

View file

@ -1,7 +1,5 @@
package com.minelittlepony.api.pony.meta;
import com.minelittlepony.api.pony.TriggerPixelType;
public enum TailLength implements TriggerPixelType<TailLength> {
STUB (0x425844),
QUARTER (0xd19fe4),

View file

@ -1,7 +1,5 @@
package com.minelittlepony.api.pony.meta;
import com.minelittlepony.api.pony.TriggerPixelType;
public enum TailShape implements TriggerPixelType<TailShape> {
STRAIGHT(0),
BUMPY (0xfc539f),

View file

@ -2,7 +2,6 @@ package com.minelittlepony.api.pony.meta;
import net.minecraft.client.texture.NativeImage;
import com.minelittlepony.api.pony.TriggerPixelType;
import com.minelittlepony.common.util.Color;
import java.util.Arrays;
@ -21,12 +20,12 @@ public enum TriggerPixel {
WEARABLES(Wearable.NONE, Channel.RAW, 1, 1),
TAIL_SHAPE(TailShape.STRAIGHT, Channel.ALL, 2, 1);
private int x;
private int y;
private final int x;
private final int y;
private Channel channel;
private final Channel channel;
TriggerPixelType<?> def;
private final TriggerPixelType<?> def;
private static final TriggerPixel[] VALUES = values();
private static final int MAX_READ_X = Arrays.stream(VALUES).mapToInt(i -> i.x).max().getAsInt();
@ -53,20 +52,20 @@ public enum TriggerPixel {
*
* @param image Image to read
*/
public <T extends TriggerPixelType<T>> TriggerPixelType.Value<T> readValue(NativeImage image) {
public <T extends TriggerPixelType<T>> T readValue(NativeImage image) {
int color = readColor(image);
if (Channel.ALPHA.readValue(x, y, image) < 255) {
return new TriggerPixelType.Value<>(color, (T)def);
return (T)def;
}
return new TriggerPixelType.Value<>(color, TriggerPixelType.getByTriggerPixel((T)def, color));
return TriggerPixelType.getByTriggerPixel((T)def, color);
}
public <T extends Enum<T> & TriggerPixelType<T>> TriggerPixelType.Flags<T> readFlags(NativeImage image) {
public <T extends Enum<T> & TriggerPixelType<T>> TriggerPixelType.Multiple<T> readFlags(NativeImage image) {
boolean[] out = new boolean[def.getClass().getEnumConstants().length];
readFlags(out, image);
return new TriggerPixelType.Flags<>(readColor(image), (T)def, out);
return new TriggerPixelType.Multiple<>(readColor(image), (T)def, out);
}
public <T extends Enum<T> & TriggerPixelType<T>> void readFlags(boolean[] out, NativeImage image) {

View file

@ -1,4 +1,4 @@
package com.minelittlepony.api.pony;
package com.minelittlepony.api.pony.meta;
import java.util.Arrays;
import java.util.List;
@ -73,7 +73,7 @@ public interface TriggerPixelType<T> {
return "#" + v;
}
public record Flags<T extends Enum<T> & TriggerPixelType<T>> (
public record Multiple<T extends Enum<T> & TriggerPixelType<T>> (
int colorCode,
T def,
boolean[] value
@ -94,21 +94,4 @@ public interface TriggerPixelType<T> {
return o.getClass() == def.getClass() && value()[((Enum<?>)o).ordinal()];
}
}
public record Value<T> (
int colorCode,
T value
) implements TriggerPixelType<T> {
@Override
public String name() {
return value instanceof TriggerPixelType t ? t.name() : TriggerPixelType.super.name();
}
@SuppressWarnings("unchecked")
@Override
public <Option extends TriggerPixelType<T>> List<Option> getOptions() {
return value instanceof TriggerPixelType t ? t.getOptions() : TriggerPixelType.super.getOptions();
}
}
}

View file

@ -2,7 +2,6 @@ package com.minelittlepony.api.pony.meta;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.pony.TriggerPixelType;
import com.minelittlepony.client.model.gear.SaddleBags;
import com.minelittlepony.common.util.Color;
@ -30,6 +29,8 @@ public enum Wearable implements TriggerPixelType<Wearable> {
public static final List<Wearable> VALUES = Arrays.stream(values()).toList();
public static final Map<Identifier, Wearable> REGISTRY = VALUES.stream().collect(Collectors.toMap(Wearable::getId, Function.identity()));
public static final Flags<Wearable> EMPTY_FLAGS = Flags.of(Wearable.class);
Wearable(int pixel, Identifier texture) {
triggerValue = pixel;
id = new Identifier("minelittlepony", name().toLowerCase(Locale.ROOT));
@ -57,20 +58,4 @@ public enum Wearable implements TriggerPixelType<Wearable> {
public int getChannelAdjustedColorCode() {
return triggerValue == 0 ? 0 : Color.argbToHex(255, triggerValue, triggerValue, triggerValue);
}
public static boolean[] flags(Wearable[] wears) {
boolean[] flags = new boolean[VALUES.size()];
for (int i = 0; i < wears.length; i++) {
flags[wears[i].ordinal()] = true;
}
return flags;
}
public static Wearable[] flags(boolean[] flags) {
List<Wearable> wears = new ArrayList<>();
for (int i = 0; i < VALUES.size(); i++) {
if (flags[i]) wears.add(VALUES.get(i));
}
return wears.toArray(new Wearable[0]);
}
}

View file

@ -1,177 +1,46 @@
package com.minelittlepony.api.pony.network;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Util;
import com.google.common.base.MoreObjects;
import com.google.common.base.Suppliers;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.TriggerPixelType;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.common.util.animation.Interpolator;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import java.util.function.Supplier;
public class MsgPonyData implements IPonyData {
public class MsgPonyData {
private static final short API_IDENTIFIER = (short) 0xABCD;
// API version - increment this number before any time any data is added/removed/moved in the data stream
private static final byte API_VERSION = 2;
private final Race race;
private final TailLength tailLength;
private final TailShape tailShape;
private final Gender gender;
private final Size size;
private final int glowColor;
private final boolean noSkin;
private final int wearableColor;
private final boolean[] wearables;
private final Supplier<Map<String, TriggerPixelType<?>>> triggerPixels = Suppliers.memoize(() -> Util.make(new TreeMap<>(), this::initTriggerPixels));
private void initTriggerPixels(Map<String, TriggerPixelType<?>> map) {
map.put("race", race);
map.put("tailLength", tailLength);
map.put("tailShape", tailShape);
map.put("gender", gender);
map.put("size", size);
map.put("magic", TriggerPixelType.of(glowColor));
map.put("gear", TriggerPixelType.of(wearableColor));
}
public MsgPonyData(PacketByteBuf buffer) {
public static PonyData read(PacketByteBuf buffer) {
short data = buffer.readShort();
if (data != API_IDENTIFIER || buffer.readByte() != API_VERSION) {
race = null;
tailLength = null;
tailShape = null;
gender = null;
size = null;
glowColor = 0;
noSkin = true;
wearables = null;
wearableColor = 0;
return;
return PonyData.NULL;
}
race = buffer.readEnumConstant(Race.class);
tailLength = buffer.readEnumConstant(TailLength.class);
tailShape = buffer.readEnumConstant(TailShape.class);
gender = buffer.readEnumConstant(Gender.class);
size = new MsgSize(buffer);
glowColor = buffer.readInt();
noSkin = buffer.readBoolean();
Wearable[] gear = new Wearable[buffer.readInt()];
Wearable[] all = Wearable.values();
for (int i = 0; i < gear.length; i++) {
gear[i] = all[buffer.readInt()];
}
wearables = Wearable.flags(gear);
wearableColor = buffer.readInt();
return new PonyData(
buffer.readEnumConstant(Race.class),
buffer.readEnumConstant(TailLength.class),
buffer.readEnumConstant(TailShape.class),
buffer.readEnumConstant(Gender.class),
new MsgSize(buffer),
buffer.readInt(),
buffer.readBoolean(),
Flags.read(Wearable.class, buffer)
);
}
public MsgPonyData(IPonyData data, boolean noSkin) {
race = data.race();
tailLength = data.tailLength();
tailShape = data.tailShape();
gender = data.gender();
size = data.size();
glowColor = data.glowColor();
wearables = Wearable.flags(data.gear());
wearableColor = data.attributes().get("gear").colorCode();
this.noSkin = noSkin;
}
public PacketByteBuf toBuffer(PacketByteBuf buffer) {
public static PacketByteBuf write(PonyData data, PacketByteBuf buffer) {
buffer.writeShort(API_IDENTIFIER);
buffer.writeByte(API_VERSION);
buffer.writeEnumConstant(race);
buffer.writeEnumConstant(tailLength);
buffer.writeEnumConstant(tailShape);
buffer.writeEnumConstant(gender);
new MsgSize(size).toBuffer(buffer);
buffer.writeInt(glowColor);
buffer.writeBoolean(noSkin);
Wearable[] gear = gear();
buffer.writeInt(gear.length);
for (int i = 0; i < gear.length; i++) {
buffer.writeInt(gear[i].ordinal());
}
buffer.writeInt(wearableColor);
buffer.writeEnumConstant(data.race());
buffer.writeEnumConstant(data.tailLength());
buffer.writeEnumConstant(data.tailShape());
buffer.writeEnumConstant(data.gender());
new MsgSize(data.size()).toBuffer(buffer);
buffer.writeInt(data.glowColor());
buffer.writeBoolean(data.noSkin());
data.gear().write(buffer);
return buffer;
}
public boolean isNoSkin() {
return noSkin;
}
@Override
public Race race() {
return race;
}
@Override
public TailLength tailLength() {
return tailLength;
}
@Override
public TailShape tailShape() {
return tailShape;
}
@Override
public Gender gender() {
return gender;
}
@Override
public Size size() {
return size;
}
@Override
public int glowColor() {
return glowColor;
}
@Override
public Wearable[] gear() {
return Wearable.flags(wearables);
}
@Override
public boolean isWearing(Wearable wearable) {
return wearables[wearable.ordinal()];
}
@Override
public Interpolator getInterpolator(UUID interpolatorId) {
return Interpolator.linear(interpolatorId);
}
@Override
public Map<String, TriggerPixelType<?>> attributes() {
return triggerPixels.get();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("race", race)
.add("tailLength", tailLength)
.add("tailShape", tailShape)
.add("gender", gender)
.add("size", size)
.add("wearables", gear())
.add("glowColor", TriggerPixelType.toHex(glowColor))
.toString();
}
private record MsgSize (
int ordinal,
String name,
@ -179,7 +48,7 @@ public class MsgPonyData implements IPonyData {
float scaleFactor,
float eyeHeightFactor,
float eyeDistanceFactor,
int triggerPixel) implements Size {
int colorCode) implements Size {
MsgSize(Size size) {
this(size.ordinal(), size.name(), size.shadowSize(), size.scaleFactor(), size.eyeHeightFactor(), size.eyeDistanceFactor(), size.colorCode());
@ -196,17 +65,12 @@ public class MsgPonyData implements IPonyData {
buffer.writeFloat(scaleFactor);
buffer.writeFloat(eyeHeightFactor);
buffer.writeFloat(eyeDistanceFactor);
buffer.writeFloat(triggerPixel);
buffer.writeFloat(colorCode);
}
@Override
public String toString() {
return name;
}
@Override
public int colorCode() {
return triggerPixel;
}
}
}

View file

@ -11,7 +11,8 @@ import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.network.MsgPonyData;
import com.minelittlepony.client.MineLittlePony;
@ -35,22 +36,22 @@ public class Channel {
ClientPlayNetworking.registerGlobalReceiver(REQUEST_PONY_DATA, (client, handler, ignored, sender) -> {
if (client.player != null) {
IPony pony = IPony.getManager().getPony(client.player);
Pony pony = Pony.getManager().getPony(client.player);
registered = true;
MineLittlePony.logger.info("Server has just consented");
sender.sendPacket(CLIENT_PONY_DATA, new MsgPonyData(pony.metadata(), pony.defaulted()).toBuffer(PacketByteBufs.create()));
sender.sendPacket(CLIENT_PONY_DATA, MsgPonyData.write(pony.metadata(), PacketByteBufs.create()));
}
});
ServerPlayNetworking.registerGlobalReceiver(CLIENT_PONY_DATA, (server, player, ignore, buffer, ignore2) -> {
MsgPonyData packet = new MsgPonyData(buffer);
PonyData packet = MsgPonyData.read(buffer);
server.execute(() -> {
PonyDataCallback.EVENT.invoker().onPonyDataAvailable(player, packet, packet.isNoSkin(), EnvType.SERVER);
PonyDataCallback.EVENT.invoker().onPonyDataAvailable(player, packet, EnvType.SERVER);
});
});
}
public static void broadcastPonyData(MsgPonyData packet) {
public static void broadcastPonyData(PonyData packet) {
if (FabricLoader.getInstance().getEnvironmentType() != EnvType.CLIENT) {
throw new RuntimeException("Client packet send called by the server");
}
@ -64,6 +65,6 @@ public class Channel {
}
}
ClientPlayNetworking.send(CLIENT_PONY_DATA, packet.toBuffer(PacketByteBufs.create()));
ClientPlayNetworking.send(CLIENT_PONY_DATA, MsgPonyData.write(packet, PacketByteBufs.create()));
}
}

View file

@ -5,17 +5,16 @@ import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
import net.minecraft.entity.player.PlayerEntity;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.PonyData;
/**
* Callback triggered on the server when receiving pony data from a client.
*
*/
public interface PonyDataCallback {
Event<PonyDataCallback> EVENT = EventFactory.createArrayBacked(PonyDataCallback.class, listeners -> (sender, data, noSkin, env) -> {
Event<PonyDataCallback> EVENT = EventFactory.createArrayBacked(PonyDataCallback.class, listeners -> (sender, data, env) -> {
for (PonyDataCallback event : listeners) {
event.onPonyDataAvailable(sender, data, noSkin, env);
event.onPonyDataAvailable(sender, data, env);
}
});
@ -23,8 +22,7 @@ public interface PonyDataCallback {
* Called when pony data is received.
* @param sender The player who sent the data - this is the owner of the skin/pony data.
* @param data The skin/pony data
* @param noSkin Whether the data is for a player with a default/unset custom skin.
* @param env The environment. Whether this call is coming from the client or server. Clients may get two calls, one for both.
*/
void onPonyDataAvailable(PlayerEntity sender, IPonyData data, boolean noSkin, EnvType env);
void onPonyDataAvailable(PlayerEntity sender, PonyData data, EnvType env);
}

View file

@ -1,4 +1,4 @@
package com.minelittlepony.client.settings;
package com.minelittlepony.client;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;

View file

@ -5,7 +5,7 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.*;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.common.util.settings.Setting;
public class HorseCam {
@ -48,7 +48,7 @@ public class HorseCam {
return pitch;
}
IPony pony = IPony.getManager().getPony(player);
Pony pony = Pony.getManager().getPony(player);
if (!pony.race().isHuman()) {
Setting<Boolean> fillyCam = MineLittlePony.getInstance().getConfig().fillycam;

View file

@ -13,7 +13,6 @@ import static com.minelittlepony.common.event.SkinFilterCallback.copy;
*
*/
class LegacySkinConverter implements SkinFilterCallback {
@Override
public void processImage(NativeImage image, boolean legacy) {
if (legacy) {

View file

@ -1,12 +1,10 @@
package com.minelittlepony.client;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.pony.PonyManager;
import com.minelittlepony.api.pony.network.fabric.Channel;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.pony.PonyManager;
import com.minelittlepony.client.pony.VariatedTextureSupplier;
import com.minelittlepony.client.render.PonyRenderDispatcher;
import com.minelittlepony.client.settings.ClientPonyConfig;
import com.minelittlepony.common.client.gui.VisibilityMode;
import com.minelittlepony.common.client.gui.element.Button;
import com.minelittlepony.common.client.gui.sprite.TextureSprite;
@ -41,7 +39,7 @@ public class MineLittlePony implements ClientModInitializer {
public static final Logger logger = LogManager.getLogger("MineLittlePony");
private ClientPonyConfig config;
private PonyManager ponyManager;
private PonyManagerImpl ponyManager;
private VariatedTextureSupplier variatedTextures;
private final KeyBinding keyBinding = new KeyBinding("key.minelittlepony.settings", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_F9, "key.categories.misc");
@ -68,7 +66,7 @@ public class MineLittlePony implements ClientModInitializer {
hasModMenu = FabricLoader.getInstance().isModLoaded("modmenu");
config = new ClientPonyConfig(GamePaths.getConfigDirectory().resolve("minelp.json"));
ponyManager = new PonyManager(config);
ponyManager = new PonyManagerImpl(config);
variatedTextures = new VariatedTextureSupplier();
KeyBindingHelper.registerKeyBinding(keyBinding);
@ -105,7 +103,7 @@ public class MineLittlePony implements ClientModInitializer {
}
if ((mainMenu || inGame) && keyBinding.isPressed()) {
client.setScreen(new GuiPonySettings(client.currentScreen));
client.setScreen(new PonySettingsscreen(client.currentScreen));
}
}
@ -119,7 +117,7 @@ public class MineLittlePony implements ClientModInitializer {
if (show) {
int y = hasHdSkins ? 75 : 50;
Button button = buttons.addButton(new Button(screen.width - 50, screen.height - y, 20, 20))
.onClick(sender -> MinecraftClient.getInstance().setScreen(new GuiPonySettings(screen)));
.onClick(sender -> MinecraftClient.getInstance().setScreen(new PonySettingsscreen(screen)));
button.getStyle()
.setIcon(new TextureSprite()
.setPosition(2, 2)

View file

@ -1,6 +1,6 @@
package com.minelittlepony.client;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.client.transform.PonyTransformation;
@ -16,7 +16,7 @@ public class PonyBounds {
return PonyPosture.getMountPony(entity).map(ridingPony -> {
LivingEntity vehicle = (LivingEntity)entity.getVehicle();
Vec3d offset = PonyTransformation.forSize(ridingPony.metadata().size()).getRiderOffset();
Vec3d offset = PonyTransformation.forSize(ridingPony.size()).getRiderOffset();
float scale = ridingPony.metadata().size().scaleFactor();
return getAbsoluteRidingOffset(vehicle).add(
@ -40,8 +40,8 @@ public class PonyBounds {
);
}
public static Box getBoundingBox(IPony pony, LivingEntity entity) {
final float scale = pony.metadata().size().scaleFactor() + 0.1F;
public static Box getBoundingBox(Pony pony, LivingEntity entity) {
final float scale = pony.size().scaleFactor() + 0.1F;
final float width = entity.getWidth() * scale;
final float height = entity.getHeight() * scale;

View file

@ -0,0 +1,97 @@
package com.minelittlepony.client;
import net.minecraft.client.MinecraftClient;
import net.minecraft.resource.metadata.ResourceMetadataReader;
import net.minecraft.util.Identifier;
import com.google.gson.*;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.client.util.render.NativeUtil;
import java.io.IOException;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable;
class PonyDataLoader {
static final Supplier<Optional<PonyData>> NULL = loaded(PonyData.NULL);
private static final ResourceMetadataReader<PonyData> SERIALIZER = new ResourceMetadataReader<PonyData>() {
private static final Gson GSON = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
@Override
public String getKey() {
return "pony";
}
@Override
public PonyData fromJson(JsonObject json) {
return GSON.fromJson(json, PonyData.class);
}
};
/**
* Parses the given resource into a new IPonyData.
* This may either come from an attached json file or the image itself.
*/
public static Supplier<Optional<PonyData>> parse(@Nullable Identifier identifier, boolean noSkin) {
if (identifier == null) {
return NULL;
}
return MinecraftClient.getInstance().getResourceManager().getResource(identifier).flatMap(res -> {
try {
return res.getMetadata().decode(SERIALIZER);
} catch (IOException e) {
MineLittlePony.logger.warn("Unable to read {} metadata", identifier, e);
}
return Optional.empty();
}).map(PonyDataLoader::loaded).orElseGet(() -> {
return load(callback -> {
NativeUtil.parseImage(identifier, image -> {
callback.accept(new PonyData(
TriggerPixel.RACE.readValue(image),
TriggerPixel.TAIL.readValue(image),
TriggerPixel.TAIL_SHAPE.readValue(image),
TriggerPixel.GENDER.readValue(image),
TriggerPixel.SIZE.readValue(image),
TriggerPixel.GLOW.readColor(image),
TriggerPixel.WEARABLES.readFlags(image),
noSkin
));
}, e -> {
MineLittlePony.logger.fatal("Unable to read {} metadata", identifier, e);
callback.accept(PonyData.NULL);
});
});
});
}
private static <T> Supplier<Optional<T>> loaded(T t) {
final Optional<T> value = Optional.of(t);
return () -> value;
}
private static <T> Supplier<Optional<T>> load(Consumer<Consumer<T>> factory) {
return new Supplier<Optional<T>>() {
Optional<T> value = Optional.empty();
boolean loadRequested;
@Override
public Optional<T> get() {
synchronized (this) {
if (!loadRequested) {
loadRequested = true;
factory.accept(value -> {
this.value = Optional.ofNullable(value);
});
}
}
return value;
}
};
}
}

View file

@ -1,11 +1,9 @@
package com.minelittlepony.client.pony;
package com.minelittlepony.client;
import com.google.common.cache.*;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.config.PonyLevel;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyManager;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.api.pony.*;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer;
import org.jetbrains.annotations.Nullable;
@ -26,39 +24,44 @@ import java.util.concurrent.TimeUnit;
/**
* The PonyManager is responsible for reading and recoding all the pony data associated with an entity of skin.
*
*/
public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloadListener {
class PonyManagerImpl implements PonyManager, SimpleSynchronousResourceReloadListener {
private static final Identifier ID = new Identifier("minelittlepony", "background_ponies");
public static final Identifier BACKGROUND_PONIES = new Identifier("minelittlepony", "textures/entity/pony");
public static final Identifier BACKGROUND_ZOMPONIES = new Identifier("minelittlepony", "textures/entity/zompony");
private final PonyConfig config;
private final Cache<Identifier, IPony> defaultedPoniesCache = CacheBuilder.newBuilder()
private final LoadingCache<Identifier, Pony> defaultedPoniesCache = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS)
.build();
.build(CacheLoader.from(resource -> {
return new Pony(resource, PonyDataLoader.parse(resource, true));
}));
private final LoadingCache<Identifier, IPony> poniesCache = CacheBuilder.newBuilder()
private final LoadingCache<Identifier, Pony> poniesCache = CacheBuilder.newBuilder()
.expireAfterAccess(30, TimeUnit.SECONDS)
.build(CacheLoader.from(Pony::new));
.build(CacheLoader.from(resource -> {
return new Pony(resource, PonyDataLoader.parse(resource, false));
}));
public PonyManager(PonyConfig config) {
public PonyManagerImpl(PonyConfig config) {
this.config = config;
Instance.instance = this;
}
@Override
public IPony getPony(Identifier resource) {
private Pony loadPony(Identifier resource, boolean defaulted) {
try {
return poniesCache.get(resource);
return (defaulted ? defaultedPoniesCache : poniesCache).get(resource);
} catch (ExecutionException e) {
return new Pony(resource, PonyData.MEM_NULL, true);
return new Pony(resource, PonyDataLoader.NULL);
}
}
@Override
public Optional<IPony> getPony(@Nullable Entity entity) {
public Pony getPony(Identifier resource) {
return loadPony(resource, false);
}
@Override
public Optional<Pony> getPony(@Nullable Entity entity) {
if (entity instanceof PlayerEntity player) {
return Optional.of(getPony(player));
}
@ -71,12 +74,12 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
}
@Override
public IPony getPony(PlayerEntity player) {
public Pony getPony(PlayerEntity player) {
Identifier skin = getSkin(player);
UUID uuid = player.getGameProfile() == null ? player.getUuid() : player.getGameProfile().getId();
if (skin != null) {
if (player instanceof IPonyManager.ForcedPony) {
if (player instanceof PonyManager.ForcedPony) {
return getPony(skin);
}
@ -87,12 +90,12 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
return getBackgroundPony(uuid);
}
return getAsDefaulted(getPony(DefaultSkinHelper.getTexture(uuid).texture()));
return loadPony(DefaultSkinHelper.getTexture(uuid).texture(), true);
}
@Override
public IPony getPony(Identifier resource, UUID uuid) {
IPony pony = getPony(resource);
public Pony getPony(Identifier resource, UUID uuid) {
Pony pony = getPony(resource);
if (config.ponyLevel.get() == PonyLevel.PONIES && pony.metadata().race().isHuman()) {
return getBackgroundPony(uuid);
@ -102,16 +105,8 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
}
@Override
public IPony getBackgroundPony(UUID uuid) {
return getAsDefaulted(getPony(MineLittlePony.getInstance().getVariatedTextures().get(BACKGROUND_PONIES, uuid).orElse(DefaultSkinHelper.getTexture(uuid).texture())));
}
private IPony getAsDefaulted(IPony pony) {
try {
return defaultedPoniesCache.get(pony.texture(), () -> new Pony(pony.texture(), ((Pony)pony).memoizedData(), true));
} catch (ExecutionException e) {
return pony;
}
public Pony getBackgroundPony(UUID uuid) {
return loadPony(MineLittlePony.getInstance().getVariatedTextures().get(VariatedTextureSupplier.BACKGROUND_PONIES_POOL, uuid).orElse(DefaultSkinHelper.getTexture(uuid).texture()), true);
}
@Nullable
@ -132,6 +127,7 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
defaultedPoniesCache.invalidate(resource);
}
@Override
public void clearCache() {
MineLittlePony.logger.info("Flushed {} cached ponies.", poniesCache.size());
poniesCache.invalidateAll();
@ -148,5 +144,4 @@ public class PonyManager implements IPonyManager, SimpleSynchronousResourceReloa
public Identifier getFabricId() {
return ID;
}
}

View file

@ -6,7 +6,6 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.*;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.client.settings.ClientPonyConfig;
import com.minelittlepony.common.client.gui.GameGui;
import com.minelittlepony.common.client.gui.ScrollContainer;
import com.minelittlepony.common.client.gui.Tooltip;
@ -24,7 +23,7 @@ import org.jetbrains.annotations.Nullable;
* In-Game options menu.
*
*/
public class GuiPonySettings extends GameGui {
public class PonySettingsscreen extends GameGui {
private static final String OPTIONS_PREFIX = "minelp.options.";
private static final String PONY_LEVEL = OPTIONS_PREFIX + "ponylevel";
private static final String MOB_PREFIX = "minelp.mobs.";
@ -41,7 +40,7 @@ public class GuiPonySettings extends GameGui {
private final boolean hiddenOptions;
public GuiPonySettings(@Nullable Screen parent) {
public PonySettingsscreen(@Nullable Screen parent) {
super(Text.literal(OPTIONS_PREFIX + "title"), parent);
config = (ClientPonyConfig)MineLittlePony.getInstance().getConfig();

View file

@ -1,5 +1,5 @@
package com.minelittlepony.client;
public interface IPreviewModel {
public interface PreviewModel {
boolean forceSeapony();
}

View file

@ -1,4 +1,4 @@
package com.minelittlepony.client.pony;
package com.minelittlepony.client;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.client.MinecraftClient;
@ -6,13 +6,14 @@ import net.minecraft.entity.Entity;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.util.MathUtil;
import java.util.*;
public class VariatedTextureSupplier implements SimpleSynchronousResourceReloadListener {
private static final Identifier ID = new Identifier("minelittlepony", "variated_textures");
public static final Identifier BACKGROUND_PONIES_POOL = new Identifier("minelittlepony", "textures/entity/pony");
public static final Identifier BACKGROUND_ZOMPONIES_POOL = new Identifier("minelittlepony", "textures/entity/zompony");
private final Map<Identifier, SkinList> entries = new HashMap<>();

View file

@ -1,9 +1,9 @@
package com.minelittlepony.client.hdskins;
package com.minelittlepony.client.compat.hdskins;
import net.minecraft.client.world.ClientWorld;
import com.minelittlepony.api.pony.*;
import com.minelittlepony.client.IPreviewModel;
import com.minelittlepony.client.PreviewModel;
import com.minelittlepony.client.render.EquineRenderManager;
import com.minelittlepony.hdskins.client.gui.player.*;
import com.minelittlepony.hdskins.client.gui.player.skins.PlayerSkins;
@ -13,7 +13,7 @@ import java.util.UUID;
/**
* Dummy model used for the skin uploading screen.
*/
class DummyPony extends DummyPlayer implements IPreviewModel, IPonyManager.ForcedPony, EquineRenderManager.RegistrationHandler {
class DummyPony extends DummyPlayer implements PreviewModel, PonyManager.ForcedPony, EquineRenderManager.RegistrationHandler {
public DummyPony(ClientWorld world, PlayerSkins<?> textures) {
super(world, textures);
@ -21,7 +21,7 @@ class DummyPony extends DummyPlayer implements IPreviewModel, IPonyManager.Force
}
@Override
public boolean shouldUpdateRegistration(IPony pony) {
public boolean shouldUpdateRegistration(Pony pony) {
return false;
}

View file

@ -1,7 +1,7 @@
package com.minelittlepony.client.hdskins;
package com.minelittlepony.client.compat.hdskins;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.client.GuiPonySettings;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.PonySettingsscreen;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.common.client.gui.dimension.Bounds;
import com.minelittlepony.common.client.gui.element.Button;
@ -29,22 +29,22 @@ class GuiSkinsMineLP extends GuiSkins {
chooser.addSkinChangedEventListener(type -> {
MineLittlePony.logger.debug("Invalidating old local skin, checking updated local skin");
if (type == SkinType.SKIN) {
IPony.getManager().removePony(previewer.getLocal().getSkins().get(SkinType.SKIN).getId());
Pony.getManager().removePony(previewer.getLocal().getSkins().get(SkinType.SKIN).getId());
}
});
uploader.addSkinLoadedEventListener((type, location, profileTexture) -> {
MineLittlePony.logger.debug("Invalidating old remote skin, checking updated remote skin");
if (type == SkinType.SKIN) {
IPony.getManager().removePony(location);
Pony.getManager().removePony(location);
}
});
}
@Override
protected void initServerPreviewButtons(Bounds area) {
if (!(parent instanceof GuiPonySettings)) {
if (!(parent instanceof PonySettingsscreen)) {
addButton(new Button(area.right() - 20, area.bottom() + 5, 20, 20))
.onClick(sender -> client.setScreen(new GuiPonySettings(this)))
.onClick(sender -> client.setScreen(new PonySettingsscreen(this)))
.getStyle()
.setIcon(new TextureSprite()
.setPosition(2, 2)

View file

@ -1,9 +1,10 @@
package com.minelittlepony.client.hdskins;
package com.minelittlepony.client.compat.hdskins;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import com.minelittlepony.api.pony.*;
import com.minelittlepony.api.pony.meta.TriggerPixelType;
import com.minelittlepony.common.client.gui.ITextContext;
import com.minelittlepony.common.client.gui.dimension.Bounds;
import com.minelittlepony.hdskins.client.gui.Carousel;
@ -23,7 +24,7 @@ class LegendOverlayWidget implements Carousel.Element, ITextContext {
@Override
public void render(DummyPlayer player, DrawContext context, int mouseX, int mouseY) {
IPonyData data = IPony.getManager().getPony(player).metadata();
PonyData data = Pony.getManager().getPony(player).metadata();
int[] index = new int[1];
data.attributes().forEach((key, value) -> {
context.getMatrices().push();

View file

@ -1,10 +1,8 @@
package com.minelittlepony.client.hdskins;
package com.minelittlepony.client.compat.hdskins;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.common.client.gui.ScrollContainer;
import com.minelittlepony.common.client.gui.element.Button;
import com.minelittlepony.common.event.ClientReadyCallback;
@ -28,7 +26,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.item.Items;
import net.minecraft.util.Identifier;
import com.minelittlepony.client.pony.PonyManager;
import com.minelittlepony.client.*;
import com.minelittlepony.client.render.entity.AquaticPlayerPonyRenderer;
/**
@ -53,8 +51,7 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
ClientReadyCallback.EVENT.register(client -> {
// Clear ponies when skins are cleared
PonyManager ponyManager = (PonyManager) MineLittlePony.getInstance().getManager();
SkinCacheClearCallback.EVENT.register(ponyManager::clearCache);
SkinCacheClearCallback.EVENT.register(MineLittlePony.getInstance().getManager()::clearCache);
// Ponify the skins GUI.
GuiSkins.setSkinsGui(GuiSkinsMineLP::new);
@ -102,7 +99,7 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
PlayerSkin main = dummy.getTextures().get(SkinType.SKIN);
Wearable wearable = Wearable.REGISTRY.getOrDefault(type.getId(), Wearable.NONE);
IPonyData metadata = IPony.getManager().getPony(main.getId()).metadata();
PonyData metadata = Pony.getManager().getPony(main.getId()).metadata();
if (wearable != Wearable.NONE && metadata.isWearing(wearable)) {
if (wearable.isSaddlebags() && metadata.race().supportsLegacySaddlebags()) {

View file

@ -1,4 +1,4 @@
package com.minelittlepony.client.hdskins;
package com.minelittlepony.client.compat.hdskins;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.Identifier;

View file

@ -1,13 +1,13 @@
package com.minelittlepony.client.modmenu;
package com.minelittlepony.client.compat.modmenu;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import com.minelittlepony.client.GuiPonySettings;
import com.minelittlepony.client.PonySettingsscreen;
public class MineLPModMenuFactory implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return GuiPonySettings::new;
return PonySettingsscreen::new;
}
}

View file

@ -5,7 +5,7 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
@ -18,10 +18,10 @@ abstract class MixinCamera {
private void redirectCameraDistance(double initial, CallbackInfoReturnable<Double> info) {
double value = info.getReturnValueD();
IPony pony = IPony.getManager().getPony(MinecraftClient.getInstance().player);
Pony pony = Pony.getManager().getPony(MinecraftClient.getInstance().player);
if (!pony.race().isHuman()) {
value *= pony.metadata().size().eyeDistanceFactor();
value *= pony.size().eyeDistanceFactor();
}
info.setReturnValue(value);

View file

@ -1,7 +1,6 @@
package com.minelittlepony.client.mixin;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.client.pony.Pony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.render.EquineRenderManager;
import net.minecraft.client.network.AbstractClientPlayerEntity;
@ -22,7 +21,7 @@ abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implem
public MixinClientPlayerEntity() { super(null, null); }
@Nullable
private IPony pony;
private Pony pony;
@Inject(method = "startRiding(Lnet/minecraft/entity/Entity;Z)Z", at = @At("RETURN"))
private void onStartRiding(Entity entity, boolean bl, CallbackInfoReturnable<Boolean> info) {
@ -35,9 +34,9 @@ abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implem
}
@Override
public boolean shouldUpdateRegistration(IPony pony) {
public boolean shouldUpdateRegistration(Pony pony) {
if (this.pony != pony && (this.pony == null || this.pony.metadata().compareTo(pony.metadata()) != 0)) {
this.pony = Pony.snapshot(pony);
this.pony = pony.immutableCopy();
return true;
}
return false;
@ -47,10 +46,10 @@ abstract class MixinClientPlayerEntity extends AbstractClientPlayerEntity implem
public float getActiveEyeHeight(EntityPose pose, EntityDimensions dimensions) {
float value = super.getActiveEyeHeight(pose, dimensions);
IPony pony = IPony.getManager().getPony(this);
Pony pony = Pony.getManager().getPony(this);
if (!pony.race().isHuman()) {
float factor = pony.metadata().size().eyeHeightFactor();
float factor = pony.size().eyeHeightFactor();
if (factor != 1) {
value *= factor;

View file

@ -102,7 +102,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
*/
@Override
public final void setAngles(T entity, float limbAngle, float limbSpeed, float animationProgress, float headYaw, float headPitch) {
attributes.checkRainboom(entity, canFly(), animationProgress);
attributes.checkRainboom(entity, this, animationProgress);
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(entity, this, ModelAttributes.Mode.OTHER);
super.setAngles(entity, limbAngle, limbSpeed, animationProgress, headYaw, headPitch);
@ -388,7 +388,7 @@ public abstract class AbstractPonyModel<T extends LivingEntity> extends ClientPo
if (attributes.shouldLiftArm(pose, complement, sigma)) {
float swag = 1;
if (!isFlying() && both) {
if (!getAttributes().isFlying && both) {
swag -= (float)Math.pow(limbSpeed, 2);
}

View file

@ -8,10 +8,10 @@ import net.minecraft.util.Hand;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.model.*;
import com.minelittlepony.api.model.fabric.PonyModelPrepareCallback;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.Size;
import com.minelittlepony.api.pony.meta.Sizes;
import com.minelittlepony.mson.api.model.biped.MsonPlayer;
@ -23,7 +23,7 @@ import com.minelittlepony.mson.api.model.biped.MsonPlayer;
*
* 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>, ModelWithHat, ModelWithArms {
public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer<T> implements PonyModel<T> {
/**
* The model attributes.
@ -47,7 +47,7 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
}
@Override
public void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode) {
public void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode) {
child = entity.isBaby();
attributes.updateLivingState(entity, pony, mode);
PonyModelPrepareCallback.EVENT.invoker().onPonyModelPrepared(entity, this, mode);
@ -60,6 +60,18 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
copyStateTo(other);
}
/**
* Copies this model's attributes into the passed model.
*/
@Override
public void copyStateTo(EntityModel<T> model) {
super.copyStateTo(model);
if (model instanceof ClientPonyModel) {
((ClientPonyModel<T>)model).attributes = attributes;
}
}
@Override
public final ModelAttributes getAttributes() {
return attributes;
@ -67,11 +79,11 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
@Override
public Size getSize() {
return child ? Sizes.FOAL : getMetadata().size();
return child ? Sizes.FOAL : PonyModel.super.getSize();
}
@Override
public void setMetadata(IPonyData meta) {
public void setMetadata(PonyData meta) {
attributes.metadata = meta;
}
@ -89,18 +101,6 @@ public abstract class ClientPonyModel<T extends LivingEntity> extends MsonPlayer
return side == Arm.RIGHT ? rightArmPose : leftArmPose;
}
/**
* Copies this model's attributes into the passed model.
*/
@Override
public void copyStateTo(EntityModel<T> model) {
super.copyStateTo(model);
if (model instanceof ClientPonyModel) {
((ClientPonyModel<T>)model).attributes = attributes;
}
}
@Override
public void setHatVisible(boolean visible) {

View file

@ -7,16 +7,14 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Arm;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.IUnicorn;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.Size;
import com.minelittlepony.mson.api.ModelView;
import com.minelittlepony.mson.api.model.BoxBuilder.RenderLayerSetter;
public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>> extends IPonyModel<T>, ModelWithArms {
public interface IPonyMixinModel<T extends LivingEntity, M extends PonyModel<T>> extends PonyModel<T> {
M mixin();
@ -29,7 +27,7 @@ public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>
}
@Override
default void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode) {
default void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode) {
mixin().updateLivingState(entity, pony, mode);
}
@ -54,7 +52,7 @@ public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>
}
@Override
default void setMetadata(IPonyData meta) {
default void setMetadata(PonyData meta) {
mixin().setMetadata(meta);
}
@ -90,7 +88,12 @@ public interface IPonyMixinModel<T extends LivingEntity, M extends IPonyModel<T>
return mixin().getBodyPart(part);
}
interface Caster<T extends LivingEntity, M extends IPonyModel<T> & IUnicorn, ArmModel> extends IPonyMixinModel<T, M>, IUnicorn {
@Override
default void setHatVisible(boolean hatVisible) {
mixin().setHatVisible(hatVisible);
}
interface Caster<T extends LivingEntity, M extends PonyModel<T> & HornedPonyModel<T>, ArmModel> extends IPonyMixinModel<T, M>, HornedPonyModel<T> {
@Override
default boolean isCasting() {
return mixin().isCasting();

View file

@ -1,22 +0,0 @@
package com.minelittlepony.client.model;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.client.render.entity.model.ModelWithArms;
import net.minecraft.entity.LivingEntity;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.ICapitated;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.mson.api.MsonModel;
public interface IPonyModel<T extends LivingEntity> extends IModel, ICapitated<ModelPart>, ModelWithArms, MsonModel {
void copyAttributes(BipedEntityModel<T> other);
void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode);
ModelPart getBodyPart(BodyPart part);
}

View file

@ -8,8 +8,9 @@ import net.minecraft.entity.mob.VexEntity;
import net.minecraft.entity.passive.*;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.gear.IGear;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.gear.*;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.model.armour.PonyArmourModel;
@ -29,7 +30,7 @@ import java.util.stream.Stream;
public final class ModelType {
private static final Map<Race, PlayerModelKey<?, ?>> PLAYER_MODELS = new HashMap<>();
private static final Map<Wearable, GearModelKey<? extends IGear>> GEAR_MODELS = new HashMap<>();
private static final Map<Wearable, GearModelKey<? extends Gear>> GEAR_MODELS = new HashMap<>();
public static final ModelKey<DJPon3EarsModel> DJ_PON_3 = register("dj_pon_three", DJPon3EarsModel::new);
@ -55,14 +56,14 @@ public final class ModelType {
public static final ModelKey<PonyArmourModel<?>> INNER_PONY_ARMOR = register("armor/inner_pony_armor", PonyArmourModel::new);
public static final ModelKey<PonyArmourModel<?>> OUTER_PONY_ARMOR = register("armor/outer_pony_armor", PonyArmourModel::new);
public static final GearModelKey<Stetson> STETSON = registerGear("stetson", Wearable.STETSON, Stetson::new);
public static final GearModelKey<AbstractGearModel> STETSON = registerGear("stetson", Wearable.STETSON, t -> new WearableGear(Wearable.STETSON, BodyPart.HEAD, 0.15F));
public static final GearModelKey<SaddleBags> SADDLEBAGS_BOTH = registerGear("saddlebags", Wearable.SADDLE_BAGS_BOTH, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_BOTH));
public static final GearModelKey<SaddleBags> SADDLEBAGS_LEFT = registerGear(SADDLEBAGS_BOTH, Wearable.SADDLE_BAGS_LEFT, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_LEFT));
public static final GearModelKey<SaddleBags> SADDLEBAGS_RIGHT = registerGear(SADDLEBAGS_BOTH, Wearable.SADDLE_BAGS_RIGHT, t -> new SaddleBags(t, Wearable.SADDLE_BAGS_RIGHT));
public static final GearModelKey<Crown> CROWN = registerGear("crown", Wearable.CROWN, Crown::new);
public static final GearModelKey<Muffin> MUFFIN = registerGear("muffin", Wearable.MUFFIN, Muffin::new);
public static final GearModelKey<WitchHat> WITCH_HAT = registerGear("witch_hat", Wearable.HAT, WitchHat::new);
public static final GearModelKey<ChristmasHat> ANTLERS = registerGear("antlers", Wearable.ANTLERS, ChristmasHat::new);
public static final GearModelKey<AbstractGearModel> MUFFIN = registerGear("muffin", Wearable.MUFFIN, t -> new WearableGear(Wearable.MUFFIN, BodyPart.HEAD, 0.45F).addPart(t.getChild("crown")));
public static final GearModelKey<AbstractGearModel> WITCH_HAT = registerGear("witch_hat", Wearable.HAT, t -> new WearableGear(Wearable.HAT, BodyPart.HEAD, 0.7F).addPart(t.getChild("hat")));
public static final GearModelKey<DeerAntlers> ANTLERS = registerGear("antlers", Wearable.ANTLERS, DeerAntlers::new);
public static final PlayerModelKey<LivingEntity, AlicornModel<?>> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new);
public static final PlayerModelKey<LivingEntity, UnicornModel<?>> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new);
@ -77,27 +78,27 @@ public final class ModelType {
public static final PlayerModelKey<LivingEntity, ChangelingModel<?>> CHANGEDLING = registerPlayer("reformed_changeling", Race.CHANGEDLING, ChangelingModel::new);
public static final PlayerModelKey<LivingEntity, EarthPonyModel<?>> ZEBRA = registerPlayer("zebra", Race.ZEBRA, EarthPonyModel::new);
static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> registerPlayer(String name, Race race,
static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<E, T> registerPlayer(String name, Race race,
BiFunction<ModelPart, Boolean, T> constructor) {
return registerPlayer(name, race, constructor, PonyArmourModel::new);
}
@SuppressWarnings("unchecked")
static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> registerPlayer(String name, Race race,
static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<E, T> registerPlayer(String name, Race race,
BiFunction<ModelPart, Boolean, T> constructor,
MsonModel.Factory<PonyArmourModel<E>> armorFactory) {
return (PlayerModelKey<E, T>)PLAYER_MODELS.computeIfAbsent(race, r -> new PlayerModelKey<>(name, constructor, armorFactory));
}
@SuppressWarnings("unchecked")
static <T extends AbstractGear> GearModelKey<T> registerGear(String name, Wearable wearable, MsonModel.Factory<T> constructor) {
static <T extends AbstractGearModel> GearModelKey<T> registerGear(String name, Wearable wearable, MsonModel.Factory<T> constructor) {
return (GearModelKey<T>)GEAR_MODELS.computeIfAbsent(wearable, w -> {
return new GearModelKey<T>(Mson.getInstance().registerModel(new Identifier("minelittlepony", "gear/" + name), constructor), constructor);
});
}
@SuppressWarnings("unchecked")
static <T extends AbstractGear> GearModelKey<T> registerGear(GearModelKey<T> key, Wearable wearable, MsonModel.Factory<T> constructor) {
static <T extends AbstractGearModel> GearModelKey<T> registerGear(GearModelKey<T> key, Wearable wearable, MsonModel.Factory<T> constructor) {
return (GearModelKey<T>)GEAR_MODELS.computeIfAbsent(wearable, w -> new GearModelKey<T>(key.key, constructor));
}
@ -107,17 +108,17 @@ public final class ModelType {
@SuppressWarnings("unchecked")
@Nullable
public static <E extends LivingEntity, T extends Model & MsonModel & IModel> PlayerModelKey<E, T> getPlayerModel(Race race) {
public static <E extends LivingEntity, T extends Model & MsonModel & PonyModel<?>> PlayerModelKey<E, T> getPlayerModel(Race race) {
return (PlayerModelKey<E, T>)PLAYER_MODELS.get(race);
}
public static Stream<Map.Entry<Wearable, GearModelKey<? extends IGear>>> getWearables() {
public static Stream<Map.Entry<Wearable, GearModelKey<? extends Gear>>> getWearables() {
return GEAR_MODELS.entrySet().stream();
}
public static void bootstrap() { }
public record GearModelKey<T extends IGear>(ModelKey<T> key, MsonModel.Factory<T> constructor) {
public record GearModelKey<T extends Gear>(ModelKey<T> key, MsonModel.Factory<T> constructor) {
public T createModel() {
return key.createModel(constructor);
}

View file

@ -6,10 +6,10 @@ import net.minecraft.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.IModelWrapper;
import com.minelittlepony.api.model.armour.*;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.mson.api.*;
@ -19,7 +19,7 @@ import java.util.function.Consumer;
/**
* Container class for the various models and their associated piece of armour.
*/
public class ModelWrapper<T extends LivingEntity, M extends IModel> implements IModelWrapper {
public class ModelWrapper<T extends LivingEntity, M extends PonyModel<?>> implements IModelWrapper {
@Nullable
private final MsonModel.Factory<PonyArmourModel<T>> armorFactory;
private final Map<ModelKey<PonyArmourModel<?>>, PonyArmourModel<T>> armor = new HashMap<>();
@ -51,7 +51,7 @@ public class ModelWrapper<T extends LivingEntity, M extends IModel> implements I
}
@Override
public ModelWrapper<T, M> applyMetadata(IPonyData meta) {
public ModelWrapper<T, M> applyMetadata(PonyData meta) {
body.setMetadata(meta);
armor.values().forEach(a -> a.setMetadata(meta));
return this;

View file

@ -7,13 +7,13 @@ import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.mson.api.*;
import java.util.function.*;
public record PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel & IModel> (
public record PlayerModelKey<T extends LivingEntity, M extends Model & PonyModel<?>> (
ModelKey<M> steveKey,
ModelKey<M> alexKey,
MsonModel.Factory<PonyArmourModel<T>> armorFactory
@ -30,12 +30,12 @@ public record PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel
return slimArms ? alexKey : steveKey;
}
public <K extends T, N extends M> ModelWrapper<K, N> create(boolean slimArms) {
public <E extends T, N extends M> ModelWrapper<E, N> create(boolean slimArms) {
return create(slimArms, null);
}
@SuppressWarnings({"rawtypes", "unchecked"})
public <K extends T, N extends M> ModelWrapper<K, N> create(boolean slimArms, @Nullable Consumer<N> initializer) {
public <E extends T, N extends M> ModelWrapper<E, N> create(boolean slimArms, @Nullable Consumer<N> initializer) {
return new ModelWrapper(this, slimArms, initializer);
}
}

View file

@ -5,9 +5,9 @@ import net.minecraft.client.render.entity.model.BipedEntityModel;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.LivingEntity;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.armour.*;
import com.minelittlepony.client.model.AbstractPonyModel;
import com.minelittlepony.client.model.IPonyModel;
public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T> implements IArmourModel<T> {
@ -18,7 +18,7 @@ public class PonyArmourModel<T extends LivingEntity> extends AbstractPonyModel<T
@Override
public boolean poseModel(T entity, float limbAngle, float limbDistance, float age, float headYaw, float headPitch,
EquipmentSlot slot, ArmourLayer layer,
IPonyModel<T> mainModel) {
PonyModel<T> mainModel) {
if (!setVisibilities(slot, layer)) {
return false;

View file

@ -6,6 +6,8 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.mob.EndermanEntity;
import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.pony.meta.Race;
public class EnderStallionModel extends SkeleponyModel<EndermanEntity> {
public boolean isCarrying;
@ -54,8 +56,8 @@ public class EnderStallionModel extends SkeleponyModel<EndermanEntity> {
}
@Override
public boolean canFly() {
return isAlicorn;
public Race getRace() {
return isAlicorn ? (super.getRace().hasHorn() ? Race.ALICORN : Race.PEGASUS) : super.getRace();
}
@Override

View file

@ -7,7 +7,7 @@ import net.minecraft.entity.mob.PiglinActivity;
import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
public class PiglinPonyModel extends ZomponyModel<HostileEntity> {
@ -23,7 +23,7 @@ public class PiglinPonyModel extends ZomponyModel<HostileEntity> {
}
@Override
public void updateLivingState(HostileEntity entity, IPony pony, ModelAttributes.Mode mode) {
public void updateLivingState(HostileEntity entity, Pony pony, ModelAttributes.Mode mode) {
super.updateLivingState(entity, pony, mode);
leftArmPose = ArmPose.EMPTY;
rightArmPose = entity.getMainHandStack().isEmpty() ? ArmPose.EMPTY : ArmPose.ITEM;

View file

@ -8,10 +8,10 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.Arm;
import net.minecraft.util.Hand;
import com.minelittlepony.client.model.IMobModel;
import com.minelittlepony.api.model.MobPosingHelper;
import com.minelittlepony.client.model.entity.race.AlicornModel;
public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> implements IMobModel {
public class SkeleponyModel<T extends HostileEntity> extends AlicornModel<T> {
public boolean isUnicorn;
@ -68,7 +68,7 @@ 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);
MobPosingHelper.rotateArmHolding(arm, direction, swingProgress, ticks);
}
@Override

View file

@ -8,7 +8,7 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.client.model.entity.race.EarthPonyModel;
@ -19,7 +19,7 @@ public class WitchPonyModel extends EarthPonyModel<WitchEntity> {
}
@Override
public void updateLivingState(WitchEntity entity, IPony pony, ModelAttributes.Mode mode) {
public void updateLivingState(WitchEntity entity, Pony pony, ModelAttributes.Mode mode) {
super.updateLivingState(entity, pony, mode);
if (entity.hasCustomName() && "Filly".equals(entity.getCustomName().getString())) {
@ -71,9 +71,6 @@ public class WitchPonyModel extends EarthPonyModel<WitchEntity> {
@Override
public boolean isWearing(Wearable wearable) {
if (wearable == Wearable.HAT) {
return true;
}
return super.isWearing(wearable);
return wearable == Wearable.HAT || super.isWearing(wearable);
}
}

View file

@ -1,11 +1,12 @@
package com.minelittlepony.client.model.entity;
import com.minelittlepony.client.model.IMobModel;
import com.minelittlepony.api.model.MobPosingHelper;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.model.entity.race.AlicornModel;
import net.minecraft.client.model.ModelPart;
import net.minecraft.entity.mob.HostileEntity;
public class ZomponyModel<Zombie extends HostileEntity> extends AlicornModel<Zombie> implements IMobModel {
public class ZomponyModel<Zombie extends HostileEntity> extends AlicornModel<Zombie> {
private boolean isPegasus;
@ -23,13 +24,13 @@ public class ZomponyModel<Zombie extends HostileEntity> extends AlicornModel<Zom
protected void rotateLegs(float move, float swing, float ticks, Zombie entity) {
super.rotateLegs(move, swing, ticks, entity);
if (isZombified(entity)) {
IMobModel.rotateUndeadArms(this, move, ticks);
MobPosingHelper.rotateUndeadArms(this, move, ticks);
}
}
@Override
public boolean canFly() {
return isPegasus;
public Race getRace() {
return isPegasus ? (super.getRace().hasHorn() ? Race.ALICORN : Race.PEGASUS) : super.getRace();
}
protected boolean isZombified(Zombie entity) {

View file

@ -1,14 +1,14 @@
package com.minelittlepony.client.model.entity.race;
import com.minelittlepony.api.model.IPart;
import com.minelittlepony.api.model.IPegasus;
import com.minelittlepony.api.model.WingedPonyModel;
import com.minelittlepony.client.model.part.PonyWings;
import com.minelittlepony.mson.api.ModelView;
import net.minecraft.client.model.ModelPart;
import net.minecraft.entity.LivingEntity;
public class AlicornModel<T extends LivingEntity> extends UnicornModel<T> implements IPegasus {
public class AlicornModel<T extends LivingEntity> extends UnicornModel<T> implements WingedPonyModel<T> {
private PonyWings<AlicornModel<T>> wings;
@ -20,7 +20,7 @@ public class AlicornModel<T extends LivingEntity> extends UnicornModel<T> implem
public void init(ModelView context) {
super.init(context);
wings = addPart(context.findByName("wings"));
bodyRenderList.add(forPart(this::getWings).checked(this::canFly));
bodyRenderList.add(forPart(this::getWings).checked(() -> getRace().hasWings()));
}
@Override

View file

@ -12,12 +12,12 @@ public class ChangelingModel<T extends LivingEntity> extends AlicornModel<T> {
@Override
public boolean wingsAreOpen() {
return (isFlying() || attributes.isCrouching) && !getAttributes().isGliding;
return (getAttributes().isFlying || getAttributes().isCrouching) && !getAttributes().isGliding;
}
@Override
public float getWingRotationFactor(float ticks) {
if (isFlying()) {
if (getAttributes().isFlying) {
return MathHelper.sin(ticks * 3) + WINGS_HALF_SPREAD_ANGLE;
}
return WINGS_RAISED_ANGLE;

View file

@ -1,14 +1,14 @@
package com.minelittlepony.client.model.entity.race;
import com.minelittlepony.api.model.IPart;
import com.minelittlepony.api.model.IPegasus;
import com.minelittlepony.api.model.WingedPonyModel;
import com.minelittlepony.client.model.part.PonyWings;
import com.minelittlepony.mson.api.ModelView;
import net.minecraft.client.model.ModelPart;
import net.minecraft.entity.LivingEntity;
public class PegasusModel<T extends LivingEntity> extends EarthPonyModel<T> implements IPegasus {
public class PegasusModel<T extends LivingEntity> extends EarthPonyModel<T> implements WingedPonyModel<T> {
private PonyWings<PegasusModel<T>> wings;

View file

@ -3,7 +3,7 @@ package com.minelittlepony.client.model.entity.race;
import com.minelittlepony.client.model.armour.PonyArmourModel;
import com.minelittlepony.mson.api.ModelView;
import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.util.math.MatrixStack;
@ -45,7 +45,7 @@ public class SeaponyModel<T extends LivingEntity> extends UnicornModel<T> {
}
@Override
public void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode) {
public void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode) {
super.updateLivingState(entity, pony, mode);
// Seaponies can't sneak, silly
@ -123,7 +123,7 @@ public class SeaponyModel<T extends LivingEntity> extends UnicornModel<T> {
}
@Override
public void updateLivingState(T entity, IPony pony, ModelAttributes.Mode mode) {
public void updateLivingState(T entity, Pony pony, ModelAttributes.Mode mode) {
super.updateLivingState(entity, pony, mode);
// Seaponies can't sneak, silly

View file

@ -16,7 +16,7 @@ import net.minecraft.util.*;
/**
* Used for both unicorns and alicorns since there's no logical way to keep them distinct and not duplicate stuff.
*/
public class UnicornModel<T extends LivingEntity> extends EarthPonyModel<T> implements IUnicorn {
public class UnicornModel<T extends LivingEntity> extends EarthPonyModel<T> implements HornedPonyModel<T> {
protected final ModelPart unicornArmRight;
protected final ModelPart unicornArmLeft;
@ -33,10 +33,10 @@ public class UnicornModel<T extends LivingEntity> extends EarthPonyModel<T> impl
public void init(ModelView context) {
super.init(context);
horn = addPart(context.findByName("horn"));
headRenderList.add(RenderList.of().add(head::rotate).add(forPart(horn)).checked(this::hasHorn));
headRenderList.add(RenderList.of().add(head::rotate).add(forPart(horn)).checked(() -> getRace().hasHorn()));
this.mainRenderList.add(withStage(BodyPart.HEAD, RenderList.of().add(head::rotate).add((stack, vertices, overlayUv, lightUv, red, green, blue, alpha) -> {
horn.renderMagic(stack, vertices, getMagicColor());
})).checked(() -> hasHorn() && hasMagic() && isCasting()));
horn.renderMagic(stack, vertices, getAttributes().metadata.glowColor());
})).checked(() -> hasMagic() && isCasting()));
}
@Override

View file

@ -7,19 +7,19 @@ import net.minecraft.entity.mob.ZombifiedPiglinEntity;
import net.minecraft.entity.player.PlayerEntity;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.gear.IStackable;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.gear.WearableGear;
import com.minelittlepony.api.pony.meta.Wearable;
public class Crown extends AbstractWearableGear implements IStackable {
public class Crown extends WearableGear {
public Crown(ModelPart tree) {
super(Wearable.CROWN, BodyPart.HEAD);
super(Wearable.CROWN, BodyPart.HEAD, 0.1F);
addPart(tree.getChild("crown"));
}
@Override
public boolean canRender(IModel model, Entity entity) {
public boolean canRender(PonyModel<?> model, Entity entity) {
return super.canRender(model, entity)
|| ((
entity instanceof AbstractPiglinEntity
@ -28,9 +28,4 @@ public class Crown extends AbstractWearableGear implements IStackable {
) && entity.hasCustomName() && entity.getCustomName().getString().equalsIgnoreCase("technoblade")
);
}
@Override
public float getStackingHeight() {
return 0.1F;
}
}

View file

@ -7,15 +7,15 @@ import net.minecraft.entity.Entity;
import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.gear.WearableGear;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.common.util.Color;
import java.util.Calendar;
import java.util.UUID;
public class ChristmasHat extends AbstractWearableGear {
public class DeerAntlers extends WearableGear {
private static boolean dayChecked = false;
private static boolean dayResult = false;
private static boolean isChristmasDay() {
@ -35,19 +35,19 @@ public class ChristmasHat extends AbstractWearableGear {
private int tint;
public ChristmasHat(ModelPart tree) {
super(Wearable.ANTLERS, BodyPart.HEAD);
public DeerAntlers(ModelPart tree) {
super(Wearable.ANTLERS, BodyPart.HEAD, 0);
left = tree.getChild("left");
right = tree.getChild("right");
}
@Override
public boolean canRender(IModel model, Entity entity) {
public boolean canRender(PonyModel<?> model, Entity entity) {
return isChristmasDay() || super.canRender(model, entity);
}
@Override
public void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
public void pose(PonyModel<?> model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
float pi = MathHelper.PI * (float) Math.pow(swing, 16);
float mve = move * 0.6662f;
@ -57,7 +57,7 @@ public class ChristmasHat extends AbstractWearableGear {
bodySwing += 0.1F;
tint = model.getMetadata().glowColor();
tint = model.getAttributes().metadata.glowColor();
left.roll = bodySwing;
right.roll = -bodySwing;
}

View file

@ -1,19 +0,0 @@
package com.minelittlepony.client.model.gear;
import net.minecraft.client.model.ModelPart;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.gear.IStackable;
import com.minelittlepony.api.pony.meta.Wearable;
public class Muffin extends AbstractWearableGear implements IStackable {
public Muffin(ModelPart tree) {
super(Wearable.MUFFIN, BodyPart.HEAD);
addPart(tree.getChild("crown"));
}
@Override
public float getStackingHeight() {
return 0.45F;
}
}

View file

@ -1,8 +1,9 @@
package com.minelittlepony.client.model.gear;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.IPegasus;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.WingedPonyModel;
import com.minelittlepony.api.model.gear.WearableGear;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.util.MathUtil;
@ -15,7 +16,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
public class SaddleBags extends AbstractWearableGear {
public class SaddleBags extends WearableGear {
public static final Identifier TEXTURE = new Identifier("minelittlepony", "textures/models/saddlebags.png");
@ -29,19 +30,15 @@ public class SaddleBags extends AbstractWearableGear {
private float dropAmount = 0;
public SaddleBags(ModelPart tree, Wearable wearable) {
super(wearable, BodyPart.BODY);
super(wearable, BodyPart.BODY, 0);
strap = tree.getChild("strap");
leftBag = tree.getChild("left_bag");
rightBag = tree.getChild("right_bag");
}
@Override
public void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
hangLow = false;
if (model instanceof IPegasus) {
hangLow = model.canFly() && ((IPegasus)model).wingsAreOpen();
}
public void pose(PonyModel<?> model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
hangLow = model instanceof WingedPonyModel pegasus && pegasus.wingsAreOpen();
float pi = MathHelper.PI * (float) Math.pow(swing, 16);
@ -53,8 +50,8 @@ public class SaddleBags extends AbstractWearableGear {
leftBag.pitch = bodySwing;
rightBag.pitch = bodySwing;
if (model instanceof IPegasus && model.isFlying()) {
bodySwing = ((IPegasus)model).getWingRotationFactor(ticks) - MathUtil.Angles._270_DEG;
if (model instanceof WingedPonyModel pegasus && pegasus.getAttributes().isFlying) {
bodySwing = pegasus.getWingRotationFactor(ticks) - MathUtil.Angles._270_DEG;
bodySwing /= 10;
}
@ -66,7 +63,7 @@ public class SaddleBags extends AbstractWearableGear {
strap.visible = wearable == Wearable.SADDLE_BAGS_BOTH;
dropAmount = hangLow ? 0.15F : 0;
dropAmount = model.getMetadata().getInterpolator(interpolatorId).interpolate("dropAmount", dropAmount, 3);
dropAmount = model.getAttributes().metadata.getInterpolator(interpolatorId).interpolate("dropAmount", dropAmount, 3);
}
@Override

View file

@ -1,19 +0,0 @@
package com.minelittlepony.client.model.gear;
import net.minecraft.client.model.ModelPart;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.gear.IStackable;
import com.minelittlepony.api.pony.meta.Wearable;
public class Stetson extends AbstractWearableGear implements IStackable {
public Stetson(ModelPart tree) {
super(Wearable.STETSON, BodyPart.HEAD);
addPart(tree.getChild("rim"));
}
@Override
public float getStackingHeight() {
return 0.15F;
}
}

View file

@ -1,19 +0,0 @@
package com.minelittlepony.client.model.gear;
import net.minecraft.client.model.ModelPart;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.gear.IStackable;
import com.minelittlepony.api.pony.meta.Wearable;
public class WitchHat extends AbstractWearableGear implements IStackable {
public WitchHat(ModelPart tree) {
super(Wearable.HAT, BodyPart.HEAD);
addPart(tree.getChild("hat"));
}
@Override
public float getStackingHeight() {
return 0.7F;
}
}

View file

@ -12,7 +12,7 @@ import com.minelittlepony.mson.api.ModelView;
import com.minelittlepony.mson.api.MsonModel;
import com.minelittlepony.util.MathUtil;
public class PonyWings<T extends Model & IPegasus> implements IPart, MsonModel {
public class PonyWings<T extends Model & WingedPonyModel<?>> implements IPart, MsonModel {
protected T pegasus;
@ -49,7 +49,11 @@ public class PonyWings<T extends Model & IPegasus> implements IPart, MsonModel {
}
public Wing getRight() {
return (pegasus.isEmbedded(Wearable.SADDLE_BAGS_BOTH) || pegasus.isEmbedded(Wearable.SADDLE_BAGS_LEFT) || pegasus.isEmbedded(Wearable.SADDLE_BAGS_RIGHT)) ? legacyWing : rightWing;
return (
pegasus.isEmbedded(Wearable.SADDLE_BAGS_BOTH)
|| pegasus.isEmbedded(Wearable.SADDLE_BAGS_LEFT)
|| pegasus.isEmbedded(Wearable.SADDLE_BAGS_RIGHT)
) ? legacyWing : rightWing;
}
@Override
@ -82,7 +86,7 @@ public class PonyWings<T extends Model & IPegasus> implements IPart, MsonModel {
flapAngle = MathUtil.Angles._270_DEG - 0.9F + (float)Math.sin(ticks / 10) / 15F;
}
if (!pegasus.isFlying()) {
if (!pegasus.getAttributes().isFlying) {
flapAngle = attributes.getMainInterpolator().interpolate("wingFlap", flapAngle, 10);
}
@ -99,7 +103,7 @@ public class PonyWings<T extends Model & IPegasus> implements IPart, MsonModel {
public static class Wing implements MsonModel {
protected IPegasus pegasus;
protected WingedPonyModel<?> pegasus;
protected final ModelPart extended;
protected final ModelPart folded;
@ -119,14 +123,14 @@ public class PonyWings<T extends Model & IPegasus> implements IPart, MsonModel {
public void rotateWalking(float swing) {
folded.yaw = swing * walkingRotationSpeed;
if (pegasus.getMetadata().race().hasBugWings()) {
if (pegasus.getRace().hasBugWings()) {
extended.yaw = folded.yaw;
}
}
public void rotateFlying(float roll) {
extended.roll = roll;
if (pegasus.getMetadata().race().hasBugWings()) {
if (pegasus.getRace().hasBugWings()) {
folded.roll = roll;
}
}

View file

@ -1,43 +0,0 @@
package com.minelittlepony.client.pony;
import java.util.function.Consumer;
public interface Memoize<T> {
T get();
default T get(T fallback) {
T value = get();
return value == null ? fallback : value;
}
default boolean isPresent() {
return true;
}
static <T> Memoize<T> of(T value) {
return () -> value;
}
static <T> Memoize<T> load(Consumer<Consumer<T>> factory) {
return new Memoize<>() {
T value;
boolean loadRequested;
@Override
public T get() {
synchronized (this) {
if (!loadRequested) {
loadRequested = true;
factory.accept(value -> {
this.value = value;
});
}
}
return value;
}
@Override
public boolean isPresent() {
return value != null;
}
};
}
}

View file

@ -1,32 +0,0 @@
package com.minelittlepony.client.pony;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.network.MsgPonyData;
import net.minecraft.util.Identifier;
public record Pony (
Identifier texture,
Memoize<IPonyData> memoizedData,
boolean defaulted
) implements IPony {
Pony(Identifier resource) {
this(resource, PonyData.parse(resource), false);
}
@Override
public boolean hasMetadata() {
return memoizedData.isPresent();
}
@Override
public IPonyData metadata() {
return memoizedData.get(PonyData.NULL);
}
public static IPony snapshot(IPony pony) {
return new Pony(pony.texture(), Memoize.of(new MsgPonyData(pony.metadata(), pony.defaulted())), pony.defaulted());
}
}

View file

@ -1,118 +0,0 @@
package com.minelittlepony.client.pony;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.pony.IPonyData;
import com.minelittlepony.api.pony.TriggerPixelType;
import com.minelittlepony.api.pony.meta.*;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.util.render.NativeUtil;
import java.io.IOException;
import java.util.*;
import org.jetbrains.annotations.Nullable;
/**
* Implementation for IPonyData.
*/
public record PonyData (
Race race,
TailLength tailLength,
TailShape tailShape,
Gender gender,
Size size,
int glowColor,
boolean[] wearables,
Map<String, TriggerPixelType<?>> attributes
) implements IPonyData {
private static final PonyDataSerialiser SERIALISER = new PonyDataSerialiser();
public static final IPonyData NULL = new PonyData(Race.HUMAN);
public static final Memoize<IPonyData> MEM_NULL = Memoize.of(NULL);
/**
* Parses the given resource into a new IPonyData.
* This may either come from an attached json file or the image itself.
*/
public static Memoize<IPonyData> parse(@Nullable Identifier identifier) {
if (identifier == null) {
return MEM_NULL;
}
return MinecraftClient.getInstance().getResourceManager().getResource(identifier).flatMap(res -> {
try {
return res.getMetadata().decode(SERIALISER);
} catch (IOException e) {
MineLittlePony.logger.warn("Unable to read {} metadata", identifier, e);
}
return null;
}).map(Memoize::of).orElseGet(() -> {
return Memoize.load(callback -> {
NativeUtil.parseImage(identifier, image -> {
callback.accept(new PonyData(
TriggerPixel.RACE.<Race>readValue(image),
TriggerPixel.TAIL.<TailLength>readValue(image),
TriggerPixel.TAIL_SHAPE.<TailShape>readValue(image),
TriggerPixel.GENDER.<Gender>readValue(image),
TriggerPixel.SIZE.<Size>readValue(image),
TriggerPixel.GLOW.readColor(image),
TriggerPixel.WEARABLES.readFlags(image)
));
}, e -> {
MineLittlePony.logger.fatal("Unable to read {} metadata", identifier, e);
callback.accept(NULL);
});
});
});
}
public PonyData(Race race) {
this(race, TailLength.FULL, TailShape.STRAIGHT, Gender.MARE, Sizes.NORMAL, 0x4444aa, new boolean[Wearable.values().length], new TreeMap<>());
attributes.put("race", race);
attributes.put("tailLength", tailLength);
attributes.put("tailShape", tailShape);
attributes.put("gender", gender);
attributes.put("size", size);
attributes.put("magic", TriggerPixelType.of(glowColor));
attributes.put("gear", TriggerPixelType.of(0));
}
PonyData(TriggerPixelType.Value<Race> race, TriggerPixelType.Value<TailLength> tailLength, TriggerPixelType.Value<TailShape> tailShape,
TriggerPixelType.Value<Gender> gender, TriggerPixelType.Value<Size> size, int glowColor, TriggerPixelType.Flags<Wearable> wearables) {
this(race.value(), tailLength.value(), tailShape.value(), gender.value(), size.value(), glowColor, wearables.value(), new TreeMap<>());
attributes.put("race", race);
attributes.put("tailLength", tailLength);
attributes.put("tailShape", tailShape);
attributes.put("gender", gender);
attributes.put("size", size);
attributes.put("magic", TriggerPixelType.of(glowColor));
attributes.put("gear", wearables);
}
@Override
public Size size() {
Sizes sz = MineLittlePony.getInstance().getConfig().sizeOverride.get();
if (sz != Sizes.UNSET) {
return sz;
}
if (size == Sizes.UNSET || !MineLittlePony.getInstance().getConfig().sizes.get()) {
return Sizes.NORMAL;
}
return size;
}
@Override
public Wearable[] gear() {
return Wearable.flags(wearables);
}
@Override
public boolean isWearing(Wearable wearable) {
return wearables[wearable.ordinal()];
}
}

View file

@ -1,26 +0,0 @@
package com.minelittlepony.client.pony;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.minelittlepony.api.pony.IPonyData;
import net.minecraft.resource.metadata.ResourceMetadataReader;
class PonyDataSerialiser implements ResourceMetadataReader<IPonyData> {
private static final Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.create();
@Override
public String getKey() {
return "pony";
}
@Override
public IPonyData fromJson(JsonObject json) {
return gson.fromJson(json, PonyData.class);
}
}

View file

@ -13,12 +13,12 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import com.minelittlepony.api.model.RenderPass;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.PonyBounds;
public final class DebugBoundingBoxRenderer {
public static <T extends LivingEntity> void render(IPony pony, EntityRenderer<T> renderer, T entity, MatrixStack stack, VertexConsumerProvider renderContext, float tickDelta) {
public static <T extends LivingEntity> void render(Pony pony, EntityRenderer<T> renderer, T entity, MatrixStack stack, VertexConsumerProvider renderContext, float tickDelta) {
if (RenderPass.getCurrent() != RenderPass.WORLD) {
return;

View file

@ -1,13 +1,10 @@
package com.minelittlepony.client.render;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.model.RenderPass;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.network.MsgPonyData;
import com.minelittlepony.api.model.*;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.network.fabric.Channel;
import com.minelittlepony.api.pony.network.fabric.PonyDataCallback;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.model.ModelWrapper;
import com.minelittlepony.client.transform.PonyPosture;
import com.minelittlepony.mson.api.ModelKey;
@ -25,7 +22,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> {
public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> {
private ModelWrapper<T, M> playerModel;
@ -104,7 +101,7 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
// negate vanilla translations so the rider begins at the ridees feet.
stack.translate(0, -ridingEntity.getHeight(), 0);
IPony riderPony = renderer.getEntityPony(ridingEntity);
Pony riderPony = renderer.getEntityPony(ridingEntity);
renderer.translateRider(ridingEntity, riderPony, entity, renderer.getEntityPony(entity), stack, ticks);
}
@ -119,8 +116,8 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
PonyPosture.of(getModel().getAttributes()).apply(entity, getModel(), stack, yaw, tickDelta, -1);
}
public IPony updateModel(T entity, ModelAttributes.Mode mode) {
IPony pony = renderer.getEntityPony(entity);
public Pony updateModel(T entity, ModelAttributes.Mode mode) {
Pony pony = renderer.getEntityPony(entity);
playerModel.applyMetadata(pony.metadata());
if (pony.hasMetadata() && entity instanceof RegistrationHandler && ((RegistrationHandler)entity).shouldUpdateRegistration(pony)) {
@ -129,10 +126,10 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
PlayerEntity clientPlayer = MinecraftClient.getInstance().player;
if (clientPlayer != null) {
if (Objects.equals(entity, clientPlayer) || Objects.equals(((PlayerEntity)entity).getGameProfile(), clientPlayer.getGameProfile())) {
Channel.broadcastPonyData(new MsgPonyData(pony.metadata(), pony.defaulted()));
Channel.broadcastPonyData(pony.metadata());
}
}
PonyDataCallback.EVENT.invoker().onPonyDataAvailable((PlayerEntity)entity, pony.metadata(), pony.defaulted(), EnvType.CLIENT);
PonyDataCallback.EVENT.invoker().onPonyDataAvailable((PlayerEntity)entity, pony.metadata(), EnvType.CLIENT);
}
getModel().updateLivingState(entity, pony, mode);
@ -168,6 +165,6 @@ public class EquineRenderManager<T extends LivingEntity, M extends EntityModel<T
}
public interface RegistrationHandler {
boolean shouldUpdateRegistration(IPony pony);
boolean shouldUpdateRegistration(Pony pony);
}
}

View file

@ -1,25 +1,25 @@
package com.minelittlepony.client.render;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.gear.IGear;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.client.model.*;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.gear.Gear;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.util.MathUtil;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
public interface IPonyRenderContext<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> extends IGear.Context<T, M> {
public interface IPonyRenderContext<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends Gear.Context<T, M> {
IPony getEntityPony(T entity);
Pony getEntityPony(T entity);
EquineRenderManager<T, M> getInternalRenderer();
/**
* Called by riders to have their transportation adjust their position.
*/
default void translateRider(T entity, IPony entityPony, LivingEntity passenger, IPony passengerPony, MatrixStack stack, float ticks) {
default void translateRider(T entity, Pony entityPony, LivingEntity passenger, Pony passengerPony, MatrixStack stack, float ticks) {
if (!passengerPony.race().isHuman()) {
float yaw = MathUtil.interpolateDegress((float)entity.prevY, (float)entity.getY(), ticks);

View file

@ -1,6 +1,6 @@
package com.minelittlepony.client.render;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.util.render.RenderLayerUtil;
@ -21,7 +21,7 @@ import net.minecraft.util.math.RotationAxis;
import net.minecraft.world.World;
public class LevitatingItemRenderer {
private VertexConsumerProvider getProvider(IPony pony, VertexConsumerProvider renderContext) {
private VertexConsumerProvider getProvider(Pony pony, VertexConsumerProvider renderContext) {
final int color = pony.metadata().glowColor();
return layer -> {
Identifier texture = RenderLayerUtil.getTexture(layer).orElse(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE);
@ -39,7 +39,7 @@ public class LevitatingItemRenderer {
if (entity instanceof PlayerEntity && (mode.isFirstPerson() || mode == ModelTransformationMode.THIRD_PERSON_LEFT_HAND || mode == ModelTransformationMode.THIRD_PERSON_RIGHT_HAND)) {
IPony pony = IPony.getManager().getPony((PlayerEntity)entity);
Pony pony = Pony.getManager().getPony((PlayerEntity)entity);
matrix.push();

View file

@ -1,10 +1,11 @@
package com.minelittlepony.client.render;
import java.util.function.Function;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.client.mixin.MixinEntityRenderers;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.render.entity.PlayerPonyRenderer;
import com.minelittlepony.client.render.entity.AquaticPlayerPonyRenderer;
@ -45,7 +46,7 @@ public class PonyRenderDispatcher {
Mson.getInstance().getEntityRendererRegistry().registerPlayerRenderer(
new Identifier("minelittlepony", "sea/" + armShape.getName()),
player -> {
return !IPony.getManager().getPony(player).race().isHuman()
return !Pony.getManager().getPony(player).race().isHuman()
&& PonyPosture.hasSeaponyForm(player)
&& player.method_52814().model() == armShape;
},
@ -54,7 +55,7 @@ public class PonyRenderDispatcher {
Mson.getInstance().getEntityRendererRegistry().registerPlayerRenderer(
new Identifier("minelittlepony", "land/" + armShape.getName()),
player -> {
return !IPony.getManager().getPony(player).race().isHuman()
return !Pony.getManager().getPony(player).race().isHuman()
&& !PonyPosture.hasSeaponyForm(player)
&& player.method_52814().model() == armShape;
},
@ -82,7 +83,7 @@ public class PonyRenderDispatcher {
@SuppressWarnings("unchecked")
@Nullable
public <T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> IPonyRenderContext<T, M> getPonyRenderer(@Nullable T entity) {
public <T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> IPonyRenderContext<T, M> getPonyRenderer(@Nullable T entity) {
if (entity == null) {
return null;
}

View file

@ -2,7 +2,7 @@ package com.minelittlepony.client.render.blockentity.skull;
import com.google.common.base.Suppliers;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.model.AbstractPonyModel;
import com.minelittlepony.client.render.MobRenderers;
import com.minelittlepony.client.render.blockentity.skull.PonySkullRenderer.ISkull;
@ -43,7 +43,7 @@ public class MobSkull implements ISkull {
}
@Override
public boolean bindPony(IPony pony) {
public boolean bindPony(Pony pony) {
ponyHead.get().setMetadata(pony.metadata());
return true;
}

View file

@ -2,7 +2,7 @@ package com.minelittlepony.client.render.blockentity.skull;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.config.PonyLevel;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.*;
@ -52,7 +52,7 @@ public class PlayerPonySkull implements ISkull {
}
@Override
public boolean bindPony(IPony pony) {
public boolean bindPony(Pony pony) {
Race race = pony.race();
if (race.isHuman()) {
race = Race.EARTH;

View file

@ -2,7 +2,7 @@ package com.minelittlepony.client.render.blockentity.skull;
import com.google.common.collect.Maps;
import com.minelittlepony.api.config.PonyConfig;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.render.MobRenderers;
@ -68,7 +68,7 @@ public class PonySkullRenderer {
return false;
}
if (!selectedSkull.bindPony(IPony.getManager().getPony(selectedSkin))) {
if (!selectedSkull.bindPony(Pony.getManager().getPony(selectedSkin))) {
return false;
}
@ -112,6 +112,6 @@ public class PonySkullRenderer {
Identifier getSkinResource(@Nullable GameProfile profile);
boolean bindPony(IPony pony);
boolean bindPony(Pony pony);
}
}

View file

@ -1,6 +1,7 @@
package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.model.*;
import com.minelittlepony.client.render.DebugBoundingBoxRenderer;
@ -26,7 +27,7 @@ import net.minecraft.entity.mob.MobEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public abstract class AbstractPonyRenderer<T extends MobEntity, M extends EntityModel<T> & IPonyModel<T> & ModelWithArms> extends MobEntityRenderer<T, M> implements IPonyRenderContext<T, M> {
public abstract class AbstractPonyRenderer<T extends MobEntity, M extends EntityModel<T> & PonyModel<T> & ModelWithArms> extends MobEntityRenderer<T, M> implements IPonyRenderContext<T, M> {
protected final EquineRenderManager<T, M> manager = new EquineRenderManager<>(this);
@ -132,8 +133,8 @@ public abstract class AbstractPonyRenderer<T extends MobEntity, M extends Entity
}
@Override
public IPony getEntityPony(T entity) {
return IPony.getManager().getPony(getTexture(entity));
public Pony getEntityPony(T entity) {
return Pony.getManager().getPony(getTexture(entity));
}
public static <E extends MobEntity, M extends ClientPonyModel<E>, T extends PonyRenderer<E, M>, F extends FeatureRenderer<E, M>>
@ -143,7 +144,7 @@ public abstract class AbstractPonyRenderer<T extends MobEntity, M extends Entity
}
@SuppressWarnings({"unchecked", "rawtypes"})
public static <T extends MobEntity, M extends EntityModel<T> & IPonyModel<T> & ModelWithArms> AbstractPonyRenderer<T, M> proxy(EntityRendererFactory.Context context, ModelKey<? super M> key, TextureSupplier<T> texture, float scale,
public static <T extends MobEntity, M extends EntityModel<T> & PonyModel<T> & ModelWithArms> AbstractPonyRenderer<T, M> proxy(EntityRendererFactory.Context context, ModelKey<? super M> key, TextureSupplier<T> texture, float scale,
List exportedLayers, Consumer<M> modelConsumer) {
var renderer = new AbstractPonyRenderer<T, M>(context, key, texture, scale) {
@Override

View file

@ -1,9 +1,9 @@
package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.IPreviewModel;
import com.minelittlepony.client.PreviewModel;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.util.MathUtil;
@ -37,7 +37,7 @@ public class AquaticPlayerPonyRenderer extends PlayerPonyRenderer {
updateSeaponyState(player);
super.render(player, entityYaw, tickDelta, stack, renderContext, light);
if (!(player instanceof IPreviewModel) && wet && player.getVelocity().length() > 0.1F) {
if (!(player instanceof PreviewModel) && wet && player.getVelocity().length() > 0.1F) {
double x = player.getEntityWorld().getRandom().nextTriangular(player.getX(), 1);
double y = player.getEntityWorld().getRandom().nextTriangular(player.getY(), 1);
double z = player.getEntityWorld().getRandom().nextTriangular(player.getZ(), 1);
@ -46,7 +46,7 @@ public class AquaticPlayerPonyRenderer extends PlayerPonyRenderer {
}
}
protected Race getPlayerRace(AbstractClientPlayerEntity entity, IPony pony) {
protected Race getPlayerRace(AbstractClientPlayerEntity entity, Pony pony) {
Race race = super.getPlayerRace(entity, pony);
return wet ? Race.SEAPONY : race == Race.SEAPONY ? Race.UNICORN : race;
}
@ -69,10 +69,10 @@ public class AquaticPlayerPonyRenderer extends PlayerPonyRenderer {
}
private void updateSeaponyState(AbstractClientPlayerEntity player) {
IPony pony = getEntityPony(player);
Pony pony = getEntityPony(player);
wet = PonyPosture.isSeaponyModifier(player);
if (!(player instanceof IPreviewModel)) {
if (!(player instanceof PreviewModel)) {
float state = wet ? 100 : 0;
float interpolated = pony.metadata().getInterpolator(player.getUuid()).interpolate("seapony_state", state, 5);

View file

@ -1,7 +1,7 @@
package com.minelittlepony.client.render.entity;
import com.minelittlepony.api.model.ModelAttributes;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.Pony;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.SkinsProxy;
@ -77,7 +77,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
@Override
public void render(AbstractClientPlayerEntity entity, float entityYaw, float tickDelta, MatrixStack stack, VertexConsumerProvider renderContext, int lightUv) {
IPony pony = getEntityPony(entity);
Pony pony = getEntityPony(entity);
model = manager.setModel(modelsCache.apply(getPlayerRace(entity, pony))).body();
// EntityModelFeatures: We have to force it to use our models otherwise EMF overrides it and breaks pony rendering
shadowRadius = manager.getModel().getSize().shadowSize();
@ -88,7 +88,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
// (shadows are drawn after us)
if (!entity.hasVehicle() && !entity.isSleeping()) {
float yaw = MathHelper.lerpAngleDegrees(tickDelta, entity.prevBodyYaw, entity.bodyYaw);
float l = entity.getWidth() / 2 * pony.metadata().size().scaleFactor();
float l = entity.getWidth() / 2 * pony.size().scaleFactor();
stack.multiply(RotationAxis.NEGATIVE_Y.rotationDegrees(yaw));
stack.translate(0, 0, -l);
@ -96,7 +96,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
}
}
protected Race getPlayerRace(AbstractClientPlayerEntity entity, IPony pony) {
protected Race getPlayerRace(AbstractClientPlayerEntity entity, Pony pony) {
return pony.race();
}
@ -144,7 +144,7 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
}
protected void renderArm(MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, AbstractClientPlayerEntity player, Arm side) {
IPony pony = getEntityPony(player);
Pony pony = getEntityPony(player);
model = manager.setModel(modelsCache.apply(getPlayerRace(player, pony))).body();
manager.updateModel(player, ModelAttributes.Mode.FIRST_PERSON);
@ -184,14 +184,14 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
}
@Override
public IPony getEntityPony(AbstractClientPlayerEntity entity) {
return IPony.getManager().getPony(entity);
public Pony getEntityPony(AbstractClientPlayerEntity entity) {
return Pony.getManager().getPony(entity);
}
@Override
public Identifier getDefaultTexture(AbstractClientPlayerEntity entity, Wearable wearable) {
return SkinsProxy.instance.getSkin(wearable.getId(), entity).orElseGet(() -> {
if (wearable.isSaddlebags() && getInternalRenderer().getModel().getMetadata().race().supportsLegacySaddlebags()) {
if (wearable.isSaddlebags() && getInternalRenderer().getModel().getRace().supportsLegacySaddlebags()) {
return getTexture(entity);
}

View file

@ -12,12 +12,12 @@ import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.util.math.Vec3d;
import com.minelittlepony.api.model.armour.ArmourLayer;
import com.minelittlepony.api.pony.PonyData;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.ModelWrapper;
import com.minelittlepony.client.model.entity.PonyArmourStandModel;
import com.minelittlepony.client.model.entity.race.EarthPonyModel;
import com.minelittlepony.client.pony.PonyData;
import com.minelittlepony.client.render.entity.feature.ArmourFeature;
public class PonyStandRenderer extends ArmorStandEntityRenderer {
@ -69,7 +69,7 @@ public class PonyStandRenderer extends ArmorStandEntityRenderer {
context.getModelManager()
);
pony.applyMetadata(new PonyData(Race.EARTH));
pony.applyMetadata(PonyData.emptyOf(Race.EARTH));
}
@Override

View file

@ -10,10 +10,10 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.PonyModel;
// separate class in case I need it later
public abstract class AbstractClothingFeature<T extends LivingEntity, M extends BipedEntityModel<T> & IModel> extends FeatureRenderer<T, M> {
public abstract class AbstractClothingFeature<T extends LivingEntity, M extends BipedEntityModel<T> & PonyModel<T>> extends FeatureRenderer<T, M> {
protected final FeatureRendererContext<T, M> renderer;

View file

@ -1,6 +1,6 @@
package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.model.ModelWrapper;
import com.minelittlepony.client.render.IPonyRenderContext;
@ -11,7 +11,7 @@ import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.LivingEntity;
public abstract class AbstractPonyFeature<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> extends FeatureRenderer<T, M> {
public abstract class AbstractPonyFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends FeatureRenderer<T, M> {
private final IPonyRenderContext<T, M> context;

View file

@ -1,7 +1,7 @@
package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.armour.*;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.model.ModelWrapper;
import com.minelittlepony.client.model.armour.DefaultArmourTextureResolver;
import com.minelittlepony.client.render.IPonyRenderContext;
@ -21,7 +21,7 @@ import net.minecraft.item.*;
import net.minecraft.item.trim.ArmorTrim;
import net.minecraft.util.Identifier;
public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> extends AbstractPonyFeature<T, M> {
public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> {
public ArmourFeature(IPonyRenderContext<T, M> context, BakedModelManager bakery) {
super(context);
@ -40,7 +40,7 @@ public class ArmourFeature<T extends LivingEntity, M extends EntityModel<T> & IP
}
public static <T extends LivingEntity, V extends BipedEntityModel<T> & IArmourModel<T>> void renderArmor(
ModelWrapper<T, ? extends IPonyModel<T>> pony, MatrixStack matrices,
ModelWrapper<T, ? extends PonyModel<T>> pony, MatrixStack matrices,
VertexConsumerProvider renderContext, int light, T entity,
float limbDistance, float limbAngle,
float age, float headYaw, float headPitch,

View file

@ -7,13 +7,13 @@ import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.math.MatrixStack;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.model.DJPon3EarsModel;
import com.minelittlepony.client.render.IPonyRenderContext;
public class DJPon3Feature<T extends AbstractClientPlayerEntity, M extends EntityModel<T> & IPonyModel<T>> extends AbstractPonyFeature<T, M> {
public class DJPon3Feature<T extends AbstractClientPlayerEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> {
private final DJPon3EarsModel deadMau5 = ModelType.DJ_PON_3.createModel();

View file

@ -1,8 +1,8 @@
package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.model.PonyElytra;
import com.minelittlepony.client.render.IPonyRenderContext;
@ -22,7 +22,7 @@ import net.minecraft.entity.EquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
public class ElytraFeature<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> extends AbstractPonyFeature<T, M> {
public class ElytraFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> {
private static final Identifier TEXTURE_ELYTRA = new Identifier("textures/entity/elytra.png");

View file

@ -11,10 +11,9 @@ import net.minecraft.util.math.random.Random;
import com.google.common.cache.*;
import com.google.common.collect.Streams;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.gear.IGear;
import com.minelittlepony.api.model.gear.IStackable;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.api.model.gear.Gear;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.client.model.ModelType;
import com.minelittlepony.client.render.IPonyRenderContext;
@ -23,11 +22,11 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
public class GearFeature<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> extends AbstractPonyFeature<T, M> {
public class GearFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends AbstractPonyFeature<T, M> {
private static final List<Supplier<IGear>> MOD_GEARS = new ArrayList<>();
private static final List<Supplier<Gear>> MOD_GEARS = new ArrayList<>();
public static void addModGear(Supplier<IGear> gear) {
public static void addModGear(Supplier<Gear> gear) {
MOD_GEARS.add(gear);
}
@ -64,29 +63,30 @@ public class GearFeature<T extends LivingEntity, M extends EntityModel<T> & IPon
final Object2FloatMap<BodyPart> renderStackingOffsets = new Object2FloatLinkedOpenHashMap<>();
for (var entry : randomisedGearCache.getUnchecked(entity.getUuid().getLeastSignificantBits())) {
if (getContext().shouldRender(model, entity, entry.wearable, entry.gear)) {
if (getContext().shouldRender(model, entity, entry.wearable(), entry.gear())) {
stack.push();
BodyPart part = entry.gear.getGearLocation();
entry.gear.transform(model, stack);
Gear gear = entry.gear();
gear.transform(model, stack);
if (entry.gear instanceof IStackable s) {
if (gear.isStackable()) {
BodyPart part = gear.getGearLocation();
float v = renderStackingOffsets.getFloat(part);
if (v != 0) {
stack.translate(0, -v, 0);
}
renderStackingOffsets.put(part, v + s.getStackingHeight());
renderStackingOffsets.put(part, v + gear.getStackingHeight());
}
renderGear(model, entity, entry.gear, stack, renderContext, lightUv, limbDistance, limbAngle, tickDelta);
renderGear(model, entity, gear, stack, renderContext, lightUv, limbDistance, limbAngle, tickDelta);
stack.pop();
}
}
}
private void renderGear(M model, T entity, IGear gear, MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, float limbDistance, float limbAngle, float tickDelta) {
private void renderGear(M model, T entity, Gear gear, MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, float limbDistance, float limbAngle, float tickDelta) {
gear.pose(model, entity, model.getAttributes().isGoingFast, entity.getUuid(), limbDistance, limbAngle, model.getWobbleAmount(), tickDelta);
gear.render(stack, renderContext.getBuffer(gear.getLayer(entity, getContext())), lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1, entity.getUuid());
}
static record Entry(IGear gear, Wearable wearable) {}
static record Entry(Gear gear, Wearable wearable) { }
}

View file

@ -7,10 +7,10 @@ import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Identifier;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.render.IPonyRenderContext;
public class GlowingEyesFeature<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T>> extends EyesFeatureRenderer<T, M> {
public class GlowingEyesFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T>> extends EyesFeatureRenderer<T, M> {
private final RenderLayer layer;

View file

@ -1,7 +1,7 @@
package com.minelittlepony.client.render.entity.feature;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.client.model.IPonyModel;
import com.minelittlepony.api.model.PonyModel;
import com.minelittlepony.client.render.IPonyRenderContext;
import net.minecraft.client.render.VertexConsumerProvider;
@ -16,7 +16,7 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Arm;
public class HeldItemFeature<T extends LivingEntity, M extends EntityModel<T> & IPonyModel<T> & ModelWithArms> extends HeldItemFeatureRenderer<T, M> {
public class HeldItemFeature<T extends LivingEntity, M extends EntityModel<T> & PonyModel<T> & ModelWithArms> extends HeldItemFeatureRenderer<T, M> {
private final IPonyRenderContext<T, M> context;

Some files were not shown because too many files have changed in this diff Show more