mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-20 23:12:33 +00:00
add basic pathfinding test
This commit is contained in:
parent
9c31f8033f
commit
d5465cd28e
20 changed files with 341 additions and 171 deletions
53
Cargo.lock
generated
53
Cargo.lock
generated
|
@ -188,6 +188,7 @@ dependencies = [
|
||||||
"bevy_ecs",
|
"bevy_ecs",
|
||||||
"bevy_log",
|
"bevy_log",
|
||||||
"bevy_tasks",
|
"bevy_tasks",
|
||||||
|
"bevy_time",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
|
@ -555,9 +556,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_app"
|
name = "bevy_app"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "611dcfbfbb4d009597d54d3b6969a4aeac6eb2d208de79d0d3333fae4f5b9834"
|
checksum = "3cb660188d5d4ceaead6d5861ce22ecedc08b68c385cc8edf0a3c0c0285560bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy_derive",
|
"bevy_derive",
|
||||||
"bevy_ecs",
|
"bevy_ecs",
|
||||||
|
@ -571,9 +572,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_derive"
|
name = "bevy_derive"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af6bc1c0cb7a100d8345484677abb7f10f65f59bd786d8c20ac764817983e3d2"
|
checksum = "c5cc78985f4d0ad1fd7b8ead06dcfaa192685775a7b1be158191c788c7d52298"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy_macro_utils",
|
"bevy_macro_utils",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -582,9 +583,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_ecs"
|
name = "bevy_ecs"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06479bbf65542c96d2623249e1835287212cf06de524620071ab2c2e4b43bf18"
|
checksum = "fb6fd0ec64cd32b8fcf16157173431ba0e675b29c4643a8d6c9a9eeef6f93c32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-channel",
|
"async-channel",
|
||||||
"bevy_ecs_macros",
|
"bevy_ecs_macros",
|
||||||
|
@ -603,9 +604,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_ecs_macros"
|
name = "bevy_ecs_macros"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "58a7a55b3d525637755303cb5c52e7ee8058f80379f3715a68d16a4fcbd1d988"
|
checksum = "e13b0fd864433db6ff825efd0eb86b2690e208151905b184cc9bfd2c3ac66c3b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy_macro_utils",
|
"bevy_macro_utils",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -631,9 +632,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_macro_utils"
|
name = "bevy_macro_utils"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40e2d6a96a512787d8871c009a0a6eca0b02b5a1f52b8caed700c7ab0d57cfb1"
|
checksum = "d1cd460205fe05634d58b32d9bb752b1b4eaf32b2d29cbd4161ba35eb44a2f8c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
|
@ -643,9 +644,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_math"
|
name = "bevy_math"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4797b608d61d315b99388479b40ad9200baa24f232a8b292f2cf14f5d8a7ab1"
|
checksum = "267f2ec44aa948051768b1320c2dbff0871799e0a3b746f5fe5b6ee7258fbaf5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glam",
|
"glam",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -653,15 +654,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_ptr"
|
name = "bevy_ptr"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9eeb9144fc8bd8676f76c7660790ffce696fc80aade804b1c4e3d36a92f9df65"
|
checksum = "15702dff420fac72c2ab92428a8600e079ae89c5845401c4e39b843665a3d2d0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_reflect"
|
name = "bevy_reflect"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8a0bd344cb46b48a89a36af8aad7718b69e5e05332e058169478792be4eed86"
|
checksum = "3ac66cccbf1457c5cfc004a0e83569bd4ddc5d6310701f4af6aa81001fe2964a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy_math",
|
"bevy_math",
|
||||||
"bevy_ptr",
|
"bevy_ptr",
|
||||||
|
@ -680,9 +681,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_reflect_derive"
|
name = "bevy_reflect_derive"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22bdf9e985f7df44712ff93156b036c301aa6d1f211aec06ee6b06599396a4f0"
|
checksum = "e5a2a1fa784e9a22560b9de350246a159cd59239eb61c7b66824031b3b28abb0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy_macro_utils",
|
"bevy_macro_utils",
|
||||||
"bit-set",
|
"bit-set",
|
||||||
|
@ -694,9 +695,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_tasks"
|
name = "bevy_tasks"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5b89169296c682d2d33f0dfc9f09abf942148adfa2cc5e0b2e17514acc0fc87"
|
checksum = "9200e7b42d49c787d9a08675c425d8bd6393ba3beed2eac64be6027a44a01870"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-channel",
|
"async-channel",
|
||||||
"async-executor",
|
"async-executor",
|
||||||
|
@ -708,9 +709,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_time"
|
name = "bevy_time"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "91119de6907ff1cb58c637df235aa2e49332303abfa919a8c84cde942cfd69a4"
|
checksum = "2ba50bf25c4dc40296b744f77de10d39c8981b710d8dce609da9de5e54ef164b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy_app",
|
"bevy_app",
|
||||||
"bevy_ecs",
|
"bevy_ecs",
|
||||||
|
@ -722,9 +723,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_utils"
|
name = "bevy_utils"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a596771e2cc8f4cde4e2dddb3c5569414ee342811bb5d317d50fe8965c1d0e31"
|
checksum = "829eb8d0d06a0baeabc2e8bad74136ed3329b055aa1e11c5d9df09ebb9be3d85"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"bevy_utils_proc_macros",
|
"bevy_utils_proc_macros",
|
||||||
|
@ -739,9 +740,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_utils_proc_macros"
|
name = "bevy_utils_proc_macros"
|
||||||
version = "0.11.1"
|
version = "0.11.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e240bb064e9a1455e98e7dc8e701e1fd972c7fd32429ed1b4e7f36ac8974b7f"
|
checksum = "0d104f29e231123c703e8b394e2341d2425c33c5a2e9ab8cc8d0a554bdb62a41"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
@ -3,13 +3,13 @@ use azalea_brigadier::{exceptions::BuiltInExceptions, string_reader::StringReade
|
||||||
#[test]
|
#[test]
|
||||||
fn can_read() {
|
fn can_read() {
|
||||||
let mut reader = StringReader::from("abc".to_string());
|
let mut reader = StringReader::from("abc".to_string());
|
||||||
assert_eq!(reader.can_read(), true);
|
assert!(reader.can_read());
|
||||||
reader.skip(); // 'a'
|
reader.skip(); // 'a'
|
||||||
assert_eq!(reader.can_read(), true);
|
assert!(reader.can_read());
|
||||||
reader.skip(); // 'b'
|
reader.skip(); // 'b'
|
||||||
assert_eq!(reader.can_read(), true);
|
assert!(reader.can_read());
|
||||||
reader.skip(); // 'c'
|
reader.skip(); // 'c'
|
||||||
assert_eq!(reader.can_read(), false);
|
assert!(!reader.can_read());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -27,11 +27,11 @@ fn get_remaining_length() {
|
||||||
#[test]
|
#[test]
|
||||||
fn can_read_length() {
|
fn can_read_length() {
|
||||||
let reader = StringReader::from("abc".to_string());
|
let reader = StringReader::from("abc".to_string());
|
||||||
assert_eq!(reader.can_read_length(1), true);
|
assert!(reader.can_read_length(1));
|
||||||
assert_eq!(reader.can_read_length(2), true);
|
assert!(reader.can_read_length(2));
|
||||||
assert_eq!(reader.can_read_length(3), true);
|
assert!(reader.can_read_length(3));
|
||||||
assert_eq!(reader.can_read_length(4), false);
|
assert!(!reader.can_read_length(4));
|
||||||
assert_eq!(reader.can_read_length(5), false);
|
assert!(!reader.can_read_length(5));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -580,7 +580,7 @@ fn expect_none() {
|
||||||
#[test]
|
#[test]
|
||||||
fn read_boolean_correct() {
|
fn read_boolean_correct() {
|
||||||
let mut reader = StringReader::from("true".to_string());
|
let mut reader = StringReader::from("true".to_string());
|
||||||
assert_eq!(reader.read_boolean().unwrap(), true);
|
assert!(reader.read_boolean().unwrap());
|
||||||
assert_eq!(reader.get_read(), "true");
|
assert_eq!(reader.get_read(), "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,10 @@ use crate::{
|
||||||
inventory::{InventoryComponent, InventoryPlugin},
|
inventory::{InventoryComponent, InventoryPlugin},
|
||||||
local_player::{
|
local_player::{
|
||||||
death_event, handle_send_packet_event, update_in_loaded_chunk, GameProfileComponent,
|
death_event, handle_send_packet_event, update_in_loaded_chunk, GameProfileComponent,
|
||||||
Hunger, LocalPlayer, PhysicsState, SendPacketEvent,
|
Hunger, LocalPlayer, SendPacketEvent,
|
||||||
},
|
},
|
||||||
mining::{self, MinePlugin},
|
mining::{self, MinePlugin},
|
||||||
movement::{LastSentLookDirection, PlayerMovePlugin},
|
movement::{LastSentLookDirection, PhysicsState, PlayerMovePlugin},
|
||||||
packet_handling::{self, PacketHandlerPlugin, PacketReceiver},
|
packet_handling::{self, PacketHandlerPlugin, PacketReceiver},
|
||||||
player::retroactively_add_game_profile_component,
|
player::retroactively_add_game_profile_component,
|
||||||
respawn::RespawnPlugin,
|
respawn::RespawnPlugin,
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub mod interact;
|
||||||
pub mod inventory;
|
pub mod inventory;
|
||||||
mod local_player;
|
mod local_player;
|
||||||
pub mod mining;
|
pub mod mining;
|
||||||
mod movement;
|
pub mod movement;
|
||||||
pub mod packet_handling;
|
pub mod packet_handling;
|
||||||
pub mod ping;
|
pub mod ping;
|
||||||
mod player;
|
mod player;
|
||||||
|
@ -36,6 +36,8 @@ pub use client::{
|
||||||
TickBroadcast,
|
TickBroadcast,
|
||||||
};
|
};
|
||||||
pub use events::Event;
|
pub use events::Event;
|
||||||
pub use local_player::{GameProfileComponent, LocalPlayer};
|
pub use local_player::{GameProfileComponent, LocalPlayer, LocalPlayerInLoadedChunk};
|
||||||
pub use movement::{SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection};
|
pub use movement::{
|
||||||
|
PhysicsState, SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection,
|
||||||
|
};
|
||||||
pub use player::PlayerInfo;
|
pub use player::PlayerInfo;
|
||||||
|
|
|
@ -20,7 +20,7 @@ use tokio::{sync::mpsc, task::JoinHandle};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
events::{Event as AzaleaEvent, LocalPlayerEvents},
|
events::{Event as AzaleaEvent, LocalPlayerEvents},
|
||||||
ClientInformation, WalkDirection,
|
ClientInformation,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This is a component for our local player entities that are probably in a
|
/// This is a component for our local player entities that are probably in a
|
||||||
|
@ -51,23 +51,6 @@ pub struct LocalPlayer {
|
||||||
pub(crate) write_packets_task: JoinHandle<()>,
|
pub(crate) write_packets_task: JoinHandle<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Component for entities that can move and sprint. Usually only in
|
|
||||||
/// [`LocalPlayer`] entities.
|
|
||||||
#[derive(Default, Component)]
|
|
||||||
pub struct PhysicsState {
|
|
||||||
/// Minecraft only sends a movement packet either after 20 ticks or if the
|
|
||||||
/// player moved enough. This is that tick counter.
|
|
||||||
pub position_remainder: u32,
|
|
||||||
pub was_sprinting: bool,
|
|
||||||
// Whether we're going to try to start sprinting this tick. Equivalent to
|
|
||||||
// holding down ctrl for a tick.
|
|
||||||
pub trying_to_sprint: bool,
|
|
||||||
|
|
||||||
pub move_direction: WalkDirection,
|
|
||||||
pub forward_impulse: f32,
|
|
||||||
pub left_impulse: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A component only present in players that contains the [`GameProfile`] (which
|
/// A component only present in players that contains the [`GameProfile`] (which
|
||||||
/// you can use to get a player's name).
|
/// you can use to get a player's name).
|
||||||
///
|
///
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::client::Client;
|
use crate::client::Client;
|
||||||
use crate::local_player::{
|
use crate::local_player::{update_in_loaded_chunk, LocalPlayer, LocalPlayerInLoadedChunk};
|
||||||
update_in_loaded_chunk, LocalPlayer, LocalPlayerInLoadedChunk, PhysicsState,
|
|
||||||
};
|
|
||||||
use azalea_entity::{metadata::Sprinting, Attributes, Jumping};
|
use azalea_entity::{metadata::Sprinting, Attributes, Jumping};
|
||||||
use azalea_entity::{LastSentPosition, LookDirection, Physics, Position};
|
use azalea_entity::{LastSentPosition, LookDirection, Physics, Position};
|
||||||
use azalea_physics::{force_jump_listener, PhysicsSet};
|
use azalea_physics::{force_jump_listener, PhysicsSet};
|
||||||
|
@ -102,6 +100,23 @@ pub struct LastSentLookDirection {
|
||||||
pub y_rot: f32,
|
pub y_rot: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Component for entities that can move and sprint. Usually only in
|
||||||
|
/// [`LocalPlayer`] entities.
|
||||||
|
#[derive(Default, Component, Clone)]
|
||||||
|
pub struct PhysicsState {
|
||||||
|
/// Minecraft only sends a movement packet either after 20 ticks or if the
|
||||||
|
/// player moved enough. This is that tick counter.
|
||||||
|
pub position_remainder: u32,
|
||||||
|
pub was_sprinting: bool,
|
||||||
|
// Whether we're going to try to start sprinting this tick. Equivalent to
|
||||||
|
// holding down ctrl for a tick.
|
||||||
|
pub trying_to_sprint: bool,
|
||||||
|
|
||||||
|
pub move_direction: WalkDirection,
|
||||||
|
pub forward_impulse: f32,
|
||||||
|
pub left_impulse: f32,
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub(crate) fn send_position(
|
pub(crate) fn send_position(
|
||||||
mut query: Query<
|
mut query: Query<
|
||||||
|
|
|
@ -191,13 +191,13 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bitset() {
|
fn test_bitset() {
|
||||||
let mut bitset = BitSet::new(64);
|
let mut bitset = BitSet::new(64);
|
||||||
assert_eq!(bitset.index(0), false);
|
assert!(!bitset.index(0));
|
||||||
assert_eq!(bitset.index(1), false);
|
assert!(!bitset.index(1));
|
||||||
assert_eq!(bitset.index(2), false);
|
assert!(!bitset.index(2));
|
||||||
bitset.set(1);
|
bitset.set(1);
|
||||||
assert_eq!(bitset.index(0), false);
|
assert!(!bitset.index(0));
|
||||||
assert_eq!(bitset.index(1), true);
|
assert!(bitset.index(1));
|
||||||
assert_eq!(bitset.index(2), false);
|
assert!(!bitset.index(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -211,11 +211,11 @@ mod tests {
|
||||||
|
|
||||||
bitset.clear(63, 65);
|
bitset.clear(63, 65);
|
||||||
|
|
||||||
assert_eq!(bitset.index(62), true);
|
assert!(bitset.index(62));
|
||||||
assert_eq!(bitset.index(63), false);
|
assert!(!bitset.index(63));
|
||||||
assert_eq!(bitset.index(64), false);
|
assert!(!bitset.index(64));
|
||||||
assert_eq!(bitset.index(65), true);
|
assert!(bitset.index(65));
|
||||||
assert_eq!(bitset.index(66), true);
|
assert!(bitset.index(66));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -229,10 +229,10 @@ mod tests {
|
||||||
|
|
||||||
bitset.clear(65, 67);
|
bitset.clear(65, 67);
|
||||||
|
|
||||||
assert_eq!(bitset.index(64), true);
|
assert!(bitset.index(64));
|
||||||
assert_eq!(bitset.index(65), false);
|
assert!(!bitset.index(65));
|
||||||
assert_eq!(bitset.index(66), false);
|
assert!(!bitset.index(66));
|
||||||
assert_eq!(bitset.index(67), true);
|
assert!(bitset.index(67));
|
||||||
assert_eq!(bitset.index(68), true);
|
assert!(bitset.index(68));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ fn bench(c: &mut Criterion) {
|
||||||
let (mut enc, dec) = create_cipher(b"0123456789abcdef");
|
let (mut enc, dec) = create_cipher(b"0123456789abcdef");
|
||||||
|
|
||||||
let mut packet = [0u8; 65536];
|
let mut packet = [0u8; 65536];
|
||||||
for i in 0..packet.len() {
|
for (i, item) in packet.iter_mut().enumerate() {
|
||||||
packet[i] = i as u8;
|
*item = i as u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
c.bench_function("Encrypt 64kb", |b| {
|
c.bench_function("Encrypt 64kb", |b| {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use azalea_core::{Vec3, AABB};
|
use azalea_core::{Vec3, AABB};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct EntityDimensions {
|
pub struct EntityDimensions {
|
||||||
pub width: f32,
|
pub width: f32,
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
|
|
|
@ -125,6 +125,11 @@ impl Debug for EntityUuid {
|
||||||
/// automatically.
|
/// automatically.
|
||||||
#[derive(Component, Clone, Copy, Debug, Default, PartialEq, Deref, DerefMut)]
|
#[derive(Component, Clone, Copy, Debug, Default, PartialEq, Deref, DerefMut)]
|
||||||
pub struct Position(Vec3);
|
pub struct Position(Vec3);
|
||||||
|
impl Position {
|
||||||
|
pub fn new(pos: Vec3) -> Self {
|
||||||
|
Self(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
impl From<&Position> for Vec3 {
|
impl From<&Position> for Vec3 {
|
||||||
fn from(value: &Position) -> Self {
|
fn from(value: &Position) -> Self {
|
||||||
value.0
|
value.0
|
||||||
|
@ -184,7 +189,7 @@ impl From<&LastSentPosition> for BlockPos {
|
||||||
///
|
///
|
||||||
/// If this is true, the entity will try to jump every tick. (It's equivalent to
|
/// If this is true, the entity will try to jump every tick. (It's equivalent to
|
||||||
/// the space key being held in vanilla.)
|
/// the space key being held in vanilla.)
|
||||||
#[derive(Debug, Component, Clone, Deref, DerefMut)]
|
#[derive(Debug, Component, Clone, Deref, DerefMut, Default)]
|
||||||
pub struct Jumping(bool);
|
pub struct Jumping(bool);
|
||||||
|
|
||||||
/// A component that contains the direction an entity is looking.
|
/// A component that contains the direction an entity is looking.
|
||||||
|
@ -196,7 +201,7 @@ pub struct LookDirection {
|
||||||
|
|
||||||
/// The physics data relating to the entity, such as position, velocity, and
|
/// The physics data relating to the entity, such as position, velocity, and
|
||||||
/// bounding box.
|
/// bounding box.
|
||||||
#[derive(Debug, Component)]
|
#[derive(Debug, Component, Clone)]
|
||||||
pub struct Physics {
|
pub struct Physics {
|
||||||
pub delta: Vec3,
|
pub delta: Vec3,
|
||||||
|
|
||||||
|
@ -219,6 +224,26 @@ pub struct Physics {
|
||||||
pub has_impulse: bool,
|
pub has_impulse: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Physics {
|
||||||
|
pub fn new(dimensions: EntityDimensions, pos: &Vec3) -> Self {
|
||||||
|
Self {
|
||||||
|
delta: Vec3::default(),
|
||||||
|
|
||||||
|
xxa: 0.,
|
||||||
|
yya: 0.,
|
||||||
|
zza: 0.,
|
||||||
|
|
||||||
|
on_ground: false,
|
||||||
|
last_on_ground: false,
|
||||||
|
|
||||||
|
bounding_box: dimensions.make_bounding_box(pos),
|
||||||
|
dimensions,
|
||||||
|
|
||||||
|
has_impulse: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Marker component for entities that are dead.
|
/// Marker component for entities that are dead.
|
||||||
///
|
///
|
||||||
/// "Dead" means that the entity has 0 health.
|
/// "Dead" means that the entity has 0 health.
|
||||||
|
@ -297,22 +322,7 @@ impl EntityBundle {
|
||||||
world_name: InstanceName(world_name),
|
world_name: InstanceName(world_name),
|
||||||
position: Position(pos),
|
position: Position(pos),
|
||||||
last_sent_position: LastSentPosition(pos),
|
last_sent_position: LastSentPosition(pos),
|
||||||
physics: Physics {
|
physics: Physics::new(dimensions, &pos),
|
||||||
delta: Vec3::default(),
|
|
||||||
|
|
||||||
xxa: 0.,
|
|
||||||
yya: 0.,
|
|
||||||
zza: 0.,
|
|
||||||
|
|
||||||
on_ground: false,
|
|
||||||
last_on_ground: false,
|
|
||||||
|
|
||||||
// TODO: have this be based on the entity type
|
|
||||||
bounding_box: dimensions.make_bounding_box(&pos),
|
|
||||||
dimensions,
|
|
||||||
|
|
||||||
has_impulse: false,
|
|
||||||
},
|
|
||||||
eye_height: EyeHeight(eye_height),
|
eye_height: EyeHeight(eye_height),
|
||||||
direction: LookDirection::default(),
|
direction: LookDirection::default(),
|
||||||
|
|
||||||
|
|
|
@ -229,6 +229,7 @@ pub fn update_entity_chunk_positions(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Despawn entities that aren't being loaded by anything.
|
/// Despawn entities that aren't being loaded by anything.
|
||||||
|
#[allow(clippy::type_complexity)]
|
||||||
pub fn remove_despawned_entities_from_indexes(
|
pub fn remove_despawned_entities_from_indexes(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut entity_infos: ResMut<EntityUuidIndex>,
|
mut entity_infos: ResMut<EntityUuidIndex>,
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
|
||||||
group.bench_function("azalea_parse", |b| {
|
group.bench_function("azalea_parse", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let input = black_box(input);
|
let input = black_box(input);
|
||||||
let nbt = azalea_nbt::Nbt::read(&mut Cursor::new(&input)).unwrap();
|
let nbt = azalea_nbt::Nbt::read(&mut Cursor::new(input)).unwrap();
|
||||||
black_box(nbt);
|
black_box(nbt);
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
|
@ -427,7 +427,7 @@ mod tests {
|
||||||
let block_state = partial_world.chunks.set_block_state(
|
let block_state = partial_world.chunks.set_block_state(
|
||||||
&BlockPos { x: 0, y: 69, z: 0 },
|
&BlockPos { x: 0, y: 69, z: 0 },
|
||||||
azalea_registry::Block::Stone.into(),
|
azalea_registry::Block::Stone.into(),
|
||||||
&mut world_lock.write().chunks,
|
&world_lock.write().chunks,
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
block_state.is_some(),
|
block_state.is_some(),
|
||||||
|
@ -490,7 +490,7 @@ mod tests {
|
||||||
waterlogged: false,
|
waterlogged: false,
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
&mut world_lock.write().chunks,
|
&world_lock.write().chunks,
|
||||||
);
|
);
|
||||||
assert!(
|
assert!(
|
||||||
block_state.is_some(),
|
block_state.is_some(),
|
||||||
|
|
|
@ -41,6 +41,7 @@ tokio = "^1.31.0"
|
||||||
uuid = "1.4.1"
|
uuid = "1.4.1"
|
||||||
bevy_log = "0.11.1"
|
bevy_log = "0.11.1"
|
||||||
azalea-entity = { version = "0.1.0", path = "../azalea-entity" }
|
azalea-entity = { version = "0.1.0", path = "../azalea-entity" }
|
||||||
|
bevy_time = "0.11.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["log"]
|
default = ["log"]
|
||||||
|
|
|
@ -18,16 +18,13 @@ async fn main() {
|
||||||
pub struct State {}
|
pub struct State {}
|
||||||
|
|
||||||
async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()> {
|
async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()> {
|
||||||
match event {
|
if let Event::Chat(m) = event {
|
||||||
Event::Chat(m) => {
|
if let (Some(sender), content) = m.split_sender_and_content() {
|
||||||
if let (Some(sender), content) = m.split_sender_and_content() {
|
if sender == bot.profile.name {
|
||||||
if sender == bot.profile.name {
|
return Ok(()); // ignore our own messages
|
||||||
return Ok(()); // ignore our own messages
|
}
|
||||||
}
|
bot.chat(&content);
|
||||||
bot.chat(&content);
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -24,52 +24,49 @@ struct State {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
|
||||||
match event {
|
if let Event::Chat(m) = event {
|
||||||
Event::Chat(m) => {
|
if m.username() == Some(bot.profile.name.clone()) {
|
||||||
if m.username() == Some(bot.profile.name.clone()) {
|
return Ok(());
|
||||||
return Ok(());
|
};
|
||||||
};
|
if m.content() != "go" {
|
||||||
if m.content() != "go" {
|
return Ok(());
|
||||||
return Ok(());
|
}
|
||||||
}
|
{
|
||||||
{
|
state.checked_chests.lock().clear();
|
||||||
state.checked_chests.lock().clear();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let chest_block = bot
|
let chest_block = bot
|
||||||
.world()
|
.world()
|
||||||
.read()
|
.read()
|
||||||
.find_block(bot.position(), &azalea::Block::Chest.into());
|
.find_block(bot.position(), &azalea::Block::Chest.into());
|
||||||
// TODO: update this when find_blocks is implemented
|
// TODO: update this when find_blocks is implemented
|
||||||
let Some(chest_block) = chest_block else {
|
let Some(chest_block) = chest_block else {
|
||||||
bot.chat("No chest found");
|
bot.chat("No chest found");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
// bot.goto(BlockPosGoal::from(chest_block));
|
// bot.goto(BlockPosGoal::from(chest_block));
|
||||||
let Some(chest) = bot.open_container(chest_block).await else {
|
let Some(chest) = bot.open_container(chest_block).await else {
|
||||||
println!("Couldn't open chest");
|
println!("Couldn't open chest");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("Getting contents");
|
println!("Getting contents");
|
||||||
for (index, slot) in chest
|
for (index, slot) in chest
|
||||||
.contents()
|
.contents()
|
||||||
.expect("we just opened the chest")
|
.expect("we just opened the chest")
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
println!("Checking slot {index}: {slot:?}");
|
println!("Checking slot {index}: {slot:?}");
|
||||||
if let ItemSlot::Present(item) = slot {
|
if let ItemSlot::Present(item) = slot {
|
||||||
if item.kind == azalea::Item::Diamond {
|
if item.kind == azalea::Item::Diamond {
|
||||||
println!("clicking slot ^");
|
println!("clicking slot ^");
|
||||||
chest.click(QuickMoveClick::Left { slot: index as u16 });
|
chest.click(QuickMoveClick::Left { slot: index as u16 });
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Done");
|
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
|
println!("Done");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -284,12 +284,11 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::Packet(packet) => match *packet {
|
Event::Packet(packet) => {
|
||||||
ClientboundGamePacket::Login(_) => {
|
if let ClientboundGamePacket::Login(_) = *packet {
|
||||||
println!("login packet");
|
println!("login packet");
|
||||||
}
|
}
|
||||||
_ => {}
|
}
|
||||||
},
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
mod astar;
|
mod astar;
|
||||||
pub mod goals;
|
pub mod goals;
|
||||||
mod moves;
|
mod moves;
|
||||||
|
pub mod simulation;
|
||||||
|
|
||||||
use crate::bot::{JumpEvent, LookAtEvent};
|
use crate::bot::{JumpEvent, LookAtEvent};
|
||||||
use crate::pathfinder::astar::a_star;
|
use crate::pathfinder::astar::a_star;
|
||||||
|
@ -22,7 +23,7 @@ use azalea_entity::Local;
|
||||||
use azalea_entity::{Physics, Position};
|
use azalea_entity::{Physics, Position};
|
||||||
use azalea_physics::PhysicsSet;
|
use azalea_physics::PhysicsSet;
|
||||||
use azalea_world::{InstanceContainer, InstanceName};
|
use azalea_world::{InstanceContainer, InstanceName};
|
||||||
use bevy_app::{FixedUpdate, Update};
|
use bevy_app::{FixedUpdate, PreUpdate, Update};
|
||||||
use bevy_ecs::prelude::Event;
|
use bevy_ecs::prelude::Event;
|
||||||
use bevy_ecs::query::Changed;
|
use bevy_ecs::query::Changed;
|
||||||
use bevy_ecs::schedule::IntoSystemConfigs;
|
use bevy_ecs::schedule::IntoSystemConfigs;
|
||||||
|
@ -44,11 +45,11 @@ impl Plugin for PathfinderPlugin {
|
||||||
// (every 50 milliseconds).
|
// (every 50 milliseconds).
|
||||||
tick_execute_path.before(PhysicsSet),
|
tick_execute_path.before(PhysicsSet),
|
||||||
)
|
)
|
||||||
|
.add_systems(PreUpdate, add_default_pathfinder)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(
|
||||||
goto_listener,
|
goto_listener,
|
||||||
add_default_pathfinder,
|
|
||||||
(handle_tasks, path_found_listener).chain(),
|
(handle_tasks, path_found_listener).chain(),
|
||||||
stop_pathfinding_on_instance_change,
|
stop_pathfinding_on_instance_change,
|
||||||
),
|
),
|
||||||
|
@ -342,3 +343,57 @@ impl Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use azalea_core::{BlockPos, ChunkPos, Vec3};
|
||||||
|
use azalea_world::{Chunk, ChunkStorage, PartialChunkStorage};
|
||||||
|
use bevy_log::LogPlugin;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
goals::BlockPosGoal,
|
||||||
|
simulation::{SimulatedPlayerBundle, Simulation},
|
||||||
|
GotoEvent,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simple_forward() {
|
||||||
|
let mut chunks = ChunkStorage::default();
|
||||||
|
let mut partial_chunks = PartialChunkStorage::default();
|
||||||
|
partial_chunks.set(
|
||||||
|
&ChunkPos { x: 0, z: 0 },
|
||||||
|
Some(Chunk::default()),
|
||||||
|
&mut chunks,
|
||||||
|
);
|
||||||
|
chunks.set_block_state(
|
||||||
|
&BlockPos::new(0, 70, 0),
|
||||||
|
azalea_registry::Block::Stone.into(),
|
||||||
|
);
|
||||||
|
chunks.set_block_state(
|
||||||
|
&BlockPos::new(0, 70, 1),
|
||||||
|
azalea_registry::Block::Stone.into(),
|
||||||
|
);
|
||||||
|
let player = SimulatedPlayerBundle::new(Vec3::new(0.5, 71., 0.5));
|
||||||
|
let mut simulation = Simulation::new(chunks, player);
|
||||||
|
simulation.app.add_plugins(LogPlugin {
|
||||||
|
level: bevy_log::Level::DEBUG,
|
||||||
|
filter: "".to_string(),
|
||||||
|
});
|
||||||
|
|
||||||
|
simulation.app.world.send_event(GotoEvent {
|
||||||
|
entity: simulation.entity,
|
||||||
|
goal: Arc::new(BlockPosGoal::from(BlockPos::new(0, 71, 1))),
|
||||||
|
});
|
||||||
|
|
||||||
|
for _ in 0..20 {
|
||||||
|
simulation.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
BlockPos::from(simulation.position()),
|
||||||
|
BlockPos::new(0, 71, 1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -192,17 +192,17 @@ mod tests {
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 0, 0),
|
&BlockPos::new(0, 0, 0),
|
||||||
azalea_registry::Block::Stone.into(),
|
azalea_registry::Block::Stone.into(),
|
||||||
&mut chunk_storage,
|
&chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 1, 0),
|
&BlockPos::new(0, 1, 0),
|
||||||
BlockState::AIR,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&chunk_storage,
|
||||||
);
|
);
|
||||||
|
|
||||||
let world = chunk_storage.into();
|
let world = chunk_storage.into();
|
||||||
assert_eq!(is_block_passable(&BlockPos::new(0, 0, 0), &world), false);
|
assert!(!is_block_passable(&BlockPos::new(0, 0, 0), &world));
|
||||||
assert_eq!(is_block_passable(&BlockPos::new(0, 1, 0), &world), true);
|
assert!(is_block_passable(&BlockPos::new(0, 1, 0), &world));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -217,17 +217,17 @@ mod tests {
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 0, 0),
|
&BlockPos::new(0, 0, 0),
|
||||||
azalea_registry::Block::Stone.into(),
|
azalea_registry::Block::Stone.into(),
|
||||||
&mut chunk_storage,
|
&chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 1, 0),
|
&BlockPos::new(0, 1, 0),
|
||||||
BlockState::AIR,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&chunk_storage,
|
||||||
);
|
);
|
||||||
|
|
||||||
let world = chunk_storage.into();
|
let world = chunk_storage.into();
|
||||||
assert_eq!(is_block_solid(&BlockPos::new(0, 0, 0), &world), true);
|
assert!(is_block_solid(&BlockPos::new(0, 0, 0), &world));
|
||||||
assert_eq!(is_block_solid(&BlockPos::new(0, 1, 0), &world), false);
|
assert!(!is_block_solid(&BlockPos::new(0, 1, 0), &world));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -242,22 +242,22 @@ mod tests {
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 0, 0),
|
&BlockPos::new(0, 0, 0),
|
||||||
azalea_registry::Block::Stone.into(),
|
azalea_registry::Block::Stone.into(),
|
||||||
&mut chunk_storage,
|
&chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 1, 0),
|
&BlockPos::new(0, 1, 0),
|
||||||
BlockState::AIR,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 2, 0),
|
&BlockPos::new(0, 2, 0),
|
||||||
BlockState::AIR,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&chunk_storage,
|
||||||
);
|
);
|
||||||
partial_world.chunks.set_block_state(
|
partial_world.chunks.set_block_state(
|
||||||
&BlockPos::new(0, 3, 0),
|
&BlockPos::new(0, 3, 0),
|
||||||
BlockState::AIR,
|
BlockState::AIR,
|
||||||
&mut chunk_storage,
|
&chunk_storage,
|
||||||
);
|
);
|
||||||
|
|
||||||
let world = chunk_storage.into();
|
let world = chunk_storage.into();
|
||||||
|
|
109
azalea/src/pathfinder/simulation.rs
Normal file
109
azalea/src/pathfinder/simulation.rs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
use std::{sync::Arc, time::Duration};
|
||||||
|
|
||||||
|
use azalea_client::PhysicsState;
|
||||||
|
use azalea_core::{ResourceLocation, Vec3};
|
||||||
|
use azalea_entity::{
|
||||||
|
attributes::AttributeInstance, metadata::Sprinting, Attributes, EntityDimensions, Physics,
|
||||||
|
Position,
|
||||||
|
};
|
||||||
|
use azalea_world::{ChunkStorage, Instance, InstanceContainer, InstanceName, MinecraftEntityId};
|
||||||
|
use bevy_app::{App, FixedUpdate};
|
||||||
|
use bevy_ecs::prelude::*;
|
||||||
|
use bevy_time::fixed_timestep::FixedTime;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
|
#[derive(Bundle, Clone)]
|
||||||
|
pub struct SimulatedPlayerBundle {
|
||||||
|
pub position: Position,
|
||||||
|
pub physics: Physics,
|
||||||
|
pub physics_state: PhysicsState,
|
||||||
|
pub attributes: Attributes,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SimulatedPlayerBundle {
|
||||||
|
pub fn new(position: Vec3) -> Self {
|
||||||
|
let dimensions = EntityDimensions {
|
||||||
|
width: 0.6,
|
||||||
|
height: 1.8,
|
||||||
|
};
|
||||||
|
|
||||||
|
SimulatedPlayerBundle {
|
||||||
|
position: Position::new(position),
|
||||||
|
physics: Physics::new(dimensions, &position),
|
||||||
|
physics_state: PhysicsState::default(),
|
||||||
|
attributes: Attributes {
|
||||||
|
speed: AttributeInstance::new(0.1),
|
||||||
|
attack_speed: AttributeInstance::new(4.0),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Simulate the Minecraft world to see if certain movements would be possible.
|
||||||
|
pub struct Simulation {
|
||||||
|
pub app: App,
|
||||||
|
pub entity: Entity,
|
||||||
|
_instance: Arc<RwLock<Instance>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Simulation {
|
||||||
|
pub fn new(chunks: ChunkStorage, player: SimulatedPlayerBundle) -> Self {
|
||||||
|
let instance_name = ResourceLocation::new("azalea:simulation");
|
||||||
|
|
||||||
|
let instance = Arc::new(RwLock::new(Instance {
|
||||||
|
chunks,
|
||||||
|
..Default::default()
|
||||||
|
}));
|
||||||
|
|
||||||
|
let mut app = App::new();
|
||||||
|
// we don't use all the default azalea plugins because we don't need all of them
|
||||||
|
app.add_plugins((
|
||||||
|
azalea_physics::PhysicsPlugin,
|
||||||
|
azalea_entity::EntityPlugin,
|
||||||
|
azalea_client::movement::PlayerMovePlugin,
|
||||||
|
super::PathfinderPlugin,
|
||||||
|
crate::BotPlugin,
|
||||||
|
azalea_client::task_pool::TaskPoolPlugin::default(),
|
||||||
|
))
|
||||||
|
// make sure it doesn't do fixed ticks without us telling it to
|
||||||
|
.insert_resource(FixedTime::new(Duration::from_secs(60)))
|
||||||
|
.insert_resource(InstanceContainer {
|
||||||
|
worlds: [(instance_name.clone(), Arc::downgrade(&instance.clone()))]
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
});
|
||||||
|
|
||||||
|
app.edit_schedule(bevy_app::Main, |schedule| {
|
||||||
|
schedule.set_executor_kind(bevy_ecs::schedule::ExecutorKind::SingleThreaded);
|
||||||
|
});
|
||||||
|
|
||||||
|
let entity = app
|
||||||
|
.world
|
||||||
|
.spawn((
|
||||||
|
MinecraftEntityId(0),
|
||||||
|
InstanceName(instance_name),
|
||||||
|
azalea_entity::Local,
|
||||||
|
azalea_client::LocalPlayerInLoadedChunk,
|
||||||
|
azalea_entity::Jumping::default(),
|
||||||
|
azalea_entity::LookDirection::default(),
|
||||||
|
Sprinting(true),
|
||||||
|
azalea_entity::metadata::Player,
|
||||||
|
player,
|
||||||
|
))
|
||||||
|
.id();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
app,
|
||||||
|
entity,
|
||||||
|
_instance: instance,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn tick(&mut self) {
|
||||||
|
self.app.world.run_schedule(FixedUpdate);
|
||||||
|
self.app.update();
|
||||||
|
}
|
||||||
|
pub fn position(&self) -> Vec3 {
|
||||||
|
**self.app.world.get::<Position>(self.entity).unwrap()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue