aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2023-08-25 02:34:31 -0500
committermat <git@matdoes.dev>2023-08-25 02:34:31 -0500
commitd5465cd28e43d48b3e913fdb1161eb907e4d80d0 (patch)
treeb0962ac1bd09b434c67296c038ef3b26245ce6d7
parent9c31f8033f006d5f505ce97e359638d6c1136859 (diff)
downloadazalea-drasl-d5465cd28e43d48b3e913fdb1161eb907e4d80d0.tar.xz
add basic pathfinding test
-rw-r--r--Cargo.lock53
-rwxr-xr-xazalea-brigadier/tests/string_reader_test.rs20
-rw-r--r--azalea-client/src/client.rs4
-rw-r--r--azalea-client/src/lib.rs8
-rw-r--r--azalea-client/src/local_player.rs19
-rw-r--r--azalea-client/src/movement.rs21
-rwxr-xr-xazalea-core/src/bitset.rs32
-rwxr-xr-xazalea-crypto/benches/my_benchmark.rs4
-rwxr-xr-xazalea-entity/src/dimensions.rs2
-rw-r--r--azalea-entity/src/lib.rs46
-rw-r--r--azalea-entity/src/plugin/indexing.rs1
-rwxr-xr-xazalea-nbt/benches/compare.rs2
-rw-r--r--azalea-physics/src/lib.rs4
-rw-r--r--azalea/Cargo.toml1
-rwxr-xr-xazalea/examples/echo.rs17
-rw-r--r--azalea/examples/steal.rs79
-rw-r--r--azalea/examples/testbot.rs7
-rw-r--r--azalea/src/pathfinder/mod.rs59
-rw-r--r--azalea/src/pathfinder/moves.rs24
-rw-r--r--azalea/src/pathfinder/simulation.rs109
20 files changed, 341 insertions, 171 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b2fc510b..ebad9585 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -188,6 +188,7 @@ dependencies = [
"bevy_ecs",
"bevy_log",
"bevy_tasks",
+ "bevy_time",
"derive_more",
"futures",
"futures-lite",
@@ -555,9 +556,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]]
name = "bevy_app"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "611dcfbfbb4d009597d54d3b6969a4aeac6eb2d208de79d0d3333fae4f5b9834"
+checksum = "3cb660188d5d4ceaead6d5861ce22ecedc08b68c385cc8edf0a3c0c0285560bf"
dependencies = [
"bevy_derive",
"bevy_ecs",
@@ -571,9 +572,9 @@ dependencies = [
[[package]]
name = "bevy_derive"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af6bc1c0cb7a100d8345484677abb7f10f65f59bd786d8c20ac764817983e3d2"
+checksum = "c5cc78985f4d0ad1fd7b8ead06dcfaa192685775a7b1be158191c788c7d52298"
dependencies = [
"bevy_macro_utils",
"quote",
@@ -582,9 +583,9 @@ dependencies = [
[[package]]
name = "bevy_ecs"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06479bbf65542c96d2623249e1835287212cf06de524620071ab2c2e4b43bf18"
+checksum = "fb6fd0ec64cd32b8fcf16157173431ba0e675b29c4643a8d6c9a9eeef6f93c32"
dependencies = [
"async-channel",
"bevy_ecs_macros",
@@ -603,9 +604,9 @@ dependencies = [
[[package]]
name = "bevy_ecs_macros"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58a7a55b3d525637755303cb5c52e7ee8058f80379f3715a68d16a4fcbd1d988"
+checksum = "e13b0fd864433db6ff825efd0eb86b2690e208151905b184cc9bfd2c3ac66c3b"
dependencies = [
"bevy_macro_utils",
"proc-macro2",
@@ -631,9 +632,9 @@ dependencies = [
[[package]]
name = "bevy_macro_utils"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40e2d6a96a512787d8871c009a0a6eca0b02b5a1f52b8caed700c7ab0d57cfb1"
+checksum = "d1cd460205fe05634d58b32d9bb752b1b4eaf32b2d29cbd4161ba35eb44a2f8c"
dependencies = [
"quote",
"rustc-hash",
@@ -643,9 +644,9 @@ dependencies = [
[[package]]
name = "bevy_math"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4797b608d61d315b99388479b40ad9200baa24f232a8b292f2cf14f5d8a7ab1"
+checksum = "267f2ec44aa948051768b1320c2dbff0871799e0a3b746f5fe5b6ee7258fbaf5"
dependencies = [
"glam",
"serde",
@@ -653,15 +654,15 @@ dependencies = [
[[package]]
name = "bevy_ptr"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9eeb9144fc8bd8676f76c7660790ffce696fc80aade804b1c4e3d36a92f9df65"
+checksum = "15702dff420fac72c2ab92428a8600e079ae89c5845401c4e39b843665a3d2d0"
[[package]]
name = "bevy_reflect"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8a0bd344cb46b48a89a36af8aad7718b69e5e05332e058169478792be4eed86"
+checksum = "3ac66cccbf1457c5cfc004a0e83569bd4ddc5d6310701f4af6aa81001fe2964a"
dependencies = [
"bevy_math",
"bevy_ptr",
@@ -680,9 +681,9 @@ dependencies = [
[[package]]
name = "bevy_reflect_derive"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22bdf9e985f7df44712ff93156b036c301aa6d1f211aec06ee6b06599396a4f0"
+checksum = "e5a2a1fa784e9a22560b9de350246a159cd59239eb61c7b66824031b3b28abb0"
dependencies = [
"bevy_macro_utils",
"bit-set",
@@ -694,9 +695,9 @@ dependencies = [
[[package]]
name = "bevy_tasks"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5b89169296c682d2d33f0dfc9f09abf942148adfa2cc5e0b2e17514acc0fc87"
+checksum = "9200e7b42d49c787d9a08675c425d8bd6393ba3beed2eac64be6027a44a01870"
dependencies = [
"async-channel",
"async-executor",
@@ -708,9 +709,9 @@ dependencies = [
[[package]]
name = "bevy_time"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91119de6907ff1cb58c637df235aa2e49332303abfa919a8c84cde942cfd69a4"
+checksum = "2ba50bf25c4dc40296b744f77de10d39c8981b710d8dce609da9de5e54ef164b"
dependencies = [
"bevy_app",
"bevy_ecs",
@@ -722,9 +723,9 @@ dependencies = [
[[package]]
name = "bevy_utils"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a596771e2cc8f4cde4e2dddb3c5569414ee342811bb5d317d50fe8965c1d0e31"
+checksum = "829eb8d0d06a0baeabc2e8bad74136ed3329b055aa1e11c5d9df09ebb9be3d85"
dependencies = [
"ahash",
"bevy_utils_proc_macros",
@@ -739,9 +740,9 @@ dependencies = [
[[package]]
name = "bevy_utils_proc_macros"
-version = "0.11.1"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e240bb064e9a1455e98e7dc8e701e1fd972c7fd32429ed1b4e7f36ac8974b7f"
+checksum = "0d104f29e231123c703e8b394e2341d2425c33c5a2e9ab8cc8d0a554bdb62a41"
dependencies = [
"proc-macro2",
"quote",
diff --git a/azalea-brigadier/tests/string_reader_test.rs b/azalea-brigadier/tests/string_reader_test.rs
index 5008eff8..de605e99 100755
--- a/azalea-brigadier/tests/string_reader_test.rs
+++ b/azalea-brigadier/tests/string_reader_test.rs
@@ -3,13 +3,13 @@ use azalea_brigadier::{exceptions::BuiltInExceptions, string_reader::StringReade
#[test]
fn can_read() {
let mut reader = StringReader::from("abc".to_string());
- assert_eq!(reader.can_read(), true);
+ assert!(reader.can_read());
reader.skip(); // 'a'
- assert_eq!(reader.can_read(), true);
+ assert!(reader.can_read());
reader.skip(); // 'b'
- assert_eq!(reader.can_read(), true);
+ assert!(reader.can_read());
reader.skip(); // 'c'
- assert_eq!(reader.can_read(), false);
+ assert!(!reader.can_read());
}
#[test]
@@ -27,11 +27,11 @@ fn get_remaining_length() {
#[test]
fn can_read_length() {
let reader = StringReader::from("abc".to_string());
- assert_eq!(reader.can_read_length(1), true);
- assert_eq!(reader.can_read_length(2), true);
- assert_eq!(reader.can_read_length(3), true);
- assert_eq!(reader.can_read_length(4), false);
- assert_eq!(reader.can_read_length(5), false);
+ assert!(reader.can_read_length(1));
+ assert!(reader.can_read_length(2));
+ assert!(reader.can_read_length(3));
+ assert!(!reader.can_read_length(4));
+ assert!(!reader.can_read_length(5));
}
#[test]
@@ -580,7 +580,7 @@ fn expect_none() {
#[test]
fn read_boolean_correct() {
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");
}
diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs
index 39b86b98..b44e8b4e 100644
--- a/azalea-client/src/client.rs
+++ b/azalea-client/src/client.rs
@@ -7,10 +7,10 @@ use crate::{
inventory::{InventoryComponent, InventoryPlugin},
local_player::{
death_event, handle_send_packet_event, update_in_loaded_chunk, GameProfileComponent,
- Hunger, LocalPlayer, PhysicsState, SendPacketEvent,
+ Hunger, LocalPlayer, SendPacketEvent,
},
mining::{self, MinePlugin},
- movement::{LastSentLookDirection, PlayerMovePlugin},
+ movement::{LastSentLookDirection, PhysicsState, PlayerMovePlugin},
packet_handling::{self, PacketHandlerPlugin, PacketReceiver},
player::retroactively_add_game_profile_component,
respawn::RespawnPlugin,
diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs
index 0321a396..4cb1eebf 100644
--- a/azalea-client/src/lib.rs
+++ b/azalea-client/src/lib.rs
@@ -22,7 +22,7 @@ pub mod interact;
pub mod inventory;
mod local_player;
pub mod mining;
-mod movement;
+pub mod movement;
pub mod packet_handling;
pub mod ping;
mod player;
@@ -36,6 +36,8 @@ pub use client::{
TickBroadcast,
};
pub use events::Event;
-pub use local_player::{GameProfileComponent, LocalPlayer};
-pub use movement::{SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection};
+pub use local_player::{GameProfileComponent, LocalPlayer, LocalPlayerInLoadedChunk};
+pub use movement::{
+ PhysicsState, SprintDirection, StartSprintEvent, StartWalkEvent, WalkDirection,
+};
pub use player::PlayerInfo;
diff --git a/azalea-client/src/local_player.rs b/azalea-client/src/local_player.rs
index a66b7ad5..2e0ccc75 100644
--- a/azalea-client/src/local_player.rs
+++ b/azalea-client/src/local_player.rs
@@ -20,7 +20,7 @@ use tokio::{sync::mpsc, task::JoinHandle};
use crate::{
events::{Event as AzaleaEvent, LocalPlayerEvents},
- ClientInformation, WalkDirection,
+ ClientInformation,
};
/// 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<()>,
}
-/// 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
/// you can use to get a player's name).
///
diff --git a/azalea-client/src/movement.rs b/azalea-client/src/movement.rs
index 0bda9b15..ad26f49c 100644
--- a/azalea-client/src/movement.rs
+++ b/azalea-client/src/movement.rs
@@ -1,7 +1,5 @@
use crate::client::Client;
-use crate::local_player::{
- update_in_loaded_chunk, LocalPlayer, LocalPlayerInLoadedChunk, PhysicsState,
-};
+use crate::local_player::{update_in_loaded_chunk, LocalPlayer, LocalPlayerInLoadedChunk};
use azalea_entity::{metadata::Sprinting, Attributes, Jumping};
use azalea_entity::{LastSentPosition, LookDirection, Physics, Position};
use azalea_physics::{force_jump_listener, PhysicsSet};
@@ -102,6 +100,23 @@ pub struct LastSentLookDirection {
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)]
pub(crate) fn send_position(
mut query: Query<
diff --git a/azalea-core/src/bitset.rs b/azalea-core/src/bitset.rs
index 381e86ea..b7a426c9 100755
--- a/azalea-core/src/bitset.rs
+++ b/azalea-core/src/bitset.rs
@@ -191,13 +191,13 @@ mod tests {
#[test]
fn test_bitset() {
let mut bitset = BitSet::new(64);
- assert_eq!(bitset.index(0), false);
- assert_eq!(bitset.index(1), false);
- assert_eq!(bitset.index(2), false);
+ assert!(!bitset.index(0));
+ assert!(!bitset.index(1));
+ assert!(!bitset.index(2));
bitset.set(1);
- assert_eq!(bitset.index(0), false);
- assert_eq!(bitset.index(1), true);
- assert_eq!(bitset.index(2), false);
+ assert!(!bitset.index(0));
+ assert!(bitset.index(1));
+ assert!(!bitset.index(2));
}
#[test]
@@ -211,11 +211,11 @@ mod tests {
bitset.clear(63, 65);
- assert_eq!(bitset.index(62), true);
- assert_eq!(bitset.index(63), false);
- assert_eq!(bitset.index(64), false);
- assert_eq!(bitset.index(65), true);
- assert_eq!(bitset.index(66), true);
+ assert!(bitset.index(62));
+ assert!(!bitset.index(63));
+ assert!(!bitset.index(64));
+ assert!(bitset.index(65));
+ assert!(bitset.index(66));
}
#[test]
@@ -229,10 +229,10 @@ mod tests {
bitset.clear(65, 67);
- assert_eq!(bitset.index(64), true);
- assert_eq!(bitset.index(65), false);
- assert_eq!(bitset.index(66), false);
- assert_eq!(bitset.index(67), true);
- assert_eq!(bitset.index(68), true);
+ assert!(bitset.index(64));
+ assert!(!bitset.index(65));
+ assert!(!bitset.index(66));
+ assert!(bitset.index(67));
+ assert!(bitset.index(68));
}
}
diff --git a/azalea-crypto/benches/my_benchmark.rs b/azalea-crypto/benches/my_benchmark.rs
index e8c4ecad..1781f471 100755
--- a/azalea-crypto/benches/my_benchmark.rs
+++ b/azalea-crypto/benches/my_benchmark.rs
@@ -5,8 +5,8 @@ fn bench(c: &mut Criterion) {
let (mut enc, dec) = create_cipher(b"0123456789abcdef");
let mut packet = [0u8; 65536];
- for i in 0..packet.len() {
- packet[i] = i as u8;
+ for (i, item) in packet.iter_mut().enumerate() {
+ *item = i as u8;
}
c.bench_function("Encrypt 64kb", |b| {
diff --git a/azalea-entity/src/dimensions.rs b/azalea-entity/src/dimensions.rs
index 1d013d10..ab5a1808 100755
--- a/azalea-entity/src/dimensions.rs
+++ b/azalea-entity/src/dimensions.rs
@@ -1,6 +1,6 @@
use azalea_core::{Vec3, AABB};
-#[derive(Debug, Default)]
+#[derive(Debug, Default, Clone)]
pub struct EntityDimensions {
pub width: f32,
pub height: f32,
diff --git a/azalea-entity/src/lib.rs b/azalea-entity/src/lib.rs
index c67817f3..db42a0ba 100644
--- a/azalea-entity/src/lib.rs
+++ b/azalea-entity/src/lib.rs
@@ -125,6 +125,11 @@ impl Debug for EntityUuid {
/// automatically.
#[derive(Component, Clone, Copy, Debug, Default, PartialEq, Deref, DerefMut)]
pub struct Position(Vec3);
+impl Position {
+ pub fn new(pos: Vec3) -> Self {
+ Self(pos)
+ }
+}
impl From<&Position> for Vec3 {
fn from(value: &Position) -> Self {
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
/// the space key being held in vanilla.)
-#[derive(Debug, Component, Clone, Deref, DerefMut)]
+#[derive(Debug, Component, Clone, Deref, DerefMut, Default)]
pub struct Jumping(bool);
/// 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
/// bounding box.
-#[derive(Debug, Component)]
+#[derive(Debug, Component, Clone)]
pub struct Physics {
pub delta: Vec3,
@@ -219,6 +224,26 @@ pub struct Physics {
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.
///
/// "Dead" means that the entity has 0 health.
@@ -297,22 +322,7 @@ impl EntityBundle {
world_name: InstanceName(world_name),
position: Position(pos),
last_sent_position: LastSentPosition(pos),
- physics: Physics {
- 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,
- },
+ physics: Physics::new(dimensions, &pos),
eye_height: EyeHeight(eye_height),
direction: LookDirection::default(),
diff --git a/azalea-entity/src/plugin/indexing.rs b/azalea-entity/src/plugin/indexing.rs
index 23f53c5f..3a349f5c 100644
--- a/azalea-entity/src/plugin/indexing.rs
+++ b/azalea-entity/src/plugin/indexing.rs
@@ -229,6 +229,7 @@ pub fn update_entity_chunk_positions(
}
/// Despawn entities that aren't being loaded by anything.
+#[allow(clippy::type_complexity)]
pub fn remove_despawned_entities_from_indexes(
mut commands: Commands,
mut entity_infos: ResMut<EntityUuidIndex>,
diff --git a/azalea-nbt/benches/compare.rs b/azalea-nbt/benches/compare.rs
index 1634b45b..863e0b9a 100755
--- a/azalea-nbt/benches/compare.rs
+++ b/azalea-nbt/benches/compare.rs
@@ -25,7 +25,7 @@ pub fn bench_read_file(filename: &str, c: &mut Criterion) {
group.bench_function("azalea_parse", |b| {
b.iter(|| {
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);
})
});
diff --git a/azalea-physics/src/lib.rs b/azalea-physics/src/lib.rs
index 6fef7ad1..f004c0fb 100644
--- a/azalea-physics/src/lib.rs
+++ b/azalea-physics/src/lib.rs
@@ -427,7 +427,7 @@ mod tests {
let block_state = partial_world.chunks.set_block_state(
&BlockPos { x: 0, y: 69, z: 0 },
azalea_registry::Block::Stone.into(),
- &mut world_lock.write().chunks,
+ &world_lock.write().chunks,
);
assert!(
block_state.is_some(),
@@ -490,7 +490,7 @@ mod tests {
waterlogged: false,
}
.into(),
- &mut world_lock.write().chunks,
+ &world_lock.write().chunks,
);
assert!(
block_state.is_some(),
diff --git a/azalea/Cargo.toml b/azalea/Cargo.toml
index 527088f8..3e7aaaa2 100644
--- a/azalea/Cargo.toml
+++ b/azalea/Cargo.toml
@@ -41,6 +41,7 @@ tokio = "^1.31.0"
uuid = "1.4.1"
bevy_log = "0.11.1"
azalea-entity = { version = "0.1.0", path = "../azalea-entity" }
+bevy_time = "0.11.2"
[features]
default = ["log"]
diff --git a/azalea/examples/echo.rs b/azalea/examples/echo.rs
index dbf56a31..01390982 100755
--- a/azalea/examples/echo.rs
+++ b/azalea/examples/echo.rs
@@ -18,16 +18,13 @@ async fn main() {
pub struct State {}
async fn handle(bot: Client, event: Event, _state: State) -> anyhow::Result<()> {
- match event {
- Event::Chat(m) => {
- if let (Some(sender), content) = m.split_sender_and_content() {
- if sender == bot.profile.name {
- return Ok(()); // ignore our own messages
- }
- bot.chat(&content);
- };
- }
- _ => {}
+ if let Event::Chat(m) = event {
+ if let (Some(sender), content) = m.split_sender_and_content() {
+ if sender == bot.profile.name {
+ return Ok(()); // ignore our own messages
+ }
+ bot.chat(&content);
+ };
}
Ok(())
diff --git a/azalea/examples/steal.rs b/azalea/examples/steal.rs
index 7a7ee4bb..9bbda945 100644
--- a/azalea/examples/steal.rs
+++ b/azalea/examples/steal.rs
@@ -24,52 +24,49 @@ struct State {
}
async fn handle(mut bot: Client, event: Event, state: State) -> anyhow::Result<()> {
- match event {
- Event::Chat(m) => {
- if m.username() == Some(bot.profile.name.clone()) {
- return Ok(());
- };
- if m.content() != "go" {
- return Ok(());
- }
- {
- state.checked_chests.lock().clear();
- }
+ if let Event::Chat(m) = event {
+ if m.username() == Some(bot.profile.name.clone()) {
+ return Ok(());
+ };
+ if m.content() != "go" {
+ return Ok(());
+ }
+ {
+ state.checked_chests.lock().clear();
+ }
- let chest_block = bot
- .world()
- .read()
- .find_block(bot.position(), &azalea::Block::Chest.into());
- // TODO: update this when find_blocks is implemented
- let Some(chest_block) = chest_block else {
- bot.chat("No chest found");
- return Ok(());
- };
- // bot.goto(BlockPosGoal::from(chest_block));
- let Some(chest) = bot.open_container(chest_block).await else {
- println!("Couldn't open chest");
- return Ok(());
- };
+ let chest_block = bot
+ .world()
+ .read()
+ .find_block(bot.position(), &azalea::Block::Chest.into());
+ // TODO: update this when find_blocks is implemented
+ let Some(chest_block) = chest_block else {
+ bot.chat("No chest found");
+ return Ok(());
+ };
+ // bot.goto(BlockPosGoal::from(chest_block));
+ let Some(chest) = bot.open_container(chest_block).await else {
+ println!("Couldn't open chest");
+ return Ok(());
+ };
- println!("Getting contents");
- for (index, slot) in chest
- .contents()
- .expect("we just opened the chest")
- .iter()
- .enumerate()
- {
- println!("Checking slot {index}: {slot:?}");
- if let ItemSlot::Present(item) = slot {
- if item.kind == azalea::Item::Diamond {
- println!("clicking slot ^");
- chest.click(QuickMoveClick::Left { slot: index as u16 });
- }
+ println!("Getting contents");
+ for (index, slot) in chest
+ .contents()
+ .expect("we just opened the chest")
+ .iter()
+ .enumerate()
+ {
+ println!("Checking slot {index}: {slot:?}");
+ if let ItemSlot::Present(item) = slot {
+ if item.kind == azalea::Item::Diamond {
+ println!("clicking slot ^");
+ chest.click(QuickMoveClick::Left { slot: index as u16 });
}
}
-
- println!("Done");
}
- _ => {}
+
+ println!("Done");
}
Ok(())
diff --git a/azalea/examples/testbot.rs b/azalea/examples/testbot.rs
index 3d566410..14800e9c 100644
--- a/azalea/examples/testbot.rs
+++ b/azalea/examples/testbot.rs
@@ -284,12 +284,11 @@ async fn handle(mut bot: Client, event: Event, _state: State) -> anyhow::Result<
_ => {}
}
}
- Event::Packet(packet) => match *packet {
- ClientboundGamePacket::Login(_) => {
+ Event::Packet(packet) => {
+ if let ClientboundGamePacket::Login(_) = *packet {
println!("login packet");
}
- _ => {}
- },
+ }
_ => {}
}
diff --git a/azalea/src/pathfinder/mod.rs b/azalea/src/pathfinder/mod.rs
index 58b59fd4..d59f0046 100644
--- a/azalea/src/pathfinder/mod.rs
+++ b/azalea/src/pathfinder/mod.rs
@@ -1,6 +1,7 @@
mod astar;
pub mod goals;
mod moves;
+pub mod simulation;
use crate::bot::{JumpEvent, LookAtEvent};
use crate::pathfinder::astar::a_star;
@@ -22,7 +23,7 @@ use azalea_entity::Local;
use azalea_entity::{Physics, Position};
use azalea_physics::PhysicsSet;
use azalea_world::{InstanceContainer, InstanceName};
-use bevy_app::{FixedUpdate, Update};
+use bevy_app::{FixedUpdate, PreUpdate, Update};
use bevy_ecs::prelude::Event;
use bevy_ecs::query::Changed;
use bevy_ecs::schedule::IntoSystemConfigs;
@@ -44,11 +45,11 @@ impl Plugin for PathfinderPlugin {
// (every 50 milliseconds).
tick_execute_path.before(PhysicsSet),
)
+ .add_systems(PreUpdate, add_default_pathfinder)
.add_systems(
Update,
(
goto_listener,
- add_default_pathfinder,
(handle_tasks, path_found_listener).chain(),
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)
+ );
+ }
+}
diff --git a/azalea/src/pathfinder/moves.rs b/azalea/src/pathfinder/moves.rs
index 04e2e725..0cc211ac 100644
--- a/azalea/src/pathfinder/moves.rs
+++ b/azalea/src/pathfinder/moves.rs
@@ -192,17 +192,17 @@ mod tests {
partial_world.chunks.set_block_state(
&BlockPos::new(0, 0, 0),
azalea_registry::Block::Stone.into(),
- &mut chunk_storage,
+ &chunk_storage,
);
partial_world.chunks.set_block_state(
&BlockPos::new(0, 1, 0),
BlockState::AIR,
- &mut chunk_storage,
+ &chunk_storage,
);
let world = chunk_storage.into();
- assert_eq!(is_block_passable(&BlockPos::new(0, 0, 0), &world), false);
- assert_eq!(is_block_passable(&BlockPos::new(0, 1, 0), &world), true);
+ assert!(!is_block_passable(&BlockPos::new(0, 0, 0), &world));
+ assert!(is_block_passable(&BlockPos::new(0, 1, 0), &world));
}
#[test]
@@ -217,17 +217,17 @@ mod tests {
partial_world.chunks.set_block_state(
&BlockPos::new(0, 0, 0),
azalea_registry::Block::Stone.into(),
- &mut chunk_storage,
+ &chunk_storage,
);
partial_world.chunks.set_block_state(
&BlockPos::new(0, 1, 0),
BlockState::AIR,
- &mut chunk_storage,
+ &chunk_storage,
);
let world = chunk_storage.into();
- assert_eq!(is_block_solid(&BlockPos::new(0, 0, 0), &world), true);
- assert_eq!(is_block_solid(&BlockPos::new(0, 1, 0), &world), false);
+ assert!(is_block_solid(&BlockPos::new(0, 0, 0), &world));
+ assert!(!is_block_solid(&BlockPos::new(0, 1, 0), &world));
}
#[test]
@@ -242,22 +242,22 @@ mod tests {
partial_world.chunks.set_block_state(
&BlockPos::new(0, 0, 0),
azalea_registry::Block::Stone.into(),
- &mut chunk_storage,
+ &chunk_storage,
);
partial_world.chunks.set_block_state(
&BlockPos::new(0, 1, 0),
BlockState::AIR,
- &mut chunk_storage,
+ &chunk_storage,
);
partial_world.chunks.set_block_state(
&BlockPos::new(0, 2, 0),
BlockState::AIR,
- &mut chunk_storage,
+ &chunk_storage,
);
partial_world.chunks.set_block_state(
&BlockPos::new(0, 3, 0),
BlockState::AIR,
- &mut chunk_storage,
+ &chunk_storage,
);
let world = chunk_storage.into();
diff --git a/azalea/src/pathfinder/simulation.rs b/azalea/src/pathfinder/simulation.rs
new file mode 100644
index 00000000..372a8a3b
--- /dev/null
+++ b/azalea/src/pathfinder/simulation.rs
@@ -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()
+ }
+}