mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 23:44:38 +00:00
different travel function in water
This commit is contained in:
parent
7d92a7e125
commit
63b4406af2
8 changed files with 288 additions and 93 deletions
|
@ -325,8 +325,8 @@ pub fn local_player_ai_step(
|
|||
) {
|
||||
for (physics_state, mut physics, mut sprinting, mut attributes) in query.iter_mut() {
|
||||
// server ai step
|
||||
physics.xxa = physics_state.left_impulse;
|
||||
physics.zza = physics_state.forward_impulse;
|
||||
physics.x_acceleration = physics_state.left_impulse;
|
||||
physics.z_acceleration = physics_state.forward_impulse;
|
||||
|
||||
// TODO: food data and abilities
|
||||
// let has_enough_food_to_sprint = self.food_data().food_level ||
|
||||
|
|
|
@ -11,6 +11,7 @@ use thiserror::Error;
|
|||
pub struct Attributes {
|
||||
pub speed: AttributeInstance,
|
||||
pub attack_speed: AttributeInstance,
|
||||
pub water_movement_efficiency: AttributeInstance,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
@ -257,12 +257,14 @@ pub struct Physics {
|
|||
pub velocity: Vec3,
|
||||
pub vec_delta_codec: VecDeltaCodec,
|
||||
|
||||
/// X acceleration.
|
||||
pub xxa: f32,
|
||||
/// Y acceleration.
|
||||
pub yya: f32,
|
||||
/// Z acceleration.
|
||||
pub zza: f32,
|
||||
/// The acceleration here is the force that will be attempted to be added to
|
||||
/// the entity's velocity next tick.
|
||||
///
|
||||
/// You should typically not set this yourself, since it's controlled by how
|
||||
/// the entity is trying to move.
|
||||
pub x_acceleration: f32,
|
||||
pub y_acceleration: f32,
|
||||
pub z_acceleration: f32,
|
||||
|
||||
on_ground: bool,
|
||||
last_on_ground: bool,
|
||||
|
@ -295,9 +297,9 @@ impl Physics {
|
|||
velocity: Vec3::default(),
|
||||
vec_delta_codec: VecDeltaCodec::new(pos),
|
||||
|
||||
xxa: 0.,
|
||||
yya: 0.,
|
||||
zza: 0.,
|
||||
x_acceleration: 0.,
|
||||
y_acceleration: 0.,
|
||||
z_acceleration: 0.,
|
||||
|
||||
on_ground: false,
|
||||
last_on_ground: false,
|
||||
|
@ -345,6 +347,14 @@ impl Physics {
|
|||
pub fn clear_fire(&mut self) {
|
||||
self.remaining_fire_ticks = 0;
|
||||
}
|
||||
|
||||
pub fn is_in_water(&self) -> bool {
|
||||
self.was_touching_water
|
||||
}
|
||||
pub fn is_in_lava(&self) -> bool {
|
||||
// TODO: also check `!this.firstTick &&`
|
||||
self.lava_fluid_height > 0.
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker component for entities that are dead.
|
||||
|
@ -444,6 +454,7 @@ impl EntityBundle {
|
|||
// entities have different defaults
|
||||
speed: AttributeInstance::new(0.1),
|
||||
attack_speed: AttributeInstance::new(4.0),
|
||||
water_movement_efficiency: AttributeInstance::new(0.0),
|
||||
},
|
||||
|
||||
jumping: Jumping(false),
|
||||
|
|
|
@ -22,6 +22,7 @@ use tracing::warn;
|
|||
|
||||
use self::world_collisions::get_block_collisions;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum MoverType {
|
||||
Own,
|
||||
Player,
|
||||
|
@ -143,8 +144,10 @@ fn collide(movement: &Vec3, world: &Instance, physics: &azalea_entity::Physics)
|
|||
}
|
||||
|
||||
/// Move an entity by a given delta, checking for collisions.
|
||||
///
|
||||
/// In Mojmap, this is `Entity.move`.
|
||||
pub fn move_colliding(
|
||||
_mover_type: &MoverType,
|
||||
_mover_type: MoverType,
|
||||
movement: &Vec3,
|
||||
world: &Instance,
|
||||
position: &mut Mut<azalea_entity::Position>,
|
||||
|
|
|
@ -25,15 +25,11 @@ pub fn update_in_water_state_and_do_fluid_pushing(
|
|||
.expect("All entities should be in a valid world");
|
||||
let world = world_lock.read();
|
||||
|
||||
println!("update_in_water_state_and_do_fluid_pushing");
|
||||
|
||||
physics.water_fluid_height = 0.;
|
||||
physics.lava_fluid_height = 0.;
|
||||
|
||||
update_in_water_state_and_do_water_current_pushing(&mut physics, &world, &position);
|
||||
|
||||
println!("physics.water_fluid_height: {}", physics.water_fluid_height);
|
||||
|
||||
// let lava_push_factor = world
|
||||
// .registries
|
||||
// .dimension_type()
|
||||
|
@ -117,10 +113,6 @@ fn update_fluid_height_and_do_fluid_pushing(
|
|||
}
|
||||
let mut additional_player_delta_for_fluid =
|
||||
get_fluid_flow(&fluid_at_cur_pos, world, cur_pos);
|
||||
println!(
|
||||
"additional_player_delta_for_fluid: {}",
|
||||
additional_player_delta_for_fluid
|
||||
);
|
||||
if min_height_touching < 0.4 {
|
||||
additional_player_delta_for_fluid *= min_height_touching;
|
||||
};
|
||||
|
@ -131,9 +123,6 @@ fn update_fluid_height_and_do_fluid_pushing(
|
|||
}
|
||||
}
|
||||
|
||||
println!("num_fluids_being_touched: {}", num_fluids_being_touched);
|
||||
println!("additional_player_delta: {}", additional_player_delta);
|
||||
|
||||
if additional_player_delta.length() > 0. {
|
||||
additional_player_delta /= num_fluids_being_touched as f64;
|
||||
|
||||
|
@ -180,10 +169,6 @@ pub fn get_fluid_flow(fluid: &FluidState, world: &Instance, pos: BlockPos) -> Ve
|
|||
.get_fluid_state(&adjacent_block_pos)
|
||||
.unwrap_or_default();
|
||||
if fluid.affects_flow(&adjacent_fluid_state) {
|
||||
println!(
|
||||
"affects flow {adjacent_block_pos} {:?}",
|
||||
adjacent_fluid_state
|
||||
);
|
||||
let mut adjacent_fluid_height = adjacent_fluid_state.height();
|
||||
let mut adjacent_height_difference: f32 = 0.;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ pub mod fluids;
|
|||
|
||||
use azalea_block::{Block, BlockState};
|
||||
use azalea_core::{
|
||||
aabb::AABB,
|
||||
math,
|
||||
position::{BlockPos, Vec3},
|
||||
tick::GameTick,
|
||||
|
@ -84,76 +85,265 @@ fn travel(
|
|||
continue;
|
||||
};
|
||||
let world = world_lock.read();
|
||||
// if !self.is_effective_ai() && !self.is_controlled_by_local_instance() {
|
||||
// // this.calculateEntityAnimation(this, this instanceof FlyingAnimal);
|
||||
// return;
|
||||
// }
|
||||
|
||||
let gravity: f64 = 0.08;
|
||||
let sprinting = *sprinting.unwrap_or(&Sprinting(false));
|
||||
|
||||
// TODO: slow falling effect
|
||||
// let is_falling = self.delta.y <= 0.;
|
||||
// TODO: elytras
|
||||
|
||||
let block_position = BlockPos::from(**position);
|
||||
// LivingEntity.travel
|
||||
let fluid_state = world.chunks.get_fluid_state(&block_position);
|
||||
|
||||
// TODO: fluids
|
||||
|
||||
// TODO: elytra
|
||||
|
||||
let block_pos_below = get_block_pos_below_that_affects_movement(&position);
|
||||
|
||||
let block_state_below = world
|
||||
.chunks
|
||||
.get_block_state(&block_pos_below)
|
||||
.unwrap_or(BlockState::AIR);
|
||||
let block_below: Box<dyn Block> = block_state_below.into();
|
||||
let block_friction = block_below.behavior().friction;
|
||||
|
||||
let inertia = if physics.on_ground() {
|
||||
block_friction * 0.91
|
||||
} else {
|
||||
0.91
|
||||
};
|
||||
|
||||
// this applies the current delta
|
||||
let mut movement = handle_relative_friction_and_calculate_movement(
|
||||
HandleRelativeFrictionAndCalculateMovementOpts {
|
||||
block_friction,
|
||||
world: &world,
|
||||
physics: &mut physics,
|
||||
direction: &direction,
|
||||
if physics.is_in_water() || physics.is_in_lava() {
|
||||
// minecraft also checks for `this.isAffectedByFluids() &&
|
||||
// !this.canStandOnFluid(fluidAtBlock)` here but it doesn't matter
|
||||
// for players
|
||||
travel_in_fluid(
|
||||
&mut physics,
|
||||
&direction,
|
||||
position,
|
||||
attributes,
|
||||
is_sprinting: sprinting.map(|s| **s).unwrap_or(false),
|
||||
sprinting,
|
||||
on_climbable,
|
||||
pose,
|
||||
jumping,
|
||||
},
|
||||
);
|
||||
|
||||
movement.y -= gravity;
|
||||
|
||||
// if (this.shouldDiscardFriction()) {
|
||||
// this.setDeltaMovement(movement.x, yMovement, movement.z);
|
||||
// } else {
|
||||
// this.setDeltaMovement(movement.x * (double)inertia, yMovement *
|
||||
// 0.9800000190734863D, movement.z * (double)inertia); }
|
||||
|
||||
// if should_discard_friction(self) {
|
||||
if false {
|
||||
physics.velocity = movement;
|
||||
&world,
|
||||
);
|
||||
} else {
|
||||
physics.velocity = Vec3 {
|
||||
x: movement.x * inertia as f64,
|
||||
y: movement.y * 0.9800000190734863f64,
|
||||
z: movement.z * inertia as f64,
|
||||
};
|
||||
travel_in_air(
|
||||
&mut physics,
|
||||
&direction,
|
||||
position,
|
||||
&attributes,
|
||||
sprinting,
|
||||
&on_climbable,
|
||||
pose,
|
||||
&jumping,
|
||||
&world,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The usual movement when we're not in water or using an elytra.
|
||||
fn travel_in_air(
|
||||
physics: &mut Physics,
|
||||
direction: &LookDirection,
|
||||
position: Mut<Position>,
|
||||
attributes: &Attributes,
|
||||
sprinting: Sprinting,
|
||||
on_climbable: &OnClimbable,
|
||||
pose: Option<&Pose>,
|
||||
jumping: &Jumping,
|
||||
world: &Instance,
|
||||
) {
|
||||
let gravity = get_effective_gravity();
|
||||
|
||||
// LivingEntity.travel starts here
|
||||
|
||||
// TODO: fluids
|
||||
|
||||
// TODO: elytra
|
||||
|
||||
let block_pos_below = get_block_pos_below_that_affects_movement(&position);
|
||||
|
||||
let block_state_below = world
|
||||
.chunks
|
||||
.get_block_state(&block_pos_below)
|
||||
.unwrap_or(BlockState::AIR);
|
||||
let block_below: Box<dyn Block> = block_state_below.into();
|
||||
let block_friction = block_below.behavior().friction;
|
||||
|
||||
let inertia = if physics.on_ground() {
|
||||
block_friction * 0.91
|
||||
} else {
|
||||
0.91
|
||||
};
|
||||
|
||||
// this applies the current delta
|
||||
let mut movement = handle_relative_friction_and_calculate_movement(
|
||||
HandleRelativeFrictionAndCalculateMovementOpts {
|
||||
block_friction,
|
||||
world: &world,
|
||||
physics,
|
||||
direction: &direction,
|
||||
position,
|
||||
attributes,
|
||||
is_sprinting: *sprinting,
|
||||
on_climbable,
|
||||
pose,
|
||||
jumping,
|
||||
},
|
||||
);
|
||||
|
||||
movement.y -= gravity;
|
||||
|
||||
// if (this.shouldDiscardFriction()) {
|
||||
// this.setDeltaMovement(movement.x, yMovement, movement.z);
|
||||
// } else {
|
||||
// this.setDeltaMovement(movement.x * (double)inertia, yMovement *
|
||||
// 0.9800000190734863D, movement.z * (double)inertia); }
|
||||
|
||||
// if should_discard_friction(self) {
|
||||
if false {
|
||||
physics.velocity = movement;
|
||||
} else {
|
||||
physics.velocity = Vec3 {
|
||||
x: movement.x * inertia as f64,
|
||||
y: movement.y * 0.9800000190734863f64,
|
||||
z: movement.z * inertia as f64,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn travel_in_fluid(
|
||||
physics: &mut Physics,
|
||||
direction: &LookDirection,
|
||||
mut position: Mut<Position>,
|
||||
attributes: &Attributes,
|
||||
sprinting: Sprinting,
|
||||
on_climbable: &OnClimbable,
|
||||
pose: Option<&Pose>,
|
||||
jumping: &Jumping,
|
||||
world: &Instance,
|
||||
) {
|
||||
let moving_down = physics.velocity.y <= 0.;
|
||||
let y = position.y;
|
||||
let gravity = get_effective_gravity();
|
||||
|
||||
let acceleration = Vec3::new(
|
||||
physics.x_acceleration as f64,
|
||||
physics.y_acceleration as f64,
|
||||
physics.z_acceleration as f64,
|
||||
);
|
||||
|
||||
if physics.was_touching_water {
|
||||
let mut water_movement_speed = if *sprinting { 0.9 } else { 0.8 };
|
||||
let mut speed = 0.02;
|
||||
let mut water_efficiency_modifier = attributes.water_movement_efficiency.calculate() as f32;
|
||||
if !physics.on_ground() {
|
||||
water_efficiency_modifier *= 0.5;
|
||||
}
|
||||
|
||||
if water_efficiency_modifier > 0. {
|
||||
water_movement_speed += (0.54600006 - water_movement_speed) * water_efficiency_modifier;
|
||||
speed += (attributes.speed.calculate() as f32 - speed) * water_efficiency_modifier;
|
||||
}
|
||||
|
||||
// if (this.hasEffect(MobEffects.DOLPHINS_GRACE)) {
|
||||
// waterMovementSpeed = 0.96F;
|
||||
// }
|
||||
|
||||
move_relative(physics, direction, speed, &acceleration);
|
||||
move_colliding(
|
||||
MoverType::Own,
|
||||
&physics.velocity.clone(),
|
||||
world,
|
||||
&mut position,
|
||||
physics,
|
||||
)
|
||||
.expect("Entity should exist");
|
||||
|
||||
let mut new_velocity = physics.velocity;
|
||||
if physics.horizontal_collision && **on_climbable {
|
||||
// underwater ladders
|
||||
new_velocity.y = 0.2;
|
||||
}
|
||||
new_velocity.x *= water_movement_speed as f64;
|
||||
new_velocity.y *= 0.8;
|
||||
new_velocity.z *= water_movement_speed as f64;
|
||||
physics.velocity =
|
||||
get_fluid_falling_adjusted_movement(gravity, moving_down, new_velocity, sprinting);
|
||||
} else {
|
||||
move_relative(physics, direction, 0.02, &acceleration);
|
||||
move_colliding(
|
||||
MoverType::Own,
|
||||
&physics.velocity.clone(),
|
||||
world,
|
||||
&mut position,
|
||||
physics,
|
||||
)
|
||||
.expect("Entity should exist");
|
||||
|
||||
if physics.lava_fluid_height <= fluid_jump_threshold() {
|
||||
physics.velocity.x *= 0.5;
|
||||
physics.velocity.y *= 0.8;
|
||||
physics.velocity.z *= 0.5;
|
||||
let new_velocity = get_fluid_falling_adjusted_movement(
|
||||
gravity,
|
||||
moving_down,
|
||||
physics.velocity,
|
||||
sprinting,
|
||||
);
|
||||
physics.velocity = new_velocity;
|
||||
} else {
|
||||
physics.velocity *= 0.5;
|
||||
}
|
||||
|
||||
if gravity != 0.0 {
|
||||
physics.velocity.y -= gravity / 4.0;
|
||||
}
|
||||
}
|
||||
|
||||
let velocity = physics.velocity;
|
||||
if physics.horizontal_collision
|
||||
&& is_free(
|
||||
physics.bounding_box,
|
||||
world,
|
||||
velocity.x,
|
||||
velocity.y + 0.6 - position.y + y,
|
||||
velocity.z,
|
||||
)
|
||||
{
|
||||
physics.velocity.y = 0.3;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_fluid_falling_adjusted_movement(
|
||||
gravity: f64,
|
||||
moving_down: bool,
|
||||
new_velocity: Vec3,
|
||||
sprinting: Sprinting,
|
||||
) -> Vec3 {
|
||||
if gravity != 0. && !*sprinting {
|
||||
let new_y_velocity;
|
||||
if moving_down
|
||||
&& (new_velocity.y - 0.005).abs() >= 0.003
|
||||
&& f64::abs(new_velocity.y - gravity / 16.0) < 0.003
|
||||
{
|
||||
new_y_velocity = -0.003;
|
||||
} else {
|
||||
new_y_velocity = new_velocity.y - gravity / 16.0;
|
||||
}
|
||||
|
||||
Vec3 {
|
||||
x: new_velocity.x,
|
||||
y: new_y_velocity,
|
||||
z: new_velocity.z,
|
||||
}
|
||||
} else {
|
||||
new_velocity
|
||||
}
|
||||
}
|
||||
|
||||
fn is_free(bounding_box: AABB, world: &Instance, x: f64, y: f64, z: f64) -> bool {
|
||||
// let bounding_box = bounding_box.move_relative(Vec3::new(x, y, z));
|
||||
|
||||
let _ = (bounding_box, world, x, y, z);
|
||||
|
||||
// TODO: implement this, see Entity.isFree
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn get_effective_gravity() -> f64 {
|
||||
// TODO: slow falling effect
|
||||
0.08
|
||||
}
|
||||
|
||||
fn fluid_jump_threshold() -> f64 {
|
||||
// this is 0.0 for entities with an eye height lower than 0.4, but that's not
|
||||
// implemented since it's usually not relevant for players (unless the player
|
||||
// was shrunk)
|
||||
0.4
|
||||
}
|
||||
|
||||
/// applies air resistance, calls self.travel(), and some other random
|
||||
/// stuff.
|
||||
#[allow(clippy::type_complexity)]
|
||||
|
@ -202,8 +392,8 @@ pub fn ai_step(
|
|||
}
|
||||
}
|
||||
|
||||
physics.xxa *= 0.98;
|
||||
physics.zza *= 0.98;
|
||||
physics.x_acceleration *= 0.98;
|
||||
physics.z_acceleration *= 0.98;
|
||||
|
||||
// TODO: freezing, pushEntities, drowning damage (in their own systems,
|
||||
// after `travel`)
|
||||
|
@ -285,22 +475,22 @@ fn handle_relative_friction_and_calculate_movement(
|
|||
direction,
|
||||
get_friction_influenced_speed(physics, attributes, block_friction, is_sprinting),
|
||||
&Vec3 {
|
||||
x: physics.xxa as f64,
|
||||
y: physics.yya as f64,
|
||||
z: physics.zza as f64,
|
||||
x: physics.x_acceleration as f64,
|
||||
y: physics.y_acceleration as f64,
|
||||
z: physics.z_acceleration as f64,
|
||||
},
|
||||
);
|
||||
|
||||
physics.velocity = handle_on_climbable(physics.velocity, on_climbable, &position, world, pose);
|
||||
|
||||
move_colliding(
|
||||
&MoverType::Own,
|
||||
MoverType::Own,
|
||||
&physics.velocity.clone(),
|
||||
world,
|
||||
&mut position,
|
||||
physics,
|
||||
)
|
||||
.expect("Entity should exist.");
|
||||
.expect("Entity should exist");
|
||||
// let delta_movement = entity.delta;
|
||||
// ladders
|
||||
// if ((entity.horizontalCollision || entity.jumping) && (entity.onClimbable()
|
||||
|
|
|
@ -89,8 +89,12 @@ pub struct Instance {
|
|||
/// An index of all the entities we know are in the chunks of the world
|
||||
pub entities_by_chunk: HashMap<ChunkPos, HashSet<Entity>>,
|
||||
|
||||
/// An index of Minecraft entity IDs to Azalea ECS entities. You should
|
||||
/// avoid using this and instead use `azalea_entity::EntityIdIndex`
|
||||
/// An index of Minecraft entity IDs to Azalea ECS entities.
|
||||
///
|
||||
/// You should avoid using this (particularly if you're using swarms) and
|
||||
/// instead use `azalea_entity::EntityIdIndex`, since some servers may
|
||||
/// give different entity IDs for the same entities to different
|
||||
/// players.
|
||||
pub entity_by_id: IntMap<MinecraftEntityId, Entity>,
|
||||
|
||||
pub registries: RegistryHolder,
|
||||
|
|
|
@ -38,6 +38,7 @@ impl SimulatedPlayerBundle {
|
|||
attributes: Attributes {
|
||||
speed: AttributeInstance::new(0.1),
|
||||
attack_speed: AttributeInstance::new(4.0),
|
||||
water_movement_efficiency: AttributeInstance::new(0.0),
|
||||
},
|
||||
inventory: Inventory::default(),
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue