mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
fix physics bugs
This commit is contained in:
parent
4885f848a4
commit
5f8704ccc5
6 changed files with 59 additions and 25 deletions
|
@ -405,6 +405,7 @@ pub fn walk_listener(
|
||||||
if let Ok((mut physics_state, mut sprinting, mut attributes)) = query.get_mut(event.entity)
|
if let Ok((mut physics_state, mut sprinting, mut attributes)) = query.get_mut(event.entity)
|
||||||
{
|
{
|
||||||
physics_state.move_direction = event.direction;
|
physics_state.move_direction = event.direction;
|
||||||
|
physics_state.trying_to_sprint = false;
|
||||||
set_sprinting(false, &mut sprinting, &mut attributes);
|
set_sprinting(false, &mut sprinting, &mut attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![feature(int_roundings)]
|
#![feature(int_roundings)]
|
||||||
#![feature(const_for)]
|
#![feature(const_for)]
|
||||||
|
#![feature(lazy_cell)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![feature(generic_const_exprs)]
|
#![feature(generic_const_exprs)]
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
pub static SIN: LazyLock<[f32; 65536]> = LazyLock::new(|| {
|
||||||
|
let mut sin = [0.0; 65536];
|
||||||
|
for i in 0..65536 {
|
||||||
|
sin[i] = f64::sin((i as f64) * 3.141592653589793 * 2.0 / 65536.0) as f32;
|
||||||
|
}
|
||||||
|
sin
|
||||||
|
});
|
||||||
|
|
||||||
|
/// A sine function that uses a lookup table.
|
||||||
|
pub fn sin(var0: f32) -> f32 {
|
||||||
|
let var0 = var0 * 10430.378;
|
||||||
|
let var0 = var0 as usize;
|
||||||
|
SIN[var0 & 65535]
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A cosine function that uses a lookup table.
|
||||||
|
pub fn cos(var0: f32) -> f32 {
|
||||||
|
let var0 = var0 * 10430.378 + 16384.0;
|
||||||
|
let var0 = var0 as usize;
|
||||||
|
SIN[var0 & 65535]
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: make this generic
|
// TODO: make this generic
|
||||||
pub fn binary_search(mut min: i32, max: i32, predicate: &dyn Fn(i32) -> bool) -> i32 {
|
pub fn binary_search(mut min: i32, max: i32, predicate: &dyn Fn(i32) -> bool) -> i32 {
|
||||||
let mut diff = max - min;
|
let mut diff = max - min;
|
||||||
|
|
|
@ -12,7 +12,7 @@ mod plugin;
|
||||||
use self::attributes::AttributeInstance;
|
use self::attributes::AttributeInstance;
|
||||||
pub use attributes::Attributes;
|
pub use attributes::Attributes;
|
||||||
use azalea_block::BlockState;
|
use azalea_block::BlockState;
|
||||||
use azalea_core::{BlockPos, ChunkPos, ResourceLocation, Vec3, AABB};
|
use azalea_core::{math, BlockPos, ChunkPos, ResourceLocation, Vec3, AABB};
|
||||||
use azalea_world::{ChunkStorage, InstanceName};
|
use azalea_world::{ChunkStorage, InstanceName};
|
||||||
use bevy_ecs::{bundle::Bundle, component::Component};
|
use bevy_ecs::{bundle::Bundle, component::Component};
|
||||||
pub use data::*;
|
pub use data::*;
|
||||||
|
@ -44,8 +44,8 @@ pub fn input_vector(direction: &LookDirection, speed: f32, acceleration: &Vec3)
|
||||||
*acceleration
|
*acceleration
|
||||||
}
|
}
|
||||||
.scale(speed as f64);
|
.scale(speed as f64);
|
||||||
let y_rot = f32::sin(direction.y_rot * 0.017453292f32);
|
let y_rot = math::sin(direction.y_rot * 0.017453292f32);
|
||||||
let x_rot = f32::cos(direction.y_rot * 0.017453292f32);
|
let x_rot = math::cos(direction.y_rot * 0.017453292f32);
|
||||||
Vec3 {
|
Vec3 {
|
||||||
x: acceleration.x * (x_rot as f64) - acceleration.z * (y_rot as f64),
|
x: acceleration.x * (x_rot as f64) - acceleration.z * (y_rot as f64),
|
||||||
y: acceleration.y,
|
y: acceleration.y,
|
||||||
|
@ -56,10 +56,10 @@ pub fn input_vector(direction: &LookDirection, speed: f32, acceleration: &Vec3)
|
||||||
pub fn view_vector(look_direction: &LookDirection) -> Vec3 {
|
pub fn view_vector(look_direction: &LookDirection) -> Vec3 {
|
||||||
let x_rot = look_direction.x_rot * 0.017453292;
|
let x_rot = look_direction.x_rot * 0.017453292;
|
||||||
let y_rot = -look_direction.y_rot * 0.017453292;
|
let y_rot = -look_direction.y_rot * 0.017453292;
|
||||||
let y_rot_cos = f32::cos(y_rot);
|
let y_rot_cos = math::cos(y_rot);
|
||||||
let y_rot_sin = f32::sin(y_rot);
|
let y_rot_sin = math::sin(y_rot);
|
||||||
let x_rot_cos = f32::cos(x_rot);
|
let x_rot_cos = math::cos(x_rot);
|
||||||
let x_rot_sin = f32::sin(x_rot);
|
let x_rot_sin = math::sin(x_rot);
|
||||||
Vec3 {
|
Vec3 {
|
||||||
x: (y_rot_sin * x_rot_cos) as f64,
|
x: (y_rot_sin * x_rot_cos) as f64,
|
||||||
y: (-x_rot_sin) as f64,
|
y: (-x_rot_sin) as f64,
|
||||||
|
|
|
@ -5,7 +5,7 @@ pub mod clip;
|
||||||
pub mod collision;
|
pub mod collision;
|
||||||
|
|
||||||
use azalea_block::{Block, BlockState};
|
use azalea_block::{Block, BlockState};
|
||||||
use azalea_core::{BlockPos, Vec3};
|
use azalea_core::{math, BlockPos, Vec3};
|
||||||
use azalea_entity::{
|
use azalea_entity::{
|
||||||
metadata::Sprinting, move_relative, Attributes, Jumping, Local, LookDirection, Physics,
|
metadata::Sprinting, move_relative, Attributes, Jumping, Local, LookDirection, Physics,
|
||||||
Position,
|
Position,
|
||||||
|
@ -30,8 +30,7 @@ pub struct PhysicsSet;
|
||||||
pub struct PhysicsPlugin;
|
pub struct PhysicsPlugin;
|
||||||
impl Plugin for PhysicsPlugin {
|
impl Plugin for PhysicsPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_event::<ForceJumpEvent>()
|
app.add_systems(FixedUpdate, (ai_step, travel).chain().in_set(PhysicsSet));
|
||||||
.add_systems(FixedUpdate, (ai_step, travel).chain().in_set(PhysicsSet));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +42,7 @@ fn travel(
|
||||||
&mut Physics,
|
&mut Physics,
|
||||||
&mut LookDirection,
|
&mut LookDirection,
|
||||||
&mut Position,
|
&mut Position,
|
||||||
|
Option<&Sprinting>,
|
||||||
&Attributes,
|
&Attributes,
|
||||||
&InstanceName,
|
&InstanceName,
|
||||||
),
|
),
|
||||||
|
@ -50,7 +50,7 @@ fn travel(
|
||||||
>,
|
>,
|
||||||
instance_container: Res<InstanceContainer>,
|
instance_container: Res<InstanceContainer>,
|
||||||
) {
|
) {
|
||||||
for (mut physics, direction, mut position, attributes, world_name) in &mut query {
|
for (mut physics, direction, mut position, sprinting, attributes, world_name) in &mut query {
|
||||||
let world_lock = instance_container
|
let world_lock = instance_container
|
||||||
.get(world_name)
|
.get(world_name)
|
||||||
.expect("All entities should be in a valid world");
|
.expect("All entities should be in a valid world");
|
||||||
|
@ -92,6 +92,7 @@ fn travel(
|
||||||
&direction,
|
&direction,
|
||||||
&mut position,
|
&mut position,
|
||||||
attributes,
|
attributes,
|
||||||
|
sprinting.map(|s| **s).unwrap_or(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
movement.y -= gravity;
|
movement.y -= gravity;
|
||||||
|
@ -108,7 +109,7 @@ fn travel(
|
||||||
} else {
|
} else {
|
||||||
physics.delta = Vec3 {
|
physics.delta = Vec3 {
|
||||||
x: movement.x * inertia as f64,
|
x: movement.x * inertia as f64,
|
||||||
y: movement.y * 0.98f64,
|
y: movement.y * 0.9800000190734863f64,
|
||||||
z: movement.z * inertia as f64,
|
z: movement.z * inertia as f64,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -120,7 +121,6 @@ fn travel(
|
||||||
pub fn ai_step(
|
pub fn ai_step(
|
||||||
mut query: Query<
|
mut query: Query<
|
||||||
(
|
(
|
||||||
Entity,
|
|
||||||
&mut Physics,
|
&mut Physics,
|
||||||
Option<&Jumping>,
|
Option<&Jumping>,
|
||||||
&Position,
|
&Position,
|
||||||
|
@ -142,9 +142,7 @@ pub fn ai_step(
|
||||||
// )>,
|
// )>,
|
||||||
instance_container: Res<InstanceContainer>,
|
instance_container: Res<InstanceContainer>,
|
||||||
) {
|
) {
|
||||||
for (entity, mut physics, jumping, position, look_direction, sprinting, instance_name) in
|
for (mut physics, jumping, position, look_direction, sprinting, instance_name) in &mut query {
|
||||||
&mut query
|
|
||||||
{
|
|
||||||
// vanilla does movement interpolation here, doesn't really matter much for a
|
// vanilla does movement interpolation here, doesn't really matter much for a
|
||||||
// bot though
|
// bot though
|
||||||
|
|
||||||
|
@ -183,10 +181,6 @@ pub fn ai_step(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Jump even if we aren't on the ground.
|
|
||||||
#[derive(Event)]
|
|
||||||
pub struct ForceJumpEvent(pub Entity);
|
|
||||||
|
|
||||||
pub fn jump_from_ground(
|
pub fn jump_from_ground(
|
||||||
physics: &mut Physics,
|
physics: &mut Physics,
|
||||||
position: &Position,
|
position: &Position,
|
||||||
|
@ -211,9 +205,9 @@ pub fn jump_from_ground(
|
||||||
// sprint jumping gives some extra velocity
|
// sprint jumping gives some extra velocity
|
||||||
let y_rot = look_direction.y_rot * 0.017453292;
|
let y_rot = look_direction.y_rot * 0.017453292;
|
||||||
physics.delta += Vec3 {
|
physics.delta += Vec3 {
|
||||||
x: (-f32::sin(y_rot) * 0.2) as f64,
|
x: (-math::sin(y_rot) * 0.2) as f64,
|
||||||
y: 0.,
|
y: 0.,
|
||||||
z: (f32::cos(y_rot) * 0.2) as f64,
|
z: (math::cos(y_rot) * 0.2) as f64,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,11 +230,12 @@ fn handle_relative_friction_and_calculate_movement(
|
||||||
direction: &LookDirection,
|
direction: &LookDirection,
|
||||||
position: &mut Position,
|
position: &mut Position,
|
||||||
attributes: &Attributes,
|
attributes: &Attributes,
|
||||||
|
is_sprinting: bool,
|
||||||
) -> Vec3 {
|
) -> Vec3 {
|
||||||
move_relative(
|
move_relative(
|
||||||
physics,
|
physics,
|
||||||
direction,
|
direction,
|
||||||
get_friction_influenced_speed(physics, attributes, block_friction),
|
get_friction_influenced_speed(physics, attributes, block_friction, is_sprinting),
|
||||||
&Vec3 {
|
&Vec3 {
|
||||||
x: physics.xxa as f64,
|
x: physics.xxa as f64,
|
||||||
y: physics.yya as f64,
|
y: physics.yya as f64,
|
||||||
|
@ -270,14 +265,23 @@ fn handle_relative_friction_and_calculate_movement(
|
||||||
// private float getFrictionInfluencedSpeed(float friction) {
|
// private float getFrictionInfluencedSpeed(float friction) {
|
||||||
// return this.onGround ? this.getSpeed() * (0.21600002F / (friction *
|
// return this.onGround ? this.getSpeed() * (0.21600002F / (friction *
|
||||||
// friction * friction)) : this.flyingSpeed; }
|
// friction * friction)) : this.flyingSpeed; }
|
||||||
fn get_friction_influenced_speed(physics: &Physics, attributes: &Attributes, friction: f32) -> f32 {
|
fn get_friction_influenced_speed(
|
||||||
|
physics: &Physics,
|
||||||
|
attributes: &Attributes,
|
||||||
|
friction: f32,
|
||||||
|
is_sprinting: bool,
|
||||||
|
) -> f32 {
|
||||||
// TODO: have speed & flying_speed fields in entity
|
// TODO: have speed & flying_speed fields in entity
|
||||||
if physics.on_ground {
|
if physics.on_ground {
|
||||||
let speed: f32 = attributes.speed.calculate() as f32;
|
let speed: f32 = attributes.speed.calculate() as f32;
|
||||||
speed * (0.216f32 / (friction * friction * friction))
|
speed * (0.216f32 / (friction * friction * friction))
|
||||||
} else {
|
} else {
|
||||||
// entity.flying_speed
|
// entity.flying_speed
|
||||||
0.02
|
if is_sprinting {
|
||||||
|
0.025999999f32
|
||||||
|
} else {
|
||||||
|
0.02
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ use azalea::pathfinder::goals::BlockPosGoal;
|
||||||
use azalea::protocol::packets::game::ClientboundGamePacket;
|
use azalea::protocol::packets::game::ClientboundGamePacket;
|
||||||
use azalea::{prelude::*, swarm::prelude::*, BlockPos, GameProfileComponent, WalkDirection};
|
use azalea::{prelude::*, swarm::prelude::*, BlockPos, GameProfileComponent, WalkDirection};
|
||||||
use azalea::{Account, Client, Event};
|
use azalea::{Account, Client, Event};
|
||||||
|
use azalea_client::SprintDirection;
|
||||||
use azalea_core::Vec3;
|
use azalea_core::Vec3;
|
||||||
use azalea_world::{InstanceName, MinecraftEntityId};
|
use azalea_world::{InstanceName, MinecraftEntityId};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -145,6 +146,9 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
|
||||||
"walk" => {
|
"walk" => {
|
||||||
bot.walk(WalkDirection::Forward);
|
bot.walk(WalkDirection::Forward);
|
||||||
}
|
}
|
||||||
|
"sprint" => {
|
||||||
|
bot.sprint(SprintDirection::Forward);
|
||||||
|
}
|
||||||
"stop" => {
|
"stop" => {
|
||||||
bot.set_jumping(false);
|
bot.set_jumping(false);
|
||||||
bot.walk(WalkDirection::None);
|
bot.walk(WalkDirection::None);
|
||||||
|
|
Loading…
Add table
Reference in a new issue