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-2023 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.Map.Entry;
28 import java.util.regex.Pattern;
29 import javax.swing.text.Segment;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.annotations.Nullable;
34 
39 public class DaimoninAITokenMarker extends TokenMarker {
40 
45  @NotNull
46  private static final Map<String, Spec> FIXED_SPECS = new HashMap<>();
47 
52  @NotNull
53  private static final Map<Pattern, Spec> REGEX_SPECS = new HashMap<>();
54 
55  static {
56  FIXED_SPECS.put("actions:", new Spec(Token.LABEL));
57  FIXED_SPECS.put("moves:", new Spec(Token.LABEL));
58  FIXED_SPECS.put("processes:", new Spec(Token.LABEL));
59  FIXED_SPECS.put("bow_attack_enemy", new Spec(Token.KEYWORD1));
60  FIXED_SPECS.put("choose_enemy", new Spec(Token.KEYWORD1, new Parameter("antilure_distance", Token.KEYWORD2, ParameterType.INTEGER)));
61  FIXED_SPECS.put("dont_stand_still", new Spec(Token.KEYWORD1, new Parameter("max_idle_time", Token.KEYWORD2, ParameterType.INTEGER)));
63  FIXED_SPECS.put("groups", new Spec(Token.KEYWORD1, new Parameter("name", Token.KEYWORD2, ParameterType.STRING)));
64  FIXED_SPECS.put("heal_friend", new Spec(Token.KEYWORD1, new Parameter("healing_min_friendship", Token.KEYWORD2, ParameterType.INTEGER)));
65  FIXED_SPECS.put("look_for_other_mobs", new Spec(Token.KEYWORD1));
66  REGEX_SPECS.put(Pattern.compile("lua:.*"), new Spec(Token.KEYWORD1));
67  FIXED_SPECS.put("melee_attack_enemy", new Spec(Token.KEYWORD1));
68  FIXED_SPECS.put("move_randomly", new Spec(Token.KEYWORD1, new Parameter("xlimit", Token.KEYWORD2, ParameterType.INTEGER), new Parameter("ylimit", Token.KEYWORD2, ParameterType.INTEGER)));
69  FIXED_SPECS.put("move_towards_enemy", new Spec(Token.KEYWORD1));
70  FIXED_SPECS.put("move_towards_enemy_last_known_pos", new Spec(Token.KEYWORD1));
71  FIXED_SPECS.put("move_towards_home", new Spec(Token.KEYWORD1));
72  FIXED_SPECS.put("move_towards_waypoint", new Spec(Token.KEYWORD1));
73  FIXED_SPECS.put("run_away_from_enemy", new Spec(Token.KEYWORD1, new Parameter("hp_threshold", Token.KEYWORD2, ParameterType.INTEGER)));
74  FIXED_SPECS.put("search_for_lost_enemy", new Spec(Token.KEYWORD1));
75  FIXED_SPECS.put("sleep", new Spec(Token.KEYWORD1));
76  FIXED_SPECS.put("spell_attack_enemy", new Spec(Token.KEYWORD1));
77  FIXED_SPECS.put("stand_still", new Spec(Token.KEYWORD1));
78  }
79 
80  @Override
81  public byte markTokensImpl(final byte token, @NotNull final Segment line) {
82  final char[] array = line.array;
83  int offset = line.offset;
84  final int end = line.count + offset;
85  if (offset >= end) {
86  // empty line ==> mark nothing
87  } else if (array[offset] == '#') {
88  // comment line
89  addToken(line.count, Token.COMMENT1);
90  } else if (array[offset] == ' ') {
91  // syntax error
92  addToken(line.count, Token.INVALID);
93  } else {
94  // normal line
95 
96  // 1. parse line into segments
97 
98  // Collects parsed segments: command, space, parameter, space,
99  // parameter, space, ...
100  final Collection<Integer> segments = new ArrayList<>();
101 
102  while (offset < end) {
103  final int commandStart = offset;
104  while (offset < end && array[offset] != ' ') {
105  offset++;
106  }
107  segments.add(offset - commandStart);
108 
109  final int spacesStart = offset;
110  while (offset < end && array[offset] == ' ') {
111  offset++;
112  }
113  segments.add(offset - spacesStart);
114  }
115 
116  // 2. create tokens
117  final Iterator<Integer> it = segments.iterator();
118  int offset2 = line.offset;
119 
120  final int commandLength = it.next();
121  final String command = new String(array, offset2, commandLength);
122  final Spec spec = getSpec(command);
123  addToken(commandLength, spec == null ? Token.INVALID : spec.getId());
124  offset2 += commandLength;
125 
126  final int spacesLength1 = it.next();
127  addToken(spacesLength1, Token.NULL);
128  offset2 += spacesLength1;
129 
130  while (it.hasNext()) {
131  final int parameterLength = it.next();
132  final String[] tmp = StringUtils.PATTERN_EQUAL.split(new String(array, offset2, parameterLength), 2);
133  if (tmp.length == 2) {
134  final String parameterString = tmp[0];
135  final String valueString = tmp[1];
136 
137  final Parameter parameter = spec == null ? null : spec.getParameter(parameterString);
138  final boolean parameterValid = parameter != null;
139  final boolean valueValid = parameter == null || parameter.getParameterType().getPattern().matcher(valueString).matches();
140  addToken(parameterString.length(), parameterValid ? parameter.getId() : Token.INVALID);
141  addToken(1, (parameterString.isEmpty() && !parameterValid) || (valueString.isEmpty() && !valueValid) ? Token.INVALID : Token.OPERATOR);
142  addToken(valueString.length(), valueValid ? Token.NULL : Token.INVALID);
143  } else {
144  // missing '=' sign ==> syntax error
145  addToken(parameterLength, Token.INVALID);
146  }
147  offset2 += parameterLength;
148 
149  final int spacesLength2 = it.next();
150  addToken(spacesLength2, Token.NULL);
151  offset2 += spacesLength2;
152  }
153  }
154 
155  return Token.NULL;
156  }
157 
164  @Nullable
165  private static Spec getSpec(@NotNull final String command) {
166  final Spec fixedSpec = FIXED_SPECS.get(command);
167  if (fixedSpec != null) {
168  return fixedSpec;
169  }
170 
171  for (final Entry<Pattern, Spec> entry : REGEX_SPECS.entrySet()) {
172  if (entry.getKey().matcher(command).matches()) {
173  return entry.getValue();
174  }
175  }
176 
177  return null;
178  }
179 
180 }
net.sf.gridarta.textedit.textarea
This package contains the other part of the script editor.
net.sf.gridarta.textedit.textarea.tokenmarker.Spec.getId
byte getId()
Returns the token id used to highlight this command.
Definition: Spec.java:59
net.sf.gridarta
Base package of all Gridarta classes.
net.sf.gridarta.textedit.textarea.tokenmarker.DaimoninAITokenMarker
A TokenMarker for the message field of Daimonin AI objects.
Definition: DaimoninAITokenMarker.java:39
net.sf.gridarta.textedit.textarea.tokenmarker.TokenMarker.addToken
void addToken(final int length, final byte id)
Adds a token to the token list.
Definition: TokenMarker.java:225
net.sf.gridarta.textedit.textarea.Token.NULL
static final byte NULL
Normal text token id.
Definition: Token.java:26
net.sf
net.sf.gridarta.textedit.textarea.tokenmarker.ParameterType.INTEGER
INTEGER
Integer parameter.
Definition: ParameterType.java:33
net.sf.gridarta.textedit.textarea.tokenmarker.DaimoninAITokenMarker.markTokensImpl
byte markTokensImpl(final byte token, @NotNull final Segment line)
An abstract method that splits a line up into tokens.
Definition: DaimoninAITokenMarker.java:81
net.sf.gridarta.textedit
net.sf.gridarta.textedit.textarea.tokenmarker.ParameterType.STRING
STRING
String parameter.
Definition: ParameterType.java:38
net.sf.gridarta.textedit.textarea.Token
A linked list of tokens.
Definition: Token.java:21
net.sf.gridarta.textedit.textarea.Token.OPERATOR
static final byte OPERATOR
Operator token id.
Definition: Token.java:78
net
net.sf.gridarta.textedit.textarea.Token.LABEL
static final byte LABEL
Label token id.
Definition: Token.java:54
net.sf.gridarta.textedit.textarea.tokenmarker.ParameterType.STRING_INTEGER
STRING_INTEGER
String/Integer list parameter.
Definition: ParameterType.java:43
net.sf.gridarta.textedit.textarea.tokenmarker.Parameter
Describes a parameter.
Definition: Parameter.java:26
net.sf.gridarta.textedit.textarea.Token.INVALID
static final byte INVALID
Invalid token id.
Definition: Token.java:84
net.sf.gridarta.textedit.textarea.Token.KEYWORD2
static final byte KEYWORD2
Keyword 2 token id.
Definition: Token.java:66
net.sf.gridarta.textedit.textarea.tokenmarker.Parameter.getParameterType
ParameterType getParameterType()
Returns the parameter type for the value of this parameter.
Definition: Parameter.java:75
net.sf.gridarta.textedit.textarea.tokenmarker.Parameter.getId
byte getId()
Returns the token id used to highlight the parameter name.
Definition: Parameter.java:67
net.sf.gridarta.textedit.textarea.Token.KEYWORD1
static final byte KEYWORD1
Keyword 1 token id.
Definition: Token.java:60
net.sf.gridarta.utils.StringUtils
Utility class for string manipulation.
Definition: StringUtils.java:31
net.sf.gridarta.textedit.textarea.tokenmarker.Spec.getParameter
Parameter getParameter(final String name)
Returns the parameter specification for a parameter name.
Definition: Spec.java:69
net.sf.gridarta.textedit.textarea.tokenmarker.Spec
Describes a command (excluding the command name).
Definition: Spec.java:29
net.sf.gridarta.textedit.textarea.tokenmarker.DaimoninAITokenMarker.FIXED_SPECS
static final Map< String, Spec > FIXED_SPECS
Commands having a fixed command name.
Definition: DaimoninAITokenMarker.java:46
net.sf.gridarta.textedit.textarea.tokenmarker.DaimoninAITokenMarker.getSpec
static Spec getSpec(@NotNull final String command)
Returns the command specification from a command name.
Definition: DaimoninAITokenMarker.java:165
net.sf.gridarta.textedit.textarea.tokenmarker.ParameterType.getPattern
Pattern getPattern()
Returns the pattern matching valid parameter values.
Definition: ParameterType.java:62
net.sf.gridarta.textedit.textarea.tokenmarker.TokenMarker
A token marker that splits lines of text into tokens.
Definition: TokenMarker.java:32
net.sf.gridarta.textedit.textarea.tokenmarker.DaimoninAITokenMarker.REGEX_SPECS
static final Map< Pattern, Spec > REGEX_SPECS
Commands having variable command names.
Definition: DaimoninAITokenMarker.java:53
net.sf.gridarta.textedit.textarea.tokenmarker.ParameterType
Describes a parameter type.
Definition: ParameterType.java:28
net.sf.gridarta.textedit.textarea.Token.COMMENT1
static final byte COMMENT1
Comment 1 token id.
Definition: Token.java:31
net.sf.gridarta.utils
Definition: ActionBuilderUtils.java:20
it
This document describes some hints and requirements for general development on the CrossfireEditor If you plan to make changes to the editor code or setup please read the following and keep it in derived from a basic editor application called Gridder by Pasi Ker�nen so please communicate with best through the cf devel mailing before considering any fundamental changes About code DO NOT USE TABS No matter what Java development platform you are please configure insert indent Tabs are displayed totally different in every editor and there are millions of different editors out there The insertion of tabs in the source code is messing up the syntax formatting in a way that is UNREPAIRABLE Apart from please keep code indentation accurate This is not just good it helps to keep code readable and in that way dramatically decreases the chance for overlooked bugs Everyone is welcomed to correct indentation errors wherever they are spotted Before you start to do this please double check that your editor is really configured to insert spaces Line feeds may be checked in either in windows or in unix linux style All reasonable text and java editors can deal with both linefeed formats Converting line feeds is but in this case please make sure that only linefeed characters are changed and nothing else is affected Due to the platform independent nature of the editor has the potential to run on almost any given operating system the build process differs greatly between systems as well as java environments In the several people have attempted to add build scripts along with structural changes to optimize the setup on one particular system environment which has led to conflict Please do *not *attempt to change the structure or any directories for the mere purpose of improving a build process or performance in a java environment Build scripts may be placed in the root it would be especially fine if it is just one or two files but the latter is not required Please excuse me for placing such restriction I and many users of the editor greatly appreciate build scripts We just had some real troubles over this issue in the past and I don t want to have them repeated the editor has relatively high performance requirements I ve spent a lot of extra work to keep everything as fast and memory efficient as possible when you add new data fields or calculations in the archetype please make sure they are as efficient as possible and worth both the time and space they consume Now don t be afraid too much No development would be possible without adding calculations and data at all Just bear in mind unlike for many other open source performance does make a difference for the CrossfireEditor The for as many systems as possible In case you are unexperienced with java and note that the graphics look different on every and with every font They also have different sizes proportions and behave different A seemingly trivial and effectless change can wreck havoc for the same GUI run on another system please don t be totally afraid of it
Definition: Developer_README.txt:76
net.sf.gridarta.utils.StringUtils.PATTERN_EQUAL
static final Pattern PATTERN_EQUAL
The pattern that matches a single equal sign ("=").
Definition: StringUtils.java:103