Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,12 @@ license = "MIT"
[dependencies]
azalea = { git = "https://github.com/azalea-rs/azalea", rev = "1accbac" }
tokio = { version = "1.48", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
anyhow = "1.0"
thiserror = "2.0"
clap = { version = "4.5", features = ["derive"] }
colored = "3.0"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
parking_lot = "0.12"
futures = "0.3"
flint-core = { git = "https://github.com/FlintTestMC/flint-core", rev = "b04ad23" }
clap_complete = "4.5.65"
2 changes: 1 addition & 1 deletion src/executor/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub fn make_block(block_str: &str) -> Block {
if let Some((k, v)) = pair.split_once('=') {
properties.insert(
k.trim().to_string(),
serde_json::Value::String(v.trim().to_string()),
serde_json::Value::String(v.strip_prefix('_').unwrap_or(v).trim().to_string()),
);
}
}
Expand Down
86 changes: 66 additions & 20 deletions src/executor/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn parse_command(message: &str) -> Option<(String, Vec<String>)> {
return None;
};

let parts: Vec<&str> = command_str.trim().split_whitespace().collect();
let parts: Vec<&str> = command_str.split_whitespace().collect();
if parts.is_empty() {
return None;
}
Expand Down Expand Up @@ -64,6 +64,14 @@ impl TestExecutor {
self.bot
.send_command("say Recorder actions: !assert <x> <y> <z>, !assert_changes")
.await?;
self.bot
.send_command(
"say Recorder actions: !pos1 <x> <y> <z>, !pos - Allow to use assert for a 3d area",
)
.await?;
self.bot
.send_command("say Recorder actions: !sprint <tick> - ticks this ticks and asserts after each tick")
.await?;
self.bot
.send_command("say !stop - Exit interactive mode")
.await?;
Expand Down Expand Up @@ -361,6 +369,16 @@ impl TestExecutor {

Ok(())
}
pub(super) fn handle_pos1(&mut self, args: &[String]) {
if args.is_empty() {
self.pos1 = None;
return;
}
let x = args[0].parse::<i32>().unwrap_or(0);
let y = args[1].parse::<i32>().unwrap_or(0);
let z = args[2].parse::<i32>().unwrap_or(0);
self.pos1 = Some([x, y, z]);
}

pub(super) async fn handle_record_assert(&mut self, args: &[String]) -> Result<()> {
let _recorder = match self.recorder.as_mut() {
Expand All @@ -378,28 +396,47 @@ impl TestExecutor {
let y = args[1].parse::<i32>().unwrap_or(0);
let z = args[2].parse::<i32>().unwrap_or(0);
let block_pos = [x, y, z];

// Get block at position
if let Some(block_str) = self.bot.get_block(block_pos).await? {
let block_id = block::extract_block_id(&block_str);
let recorder = self.recorder.as_mut().unwrap();
recorder.add_assertion(block_pos, &block_id);

self.bot
.send_command(&format!(
"say Added assert at [{}, {}, {}] = {}",
block_pos[0], block_pos[1], block_pos[2], block_id
))
.await?;
let mut blocks = Vec::new();
if let Some(pos1) = self.pos1 {
let min_x = block_pos[0].min(pos1[0]);
let max_x = block_pos[0].max(pos1[0]);
let min_y = block_pos[1].min(pos1[1]);
let max_y = block_pos[1].max(pos1[1]);
let min_z = block_pos[2].min(pos1[2]);
let max_z = block_pos[2].max(pos1[2]);

for x in min_x..=max_x {
for y in min_y..=max_y {
for z in min_z..=max_z {
blocks.push([x, y, z]);
}
}
}
} else {
self.bot
.send_command(&format!(
"say No block found at [{}, {}, {}]",
block_pos[0], block_pos[1], block_pos[2]
))
.await?;
blocks.push(block_pos)
}
// Get block at position
for pos in blocks {
if let Some(block_str) = self.bot.get_block(pos).await? {
let block_id = block::extract_block_id(&block_str);
let recorder = self.recorder.as_mut().unwrap();
recorder.add_assertion(pos, &block_id);

self.bot
.send_command(&format!(
"say Added assert at [{}, {}, {}] = {}",
pos[0], pos[1], pos[2], block_id
))
.await?;
} else {
self.bot
.send_command(&format!(
"say No block found at [{}, {}, {}]",
pos[0], pos[1], pos[2]
))
.await?;
}
}
Ok(())
}

Expand Down Expand Up @@ -552,4 +589,13 @@ impl TestExecutor {
}
Ok(())
}

pub(super) async fn handle_record_sprint(&mut self, ticks: u32) -> Result<()> {
for _ in 0..ticks {
self.handle_record_tick().await?;
self.handle_record_assert(&self.last_assert_pos.clone())
.await?;
}
Ok(())
}
}
34 changes: 33 additions & 1 deletion src/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use flint_core::results::{ActionOutcome, AssertFailure, TestResult};
use flint_core::test_spec::{TestSpec, TimelineEntry};
use flint_core::timeline::TimelineAggregate;
use std::io::Write;

pub use tick::{COMMAND_DELAY_MS, MIN_RETRY_DELAY_MS};

// Timing constants
Expand All @@ -39,6 +38,8 @@ pub struct TestExecutor {
verbose: bool,
quiet: bool,
fail_fast: bool,
pos1: Option<[i32; 3]>,
last_assert_pos: Vec<String>,
}

impl Default for TestExecutor {
Expand All @@ -50,6 +51,8 @@ impl Default for TestExecutor {
verbose: false,
quiet: false,
fail_fast: false,
pos1: None,
last_assert_pos: vec![],
}
}
}
Expand Down Expand Up @@ -217,15 +220,44 @@ impl TestExecutor {
self.handle_record_tick().await?;
}

"!pos1" | "!pos" => {
if (!args.is_empty() && args.len() < 3) || args.len() > 3 {
self.bot
.send_command("say Usage: !assert <x> <y> <z>")
.await?;
continue;
}
self.handle_pos1(&args);
}

"!assert" => {
if args.len() < 3 {
self.bot
.send_command("say Usage: !assert <x> <y> <z>")
.await?;
continue;
}
self.last_assert_pos = args.clone();
self.handle_record_assert(&args).await?;
}
"!sprint" => {
if args.len() != 1 {
self.bot.send_command("say Usage: !sprint <ticks>").await?;
continue;
}
let ticks = args[0].parse::<u32>().unwrap_or(1);
if ticks == 0 {
self.bot
.send_command("say Sprint ticks must be greater than 0")
.await?;
continue;
}
if self.last_assert_pos.is_empty() {
self.bot.send_command("say Please assert a position first, which should be used for each string (can be also a 3d area)").await?;
continue;
}
self.handle_record_sprint(ticks).await?;
}

"!save" => {
if self.handle_record_save().await? {
Expand Down
2 changes: 1 addition & 1 deletion src/executor/recorder/bounding_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl BoundingBox {

/// Expand the bounding box to include a position
pub fn expand(&mut self, pos: [i32; 3]) {
for i in 0..3 {
for (i, _) in pos.iter().enumerate() {
self.min[i] = self.min[i].min(pos[i]);
self.max[i] = self.max[i].max(pos[i]);
}
Expand Down