UNPKG

@hastearcade/snowglobe

Version:

A TypeScript port of CrystalOrb, a high-level Rust game networking library

74 lines 2.82 kB
import * as Timestamp from './timestamp.js'; export class CommandBuffer { map; _timestamp; constructor(map = new Map(), _timestamp = Timestamp.make()) { this.map = map; this._timestamp = _timestamp; // The original crystalorb implementation used a more effecient datatype // to insert commands in reverse timestamp order. // TODO investigate whether map is too slow here } timestamp() { return this._timestamp; } filterStaleTimestamps(timestamp, before) { if (timestamp != null) { this.map.forEach((value, key) => { if (Timestamp.cmp(key, timestamp) === (before ? -1 : 1)) { this.map.delete(key); } }); } } updateTimestamp(timestamp) { this._timestamp = timestamp; const acceptableRange = Timestamp.comparableRangeWithMidpoint(this._timestamp); this.filterStaleTimestamps(acceptableRange.min, true); this.filterStaleTimestamps(acceptableRange.max, false); } drainAll() { const sortedCommands = [...this.map.entries()].sort((a, b) => Timestamp.cmp(a[0], b[0])); this.map.clear(); return sortedCommands.map(tc => tc[1]).flat(); } drainUpTo(timestamp) { const sortedCommands = [...this.map.entries()].sort((a, b) => Timestamp.cmp(a[0], b[0])); const filteredCommands = sortedCommands.filter(tc => Timestamp.cmp(tc[0], timestamp) <= 0); for (const [timestamp] of filteredCommands) { this.map.delete(timestamp); } return filteredCommands.map(tc => tc[1]).flat(); } insert(timestampedCommand) { const incomingTimestamp = Timestamp.get(timestampedCommand); if (Timestamp.acceptableTimestampRange(this._timestamp, incomingTimestamp)) { const commandsExist = this.map.get(incomingTimestamp); if (commandsExist == null) { this.map.set(incomingTimestamp, [timestampedCommand]); } else { this.map.set(incomingTimestamp, [...commandsExist, timestampedCommand]); } } else { console.warn("The command's timestamp is outside the acceptable range and will be ignored"); } } commandsAt(timestamp) { return this.map.get(timestamp); } length() { return this.map.size; } [Symbol.iterator]() { return this.map.entries(); } clone() { return new CommandBuffer(new Map(Array.from(this.map.entries()).map(([timestamp, commands]) => [ timestamp, commands.map(command => Timestamp.set(command.clone(), timestamp)) ])), Timestamp.make(this._timestamp)); } } //# sourceMappingURL=command.js.map