1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
// A tool to manage land claims (i.e. a certain Space is delegated to only call a specific `call()` if a tileUpdate occurs differing from that Space)
const ms = require('../utils/measurespace');
const ri = require('../utils/rectintersect');
const vec = require('../utils/vec');
const comb = require('../utils/comb');
module.exports = function(catchall){
// catchall is called if tileUpdate occurs w/ no relevant claim on a part.
let claims = {};
let claimId = 0;
this.claim = function(space, call, excl=true){
// `space` is Space obj; `call` is callback function
// `exclusive` sets whether this callback will prevent other (incl. catchall) functions from seeing the space. Cannot be used with an exclusive callback, and does not guarantee order.
// If exclusive claim intersects another claim, behavior undefined.
claimId++;
claims[claimId] = {'space':space, 'call':call, 'excl':excl, 'area':ms(space)}
return claimId;
}
this.unclaim = function(id){
delete claims[id];
}
this.handle = function(send, tilespaces, locs){
// Because usually tilespaces is small, the inefficiency of an O(nk) rect match is acceptable
for (let id in claims){
claim = claims[id];
diffspace = {};
rellocs = [];
for (let loc of locs){
let tile = tilespaces[loc];
if (ri(claim.area, [vec.tileToChar(loc), vec.tileToChar(vec.add(loc, [1,1]))])){
let diff = claim.space.copy();
diff.comb(tile, comb.unmask);
rellocs.push(loc);
diffspace[loc] = diff;
if (claim.excl){
let newtile = claim.space.copy();
newtile.comb(tile, comb.mask);
tilespaces[loc] = newtile;
}
}
}
claim.call(send, diffspace, rellocs, id, claim.space, claim.area); // claim.space should not be modified by the function. it is only present to make functions easier to write
}
catchall(send, tilespaces, locs);
}
}
|