aboutsummaryrefslogtreecommitdiff
path: root/tools/claim.js
blob: b43417bfb7acf584fd32f6fd5ebb5676a76b007a (plain)
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 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
    }
    this.emit('fallback', send, tilespaces, locs);
  }
}