mirror of
https://github.com/PlaceholderAPI/PlaceholderAPI
synced 2025-11-12 21:49:40 +01:00
Compare commits
3 Commits
feature/co
...
feature/ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ba5e5dd89 | ||
|
|
9689eec3ab | ||
|
|
19fca16653 |
@@ -9,7 +9,6 @@
|
|||||||
[spigot]: https://www.spigotmc.org/resources/6245/
|
[spigot]: https://www.spigotmc.org/resources/6245/
|
||||||
[hangar]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
|
[hangar]: https://hangar.papermc.io/HelpChat/PlaceholderAPI
|
||||||
[bbb]: https://builtbybit.com/resources/placeholderapi.24306
|
[bbb]: https://builtbybit.com/resources/placeholderapi.24306
|
||||||
[modrinth]: https://modrinth.com/plugin/placeholderapi
|
|
||||||
[Expansions cloud]: https://api.extendedclip.com/home
|
[Expansions cloud]: https://api.extendedclip.com/home
|
||||||
[placeholder list]: https://helpch.at/placeholders
|
[placeholder list]: https://helpch.at/placeholders
|
||||||
[statistics]: https://bstats.org/plugin/bukkit/PlaceholderAPI
|
[statistics]: https://bstats.org/plugin/bukkit/PlaceholderAPI
|
||||||
@@ -17,7 +16,7 @@
|
|||||||
[ci]: http://ci.extendedclip.com/job/PlaceholderAPI/
|
[ci]: http://ci.extendedclip.com/job/PlaceholderAPI/
|
||||||
[ciImg]: http://ci.extendedclip.com/buildStatus/icon?job=PlaceholderAPI
|
[ciImg]: http://ci.extendedclip.com/buildStatus/icon?job=PlaceholderAPI
|
||||||
|
|
||||||
[APIversionImg]: https://repo.extendedclip.com/api/badge/latest/releases/me/clip/placeholderapi?name=API%20Version
|
[APIversionImg]: https://img.shields.io/nexus/placeholderapi/me.clip/placeholderapi?server=https%3A%2F%2Frepo.extendedclip.com&label=API%20Version
|
||||||
[logo]: https://wiki.placeholderapi.com/assets/img/papi-logo.png
|
[logo]: https://wiki.placeholderapi.com/assets/img/papi-logo.png
|
||||||
|
|
||||||
[contributing]: https://github.com/PlaceholderAPI/PlaceholderAPI/blob/master/.github/CONTRIBUTING.md
|
[contributing]: https://github.com/PlaceholderAPI/PlaceholderAPI/blob/master/.github/CONTRIBUTING.md
|
||||||
@@ -33,7 +32,7 @@
|
|||||||
|
|
||||||
Support for specific plugins are provided either by the plugin itself or through expansions. The expansions may be downloaded in-game through the PAPI Expansion Cloud. There are currently over 240+ expansions that support a wide variety of plugins, such as Essentials, Factions, LuckPerms, and Vault.
|
Support for specific plugins are provided either by the plugin itself or through expansions. The expansions may be downloaded in-game through the PAPI Expansion Cloud. There are currently over 240+ expansions that support a wide variety of plugins, such as Essentials, Factions, LuckPerms, and Vault.
|
||||||
|
|
||||||
PlaceholderAPI has been downloaded over 1,700,000 times on Spigot and has been used concurrently on over 45,000 servers, which makes it a must-have for a server of any type or scale.
|
PlaceholderAPI has been downloaded over 1,600,000 times and has been used concurrently on over 40,000 servers, which makes it a must-have for a server of any type or scale.
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
If you would like to contribute towards PlaceholderAPI should you take a look at our [Contributing file][contributing] for the ins and outs on how you can do that and what you need to keep in mind.
|
If you would like to contribute towards PlaceholderAPI should you take a look at our [Contributing file][contributing] for the ins and outs on how you can do that and what you need to keep in mind.
|
||||||
@@ -52,5 +51,4 @@ If you would like to create your own Placeholder Expansion for PlaceholderAPI, t
|
|||||||
- [Spigot Page][spigot]
|
- [Spigot Page][spigot]
|
||||||
- [Hangar Page][hangar]
|
- [Hangar Page][hangar]
|
||||||
- [BuiltByBit Page][bbb]
|
- [BuiltByBit Page][bbb]
|
||||||
- [Modrinth Page][modrinth]
|
|
||||||
- [Plugin Statistics][statistics]
|
- [Plugin Statistics][statistics]
|
||||||
|
|||||||
@@ -20,15 +20,13 @@ repositories {
|
|||||||
|
|
||||||
maven("https://repo.codemc.org/repository/maven-public/")
|
maven("https://repo.codemc.org/repository/maven-public/")
|
||||||
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/")
|
||||||
maven("https://repo.papermc.io/repository/maven-public/")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.bstats:bstats-bukkit:3.0.1")
|
implementation("org.bstats:bstats-bukkit:3.0.1")
|
||||||
implementation("net.kyori:adventure-platform-bukkit:4.4.1")
|
implementation("net.kyori:adventure-platform-bukkit:4.3.3")
|
||||||
|
|
||||||
//compileOnly("org.spigotmc:spigot-api:1.21-R0.1-SNAPSHOT")
|
compileOnly("org.spigotmc:spigot-api:1.21-R0.1-SNAPSHOT")
|
||||||
compileOnly("dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT")
|
|
||||||
compileOnlyApi("org.jetbrains:annotations:23.0.0")
|
compileOnlyApi("org.jetbrains:annotations:23.0.0")
|
||||||
|
|
||||||
testImplementation("org.openjdk.jmh:jmh-core:1.32")
|
testImplementation("org.openjdk.jmh:jmh-core:1.32")
|
||||||
@@ -45,8 +43,6 @@ java {
|
|||||||
|
|
||||||
withJavadocJar()
|
withJavadocJar()
|
||||||
withSourcesJar()
|
withSourcesJar()
|
||||||
|
|
||||||
disableAutoTargetJvm()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
license {
|
license {
|
||||||
@@ -112,9 +108,9 @@ tasks {
|
|||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
if ("-DEV" in version.toString()) {
|
if ("-DEV" in version.toString()) {
|
||||||
url = uri("https://repo.extendedclip.com/snapshots")
|
url = uri("https://repo.extendedclip.com/content/repositories/dev/")
|
||||||
} else {
|
} else {
|
||||||
url = uri("https://repo.extendedclip.com/releases")
|
url = uri("https://repo.extendedclip.com/content/repositories/placeholderapi/")
|
||||||
}
|
}
|
||||||
|
|
||||||
credentials {
|
credentials {
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ import me.clip.placeholderapi.replacer.CharsReplacer;
|
|||||||
import me.clip.placeholderapi.replacer.Replacer;
|
import me.clip.placeholderapi.replacer.Replacer;
|
||||||
import me.clip.placeholderapi.replacer.Replacer.Closure;
|
import me.clip.placeholderapi.replacer.Replacer.Closure;
|
||||||
import me.clip.placeholderapi.util.Msg;
|
import me.clip.placeholderapi.util.Msg;
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.TextReplacementConfig;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
@@ -59,12 +57,6 @@ public final class PlaceholderAPI {
|
|||||||
|
|
||||||
// === Current API ===
|
// === Current API ===
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Component setComponentPlaceholders(final OfflinePlayer player, @NotNull final Component component) {
|
|
||||||
// change charsreplacer to custom that returns component instead of string - this is going to suck mega
|
|
||||||
return component.replaceText(config -> config.match(PLACEHOLDER_PATTERN).replacement((result, builder) -> builder.content(REPLACER_PERCENT.apply(builder.content(), player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates all placeholders into their corresponding values.
|
* Translates all placeholders into their corresponding values.
|
||||||
* <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}.
|
* <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}.
|
||||||
@@ -144,8 +136,8 @@ public final class PlaceholderAPI {
|
|||||||
* @return String containing all translated placeholders
|
* @return String containing all translated placeholders
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public static List<@NotNull String> setBracketPlaceholders(final OfflinePlayer player,
|
public static List<String> setBracketPlaceholders(final OfflinePlayer player,
|
||||||
@NotNull final List<@NotNull String> text) {
|
@NotNull final List<String> text) {
|
||||||
return text.stream().map(line -> setBracketPlaceholders(player, line))
|
return text.stream().map(line -> setBracketPlaceholders(player, line))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
@@ -158,8 +150,7 @@ public final class PlaceholderAPI {
|
|||||||
* @param text Text to set the placeholder values in
|
* @param text Text to set the placeholder values in
|
||||||
* @return String containing all translated placeholders
|
* @return String containing all translated placeholders
|
||||||
*/
|
*/
|
||||||
@NotNull
|
public static String setBracketPlaceholders(Player player, String text) {
|
||||||
public static String setBracketPlaceholders(Player player, @NotNull String text) {
|
|
||||||
return setBracketPlaceholders((OfflinePlayer) player, text);
|
return setBracketPlaceholders((OfflinePlayer) player, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,8 +162,7 @@ public final class PlaceholderAPI {
|
|||||||
* @param text List of Strings to set the placeholder values in
|
* @param text List of Strings to set the placeholder values in
|
||||||
* @return String containing all translated placeholders
|
* @return String containing all translated placeholders
|
||||||
*/
|
*/
|
||||||
@NotNull
|
public static List<String> setBracketPlaceholders(Player player, List<String> text) {
|
||||||
public static List<String> setBracketPlaceholders(Player player, @NotNull List<String> text) {
|
|
||||||
return setBracketPlaceholders((OfflinePlayer) player, text);
|
return setBracketPlaceholders((OfflinePlayer) player, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ import me.clip.placeholderapi.expansion.Version;
|
|||||||
import me.clip.placeholderapi.expansion.manager.CloudExpansionManager;
|
import me.clip.placeholderapi.expansion.manager.CloudExpansionManager;
|
||||||
import me.clip.placeholderapi.expansion.manager.LocalExpansionManager;
|
import me.clip.placeholderapi.expansion.manager.LocalExpansionManager;
|
||||||
import me.clip.placeholderapi.listeners.ServerLoadEventListener;
|
import me.clip.placeholderapi.listeners.ServerLoadEventListener;
|
||||||
import me.clip.placeholderapi.scheduler.UniversalScheduler;
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.schedulers.TaskScheduler;
|
|
||||||
import me.clip.placeholderapi.updatechecker.UpdateChecker;
|
import me.clip.placeholderapi.updatechecker.UpdateChecker;
|
||||||
import me.clip.placeholderapi.util.Msg;
|
import me.clip.placeholderapi.util.Msg;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||||
@@ -88,12 +86,9 @@ public final class PlaceholderAPIPlugin extends JavaPlugin {
|
|||||||
private final LocalExpansionManager localExpansionManager = new LocalExpansionManager(this);
|
private final LocalExpansionManager localExpansionManager = new LocalExpansionManager(this);
|
||||||
@NotNull
|
@NotNull
|
||||||
private final CloudExpansionManager cloudExpansionManager = new CloudExpansionManager(this);
|
private final CloudExpansionManager cloudExpansionManager = new CloudExpansionManager(this);
|
||||||
@NotNull
|
|
||||||
private final TaskScheduler scheduler = UniversalScheduler.getScheduler(this);
|
|
||||||
|
|
||||||
private BukkitAudiences adventure;
|
private BukkitAudiences adventure;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the static instance of the main class for PlaceholderAPI. This class is not the actual API
|
* Gets the static instance of the main class for PlaceholderAPI. This class is not the actual API
|
||||||
* class, this is the main class that extends JavaPlugin. For most API methods, use static methods
|
* class, this is the main class that extends JavaPlugin. For most API methods, use static methods
|
||||||
@@ -179,7 +174,7 @@ public final class PlaceholderAPIPlugin extends JavaPlugin {
|
|||||||
|
|
||||||
HandlerList.unregisterAll(this);
|
HandlerList.unregisterAll(this);
|
||||||
|
|
||||||
scheduler.cancelTasks(this);
|
Bukkit.getScheduler().cancelTasks(this);
|
||||||
|
|
||||||
adventure.close();
|
adventure.close();
|
||||||
adventure = null;
|
adventure = null;
|
||||||
@@ -220,11 +215,6 @@ public final class PlaceholderAPIPlugin extends JavaPlugin {
|
|||||||
return adventure;
|
return adventure;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public TaskScheduler getScheduler() {
|
|
||||||
return scheduler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtain the configuration class for PlaceholderAPI.
|
* Obtain the configuration class for PlaceholderAPI.
|
||||||
*
|
*
|
||||||
@@ -272,8 +262,8 @@ public final class PlaceholderAPIPlugin extends JavaPlugin {
|
|||||||
Class.forName("org.bukkit.event.server.ServerLoadEvent");
|
Class.forName("org.bukkit.event.server.ServerLoadEvent");
|
||||||
new ServerLoadEventListener(this);
|
new ServerLoadEventListener(this);
|
||||||
} catch (final ClassNotFoundException ignored) {
|
} catch (final ClassNotFoundException ignored) {
|
||||||
scheduler
|
Bukkit.getScheduler()
|
||||||
.runTaskLater(() -> getLocalExpansionManager().load(Bukkit.getConsoleSender()), 1);
|
.runTaskLater(this, () -> getLocalExpansionManager().load(Bukkit.getConsoleSender()), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,16 +20,12 @@
|
|||||||
|
|
||||||
package me.clip.placeholderapi;
|
package me.clip.placeholderapi;
|
||||||
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public abstract class PlaceholderHook {
|
public abstract class PlaceholderHook {
|
||||||
@Deprecated
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String onRequest(final OfflinePlayer player, @NotNull final String params) {
|
public String onRequest(final OfflinePlayer player, @NotNull final String params) {
|
||||||
if (player != null && player.isOnline()) {
|
if (player != null && player.isOnline()) {
|
||||||
@@ -39,16 +35,8 @@ public abstract class PlaceholderHook {
|
|||||||
return onPlaceholderRequest(null, params);
|
return onPlaceholderRequest(null, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String onPlaceholderRequest(final Player player, @NotNull final String params) {
|
public String onPlaceholderRequest(final Player player, @NotNull final String params) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Component onPlaceholderComponentRequest(final OfflinePlayer player, @NotNull final String params) {
|
|
||||||
final String result = onRequest(player, params);
|
|
||||||
|
|
||||||
return result == null ? null : Component.text(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,10 +51,7 @@ public enum NMSVersion {
|
|||||||
SPIGOT_1_20_R2("v1_20_R2"),
|
SPIGOT_1_20_R2("v1_20_R2"),
|
||||||
SPIGOT_1_20_R3("v1_20_R3"),
|
SPIGOT_1_20_R3("v1_20_R3"),
|
||||||
SPIGOT_1_20_R4("v1_20_R4"),
|
SPIGOT_1_20_R4("v1_20_R4"),
|
||||||
SPIGOT_1_21_R1("v1_21_R1"),
|
SPIGOT_1_21_R1("v1_21_R1");
|
||||||
SPIGOT_1_21_R2("V1_21_R2"),
|
|
||||||
SPIGOT_1_21_R3("V1_21_R3"),
|
|
||||||
SPIGOT_1_21_R4("V1_21_R4");
|
|
||||||
|
|
||||||
private final String version;
|
private final String version;
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,12 @@ public abstract class PlaceholderExpansion extends PlaceholderHook {
|
|||||||
* command is used
|
* command is used
|
||||||
*
|
*
|
||||||
* @return if this expansion should persist through placeholder reloads
|
* @return if this expansion should persist through placeholder reloads
|
||||||
|
*
|
||||||
|
* @deprecated PlaceholderExpansions registered through their {@link #register()} and not through
|
||||||
|
* {@link me.clip.placeholderapi.expansion.manager.LocalExpansionManager#register(Class)}
|
||||||
|
* will be considered internal now and not be unregistered during Plugin reloads.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public boolean persist() {
|
public boolean persist() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -202,8 +202,10 @@ public final class CloudExpansionManager {
|
|||||||
|
|
||||||
// loop through what's left on the main thread
|
// loop through what's left on the main thread
|
||||||
plugin
|
plugin
|
||||||
|
.getServer()
|
||||||
.getScheduler()
|
.getScheduler()
|
||||||
.runTask(
|
.runTask(
|
||||||
|
plugin,
|
||||||
() -> {
|
() -> {
|
||||||
try {
|
try {
|
||||||
for (Map.Entry<String, CloudExpansion> entry : values.entrySet()) {
|
for (Map.Entry<String, CloudExpansion> entry : values.entrySet()) {
|
||||||
|
|||||||
@@ -34,9 +34,9 @@ import java.util.Objects;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.CompletionException;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.events.ExpansionRegisterEvent;
|
import me.clip.placeholderapi.events.ExpansionRegisterEvent;
|
||||||
@@ -46,6 +46,7 @@ import me.clip.placeholderapi.expansion.Cacheable;
|
|||||||
import me.clip.placeholderapi.expansion.Cleanable;
|
import me.clip.placeholderapi.expansion.Cleanable;
|
||||||
import me.clip.placeholderapi.expansion.Configurable;
|
import me.clip.placeholderapi.expansion.Configurable;
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion.Type;
|
||||||
import me.clip.placeholderapi.expansion.Taskable;
|
import me.clip.placeholderapi.expansion.Taskable;
|
||||||
import me.clip.placeholderapi.expansion.VersionSpecific;
|
import me.clip.placeholderapi.expansion.VersionSpecific;
|
||||||
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
||||||
@@ -264,6 +265,9 @@ public final class LocalExpansionManager implements Listener {
|
|||||||
|
|
||||||
if (expansion instanceof VersionSpecific) {
|
if (expansion instanceof VersionSpecific) {
|
||||||
VersionSpecific nms = (VersionSpecific) expansion;
|
VersionSpecific nms = (VersionSpecific) expansion;
|
||||||
|
Msg.warn("Nag Author(s) %s of expansion %s about their usage of the deprecated "
|
||||||
|
+ "VersionSpecific interface!", expansion.getAuthor(), expansion.getIdentifier());
|
||||||
|
Msg.warn("They should switch to a new method of determining the Server version.");
|
||||||
if (!nms.isCompatibleWith(PlaceholderAPIPlugin.getServerVersion())) {
|
if (!nms.isCompatibleWith(PlaceholderAPIPlugin.getServerVersion())) {
|
||||||
Msg.warn("Your server version is incompatible with expansion %s %s",
|
Msg.warn("Your server version is incompatible with expansion %s %s",
|
||||||
expansion.getIdentifier(), expansion.getVersion());
|
expansion.getIdentifier(), expansion.getVersion());
|
||||||
@@ -320,6 +324,15 @@ public final class LocalExpansionManager implements Listener {
|
|||||||
|
|
||||||
@ApiStatus.Internal
|
@ApiStatus.Internal
|
||||||
public boolean unregister(@NotNull final PlaceholderExpansion expansion) {
|
public boolean unregister(@NotNull final PlaceholderExpansion expansion) {
|
||||||
|
if (expansion.getExpansionType() == Type.INTERNAL || expansion.persist()) {
|
||||||
|
if (expansion.getExpansionType() == Type.EXTERNAL && expansion.persist()) {
|
||||||
|
Msg.warn("Nag Author(s) %s about their external expansion %s having persist set to true",
|
||||||
|
expansion.getAuthor(), expansion.getIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (expansions.remove(expansion.getIdentifier().toLowerCase(Locale.ROOT)) == null) {
|
if (expansions.remove(expansion.getIdentifier().toLowerCase(Locale.ROOT)) == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -393,10 +406,6 @@ public final class LocalExpansionManager implements Listener {
|
|||||||
|
|
||||||
private void unregisterAll() {
|
private void unregisterAll() {
|
||||||
for (final PlaceholderExpansion expansion : Sets.newHashSet(expansions.values())) {
|
for (final PlaceholderExpansion expansion : Sets.newHashSet(expansions.values())) {
|
||||||
if (expansion.persist()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
expansion.unregister();
|
expansion.unregister();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -440,8 +449,7 @@ public final class LocalExpansionManager implements Listener {
|
|||||||
Msg.severe("Failed to load expansion %s (is a dependency missing?)", e, file.getName());
|
Msg.severe("Failed to load expansion %s (is a dependency missing?)", e, file.getName());
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
plugin.getLogger().log(Level.SEVERE, "Failed to load expansion file: " + file.getAbsolutePath(), e);
|
throw new CompletionException(e.getMessage() + " (expansion file: " + file.getAbsolutePath() + ")", e);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,303 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of adventure, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017-2025 KyoriPowered
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
package me.clip.placeholderapi.replacer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.regex.MatchResult;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
|
||||||
import net.kyori.adventure.text.*;
|
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
|
||||||
import net.kyori.adventure.text.format.Style;
|
|
||||||
import net.kyori.adventure.text.renderer.ComponentRenderer;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A renderer performing a replacement on every {@link TextComponent} element of a component tree.
|
|
||||||
*/
|
|
||||||
final class ComponentCharsReplacer implements ComponentRenderer<ComponentCharsReplacer.State> {
|
|
||||||
//static final TextReplacementRenderer INSTANCE = new TextReplacementRenderer();
|
|
||||||
private final OfflinePlayer player;
|
|
||||||
private final Function<String, @Nullable PlaceholderExpansion> lookup;
|
|
||||||
private static final Closure CLOSURE = Closure.PERCENT;
|
|
||||||
|
|
||||||
enum Closure {
|
|
||||||
BRACKET('{', '}'),
|
|
||||||
PERCENT('%', '%');
|
|
||||||
|
|
||||||
|
|
||||||
public final char head, tail;
|
|
||||||
|
|
||||||
Closure(final char head, final char tail) {
|
|
||||||
this.head = head;
|
|
||||||
this.tail = tail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComponentCharsReplacer(@Nullable final OfflinePlayer player,
|
|
||||||
@NotNull final Function<String, @Nullable PlaceholderExpansion> lookup) {
|
|
||||||
this.player = player;
|
|
||||||
this.lookup = lookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component render(final Component component, final State state) {
|
|
||||||
if (!state.running) return component;
|
|
||||||
final boolean prevFirstMatch = state.firstMatch;
|
|
||||||
state.firstMatch = true;
|
|
||||||
|
|
||||||
final List<Component> oldChildren = component.children();
|
|
||||||
final int oldChildrenSize = oldChildren.size();
|
|
||||||
Style oldStyle = component.style();
|
|
||||||
List<Component> children = null;
|
|
||||||
Component modified = component;
|
|
||||||
// replace the component itself
|
|
||||||
if (component instanceof TextComponent) {
|
|
||||||
TextComponent tc = (TextComponent) component;
|
|
||||||
final String content = tc.content();
|
|
||||||
|
|
||||||
final char[] chars = content.toCharArray();
|
|
||||||
final StringBuilder identifier = new StringBuilder();
|
|
||||||
final StringBuilder parameters = new StringBuilder();
|
|
||||||
|
|
||||||
final Map<List<Integer>, Component> replacements = new HashMap<>();
|
|
||||||
|
|
||||||
for (int i = 0; i < chars.length; i++) {
|
|
||||||
final char l = chars[i];
|
|
||||||
|
|
||||||
if (l != CLOSURE.head || i + 1 >= chars.length) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean identified = false;
|
|
||||||
boolean invalid = true;
|
|
||||||
boolean hadSpace = false;
|
|
||||||
|
|
||||||
while (++i < chars.length) {
|
|
||||||
final char p = chars[i];
|
|
||||||
|
|
||||||
if (p == ' ' && !identified) {
|
|
||||||
hadSpace = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == CLOSURE.tail) {
|
|
||||||
invalid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == '_' && !identified) {
|
|
||||||
identified = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (identified) {
|
|
||||||
parameters.append(p);
|
|
||||||
} else {
|
|
||||||
identifier.append(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final String identifierString = identifier.toString();
|
|
||||||
final String lowerIdentifiedString = identifierString.toLowerCase();
|
|
||||||
final String parametersString = parameters.toString();
|
|
||||||
|
|
||||||
identifier.setLength(0);
|
|
||||||
parameters.setLength(0);
|
|
||||||
|
|
||||||
if (invalid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
replacements.put(Lists.newArrayList(i, i + identifierString.length() + parametersString.length()), lookup.apply(lowerIdentifiedString).onPlaceholderComponentRequest(player, parametersString));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// do something with our replacements
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
final Matcher matcher = state.pattern.matcher(content);
|
|
||||||
int replacedUntil = 0; // last index handled
|
|
||||||
while (matcher.find()) {
|
|
||||||
final PatternReplacementResult result = state.continuer.shouldReplace(matcher, ++state.matchCount, state.replaceCount);
|
|
||||||
|
|
||||||
if (matcher.start() == 0) {
|
|
||||||
// if we're a full match, modify the component directly
|
|
||||||
if (matcher.end() == content.length()) {
|
|
||||||
final ComponentLike replacement = state.replacement.apply(matcher, Component.text().content(matcher.group())
|
|
||||||
.style(component.style()));
|
|
||||||
|
|
||||||
modified = replacement == null ? Component.empty() : replacement.asComponent();
|
|
||||||
|
|
||||||
if (modified.style().hoverEvent() != null) {
|
|
||||||
oldStyle = oldStyle.hoverEvent(null); // Remove original hover if it has been replaced completely
|
|
||||||
}
|
|
||||||
|
|
||||||
// merge style of the match into this component to prevent unexpected loss of style
|
|
||||||
modified = modified.style(modified.style().merge(component.style(), Style.Merge.Strategy.IF_ABSENT_ON_TARGET));
|
|
||||||
|
|
||||||
if (children == null) { // Prepare children
|
|
||||||
children = new ArrayList<>(oldChildrenSize + modified.children().size());
|
|
||||||
children.addAll(modified.children());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// otherwise, work on a child of the root node
|
|
||||||
modified = Component.text("", component.style());
|
|
||||||
final ComponentLike child = state.replacement.apply(matcher, Component.text().content(matcher.group()));
|
|
||||||
if (child != null) {
|
|
||||||
if (children == null) {
|
|
||||||
children = new ArrayList<>(oldChildrenSize + 1);
|
|
||||||
}
|
|
||||||
children.add(child.asComponent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (children == null) {
|
|
||||||
children = new ArrayList<>(oldChildrenSize + 2);
|
|
||||||
}
|
|
||||||
if (state.firstMatch) {
|
|
||||||
// truncate parent to content before match
|
|
||||||
modified = ((TextComponent) component).content(content.substring(0, matcher.start()));
|
|
||||||
} else if (replacedUntil < matcher.start()) {
|
|
||||||
children.add(Component.text(content.substring(replacedUntil, matcher.start())));
|
|
||||||
}
|
|
||||||
final ComponentLike builder = state.replacement.apply(matcher, Component.text().content(matcher.group()));
|
|
||||||
if (builder != null) {
|
|
||||||
children.add(builder.asComponent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.replaceCount++;
|
|
||||||
state.firstMatch = false;
|
|
||||||
replacedUntil = matcher.end();
|
|
||||||
}
|
|
||||||
if (replacedUntil < content.length()) {
|
|
||||||
// append trailing content
|
|
||||||
if (replacedUntil > 0) {
|
|
||||||
if (children == null) {
|
|
||||||
children = new ArrayList<>(oldChildrenSize);
|
|
||||||
}
|
|
||||||
children.add(Component.text(content.substring(replacedUntil)));
|
|
||||||
}
|
|
||||||
// otherwise, we haven't modified the component, so nothing to change
|
|
||||||
}
|
|
||||||
} else if (modified instanceof TranslatableComponent) { // get TranslatableComponent with() args
|
|
||||||
final List<TranslationArgument> args = ((TranslatableComponent) modified).arguments();
|
|
||||||
List<TranslationArgument> newArgs = null;
|
|
||||||
for (int i = 0, size = args.size(); i < size; i++) {
|
|
||||||
final TranslationArgument original = args.get(i);
|
|
||||||
final TranslationArgument replaced = original.value() instanceof Component ? TranslationArgument.component(this.render((Component) original.value(), state)) : original;
|
|
||||||
if (replaced != original) {
|
|
||||||
if (newArgs == null) {
|
|
||||||
newArgs = new ArrayList<>(size);
|
|
||||||
if (i > 0) {
|
|
||||||
newArgs.addAll(args.subList(0, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newArgs != null) {
|
|
||||||
newArgs.add(replaced);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newArgs != null) {
|
|
||||||
modified = ((TranslatableComponent) modified).arguments(newArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Only visit children if we're running
|
|
||||||
if (state.running) {
|
|
||||||
// hover event
|
|
||||||
if (state.replaceInsideHoverEvents) {
|
|
||||||
final HoverEvent<?> event = oldStyle.hoverEvent();
|
|
||||||
if (event != null) {
|
|
||||||
final HoverEvent<?> rendered = event.withRenderedValue(this, state);
|
|
||||||
if (event != rendered) {
|
|
||||||
modified = modified.style(s -> s.hoverEvent(rendered));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Children
|
|
||||||
boolean first = true;
|
|
||||||
for (int i = 0; i < oldChildrenSize; i++) {
|
|
||||||
final Component child = oldChildren.get(i);
|
|
||||||
final Component replaced = this.render(child, state);
|
|
||||||
if (replaced != child) {
|
|
||||||
if (children == null) {
|
|
||||||
children = new ArrayList<>(oldChildrenSize);
|
|
||||||
}
|
|
||||||
if (first) {
|
|
||||||
children.addAll(oldChildren.subList(0, i));
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
if (children != null) {
|
|
||||||
children.add(replaced);
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we're not visiting children, re-add original children if necessary
|
|
||||||
if (children != null) {
|
|
||||||
children.addAll(oldChildren);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.firstMatch = prevFirstMatch;
|
|
||||||
// Update the modified component with new children
|
|
||||||
if (children != null) {
|
|
||||||
return modified.children(children);
|
|
||||||
}
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class State {
|
|
||||||
final Pattern pattern;
|
|
||||||
final BiFunction<MatchResult, TextComponent.Builder, @Nullable ComponentLike> replacement;
|
|
||||||
final TextReplacementConfig.Condition continuer;
|
|
||||||
final boolean replaceInsideHoverEvents;
|
|
||||||
boolean running = true;
|
|
||||||
int matchCount = 0;
|
|
||||||
int replaceCount = 0;
|
|
||||||
boolean firstMatch = true;
|
|
||||||
|
|
||||||
State(final Pattern pattern, final BiFunction<MatchResult, TextComponent.Builder, @Nullable ComponentLike> replacement, final TextReplacementConfig.Condition continuer, final boolean replaceInsideHoverEvents) {
|
|
||||||
this.pattern = pattern;
|
|
||||||
this.replacement = replacement;
|
|
||||||
this.continuer = continuer;
|
|
||||||
this.replaceInsideHoverEvents = replaceInsideHoverEvents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2023 Sevastjan
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.clip.placeholderapi.scheduler;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.schedulers.TaskScheduler;
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.tasks.MyScheduledTask;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
/** Just modified BukkitRunnable */
|
|
||||||
public abstract class UniversalRunnable implements Runnable {
|
|
||||||
MyScheduledTask task;
|
|
||||||
|
|
||||||
public synchronized void cancel() throws IllegalStateException {
|
|
||||||
checkScheduled();
|
|
||||||
task.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this task has been cancelled.
|
|
||||||
*
|
|
||||||
* @return true if the task has been cancelled
|
|
||||||
* @throws IllegalStateException if task was not scheduled yet
|
|
||||||
*/
|
|
||||||
public synchronized boolean isCancelled() throws IllegalStateException {
|
|
||||||
checkScheduled();
|
|
||||||
return task.isCancelled();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules this in the Bukkit scheduler to run on next tick.
|
|
||||||
*
|
|
||||||
* @param plugin the reference to the plugin scheduling task
|
|
||||||
* @return {@link MyScheduledTask}
|
|
||||||
* @throws IllegalArgumentException if plugin is null
|
|
||||||
* @throws IllegalStateException if this was already scheduled
|
|
||||||
* @see TaskScheduler#runTask(Runnable)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public synchronized MyScheduledTask runTask(Plugin plugin) throws IllegalArgumentException, IllegalStateException {
|
|
||||||
checkNotYetScheduled();
|
|
||||||
return setupTask(UniversalScheduler.getScheduler(plugin).runTask(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <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>
|
|
||||||
* Schedules this in the Bukkit scheduler to run asynchronously.
|
|
||||||
*
|
|
||||||
* @param plugin the reference to the plugin scheduling task
|
|
||||||
* @return {@link MyScheduledTask}
|
|
||||||
* @throws IllegalArgumentException if plugin is null
|
|
||||||
* @throws IllegalStateException if this was already scheduled
|
|
||||||
* @see TaskScheduler#runTaskAsynchronously(Runnable)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public synchronized MyScheduledTask runTaskAsynchronously(Plugin plugin) throws IllegalArgumentException, IllegalStateException {
|
|
||||||
checkNotYetScheduled();
|
|
||||||
return setupTask(UniversalScheduler.getScheduler(plugin).runTaskAsynchronously(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules this to run after the specified number of server ticks.
|
|
||||||
*
|
|
||||||
* @param plugin the reference to the plugin scheduling task
|
|
||||||
* @param delay the ticks to wait before running the task
|
|
||||||
* @return {@link MyScheduledTask}
|
|
||||||
* @throws IllegalArgumentException if plugin is null
|
|
||||||
* @throws IllegalStateException if this was already scheduled
|
|
||||||
* @see TaskScheduler#runTaskLater(Runnable, long)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public synchronized MyScheduledTask runTaskLater(Plugin plugin, long delay) throws IllegalArgumentException, IllegalStateException {
|
|
||||||
checkNotYetScheduled();
|
|
||||||
return setupTask(UniversalScheduler.getScheduler(plugin).runTaskLater(this, delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <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>
|
|
||||||
* Schedules this to run asynchronously after the specified number of
|
|
||||||
* server ticks.
|
|
||||||
*
|
|
||||||
* @param plugin the reference to the plugin scheduling task
|
|
||||||
* @param delay the ticks to wait before running the task
|
|
||||||
* @return {@link MyScheduledTask}
|
|
||||||
* @throws IllegalArgumentException if plugin is null
|
|
||||||
* @throws IllegalStateException if this was already scheduled
|
|
||||||
* @see TaskScheduler#runTaskLaterAsynchronously(Runnable, long)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public synchronized MyScheduledTask runTaskLaterAsynchronously(Plugin plugin, long delay) throws IllegalArgumentException, IllegalStateException {
|
|
||||||
checkNotYetScheduled();
|
|
||||||
return setupTask(UniversalScheduler.getScheduler(plugin).runTaskLaterAsynchronously(this, delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules this to repeatedly run until cancelled, starting after the
|
|
||||||
* specified number of server ticks.
|
|
||||||
*
|
|
||||||
* @param plugin the reference to the plugin scheduling task
|
|
||||||
* @param delay the ticks to wait before running the task
|
|
||||||
* @param period the ticks to wait between runs
|
|
||||||
* @return {@link MyScheduledTask}
|
|
||||||
* @throws IllegalArgumentException if plugin is null
|
|
||||||
* @throws IllegalStateException if this was already scheduled
|
|
||||||
* @see TaskScheduler#runTaskTimer(Runnable, long, long)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public synchronized MyScheduledTask runTaskTimer(Plugin plugin, long delay, long period) throws IllegalArgumentException, IllegalStateException {
|
|
||||||
checkNotYetScheduled();
|
|
||||||
return setupTask(UniversalScheduler.getScheduler(plugin).runTaskTimer(this, delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <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>
|
|
||||||
* Schedules this to repeatedly run asynchronously until cancelled,
|
|
||||||
* starting after the specified number of server ticks.
|
|
||||||
*
|
|
||||||
* @param plugin the reference to the plugin scheduling task
|
|
||||||
* @param delay the ticks to wait before running the task for the first
|
|
||||||
* time
|
|
||||||
* @param period the ticks to wait between runs
|
|
||||||
* @return {@link MyScheduledTask}
|
|
||||||
* @throws IllegalArgumentException if plugin is null
|
|
||||||
* @throws IllegalStateException if this was already scheduled
|
|
||||||
* @see TaskScheduler#runTaskTimerAsynchronously(Runnable, long, long)
|
|
||||||
*/
|
|
||||||
|
|
||||||
public synchronized MyScheduledTask runTaskTimerAsynchronously(Plugin plugin, long delay, long period) throws IllegalArgumentException, IllegalStateException {
|
|
||||||
checkNotYetScheduled();
|
|
||||||
return setupTask(UniversalScheduler.getScheduler(plugin).runTaskTimerAsynchronously(this, delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkScheduled() {
|
|
||||||
if (task == null) {
|
|
||||||
throw new IllegalStateException("Not scheduled yet");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkNotYetScheduled() {
|
|
||||||
if (task != null) {
|
|
||||||
throw new IllegalStateException("Already scheduled");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private MyScheduledTask setupTask(final MyScheduledTask task) {
|
|
||||||
this.task = task;
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2023 Sevastjan
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.clip.placeholderapi.scheduler;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.scheduler.bukkit.BukkitScheduler;
|
|
||||||
import me.clip.placeholderapi.scheduler.folia.FoliaScheduler;
|
|
||||||
import me.clip.placeholderapi.scheduler.paper.PaperScheduler;
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.schedulers.TaskScheduler;
|
|
||||||
import me.clip.placeholderapi.scheduler.utils.JavaUtil;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
public class UniversalScheduler {
|
|
||||||
private static final boolean IS_FOLIA = JavaUtil.classExists("io.papermc.paper.threadedregions.RegionizedServer");
|
|
||||||
private static final boolean IS_CANVAS = JavaUtil.classExists("io.canvasmc.canvas.server.ThreadedServer");
|
|
||||||
private static final boolean IS_EXPANDED_SCHEDULING_AVAILABLE = JavaUtil.classExists("io.papermc.paper.threadedregions.scheduler.ScheduledTask");
|
|
||||||
|
|
||||||
public static TaskScheduler getScheduler(Plugin plugin) {
|
|
||||||
return IS_FOLIA || IS_CANVAS ? new FoliaScheduler(plugin) : (IS_EXPANDED_SCHEDULING_AVAILABLE ? new PaperScheduler(plugin) : new BukkitScheduler(plugin));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2023 Sevastjan
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.clip.placeholderapi.scheduler.bukkit;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.tasks.MyScheduledTask;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
import org.bukkit.scheduler.BukkitTask;
|
|
||||||
|
|
||||||
public class BukkitScheduledTask implements MyScheduledTask {
|
|
||||||
|
|
||||||
BukkitTask task;
|
|
||||||
|
|
||||||
boolean isRepeating;
|
|
||||||
|
|
||||||
public BukkitScheduledTask(final BukkitTask task) {
|
|
||||||
this.task = task;
|
|
||||||
this.isRepeating = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BukkitScheduledTask(final BukkitTask task, boolean isRepeating) {
|
|
||||||
this.task = task;
|
|
||||||
this.isRepeating = isRepeating;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancel() {
|
|
||||||
task.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return task.isCancelled();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Plugin getOwningPlugin() {
|
|
||||||
return task.getOwner();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCurrentlyRunning() {
|
|
||||||
return Bukkit.getServer().getScheduler().isCurrentlyRunning(this.task.getTaskId()); //There's no other way. Fuck bukkit
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRepeatingTask() {
|
|
||||||
return isRepeating;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2023 Sevastjan
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.clip.placeholderapi.scheduler.bukkit;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.schedulers.TaskScheduler;
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.tasks.MyScheduledTask;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
public class BukkitScheduler implements TaskScheduler {
|
|
||||||
final Plugin plugin;
|
|
||||||
|
|
||||||
public BukkitScheduler(Plugin plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGlobalThread() {
|
|
||||||
return Bukkit.getServer().isPrimaryThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEntityThread(Entity entity) {
|
|
||||||
return Bukkit.getServer().isPrimaryThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRegionThread(Location location) {
|
|
||||||
return Bukkit.getServer().isPrimaryThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTask(Runnable runnable) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTask(plugin, runnable));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLater(Runnable runnable, long delay) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimer(Runnable runnable, long delay, long period) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskAsynchronously(Runnable runnable) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLaterAsynchronously(Runnable runnable, long delay) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimerAsynchronously(Runnable runnable, long delay, long period) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Useless? Or...
|
|
||||||
public MyScheduledTask runTask(Plugin plugin, Runnable runnable) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTask(plugin, runnable));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLater(Plugin plugin, Runnable runnable, long delay) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLater(plugin, runnable, delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimer(Plugin plugin, Runnable runnable, long delay, long period) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskAsynchronously(Plugin plugin, Runnable runnable) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLaterAsynchronously(Plugin plugin, Runnable runnable, long delay) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimerAsynchronously(Plugin plugin, Runnable runnable, long delay, long period) {
|
|
||||||
return new BukkitScheduledTask(Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Runnable runnable) {
|
|
||||||
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelTasks() {
|
|
||||||
Bukkit.getScheduler().cancelTasks(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelTasks(Plugin plugin) {
|
|
||||||
Bukkit.getScheduler().cancelTasks(plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2023 Sevastjan
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.clip.placeholderapi.scheduler.folia;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.tasks.MyScheduledTask;
|
|
||||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
public class FoliaScheduledTask implements MyScheduledTask {
|
|
||||||
private final ScheduledTask task;
|
|
||||||
|
|
||||||
public FoliaScheduledTask(final ScheduledTask task) {
|
|
||||||
this.task = task;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void cancel() {
|
|
||||||
this.task.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCancelled() {
|
|
||||||
return this.task.isCancelled();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Plugin getOwningPlugin() {
|
|
||||||
return this.task.getOwningPlugin();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCurrentlyRunning() {
|
|
||||||
final ScheduledTask.ExecutionState state = this.task.getExecutionState();
|
|
||||||
return state == ScheduledTask.ExecutionState.RUNNING || state == ScheduledTask.ExecutionState.CANCELLED_RUNNING;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRepeatingTask() {
|
|
||||||
return this.task.isRepeatingTask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,220 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2023 Sevastjan
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.clip.placeholderapi.scheduler.folia;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.schedulers.TaskScheduler;
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.tasks.MyScheduledTask;
|
|
||||||
import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
|
|
||||||
import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler;
|
|
||||||
import io.papermc.paper.threadedregions.scheduler.RegionScheduler;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
public class FoliaScheduler implements TaskScheduler {
|
|
||||||
|
|
||||||
final Plugin plugin;
|
|
||||||
|
|
||||||
public FoliaScheduler(Plugin plugin) {
|
|
||||||
this.plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final RegionScheduler regionScheduler = Bukkit.getServer().getRegionScheduler();
|
|
||||||
private final GlobalRegionScheduler globalRegionScheduler = Bukkit.getServer().getGlobalRegionScheduler();
|
|
||||||
private final AsyncScheduler asyncScheduler = Bukkit.getServer().getAsyncScheduler();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGlobalThread() {
|
|
||||||
return Bukkit.getServer().isGlobalTickThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isTickThread() {
|
|
||||||
return Bukkit.getServer().isPrimaryThread(); // The Paper implementation checks whether this is a tick thread, this method exists to avoid confusion.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEntityThread(Entity entity) {
|
|
||||||
return Bukkit.getServer().isOwnedByCurrentRegion(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRegionThread(Location location) {
|
|
||||||
return Bukkit.getServer().isOwnedByCurrentRegion(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTask(Runnable runnable) {
|
|
||||||
return new FoliaScheduledTask(globalRegionScheduler.run(plugin, task -> runnable.run()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLater(Runnable runnable, long delay) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
if (delay <= 0) {
|
|
||||||
return runTask(runnable);
|
|
||||||
}
|
|
||||||
return new FoliaScheduledTask(globalRegionScheduler.runDelayed(plugin, task -> runnable.run(), delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimer(Runnable runnable, long delay, long period) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
delay = getOneIfNotPositive(delay);
|
|
||||||
return new FoliaScheduledTask(globalRegionScheduler.runAtFixedRate(plugin, task -> runnable.run(), delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTask(Plugin plugin, Runnable runnable) {
|
|
||||||
return new FoliaScheduledTask(globalRegionScheduler.run(plugin, task -> runnable.run()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLater(Plugin plugin, Runnable runnable, long delay) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
if (delay <= 0) {
|
|
||||||
return runTask(plugin, runnable);
|
|
||||||
}
|
|
||||||
return new FoliaScheduledTask(globalRegionScheduler.runDelayed(plugin, task -> runnable.run(), delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimer(Plugin plugin, Runnable runnable, long delay, long period) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
delay = getOneIfNotPositive(delay);
|
|
||||||
return new FoliaScheduledTask(globalRegionScheduler.runAtFixedRate(plugin, task -> runnable.run(), delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTask(Location location, Runnable runnable) {
|
|
||||||
return new FoliaScheduledTask(regionScheduler.run(plugin, location, task -> runnable.run()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLater(Location location, Runnable runnable, long delay) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
if (delay <= 0) {
|
|
||||||
return runTask(runnable);
|
|
||||||
}
|
|
||||||
return new FoliaScheduledTask(regionScheduler.runDelayed(plugin, location, task -> runnable.run(), delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimer(Location location, Runnable runnable, long delay, long period) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
delay = getOneIfNotPositive(delay);
|
|
||||||
return new FoliaScheduledTask(regionScheduler.runAtFixedRate(plugin, location, task -> runnable.run(), delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTask(Entity entity, Runnable runnable) {
|
|
||||||
return new FoliaScheduledTask(entity.getScheduler().run(plugin, task -> runnable.run(), null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLater(Entity entity, Runnable runnable, long delay) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
if (delay <= 0) {
|
|
||||||
return runTask(entity, runnable);
|
|
||||||
}
|
|
||||||
return new FoliaScheduledTask(entity.getScheduler().runDelayed(plugin, task -> runnable.run(), null, delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimer(Entity entity, Runnable runnable, long delay, long period) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
delay = getOneIfNotPositive(delay);
|
|
||||||
return new FoliaScheduledTask(entity.getScheduler().runAtFixedRate(plugin, task -> runnable.run(), null, delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskAsynchronously(Runnable runnable) {
|
|
||||||
return new FoliaScheduledTask(asyncScheduler.runNow(plugin, task -> runnable.run()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLaterAsynchronously(Runnable runnable, long delay) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
delay = getOneIfNotPositive(delay);
|
|
||||||
return new FoliaScheduledTask(asyncScheduler.runDelayed(plugin, task -> runnable.run(), delay * 50L, TimeUnit.MILLISECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimerAsynchronously(Runnable runnable, long delay, long period) {
|
|
||||||
return new FoliaScheduledTask(asyncScheduler.runAtFixedRate(plugin, task -> runnable.run(), delay * 50, period * 50, TimeUnit.MILLISECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskAsynchronously(Plugin plugin, Runnable runnable) {
|
|
||||||
return new FoliaScheduledTask(asyncScheduler.runNow(plugin, task -> runnable.run()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskLaterAsynchronously(Plugin plugin, Runnable runnable, long delay) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
delay = getOneIfNotPositive(delay);
|
|
||||||
return new FoliaScheduledTask(asyncScheduler.runDelayed(plugin, task -> runnable.run(), delay * 50L, TimeUnit.MILLISECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MyScheduledTask runTaskTimerAsynchronously(Plugin plugin, Runnable runnable, long delay, long period) {
|
|
||||||
//Folia exception: Delay ticks may not be <= 0
|
|
||||||
delay = getOneIfNotPositive(delay);
|
|
||||||
return new FoliaScheduledTask(asyncScheduler.runAtFixedRate(plugin, task -> runnable.run(), delay * 50, period * 50, TimeUnit.MILLISECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Runnable runnable) {
|
|
||||||
globalRegionScheduler.execute(plugin, runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Location location, Runnable runnable) {
|
|
||||||
regionScheduler.execute(plugin, location, runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Entity entity, Runnable runnable) {
|
|
||||||
entity.getScheduler().execute(plugin, runnable, null, 1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelTasks() {
|
|
||||||
globalRegionScheduler.cancelTasks(plugin);
|
|
||||||
asyncScheduler.cancelTasks(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cancelTasks(Plugin plugin) {
|
|
||||||
globalRegionScheduler.cancelTasks(plugin);
|
|
||||||
asyncScheduler.cancelTasks(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private long getOneIfNotPositive(long x) {
|
|
||||||
return x <= 0 ? 1L : x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2023 Sevastjan
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.clip.placeholderapi.scheduler.paper;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.scheduler.folia.FoliaScheduler;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
//Thanks to Towny
|
|
||||||
public class PaperScheduler extends FoliaScheduler {
|
|
||||||
public PaperScheduler(Plugin plugin) {
|
|
||||||
super(plugin);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGlobalThread() {
|
|
||||||
// isGlobalThread does not exist on paper, match the bukkit task scheduler's behaviour.
|
|
||||||
return Bukkit.getServer().isPrimaryThread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,346 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2023 Sevastjan
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.clip.placeholderapi.scheduler.scheduling.schedulers;
|
|
||||||
|
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.tasks.MyScheduledTask;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Entity;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
|
|
||||||
public interface TaskScheduler {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Folia</b>: Returns whether the current thread is ticking the global region <br>
|
|
||||||
* <b>Paper & Bukkit</b>: Returns {@link org.bukkit.Server#isPrimaryThread}
|
|
||||||
*/
|
|
||||||
boolean isGlobalThread();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {@link org.bukkit.Server#isPrimaryThread}
|
|
||||||
*/
|
|
||||||
default boolean isTickThread() {
|
|
||||||
return Bukkit.getServer().isPrimaryThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Folia & Paper</b>: Returns whether the current thread is ticking a region and that the region
|
|
||||||
* being ticked owns the specified entity. Note that this function is the only appropriate method of
|
|
||||||
* checking for ownership of an entity, as retrieving the entity's location is undefined unless the
|
|
||||||
* entity is owned by the current region
|
|
||||||
* <p>
|
|
||||||
* <b>Bukkit</b>: returns {@link org.bukkit.Server#isPrimaryThread}
|
|
||||||
*
|
|
||||||
* @param entity Specified entity
|
|
||||||
*/
|
|
||||||
boolean isEntityThread(Entity entity);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Folia & Paper</b>: Returns whether the current thread is ticking a region and that the region
|
|
||||||
* being ticked owns the chunk at the specified world and block position as included in the specified location
|
|
||||||
* <p>
|
|
||||||
* <b>Bukkit</b>: returns {@link org.bukkit.Server#isPrimaryThread}
|
|
||||||
*
|
|
||||||
* @param location Specified location, must have a non-null world.
|
|
||||||
*/
|
|
||||||
boolean isRegionThread(Location location);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules a task to be executed on the next tick <br>
|
|
||||||
* <b>Folia & Paper</b>: ...on the global region <br>
|
|
||||||
* <b>Bukkit</b>: ...on the main thread
|
|
||||||
*
|
|
||||||
* @param runnable The task to execute
|
|
||||||
*/
|
|
||||||
MyScheduledTask runTask(Runnable runnable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules a task to be executed after the specified delay in ticks <br>
|
|
||||||
* <b>Folia & Paper</b>: ...on the global region <br>
|
|
||||||
* <b>Bukkit</b>: ...on the main thread
|
|
||||||
*
|
|
||||||
* @param runnable The task to execute
|
|
||||||
* @param delay The delay, in ticks
|
|
||||||
*/
|
|
||||||
MyScheduledTask runTaskLater(Runnable runnable, long delay);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules a repeating task to be executed after the initial delay with the specified period <br>
|
|
||||||
* <b>Folia & Paper</b>: ...on the global region <br>
|
|
||||||
* <b>Bukkit</b>: ...on the main thread
|
|
||||||
*
|
|
||||||
* @param runnable The task to execute
|
|
||||||
* @param delay The initial delay, in ticks.
|
|
||||||
* @param period The period, in ticks.
|
|
||||||
*/
|
|
||||||
MyScheduledTask runTaskTimer(Runnable runnable, long delay, long period);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated: use {@link #runTask(Runnable)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default MyScheduledTask runTask(Plugin plugin, Runnable runnable) {
|
|
||||||
return runTask(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated: use {@link #runTaskLater(Runnable, long)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default MyScheduledTask runTaskLater(Plugin plugin, Runnable runnable, long delay) {
|
|
||||||
return runTaskLater(runnable, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated: use {@link #runTaskTimer(Runnable, long, long)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default MyScheduledTask runTaskTimer(Plugin plugin, Runnable runnable, long delay, long period) {
|
|
||||||
return runTaskTimer(runnable, delay, period);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Folia & Paper</b>: Schedules a task to be executed on the region which owns the location on the next tick
|
|
||||||
* <p>
|
|
||||||
* <b>Bukkit</b>: same as {@link #runTask(Runnable)}
|
|
||||||
*
|
|
||||||
* @param location The location which the region executing should own
|
|
||||||
* @param runnable The task to execute
|
|
||||||
*/
|
|
||||||
default MyScheduledTask runTask(Location location, Runnable runnable) {
|
|
||||||
return runTask(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Folia & Paper</b>: Schedules a task to be executed on the region which owns the location after the
|
|
||||||
* specified delay in ticks
|
|
||||||
* <p>
|
|
||||||
* <b>Bukkit</b>: same as {@link #runTaskLater(Runnable, long)}
|
|
||||||
*
|
|
||||||
* @param location The location which the region executing should own
|
|
||||||
* @param runnable The task to execute
|
|
||||||
* @param delay The delay, in ticks.
|
|
||||||
*/
|
|
||||||
default MyScheduledTask runTaskLater(Location location, Runnable runnable, long delay) {
|
|
||||||
return runTaskLater(runnable, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Folia & Paper</b>: Schedules a repeating task to be executed on the region which owns the location
|
|
||||||
* after the initial delay with the specified period
|
|
||||||
* <p>
|
|
||||||
* <b>Bukkit</b>: same as {@link #runTaskTimer(Runnable, long, long)}
|
|
||||||
*
|
|
||||||
* @param location The location which the region executing should own
|
|
||||||
* @param runnable The task to execute
|
|
||||||
* @param delay The initial delay, in ticks.
|
|
||||||
* @param period The period, in ticks.
|
|
||||||
*/
|
|
||||||
default MyScheduledTask runTaskTimer(Location location, Runnable runnable, long delay, long period) {
|
|
||||||
return runTaskTimer(runnable, delay, period);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated: use {@link #runTaskLater(Runnable, long)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default MyScheduledTask scheduleSyncDelayedTask(Runnable runnable, long delay) {
|
|
||||||
return runTaskLater(runnable, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated: use {@link #execute(Runnable)} or {@link #runTask(Runnable)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default MyScheduledTask scheduleSyncDelayedTask(Runnable runnable) {
|
|
||||||
return runTask(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated: use {@link #runTaskTimer(Runnable, long, long)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default MyScheduledTask scheduleSyncRepeatingTask(Runnable runnable, long delay, long period) {
|
|
||||||
return runTaskTimer(runnable, delay, period);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Folia & Paper</b>: Schedules a task to be executed on the region which owns the location
|
|
||||||
* of given entity on the next tick
|
|
||||||
* <p>
|
|
||||||
* <b>Bukkit</b>: same as {@link #runTask(Runnable)}
|
|
||||||
*
|
|
||||||
* @param entity The entity whose location the region executing should own
|
|
||||||
* @param runnable The task to execute
|
|
||||||
*/
|
|
||||||
default MyScheduledTask runTask(Entity entity, Runnable runnable) {
|
|
||||||
return runTask(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Folia & Paper</b>: Schedules a task to be executed on the region which owns the location
|
|
||||||
* of given entity after the specified delay in ticks
|
|
||||||
* <p>
|
|
||||||
* <b>Bukkit</b>: same as {@link #runTaskLater(Runnable, long)}
|
|
||||||
*
|
|
||||||
* @param entity The entity whose location the region executing should own
|
|
||||||
* @param runnable The task to execute
|
|
||||||
* @param delay The delay, in ticks.
|
|
||||||
*/
|
|
||||||
default MyScheduledTask runTaskLater(Entity entity, Runnable runnable, long delay) {
|
|
||||||
return runTaskLater(runnable, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <b>Folia & Paper</b>: Schedules a repeating task to be executed on the region which owns the
|
|
||||||
* location of given entity after the initial delay with the specified period
|
|
||||||
* <p>
|
|
||||||
* <b>Bukkit</b>: same as {@link #runTaskTimer(Runnable, long, long)}
|
|
||||||
*
|
|
||||||
* @param entity The entity whose location the region executing should own
|
|
||||||
* @param runnable The task to execute
|
|
||||||
* @param delay The initial delay, in ticks.
|
|
||||||
* @param period The period, in ticks.
|
|
||||||
*/
|
|
||||||
default MyScheduledTask runTaskTimer(Entity entity, Runnable runnable, long delay, long period) {
|
|
||||||
return runTaskTimer(runnable, delay, period);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules the specified task to be executed asynchronously immediately
|
|
||||||
*
|
|
||||||
* @param runnable The task to execute
|
|
||||||
* @return The {@link MyScheduledTask} that represents the scheduled task
|
|
||||||
*/
|
|
||||||
MyScheduledTask runTaskAsynchronously(Runnable runnable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules the specified task to be executed asynchronously after the time delay has passed
|
|
||||||
*
|
|
||||||
* @param runnable The task to execute
|
|
||||||
* @param delay The time delay to pass before the task should be executed
|
|
||||||
* @return The {@link MyScheduledTask} that represents the scheduled task
|
|
||||||
*/
|
|
||||||
MyScheduledTask runTaskLaterAsynchronously(Runnable runnable, long delay);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules the specified task to be executed asynchronously after the initial delay has passed,
|
|
||||||
* and then periodically executed with the specified period
|
|
||||||
*
|
|
||||||
* @param runnable The task to execute
|
|
||||||
* @param delay The time delay to pass before the first execution of the task, in ticks
|
|
||||||
* @param period The time between task executions after the first execution of the task, in ticks
|
|
||||||
* @return The {@link MyScheduledTask} that represents the scheduled task
|
|
||||||
*/
|
|
||||||
MyScheduledTask runTaskTimerAsynchronously(Runnable runnable, long delay, long period);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated: use {@link #runTaskAsynchronously(Runnable)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default MyScheduledTask runTaskAsynchronously(Plugin plugin, Runnable runnable) {
|
|
||||||
return runTaskAsynchronously(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated: use {@link #runTaskLaterAsynchronously(Runnable, long)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default MyScheduledTask runTaskLaterAsynchronously(Plugin plugin, Runnable runnable, long delay) {
|
|
||||||
return runTaskLaterAsynchronously(runnable, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deprecated: use {@link #runTaskTimerAsynchronously(Runnable, long, long)}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
default MyScheduledTask runTaskTimerAsynchronously(Plugin plugin, Runnable runnable, long delay, long period) {
|
|
||||||
return runTaskTimerAsynchronously(runnable, delay, period);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls a method on the main thread and returns a Future object. This task will be executed
|
|
||||||
* by the main(Bukkit)/global(Folia&Paper) server thread.
|
|
||||||
* <p>
|
|
||||||
* Note: The Future.get() methods must NOT be called from the main thread.
|
|
||||||
* <p>
|
|
||||||
* Note2: There is at least an average of 10ms latency until the isDone() method returns true.
|
|
||||||
*
|
|
||||||
* @param task Task to be executed
|
|
||||||
*/
|
|
||||||
default <T> Future<T> callSyncMethod(final Callable<T> task) {
|
|
||||||
CompletableFuture<T> completableFuture = new CompletableFuture<>();
|
|
||||||
execute(() -> {
|
|
||||||
try {
|
|
||||||
completableFuture.complete(task.call());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return completableFuture;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules a task to be executed on the global region
|
|
||||||
*
|
|
||||||
* @param runnable The task to execute
|
|
||||||
*/
|
|
||||||
void execute(Runnable runnable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules a task to be executed on the region which owns the location
|
|
||||||
*
|
|
||||||
* @param location The location which the region executing should own
|
|
||||||
* @param runnable The task to execute
|
|
||||||
*/
|
|
||||||
default void execute(Location location, Runnable runnable) {
|
|
||||||
execute(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedules a task to be executed on the region which owns the location of given entity
|
|
||||||
*
|
|
||||||
* @param entity The entity which location the region executing should own
|
|
||||||
* @param runnable The task to execute
|
|
||||||
*/
|
|
||||||
default void execute(Entity entity, Runnable runnable) {
|
|
||||||
execute(runnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to cancel all tasks scheduled by this plugin
|
|
||||||
*/
|
|
||||||
void cancelTasks();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to cancel all tasks scheduled by the specified plugin
|
|
||||||
*
|
|
||||||
* @param plugin specified plugin
|
|
||||||
*/
|
|
||||||
void cancelTasks(Plugin plugin);
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* MIT License
|
|
||||||
*
|
|
||||||
* Copyright (c) 2023 Sevastjan
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
* a copy of this software and associated documentation files (the "Software"),
|
|
||||||
* to deal in the Software without restriction, including without limitation
|
|
||||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
* and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
* Software is furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
||||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
||||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.clip.placeholderapi.scheduler.scheduling.tasks;
|
|
||||||
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
|
|
||||||
public interface MyScheduledTask {
|
|
||||||
/**
|
|
||||||
* Cancels executing task
|
|
||||||
*/
|
|
||||||
void cancel();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if task is cancelled, false otherwise
|
|
||||||
*/
|
|
||||||
boolean isCancelled();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The plugin under which the task was scheduled.
|
|
||||||
*/
|
|
||||||
Plugin getOwningPlugin();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if task is currently executing, false otherwise
|
|
||||||
*/
|
|
||||||
boolean isCurrentlyRunning();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if task is repeating, false otherwise
|
|
||||||
*/
|
|
||||||
boolean isRepeatingTask();
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package me.clip.placeholderapi.scheduler.utils;
|
|
||||||
|
|
||||||
public class JavaUtil {
|
|
||||||
public static boolean classExists(String className) {
|
|
||||||
try {
|
|
||||||
Class.forName(className);
|
|
||||||
return true;
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,7 +26,6 @@ import java.net.URL;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.scheduler.scheduling.schedulers.TaskScheduler;
|
|
||||||
import me.clip.placeholderapi.util.Msg;
|
import me.clip.placeholderapi.util.Msg;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@@ -36,17 +35,15 @@ import org.bukkit.event.player.PlayerJoinEvent;
|
|||||||
|
|
||||||
public class UpdateChecker implements Listener {
|
public class UpdateChecker implements Listener {
|
||||||
|
|
||||||
private static final int RESOURCE_ID = 6245;
|
private final int RESOURCE_ID = 6245;
|
||||||
private final PlaceholderAPIPlugin plugin;
|
private final PlaceholderAPIPlugin plugin;
|
||||||
private final TaskScheduler scheduler;
|
|
||||||
private final String pluginVersion;
|
private final String pluginVersion;
|
||||||
private String spigotVersion;
|
private String spigotVersion;
|
||||||
private boolean updateAvailable;
|
private boolean updateAvailable;
|
||||||
|
|
||||||
public UpdateChecker(PlaceholderAPIPlugin plugin) {
|
public UpdateChecker(PlaceholderAPIPlugin i) {
|
||||||
this.plugin = plugin;
|
plugin = i;
|
||||||
scheduler = plugin.getScheduler();
|
pluginVersion = i.getDescription().getVersion();
|
||||||
pluginVersion = plugin.getDescription().getVersion();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasUpdateAvailable() {
|
public boolean hasUpdateAvailable() {
|
||||||
@@ -58,7 +55,7 @@ public class UpdateChecker implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void fetch() {
|
public void fetch() {
|
||||||
scheduler.runTaskAsynchronously(() -> {
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||||
try {
|
try {
|
||||||
HttpsURLConnection con = (HttpsURLConnection) new URL(
|
HttpsURLConnection con = (HttpsURLConnection) new URL(
|
||||||
"https://api.spigotmc.org/legacy/update.php?resource=" + RESOURCE_ID).openConnection();
|
"https://api.spigotmc.org/legacy/update.php?resource=" + RESOURCE_ID).openConnection();
|
||||||
@@ -79,7 +76,7 @@ public class UpdateChecker implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduler.runTask(() -> {
|
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||||
plugin.getLogger()
|
plugin.getLogger()
|
||||||
.info("An update for PlaceholderAPI (v" + getSpigotVersion() + ") is available at:");
|
.info("An update for PlaceholderAPI (v" + getSpigotVersion() + ") is available at:");
|
||||||
plugin.getLogger()
|
plugin.getLogger()
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ import java.util.function.BiConsumer;
|
|||||||
import java.util.stream.Collector;
|
import java.util.stream.Collector;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -38,14 +36,14 @@ public final class Futures {
|
|||||||
private Futures() {}
|
private Futures() {}
|
||||||
|
|
||||||
|
|
||||||
public static <T> void onMainThread(@NotNull final PlaceholderAPIPlugin plugin,
|
public static <T> void onMainThread(@NotNull final Plugin plugin,
|
||||||
@NotNull final CompletableFuture<T> future,
|
@NotNull final CompletableFuture<T> future,
|
||||||
@NotNull final BiConsumer<T, Throwable> consumer) {
|
@NotNull final BiConsumer<T, Throwable> consumer) {
|
||||||
future.whenComplete((value, exception) -> {
|
future.whenComplete((value, exception) -> {
|
||||||
if (Bukkit.isPrimaryThread()) {
|
if (Bukkit.isPrimaryThread()) {
|
||||||
consumer.accept(value, exception);
|
consumer.accept(value, exception);
|
||||||
} else {
|
} else {
|
||||||
plugin.getScheduler().runTask(() -> consumer.accept(value, exception));
|
Bukkit.getScheduler().runTask(plugin, () -> consumer.accept(value, exception));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
name: PlaceholderAPI
|
name: PlaceholderAPI
|
||||||
main: "me.clip.placeholderapi.PlaceholderAPIPlugin"
|
main: "me.clip.placeholderapi.PlaceholderAPIPlugin"
|
||||||
folia-supported: true
|
|
||||||
|
|
||||||
version: ${version}
|
version: ${version}
|
||||||
author: HelpChat
|
author: HelpChat
|
||||||
|
|||||||
Reference in New Issue
Block a user