1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 06:16:04 +00:00

start trying to fix

This commit is contained in:
mat 2023-03-12 16:12:28 -05:00
parent babb0d3a74
commit 3edd35aa42
17 changed files with 171 additions and 69 deletions

View file

@ -2,7 +2,7 @@ use crate::{
chat::ChatPlugin,
disconnect::{DisconnectEvent, DisconnectPlugin},
events::{Event, EventPlugin, LocalPlayerEvents},
interact::CurrentSequenceNumber,
interact::{CurrentSequenceNumber, InteractPlugin},
inventory::{InventoryComponent, InventoryPlugin},
local_player::{
death_event, handle_send_packet_event, update_in_loaded_chunk, GameProfileComponent,
@ -435,6 +435,11 @@ impl Client {
self.query::<&T>(&mut self.ecs.lock()).clone()
}
/// Get a component from this client, or `None` if it doesn't exist.
pub fn get_component<T: Component + Clone>(&self) -> Option<T> {
self.query::<Option<&T>>(&mut self.ecs.lock()).cloned()
}
/// Get a reference to our (potentially shared) world.
///
/// This gets the [`Instance`] from our world container. If it's a normal
@ -515,11 +520,7 @@ impl Plugin for AzaleaPlugin {
// Minecraft ticks happen every 50ms
app.insert_resource(FixedTime::new(Duration::from_millis(50)));
app.add_system(
update_in_loaded_chunk
.after(PhysicsSet)
.after(handle_send_packet_event),
);
app.add_system(update_in_loaded_chunk.after(PhysicsSet));
// fire the Death event when the player dies.
app.add_system(death_event);
@ -635,5 +636,6 @@ impl PluginGroup for DefaultPlugins {
.add(ChatPlugin)
.add(DisconnectPlugin)
.add(PlayerMovePlugin)
.add(InteractPlugin)
}
}

View file

@ -5,7 +5,7 @@ use azalea_protocol::packets::game::{
serverbound_use_item_on_packet::{BlockHit, ServerboundUseItemOnPacket},
};
use azalea_world::{
entity::{view_vector, EyeHeight, LookDirection, Position, WorldName},
entity::{clamp_look_direction, view_vector, EyeHeight, LookDirection, Position, WorldName},
InstanceContainer,
};
use bevy_app::{App, Plugin};
@ -13,19 +13,28 @@ use bevy_ecs::{
component::Component,
entity::Entity,
event::EventReader,
system::{Query, Res},
schedule::{IntoSystemConfig, IntoSystemConfigs},
system::{Commands, Query, Res},
};
use derive_more::{Deref, DerefMut};
use log::warn;
use crate::{local_player::LocalGameMode, Client, LocalPlayer};
use crate::{
local_player::{handle_send_packet_event, LocalGameMode},
Client, LocalPlayer,
};
/// A plugin that allows clients to interact with blocks in the world.
pub struct InteractPlugin;
impl Plugin for InteractPlugin {
fn build(&self, app: &mut App) {
app.add_event::<BlockInteractEvent>()
.add_systems((handle_block_interact_event, update_hit_result_component));
app.add_event::<BlockInteractEvent>().add_systems(
(
handle_block_interact_event,
update_hit_result_component.after(clamp_look_direction),
)
.before(handle_send_packet_event),
);
}
}
@ -96,8 +105,10 @@ fn handle_block_interact_event(
}
fn update_hit_result_component(
mut commands: Commands,
mut query: Query<(
&mut HitResultComponent,
Entity,
Option<&mut HitResultComponent>,
&LocalGameMode,
&Position,
&EyeHeight,
@ -106,7 +117,7 @@ fn update_hit_result_component(
)>,
instance_container: Res<InstanceContainer>,
) {
for (mut hit_result_ref, game_mode, position, eye_height, look_direction, world_name) in
for (entity, hit_result_ref, game_mode, position, eye_height, look_direction, world_name) in
&mut query
{
let pick_range = if game_mode.current == GameMode::Creative {
@ -121,6 +132,10 @@ fn update_hit_result_component(
z: position.z,
};
let end_position = eye_position + view_vector * pick_range;
println!(
"eye_position: {:?}, end_position: {:?}",
eye_position, end_position
);
let instance_lock = instance_container
.get(world_name)
.expect("entities must always be in a valid world");
@ -134,6 +149,12 @@ fn update_hit_result_component(
fluid_pick_type: FluidPickType::None,
},
);
**hit_result_ref = hit_result;
if let Some(mut hit_result_ref) = hit_result_ref {
**hit_result_ref = hit_result;
} else {
commands
.entity(entity)
.insert(HitResultComponent(hit_result));
}
}
}

View file

@ -4,11 +4,15 @@ use azalea_auth::game_profile::GameProfile;
use azalea_core::{ChunkPos, GameMode};
use azalea_protocol::packets::game::ServerboundGamePacket;
use azalea_world::{
entity::{self, Dead},
Instance, PartialInstance,
entity::{self, Dead, WorldName},
Instance, InstanceContainer, PartialInstance,
};
use bevy_ecs::{
component::Component, entity::Entity, event::EventReader, query::Added, system::Query,
component::Component,
entity::Entity,
event::EventReader,
query::Added,
system::{Query, Res},
};
use derive_more::{Deref, DerefMut};
use parking_lot::RwLock;
@ -83,6 +87,7 @@ pub struct LocalPlayerInLoadedChunk;
#[derive(Component, Clone, Debug, Copy)]
pub struct LocalGameMode {
pub current: GameMode,
pub previous: Option<GameMode>,
}
impl LocalPlayer {
@ -129,16 +134,15 @@ impl Drop for LocalPlayer {
/// Update the [`LocalPlayerInLoadedChunk`] component for all [`LocalPlayer`]s.
pub fn update_in_loaded_chunk(
mut commands: bevy_ecs::system::Commands,
query: Query<(Entity, &LocalPlayer, &entity::Position)>,
query: Query<(Entity, &WorldName, &entity::Position)>,
instance_container: Res<InstanceContainer>,
) {
for (entity, local_player, position) in &query {
let player_chunk_pos = ChunkPos::from(position);
let in_loaded_chunk = local_player
.world
.read()
.chunks
.get(&player_chunk_pos)
.is_some();
let instance_lock = instance_container
.get(&local_player)
.expect("local player should always be in an instance");
let in_loaded_chunk = instance_lock.read().chunks.get(&player_chunk_pos).is_some();
if in_loaded_chunk {
commands.entity(entity).insert(LocalPlayerInLoadedChunk);
} else {

View file

@ -251,9 +251,14 @@ fn process_packet_events(ecs: &mut World) {
metadata: PlayerMetadataBundle::default(),
};
// insert our components into the ecs :)
commands
.entity(player_entity)
.insert((MinecraftEntityId(p.player_id), player_bundle));
commands.entity(player_entity).insert((
MinecraftEntityId(p.player_id),
LocalGameMode {
current: p.game_type,
previous: p.previous_game_type.into(),
},
player_bundle,
));
}
// send the client information that we have set

View file

@ -164,15 +164,15 @@ impl AABB {
}
}
pub fn move_relative(&self, x: f64, y: f64, z: f64) -> AABB {
pub fn move_relative(&self, delta: &Vec3) -> AABB {
AABB {
min_x: self.min_x + x,
min_y: self.min_y + y,
min_z: self.min_z + z,
min_x: self.min_x + delta.x,
min_y: self.min_y + delta.y,
min_z: self.min_z + delta.z,
max_x: self.max_x + x,
max_y: self.max_y + y,
max_z: self.max_z + z,
max_x: self.max_x + delta.x,
max_y: self.max_y + delta.y,
max_z: self.max_z + delta.z,
}
}
@ -242,8 +242,15 @@ impl AABB {
let delta = to - from;
for aabb in boxes {
dir = Self::get_direction(aabb, from, &mut t, dir, &delta);
dir = Self::get_direction(
&aabb.move_relative(&pos.to_vec3()),
from,
&mut t,
dir,
&delta,
);
}
println!("dir: {dir:?} delta: {delta:?}");
let dir = dir?;
Some(BlockHitResult {
location: from + &(delta * t),
@ -258,11 +265,11 @@ impl AABB {
aabb: &AABB,
from: &Vec3,
t: &mut f64,
dir: Option<Direction>,
mut dir: Option<Direction>,
delta: &Vec3,
) -> Option<Direction> {
if delta.x > EPSILON {
return Self::clip_point(ClipPointOpts {
dir = Self::clip_point(ClipPointOpts {
t,
approach_dir: dir,
delta,
@ -275,7 +282,7 @@ impl AABB {
start: from,
});
} else if delta.x < -EPSILON {
return Self::clip_point(ClipPointOpts {
dir = Self::clip_point(ClipPointOpts {
t,
approach_dir: dir,
delta,
@ -290,7 +297,7 @@ impl AABB {
}
if delta.y > EPSILON {
return Self::clip_point(ClipPointOpts {
dir = Self::clip_point(ClipPointOpts {
t,
approach_dir: dir,
delta: &Vec3 {
@ -311,7 +318,7 @@ impl AABB {
},
});
} else if delta.y < -EPSILON {
return Self::clip_point(ClipPointOpts {
dir = Self::clip_point(ClipPointOpts {
t,
approach_dir: dir,
delta: &Vec3 {
@ -334,7 +341,7 @@ impl AABB {
}
if delta.z > EPSILON {
return Self::clip_point(ClipPointOpts {
dir = Self::clip_point(ClipPointOpts {
t,
approach_dir: dir,
delta: &Vec3 {
@ -355,7 +362,7 @@ impl AABB {
},
});
} else if delta.z < -EPSILON {
return Self::clip_point(ClipPointOpts {
dir = Self::clip_point(ClipPointOpts {
t,
approach_dir: dir,
delta: &Vec3 {
@ -381,9 +388,9 @@ impl AABB {
}
fn clip_point(opts: ClipPointOpts) -> Option<Direction> {
let t_x = (opts.begin - opts.start.x) / opts.delta.x;
let t_y = (opts.start.y + t_x) / opts.delta.y;
let t_z = (opts.start.z + t_x) / opts.delta.z;
let t_x = (opts.min_x - opts.start.x) / opts.delta.x;
let t_y = (opts.start.y + t_x) * opts.delta.y;
let t_z = (opts.start.z + t_x) * opts.delta.z;
if 0.0 < t_x
&& t_x < *opts.t
&& opts.min_x - EPSILON < t_y
@ -433,3 +440,28 @@ impl AABB {
axis.choose(self.min_x, self.min_y, self.min_z)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_aabb_clip_iterable() {
assert_ne!(
AABB::clip_iterable(
&vec![AABB {
min_x: 0.,
min_y: 0.,
min_z: 0.,
max_x: 1.,
max_y: 1.,
max_z: 1.,
}],
&Vec3::new(0., 0., 0.),
&Vec3::new(1., 1., 1.),
&BlockPos::new(0, 0, 0),
),
None
);
}
}

View file

@ -1,6 +1,6 @@
use crate::{BlockPos, Direction, Vec3};
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BlockHitResult {
pub location: Vec3,
pub direction: Direction,

View file

@ -2,7 +2,7 @@ use azalea_buf::McBuf;
use crate::Vec3;
#[derive(Clone, Copy, Debug, McBuf, Default)]
#[derive(Clone, Copy, Debug, McBuf, Default, Eq, PartialEq)]
pub enum Direction {
#[default]
Down = 0,

View file

@ -152,6 +152,15 @@ impl BlockPos {
}
}
/// Convert the block position into a Vec3 without centering it.
pub fn to_vec3(&self) -> Vec3 {
Vec3 {
x: self.x as f64,
y: self.y as f64,
z: self.z as f64,
}
}
/// Get the distance of this vector from the origin by doing `x + y + z`.
pub fn length_manhattan(&self) -> u32 {
(self.x.abs() + self.y.abs() + self.z.abs()) as u32

View file

@ -68,6 +68,7 @@ pub fn clip(chunk_storage: &ChunkStorage, context: ClipContext) -> BlockHitResul
block_shape,
&block_state,
);
println!("block_pos: {block_pos:?} block_hit_result: {block_hit_result:?}");
// let block_distance = if let Some(block_hit_result) = block_hit_result {
// context.from.distance_to_sqr(&block_hit_result.location)
// } else {
@ -126,7 +127,7 @@ fn clip_with_interaction_override(
}
Some(block_hit_result)
} else {
None
block_hit_result
}
}
@ -190,19 +191,19 @@ pub fn traverse_blocks<C, T>(
* if vec_sign.x > 0. {
1. - right_before_start.x.fract()
} else {
right_before_start.x.fract()
right_before_start.x.fract().abs()
},
y: percentage_step.y
* if vec_sign.y > 0. {
1. - right_before_start.y.fract()
} else {
right_before_start.y.fract()
right_before_start.y.fract().abs()
},
z: percentage_step.z
* if vec_sign.z > 0. {
1. - right_before_start.z.fract()
} else {
right_before_start.z.fract()
right_before_start.z.fract().abs()
},
};

View file

@ -45,6 +45,7 @@ impl DiscreteVoxelShape {
return false;
}
let (x, y, z) = (x as u32, y as u32, z as u32);
(x < self.size(Axis::X) && y < self.size(Axis::Y) && z < self.size(Axis::Z))
&& (self.is_full(x, y, z))
}

View file

@ -216,7 +216,11 @@ fn collide_with_shapes(
if y_movement != 0. {
y_movement = Shapes::collide(&Axis::Y, &entity_box, collision_boxes, y_movement);
if y_movement != 0. {
entity_box = entity_box.move_relative(0., y_movement, 0.);
entity_box = entity_box.move_relative(&Vec3 {
x: 0.,
y: y_movement,
z: 0.,
});
}
}
@ -227,14 +231,22 @@ fn collide_with_shapes(
if more_z_movement && z_movement != 0. {
z_movement = Shapes::collide(&Axis::Z, &entity_box, collision_boxes, z_movement);
if z_movement != 0. {
entity_box = entity_box.move_relative(0., 0., z_movement);
entity_box = entity_box.move_relative(&Vec3 {
x: 0.,
y: 0.,
z: z_movement,
});
}
}
if x_movement != 0. {
x_movement = Shapes::collide(&Axis::X, &entity_box, collision_boxes, x_movement);
if x_movement != 0. {
entity_box = entity_box.move_relative(x_movement, 0., 0.);
entity_box = entity_box.move_relative(&Vec3 {
x: x_movement,
y: 0.,
z: 0.,
});
}
}

View file

@ -394,10 +394,12 @@ impl VoxelShape {
pub fn clip(&self, from: &Vec3, to: &Vec3, block_pos: &BlockPos) -> Option<BlockHitResult> {
if self.is_empty() {
println!("empty");
return None;
}
let vector = to - from;
if vector.length_sqr() < EPSILON {
println!("short {}", vector.length_sqr());
return None;
}
let right_after_start = from + &(vector * 0.0001);
@ -415,6 +417,7 @@ impl VoxelShape {
miss: false,
})
} else {
println!("clip iterable {}", vector.length_sqr());
AABB::clip_iterable(&self.to_aabbs(), &from, &to, &block_pos)
}
}

View file

@ -8,8 +8,8 @@ use azalea_block::{Block, BlockState};
use azalea_core::{BlockPos, Vec3};
use azalea_world::{
entity::{
metadata::Sprinting, move_relative, Attributes, Jumping, Local, LookDirection, Physics,
Position, WorldName,
clamp_look_direction, metadata::Sprinting, move_relative, Attributes, Jumping, Local,
LookDirection, Physics, Position, WorldName,
},
Instance, InstanceContainer,
};
@ -31,7 +31,11 @@ pub struct PhysicsPlugin;
impl Plugin for PhysicsPlugin {
fn build(&self, app: &mut App) {
app.add_event::<ForceJumpEvent>()
.add_system(force_jump_listener.before(azalea_world::entity::update_bounding_box))
.add_system(
force_jump_listener
.before(azalea_world::entity::update_bounding_box)
.after(clamp_look_direction),
)
.add_systems(
(ai_step, travel)
.chain()

View file

@ -323,7 +323,7 @@ fn remove_despawned_entities_from_indexes(
}
}
fn clamp_look_direction(mut query: Query<&mut LookDirection>) {
pub fn clamp_look_direction(mut query: Query<&mut LookDirection>) {
for mut look_direction in &mut query {
look_direction.y_rot = look_direction.y_rot % 360.0;
look_direction.x_rot = look_direction.x_rot.clamp(-90.0, 90.0) % 360.0;

View file

@ -23,7 +23,8 @@ pub use data::*;
use derive_more::{Deref, DerefMut};
pub use dimensions::{update_bounding_box, EntityDimensions};
pub use info::{
EntityInfos, EntityPlugin, EntityUpdateSet, LoadedBy, PartialEntityInfos, RelativeEntityUpdate,
clamp_look_direction, EntityInfos, EntityPlugin, EntityUpdateSet, LoadedBy, PartialEntityInfos,
RelativeEntityUpdate,
};
use std::fmt::Debug;
use uuid::Uuid;
@ -70,16 +71,16 @@ pub fn input_vector(direction: &LookDirection, speed: f32, acceleration: &Vec3)
}
pub fn view_vector(look_direction: &LookDirection) -> Vec3 {
let y_rot = look_direction.y_rot * 0.017453292;
let x_rot = -look_direction.x_rot * 0.017453292;
let x_rot_cos = f32::cos(x_rot);
let x_rot_sin = f32::sin(x_rot);
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);
Vec3 {
x: (x_rot_sin * y_rot_cos) as f64,
y: (-y_rot_sin) as f64,
z: (x_rot_cos * y_rot_cos) as f64,
x: (y_rot_sin * x_rot_cos) as f64,
y: (-x_rot_sin) as f64,
z: (y_rot_cos * x_rot_cos) as f64,
}
}

View file

@ -5,6 +5,7 @@
use azalea::ecs::query::With;
use azalea::entity::metadata::Player;
use azalea::entity::Position;
use azalea::interact::HitResultComponent;
use azalea::inventory::InventoryComponent;
use azalea::pathfinder::BlockPosGoal;
use azalea::{prelude::*, swarm::prelude::*, BlockPos, GameProfileComponent, WalkDirection};
@ -47,7 +48,7 @@ async fn main() -> anyhow::Result<()> {
let mut accounts = Vec::new();
let mut states = Vec::new();
for i in 0..5 {
for i in 0..1 {
accounts.push(Account::offline(&format!("bot{i}")));
states.push(State::default());
}
@ -165,6 +166,10 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
bot.chat("no diamond block found");
}
}
"hitresult" => {
let hit_result = bot.get_component::<HitResultComponent>();
bot.chat(&format!("hit_result: {hit_result:?}",));
}
_ => {}
}
}

View file

@ -9,7 +9,7 @@ use crate::ecs::{
};
use azalea_core::Vec3;
use azalea_physics::{force_jump_listener, PhysicsSet};
use azalea_world::entity::LookDirection;
use azalea_world::entity::{clamp_look_direction, LookDirection};
use azalea_world::entity::{metadata::Player, Jumping, Local, Position};
use std::f64::consts::PI;
@ -23,7 +23,9 @@ impl Plugin for BotPlugin {
.add_event::<JumpEvent>()
.add_systems((
insert_bot,
look_at_listener.before(force_jump_listener),
look_at_listener
.before(force_jump_listener)
.before(clamp_look_direction),
jump_listener,
stop_jumping
.in_schedule(CoreSchedule::FixedUpdate)