/
ZapCommand.java
181 lines (153 loc) · 8.01 KB
/
ZapCommand.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
package net.aufdemrand.denizen.scripts.commands.core;
import net.aufdemrand.denizen.BukkitScriptEntryData;
import net.aufdemrand.denizen.scripts.containers.core.InteractScriptHelper;
import net.aufdemrand.denizen.utilities.DenizenAPI;
import net.aufdemrand.denizen.utilities.debugging.dB;
import net.aufdemrand.denizencore.exceptions.InvalidArgumentsException;
import net.aufdemrand.denizencore.objects.Duration;
import net.aufdemrand.denizencore.objects.Element;
import net.aufdemrand.denizencore.objects.aH;
import net.aufdemrand.denizencore.objects.dScript;
import net.aufdemrand.denizencore.scripts.ScriptEntry;
import net.aufdemrand.denizencore.scripts.commands.AbstractCommand;
import org.bukkit.event.Listener;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ZapCommand extends AbstractCommand implements Listener {
// <--[command]
// @Name Zap
// @Syntax zap (<script>) [<step>] (<duration>)
// @Required 0
// @Short Changes the current script step.
// @Group core
//
// @Description
// TODO: Document Command Details
//
// @Tags
// <s@script.step[<player>]>
//
// @Usage
// Use to change the step to 2
// - zap 2
//
// @Usage
// Use to change the step to 3 in a script called Interact_Example.
// - zap 3 s@Interact_Example
//
// @Usage
// Use to change the step to 1 for player bob in a script called InteractScript.
// - zap 1 s@InteractScript player:p@bob
// -->
@Override
public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {
for (aH.Argument arg : aH.interpretArguments(scriptEntry.aHArgs)) {
// If the scripter uses the 'script:step' format, handle it.
if (!scriptEntry.hasObject("script")
&& !scriptEntry.hasObject("step")
&& arg.hasPrefix()
&& arg.getPrefix().matchesArgumentType(dScript.class)) {
scriptEntry.addObject("script", arg.getPrefix().asType(dScript.class));
scriptEntry.addObject("step", arg.asElement());
}
// If a script is found, use that to ZAP
else if (!scriptEntry.hasObject("script")
&& arg.matchesArgumentType(dScript.class)
&& !arg.matchesPrefix("step")) {
scriptEntry.addObject("script", arg.asType(dScript.class));
}
// Add argument as step
else if (!scriptEntry.hasObject("step")) {
scriptEntry.addObject("step", arg.asElement());
}
// Lastly duration
else if (!scriptEntry.hasObject("duration")
&& arg.matchesArgumentType(Duration.class)) {
scriptEntry.addObject("duration", arg.asType(Duration.class));
}
else {
arg.reportUnhandled();
}
}
// Add default script if none was specified.
scriptEntry.defaultObject("script", scriptEntry.getScript());
// Check if player is valid
if (!((BukkitScriptEntryData) scriptEntry.entryData).hasPlayer() || !((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().isValid()) {
throw new InvalidArgumentsException("Must have player context!");
}
}
//"PlayerName,ScriptName", TaskID
private static Map<String, Integer> durations = new ConcurrentHashMap<>(8, 0.9f, 1);
@Override
public void execute(final ScriptEntry scriptEntry) {
final dScript script = (dScript) scriptEntry.getObject("script");
Duration duration = (Duration) scriptEntry.getObject("duration");
if (scriptEntry.dbCallShouldDebug()) {
dB.report(scriptEntry, getName(), ((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().debug() + script.debug()
+ (scriptEntry.hasObject("step")
? scriptEntry.getElement("step").debug() : aH.debugObj("step", "++ (inc)"))
+ (duration != null ? duration.debug() : ""));
}
String step = scriptEntry.hasObject("step") ? scriptEntry.getElement("step").asString() : null;
// Let's get the current step for reference.
String currentStep = InteractScriptHelper.getCurrentStep(((BukkitScriptEntryData) scriptEntry.entryData).getPlayer(), script.getName());
// Special-case for backwards compatibility: ability to use ZAP to count up steps.
if (step == null) {
// Okay, no step was identified.. that means we should count up,
// ie. if currentStep = 1, new step should = 2
// If the currentStep is a number, increment it. If not, set it
// to '1' so it can be incremented next time.
if (aH.matchesInteger(currentStep)) {
step = String.valueOf(aH.getIntegerFrom(currentStep) + 1);
}
else {
step = "1";
}
}
if (step.equalsIgnoreCase(currentStep)) {
dB.echoError(scriptEntry.getResidingQueue(), "Zapping to own current step!");
return;
}
// If the durationsMap already contains an entry for this player/script combination,
// cancel the task since it's probably not desired to change back anymore if another
// ZAP for this script is taking place.
if (durations.containsKey(((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().getSaveName() + "," + script.getName())) {
try {
DenizenAPI.getCurrentInstance().getServer().getScheduler().cancelTask(durations.get(((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().getSaveName() + "," + script.getName()));
}
catch (Exception e) {
}
}
// One last thing... check for duration.
if (duration != null && duration.getSeconds() > 0) {
// If a DURATION is specified, the currentStep should be remembered and
// restored after the duration.
scriptEntry.addObject("step", new Element(currentStep));
// And let's take away the duration that was set to avoid a re-duration
// inception-ion-ion-ion-ion... ;)
scriptEntry.addObject("duration", Duration.ZERO);
// Now let's add a delayed task to set it back after the duration
// Delays are in ticks, so let's multiply our duration (which is in seconds) by 20.
// 20 ticks per second.
long delay = (long) (duration.getSeconds() * 20);
// Set delayed task and put id in a map
dB.log("Setting delayed task 'RESET ZAP' for '" + script.identify() + "'");
durations.put(((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().getSaveName() + "," + script.getName(),
DenizenAPI.getCurrentInstance().getServer().getScheduler().scheduleSyncDelayedTask(DenizenAPI.getCurrentInstance(),
new Runnable() {
@Override
public void run() {
dB.log("Running delayed task 'RESET ZAP' for '" + script.identify() + "'");
durations.remove(((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().getSaveName() + "," + script.getName().toUpperCase());
execute(scriptEntry);
}
}, delay));
}
//
// FINALLY! ZAP! Change the step in Saves... your step is now ZAPPED!
// Fun fact: ZAP is named in homage of ZZT-OOPs ZAP command. Google it.
//
DenizenAPI.getCurrentInstance().getSaves().set("Players." + ((BukkitScriptEntryData) scriptEntry.entryData).getPlayer().getSaveName()
+ ".Scripts." + script.getName().toUpperCase() + "." + "Current Step", step);
}
}