Gridarta Editor
DaimoninAITokenMarker.java
Go to the documentation of this file.
1 /*
2  * Gridarta MMORPG map editor for Crossfire, Daimonin and similar games.
3  * Copyright (C) 2000-2015 The Gridarta Developers.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 package net.sf.gridarta.textedit.textarea.tokenmarker;
21 
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.Map;
27 import java.util.regex.Pattern;
28 import javax.swing.text.Segment;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33 
38 public class DaimoninAITokenMarker extends TokenMarker {
39 
44  private static final Map<String, Spec> FIXED_SPECS = new HashMap<>();
45 
50  private static final Map<Pattern, Spec> REGEX_SPECS = new HashMap<>();
51 
52  static {
53  FIXED_SPECS.put("actions:", new Spec(Token.LABEL));
54  FIXED_SPECS.put("moves:", new Spec(Token.LABEL));
55  FIXED_SPECS.put("processes:", new Spec(Token.LABEL));
56  FIXED_SPECS.put("bow_attack_enemy", new Spec(Token.KEYWORD1));
57  FIXED_SPECS.put("choose_enemy", new Spec(Token.KEYWORD1, new Parameter("antilure_distance", Token.KEYWORD2, ParameterType.INTEGER)));
58  FIXED_SPECS.put("dont_stand_still", new Spec(Token.KEYWORD1, new Parameter("max_idle_time", Token.KEYWORD2, ParameterType.INTEGER)));
60  FIXED_SPECS.put("groups", new Spec(Token.KEYWORD1, new Parameter("name", Token.KEYWORD2, ParameterType.STRING)));
61  FIXED_SPECS.put("heal_friend", new Spec(Token.KEYWORD1, new Parameter("healing_min_friendship", Token.KEYWORD2, ParameterType.INTEGER)));
62  FIXED_SPECS.put("look_for_other_mobs", new Spec(Token.KEYWORD1));
63  REGEX_SPECS.put(Pattern.compile("lua:.*"), new Spec(Token.KEYWORD1));
64  FIXED_SPECS.put("melee_attack_enemy", new Spec(Token.KEYWORD1));
65  FIXED_SPECS.put("move_randomly", new Spec(Token.KEYWORD1, new Parameter("xlimit", Token.KEYWORD2, ParameterType.INTEGER), new Parameter("ylimit", Token.KEYWORD2, ParameterType.INTEGER)));
66  FIXED_SPECS.put("move_towards_enemy", new Spec(Token.KEYWORD1));
67  FIXED_SPECS.put("move_towards_enemy_last_known_pos", new Spec(Token.KEYWORD1));
68  FIXED_SPECS.put("move_towards_home", new Spec(Token.KEYWORD1));
69  FIXED_SPECS.put("move_towards_waypoint", new Spec(Token.KEYWORD1));
70  FIXED_SPECS.put("run_away_from_enemy", new Spec(Token.KEYWORD1, new Parameter("hp_threshold", Token.KEYWORD2, ParameterType.INTEGER)));
71  FIXED_SPECS.put("search_for_lost_enemy", new Spec(Token.KEYWORD1));
72  FIXED_SPECS.put("sleep", new Spec(Token.KEYWORD1));
73  FIXED_SPECS.put("spell_attack_enemy", new Spec(Token.KEYWORD1));
74  FIXED_SPECS.put("stand_still", new Spec(Token.KEYWORD1));
75  }
76 
77  @Override
78  public byte markTokensImpl(final byte token, @NotNull final Segment line) {
79  final char[] array = line.array;
80  int offset = line.offset;
81  final int end = line.count + offset;
82  if (offset >= end) {
83  // empty line ==> mark nothing
84  } else if (array[offset] == '#') {
85  // comment line
86  addToken(line.count, Token.COMMENT1);
87  } else if (array[offset] == ' ') {
88  // syntax error
89  addToken(line.count, Token.INVALID);
90  } else {
91  // normal line
92 
93  // 1. parse line into segments
94 
95  // Collects parsed segments: command, space, parameter, space,
96  // parameter, space, ...
97  final Collection<Integer> segments = new ArrayList<>();
98 
99  while (offset < end) {
100  final int commandStart = offset;
101  while (offset < end && array[offset] != ' ') {
102  offset++;
103  }
104  segments.add(offset - commandStart);
105 
106  final int spacesStart = offset;
107  while (offset < end && array[offset] == ' ') {
108  offset++;
109  }
110  segments.add(offset - spacesStart);
111  }
112 
113  // 2. create tokens
114  final Iterator<Integer> it = segments.iterator();
115  int offset2 = line.offset;
116 
117  final int commandLength = it.next();
118  final String command = new String(array, offset2, commandLength);
119  final Spec spec = getSpec(command);
120  addToken(commandLength, spec != null ? spec.getId() : Token.INVALID);
121  offset2 += commandLength;
122 
123  final int spacesLength1 = it.next();
124  addToken(spacesLength1, Token.NULL);
125  offset2 += spacesLength1;
126 
127  while (it.hasNext()) {
128  final int parameterLength = it.next();
129  final String[] tmp = StringUtils.PATTERN_EQUAL.split(new String(array, offset2, parameterLength), 2);
130  if (tmp.length == 2) {
131  final String parameterString = tmp[0];
132  final String valueString = tmp[1];
133 
134  final Parameter parameter = spec != null ? spec.getParameter(parameterString) : null;
135  final boolean parameterValid = parameter != null;
136  final boolean valueValid = parameter == null || parameter.getParameterType().getPattern().matcher(valueString).matches();
137  addToken(parameterString.length(), parameterValid ? parameter.getId() : Token.INVALID);
138  addToken(1, (parameterString.isEmpty() && !parameterValid) || (valueString.isEmpty() && !valueValid) ? Token.INVALID : Token.OPERATOR);
139  addToken(valueString.length(), valueValid ? Token.NULL : Token.INVALID);
140  } else {
141  // missing '=' sign ==> syntax error
142  addToken(parameterLength, Token.INVALID);
143  }
144  offset2 += parameterLength;
145 
146  final int spacesLength2 = it.next();
147  addToken(spacesLength2, Token.NULL);
148  offset2 += spacesLength2;
149  }
150  }
151 
152  return Token.NULL;
153  }
154 
161  @Nullable
162  private static Spec getSpec(@NotNull final String command) {
163  final Spec fixedSpec = FIXED_SPECS.get(command);
164  if (fixedSpec != null) {
165  return fixedSpec;
166  }
167 
168  for (final Map.Entry<Pattern, Spec> entry : REGEX_SPECS.entrySet()) {
169  if (entry.getKey().matcher(command).matches()) {
170  return entry.getValue();
171  }
172  }
173 
174  return null;
175  }
176 
177 }
static final Map< Pattern, Spec > REGEX_SPECS
Commands having variable command names.
ParameterType getParameterType()
Returns the parameter type for the value of this parameter.
Definition: Parameter.java:75
byte getId()
Returns the token id used to highlight this command.
Definition: Spec.java:59
Utility class for string manipulation.
static final Pattern PATTERN_EQUAL
The pattern that matches a single equal sign ("=").
static final byte COMMENT1
Comment 1 token id.
Definition: Token.java:31
void addToken(final int length, final byte id)
Adds a token to the token list.
Pattern getPattern()
Returns the pattern matching valid parameter values.
byte getId()
Returns the token id used to highlight the parameter name.
Definition: Parameter.java:67
Base package of all Gridarta classes.
Parameter getParameter(final String name)
Returns the parameter specification for a parameter name.
Definition: Spec.java:69
A linked list of tokens.
Definition: Token.java:21
static final byte OPERATOR
Operator token id.
Definition: Token.java:78
This package contains the other part of the script editor.
A TokenMarker for the message field of Daimonin AI objects.
static final byte NULL
Normal text token id.
Definition: Token.java:26
static final byte KEYWORD2
Keyword 2 token id.
Definition: Token.java:66
A token marker that splits lines of text into tokens.
static final byte KEYWORD1
Keyword 1 token id.
Definition: Token.java:60
byte markTokensImpl(final byte token, @NotNull final Segment line)
static final byte INVALID
Invalid token id.
Definition: Token.java:84
Describes a command (excluding the command name).
Definition: Spec.java:29
static final byte LABEL
Label token id.
Definition: Token.java:54
static Spec getSpec(@NotNull final String command)
Returns the command specification from a command name.
static final Map< String, Spec > FIXED_SPECS
Commands having a fixed command name.