/
ReplaceableTagEvent.java
307 lines (231 loc) · 8.1 KB
/
ReplaceableTagEvent.java
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
package net.aufdemrand.denizen.events.bukkit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.aufdemrand.denizen.objects.dNPC;
import net.aufdemrand.denizen.objects.dPlayer;
import net.aufdemrand.denizen.scripts.ScriptEntry;
import net.aufdemrand.denizen.tags.Attribute;
import net.aufdemrand.denizen.tags.TagManager;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.minecraft.util.org.apache.commons.lang3.StringUtils;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
/**
* Bukkit event that fires on the finding of a replaceable tag, as indicated by surrounding < >'s.
*
* @author Jeremy Schroeder
*
* @version 1.0
*
*/
public class ReplaceableTagEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final dPlayer player;
private final dNPC npc;
private boolean instant = false;
private boolean wasReplaced = false;
private String alternative = null;
private boolean alternative_tagged = false;
private String replaced = null;
private String value = null;
private boolean value_tagged = false;
private Attribute core_attributes = null;
private ScriptEntry scriptEntry = null;
// Alternative text pattern that matches everything after ||
private static Pattern alternativeRegex = Pattern.compile("\\|\\|(.*)", Pattern.DOTALL | Pattern.MULTILINE);
public String raw_tag;
////////////
// Constructors
public ReplaceableTagEvent(dPlayer player, dNPC npc, String tag) { this(player, npc, tag, null); }
public ReplaceableTagEvent(dPlayer player, dNPC npc, String tag, ScriptEntry scriptEntry) {
// Reference ScriptEntry if available
this.scriptEntry = scriptEntry;
// Reference player/npc
this.player = player;
this.npc = npc;
// If tag is not replaced, return the tag
// TODO: Possibly make this return "null" ... might break some
// scripts using tags incorrectly, but makes more sense overall
this.replaced = tag;
// Check if tag is 'instant'
if (tag.length() > 0) {
char start = tag.charAt(0);
if (start == '!' || start == '^') {
instant = true;
tag = tag.substring(1);
}
}
// Get alternative text
Matcher alternativeMatcher = alternativeRegex.matcher(tag);
if (alternativeMatcher.find()) {
// remove found alternative from tag
tag = tag.substring(0, alternativeMatcher.start()).trim();
// get rid of the || at the alternative's start and any trailing spaces
alternative = alternativeMatcher.group(1).trim();
}
// Get value (if present)
if (tag.indexOf(':') > 0) {
int x1 = -1;
int braced = 0;
for (int x = 0; x < tag.length(); x++) {
Character chr = tag.charAt(x);
if (chr == '[')
braced++;
else if (chr == ']') {
if (braced > 0) braced--;
}
else if (chr == ':' && braced == 0 && x != tag.length() - 1 && x > 0) {
x1 = x;
break;
}
}
if (x1 > -1) {
value = tag.substring(x1 + 1);
tag = tag.substring(0, x1);
}
}
// Alternatives are stripped, value is stripped, let's remember the raw tag for the attributer.
raw_tag = tag;
// Use Attributes system to get type/subtype/etc. etc. for 'static/legacy' tags.
core_attributes = new Attribute(raw_tag, scriptEntry);
core_attributes.setHadAlternative(hasAlternative());
}
// Matches method (checks first attribute (name) of the tag)
public boolean matches(String tagName) {
String[] tagNames = StringUtils.split(tagName, ',');
String name = getName();
for (String string: tagNames)
if (name.equalsIgnoreCase(string.trim())) return true;
return false;
}
private String StripContext(String input) {
if (input == null)
return null;
int index = input.indexOf('[');
if (index < 0 || !input.endsWith("]"))
return input;
else
return input.substring(0, index);
}
////////
// Replaceable Tag 'Parts'
// <name.type.subtype.specifier:value>
// Name
public String getName() {
return StripContext(core_attributes.getAttribute(1));
}
public String getNameContext() {
return core_attributes.getContext(1);
}
public boolean hasNameContext() {
return core_attributes.hasContext(1);
}
// Type
public String getType() {
return StripContext(core_attributes.getAttribute(2));
}
public boolean hasType() {
return core_attributes.getAttribute(2).length() > 0;
}
public String getTypeContext() {
return core_attributes.getContext(2);
}
public boolean hasTypeContext() {
return core_attributes.hasContext(2);
}
// Subtype
public String getSubType() {
return StripContext(core_attributes.getAttribute(3));
}
public boolean hasSubType() {
return core_attributes.getAttribute(3).length() > 0;
}
public String getSubTypeContext() {
return core_attributes.getContext(3);
}
public boolean hasSubTypeContext() {
return core_attributes.hasContext(3);
}
// Specifier
public String getSpecifier() {
return StripContext(core_attributes.getAttribute(4));
}
public boolean hasSpecifier() {
return core_attributes.getAttribute(4).length() > 0;
}
public String getSpecifierContext() {
return core_attributes.getContext(4);
}
public boolean hasSpecifierContext() {
return core_attributes.hasContext(4);
}
// Value
public String getValue() {
if (value_tagged)
return value;
value_tagged = true;
value = TagManager.CleanOutputFully(TagManager.tag(
getPlayer(), getNPC(), value, false, getScriptEntry()));
return value;
}
public boolean hasValue() {
return value != null;
}
// Alternative
public String getAlternative() {
if (alternative_tagged)
return alternative;
alternative_tagged = true;
alternative = TagManager.CleanOutputFully(TagManager.tag(
getPlayer(), getNPC(), alternative, false, getScriptEntry()));
return alternative;
}
public boolean hasAlternative() {
return alternative != null;
}
// Other internal mechanics
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
public dNPC getNPC() {
return npc;
}
public dPlayer getPlayer() {
return player;
}
public String getReplaced() {
return replaced;
}
public boolean isInstant() {
return instant;
}
public boolean replaced() {
return wasReplaced;
}
public void setReplaced(String string) {
replaced = string;
wasReplaced = true;
}
public boolean hasScriptEntryAttached() {
return scriptEntry != null;
}
public ScriptEntry getScriptEntry() {
return scriptEntry;
}
/**
* Gets an Attribute object for easy parsing/reading
* of the different tag attributes.
*
* @return attributes
*/
public Attribute getAttributes() {
return core_attributes;
}
@Override
public String toString() {
return core_attributes.toString() + (hasValue() ? ":" + value: "") + (hasAlternative() ? "||" + alternative: "");
}
}