Fixed flight velocity/control state going out of sync with the server and add some behavioural tweaks

Note to Fauli: SPACE TO FLAP/ASCENT, SHIFT TO DESCEND

Also changed the behaviour for changeling flight (again).

Fixes #205
Fixes #179
Fixes #165
Fixes #176
This commit is contained in:
Sollace 2023-10-11 15:49:54 +01:00
parent 427fc7d210
commit b4a595550a
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
3 changed files with 77 additions and 27 deletions

View file

@ -19,6 +19,8 @@ import com.minelittlepony.unicopia.item.AmuletItem;
import com.minelittlepony.unicopia.item.ChargeableItem; import com.minelittlepony.unicopia.item.ChargeableItem;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.network.Channel;
import com.minelittlepony.unicopia.network.MsgPlayerFlightControlsInput;
import com.minelittlepony.unicopia.particle.*; import com.minelittlepony.unicopia.particle.*;
import com.minelittlepony.unicopia.projectile.ProjectileUtil; import com.minelittlepony.unicopia.projectile.ProjectileUtil;
import com.minelittlepony.unicopia.server.world.BlockDestructionManager; import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
@ -43,6 +45,7 @@ import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.util.math.*; import net.minecraft.util.math.*;
import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.event.GameEvent; import net.minecraft.world.event.GameEvent;
@ -130,7 +133,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
@Override @Override
public boolean isGliding() { public boolean isGliding() {
return ticksToGlide <= 0 && isFlying() && !entity.isSneaking(); return ticksToGlide <= 0 && isFlying() && !pony.getJumpingHeuristic().getState();
} }
@Override @Override
@ -228,6 +231,10 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
public void tick() { public void tick() {
super.tick(); super.tick();
if (pony.isClient() && this.isFlying()) {
Channel.FLIGHT_CONTROLS_INPUT.sendToServer(new MsgPlayerFlightControlsInput(pony));
}
prevThrustScale = thrustScale; prevThrustScale = thrustScale;
if (wallHitCooldown > 0) { if (wallHitCooldown > 0) {
@ -404,16 +411,14 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
entity.fallDistance = 0; entity.fallDistance = 0;
if (type.isAvian()) { applyThrust(velocity);
applyThrust(velocity);
if (type.isAvian()) {
if (pony.getObservedSpecies() != Race.BAT && entity.getWorld().random.nextInt(9000) == 0) { if (pony.getObservedSpecies() != Race.BAT && entity.getWorld().random.nextInt(9000) == 0) {
entity.dropItem(UItems.PEGASUS_FEATHER); entity.dropItem(UItems.PEGASUS_FEATHER);
playSound(USounds.ENTITY_PLAYER_PEGASUS_MOLT, 0.3F, 1); playSound(USounds.ENTITY_PLAYER_PEGASUS_MOLT, 0.3F, 1);
UCriteria.SHED_FEATHER.trigger(entity); UCriteria.SHED_FEATHER.trigger(entity);
} }
} else {
applyThrust(velocity);
} }
moveFlying(velocity); moveFlying(velocity);
@ -429,8 +434,6 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
InteractionManager.instance().playLoopingSound(entity, InteractionManager.SOUND_GLIDING, entity.getId()); InteractionManager.instance().playLoopingSound(entity, InteractionManager.SOUND_GLIDING, entity.getId());
} }
} }
} else if (type == FlightType.INSECTOID && !SpellPredicate.IS_DISGUISE.isOn(pony)) { } else if (type == FlightType.INSECTOID && !SpellPredicate.IS_DISGUISE.isOn(pony)) {
if (entity.getWorld().isClient && !soundPlaying) { if (entity.getWorld().isClient && !soundPlaying) {
soundPlaying = true; soundPlaying = true;
@ -477,7 +480,8 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
} }
private void playSound(SoundEvent sound, float volume, float pitch) { private void playSound(SoundEvent sound, float volume, float pitch) {
entity.getWorld().playSoundFromEntity(null, entity, sound, SoundCategory.PLAYERS, volume, pitch); entity.sendMessage(Text.literal((entity.getWorld().isClient ? "[Client]" : "[Server]") + "Playing " + sound));
entity.getWorld().playSoundFromEntity(entity, entity, sound, SoundCategory.PLAYERS, volume, pitch);
} }
private void tickNaturalFlight(MutableVector velocity) { private void tickNaturalFlight(MutableVector velocity) {
@ -556,12 +560,14 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
isFlyingEither = true; isFlyingEither = true;
isFlyingSurvival = true; isFlyingSurvival = true;
thrustScale = 0; thrustScale = 0;
descentRate = 0;
entity.calculateDimensions(); entity.calculateDimensions();
if (entity.isOnGround() || !force) { if (entity.isOnGround() || !force) {
Supplier<Vec3d> vec = VecHelper.sphere(pony.asWorld().getRandom(), 0.5D); Supplier<Vec3d> pos = VecHelper.sphere(pony.asWorld().getRandom(), 0.5D);
pony.spawnParticles(ParticleTypes.CAMPFIRE_COSY_SMOKE, vec, vec, 5); Supplier<Vec3d> vel = VecHelper.sphere(pony.asWorld().getRandom(), 0.15D);
pony.spawnParticles(ParticleTypes.CLOUD, vec, vec, 5); pony.spawnParticles(ParticleTypes.CAMPFIRE_COSY_SMOKE, pos, vel, 5);
pony.spawnParticles(ParticleTypes.CLOUD, pos, vel, 5);
} }
} }
@ -627,11 +633,12 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
if (descentRate < 0) { if (descentRate < 0) {
descentRate *= 0.8F; descentRate *= 0.8F;
} }
velocity.y -= descentRate * getGravityModifier(); velocity.y -= descentRate * getGravityModifier();
} }
private void applyThrust(MutableVector velocity) { private void applyThrust(MutableVector velocity) {
boolean manualFlap = pony.sneakingChanged() && entity.isSneaking(); boolean manualFlap = pony.getJumpingHeuristic().hasChanged(Heuristic.ONCE) && pony.getJumpingHeuristic().getState();
if (manualFlap) { if (manualFlap) {
flapping = true; flapping = true;
ticksToGlide = MAX_TICKS_TO_GLIDE; ticksToGlide = MAX_TICKS_TO_GLIDE;
@ -641,24 +648,30 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
boolean hovering = entity.getVelocity().horizontalLength() < 0.1; boolean hovering = entity.getVelocity().horizontalLength() < 0.1;
if (thrustScale <= 0.000001F & flapping) { if (!entity.getWorld().isClient) {
flapping = false; entity.sendMessage(Text.literal("Jumping:" + pony.getJumpingHeuristic().getState()));
if (!SpellPredicate.IS_DISGUISE.isOn(pony)) { }
if (lastFlightType != FlightType.INSECTOID) {
if (lastFlightType == FlightType.INSECTOID) {
descentRate = pony.getJumpingHeuristic().getState() ? -0.5F : 0;
} else {
if (thrustScale <= 0.000001F & flapping) {
flapping = false;
if (!SpellPredicate.IS_DISGUISE.isOn(pony)) {
playSound(lastFlightType.getWingFlapSound(), 0.25F, entity.getSoundPitch() * lastFlightType.getWingFlapSoundPitch()); playSound(lastFlightType.getWingFlapSound(), 0.25F, entity.getSoundPitch() * lastFlightType.getWingFlapSoundPitch());
entity.getWorld().emitGameEvent(entity, GameEvent.ELYTRA_GLIDE, entity.getPos());
}
thrustScale = 1;
if (manualFlap) {
descentRate -= 0.5;
} else {
descentRate = Math.max(0, descentRate / 2);
} }
entity.getWorld().emitGameEvent(entity, GameEvent.ELYTRA_GLIDE, entity.getPos());
}
thrustScale = 1;
if (manualFlap) {
descentRate -= 0.5;
} else {
descentRate = Math.max(0, descentRate / 2);
} }
} }
float heavyness = EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity); float heavyness = EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity);
float thrustStrength = 0.135F * thrustScale; float thrustStrength = 0.235F * thrustScale;
if (heavyness > 0) { if (heavyness > 0) {
thrustStrength /= 1 + heavyness; thrustStrength /= 1 + heavyness;
@ -666,9 +679,13 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
Vec3d direction = entity.getRotationVec(1).normalize().multiply(thrustStrength); Vec3d direction = entity.getRotationVec(1).normalize().multiply(thrustStrength);
if (!hovering) { if (hovering) {
velocity.x += direction.x; if (entity.isSneaking()) {
velocity.z += direction.z; velocity.y -= 0.2F;
}
} else {
velocity.x += direction.x * 1.3F;
velocity.z += direction.z * 1.3F;
velocity.y += ((direction.y * 2.45 + Math.abs(direction.y) * 10)) * getGravitySignum();// - heavyness / 5F velocity.y += ((direction.y * 2.45 + Math.abs(direction.y) * 10)) * getGravitySignum();// - heavyness / 5F
} }

View file

@ -15,6 +15,7 @@ public interface Channel {
C2SPacketType<MsgRequestSpeciesChange> CLIENT_REQUEST_SPECIES_CHANGE = SimpleNetworking.clientToServer(Unicopia.id("request_capabilities"), MsgRequestSpeciesChange::new); C2SPacketType<MsgRequestSpeciesChange> CLIENT_REQUEST_SPECIES_CHANGE = SimpleNetworking.clientToServer(Unicopia.id("request_capabilities"), MsgRequestSpeciesChange::new);
C2SPacketType<MsgMarkTraitRead> MARK_TRAIT_READ = SimpleNetworking.clientToServer(Unicopia.id("mark_trait_read"), MsgMarkTraitRead::new); C2SPacketType<MsgMarkTraitRead> MARK_TRAIT_READ = SimpleNetworking.clientToServer(Unicopia.id("mark_trait_read"), MsgMarkTraitRead::new);
C2SPacketType<MsgRemoveSpell> REMOVE_SPELL = SimpleNetworking.clientToServer(Unicopia.id("remove_spell"), MsgRemoveSpell::new); C2SPacketType<MsgRemoveSpell> REMOVE_SPELL = SimpleNetworking.clientToServer(Unicopia.id("remove_spell"), MsgRemoveSpell::new);
C2SPacketType<MsgPlayerFlightControlsInput> FLIGHT_CONTROLS_INPUT = SimpleNetworking.clientToServer(Unicopia.id("flight_controls"), MsgPlayerFlightControlsInput::new);
S2CPacketType<MsgPlayerCapabilities> SERVER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClient(Unicopia.id("player_capabilities"), MsgPlayerCapabilities::new); S2CPacketType<MsgPlayerCapabilities> SERVER_PLAYER_CAPABILITIES = SimpleNetworking.serverToClient(Unicopia.id("player_capabilities"), MsgPlayerCapabilities::new);
S2CPacketType<MsgSpawnProjectile> SERVER_SPAWN_PROJECTILE = SimpleNetworking.serverToClient(Unicopia.id("projectile_entity"), MsgSpawnProjectile::new); S2CPacketType<MsgSpawnProjectile> SERVER_SPAWN_PROJECTILE = SimpleNetworking.serverToClient(Unicopia.id("projectile_entity"), MsgSpawnProjectile::new);

View file

@ -0,0 +1,32 @@
package com.minelittlepony.unicopia.network;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.sollace.fabwork.api.packets.HandledPacket;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.network.ServerPlayerEntity;
public record MsgPlayerFlightControlsInput (
boolean ascending,
boolean descending
) implements HandledPacket<ServerPlayerEntity> {
public MsgPlayerFlightControlsInput(Pony pony) {
this(pony.getJumpingHeuristic().getState(), pony.asEntity().isSneaking());
}
public MsgPlayerFlightControlsInput(PacketByteBuf buffer) {
this(buffer.readBoolean(), buffer.readBoolean());
}
@Override
public void toBuffer(PacketByteBuf buffer) {
buffer.writeBoolean(ascending);
buffer.writeBoolean(descending);
}
@Override
public void handle(ServerPlayerEntity sender) {
sender.setSneaking(descending);
sender.setJumping(ascending);
}
}