-
Notifications
You must be signed in to change notification settings - Fork 520
/
Copy pathBukkitService.java
359 lines (327 loc) · 12 KB
/
BukkitService.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
package fr.xephi.authme.service;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.initialization.SettingsDependent;
import fr.xephi.authme.settings.Settings;
import fr.xephi.authme.settings.properties.PluginSettings;
import org.bukkit.BanEntry;
import org.bukkit.BanList;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Date;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
/**
* Service for operations requiring the Bukkit API, such as for scheduling.
*/
public class BukkitService implements SettingsDependent {
/** Number of ticks per second in the Bukkit main thread. */
public static final int TICKS_PER_SECOND = 20;
/** Number of ticks per minute. */
public static final int TICKS_PER_MINUTE = 60 * TICKS_PER_SECOND;
private final AuthMe authMe;
private boolean useAsyncTasks;
@Inject
BukkitService(AuthMe authMe, Settings settings) {
this.authMe = authMe;
reload(settings);
}
/**
* Schedules a once off task to occur as soon as possible.
* <p>
* This task will be executed by the main server thread.
*
* @param task Task to be executed
* @return Task id number (-1 if scheduling failed)
*/
public int scheduleSyncDelayedTask(Runnable task) {
return Bukkit.getScheduler().scheduleSyncDelayedTask(authMe, task);
}
/**
* Schedules a once off task to occur after a delay.
* <p>
* This task will be executed by the main server thread.
*
* @param task Task to be executed
* @param delay Delay in server ticks before executing task
* @return Task id number (-1 if scheduling failed)
*/
public int scheduleSyncDelayedTask(Runnable task, long delay) {
return Bukkit.getScheduler().scheduleSyncDelayedTask(authMe, task, delay);
}
/**
* Schedules a synchronous task if we are currently on a async thread; if not, it runs the task immediately.
* Use this when {@link #runTaskOptionallyAsync(Runnable) optionally asynchronous tasks} have to
* run something synchronously.
*
* @param task the task to be run
*/
public void scheduleSyncTaskFromOptionallyAsyncTask(Runnable task) {
if (Bukkit.isPrimaryThread()) {
task.run();
} else {
scheduleSyncDelayedTask(task);
}
}
/**
* Returns a task that will run on the next server tick.
*
* @param task the task to be run
* @return a BukkitTask that contains the id number
* @throws IllegalArgumentException if plugin is null
* @throws IllegalArgumentException if task is null
*/
public BukkitTask runTask(Runnable task) {
return Bukkit.getScheduler().runTask(authMe, task);
}
/**
* Returns a task that will run after the specified number of server
* ticks.
*
* @param task the task to be run
* @param delay the ticks to wait before running the task
* @return a BukkitTask that contains the id number
* @throws IllegalArgumentException if plugin is null
* @throws IllegalArgumentException if task is null
*/
public BukkitTask runTaskLater(Runnable task, long delay) {
return Bukkit.getScheduler().runTaskLater(authMe, task, delay);
}
/**
* Schedules this task to run asynchronously or immediately executes it based on
* AuthMe's configuration.
*
* @param task the task to run
*/
public void runTaskOptionallyAsync(Runnable task) {
if (useAsyncTasks) {
runTaskAsynchronously(task);
} else {
task.run();
}
}
/**
* <b>Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.</b>
* <p>
* Returns a task that will run asynchronously.
*
* @param task the task to be run
* @return a BukkitTask that contains the id number
* @throws IllegalArgumentException if plugin is null
* @throws IllegalArgumentException if task is null
*/
public BukkitTask runTaskAsynchronously(Runnable task) {
return Bukkit.getScheduler().runTaskAsynchronously(authMe, task);
}
/**
* <b>Asynchronous tasks should never access any API in Bukkit. Great care
* should be taken to assure the thread-safety of asynchronous tasks.</b>
* <p>
* Returns a task that will repeatedly run asynchronously until cancelled,
* starting after the specified number of server ticks.
*
* @param task the task to be run
* @param delay the ticks to wait before running the task for the first
* time
* @param period the ticks to wait between runs
* @return a BukkitTask that contains the id number
* @throws IllegalArgumentException if task is null
* @throws IllegalStateException if this was already scheduled
*/
public BukkitTask runTaskTimerAsynchronously(BukkitRunnable task, long delay, long period) {
return task.runTaskTimerAsynchronously(authMe, delay, period);
}
/**
* Schedules the given task to repeatedly run until cancelled, starting after the
* specified number of server ticks.
*
* @param task the task to schedule
* @param delay the ticks to wait before running the task
* @param period the ticks to wait between runs
* @return a BukkitTask that contains the id number
* @throws IllegalArgumentException if plugin is null
* @throws IllegalStateException if this was already scheduled
*/
public BukkitTask runTaskTimer(BukkitRunnable task, long delay, long period) {
return task.runTaskTimer(authMe, delay, period);
}
/**
* Broadcast a message to all players.
*
* @param message the message
* @return the number of players
*/
public int broadcastMessage(String message) {
return Bukkit.broadcastMessage(message);
}
/**
* Gets the player with the exact given name, case insensitive.
*
* @param name Exact name of the player to retrieve
* @return a player object if one was found, null otherwise
*/
public Player getPlayerExact(String name) {
return authMe.getServer().getPlayerExact(name);
}
/**
* Gets the player by the given name, regardless if they are offline or
* online.
* <p>
* This method may involve a blocking web request to get the UUID for the
* given name.
* <p>
* This will return an object even if the player does not exist. To this
* method, all players will exist.
*
* @param name the name the player to retrieve
* @return an offline player
*/
public OfflinePlayer getOfflinePlayer(String name) {
return authMe.getServer().getOfflinePlayer(name);
}
/**
* Gets a set containing all banned players.
*
* @return a set containing banned players
*/
public Set<OfflinePlayer> getBannedPlayers() {
return Bukkit.getBannedPlayers();
}
/**
* Gets every player that has ever played on this server.
*
* @return an array containing all previous players
*/
public OfflinePlayer[] getOfflinePlayers() {
return Bukkit.getOfflinePlayers();
}
/**
* Gets a view of all currently online players.
*
* @return collection of online players
*/
@SuppressWarnings("unchecked")
public Collection<Player> getOnlinePlayers() {
return (Collection<Player>) Bukkit.getOnlinePlayers();
}
/**
* Calls an event with the given details.
*
* @param event Event details
* @throws IllegalStateException Thrown when an asynchronous event is
* fired from synchronous code.
*/
public void callEvent(Event event) {
Bukkit.getPluginManager().callEvent(event);
}
/**
* Creates an event with the provided function and emits it.
*
* @param eventSupplier the event supplier: function taking a boolean specifying whether AuthMe is configured
* in async mode or not
* @param <E> the event type
* @return the event that was created and emitted
*/
public <E extends Event> E createAndCallEvent(Function<Boolean, E> eventSupplier) {
E event = eventSupplier.apply(useAsyncTasks);
callEvent(event);
return event;
}
/**
* Gets the world with the given name.
*
* @param name the name of the world to retrieve
* @return a world with the given name, or null if none exists
*/
public World getWorld(String name) {
return Bukkit.getWorld(name);
}
/**
* Dispatches a command on this server, and executes it if found.
*
* @param sender the apparent sender of the command
* @param commandLine the command + arguments. Example: <code>test abc 123</code>
* @return returns false if no target is found
*/
public boolean dispatchCommand(CommandSender sender, String commandLine) {
return Bukkit.dispatchCommand(sender, commandLine);
}
/**
* Dispatches a command to be run as console user on this server, and executes it if found.
*
* @param commandLine the command + arguments. Example: <code>test abc 123</code>
* @return returns false if no target is found
*/
public boolean dispatchConsoleCommand(String commandLine) {
return Bukkit.dispatchCommand(Bukkit.getConsoleSender(), commandLine);
}
@Override
public void reload(Settings settings) {
useAsyncTasks = settings.getProperty(PluginSettings.USE_ASYNC_TASKS);
}
/**
* Send the specified bytes to bungeecord using the specified player connection.
*
* @param player the player
* @param bytes the message
*/
public void sendBungeeMessage(Player player, byte[] bytes) {
player.sendPluginMessage(authMe, "BungeeCord", bytes);
}
/**
* Adds a ban to the list. If a previous ban exists, this will
* update the previous entry.
*
* @param ip the ip of the ban
* @param reason reason for the ban, null indicates implementation default
* @param expires date for the ban's expiration (unban), or null to imply
* forever
* @param source source of the ban, null indicates implementation default
* @return the entry for the newly created ban, or the entry for the
* (updated) previous ban
*/
public BanEntry banIp(String ip, String reason, Date expires, String source) {
return Bukkit.getServer().getBanList(BanList.Type.IP).addBan(ip, reason, expires, source);
}
/**
* Returns an optional with a boolean indicating whether bungeecord is enabled or not if the
* server implementation is Spigot. Otherwise returns an empty optional.
*
* @return Optional with configuration value for Spigot, empty optional otherwise
*/
public Optional<Boolean> isBungeeCordConfiguredForSpigot() {
try {
YamlConfiguration spigotConfig = Bukkit.spigot().getConfig();
return Optional.of(spigotConfig.getBoolean("settings.bungeecord"));
} catch (NoSuchMethodError e) {
return Optional.empty();
}
}
/**
* Creates a PotionEffect with blindness for the given duration in ticks.
*
* @param timeoutInTicks duration of the effect in ticks
* @return blindness potion effect
*/
public PotionEffect createBlindnessEffect(int timeoutInTicks) {
return new PotionEffect(PotionEffectType.BLINDNESS, timeoutInTicks, 2);
}
/**
* @return the IP string that this server is bound to, otherwise empty string
*/
public String getIp() {
return Bukkit.getServer().getIp();
}
}