-
-
Notifications
You must be signed in to change notification settings - Fork 30
/
ScriptQueue.java
1051 lines (879 loc) · 32.5 KB
/
ScriptQueue.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
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
package net.aufdemrand.denizencore.scripts.queues;
import net.aufdemrand.denizencore.DenizenCore;
import net.aufdemrand.denizencore.events.ScriptEvent;
import net.aufdemrand.denizencore.interfaces.ContextSource;
import net.aufdemrand.denizencore.objects.*;
import net.aufdemrand.denizencore.objects.properties.Property;
import net.aufdemrand.denizencore.objects.properties.PropertyParser;
import net.aufdemrand.denizencore.scripts.ScriptEntry;
import net.aufdemrand.denizencore.scripts.commands.core.DetermineCommand;
import net.aufdemrand.denizencore.scripts.queues.core.TimedQueue;
import net.aufdemrand.denizencore.tags.Attribute;
import net.aufdemrand.denizencore.tags.TagContext;
import net.aufdemrand.denizencore.utilities.CoreUtilities;
import net.aufdemrand.denizencore.utilities.DefinitionProvider;
import net.aufdemrand.denizencore.utilities.QueueWordList;
import net.aufdemrand.denizencore.utilities.debugging.Debuggable;
import net.aufdemrand.denizencore.utilities.debugging.dB;
import net.aufdemrand.denizencore.utilities.scheduling.AsyncSchedulable;
import net.aufdemrand.denizencore.utilities.scheduling.OneTimeSchedulable;
import net.aufdemrand.denizencore.utilities.scheduling.Schedulable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* ScriptQueues hold/control ScriptEntries while being sent
* to the CommandExecuter
*/
public abstract class ScriptQueue implements Debuggable, dObject, DefinitionProvider {
private static final Map<Class<? extends ScriptQueue>, String> classNameCache = new HashMap<Class<? extends ScriptQueue>, String>();
protected static long total_queues = 0;
/**
* Returns the number of queues created in the current instance
* as well as the number of currently active queues.
*
* @return stats
*/
public static String _getStats() {
StringBuilder stats = new StringBuilder();
for (ScriptEvent event : ScriptEvent.events) {
stats.append("Event '" + event.getName() + "' ran "
+ event.fires + " times (" + event.scriptFires + " script fires)"
+ ", totalling " + ((float) event.nanoTimes / 1000000f) + "ms, averaging "
+ ((float) event.nanoTimes / 1000000f / (float) event.fires) + "ms per event or " +
+((float) event.nanoTimes / 1000000f / (float) event.scriptFires) + "ms per script.\n");
}
return "Total number of queues created: "
+ total_queues
+ ", currently active queues: "
+ _queues.size() + ",\n" + stats.toString();
}
/**
* Gets an existing queue. Cast to the correct QueueType to
* access further methods.
*
* @param id the id of the queue
* @return a ScriptQueue instance, or null
*/
public static ScriptQueue _getExistingQueue(String id) {
if (!_queueExists(id)) {
return null;
}
else {
return _queues.get(id);
}
}
/*
private static String randomEntry(String[] strings) {
return strings[CoreUtilities.getRandom().nextInt(strings.length)];
}*/
/**
* Gets a random id for use in creating a 'nameless' queue.
*
* @param prefix the name of the script running the new queue.
* @return String value of a random id
*/
public static String getNextId(String prefix) {
// DUUIDs v2.1
int size = QueueWordList.FinalWordList.size();
String id = prefix + "_"
+ QueueWordList.FinalWordList.get(CoreUtilities.getRandom().nextInt(size))
+ QueueWordList.FinalWordList.get(CoreUtilities.getRandom().nextInt(size))
+ QueueWordList.FinalWordList.get(CoreUtilities.getRandom().nextInt(size));
// DUUIDs v3.1
/*
String id = prefix.replace(' ', '_')
+ "_"
+ randomEntry(QueueWordList.Pronouns)
+ randomEntry(QueueWordList.Verbs)
+ randomEntry(QueueWordList.Modifiers)
+ randomEntry(QueueWordList.Adjectives)
+ randomEntry(QueueWordList.Nouns);*/
return _queues.containsKey(id) ? getNextId(prefix) : id;
}
/**
* Checks the type of an existing queue with the type given.
*
* @param queue id of the queue
* @param type class of the queue type
* @return true if they match, false if the queue
* doesn't exist or does not match
*/
public static boolean _matchesType(String queue, Class type) {
return (_queueExists(queue)) && _queues.get(queue).getClass() == type;
}
// Contains all currently active queues, keyed by a String id.
protected static Map<String, ScriptQueue> _queues =
new ConcurrentHashMap<String, ScriptQueue>(8, 0.9f, 1);
/**
* Returns a collection of all active queues.
*
* @return a collection of ScriptQueues
*/
public static Collection<ScriptQueue> _getQueues() {
return _queues.values();
}
/**
* Checks if a queue exists with the given id.
*
* @param id the String ID of the queue to check.
* @return true if it exists.
*/
public static boolean _queueExists(String id) {
return _queues.containsKey(id);
}
/////////////////////
// Public instance fields
/////////////////////
// Name of the queue -- this identifies
// the ScriptQueue when using _getQueue()
public String id;
// Whether the queue was cleared
public boolean was_cleared = false;
// Whether the queue should run asynchronously
public boolean run_async = false;
/////////////////////
// Private instance fields and constructors
/////////////////////
// List of ScriptEntries in the queue
private final List<ScriptEntry>
script_entries = new ArrayList<ScriptEntry>();
// The last script entry that was executed
// in this queue.
private ScriptEntry lastEntryExecuted = null;
// If this number is larger than Java's
// getCurrentTimeMillis(), the queue will
// delay execution of the next ScriptEntry
private long delay_time = 0;
// ScriptQueues can have a definitions,
// keyed by a String Id. Denizen's
// 'Definitions' system uses this map.
// This information is fetched by using
// %definition_name%
private final Map<String, String>
definitions = new ConcurrentHashMap<String, String>(8, 0.9f, 1);
// Held script entries can be recalled later in the script
// and their scriptEntry context can be recalled. Good for
// commands that contain unique items/objects that it's
// created.
private final Map<String, ScriptEntry>
held_entries = new ConcurrentHashMap<String, ScriptEntry>(8, 0.9f, 1);
private dScript script;
/**
* Creates a ScriptQueue instance. Users of
* the API should instead use the static members
* of classes that extend ScriptQueue.
*
* @param id the name of the ScriptQueue
*/
protected ScriptQueue(String id) {
// Remember the 'id'
this.id = id;
// Increment the stats
total_queues++;
}
protected ScriptQueue(String id, boolean async) {
this(id);
this.run_async = async;
}
/////////////////////
// Public instance setters and getters
/////////////////////
/**
* Gets a boolean indicating whether the queue
* was cleared.
*
* @return whether the queue has been cleared.
*/
public boolean getWasCleared() {
return was_cleared;
}
/**
* Gets a held script entry. Held script entries might
* contains some script entry context that might need
* to be fetched!
*/
public ScriptEntry getHeldScriptEntry(String id) {
return held_entries.get(id.toLowerCase());
}
/**
* Provides a way to hold a script entry for retrieval later in the
* script. Keyed by an id, which is turned to lowercase making
* it case insensitive.
*
* @param id intended name of the entry
* @param entry the ScriptEntry instance
* @return the ScriptQueue, just in case you need to do more with it
*/
public ScriptQueue holdScriptEntry(String id, ScriptEntry entry) {
// to lowercase to avoid case sensitivity.
held_entries.put(id.toLowerCase(), entry);
return this;
}
/**
* Gets a context from the queue. Script writers can
* use the <c.context_name> or <context.context_name> tags
* to fetch this data.
*
* @param id The name of the definitions
* @return The value of the definitions, or null
*/
public dObject getContext(String id) {
id = CoreUtilities.toLowerCase(id);
if (cs == null) {
return null;
}
dObject obj = cachedContext.get(id);
if (obj != null) {
return obj;
}
obj = cs.getContext(id);
if (obj != null && cs.getShouldCache()) {
cachedContext.put(id, obj);
}
return obj;
}
private ContextSource cs = null;
public HashMap<String, dObject> cachedContext;
public void setContextSource(ContextSource source) {
cs = source;
cachedContext = new HashMap<String, dObject>();
}
private long reqId = -1L;
/**
* Sets the instant-queue ID for usage by the determine command.
*
* @param ID the ID to use.
* @return the queue for re-use.
*/
public ScriptQueue setReqId(long ID) {
reqId = ID;
return this;
}
/**
* Gets a definition from the queue. Denizen's
* CommandExecuter will fetch this information
* by using the %definition_name% format, similar
* to 'replaceable tags'
*
* @param definition The name of the definitions
* @return The value of the definitions, or null
*/
@Override
public String getDefinition(String definition) {
if (definition == null) {
return null;
}
return definitions.get(definition.toLowerCase());
}
/**
* Checks for a piece of definitions.
*
* @param definition The name of the definitions
* @return true if the definition exists.
*/
@Override
public boolean hasDefinition(String definition) {
return definitions.containsKey(definition.toLowerCase());
}
/**
* Adds a new piece of definitions to the queue. This
* can be done with dScript as well by using the
* 'define' command.
*
* @param definition the name of the definitions
* @param value the value of the definition
*/
@Override
public void addDefinition(String definition, String value) {
definitions.put(definition.toLowerCase(), value);
}
/**
* Removes an existing definitions from the queue. This
* can be done with dScript as well by using the
* 'define' command, with :! as the value using the definition
* name as a prefix.
*
* @param definition the name of the definitions
*/
@Override
public void removeDefinition(String definition) {
definitions.remove(definition.toLowerCase());
}
/**
* Returns a Map of all the current definitions
* stored in the queue, keyed by 'definition id'
*
* @return all current definitions, empty if none.
*/
@Override
public Map<String, String> getAllDefinitions() {
return definitions;
}
/**
* The last entry that was executed. Note: any
* replaceable tags/etc. are already replaced
* in this ScriptEntry.
*
* @return the last entry executed
*/
public ScriptEntry getLastEntryExecuted() {
return lastEntryExecuted;
}
/**
* Clears the script queue.
* <p/>
* Use the 'queue clear' command in dScript to
* access this method.
*/
public void clear() {
was_cleared = true;
script_entries.clear();
}
/**
* Will delay the start of the queue until Java's
* System.currentTimeMillis() is less than the
* delayTime.
*
* @param delayTime the time to start the queue, in
* System.currentTimeMillis() format.
*/
public void delayUntil(long delayTime) {
this.delay_time = delayTime;
}
///////////////////
// Public 'functional' methods
//////////////////
/**
* Converts any queue type to a timed queue.
*
* @param delay how long to delay initially.
* @return the newly created queue.
*/
public TimedQueue forceToTimed(Duration delay) {
Runnable r = callback;
callback = null;
stop();
TimedQueue newQueue = TimedQueue.getQueue(id);
newQueue.run_async = this.run_async;
for (ScriptEntry entry : getEntries()) {
entry.setInstant(true);
}
newQueue.addEntries(getEntries());
for (Map.Entry<String, String> def : getAllDefinitions().entrySet()) {
newQueue.addDefinition(def.getKey(), def.getValue());
}
newQueue.setContextSource(cs);
newQueue.cachedContext = cachedContext;
for (Map.Entry<String, ScriptEntry> entry : held_entries.entrySet()) {
newQueue.holdScriptEntry(entry.getKey(), entry.getValue());
}
newQueue.setLastEntryExecuted(getLastEntryExecuted());
newQueue.setSpeed(1);
clear();
if (delay != null) {
newQueue.delayFor(delay);
}
newQueue.callBack(r);
newQueue.start();
return newQueue;
}
/**
* Called when the script queue is started.
*/
protected abstract void onStart();
protected boolean is_started;
private Class<? extends ScriptQueue> cachedClass;
public long startTime = 0;
private long startTimeMilli = 0;
/**
* Starts the script queue.
*/
public void start() {
if (is_started) {
return;
}
// Save the instance to the _queues static map
_queues.put(id, this);
// Set as started, and check for a valid delay_time.
is_started = true;
boolean is_delayed = delay_time > System.currentTimeMillis();
// Record what script generated the first entry in the queue
if (script_entries.size() > 0) {
script = script_entries.get(0).getScript();
}
// Debug info
Class<? extends ScriptQueue> clazz = this.cachedClass == null ? this.cachedClass = getClass() : this.cachedClass;
String name = classNameCache.get(clazz);
if (name == null) {
classNameCache.put(clazz, name = clazz.getSimpleName());
}
if (is_delayed) {
dB.echoDebug(this, "Delaying " + name + " '" + id + "'" + " for '"
+ new Duration(((double) (delay_time - System.currentTimeMillis())) / 1000f).identify() + "'...");
}
else {
dB.echoDebug(this, "Starting " + name + " '" + id + "'...");
}
Runnable runToStart = new Runnable() {
@Override
public void run() {
startTime = System.nanoTime();
startTimeMilli = System.currentTimeMillis();
onStart(); /* Start the engine */
}
};
// If it's delayed, schedule it for later
if (is_delayed) {
Schedulable schedulable = new OneTimeSchedulable(runToStart,
// Take the delay time, find out how many milliseconds away
// it is, turn it into seconds, then divide by 20 for ticks.
((float) (delay_time - System.currentTimeMillis())) / 1000);
if (run_async) {
schedulable = new AsyncSchedulable(schedulable);
}
DenizenCore.schedule(schedulable);
}
else {
// If it's not, start the engine now!
if (!run_async) {
runToStart.run();
}
else {
AsyncSchedulable.executor.execute(runToStart);
}
}
}
/**
* Immediately runs a list of entries within the script queue.
* Primarily used as a simple method of instant command injection.
*
* @param entries the entries to be run.
*/
public String runNow(List<ScriptEntry> entries, String type) {
// Inject the entries at the start
injectEntries(entries, 0);
//Note which entry comes next in the existing queue
ScriptEntry nextup = getQueueSize() > entries.size() ? getEntry(entries.size()) : null;
// Loop through until the queue is emptied or the entry noted above is reached
while (getQueueSize() > 0 && getEntry(0) != nextup && !was_cleared) {
if (breakMe != null) {
removeEntry(0);
}
else {
// Ensure the engine won't try to run its own instant code on the entry.
getEntry(0).setInstant(false);
// Don't let the system try to 'hold' this entry.
getEntry(0).setFinished(true);
// Execute the ScriptEntry properly through the Script Engine.
DenizenCore.getScriptEngine().revolve(this);
}
}
if (breakMe != null && breakMe.startsWith(type)) {
String origBreakMe = breakMe;
breakMe = null;
return origBreakMe;
}
return null;
}
private Runnable callback = null;
/**
* Adds a runnable to call back when the queue is completed.
*
* @param r the Runnable to call back
*/
public void callBack(Runnable r) {
callback = r;
}
private String breakMe = null;
public void breakLoop(String toBreak) {
breakMe = toBreak;
}
public String isLoopBroken() {
return breakMe;
}
/**
* Stops the script_queue and breaks it down.
*/
protected abstract void onStop();
protected boolean is_stopping = false;
public void stop() {
// If this is the first time this has been called, check the
// ScriptContainer event 'on queue completes' which may have
// a few more script entries to run.
if (!is_stopping) {
is_stopping = true;
// Get the entries
List<ScriptEntry> entries =
(lastEntryExecuted != null && lastEntryExecuted.getScript() != null ?
lastEntryExecuted.getScript().getContainer()
.getEntries(lastEntryExecuted.entryData.clone(), "on queue completes") : new ArrayList<ScriptEntry>());
// Add the 'finishing' entries back into the queue (if not empty)
if (!entries.isEmpty()) {
script_entries.addAll(entries);
dB.echoDebug(this, "Finishing up queue '" + id + "'...");
}
else /* if empty, just stop the queue like normal */ {
if (_queues.get(id) == this) {
_queues.remove(id);
}
dB.echoDebug(this, "Completing queue '" + id + "' in " + ((System.nanoTime() - startTime) / 1000000) + "ms.");
if (callback != null) {
callback.run();
}
is_started = false;
onStop();
}
}
// Else, just complete the queue.
// 1) Remove the id from active queue list
// 2) Cancel the corresponding task_id
else {
if (_queues.get(id) == this) {
_queues.remove(id);
dB.echoDebug(this, "Re-completing queue '" + id + "' in " + ((System.nanoTime() - startTime) / 1000000) + "ms.");
if (callback != null) {
callback.run();
}
is_started = false;
onStop();
}
}
}
////////////////////
// Internal methods and fields
////////////////////
/**
* Sets the last entry executed by the ScriptEngine.
*
* @param entry the ScriptEntry last executed.
*/
public void setLastEntryExecuted(ScriptEntry entry) {
lastEntryExecuted = entry;
}
protected abstract boolean shouldRevolve();
protected void revolve() {
// If entries queued up are empty, deconstruct the queue.
if (script_entries.isEmpty()) {
stop();
return;
}
if (!shouldRevolve()) {
return;
}
// Criteria met for a successful 'revolution' of this queue,
// so send the next script entry to the ScriptEngine.
DenizenCore.getScriptEngine().revolve(this);
if (script_entries.isEmpty()) {
stop();
}
}
public ScriptEntry getNext() {
if (!script_entries.isEmpty()) {
return script_entries.remove(0);
}
else {
return null;
}
}
public ScriptQueue addEntries(List<ScriptEntry> entries) {
script_entries.addAll(entries);
return this;
}
public List<ScriptEntry> getEntries() {
return script_entries;
}
public boolean hasInjectedItems = false;
public ScriptQueue injectEntries(List<ScriptEntry> entries, int position) {
if (position > script_entries.size() || position < 0) {
position = 1;
}
if (script_entries.size() == 0) {
position = 0;
}
script_entries.addAll(position, entries);
hasInjectedItems = true;
return this;
}
public boolean removeEntry(int position) {
if (script_entries.size() < position) {
return false;
}
script_entries.remove(position);
return true;
}
public ScriptEntry getEntry(int position) {
if (script_entries.size() < position) {
return null;
}
return script_entries.get(position);
}
public ScriptQueue injectEntry(ScriptEntry entry, int position) {
if (position > script_entries.size() || position < 0) {
position = 1;
}
if (script_entries.size() == 0) {
position = 0;
}
script_entries.add(position, entry);
hasInjectedItems = true;
return this;
}
public int getQueueSize() {
return script_entries.size();
}
// DEBUGGABLE
//
@Override
public boolean shouldDebug() throws Exception {
return (lastEntryExecuted != null ? lastEntryExecuted.shouldDebug()
: script_entries.get(0).shouldDebug());
}
@Override
public boolean shouldFilter(String criteria) throws Exception {
return (lastEntryExecuted != null ? lastEntryExecuted.getScript().getName().equalsIgnoreCase(criteria.replace("s@", ""))
: script_entries.get(0).getScript().getName().equalsIgnoreCase(criteria.replace("s@", "")));
}
// dOBJECT
//
public static ScriptQueue valueOf(String string) {
return valueOf(string, null);
}
/**
* Gets a Queue Object from a string form of q@queue_name.
*
* @param string the string or dScript argument String
* @return a ScriptQueue, or null if incorrectly formatted
*/
@Fetchable("q")
public static ScriptQueue valueOf(String string, TagContext context) {
if (string == null) {
return null;
}
if (string.startsWith("q@") && string.length() > 2) {
string = string.substring(2);
}
if (_queueExists(string)) {
return _getExistingQueue(string);
}
return null;
}
public static boolean matches(String string) {
// Starts with q@? Assume match.
if (string.toLowerCase().startsWith("q@")) {
return true;
}
else {
return false;
}
}
String prefix = "Queue";
@Override
public String getPrefix() {
return prefix;
}
@Override
public ScriptQueue setPrefix(String prefix) {
this.prefix = prefix;
return this;
}
@Override
public String debug() {
return "<G>" + prefix + "='<Y>" + identify() + "<G>' ";
}
@Override
public boolean isUnique() {
return true;
}
@Override
public String getObjectType() {
return "queue";
}
@Override
public String identify() {
return "q@" + id;
}
@Override
public String identifySimple() {
return identify();
}
@Override
public String toString() {
return identify();
}
public static void registerTags() {
// <--[tag]
// @attribute <q@queue.id>
// @returns Element
// @description
// Returns the id of the queue.
// -->
registerTag("id", new TagRunnable() {
@Override
public String run(Attribute attribute, dObject object) {
return new Element(((ScriptQueue) object).id).getAttribute(attribute.fulfill(1));
}
});
// <--[tag]
// @attribute <q@queue.size>
// @returns Element
// @description
// Returns the number of script entries in the queue.
// -->
registerTag("size", new TagRunnable() {
@Override
public String run(Attribute attribute, dObject object) {
return new Element(((ScriptQueue) object).script_entries.size()).getAttribute(attribute.fulfill(1));
}
});
// <--[tag]
// @attribute <q@queue.start_time>
// @returns Duration
// @description
// Returns the time this queue started as a duration.
// -->
registerTag("start_time", new TagRunnable() {
@Override
public String run(Attribute attribute, dObject object) {
return new Duration(((ScriptQueue) object).startTimeMilli / 50).getAttribute(attribute.fulfill(1));
}
});
// <--[tag]
// @attribute <q@queue.state>
// @returns Element
// @description
// Returns 'stopping', 'running', or 'unknown'.
// -->
registerTag("state", new TagRunnable() {
@Override
public String run(Attribute attribute, dObject object) {
String state;
if (((ScriptQueue) object).is_started) {
state = "running";
}
else if (((ScriptQueue) object).is_stopping) {
state = "stopping";
}
else {
state = "unknown";
}
return new Element(state).getAttribute(attribute.fulfill(1));
}
});
// <--[tag]
// @attribute <q@queue.script>
// @returns dScript
// @description
// Returns the script that started this queue.
// -->
registerTag("script", new TagRunnable() {
@Override
public String run(Attribute attribute, dObject object) {
if (((ScriptQueue) object).script == null) {
return null;
}
return ((ScriptQueue) object).script.getAttribute(attribute.fulfill(1));
}
});
// <--[tag]
// @attribute <q@queue.commands>
// @returns dList
// @description
// Returns a list of commands waiting in the queue.
// -->
registerTag("commands", new TagRunnable() {
@Override
public String run(Attribute attribute, dObject object) {
dList commands = new dList();
for (ScriptEntry entry : ((ScriptQueue) object).script_entries) {
StringBuilder sb = new StringBuilder();
sb.append(entry.getCommandName()).append(" ");
for (String arg : entry.getOriginalArguments()) {
sb.append(arg).append(" ");
}
commands.add(sb.substring(0, sb.length() - 1));
}
return commands.getAttribute(attribute.fulfill(1));
}
});
// <--[tag]
// @attribute <q@queue.definitions>
// @returns dList
// @description
// Returns the names of all definitions that were passed to the current queue.
// -->
registerTag("definitions", new TagRunnable() {
@Override
public String run(Attribute attribute, dObject object) {
return new dList(((ScriptQueue) object).getAllDefinitions().keySet()).getAttribute(attribute.fulfill(1));
}
});
// <--[tag]
// @attribute <q@queue.definition[<definition>]>
// @returns dList
// @description
// Returns the value of the specified definition.
// Returns null if the queue lacks the definition.
// -->
registerTag("definition", new TagRunnable() {
@Override
public String run(Attribute attribute, dObject object) {
if (!attribute.hasContext(1)) {
dB.echoError("The tag q@queue.definition[...] must have a value.");
return null;
}
return new Element(((ScriptQueue) object).getDefinition(attribute.getContext(1))).getAttribute(attribute.fulfill(1));
}
});
// <--[tag]
// @attribute <q@queue.determination>
// @returns dObject
// @description
// Returns the value that has been determined via <@link command Determine>
// for this queue, or null if there is none.
// The object will be returned as the most-valid type based on the input.
// -->
registerTag("determination", new TagRunnable() {