Fixed batpony hanging ability and fixed rendering of upside down players

This commit is contained in:
Sollace 2022-09-19 17:33:38 +02:00
parent 869d900f14
commit 3916e4810f
6 changed files with 56 additions and 44 deletions

View file

@ -2,15 +2,11 @@ package com.minelittlepony.unicopia.ability;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.ability.data.Multi; import com.minelittlepony.unicopia.ability.data.Multi;
import com.minelittlepony.unicopia.entity.UEntityAttributes;
import com.minelittlepony.unicopia.entity.player.PlayerAttributes;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.util.RayTraceHelper; import com.minelittlepony.unicopia.util.RayTraceHelper;
import net.minecraft.entity.attribute.EntityAttributeInstance;
import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
/** /**
* A magic casting ability for unicorns. * A magic casting ability for unicorns.
@ -47,7 +43,7 @@ public class BatPonyHangAbility implements Ability<Multi> {
return RayTraceHelper.doTrace(player.getMaster(), 5, 1, EntityPredicates.EXCEPT_SPECTATOR).getBlockPos() return RayTraceHelper.doTrace(player.getMaster(), 5, 1, EntityPredicates.EXCEPT_SPECTATOR).getBlockPos()
.map(BlockPos::down) .map(BlockPos::down)
.filter(pos -> player.getReferenceWorld().isAir(pos) && player.getReferenceWorld().isAir(pos.down()) && player.canHangAt(pos)) .filter(player::canHangAt)
.map(pos -> new Multi(pos, 1)) .map(pos -> new Multi(pos, 1))
.orElse(null); .orElse(null);
} }
@ -59,20 +55,13 @@ public class BatPonyHangAbility implements Ability<Multi> {
@Override @Override
public void apply(Pony player, Multi data) { public void apply(Pony player, Multi data) {
EntityAttributeInstance attr = player.getMaster().getAttributeInstance(UEntityAttributes.ENTITY_GRAVTY_MODIFIER); if (data.hitType == 0 && player.isHanging()) {
player.stopHanging();
if (data.hitType == 0 && attr.hasModifier(PlayerAttributes.BAT_HANGING)) {
attr.removeModifier(PlayerAttributes.BAT_HANGING);
return; return;
} }
if (data.hitType == 1 && player.canHangAt(data.pos())) { if (data.hitType == 1 && player.canHangAt(data.pos())) {
player.getMaster().teleport(data.x + 0.5, data.y - 2, data.z + 0.5); player.startHanging(data.pos());
player.getMaster().setVelocity(Vec3d.ZERO);
if (!attr.hasModifier(PlayerAttributes.BAT_HANGING)) {
attr.addPersistentModifier(PlayerAttributes.BAT_HANGING);
}
} }
} }

View file

@ -88,11 +88,15 @@ public class WorldRenderDelegate {
roll = pony instanceof Pony ? ((Pony)pony).getInterpolator().interpolate("g_roll", roll, 15) : roll; roll = pony instanceof Pony ? ((Pony)pony).getInterpolator().interpolate("g_roll", roll, 15) : roll;
matrices.translate(x, y + owner.getHeight() / 2, z); matrices.translate(x, y + owner.getHeight() / 2, z);
matrices.multiply(Vec3f.POSITIVE_X.getDegreesQuaternion(roll)); matrices.multiply(Vec3f.POSITIVE_X.getDegreesQuaternion(roll));
matrices.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(roll)); matrices.multiply(Vec3f.POSITIVE_Y.getDegreesQuaternion(roll));
if (pony instanceof Pony) { if (pony instanceof Pony) {
roll = ((Pony)pony).getCamera().calculateRoll(); roll = ((Pony)pony).getCamera().calculateRoll();
if (negative) {
roll -= 180;
}
matrices.multiply(Vec3f.NEGATIVE_Y.getDegreesQuaternion(yaw)); matrices.multiply(Vec3f.NEGATIVE_Y.getDegreesQuaternion(yaw));
matrices.multiply(Vec3f.POSITIVE_Z.getDegreesQuaternion(roll)); matrices.multiply(Vec3f.POSITIVE_Z.getDegreesQuaternion(roll));

View file

@ -22,7 +22,7 @@ public final class PlayerDimensions {
return getPredicate() return getPredicate()
.flatMap(e -> e.getTargetEyeHeight(pony)) .flatMap(e -> e.getTargetEyeHeight(pony))
.filter(h -> h > 0) .filter(h -> h > 0)
.or(() -> physics.isFlyingSurvival ? FLYING_EYE_HEIGHT : Optional.empty()) .or(() -> physics.isFlyingSurvival ? FLYING_EYE_HEIGHT : physics.isGravityNegative() ? Optional.of(dimensions.height) : Optional.empty())
.map(h -> { .map(h -> {
if (physics.isGravityNegative()) { if (physics.isGravityNegative()) {
if (pony.getMaster().isSneaking()) { if (pony.getMaster().isSneaking()) {

View file

@ -294,7 +294,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
entity.setVelocity(velocity.toImmutable()); entity.setVelocity(velocity.toImmutable());
if (isFlying() && !entity.isFallFlying()) { if (isFlying() && !entity.isFallFlying() && !pony.isHanging()) {
float pitch = ((LivingEntityDuck)entity).getLeaningPitch(); float pitch = ((LivingEntityDuck)entity).getLeaningPitch();
if (pitch < 1) { if (pitch < 1) {
@ -429,7 +429,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
&& (horMotion > 0.2 || (motion > 0.2 && velocity.y < -0.02 * getGravitySignum())); && (horMotion > 0.2 || (motion > 0.2 && velocity.y < -0.02 * getGravitySignum()));
boolean fallingTakeOffCondition = !entity.isOnGround() && velocity.y < -1.6 * getGravitySignum(); boolean fallingTakeOffCondition = !entity.isOnGround() && velocity.y < -1.6 * getGravitySignum();
if (takeOffCondition || fallingTakeOffCondition) { if ((takeOffCondition || fallingTakeOffCondition) && !pony.isHanging()) {
entity.getAbilities().flying = true; entity.getAbilities().flying = true;
isFlyingEither = true; isFlyingEither = true;
isFlyingSurvival = true; isFlyingSurvival = true;

View file

@ -20,6 +20,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
import com.minelittlepony.unicopia.ability.magic.spell.trait.TraitDiscovery; import com.minelittlepony.unicopia.ability.magic.spell.trait.TraitDiscovery;
import com.minelittlepony.unicopia.advancement.UCriteria; import com.minelittlepony.unicopia.advancement.UCriteria;
import com.minelittlepony.unicopia.entity.*; import com.minelittlepony.unicopia.entity.*;
import com.minelittlepony.unicopia.entity.duck.LivingEntityDuck;
import com.minelittlepony.unicopia.entity.effect.SunBlindnessStatusEffect; import com.minelittlepony.unicopia.entity.effect.SunBlindnessStatusEffect;
import com.minelittlepony.unicopia.entity.effect.UEffects; import com.minelittlepony.unicopia.entity.effect.UEffects;
import com.minelittlepony.unicopia.item.FriendshipBraceletItem; import com.minelittlepony.unicopia.item.FriendshipBraceletItem;
@ -30,10 +31,8 @@ import com.minelittlepony.unicopia.network.MsgOtherPlayerCapabilities;
import com.minelittlepony.unicopia.network.MsgPlayerAnimationChange; import com.minelittlepony.unicopia.network.MsgPlayerAnimationChange;
import com.minelittlepony.unicopia.network.MsgRequestSpeciesChange; import com.minelittlepony.unicopia.network.MsgRequestSpeciesChange;
import com.minelittlepony.unicopia.network.datasync.Transmittable; import com.minelittlepony.unicopia.network.datasync.Transmittable;
import com.minelittlepony.unicopia.util.*;
import com.minelittlepony.unicopia.network.datasync.EffectSync.UpdateCallback; import com.minelittlepony.unicopia.network.datasync.EffectSync.UpdateCallback;
import com.minelittlepony.unicopia.util.Copieable;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.Tickable;
import com.minelittlepony.common.util.animation.LinearInterpolator; import com.minelittlepony.common.util.animation.LinearInterpolator;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
@ -44,6 +43,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.attribute.DefaultAttributeContainer;
import net.minecraft.entity.attribute.EntityAttributeInstance;
import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.damage.EntityDamageSource; import net.minecraft.entity.damage.EntityDamageSource;
import net.minecraft.entity.data.DataTracker; import net.minecraft.entity.data.DataTracker;
@ -59,8 +59,7 @@ import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvents; import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.Hand; import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.*;
import net.minecraft.util.math.Direction;
public class Pony extends Living<PlayerEntity> implements Transmittable, Copieable<Pony>, UpdateCallback { public class Pony extends Living<PlayerEntity> implements Transmittable, Copieable<Pony>, UpdateCallback {
@ -97,6 +96,7 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
private boolean speciesSet; private boolean speciesSet;
private boolean speciesPersisted; private boolean speciesPersisted;
private Optional<BlockPos> hangingPosition = Optional.empty();
private int ticksHanging; private int ticksHanging;
private float magicExhaustion = 0; private float magicExhaustion = 0;
@ -323,41 +323,53 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
return entity.getAttributeInstance(UEntityAttributes.ENTITY_GRAVTY_MODIFIER).hasModifier(PlayerAttributes.BAT_HANGING); return entity.getAttributeInstance(UEntityAttributes.ENTITY_GRAVTY_MODIFIER).hasModifier(PlayerAttributes.BAT_HANGING);
} }
public void stopHanging() {
entity.getAttributeInstance(UEntityAttributes.ENTITY_GRAVTY_MODIFIER).removeModifier(PlayerAttributes.BAT_HANGING);
entity.calculateDimensions();
ticksHanging = 0;
hangingPosition = Optional.empty();
}
public void startHanging(BlockPos pos) {
hangingPosition = Optional.of(pos);
EntityAttributeInstance attr = entity.getAttributeInstance(UEntityAttributes.ENTITY_GRAVTY_MODIFIER);
if (!attr.hasModifier(PlayerAttributes.BAT_HANGING)) {
attr.addPersistentModifier(PlayerAttributes.BAT_HANGING);
}
entity.teleport(pos.getX() + 0.5, pos.getY() - 1, pos.getZ() + 0.5);
entity.setVelocity(Vec3d.ZERO);
entity.setSneaking(false);
entity.stopFallFlying();
}
public boolean canHangAt(BlockPos pos) { public boolean canHangAt(BlockPos pos) {
if (!getReferenceWorld().isAir(pos) || !getReferenceWorld().isAir(pos.down())) {
return false;
}
pos = pos.up();
BlockState state = getReferenceWorld().getBlockState(pos); BlockState state = getReferenceWorld().getBlockState(pos);
return state.isSolidSurface(getReferenceWorld(), pos, getEntity(), Direction.DOWN); return state.isSolidSurface(getReferenceWorld(), pos, getEntity(), Direction.DOWN);
} }
private BlockPos getHangingPos() {
BlockPos pos = getOrigin();
return new BlockPos(pos.getX(), pos.getY() + entity.getEyeHeight(entity.getPose()) + 2, pos.getZ());
}
@Override @Override
public void tick() { public void tick() {
if (animationDuration >= 0) { if (animationDuration >= 0 && --animationDuration <= 0) {
if (--animationDuration <= 0) {
setAnimation(Animation.NONE); setAnimation(Animation.NONE);
} }
}
if (isHanging()) { if (isHanging()) {
if (ticksHanging++ > 40) { ((LivingEntityDuck)entity).setLeaningPitch(0);
if (entity.getVelocity().horizontalLengthSquared() > 0.01 if (!isClient() && (getSpecies() != Race.BAT || (ticksHanging++ > 40 && hangingPosition.filter(getOrigin()::equals).filter(this::canHangAt).isPresent()))) {
|| entity.isSneaking() stopHanging();
|| !canHangAt(getHangingPos())) {
entity.getAttributes().getCustomInstance(UEntityAttributes.ENTITY_GRAVTY_MODIFIER).removeModifier(PlayerAttributes.BAT_HANGING);
entity.calculateDimensions();
}
} }
} else { } else {
ticksHanging = 0; ticksHanging = 0;
} }
if (getSpecies() == Race.BAT) { if (getSpecies() == Race.BAT && !entity.hasPortalCooldown()) {
if (SunBlindnessStatusEffect.hasSunExposure(entity)) { if (SunBlindnessStatusEffect.hasSunExposure(entity)) {
if (ticksInSun < 200) { if (ticksInSun < 200) {
ticksInSun++; ticksInSun++;
@ -542,6 +554,10 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
super.toNBT(compound); super.toNBT(compound);
compound.putString("playerSpecies", Race.REGISTRY.getId(getSpecies()).toString()); compound.putString("playerSpecies", Race.REGISTRY.getId(getSpecies()).toString());
compound.putFloat("magicExhaustion", magicExhaustion); compound.putFloat("magicExhaustion", magicExhaustion);
compound.putInt("ticksHanging", ticksHanging);
NbtSerialisable.writeBlockPos("hangingPosition", hangingPosition, compound);
compound.putInt("ticksInSun", ticksInSun);
compound.putBoolean("hasShades", hasShades);
compound.put("powers", powers.toNBT()); compound.put("powers", powers.toNBT());
compound.put("gravity", gravity.toNBT()); compound.put("gravity", gravity.toNBT());
compound.put("charms", charms.toNBT()); compound.put("charms", charms.toNBT());
@ -566,7 +582,6 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
super.fromNBT(compound); super.fromNBT(compound);
speciesPersisted = true; speciesPersisted = true;
setSpecies(Race.fromName(compound.getString("playerSpecies"), Race.HUMAN)); setSpecies(Race.fromName(compound.getString("playerSpecies"), Race.HUMAN));
powers.fromNBT(compound.getCompound("powers")); powers.fromNBT(compound.getCompound("powers"));
gravity.fromNBT(compound.getCompound("gravity")); gravity.fromNBT(compound.getCompound("gravity"));
charms.fromNBT(compound.getCompound("charms")); charms.fromNBT(compound.getCompound("charms"));
@ -576,6 +591,10 @@ public class Pony extends Living<PlayerEntity> implements Transmittable, Copieab
mana.fromNBT(compound.getCompound("mana")); mana.fromNBT(compound.getCompound("mana"));
magicExhaustion = compound.getFloat("magicExhaustion"); magicExhaustion = compound.getFloat("magicExhaustion");
ticksHanging = compound.getInt("ticksHanging");
hangingPosition = NbtSerialisable.readBlockPos("hangingPosition", compound);
ticksInSun = compound.getInt("ticksInSun");
hasShades = compound.getBoolean("hasShades");
if (compound.contains("effect")) { if (compound.contains("effect")) {
getSpellSlot().put(Spell.readNbt(compound.getCompound("effect"))); getSpellSlot().put(Spell.readNbt(compound.getCompound("effect")));

View file

@ -42,7 +42,7 @@ public interface NbtSerialisable {
} }
static void writeBlockPos(String name, Optional<BlockPos> pos, NbtCompound nbt) { static void writeBlockPos(String name, Optional<BlockPos> pos, NbtCompound nbt) {
pos.map(NbtHelper::fromBlockPos).ifPresent(p -> nbt.put("hoveringPosition", p)); pos.map(NbtHelper::fromBlockPos).ifPresent(p -> nbt.put(name, p));
} }
static Optional<BlockPos> readBlockPos(String name, NbtCompound nbt) { static Optional<BlockPos> readBlockPos(String name, NbtCompound nbt) {