Selector.parse constructor

Selector.parse(
  1. String selector
)

Parse a Selector, for example:

Selector s = Selector.parse('@a[nbt={a:1b},level=1..3,gamemode=survival,sort=nearest,x=10,dx=10,scores={score=..10,score2=99..}]');

Implementation

Selector.parse(String selector) {
  var p = Parsable(selector);
  if (p.actual() != '@') {
    throw p.error('Selector has to start with a \'@\'-symbol');
  }
  p.skip();
  var ranges = <String, double>{};
  if (p.actual() != 'e' &&
      p.actual() != 'a' &&
      p.actual() != 's' &&
      p.actual() != 'p' &&
      p.actual() != 'r') {
    throw p.error(
        'The second letter of a selector has to be "a", "e", "p", "r" or "s"');
  }
  this.selector = p.actual();
  if (!p.ended) p.skip();
  if (p.actual() == '[') {
    p.skip();
    var foundComma = true;
    while (p.actual() != ']') {
      if (!foundComma) throw p.error('Expecting \',\' or \']\'');
      if (!RegExp(r'[a-z]').hasMatch(p.actual())) {
        throw p.error('Needing letter a-z or \']\'');
      }
      var key = '';
      while (RegExp(r'[a-z]').hasMatch(p.actual())) {
        key += p.next();
      }
      if (p.next() != '=') throw p.error('Expecting \'=\'');
      switch (key) {
        case 'scores':
          if (p.actual() != '{') {
            throw p.error('Expecting \'{\'');
          }
          var comma = true;
          p.skip();
          while (p.actual() != '}') {
            if (!comma) throw p.error('Expecting \',\' or \'}\'');
            var score = _parseString(p);
            if (p.next() != '=') throw p.error('Expecting \'=\'');
            var r = _parseRange(p);
            scores ??= [];
            scores!.add(Score.fromSelected(score).matchesRange(r));
            if (p.actual() == ',') {
              comma = true;
              p.skip();
            }
          }
          p.skip();
          break;
        case 'gamemode':
          gamemode = _parseKeyword<Gamemode>(p, {
            'survival': Gamemode.survival,
            'creative': Gamemode.creative,
            'adventure': Gamemode.adventure,
            'spectator': Gamemode.spectator
          });
          break;
        case 'sort':
          sorting = _parseKeyword(p, {
            'nearest': Sort.nearest,
            'furthest': Sort.furthest,
            'random': Sort.random,
            'arbitrary': Sort.arbitrary
          });
          break;
        case 'x':
          ranges[key] = _parseDouble(p);
          break;
        case 'y':
          ranges[key] = _parseDouble(p);
          break;
        case 'z':
          ranges[key] = _parseDouble(p);
          break;
        case 'dx':
          ranges[key] = _parseDouble(p);
          break;
        case 'dy':
          ranges[key] = _parseDouble(p);
          break;
        case 'dz':
          ranges[key] = _parseDouble(p);
          break;
        case 'nbt':
          if (nbt == null) {
            nbt = gson.decoder.decode(p) as Map<String, dynamic>;
          } else {
            nbt!.addAll(gson.decoder.decode(p) as Map<String, dynamic>);
          }
          break;
        case 'tag':
          if (tags == null) {
            tags = [_parseString(p)];
          } else {
            tags!.add(_parseString(p));
          }
          break;
        case 'name':
          name = gson.decoder.decodeString(p);
          break;
        case 'team':
          team = Team(_parseString(p));
          break;
        case 'predicate':
          predicate = _parseString(p);
          break;
        case 'type':
          type = EntityType(_parseString(p));
          break;
        case 'limit':
          limit = _parseInt(p);
          break;
        case 'level':
          level = _parseRange(p);
          break;
        case 'x_rotation':
          verticalRotation = _parseRange(p);
          break;
        case 'y_rotation':
          horizontalRotation = _parseRange(p);
          break;
        case 'distance':
          distance = _parseRange(p);
          break;
        default:
          p.goBack(2);
          throw p.error('Unknown key \'$key\'', from: key.length - 1);
      }
      if (p.actual() == ',') {
        foundComma = true;
        p.skip();
      }
    }
  }
  if (ranges.isNotEmpty) {
    area = Area.fromRanges(ranges: ranges);
  }
}