Fixed certain race buffs and checks not accounting for worn amulets (or failing if wearing an amulet)

This commit is contained in:
Sollace 2023-09-01 19:09:13 +01:00
parent 75a6912459
commit 76a7ecc3bb
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
32 changed files with 104 additions and 114 deletions

View file

@ -5,7 +5,6 @@ import java.util.function.Predicate;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.entity.Equine;
import com.minelittlepony.unicopia.entity.MagicImmune;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import net.minecraft.enchantment.EnchantmentHelper;
@ -16,11 +15,13 @@ import net.minecraft.predicate.entity.EntityPredicates;
public interface EquinePredicates {
Predicate<Entity> IS_PLAYER = e -> e instanceof PlayerEntity;
Predicate<Entity> BAT = physicalRaceMatches(Race.BAT::equals);
Predicate<Entity> CHANGELING = physicalRaceMatches(Race.CHANGELING::equals);
Predicate<Entity> RACE_INTERACT_WITH_CLOUDS = raceMatches(Race::canInteractWithClouds);
Predicate<Entity> PLAYER_EARTH = IS_PLAYER.and(ofRace(Race.EARTH));
Predicate<Entity> PLAYER_BAT = IS_PLAYER.and(ofRace(Race.BAT)).or(physicalRaceMatches(Race.BAT::equals));
Predicate<Entity> PLAYER_BAT = IS_PLAYER.and(BAT);
Predicate<Entity> PLAYER_UNICORN = IS_PLAYER.and(raceMatches(Race::canCast));
Predicate<Entity> PLAYER_CHANGELING = IS_PLAYER.and(ofRace(Race.CHANGELING));
Predicate<Entity> PLAYER_PEGASUS = IS_PLAYER.and(e -> ((PlayerEntity)e).getAbilities().creativeMode || RACE_INTERACT_WITH_CLOUDS.test(e));
@ -45,10 +46,10 @@ public interface EquinePredicates {
}
static Predicate<Entity> raceMatches(Predicate<Race> predicate) {
return e -> Equine.of(e).map(Equine::getSpecies).filter(predicate).isPresent();
return e -> Equine.of(e).filter(pony -> pony.getCompositeRace().any(predicate)).isPresent();
}
static Predicate<Entity> physicalRaceMatches(Predicate<Race> predicate) {
return e -> Pony.of(e).map(Pony::getActualSpecies).filter(predicate).isPresent();
return e -> Equine.of(e).filter(pony -> predicate.test(pony.getCompositeRace().physical())).isPresent();
}
}

View file

@ -187,6 +187,12 @@ public record Race (boolean canCast, FlightType flightType, boolean canUseEarth,
}
public record Composite (Race physical, @Nullable Race pseudo) {
public static Composite DEFAULT = new Composite(Race.HUMAN, null);
public Race collapsed() {
return pseudo == null ? physical : pseudo;
}
public boolean includes(Race race) {
return physical == race || pseudo == race;
}
@ -194,6 +200,18 @@ public record Race (boolean canCast, FlightType flightType, boolean canUseEarth,
public boolean any(Predicate<Race> test) {
return test.test(physical) || (pseudo != null && test.test(pseudo));
}
public boolean canUseEarth() {
return any(Race::canUseEarth);
}
public boolean canFly() {
return any(Race::canFly);
}
public boolean canCast() {
return any(Race::canCast);
}
}
}

View file

@ -103,8 +103,8 @@ public class Unicopia implements ModInitializer {
public interface SidedAccess {
Optional<Pony> getPony();
default Race getPlayerSpecies() {
return getPony().map(Pony::getSpecies).orElse(Race.HUMAN);
default Race.Composite getPlayerSpecies() {
return getPony().map(Pony::getCompositeRace).orElse(Race.Composite.DEFAULT);
}
}
}

View file

@ -66,8 +66,9 @@ public class AbilityDispatcher implements Tickable, NbtSerialisable {
}
public int getMaxPage() {
if (maxPage < 0 || prevRace != player.getSpecies()) {
prevRace = player.getSpecies();
Race newRace = player.getCompositeRace().collapsed();
if (maxPage < 0 || prevRace != newRace) {
prevRace = newRace;
maxPage = 0;
for (AbilitySlot slot : AbilitySlot.values()) {
maxPage = Math.max(maxPage, getStat(slot).getMaxPage() - 1);

View file

@ -127,7 +127,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
double amount = (1.5F * player.getAttributeInstance(EntityAttributes.GENERIC_ATTACK_DAMAGE).getValue() + heavyness * 0.4) / (float)(dist * 1.3F);
if (i instanceof PlayerEntity) {
Race race = Pony.of((PlayerEntity)i).getSpecies();
Race.Composite race = Pony.of((PlayerEntity)i).getCompositeRace();
if (race.canUseEarth()) {
amount /= 3;
}

View file

@ -45,7 +45,7 @@ public class PegasusFlightToggleAbility implements Ability<Hit> {
Identifier id = Abilities.REGISTRY.getId(this);
return new Identifier(id.getNamespace(), "textures/gui/ability/" + id.getPath()
+ (player.getPhysics().isFlying() ? "_land" : "_takeoff")
+ (player.getSpecies() == Race.CHANGELING ? "_changeling" : "")
+ (player.getObservedSpecies() == Race.CHANGELING ? "_changeling" : "")
+ ".png");
}

View file

@ -48,13 +48,13 @@ public interface AttractionUtils {
return Pony.of(entity).map(pony -> {
double force = 0.75;
if (pony.getSpecies().canUseEarth()) {
if (pony.getCompositeRace().canUseEarth()) {
force /= 2;
if (pony.asEntity().isSneaking()) {
force /= 6;
}
} else if (pony.getSpecies().canFly()) {
} else if (pony.getCompositeRace().canFly()) {
force *= 2;
}

View file

@ -138,7 +138,7 @@ public class SiphoningSpell extends AbstractAreaEffectSpell {
if (e instanceof PlayerEntity) {
Pony player = Pony.of((PlayerEntity)e);
Race race = player.getSpecies();
Race.Composite race = player.getCompositeRace();
if (race.canCast()) {
dealt /= 2;

View file

@ -83,7 +83,7 @@ public class CustomEventCriterion extends AbstractCriterion<CustomEventCriterion
public boolean test(String event, int count, ServerPlayerEntity player) {
return this.event.equalsIgnoreCase(event)
&& (races.isEmpty() || races.contains(Pony.of(player).getActualSpecies()))
&& (races.isEmpty() || races.contains(Pony.of(player).getSpecies()))
&& (flying == null || flying == Pony.of(player).getPhysics().isFlying())
&& (repeatCount <= 0 || (count > 0 && count % repeatCount == 0));
}

View file

@ -44,7 +44,7 @@ public class RaceChangeCriterion extends AbstractCriterion<RaceChangeCriterion.C
}
public boolean test(ServerPlayerEntity player) {
return Pony.of(player).getActualSpecies() == race;
return Pony.of(player).getSpecies() == race;
}
@Override

View file

@ -77,7 +77,7 @@ public class BaseZapAppleLeavesBlock extends LeavesBlock implements TintedBlock
float delta = super.calcBlockBreakingDelta(state, player, world, pos);
if (Pony.of(player).getSpecies().canUseEarth()) {
if (Pony.of(player).getCompositeRace().canUseEarth()) {
delta *= 50;
}

View file

@ -56,7 +56,7 @@ public class ZapAppleLogBlock extends PillarBlock {
float delta = super.calcBlockBreakingDelta(state, player, world, pos);
if (Pony.of(player).getSpecies().canUseEarth()) {
if (Pony.of(player).getCompositeRace().canUseEarth()) {
delta *= 50;
}

View file

@ -54,7 +54,7 @@ public class ZapBlock extends Block {
float delta = super.calcBlockBreakingDelta(state, player, world, pos);
if (Pony.of(player).getSpecies().canUseEarth()) {
if (Pony.of(player).getCompositeRace().canUseEarth()) {
delta *= 50;
}

View file

@ -1,22 +0,0 @@
package com.minelittlepony.unicopia.client.gui.spellbook;
import java.util.List;
import com.minelittlepony.common.client.gui.Tooltip;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.text.Text;
public class ProfileTooltip {
public static Tooltip get(Pony pony) {
return () -> {
return List.of(
Text.literal(String.format("Level %d ", pony.getLevel().get() + 1)).append(pony.getActualSpecies().getDisplayName()).formatted(pony.getSpecies().getAffinity().getColor()),
Text.literal(String.format("Mana: %d%%", (int)(pony.getMagicalReserves().getMana().getPercentFill() * 100))),
Text.literal(String.format("Corruption: %d%%", (int)(pony.getCorruption().getScaled(100)))),
Text.literal(String.format("Experience: %d", (int)(pony.getMagicalReserves().getXp().getPercentFill() * 100))),
Text.literal(String.format("Next level in: %dxp", 100 - (int)(pony.getMagicalReserves().getXp().getPercentFill() * 100)))
);
};
}
}

View file

@ -1,7 +1,10 @@
package com.minelittlepony.unicopia.client.gui.spellbook;
import java.util.List;
import com.minelittlepony.common.client.gui.IViewRoot;
import com.minelittlepony.common.client.gui.dimension.Bounds;
import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.client.gui.*;
import com.minelittlepony.unicopia.entity.player.*;
import com.minelittlepony.unicopia.util.ColorHelper;
@ -35,14 +38,21 @@ public class SpellbookProfilePageContent implements SpellbookChapterList.Content
screen.addDrawable(new SpellbookScreen.ImageButton(x, y, size, size))
.getStyle()
.setIcon(TribeButton.createSprite(pony.getActualSpecies(), 0, 0, size))
.setTooltip(ProfileTooltip.get(pony));
.setIcon(TribeButton.createSprite(pony.getSpecies(), 0, 0, size))
.setTooltip(() -> List.of(
Text.literal(String.format("Level %d ", pony.getLevel().get() + 1)).append(pony.getSpecies().getDisplayName()).formatted(pony.getSpecies().getAffinity().getColor()),
Text.literal(String.format("Mana: %d%%", (int)(pony.getMagicalReserves().getMana().getPercentFill() * 100))),
Text.literal(String.format("Corruption: %d%%", (int)(pony.getCorruption().getScaled(100)))),
Text.literal(String.format("Experience: %d", (int)(pony.getMagicalReserves().getXp().getPercentFill() * 100))),
Text.literal(String.format("Next level in: %dxp", 100 - (int)(pony.getMagicalReserves().getXp().getPercentFill() * 100)))
));
if (pony.getSpecies() != pony.getActualSpecies()) {
Race inherited = pony.getCompositeRace().collapsed();
if (inherited != pony.getSpecies()) {
int halfSize = size / 2;
screen.addDrawable(new SpellbookScreen.ImageButton(x + halfSize, y + halfSize, halfSize, halfSize))
.getStyle()
.setIcon(TribeButton.createSprite(pony.getSpecies(), 0, 0, halfSize));
.setIcon(TribeButton.createSprite(inherited, 0, 0, halfSize));
}
}

View file

@ -87,7 +87,7 @@ class SpeciesCommand {
}
static int get(ServerCommandSource source, PlayerEntity player, boolean isSelf) {
Race spec = Pony.of(player).getActualSpecies();
Race spec = Pony.of(player).getSpecies();
String name = "commands.race.tell.";
name += isSelf ? "self" : "other";

View file

@ -20,6 +20,10 @@ public interface Equine<T extends Entity> extends NbtSerialisable, Tickable, Pro
void setSpecies(Race race);
default Race.Composite getCompositeRace() {
return new Race.Composite(getSpecies(), null);
}
/**
* Called at the beginning of an update cycle.
*/

View file

@ -81,7 +81,7 @@ public class RaceChangeStatusEffect extends StatusEffect {
int progression = ticks % (stage.ordinal() * STAGE_DURATION);
if ((eq instanceof Pony pony ? pony.getActualSpecies() : eq.getSpecies()) == race || !race.isPermitted(entity instanceof PlayerEntity player ? player : null)) {
if (eq.getSpecies() == race || !race.isPermitted(entity instanceof PlayerEntity player ? player : null)) {
if (progression == 0 && entity instanceof PlayerEntity player && stage == Stage.CRAWLING) {
player.sendMessage(Stage.INITIAL.getMessage(race), true);
}

View file

@ -95,13 +95,13 @@ class ManaContainer implements MagicReserves, Tickable, NbtSerialisable, Copyabl
energy.addPercent(-1);
}
if (pony.getSpecies().canFly() && !pony.getPhysics().isFlying()) {
if (pony.getCompositeRace().canFly() && !pony.getPhysics().isFlying()) {
exhaustion.multiply(0.8F);
} else {
exhaustion.addPercent(-1);
}
if (!pony.getSpecies().canFly() || !pony.getPhysics().isFlying()) {
if (!pony.getCompositeRace().canFly() || !pony.getPhysics().isFlying()) {
if (mana.getPercentFill() < 1 && mana.getShadowFill(1) <= mana.getPercentFill(1)) {
mana.addPercent(MathHelper.clamp(1 + pony.getLevel().get(), 1, 50) / 4F);
}

View file

@ -17,9 +17,9 @@ public class PlayerAttributes implements Tickable {
private static final EntityAttributeModifier EARTH_PONY_STRENGTH =
new EntityAttributeModifier(UUID.fromString("777a5505-521e-480b-b9d5-6ea54f259564"), "Earth Pony Strength", 0.6, Operation.MULTIPLY_TOTAL);
private static final EntityAttributeModifier EARTH_PONY_MINING_SPEED =
new EntityAttributeModifier(UUID.fromString("9fc9e269-152e-0b48-9bd5-564a546e59f2"), "Earth Pony Mining Speed", 0.4, Operation.MULTIPLY_TOTAL);
new EntityAttributeModifier(UUID.fromString("9fc9e269-152e-0b48-9bd5-564a546e59f2"), "Earth Pony Mining Speed", 0.5, Operation.MULTIPLY_TOTAL);
private static final EntityAttributeModifier EARTH_PONY_KNOCKBACK_RESISTANCE =
new EntityAttributeModifier(UUID.fromString("79e269a8-03e8-b9d5-5853-e25fdcf6706d"), "Earth Pony Knockback Resistance", 2, Operation.ADDITION);
new EntityAttributeModifier(UUID.fromString("79e269a8-03e8-b9d5-5853-e25fdcf6706d"), "Earth Pony Knockback Resistance", 6, Operation.ADDITION);
private static final EntityAttributeModifier PEGASUS_SPEED =
new EntityAttributeModifier(UUID.fromString("9e2699fc-3b8d-4f71-9d2d-fb92ee19b4f7"), "Pegasus Speed", 0.2, Operation.MULTIPLY_TOTAL);
@ -41,15 +41,18 @@ public class PlayerAttributes implements Tickable {
@Override
public void tick() {
PlayerEntity entity = pony.asEntity();
Race race = pony.getSpecies();
Race.Composite race = pony.getCompositeRace();
toggleAttribute(entity, EntityAttributes.GENERIC_ATTACK_DAMAGE, EARTH_PONY_STRENGTH, race.canUseEarth());
toggleAttribute(entity, EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, EARTH_PONY_STRENGTH, race.canUseEarth());
toggleAttribute(entity, EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, EARTH_PONY_KNOCKBACK_RESISTANCE, race.canUseEarth() && entity.isSneaking());
toggleAttribute(entity, EntityAttributes.GENERIC_MOVEMENT_SPEED, PEGASUS_SPEED, race.canFly());
toggleAttribute(entity, EntityAttributes.GENERIC_ATTACK_SPEED, PEGASUS_SPEED, race.canFly());
toggleAttribute(entity, UEntityAttributes.EXTENDED_REACH_DISTANCE, PEGASUS_REACH, race.canFly());
toggleAttribute(entity, UEntityAttributes.EXTRA_MINING_SPEED, EARTH_PONY_MINING_SPEED, race.canUseEarth());
boolean earth = race.canUseEarth();
boolean flight = race.canFly();
toggleAttribute(entity, EntityAttributes.GENERIC_ATTACK_DAMAGE, EARTH_PONY_STRENGTH, earth);
toggleAttribute(entity, EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, EARTH_PONY_STRENGTH, earth);
toggleAttribute(entity, EntityAttributes.GENERIC_KNOCKBACK_RESISTANCE, EARTH_PONY_KNOCKBACK_RESISTANCE, earth && entity.isSneaking());
toggleAttribute(entity, EntityAttributes.GENERIC_MOVEMENT_SPEED, PEGASUS_SPEED, flight);
toggleAttribute(entity, EntityAttributes.GENERIC_ATTACK_SPEED, PEGASUS_SPEED, flight);
toggleAttribute(entity, UEntityAttributes.EXTENDED_REACH_DISTANCE, PEGASUS_REACH, flight);
toggleAttribute(entity, UEntityAttributes.EXTRA_MINING_SPEED, EARTH_PONY_MINING_SPEED, earth);
}
private void toggleAttribute(PlayerEntity entity, EntityAttribute attribute, EntityAttributeModifier modifier, boolean enable) {

View file

@ -353,7 +353,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
descentRate = 0;
ticksDiving = 0;
if (Abilities.RAINBOOM.canUse(pony.getActualSpecies()) && entity.isOnGround()) {
if (Abilities.RAINBOOM.canUse(pony.getSpecies()) && entity.isOnGround()) {
pony.getMagicalReserves().getCharge().set(0);
}
@ -683,7 +683,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
SoundEmitter.playSoundAt(entity, USounds.AMBIENT_WIND_GUST, SoundCategory.AMBIENT, 3, 1);
}
float weight = 1 + (EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity) * 0.8F) + (pony.getActualSpecies().canUseEarth() ? 1 : 0);
float weight = 1 + (EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity) * 0.8F) + (pony.getCompositeRace().canUseEarth() ? 1 : 0);
velocity.add(WeatherConditions.getAirflow(entity.getBlockPos(), entity.getWorld()), 0.04F * effectStrength);
velocity.add(Vec3d.fromPolar(

View file

@ -190,23 +190,11 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
/**
* Gets this player's species as it appears when interacting physically with other players or the world.
* This includes temporary race swaps due to illusions/shape shifting as well as artifacts that merely
* grant the abilities of a race, such as the alicorn amulet.
*
* @deprecated Use {@link Pony#getCompositeRace()} or {@link Pony#getObservedSpecies()}
* Gets this player's inherent species.
*/
@Deprecated
@Override
public Race getSpecies() {
if (AmuletSelectors.ALICORN_AMULET.test(entity)) {
return Race.ALICORN;
}
if (AmuletSelectors.UNICORN_AMULET.test(entity)) {
return Race.UNICORN;
}
return getObservedSpecies();
return Race.fromName(entity.getDataTracker().get(RACE), Race.HUMAN);
}
/**
@ -219,30 +207,23 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
.map(AbstractDisguiseSpell::getDisguise)
.map(EntityAppearance::getAppearance)
.flatMap(Pony::of)
.map(Pony::getActualSpecies)
.orElseGet(this::getActualSpecies);
.map(Pony::getSpecies)
.orElseGet(this::getSpecies);
}
/**
* Gets the composite race that represents what this player is capable of.
* Physical is the race they appear to have, whilst pseudo is the race who's abilities they have been granted by magical means.
*/
@Override
public Race.Composite getCompositeRace() {
Race observed = getObservedSpecies();
return new Race.Composite(observed,
return new Race.Composite(getObservedSpecies(),
AmuletSelectors.UNICORN_AMULET.test(entity) ? Race.UNICORN
: AmuletSelectors.ALICORN_AMULET.test(entity) ? Race.ALICORN
: null
);
}
/**
* Gets the origin species of the player. This excludes any shapeshifting, illusions, or magic.
*/
public Race getActualSpecies() {
return Race.fromName(entity.getDataTracker().get(RACE), Race.HUMAN);
}
@Override
public void setSpecies(Race race) {
race = race.validate(entity);
@ -575,7 +556,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
}
if (entity.hurtTime == 1 && getSpecies().canCast()) {
if (entity.hurtTime == 1 && getCompositeRace().physical().canCast()) {
corruption.add(1);
setDirty();
}
@ -586,7 +567,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
public void tick() {
super.tick();
Race currentRace = getActualSpecies();
Race currentRace = getSpecies();
if (!currentRace.isUnset()) {
Race newRace = currentRace.validate(entity);
@ -596,16 +577,12 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
sendCapabilities();
//if (!isClient()) {
// CrystalShardsEntity.infestBlock((ServerWorld)asWorld(), entity.getBlockPos().down());
//}
}
@Override
public boolean canBeSeenBy(Entity entity) {
if (entity instanceof HostileEntity hostile
&& getActualSpecies() == Race.BAT
&& getSpecies() == Race.BAT
&& hostile.getTarget() != this.entity
&& hostile.getAttacker() != this.entity
&& entity.distanceTo(this.entity) > entity.getWidth()) {
@ -659,7 +636,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
&& !cause.isOf(DamageTypes.THORNS)
&& !cause.isOf(DamageTypes.FREEZE)) {
if (getSpecies().canUseEarth() && entity.isSneaking()) {
if (getCompositeRace().canUseEarth() && entity.isSneaking()) {
amount /= (cause.isOf(DamageTypes.MOB_PROJECTILE) ? 3 : 2) * (entity.getHealth() < 5 ? 3 : 1);
return Optional.of(amount);
@ -692,7 +669,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
}
if (getSpecies().canFly() || (getSpecies().canUseEarth() && entity.isSneaking())) {
if (getCompositeRace().canFly() || (getCompositeRace().canUseEarth() && entity.isSneaking())) {
distance -= 5;
}
distance = Math.max(0, distance);
@ -710,7 +687,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
protected void handleFall(float distance, float damageMultiplier, DamageSource cause) {
super.handleFall(distance, damageMultiplier, cause);
if (getSpecies().canUseEarth() && entity.isSneaking()) {
if (getCompositeRace().canUseEarth() && entity.isSneaking()) {
double radius = distance / 10;
if (radius > 0) {
EarthPonyStompAbility.spawnEffectAround(entity, entity.getLandingPos(), radius, radius);
@ -775,7 +752,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
public ActionResult canSleepNow() {
if (asWorld().getGameRules().getBoolean(UGameRules.DO_NOCTURNAL_BAT_PONIES) && getActualSpecies().isNocturnal()) {
if (asWorld().getGameRules().getBoolean(UGameRules.DO_NOCTURNAL_BAT_PONIES) && getSpecies().isNocturnal()) {
return asWorld().isDay() ? ActionResult.SUCCESS : ActionResult.FAIL;
}
@ -790,7 +767,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
@Override
public void toSyncronisedNbt(NbtCompound compound) {
super.toSyncronisedNbt(compound);
compound.putString("playerSpecies", Race.REGISTRY.getId(getActualSpecies()).toString());
compound.putString("playerSpecies", Race.REGISTRY.getId(getSpecies()).toString());
compound.putFloat("magicExhaustion", magicExhaustion);
compound.putInt("ticksHanging", ticksHanging);
BLOCK_POS.writeOptional("hangingPosition", compound, getHangingPosition());
@ -843,7 +820,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
&& entity instanceof ServerPlayerEntity
&& entity.getWorld().getGameRules().getBoolean(UGameRules.SWAP_TRIBE_ON_DEATH)
&& oldPlayer.respawnRace.isUnset())
|| oldPlayer.getActualSpecies().isUnset();
|| oldPlayer.getSpecies().isUnset();
if (alive) {
oldPlayer.getSpellSlot().stream(true).forEach(getSpellSlot()::put);
@ -866,7 +843,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
}
}
setSpecies(oldPlayer.respawnRace != Race.UNSET && !alive ? oldPlayer.respawnRace : oldPlayer.getActualSpecies());
setSpecies(oldPlayer.respawnRace != Race.UNSET && !alive ? oldPlayer.respawnRace : oldPlayer.getSpecies());
getDiscoveries().copyFrom(oldPlayer.getDiscoveries(), alive);
getPhysics().copyFrom(oldPlayer.getPhysics(), alive);
if (!forcedSwap) {

View file

@ -138,7 +138,7 @@ public class BellItem extends Item implements ChargeableItem {
if (living instanceof Pony pony) {
amountDrawn = pony.getMagicalReserves().getMana().get() * 0.2F;
pony.getMagicalReserves().getMana().multiply(0.8F);
if (pony.getActualSpecies() == Race.CHANGELING) {
if (pony.getSpecies() == Race.CHANGELING) {
particleType = ParticleTypes.HEART;
}
} else {

View file

@ -130,7 +130,7 @@ public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Art
}
});
VecHelper.findInRange(entity, entity.getWorld(), entity.getPos(), 20, i -> {
return i instanceof ItemEntity ie && isFillable(ie.getStack()) && Equine.of(i).filter(p -> p.getSpecies() == Race.CHANGELING).isPresent();
return i instanceof ItemEntity ie && isFillable(ie.getStack()) && EquinePredicates.CHANGELING.test(i);
}).forEach(i -> containers.add((ItemEntity)i));
int demand = outputs.size() + containers.stream().mapToInt(i -> i.getStack().getCount()).sum();

View file

@ -41,7 +41,7 @@ public interface EnchantmentUtil {
}
static int getLuck(int baseline, LivingEntity entity) {
boolean naturallyLucky = Living.getOrEmpty(entity).filter(c -> c.getSpecies().canUseEarth()).isPresent();
boolean naturallyLucky = Living.getOrEmpty(entity).filter(c -> c.getCompositeRace().canUseEarth()).isPresent();
if (naturallyLucky) {
baseline += 15;
}

View file

@ -30,7 +30,7 @@ abstract class MixinDamageSource {
});
Pony.of(entity).filter(e -> e.getSpecies().canFly()).ifPresent(pony -> {
Pony.of(entity).filter(e -> e.getCompositeRace().canFly()).ifPresent(pony -> {
if (pony.getPhysics().isFlying()) {
info.setReturnValue(Text.translatable("death.attack.unicopia.generic.whilst_flying", info.getReturnValue()));
}
@ -47,7 +47,7 @@ abstract class MixinFallLocation {
return;
}
Pony.of(entity).ifPresent(pony -> {
if (pony.getSpecies().canFly()) {
if (pony.getCompositeRace().canFly()) {
info.setReturnValue(new FallLocation(location.id() + ".pegasus"));
}
});

View file

@ -5,7 +5,6 @@ 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.unicopia.Race;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.block.PowderSnowBlock;
@ -15,7 +14,7 @@ import net.minecraft.entity.Entity;
abstract class MixinPowderSnowBlock {
@Inject(method = "canWalkOnPowderSnow", at = @At("HEAD"), cancellable = true)
private static void onCanWalkOnPowderSnow(Entity entity, CallbackInfoReturnable<Boolean> info) {
if (Pony.of(entity).map(Pony::getSpecies).filter(Race::canFly).isPresent()) {
if (Pony.of(entity).filter(pony -> pony.getCompositeRace().canFly()).isPresent()) {
info.setReturnValue(true);
}
}

View file

@ -40,7 +40,7 @@ abstract class MixinServerPlayerEntity extends PlayerEntity implements ScreenHan
at = @At(value = "FIELD", target = "net/minecraft/entity/player/PlayerEntity$SleepFailureReason.NOT_POSSIBLE_NOW:Lnet/minecraft/entity/player/PlayerEntity$SleepFailureReason;"),
cancellable = true)
private void onTrySleep(BlockPos pos, CallbackInfoReturnable<Either<PlayerEntity.SleepFailureReason, Unit>> info) {
if (get().getActualSpecies().isNocturnal() && get().asWorld().getGameRules().getBoolean(UGameRules.DO_NOCTURNAL_BAT_PONIES)) {
if (get().getSpecies().isNocturnal() && get().asWorld().getGameRules().getBoolean(UGameRules.DO_NOCTURNAL_BAT_PONIES)) {
((PlayerEntity)this).sendMessage(Text.translatable("block.unicopia.bed.no_sleep.nocturnal"), true);
info.setReturnValue(Either.left(PlayerEntity.SleepFailureReason.OTHER_PROBLEM));

View file

@ -35,7 +35,7 @@ public interface Channel {
static void bootstrap() {
ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
Pony pony = Pony.of(handler.player);
if (pony.getActualSpecies() == Race.UNSET) {
if (pony.getSpecies() == Race.UNSET) {
Race race = UnicopiaWorldProperties.forWorld(handler.player.getServerWorld()).getDefaultRace();
if (!race.isPermitted(handler.player)) {
race = Race.UNSET;

View file

@ -35,14 +35,14 @@ public record MsgRequestSpeciesChange (
public void handle(ServerPlayerEntity sender) {
Pony player = Pony.of(sender);
if (force || player.getActualSpecies().isUnset()) {
if (force || player.getSpecies().isUnset()) {
player.setSpecies(newRace.isPermitted(sender) ? newRace : UnicopiaWorldProperties.forWorld((ServerWorld)player.asWorld()).getDefaultRace());
if (force) {
if (sender.getWorld().getGameRules().getBoolean(UGameRules.ANNOUNCE_TRIBE_JOINS)) {
Text message = Text.translatable("respawn.reason.joined_new_tribe",
sender.getDisplayName(),
player.getActualSpecies().getDisplayName(), player.getActualSpecies().getAltDisplayName());
player.getSpecies().getDisplayName(), player.getSpecies().getAltDisplayName());
sender.getWorld().getPlayers().forEach(p -> {
((ServerPlayerEntity)p).sendMessageToClient(message, false);
});

View file

@ -33,7 +33,7 @@ public class NocturnalSleepManager extends SleepManager {
if (world.getGameRules().getBoolean(GameRules.DO_DAYLIGHT_CYCLE) && world.getPlayers().stream()
.filter(LivingEntity::isSleeping)
.map(Pony::of)
.map(Pony::getActualSpecies)
.map(Pony::getSpecies)
.noneMatch(Race::isDayurnal)) {
world.setTimeOfDay(world.getLevelProperties().getTimeOfDay() - DAY_LENGTH + 13500);
}
@ -50,7 +50,7 @@ public class NocturnalSleepManager extends SleepManager {
return players.stream().filter(player -> {
Pony pony = Pony.of(player);
return (pony.getActualSpecies().isNocturnal() == world.isDay());
return (pony.getSpecies().isNocturnal() == world.isDay());
}).toList();
}

View file

@ -74,8 +74,7 @@ public class MagicalDamageSource extends DamageSource {
}
Text message = Text.translatable(basic, params.toArray());
return Pony.of(target).filter(e -> e.getSpecies().canFly()).map(pony -> {
return Pony.of(target).filter(e -> e.getCompositeRace().canFly()).map(pony -> {
if (pony.getPhysics().isFlying()) {
return Text.translatable("death.attack.unicopia.generic.whilst_flying", message);
}