1
2
Fork 0
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:
mat 2023-09-10 18:18:49 -05:00
parent 4885f848a4
commit 5f8704ccc5
6 changed files with 59 additions and 25 deletions

View file

@ -405,6 +405,7 @@ pub fn walk_listener(
if let Ok((mut physics_state, mut sprinting, mut attributes)) = query.get_mut(event.entity)
{
physics_state.move_direction = event.direction;
physics_state.trying_to_sprint = false;
set_sprinting(false, &mut sprinting, &mut attributes);
}
}

View file

@ -1,6 +1,7 @@
#![doc = include_str!("../README.md")]
#![feature(int_roundings)]
#![feature(const_for)]
#![feature(lazy_cell)]
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]

View file

@ -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
pub fn binary_search(mut min: i32, max: i32, predicate: &dyn Fn(i32) -> bool) -> i32 {
let mut diff = max - min;

View file

@ -12,7 +12,7 @@ mod plugin;
use self::attributes::AttributeInstance;
pub use attributes::Attributes;
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 bevy_ecs::{bundle::Bundle, component::Component};
pub use data::*;
@ -44,8 +44,8 @@ pub fn input_vector(direction: &LookDirection, speed: f32, acceleration: &Vec3)
*acceleration
}
.scale(speed as f64);
let y_rot = f32::sin(direction.y_rot * 0.017453292f32);
let x_rot = f32::cos(direction.y_rot * 0.017453292f32);
let y_rot = math::sin(direction.y_rot * 0.017453292f32);
let x_rot = math::cos(direction.y_rot * 0.017453292f32);
Vec3 {
x: acceleration.x * (x_rot as f64) - acceleration.z * (y_rot as f64),
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 {
let x_rot = look_direction.x_rot * 0.017453292;
let y_rot = -look_direction.y_rot * 0.017453292;
let y_rot_cos = f32::cos(y_rot);
let y_rot_sin = f32::sin(y_rot);
let x_rot_cos = f32::cos(x_rot);
let x_rot_sin = f32::sin(x_rot);
let y_rot_cos = math::cos(y_rot);
let y_rot_sin = math::sin(y_rot);
let x_rot_cos = math::cos(x_rot);
let x_rot_sin = math::sin(x_rot);
Vec3 {
x: (y_rot_sin * x_rot_cos) as f64,
y: (-x_rot_sin) as f64,

View file

@ -5,7 +5,7 @@ pub mod clip;
pub mod collision;
use azalea_block::{Block, BlockState};
use azalea_core::{BlockPos, Vec3};
use azalea_core::{math, BlockPos, Vec3};
use azalea_entity::{
metadata::Sprinting, move_relative, Attributes, Jumping, Local, LookDirection, Physics,
Position,
@ -30,8 +30,7 @@ pub struct PhysicsSet;
pub struct PhysicsPlugin;
impl Plugin for PhysicsPlugin {
fn build(&self, app: &mut App) {
app.add_event::<ForceJumpEvent>()
.add_systems(FixedUpdate, (ai_step, travel).chain().in_set(PhysicsSet));
app.add_systems(FixedUpdate, (ai_step, travel).chain().in_set(PhysicsSet));
}
}
@ -43,6 +42,7 @@ fn travel(
&mut Physics,
&mut LookDirection,
&mut Position,
Option<&Sprinting>,
&Attributes,
&InstanceName,
),
@ -50,7 +50,7 @@ fn travel(
>,
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
.get(world_name)
.expect("All entities should be in a valid world");
@ -92,6 +92,7 @@ fn travel(
&direction,
&mut position,
attributes,
sprinting.map(|s| **s).unwrap_or(false),
);
movement.y -= gravity;
@ -108,7 +109,7 @@ fn travel(
} else {
physics.delta = Vec3 {
x: movement.x * inertia as f64,
y: movement.y * 0.98f64,
y: movement.y * 0.9800000190734863f64,
z: movement.z * inertia as f64,
};
}
@ -120,7 +121,6 @@ fn travel(
pub fn ai_step(
mut query: Query<
(
Entity,
&mut Physics,
Option<&Jumping>,
&Position,
@ -142,9 +142,7 @@ pub fn ai_step(
// )>,
instance_container: Res<InstanceContainer>,
) {
for (entity, mut physics, jumping, position, look_direction, sprinting, instance_name) in
&mut query
{
for (mut physics, jumping, position, look_direction, sprinting, instance_name) in &mut query {
// vanilla does movement interpolation here, doesn't really matter much for a
// 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(
physics: &mut Physics,
position: &Position,
@ -211,9 +205,9 @@ pub fn jump_from_ground(
// sprint jumping gives some extra velocity
let y_rot = look_direction.y_rot * 0.017453292;
physics.delta += Vec3 {
x: (-f32::sin(y_rot) * 0.2) as f64,
x: (-math::sin(y_rot) * 0.2) as f64,
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,
position: &mut Position,
attributes: &Attributes,
is_sprinting: bool,
) -> Vec3 {
move_relative(
physics,
direction,
get_friction_influenced_speed(physics, attributes, block_friction),
get_friction_influenced_speed(physics, attributes, block_friction, is_sprinting),
&Vec3 {
x: physics.xxa as f64,
y: physics.yya as f64,
@ -270,16 +265,25 @@ fn handle_relative_friction_and_calculate_movement(
// private float getFrictionInfluencedSpeed(float friction) {
// return this.onGround ? this.getSpeed() * (0.21600002F / (friction *
// 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
if physics.on_ground {
let speed: f32 = attributes.speed.calculate() as f32;
speed * (0.216f32 / (friction * friction * friction))
} else {
// entity.flying_speed
if is_sprinting {
0.025999999f32
} else {
0.02
}
}
}
/// Returns the what the entity's jump should be multiplied by based on the
/// block they're standing on.

View file

@ -11,6 +11,7 @@ use azalea::pathfinder::goals::BlockPosGoal;
use azalea::protocol::packets::game::ClientboundGamePacket;
use azalea::{prelude::*, swarm::prelude::*, BlockPos, GameProfileComponent, WalkDirection};
use azalea::{Account, Client, Event};
use azalea_client::SprintDirection;
use azalea_core::Vec3;
use azalea_world::{InstanceName, MinecraftEntityId};
use std::time::Duration;
@ -145,6 +146,9 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
"walk" => {
bot.walk(WalkDirection::Forward);
}
"sprint" => {
bot.sprint(SprintDirection::Forward);
}
"stop" => {
bot.set_jumping(false);
bot.walk(WalkDirection::None);