use crate::options::Options;
use crate::context::Context;
use crate::symbols::{ensure_symbol_index, recursive_symbol_indexes_ensured};
use crate::pending::{Pending, Created, Updated, Removed, UpdateOptions, Mask, ExtendedOptions, EnumDefaultSymbols};
fn updater(context: Context, options: ExtendedOptions) {
let options = if let Options::ExtendedOptions(opt) = options {
opt
} else {
Options::new(options)
};
let Options {
responder,
enumDefaultSymbols,
compressStringsAsInts,
updateOptions,
} = options;
let OptionsUpdate {
batched,
batchSize,
mask,
type,
validKeys,
} = updateOptions;
if !context.pending {
return;
}
let mut batch: Vec<Vec<String | i32>> = Vec::new();
let mut batchBlock: Vec<any> = Vec::new();
let ContextPending {
created = {},
removed = {},
symbols = [],
updated = {},
} = context.pending;
fn mergeBatch(action: String | i32) {
if batched && !batchBlock.is_empty() {
batch.push(vec![action].append(&mut batchBlock));
batchBlock.clear();
}
}
fn queueMessage(action: String | i32, payload: any) {
if batched {
batchBlock.extend(payload);
if batchBlock.len() >= batchSize {
mergeBatch(action);
}
} else {
if compressStringsAsInts {
action = ensureSymbolIndex(action, context, options);
}
responder([action, payload], type);
}
}
fn ensureSymbol(symbol: String | i32) -> String | i32 {
if compressStringsAsInts {
symbol = ensureSymbolIndex(symbol, context, options);
}
symbol
}
if !mask || !mask.entities {
for key in created.entities.unwrap_or_default() {
let nkey = ensureSymbol(key);
queueMessage(enumDefaultSymbols.createEntity, nkey);
}
mergeBatch(enumDefaultSymbols.createEntity);
created.entities = Vec::new();
}
if !mask || !mask.actors {
for id in created.actors.unwrap_or_default() {
let nid = ensureSymbol(id);
queueMessage(enumDefaultSymbols.spawnActor, nid);
}
mergeBatch(enumDefaultSymbols.spawnActor);
created.actors = Vec::new();
}
if !mask || !mask.entities {
for key in removed.entities.unwrap_or_default() {
let nkey = ensureSymbol(key);
queueMessage(enumDefaultSymbols.removeEntity, nkey);
}
mergeBatch(enumDefaultSymbols.removeEntity);
removed.entities = Vec::new();
}
if !mask || !mask.actors {
for id in removed.actors.unwrap_or_default() {
let nid = ensureSymbol(id);
queueMessage(enumDefaultSymbols.removeActor, nid);
}
mergeBatch(enumDefaultSymbols.removeActor);
removed.actors = Vec::new();
}
if !mask || !mask.components {
for (id, components) in removed.components.unwrap_or_default() {
let nid = ensureSymbol(id);
for (key, _) in components {
if validKeys && !validKeys[key] {
break;
}
let nkey = ensureSymbol(key);
let payload = [nid, nkey];
queueMessage(enumDefaultSymbols.removeComponent, payload);
}
}
mergeBatch(enumDefaultSymbols.removeComponent);
removed.components = HashMap::new();
}
if !mask || !mask.components {
let components = context.components;
for (id, _) in created.components.unwrap_or_default() {
if !components || !components[id] {
break;
}
for (key, value) in components[id] {
if validKeys && !validKeys[key] {
break;
}
let nid = ensureSymbol(id);
let nkey = ensureSymbol(key);
let payload = [nid, nkey, value];
queueMessage(enumDefaultSymbols.upsertComponent, payload);
}
}
mergeBatch(enumDefaultSymbols.upsertComponent);
created.components = HashMap::new();
}
if !mask || !mask.components {
let components = context.components;
for (id, updatedComponents) in updated.components.unwrap_or_default() {
if !components || !components[id] {
break;
}
for (key, _) in updatedComponents[id] {
if validKeys && !validKeys[key] {
break;
}
let value = components[id][key];
if compressStringsAsInts {
value = recursiveSymbolIndexesEnsured(key, value, context, options);
}
let nid = ensureSymbol(id);
let nkey = ensureSymbol(key);
let payload = [nid, nkey, value];
queueMessage(enumDefaultSymbols.upsertComponent, payload);
}
}
mergeBatch(enumDefaultSymbols.upsertComponent);
updated.components = HashMap::new();
}
if !mask || !mask.inputs {
for (id, createdInputs) in created.inputs.unwrap_or_default() {
for index in createdInputs.unwrap_or_default() {
let payload = createdInputs[index];
let input = payload;
queueMessage(enumDefaultSymbols.actorInput, input);
}
}
mergeBatch(enumDefaultSymbols.actorInput);
created.inputs = HashMap::new();
}
if !mask || !mask.symbols {
for symbolOp in symbols {
if batched {
batchBlock.push(symbolOp);
} else {
let message = [enumDefaultSymbols.mergeSymbol, symbolOp];
responder(message, type);
}
if batchBlock.len() >= batchSize && !batchBlock.is_empty() {
batch.insert(0, [enumDefaultSymbols.mergeSymbol].append(&mut batchBlock));
batchBlock.clear();
}
}
if batched && !batchBlock.is_empty() {
batch.insert(0, [enumDefaultSymbols.mergeSymbol].append(&mut batchBlock));
batchBlock.clear();
}
context.pending.symbols = Vec::new();
}
if batched && !batch.is_empty() {
for batchSlice in batch {
if let Some(batchSlice) = batchSlice {
responder([enumDefaultSymbols.batch, batchSlice]);
}
}
}
}