This commit is contained in:
2026-06-21 22:04:10 -05:00
parent 475534f7c4
commit 87979ac610
7 changed files with 134 additions and 255 deletions
+23 -25
View File
@@ -1107,37 +1107,35 @@ fn register_write_api(engine: &mut Engine, queues: &QueueMap) {
},
);
// swap(pairs): apply a batch of one-way solid moves simultaneously. `pairs` is
// an array whose elements are four-int arrays `[src_x, src_y, dst_x, dst_y]`. A
// malformed entry is skipped with a logged error. Zero time cost.
// shift([[x, y], ...): Emits a shift action which moves the contents of each given cell in
// a loop (the last cell is moved to the first coord). Doesn't move things that aren't pushable,
// and won't move anything into a cell that's not vacant (or vacated by this shift).
let q = queues.clone();
engine.register_fn("swap", move |ctx: NativeCallContext, arr: Array| {
engine.register_fn("shift", move |ctx: NativeCallContext, arr: Array| {
let src = source_of(&ctx);
let mut pairs: Vec<(i32, i32, i32, i32)> = Vec::new();
for elem in &arr {
// Each entry must be an array of exactly four integers.
let coords: Option<Vec<i64>> = elem.read_lock::<Array>().and_then(|inner| {
if inner.len() == 4 {
inner.iter().map(|v| v.as_int().ok()).collect()
} else {
None
}
});
match coords {
Some(c) => pairs.push((c[0] as i32, c[1] as i32, c[2] as i32, c[3] as i32)),
None => emit(
&q,
src,
Action::Log(LogLine::error(
"swap: each entry must be [src_x, src_y, dst_x, dst_y]".to_string(),
)),
),
}
match read_coord_array(&arr) {
Ok(pairs) => emit(&q, src, Action::Shift(pairs)),
Err(_) => emit(&q, src, Action::Log(LogLine::error("shift: each entry must be [x, y]".to_string())))
}
emit(&q, src, Action::Swap(pairs));
});
}
/// Read a `Vec<(i32, i32)>` from a Rhai array, to receive a list of coordinates from a script.
/// Returns Err if the array isn't `[[x, y], ...]`
fn read_coord_array(arr: &Array) -> Result<Vec<(i32, i32)>, ()> {
let mut pairs: Vec<(i32, i32)> = Vec::new();
for elem in arr {
let coords: Option<Vec<i64>> = elem.read_lock::<Array>().and_then(|inner| {
inner.iter().map(|v| v.as_int().ok()).collect()
});
if let Some(coords) = coords && coords.len() == 2 {
pairs.push((coords[0] as i32, coords[1] as i32))
} else {
return Err(());
}
}
Ok(pairs)
}
// ── Queue API ─────────────────────────────────────────────────────────────────
fn register_queue_api(engine: &mut Engine) {