@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
157 lines (126 loc) • 3.09 kB
JavaScript
import List from "./List.js";
/**
* @template T
*/
export class ListForwarder {
/**
* Where the data ends up
* @type {List<T>}
* @private
*/
#destination = new List();
/**
* Where to take data from
* @type {List<T>[]}
* @private
*/
#sources = [];
/**
*
* @type {boolean}
* @private
*/
#is_linked = false;
/**
*
* @param {List<T>} v
*/
set destination(v) {
if (this.#is_linked) {
// already linked
throw new Error('Invalid state: linked');
}
this.#destination = v;
}
/**
*
* @return {List<T>}
*/
get destination() {
return this.#destination;
}
/**
*
* @param {List<T>} source
* @return {boolean}
*/
add(source) {
this.#sources.push(source);
if (this.#is_linked) {
this.#link_one(source);
}
return true;
}
/**
*
* @param {List<T>} source
* @private
*/
#link_one(source) {
source.on.added.add(this.#destination.add, this.#destination);
source.on.removed.add(this.#destination.removeOneOf, this.#destination);
// move data to destination
source.forEach(this.#destination.add, this.#destination);
}
/**
*
* @param {List<T>} source
* @private
*/
#unlink_one(source) {
source.on.added.remove(this.#destination.add, this.#destination);
source.on.removed.remove(this.#destination.removeOneOf, this.#destination);
// remove all data from destination
source.forEach(this.#destination.removeOneOf, this.#destination);
}
/**
*
* @param {List<T>} source
* @return {boolean}
*/
remove(source) {
const i = this.#sources.indexOf(source);
if (i === -1) {
return false;
}
if (this.#is_linked) {
this.#unlink_one(source);
}
this.#sources.splice(i, 1);
return true;
}
link() {
if (this.#is_linked) {
return;
}
if (this.#destination === null) {
throw new Error('Illegal state: destination not set');
}
this.#is_linked = true;
const sources = this.#sources;
const n = sources.length;
for (let i = 0; i < n; i++) {
const source = sources[i];
this.#link_one(source);
}
}
unlink() {
if (!this.#is_linked) {
return;
}
this.#is_linked = false;
const sources = this.#sources;
const n = sources.length;
for (let i = 0; i < n; i++) {
const source = sources[i];
this.#unlink_one(source);
}
}
/**
*
* @return {boolean}
*/
isLinked() {
return this.#is_linked;
}
}