From 5ec332a165fb60d146b98392e46b3675fc1a2043 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 16 Aug 2023 19:42:31 +0100 Subject: [PATCH] Implement bat wings and unicorn horns for ponies that don't normally have them but are those races in the mod --- .../ability/EarthPonyKickAbility.java | 6 +- .../ability/PegasusRainboomAbility.java | 4 +- .../client/minelittlepony/BodyPartGear.java | 133 ++++++++++++++++++ .../unicopia/client/minelittlepony/Main.java | 35 ++--- .../client/minelittlepony/WingsGear.java | 91 ------------ 5 files changed, 149 insertions(+), 120 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/client/minelittlepony/BodyPartGear.java delete mode 100644 src/main/java/com/minelittlepony/unicopia/client/minelittlepony/WingsGear.java diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java index 0b3c0f07..6dc7fffd 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java @@ -59,9 +59,7 @@ public class EarthPonyKickAbility implements Ability { @Override public double getCostEstimate(Pony player) { - double distance = MineLPDelegate.getInstance().getPlayerPonyRace(player.asEntity()).isHuman() ? 6 : -6; - - return TraceHelper.findBlock(player.asEntity(), distance, 1) + return TraceHelper.findBlock(player.asEntity(), getKickDirection(player) * 6, 1) .filter(pos -> TreeType.at(pos, player.asWorld()) != TreeType.NONE) .isPresent() ? 3 : 1; } @@ -121,7 +119,7 @@ public class EarthPonyKickAbility implements Ability { } private int getKickDirection(Pony player) { - return MineLPDelegate.getInstance().getPlayerPonyRace(player.asEntity()).isHuman() ? 1 : -1; + return MineLPDelegate.getInstance().getPlayerPonyRace(player.asEntity()).isEquine() ? -1 : 1; } private Pos getDefaultKickLocation(Pony player) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java index a390d231..087e1cb0 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/PegasusRainboomAbility.java @@ -38,7 +38,7 @@ public class PegasusRainboomAbility implements Ability { @Nullable @Override public Optional prepare(Pony player) { - return Hit.of(player.canUseSuperMove() && player.getPhysics().isFlying() && !SpellType.RAINBOOM.isOn(player)); + return Hit.of(player.canUseSuperMove() && player.getPhysics().isFlying() && !player.getMotion().isRainbooming()); } @Override @@ -54,7 +54,7 @@ public class PegasusRainboomAbility implements Ability { @Override public boolean onQuickAction(Pony player, ActivationType type, Optional data) { - if (type == ActivationType.TAP && player.getPhysics().isFlying() && player.getMagicalReserves().getMana().get() > 40) { + if (type == ActivationType.TAP && !player.getMotion().isRainbooming() && player.getPhysics().isFlying() && player.getMagicalReserves().getMana().get() > 40) { player.getPhysics().dashForward((float)player.asWorld().random.nextTriangular(2.5F, 0.3F)); player.subtractEnergyCost(4); player.getMagicalReserves().getCharge().add(2); diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/BodyPartGear.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/BodyPartGear.java new file mode 100644 index 00000000..65d8bd32 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/BodyPartGear.java @@ -0,0 +1,133 @@ +package com.minelittlepony.unicopia.client.minelittlepony; + +import java.util.UUID; +import java.util.function.Function; +import java.util.function.Predicate; + +import com.minelittlepony.api.model.*; +import com.minelittlepony.api.model.gear.IGear; +import com.minelittlepony.client.model.ClientPonyModel; +import com.minelittlepony.client.model.ModelType; +import com.minelittlepony.client.model.PlayerModelKey; +import com.minelittlepony.client.model.entity.race.PegasusModel; +import com.minelittlepony.client.model.entity.race.UnicornModel; +import com.minelittlepony.client.model.part.UnicornHorn; +import com.minelittlepony.mson.api.MsonModel; +import com.minelittlepony.unicopia.EquinePredicates; +import com.minelittlepony.unicopia.Race; +import com.minelittlepony.unicopia.Unicopia; +import com.minelittlepony.unicopia.entity.AmuletSelectors; + +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.entity.LivingEntity; +import net.minecraft.util.Identifier; + +class BodyPartGear & MsonModel & IModel> implements IGear { + private static final Identifier ICARUS_WINGS = Unicopia.id("textures/models/wings/icarus_pony.png"); + private static final Identifier ICARUS_WINGS_CORRUPTED = Unicopia.id("textures/models/wings/icarus_corrupted_pony.png"); + + public static final Predicate BAT_WINGS_PREDICATE = AmuletSelectors.PEGASUS_AMULET.negate().and(EquinePredicates.PLAYER_BAT); + public static final Identifier BAT_WINGS = Unicopia.id("textures/models/wings/bat_pony.png"); + + public static final Predicate UNICORN_HORN_PREDICATE = AmuletSelectors.ALICORN_AMULET.or(EquinePredicates.raceMatches(Race::canCast)); + public static final Identifier UNICORN_HORN = Unicopia.id("textures/models/horn/unicorn.png"); + + public static final Predicate PEGA_WINGS_PREDICATE = AmuletSelectors.PEGASUS_AMULET.or(EquinePredicates.raceMatches(Race::canInteractWithClouds)); + public static final Identifier PEGASUS_WINGS = Unicopia.id("textures/models/wings/pegasus_pony.png"); + + public static BodyPartGear pegasusWings() { + return new BodyPartGear<>(BodyPart.BODY, ModelType.PEGASUS, PEGA_WINGS_PREDICATE, WingsGearModel::new, WingsGearModel::getWings, e -> { + if (AmuletSelectors.PEGASUS_AMULET.test((LivingEntity)e)) { + return e.getWorld().getDimension().ultrawarm() ? ICARUS_WINGS_CORRUPTED : ICARUS_WINGS; + } + return PEGASUS_WINGS; + }); + } + + public static BodyPartGear batWings() { + return new BodyPartGear<>(BodyPart.BODY, ModelType.BAT_PONY, BAT_WINGS_PREDICATE, WingsGearModel::new, WingsGearModel::getWings, e -> BAT_WINGS); + } + + public static BodyPartGear unicornHorn() { + return new BodyPartGear<>(BodyPart.HEAD, ModelType.UNICORN, UNICORN_HORN_PREDICATE, HornGearModel::new, HornGearModel::getHorn, e -> UNICORN_HORN); + } + + private final M model; + private final Predicate renderTargetPredicate; + private final IPart part; + private final Function textureSupplier; + private final BodyPart gearLocation; + + public BodyPartGear( + BodyPart gearLocation, + PlayerModelKey modelKey, + Predicate renderTargetPredicate, + MsonModel.Factory modelFactory, + Function partExtractor, + Function textureSupplier) { + this.gearLocation = gearLocation; + this.model = modelKey.steveKey().createModel(modelFactory); + this.part = partExtractor.apply(this.model); + this.renderTargetPredicate = renderTargetPredicate; + this.textureSupplier = textureSupplier; + } + + @Override + public BodyPart getGearLocation() { + return gearLocation; + } + + @Override + public boolean canRender(IModel model, Entity entity) { + return entity instanceof LivingEntity l + && MineLPDelegate.getInstance().getRace(entity).isEquine() + && !MineLPDelegate.getInstance().getRace(entity).canFly() + && renderTargetPredicate.test(l); + } + + @Override + public Identifier getTexture(T entity, Context context) { + return textureSupplier.apply(entity); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) { + ((ClientPonyModel)model).copyAttributes(this.model); + part.setPartAngles(this.model.getAttributes(), move, swing, bodySwing, ticks); + } + + @Override + public void render(MatrixStack stack, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha, UUID interpolatorId) { + part.renderPart(stack, consumer, light, overlay, red, green, blue, alpha, model.getAttributes()); + } + + static final class WingsGearModel extends PegasusModel { + public WingsGearModel(ModelPart tree) { + super(tree, false); + } + + @Override + public boolean canFly() { + return true; + } + } + + static final class HornGearModel extends UnicornModel { + public HornGearModel(ModelPart tree) { + super(tree, false); + } + + @Override + public boolean canFly() { + return true; + } + + public UnicornHorn getHorn() { + return horn; + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java index c5922d42..2f7c292d 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java +++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java @@ -27,7 +27,9 @@ public class Main extends MineLPDelegate implements ClientModInitializer { IGear.register(() -> new BangleGear(TrinketsDelegate.MAINHAND)); IGear.register(() -> new BangleGear(TrinketsDelegate.OFFHAND)); IGear.register(HeldEntityGear::new); - IGear.register(WingsGear::new); + IGear.register(BodyPartGear::pegasusWings); + IGear.register(BodyPartGear::batWings); + IGear.register(BodyPartGear::unicornHorn); IGear.register(AmuletGear::new); IGear.register(GlassesGear::new); } @@ -80,27 +82,14 @@ public class Main extends MineLPDelegate implements ClientModInitializer { } private static Race toUnicopiaRace(com.minelittlepony.api.pony.meta.Race race) { - switch (race) { - case ALICORN: - return Race.ALICORN; - case CHANGELING: - case CHANGEDLING: - return Race.CHANGELING; - case ZEBRA: - case EARTH: - return Race.EARTH; - case GRYPHON: - case HIPPOGRIFF: - case PEGASUS: - return Race.PEGASUS; - case BATPONY: - return Race.BAT; - case SEAPONY: - case UNICORN: - case KIRIN: - return Race.UNICORN; - default: - return Race.HUMAN; - } + return switch (race) { + case ALICORN -> Race.ALICORN; + case CHANGELING, CHANGEDLING -> Race.CHANGELING; + case ZEBRA, EARTH -> Race.EARTH; + case GRYPHON, HIPPOGRIFF, PEGASUS -> Race.PEGASUS; + case BATPONY -> Race.BAT; + case SEAPONY, UNICORN, KIRIN -> Race.UNICORN; + default -> Race.HUMAN; + }; } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/WingsGear.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/WingsGear.java deleted file mode 100644 index 7c759bdc..00000000 --- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/WingsGear.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.minelittlepony.unicopia.client.minelittlepony; - -import java.util.UUID; - -import com.minelittlepony.api.model.*; -import com.minelittlepony.api.model.gear.IGear; -import com.minelittlepony.api.pony.*; -import com.minelittlepony.client.model.ClientPonyModel; -import com.minelittlepony.client.model.ModelType; -import com.minelittlepony.client.model.entity.race.PegasusModel; -import com.minelittlepony.unicopia.Race; -import com.minelittlepony.unicopia.Unicopia; -import com.minelittlepony.unicopia.entity.*; -import com.minelittlepony.unicopia.entity.player.Pony; - -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.entity.LivingEntity; -import net.minecraft.util.Identifier; - -class WingsGear implements IGear { - private static final Identifier ICARUS_WINGS = Unicopia.id("textures/models/wings/icarus_pony.png"); - private static final Identifier ICARUS_WINGS_CORRUPTED = Unicopia.id("textures/models/wings/icarus_corrupted_pony.png"); - private static final Identifier PEGASUS_WINGS = Unicopia.id("textures/models/wings/pegasus_pony.png"); - private static final Identifier BAT_WINGS = Unicopia.id("textures/models/wings/bat_pony.png"); - - private final Model model = ModelType.PEGASUS.steveKey().createModel(Model::new); - - @Override - public boolean canRender(IModel model, Entity entity) { - return entity instanceof LivingEntity l - && !MineLPDelegate.getInstance().getRace(entity).canFly() - && (AmuletSelectors.PEGASUS_AMULET.test(l) || Equine.of(entity).filter(this::canRender).isPresent()); - } - - protected boolean canRender(Equine equine) { - if (equine instanceof Pony pony) { - return pony.getObservedSpecies().canInteractWithClouds(); - } - return equine.getSpecies().canFly(); - } - - @Override - public BodyPart getGearLocation() { - return BodyPart.BODY; - } - - @Override - public Identifier getTexture(T entity, Context context) { - Living living = Living.living(entity); - if (living == null) { - return DefaultPonySkinHelper.STEVE; - } - - if (AmuletSelectors.PEGASUS_AMULET.test(living.asEntity())) { - return entity.getWorld().getDimension().ultrawarm() ? ICARUS_WINGS_CORRUPTED : ICARUS_WINGS; - } - - Race race = living instanceof Pony pony ? pony.getObservedSpecies() : living.getSpecies(); - if (race.canInteractWithClouds()) { - return PEGASUS_WINGS; - } - - return BAT_WINGS; - } - - @SuppressWarnings({ "unchecked", "rawtypes" }) - @Override - public void pose(IModel model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) { - ((ClientPonyModel)model).copyAttributes(this.model); - this.model.getWings().setPartAngles(this.model.getAttributes(), move, swing, bodySwing, ticks); - } - - @Override - public void render(MatrixStack stack, VertexConsumer consumer, int light, int overlay, float red, float green, float blue, float alpha, UUID interpolatorId) { - model.getWings().renderPart(stack, consumer, light, overlay, red, green, blue, alpha, model.getAttributes()); - } - - static class Model extends PegasusModel { - public Model(ModelPart tree) { - super(tree, false); - } - - @Override - public boolean canFly() { - return true; - } - } -}