fix multiple includes per chat

previously, putting everything into a "changeset" first (where each item
says "replace line X with the following block") and applying the
changeset after collecting all changes would lead to wrong line numbers,
since inserting a block will move all lines down by some amount.

Gotta replace the include-line with the block right away before you move
on to following include lines.

This was so complex in the first place to please rust's borrow checker.
This commit is contained in:
yuni 2024-06-12 02:28:53 +02:00
parent f8913b8fa3
commit a3c87e1651

View file

@ -202,31 +202,37 @@ impl ChatDB {
sequence: &mut Value,
include_db: &HashMap<String, Vec<Value>>,
) {
let mut changes: Vec<(usize, String)> = Vec::new();
if let Some(vector) = sequence.as_sequence_mut() {
for (index, item) in vector.iter_mut().enumerate() {
let mut index = 0;
loop {
// this loop seems unnecessarily convoluted, but I had to write it
// this way to make rust's borrow checker happy.
let item_maybe = vector.get(index);
let item = if let Some(item) = item_maybe {
item.clone()
} else {
break;
};
match item {
Value::Mapping(map) => {
for (key, value) in map.iter_mut() {
Value::Mapping(mut map) => {
for (key, value) in map.clone().iter() {
if let (Some(key), Some(value)) = (key.as_str(), value.as_str()) {
let label = value.to_string();
if key == TOKEN_INCLUDE {
changes.push((index, value.to_string()));
vector.remove(index);
if let Some(chat) = include_db.get(&label) {
vector.splice(index..index, chat.iter().cloned());
}
}
} else if value.is_sequence() {
let value = map.get_mut(key).unwrap();
ChatDB::preprocess_includes_recursively(value, include_db);
}
}
}
_ => {}
}
}
for (index, label) in changes {
if index < vector.len() {
vector.remove(index);
if let Some(chat) = include_db.get(&label) {
vector.splice(index..index, chat.iter().cloned());
}
}
index += 1;
}
}
}
@ -946,6 +952,10 @@ pub fn update_chat_variables(
q_player: Query<&actor::Suit, With<actor::Player>>,
) {
if let Ok(suit) = q_player.get_single() {
vars.set_in_scope("$", "player_oxygen_seconds", (suit.oxygen / nature::OXY_S).to_string());
vars.set_in_scope(
"$",
"player_oxygen_seconds",
(suit.oxygen / nature::OXY_S).to_string(),
);
}
}