Players can now upload a texture to use for each type of wearable

This commit is contained in:
Sollace 2022-12-10 19:36:55 +00:00
parent 2cbdc7477c
commit e54b29146a
22 changed files with 219 additions and 192 deletions

View file

@ -84,6 +84,14 @@ public interface IModel {
* Tests if this model is wearing the given piece of gear.
*/
default boolean isWearing(Wearable wearable) {
return isEmbedded(wearable) || getAttributes().featureSkins.contains(wearable.getId());
}
/**
* Tests if the chosen piece of gear is sourcing its texture from the main skin.
* i.e. Used to change wing rendering when using saddlebags.
*/
default boolean isEmbedded(Wearable wearable) {
return getMetadata().isWearing(wearable);
}
}

View file

@ -2,16 +2,18 @@ package com.minelittlepony.api.model;
import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.PonyPosture;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.util.MathUtil;
import java.util.*;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Arm;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import java.util.UUID;
import static com.minelittlepony.api.model.PonyModelConstants.ROTATE_270;
import static com.minelittlepony.api.model.PonyModelConstants.WING_ROT_Z_SNEAK;
import static com.minelittlepony.api.model.PonyModelConstants.WING_ROT_Z_FLYING;
@ -95,6 +97,11 @@ public class ModelAttributes {
*/
public float wingAngle;
/**
* Contains a list of additional skins available for rendering.
*/
public Set<Identifier> featureSkins = new HashSet<>();
/**
* Checks flying and speed conditions and sets rainboom to true if we're a species with wings and is going faaast.
*/
@ -135,6 +142,7 @@ public class ModelAttributes {
isRidingInteractive = PonyPosture.isRidingAPony(entity);
interpolatorId = entity.getUuid();
isLeftHanded = entity.getMainArm() == Arm.LEFT;
featureSkins = SkinsProxy.instance.getAvailableSkins(entity);
}
public enum Mode {

View file

@ -105,7 +105,7 @@ public interface IGear {
/**
* The empty context.
*/
Context<?, ?> NULL = (e, g) -> null;
Context<?, ?> NULL = (e, g) -> g.getDefaultTexture();
/**
* Checks whether the given wearable and gear are able to render for this specific entity and its renderer.

View file

@ -1,26 +1,44 @@
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;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
public enum Wearable implements TriggerPixelType<Wearable> {
NONE (0x00),
CROWN (0x16),
MUFFIN (0x32),
HAT (0x64),
ANTLERS (0x96),
SADDLE_BAGS_LEFT (0xC6),
SADDLE_BAGS_RIGHT (0xC7),
SADDLE_BAGS_BOTH (0xC8),
STETSON (0xFA);
NONE (0x00, null),
CROWN (0x16, new Identifier("minelittlepony", "textures/models/crown.png")),
MUFFIN (0x32, new Identifier("minelittlepony", "textures/models/muffin.png")),
HAT (0x64, new Identifier("textures/entity/witch.png")),
ANTLERS (0x96, new Identifier("minelittlepony", "textures/models/antlers.png")),
SADDLE_BAGS_LEFT (0xC6, SaddleBags.TEXTURE),
SADDLE_BAGS_RIGHT (0xC7, SaddleBags.TEXTURE),
SADDLE_BAGS_BOTH (0xC8, SaddleBags.TEXTURE),
STETSON (0xFA, new Identifier("minelittlepony", "textures/models/stetson.png"));
private int triggerValue;
Wearable(int pixel) {
private final Identifier id;
private final Identifier texture;
public static final List<Wearable> VALUES = Arrays.stream(values()).toList();
Wearable(int pixel, Identifier texture) {
triggerValue = pixel;
id = new Identifier("minelittlepony", name().toLowerCase(Locale.ROOT));
this.texture = texture;
}
public Identifier getId() {
return id;
}
public Identifier getDefaultTexture() {
return texture;
}
@Override
@ -38,7 +56,7 @@ public enum Wearable implements TriggerPixelType<Wearable> {
}
public static boolean[] flags(Wearable[] wears) {
boolean[] flags = new boolean[values().length];
boolean[] flags = new boolean[VALUES.size()];
for (int i = 0; i < wears.length; i++) {
flags[wears[i].ordinal()] = true;
}
@ -47,9 +65,8 @@ public enum Wearable implements TriggerPixelType<Wearable> {
public static Wearable[] flags(boolean[] flags) {
List<Wearable> wears = new ArrayList<>();
Wearable[] values = values();
for (int i = 0; i < values.length; i++) {
if (flags[i]) wears.add(values[i]);
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,16 +1,19 @@
package com.minelittlepony.client;
import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.client.render.EquineRenderManager;
import com.minelittlepony.common.client.gui.ScrollContainer;
import com.minelittlepony.common.client.gui.Tooltip;
import com.minelittlepony.common.client.gui.element.Button;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
import java.util.Optional;
import java.util.Set;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.texture.PlayerSkinProvider;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.Nullable;
@ -41,8 +44,12 @@ public class SkinsProxy {
.setText("minelp.options.skins.hdskins.open");
}
public Identifier getSeaponySkin(EquineRenderManager<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> manager, AbstractClientPlayerEntity player) {
return manager.getTexture(player);
public Optional<Identifier> getSkin(Identifier skinTypeId, AbstractClientPlayerEntity player) {
return Optional.empty();
}
public Set<Identifier> getAvailableSkins(Entity entity) {
return Set.of();
}
}

View file

@ -1,32 +1,36 @@
package com.minelittlepony.client.hdskins;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.common.client.gui.ScrollContainer;
import com.minelittlepony.common.client.gui.element.Button;
import com.minelittlepony.common.event.ClientReadyCallback;
import com.minelittlepony.hdskins.client.SkinCacheClearCallback;
import com.minelittlepony.hdskins.client.*;
import com.minelittlepony.hdskins.client.ducks.ClientPlayerInfo;
import com.minelittlepony.hdskins.client.dummy.DummyPlayer;
import com.minelittlepony.hdskins.client.gui.GuiSkins;
import com.minelittlepony.hdskins.client.resources.LocalPlayerSkins;
import com.minelittlepony.hdskins.mixin.client.MixinClientPlayer;
import com.minelittlepony.hdskins.profile.SkinType;
import com.mojang.authlib.GameProfile;
import java.util.*;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import net.fabricmc.api.ClientModInitializer;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.network.AbstractClientPlayerEntity;
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.render.EquineRenderManager;
import com.minelittlepony.hdskins.client.HDSkins;
import com.minelittlepony.client.render.entity.PlayerSeaponyRenderer;
/**
* All the interactions with HD Skins.
@ -35,11 +39,18 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
static SkinType seaponySkinType;
static final Map<SkinType, Wearable> wearableTypes = new HashMap<>();
@Override
public void onInitializeClient() {
SkinsProxy.instance = this;
seaponySkinType = SkinType.register(new Identifier("minelp", "seapony"), Items.COD_BUCKET.getDefaultStack());
seaponySkinType = SkinType.register(PlayerSeaponyRenderer.SKIN_TYPE_ID, Items.COD_BUCKET.getDefaultStack());
Wearable.VALUES.forEach(wearable -> {
if (wearable != Wearable.NONE) {
wearableTypes.put(SkinType.register(wearable.getId(), Items.BUNDLE.getDefaultStack()), wearable);
}
});
ClientReadyCallback.EVENT.register(client -> {
// Clear ponies when skins are cleared
@ -62,18 +73,39 @@ public class MineLPHDSkins extends SkinsProxy implements ClientModInitializer {
}
@Override
public Identifier getSeaponySkin(EquineRenderManager<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> manager, AbstractClientPlayerEntity player) {
if (player instanceof DummyPlayer) {
return ((DummyPlayer)player).getTextures().get(seaponySkinType).getId();
} else {
ClientPlayerInfo info = (ClientPlayerInfo)((MixinClientPlayer)player).getBackingClientData();
Identifier tex = info.getSkins().getSkin(seaponySkinType);
if (tex != null) {
return tex;
}
public Optional<Identifier> getSkin(Identifier skinTypeId, AbstractClientPlayerEntity player) {
return SkinType.REGISTRY.getOrEmpty(skinTypeId).flatMap(type -> getSkin(type, player));
}
public Set<Identifier> getAvailableSkins(Entity entity) {
if (entity instanceof DummyPlayer dummy) {
return SkinType.REGISTRY.stream()
.filter(type -> {
return dummy.getTextures().get(type).isReady()
|| (dummy.getTextures().getPosture().getActiveSkinType() == type && dummy.getTextures() instanceof LocalPlayerSkins);
})
.map(SkinType::getId)
.collect(Collectors.toSet());
}
return super.getSeaponySkin(manager, player);
if (entity instanceof AbstractClientPlayerEntity player) {
PlayerSkins skins = ((ClientPlayerInfo)((MixinClientPlayer)player).getBackingClientData()).getSkins();
return SkinType.REGISTRY.stream()
.filter(type -> skins.getSkin(type) != null)
.map(SkinType::getId)
.collect(Collectors.toSet());
}
return Set.of();
}
private Optional<Identifier> getSkin(SkinType type, AbstractClientPlayerEntity player) {
if (player instanceof DummyPlayer dummy) {
return Optional.of(dummy.getTextures().get(type).getId());
}
return Optional.ofNullable(((ClientPlayerInfo)((MixinClientPlayer)player).getBackingClientData()).getSkins().getSkin(type));
}
@Override

View file

@ -9,6 +9,7 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.api.pony.*;
import com.minelittlepony.api.pony.meta.TriggerPixel;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.render.entity.SeaponyRenderer;
import com.minelittlepony.common.client.gui.dimension.Bounds;
@ -34,6 +35,12 @@ class PonyPreview extends PlayerPreview {
return DefaultSkinGenerator.generateGreyScale(SeaponyRenderer.TEXTURE, SeaponyRenderer.TEXTURE, getExclusion());
}
Wearable wearable = MineLPHDSkins.wearableTypes.getOrDefault(type, Wearable.NONE);
if (wearable != Wearable.NONE) {
return DefaultSkinGenerator.generateGreyScale(wearable.getDefaultTexture(), wearable.getDefaultTexture(), getExclusion());
}
return super.getDefaultSkin(type, slim);
}

View file

@ -29,9 +29,8 @@ import java.util.function.BiFunction;
import java.util.stream.Stream;
public final class ModelType {
private static final Map<Race, PlayerModelKey<?, ?>> PLAYER_MODELS = new HashMap<>();
private static final Map<Wearable, ModelKey<? extends IGear>> GEAR_MODELS = new HashMap<>();
private static final Map<Wearable, GearModelKey<? extends IGear>> GEAR_MODELS = new HashMap<>();
public static final ModelKey<DJPon3EarsModel> DJ_PON_3 = register("dj_pon_three", DJPon3EarsModel::new);
@ -55,12 +54,14 @@ public final class ModelType {
public static final ModelKey<PonyArmourModel<?>> ARMOUR_INNER = register("armour_inner", PonyArmourModel::new);
public static final ModelKey<PonyArmourModel<?>> ARMOUR_OUTER = register("armour_outer", PonyArmourModel::new);
public static final ModelKey<Stetson> STETSON = registerGear("stetson", Wearable.STETSON, Stetson::new);
public static final ModelKey<SaddleBags> SADDLEBAGS = registerGear("saddlebags", Wearable.SADDLE_BAGS_BOTH, SaddleBags::new);
public static final ModelKey<Crown> CROWN = registerGear("crown", Wearable.CROWN, Crown::new);
public static final ModelKey<Muffin> MUFFIN = registerGear("muffin", Wearable.MUFFIN, Muffin::new);
public static final ModelKey<WitchHat> WITCH_HAT = registerGear("witch_hat", Wearable.HAT, WitchHat::new);
public static final ModelKey<ChristmasHat> ANTLERS = registerGear("antlers", Wearable.ANTLERS, ChristmasHat::new);
public static final GearModelKey<Stetson> STETSON = registerGear("stetson", Wearable.STETSON, Stetson::new);
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 PlayerModelKey<?, AlicornModel<?>> ALICORN = registerPlayer("alicorn", Race.ALICORN, AlicornModel::new);
public static final PlayerModelKey<?, UnicornModel<?>> UNICORN = registerPlayer("unicorn", Race.UNICORN, UnicornModel::new);
@ -87,12 +88,17 @@ public final class ModelType {
}
@SuppressWarnings("unchecked")
static <T extends AbstractGear> ModelKey<T> registerGear(String name, Wearable wearable, MsonModel.Factory<T> constructor) {
return (ModelKey<T>)GEAR_MODELS.computeIfAbsent(wearable, w -> {
return Mson.getInstance().registerModel(new Identifier("minelittlepony", "gear/" + name), constructor);
static <T extends AbstractGear> 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) {
return (GearModelKey<T>)GEAR_MODELS.computeIfAbsent(wearable, w -> new GearModelKey<T>(key.key, constructor));
}
static <T extends Model> ModelKey<T> register(String name, MsonModel.Factory<T> constructor) {
return Mson.getInstance().registerModel(new Identifier("minelittlepony", name), constructor);
}
@ -103,9 +109,15 @@ public final class ModelType {
return (PlayerModelKey<E, T>)PLAYER_MODELS.get(race);
}
public static Stream<Map.Entry<Wearable, ModelKey<? extends IGear>>> getWearables() {
public static Stream<Map.Entry<Wearable, GearModelKey<? extends IGear>>> getWearables() {
return GEAR_MODELS.entrySet().stream();
}
public static void bootstrap() {};
public static void bootstrap() { }
public record GearModelKey<T extends IGear>(ModelKey<T> key, MsonModel.Factory<T> constructor) {
public T createModel() {
return key.createModel(constructor);
}
}
}

View file

@ -15,18 +15,17 @@ import com.minelittlepony.mson.api.MsonModel;
import java.util.function.BiFunction;
import java.util.function.Function;
public class PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel> {
private final ModelKey<M> steveKey;
private final ModelKey<M> alexKey;
private final RendererFactory rendererFactory;
public record PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel> (
ModelKey<M> steveKey,
ModelKey<M> alexKey,
RendererFactory factory
) {
PlayerModelKey(String name, BiFunction<ModelPart, Boolean, M> modelFactory, RendererFactory rendererFactory) {
this.rendererFactory = rendererFactory;
steveKey = Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/steve/" + name), tree -> modelFactory.apply(tree, false));
alexKey = Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/alex/" + name), tree -> modelFactory.apply(tree, true));
this(
Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/steve/" + name), tree -> modelFactory.apply(tree, false)),
Mson.getInstance().registerModel(new Identifier("minelittlepony", "races/alex/" + name), tree -> modelFactory.apply(tree, true)),
rendererFactory
);
}
public ModelKey<M> getKey(boolean slimArms) {
@ -34,8 +33,8 @@ public class PlayerModelKey<T extends LivingEntity, M extends Model & MsonModel>
}
@SuppressWarnings("unchecked")
public Function<EntityRendererFactory.Context, PlayerEntityRenderer> getRendererFactory(boolean slimArms) {
return d -> rendererFactory.create(d, slimArms, (ModelKey<? extends ClientPonyModel<AbstractClientPlayerEntity>>)getKey(slimArms));
public Function<EntityRendererFactory.Context, PlayerEntityRenderer> getFactory(boolean slimArms) {
return d -> factory.create(d, slimArms, (ModelKey<? extends ClientPonyModel<AbstractClientPlayerEntity>>)getKey(slimArms));
}
public interface RendererFactory {

View file

@ -0,0 +1,34 @@
package com.minelittlepony.client.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.pony.meta.Wearable;
public abstract class AbstractWearableGear extends AbstractGear {
protected final Wearable wearable;
protected final BodyPart location;
protected AbstractWearableGear(Wearable wearable, BodyPart location) {
this.wearable = wearable;
this.location = location;
}
@Override
public BodyPart getGearLocation() {
return location;
}
@Override
public boolean canRender(IModel model, Entity entity) {
return model.isWearing(wearable);
}
@Override
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
return context.getDefaultTexture(entity, wearable);
}
}

View file

@ -4,7 +4,6 @@ import net.minecraft.client.model.ModelPart;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import com.minelittlepony.api.model.BodyPart;
@ -16,7 +15,7 @@ import com.minelittlepony.common.util.Color;
import java.util.Calendar;
import java.util.UUID;
public class ChristmasHat extends AbstractGear implements PonyModelConstants {
public class ChristmasHat extends AbstractWearableGear implements PonyModelConstants {
private static boolean dayChecked = false;
private static boolean dayResult = false;
@ -32,21 +31,20 @@ public class ChristmasHat extends AbstractGear implements PonyModelConstants {
return dayResult;
}
private static final Identifier TEXTURE = new Identifier("minelittlepony", "textures/models/antlers.png");
private final ModelPart left;
private final ModelPart right;
private int tint;
public ChristmasHat(ModelPart tree) {
super(Wearable.ANTLERS, BodyPart.HEAD);
left = tree.getChild("left");
right = tree.getChild("right");
}
@Override
public boolean canRender(IModel model, Entity entity) {
return isChristmasDay() || model.isWearing(Wearable.ANTLERS);
return isChristmasDay() || super.canRender(model, entity);
}
@Override
@ -65,16 +63,6 @@ public class ChristmasHat extends AbstractGear implements PonyModelConstants {
right.roll = -bodySwing;
}
@Override
public BodyPart getGearLocation() {
return BodyPart.HEAD;
}
@Override
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
return TEXTURE;
}
@Override
public void render(MatrixStack stack, VertexConsumer vertices, int overlayUv, int lightUv, float red, float green, float blue, float alpha, UUID interpolatorId) {
if (tint != 0) {

View file

@ -5,23 +5,22 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.mob.AbstractPiglinEntity;
import net.minecraft.entity.mob.ZombifiedPiglinEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.Identifier;
import com.minelittlepony.api.model.BodyPart;
import com.minelittlepony.api.model.IModel;
import com.minelittlepony.api.model.gear.IStackable;
import com.minelittlepony.api.pony.meta.Wearable;
public class Crown extends AbstractGear implements IStackable {
public static final Identifier TEXTURE = new Identifier("minelittlepony", "textures/models/crown.png");
public class Crown extends AbstractWearableGear implements IStackable {
public Crown(ModelPart tree) {
super(Wearable.CROWN, BodyPart.HEAD);
addPart(tree.getChild("crown"));
}
@Override
public boolean canRender(IModel model, Entity entity) {
return model.isWearing(Wearable.CROWN)
return super.canRender(model, entity)
|| ((
entity instanceof AbstractPiglinEntity
|| entity instanceof PlayerEntity
@ -30,16 +29,6 @@ public class Crown extends AbstractGear implements IStackable {
);
}
@Override
public BodyPart getGearLocation() {
return BodyPart.HEAD;
}
@Override
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
return TEXTURE;
}
@Override
public float getStackingHeight() {
return 0.1F;

View file

@ -1,37 +1,17 @@
package com.minelittlepony.client.model.gear;
import net.minecraft.client.model.ModelPart;
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.gear.IStackable;
import com.minelittlepony.api.pony.meta.Wearable;
public class Muffin extends AbstractGear implements IStackable {
private static final Identifier TEXTURE = new Identifier("minelittlepony", "textures/models/muffin.png");
public class Muffin extends AbstractWearableGear implements IStackable {
public Muffin(ModelPart tree) {
super(Wearable.MUFFIN, BodyPart.HEAD);
addPart(tree.getChild("crown"));
}
@Override
public boolean canRender(IModel model, Entity entity) {
return model.isWearing(Wearable.MUFFIN);
}
@Override
public BodyPart getGearLocation() {
return BodyPart.HEAD;
}
@Override
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
return TEXTURE;
}
@Override
public float getStackingHeight() {
return 0.45F;

View file

@ -15,7 +15,7 @@ import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
public class SaddleBags extends AbstractGear implements PonyModelConstants {
public class SaddleBags extends AbstractWearableGear implements PonyModelConstants {
public static final Identifier TEXTURE = new Identifier("minelittlepony", "textures/models/saddlebags.png");
@ -26,9 +26,10 @@ public class SaddleBags extends AbstractGear implements PonyModelConstants {
private boolean hangLow = false;
float dropAmount = 0;
private float dropAmount = 0;
public SaddleBags(ModelPart tree) {
public SaddleBags(ModelPart tree, Wearable wearable) {
super(wearable, BodyPart.BODY);
strap = tree.getChild("strap");
leftBag = tree.getChild("left_bag");
rightBag = tree.getChild("right_bag");
@ -60,17 +61,13 @@ public class SaddleBags extends AbstractGear implements PonyModelConstants {
leftBag.roll = bodySwing;
rightBag.roll = -bodySwing;
leftBag.visible = model.isWearing(Wearable.SADDLE_BAGS_BOTH) || model.isWearing(Wearable.SADDLE_BAGS_LEFT);
rightBag.visible = model.isWearing(Wearable.SADDLE_BAGS_BOTH) || model.isWearing(Wearable.SADDLE_BAGS_RIGHT);
leftBag.visible = wearable == Wearable.SADDLE_BAGS_BOTH || wearable == Wearable.SADDLE_BAGS_LEFT;
rightBag.visible = wearable == Wearable.SADDLE_BAGS_BOTH || wearable == Wearable.SADDLE_BAGS_RIGHT;
dropAmount = hangLow ? 0.15F : 0;
dropAmount = model.getMetadata().getInterpolator(interpolatorId).interpolate("dropAmount", dropAmount, 3);
}
public void sethangingLow(boolean veryLow) {
hangLow = veryLow;
}
@Override
public void render(MatrixStack stack, VertexConsumer renderContext, int overlayUv, int lightUv, float red, float green, float blue, float alpha, UUID interpolatorId) {
stack.push();
@ -88,19 +85,4 @@ public class SaddleBags extends AbstractGear implements PonyModelConstants {
strap.render(stack, renderContext, overlayUv, lightUv, red, green, blue, alpha);
}
}
@Override
public boolean canRender(IModel model, Entity entity) {
return model.isWearing(Wearable.SADDLE_BAGS_BOTH) || model.isWearing(Wearable.SADDLE_BAGS_LEFT) || model.isWearing(Wearable.SADDLE_BAGS_RIGHT);
}
@Override
public BodyPart getGearLocation() {
return BodyPart.BODY;
}
@Override
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
return context.getDefaultTexture(entity, Wearable.SADDLE_BAGS_BOTH);
}
}

View file

@ -1,36 +1,17 @@
package com.minelittlepony.client.model.gear;
import net.minecraft.client.model.ModelPart;
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.gear.IStackable;
import com.minelittlepony.api.pony.meta.Wearable;
public class Stetson extends AbstractGear implements IStackable {
private static final Identifier TEXTURE = new Identifier("minelittlepony", "textures/models/stetson.png");
public class Stetson extends AbstractWearableGear implements IStackable {
public Stetson(ModelPart tree) {
super(Wearable.STETSON, BodyPart.HEAD);
addPart(tree.getChild("rim"));
}
@Override
public BodyPart getGearLocation() {
return BodyPart.HEAD;
}
@Override
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
return TEXTURE;
}
@Override
public boolean canRender(IModel model, Entity entity) {
return model.isWearing(Wearable.STETSON);
}
@Override
public float getStackingHeight() {
return 0.15F;

View file

@ -1,37 +1,17 @@
package com.minelittlepony.client.model.gear;
import net.minecraft.client.model.ModelPart;
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.gear.IStackable;
import com.minelittlepony.api.pony.meta.Wearable;
public class WitchHat extends AbstractGear implements IStackable {
private static final Identifier WITCH_TEXTURES = new Identifier("textures/entity/witch.png");
public class WitchHat extends AbstractWearableGear implements IStackable {
public WitchHat(ModelPart tree) {
super(Wearable.HAT, BodyPart.HEAD);
addPart(tree.getChild("hat"));
}
@Override
public boolean canRender(IModel model, Entity entity) {
return model.isWearing(Wearable.HAT);
}
@Override
public BodyPart getGearLocation() {
return BodyPart.HEAD;
}
@Override
public <T extends Entity> Identifier getTexture(T entity, Context<T, ?> context) {
return WITCH_TEXTURES;
}
@Override
public float getStackingHeight() {
return 0.7F;

View file

@ -40,7 +40,7 @@ public class PegasusWings<T extends Model & IPegasus> implements IPart, MsonMode
}
public Wing getRight() {
return pegasus.isBurdened() ? legacyWing : rightWing;
return (pegasus.isEmbedded(Wearable.SADDLE_BAGS_BOTH) || pegasus.isEmbedded(Wearable.SADDLE_BAGS_LEFT) || pegasus.isEmbedded(Wearable.SADDLE_BAGS_RIGHT)) ? legacyWing : rightWing;
}
@Override

View file

@ -57,7 +57,7 @@ public class PonyRenderDispatcher {
private void addPlayerSkin(EntityRenderDispatcher manager, boolean slimArms, Race race) {
Mson.getInstance().getEntityRendererRegistry().registerPlayerRenderer(
race.getModelId(slimArms),
ModelType.getPlayerModel(race).getRendererFactory(slimArms)
ModelType.getPlayerModel(race).getFactory(slimArms)
);
}

View file

@ -5,6 +5,7 @@ import com.minelittlepony.api.pony.IPony;
import com.minelittlepony.api.pony.meta.Race;
import com.minelittlepony.api.pony.meta.Wearable;
import com.minelittlepony.client.MineLittlePony;
import com.minelittlepony.client.SkinsProxy;
import com.minelittlepony.client.model.ClientPonyModel;
import com.minelittlepony.client.model.ModelWrapper;
import com.minelittlepony.client.model.gear.SaddleBags;
@ -198,12 +199,12 @@ public class PlayerPonyRenderer extends PlayerEntityRenderer implements IPonyRen
@Override
public Identifier getDefaultTexture(AbstractClientPlayerEntity entity, Wearable wearable) {
if (wearable.isSaddlebags()) {
if (getInternalRenderer().getModel().getMetadata().getRace() == Race.BATPONY) {
return SkinsProxy.instance.getSkin(wearable.getId(), entity).orElseGet(() -> {
if (wearable.isSaddlebags() && getInternalRenderer().getModel().getMetadata().getRace() == Race.BATPONY) {
return SaddleBags.TEXTURE;
}
}
return getTexture(entity);
return wearable.getDefaultTexture();
});
}
}

View file

@ -16,6 +16,7 @@ import net.minecraft.particle.ParticleTypes;
import net.minecraft.util.Identifier;
public class PlayerSeaponyRenderer extends PlayerPonyRenderer {
public static final Identifier SKIN_TYPE_ID = new Identifier("minelp", "seapony");
private final ModelWrapper<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> seapony;
private final ModelWrapper<AbstractClientPlayerEntity, ClientPonyModel<AbstractClientPlayerEntity>> normalPony;
@ -29,7 +30,7 @@ public class PlayerSeaponyRenderer extends PlayerPonyRenderer {
@Override
public Identifier getTexture(AbstractClientPlayerEntity player) {
return SkinsProxy.instance.getSeaponySkin(manager, player);
return SkinsProxy.instance.getSkin(SKIN_TYPE_ID, player).orElseGet(() -> super.getTexture(player));
}
@Override

View file

@ -8,7 +8,8 @@ import net.minecraft.client.render.entity.feature.*;
import net.minecraft.client.render.entity.model.*;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.passive.PigEntity;
import com.minelittlepony.client.model.gear.Crown;
import com.minelittlepony.api.pony.meta.Wearable;
public class PonyPigRenderer extends PigEntityRenderer {
@ -34,7 +35,7 @@ public class PonyPigRenderer extends PigEntityRenderer {
getContextModel().copyStateTo(model);
model.animateModel(entity, limbAngle, limbDistance, tickDelta);
model.setAngles(entity, limbAngle, limbDistance, animationProgress, headYaw, headPitch);
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getEntityCutoutNoCull(Crown.TEXTURE));
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(RenderLayer.getEntityCutoutNoCull(Wearable.CROWN.getDefaultTexture()));
model.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
}
}

View file

@ -78,7 +78,7 @@ abstract class AbstractNpcRenderer<T extends MobEntity & VillagerDataContainer>
if (wearable.isSaddlebags()) {
return clothing.createTexture(villager, "accessory");
}
return getTexture(villager);
return wearable.getDefaultTexture();
}
@Override