aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/tests
diff options
context:
space:
mode:
authormat <git@matdoes.dev>2025-06-11 22:22:26 +0000
committermat <git@matdoes.dev>2025-06-11 22:22:26 +0000
commit1b348ceeffc61e49b19f2982e7a9de479c1678de (patch)
treebead28ce1a076a3af5ca5df2c326c9e94b63dd92 /azalea-client/tests
parent067ec06f26ecaf7a319eb3ce61307b9730176313 (diff)
downloadazalea-drasl-1b348ceeffc61e49b19f2982e7a9de479c1678de.tar.xz
implement reverting block state predictions on ack
Diffstat (limited to 'azalea-client/tests')
-rw-r--r--azalea-client/tests/mine_block_rollback.rs49
-rw-r--r--azalea-client/tests/mine_block_without_rollback.rs51
2 files changed, 100 insertions, 0 deletions
diff --git a/azalea-client/tests/mine_block_rollback.rs b/azalea-client/tests/mine_block_rollback.rs
new file mode 100644
index 00000000..e9b46d13
--- /dev/null
+++ b/azalea-client/tests/mine_block_rollback.rs
@@ -0,0 +1,49 @@
+use azalea_client::{mining::StartMiningBlockEvent, test_utils::prelude::*};
+use azalea_core::{
+ position::{BlockPos, ChunkPos},
+ resource_location::ResourceLocation,
+};
+use azalea_protocol::packets::{
+ ConnectionProtocol,
+ game::{ClientboundBlockChangedAck, ClientboundBlockUpdate},
+};
+use azalea_registry::{Block, DataRegistry, DimensionType};
+
+#[test]
+fn test_mine_block_rollback() {
+ init_tracing();
+
+ let mut simulation = Simulation::new(ConnectionProtocol::Game);
+ simulation.receive_packet(make_basic_login_packet(
+ DimensionType::new_raw(0),
+ ResourceLocation::new("azalea:overworld"),
+ ));
+
+ simulation.receive_packet(make_basic_empty_chunk(ChunkPos::new(0, 0), (384 + 64) / 16));
+ simulation.tick();
+
+ let pos = BlockPos::new(1, 2, 3);
+ simulation.receive_packet(ClientboundBlockUpdate {
+ pos,
+ // tnt is used for this test because it's insta-mineable so we don't have to waste ticks
+ // waiting
+ block_state: Block::Tnt.into(),
+ });
+ simulation.tick();
+ assert_eq!(simulation.get_block_state(pos), Some(Block::Tnt.into()));
+ println!("set serverside tnt");
+
+ simulation.send_event(StartMiningBlockEvent {
+ entity: simulation.entity,
+ position: pos,
+ });
+ simulation.tick();
+ assert_eq!(simulation.get_block_state(pos), Some(Block::Air.into()));
+ println!("set clientside air");
+
+ // server didn't send the new block, so the change should be rolled back
+ simulation.receive_packet(ClientboundBlockChangedAck { seq: 1 });
+ simulation.tick();
+ assert_eq!(simulation.get_block_state(pos), Some(Block::Tnt.into()));
+ println!("reset serverside tnt");
+}
diff --git a/azalea-client/tests/mine_block_without_rollback.rs b/azalea-client/tests/mine_block_without_rollback.rs
new file mode 100644
index 00000000..02fb1a77
--- /dev/null
+++ b/azalea-client/tests/mine_block_without_rollback.rs
@@ -0,0 +1,51 @@
+use azalea_client::{mining::StartMiningBlockEvent, test_utils::prelude::*};
+use azalea_core::{
+ position::{BlockPos, ChunkPos},
+ resource_location::ResourceLocation,
+};
+use azalea_protocol::packets::{
+ ConnectionProtocol,
+ game::{ClientboundBlockChangedAck, ClientboundBlockUpdate},
+};
+use azalea_registry::{Block, DataRegistry, DimensionType};
+
+#[test]
+fn test_mine_block_without_rollback() {
+ init_tracing();
+
+ let mut simulation = Simulation::new(ConnectionProtocol::Game);
+ simulation.receive_packet(make_basic_login_packet(
+ DimensionType::new_raw(0),
+ ResourceLocation::new("azalea:overworld"),
+ ));
+
+ simulation.receive_packet(make_basic_empty_chunk(ChunkPos::new(0, 0), (384 + 64) / 16));
+ simulation.tick();
+
+ let pos = BlockPos::new(1, 2, 3);
+ simulation.receive_packet(ClientboundBlockUpdate {
+ pos,
+ // tnt is used for this test because it's insta-mineable so we don't have to waste ticks
+ // waiting
+ block_state: Block::Tnt.into(),
+ });
+ simulation.tick();
+ assert_eq!(simulation.get_block_state(pos), Some(Block::Tnt.into()));
+
+ simulation.send_event(StartMiningBlockEvent {
+ entity: simulation.entity,
+ position: pos,
+ });
+ simulation.tick();
+ assert_eq!(simulation.get_block_state(pos), Some(Block::Air.into()));
+
+ // server acknowledged our change by sending a BlockUpdate + BlockChangedAck, so
+ // no rollback
+ simulation.receive_packet(ClientboundBlockUpdate {
+ pos,
+ block_state: Block::Air.into(),
+ });
+ simulation.receive_packet(ClientboundBlockChangedAck { seq: 1 });
+ simulation.tick();
+ assert_eq!(simulation.get_block_state(pos), Some(Block::Air.into()));
+}