Compare commits

...
34 Commits
Author SHA1 Message Date
Warrior 736171a3ae Run smite with entity scheduler 2026-05-03 13:35:38 -07:00
Warrior eb9b7dc74c Modify thunder on global thread 2026-05-03 13:35:38 -07:00
Warrior bb0f9f3c51 Fix retrieving tile entity count for gc command 2026-05-03 13:35:38 -07:00
Warrior 853ac1ea4b Fix merge artifact (?) 2026-05-03 13:35:38 -07:00
Warrior e7461bfd38 Run kill command on entity thread 2026-05-03 13:35:38 -07:00
JRoy 63dcfa2333 sure 2026-02-28 15:20:36 -08:00
JRoy 4423bc824e Merge branch '2.x' into fork/Warriorrrr/feat/folia/merge-2.x-changes
# Conflicts:
#	Essentials/src/main/java/com/earth2me/essentials/Essentials.java
#	Essentials/src/main/java/com/earth2me/essentials/commands/Commandessentials.java
2026-02-28 15:19:54 -08:00
Warrior b30021321a Move economy layers initialization to after providers
EconomyLayers relies on the scheduler to be initialized to enable properly
2026-02-13 20:12:00 +01:00
Warrior 00e35092ad Update scheduling providers to work with new provider system 2026-02-13 19:59:33 +01:00
Warrior 25685a8a64 Merge branch '2.x' into feat/folia/merge-2.x-changes 2026-02-13 19:39:46 +01:00
Josh Roy d73ed137fa Fix time/weather commands 2023-08-22 12:12:33 -04:00
Josh Roy d0493ccd2a Merge remote-tracking branch 'upstream/2.x' into refactor/folia
# Conflicts:
#	Essentials/src/main/java/com/earth2me/essentials/commands/Commandskull.java
2023-08-22 11:37:36 -04:00
Josh Roy 0c8bc16c3d Fix time command 2023-07-27 19:59:56 -04:00
Josh Roy d4ebaf61d4 Fix weather command 2023-07-27 19:38:32 -04:00
Josh Roy 1a108b5e2e Bump folia version 2023-07-27 19:35:45 -04:00
Josh Roy 10fc005652 Merge remote-tracking branch 'upstream/2.x' into refactor/folia
# Conflicts:
#	EssentialsDiscord/src/main/java/net/essentialsx/discord/util/ConsoleInjector.java
2023-07-27 19:30:00 -04:00
Josh Roy 4256909eee Fix folia init tasks never getting called LOLW 2023-04-26 21:28:33 -04:00
Josh Roy 9133dce3eb Merge branch '2.x' into refactor/folia 2023-04-15 20:34:56 -04:00
Josh Roy ec5007c07e fix wrong period/timeunit for folia scheduling 2023-04-12 18:45:22 -04:00
Josh Roy 4cb861badc Run interaction commands async for now (hopefully okay) 2023-04-02 21:11:55 -04:00
Josh Roy 7279be7850 allow DiscordMessageEvent calls from any context 2023-04-02 20:58:56 -04:00
Josh Roy 2ba1eb0cf9 fix "Fix moo" 2023-04-01 17:42:38 -04:00
Josh Roy 7216fddfbe Add helper methods for ensuring thread contexts 2023-03-30 13:40:13 -04:00
Josh Roy 2d8cc827b9 Add method for checking the global thread 2023-03-30 13:31:16 -04:00
Josh Roy 4ff9286a79 Move over some discord things 2023-03-30 13:28:41 -04:00
Josh Roy 9a5ac3cad8 Fix tests 2023-03-30 13:20:29 -04:00
Josh Roy 05a8aa8883 Switch to Paper repo 2023-03-30 13:06:35 -04:00
Josh Roy 1d93ebfddd Fix moo 2023-03-29 19:59:30 -04:00
Josh Roy 04683ee43b Fix async entity dismounts 2023-03-29 19:57:57 -04:00
Josh Roy a649f978c5 Add some thread checking helper methods
pending PaperMC/Folia#5 for global region helpers
2023-03-28 21:57:24 -04:00
Josh Roy 20882940c5 Actually fire init tasks in Folia 2023-03-28 21:30:51 -04:00
Josh Roy 07fbf93001 Ensure nuke commands runs on correct threads 2023-03-28 21:23:27 -04:00
Josh Roy 0e4bab24cb Get like 70% of the plugin to work 2023-03-27 23:31:39 -04:00
Josh Roy 15c48d457a Add Folia providers 2023-03-27 23:29:42 -04:00
58 changed files with 683 additions and 229 deletions

No files matched your search

+2
View File
@@ -25,6 +25,7 @@ dependencies {
api(project(path: ':providers:PaperProvider', configuration: 'shadow')){
exclude(module: 'paper-api')
}
api project(':providers:FoliaProvider')
api(project(':providers:NMSReflectionProvider')) {
exclude(module: 'bukkit')
}
@@ -73,6 +74,7 @@ shadowJar {
include (dependency('net.kyori:adventure-text-minimessage'))
include (project(':providers:BaseProviders'))
include (project(path: ':providers:PaperProvider', configuration: 'shadow'))
include (project(':providers:FoliaProvider'))
include (project(':providers:NMSReflectionProvider'))
include (project(':providers:1_8Provider'))
include (project(':providers:1_12Provider'))
@@ -139,19 +139,6 @@ public class AsyncTeleport implements IAsyncTeleport {
paperFuture.exceptionally(future::completeExceptionally);
}
private void runOnMain(final Runnable runnable) throws ExecutionException, InterruptedException {
if (Bukkit.isPrimaryThread()) {
runnable.run();
return;
}
final CompletableFuture<Object> taskLock = new CompletableFuture<>();
Bukkit.getScheduler().runTask(ess, () -> {
runnable.run();
taskLock.complete(new Object());
});
taskLock.get();
}
protected void nowAsync(final IUser teleportee, final ITarget target, final TeleportCause cause, final CompletableFuture<Boolean> future) {
cancel(false);
@@ -169,8 +156,8 @@ public class AsyncTeleport implements IAsyncTeleport {
}
try {
runOnMain(() -> teleportee.getBase().eject()); //EntityDismountEvent requires a sync context.
} catch (final ExecutionException | InterruptedException e) {
ess.ensureEntity(teleportee.getBase(), () -> teleportee.getBase().eject()); //EntityDismountEvent requires a sync context.
} catch (final RuntimeException e) {
future.completeExceptionally(e);
return;
}
@@ -190,8 +177,7 @@ public class AsyncTeleport implements IAsyncTeleport {
if (LocationUtil.isBlockUnsafeForUser(ess, teleportee, chunk.getWorld(), loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())) {
if (ess.getSettings().isTeleportSafetyEnabled()) {
if (ess.getSettings().isForceDisableTeleportSafety()) {
//The chunk we're teleporting to is 100% going to be loaded here, no need to teleport async.
teleportee.getBase().teleport(loc, cause);
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
} else {
try {
//There's a chance the safer location is outside the loaded chunk so still teleport async here.
@@ -207,8 +193,7 @@ public class AsyncTeleport implements IAsyncTeleport {
}
} else {
if (ess.getSettings().isForceDisableTeleportSafety()) {
//The chunk we're teleporting to is 100% going to be loaded here, no need to teleport async.
teleportee.getBase().teleport(loc, cause);
PaperLib.teleportAsync(teleportee.getBase(), loc, cause);
} else {
if (ess.getSettings().isTeleportToCenterLocation()) {
loc = LocationUtil.getRoundedDestination(loc);
@@ -1,13 +1,14 @@
package com.earth2me.essentials;
import net.ess3.api.IEssentials;
import net.ess3.api.IUser;
import net.ess3.provider.SchedulingProvider;
import org.bukkit.Location;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import org.bukkit.Location;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import net.ess3.api.IEssentials;
import net.ess3.api.IUser;
import net.essentialsx.api.v2.events.TeleportWarmupCancelledEvent;
import net.essentialsx.api.v2.events.TeleportWarmupCancelledEvent.CancelReason;
@@ -31,7 +32,7 @@ public class AsyncTimedTeleport implements Runnable {
private final boolean timer_canMove;
private final Trade timer_chargeFor;
private final TeleportCause timer_cause;
private int timer_task;
private SchedulingProvider.EssentialsTask timer_task;
private double timer_health;
AsyncTimedTeleport(final IUser user, final IEssentials ess, final AsyncTeleport teleport, final long delay, final IUser teleportUser, final ITarget target, final Trade chargeFor, final TeleportCause cause, final boolean respawn) {
@@ -55,7 +56,7 @@ public class AsyncTimedTeleport implements Runnable {
this.timer_respawn = respawn;
this.timer_canMove = user.isAuthorized("essentials.teleport.timer.move");
timer_task = ess.runTaskTimerAsynchronously(this, 20, 20).getTaskId();
timer_task = ess.runTaskTimerAsynchronously(this, 20, 20);
if (future != null) {
this.parentFuture = future;
@@ -142,16 +143,16 @@ public class AsyncTimedTeleport implements Runnable {
}
}
ess.scheduleSyncDelayedTask(new DelayedTeleportTask());
ess.scheduleEntityDelayedTask(teleportOwner.getBase(), new DelayedTeleportTask());
}
//If we need to cancelTimer a pending teleportPlayer call this method
void cancelTimer(final boolean notifyUser) {
if (timer_task == -1) {
if (timer_task == null) {
return;
}
try {
ess.getServer().getScheduler().cancelTask(timer_task);
timer_task.cancel();
final IUser teleportUser = ess.getUser(this.timer_teleportee);
if (teleportUser != null && teleportUser.getBase() != null) {
@@ -167,7 +168,7 @@ public class AsyncTimedTeleport implements Runnable {
}
}
} finally {
timer_task = -1;
timer_task = null;
}
}
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials;
import net.ess3.api.IEssentials;
import net.ess3.provider.SchedulingProvider;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
@@ -18,7 +19,7 @@ public class Backup implements Runnable {
private transient final IEssentials ess;
private final AtomicBoolean pendingShutdown = new AtomicBoolean(false);
private transient boolean running = false;
private transient int taskId = -1;
private transient SchedulingProvider.EssentialsTask task = null;
private transient boolean active = false;
private transient CompletableFuture<Object> taskLock = null;
@@ -36,10 +37,10 @@ public class Backup implements Runnable {
public synchronized void stopTask() {
running = false;
if (taskId != -1) {
server.getScheduler().cancelTask(taskId);
if (task != null) {
task.cancel();
}
taskId = -1;
task = null;
}
private synchronized void startTask() {
@@ -48,7 +49,7 @@ public class Backup implements Runnable {
if (interval < 1200) {
return;
}
taskId = ess.scheduleSyncRepeatingTask(this, interval, interval);
task = ess.scheduleGlobalRepeatingTask(this, interval, interval);
running = true;
}
}
@@ -123,7 +124,7 @@ public class Backup implements Runnable {
}
if (!pendingShutdown.get()) {
ess.scheduleSyncDelayedTask(new BackupEnableSaveTask());
ess.scheduleGlobalDelayedTask(new BackupEnableSaveTask());
}
}
});
@@ -28,6 +28,7 @@ import com.earth2me.essentials.commands.NoChargeException;
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
import com.earth2me.essentials.commands.PlayerNotFoundException;
import com.earth2me.essentials.commands.QuietAbortException;
import com.earth2me.essentials.config.EssentialsConfiguration;
import com.earth2me.essentials.economy.EconomyLayers;
import com.earth2me.essentials.economy.vault.VaultEconomyProvider;
import com.earth2me.essentials.items.AbstractItemDb;
@@ -49,7 +50,6 @@ import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.VersionUtil;
import io.papermc.lib.PaperLib;
import net.ess3.api.Economy;
import com.earth2me.essentials.config.EssentialsConfiguration;
import net.ess3.api.IEssentials;
import net.ess3.api.IItemDb;
import net.ess3.api.IJails;
@@ -68,15 +68,19 @@ import net.ess3.provider.InventoryViewProvider;
import net.ess3.provider.KnownCommandsProvider;
import net.ess3.provider.PlayerLocaleProvider;
import net.ess3.provider.ProviderListener;
import net.ess3.provider.SchedulingProvider;
import net.ess3.provider.ServerStateProvider;
import net.ess3.provider.providers.BaseBannerDataProvider;
import net.ess3.provider.providers.BaseInventoryViewProvider;
import net.ess3.provider.providers.BlockMetaSpawnerItemProvider;
import net.ess3.provider.providers.BukkitMaterialTagProvider;
import net.ess3.provider.providers.BukkitSchedulingProvider;
import net.ess3.provider.providers.BukkitSpawnerBlockProvider;
import net.ess3.provider.providers.BukkitTileEntityProvider;
import net.ess3.provider.providers.BukkitWorldTileEntityCountProvider;
import net.ess3.provider.providers.FixedHeightWorldInfoProvider;
import net.ess3.provider.providers.FlatSpawnEggProvider;
import net.ess3.provider.providers.FoliaSchedulingProvider;
import net.ess3.provider.providers.LegacyBannerDataProvider;
import net.ess3.provider.providers.LegacyBiomeNameProvider;
import net.ess3.provider.providers.LegacyDamageEventProvider;
@@ -102,10 +106,12 @@ import net.ess3.provider.providers.PaperSerializationProvider;
import net.ess3.provider.providers.PaperServerStateProvider;
import net.ess3.provider.providers.PaperTickCountProvider;
import net.ess3.provider.providers.PaperTileEntityProvider;
import net.ess3.provider.providers.PaperWorldTileEntityCountProvider;
import net.ess3.provider.providers.PrehistoricPotionMetaProvider;
import net.essentialsx.api.v2.services.BalanceTop;
import net.essentialsx.api.v2.services.mail.MailService;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.block.Block;
@@ -115,6 +121,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.EventHandler;
@@ -129,8 +136,6 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicePriority;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import java.util.ArrayList;
import java.util.Collection;
@@ -143,6 +148,8 @@ import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -322,9 +329,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
confList.add(jails);
execTimer.mark("Init(Jails)");
EconomyLayers.onEnable(this);
execTimer.mark("Init(EconomyLayers)");
// Spawner item provider only uses one, but it's here for legacy...
providerFactory.registerProvider(BlockMetaSpawnerItemProvider.class);
@@ -394,10 +398,16 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
// Tile Entity Provider
providerFactory.registerProvider(BukkitTileEntityProvider.class, PaperTileEntityProvider.class);
// World Tile Entity Count Provider
providerFactory.registerProvider(BukkitWorldTileEntityCountProvider.class, PaperWorldTileEntityCountProvider.class);
// Tick Count Provider
providerFactory.registerProvider(PaperTickCountProvider.class);
if (!TESTING) {
// Scheduling provider
providerFactory.registerProvider(FoliaSchedulingProvider.class, BukkitSchedulingProvider.class);
if (!TESTING || true) { // FIXME: The scheduling provider is necessary for tests to pass without adding checks for TESTING everywhere
providerFactory.finalizeRegistration();
}
@@ -418,6 +428,12 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
execTimer.mark("Init(Providers)");
EconomyLayers.onEnable(this);
execTimer.mark("Init(EconomyLayers)");
registerListeners(getServer().getPluginManager());
initAdventureFacet();
reload();
// The item spawn blacklist is loaded with all other settings, before the item
@@ -428,7 +444,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
alternativeCommandsHandler = new AlternativeCommandsHandler(this);
timer = new EssentialsTimer(this);
scheduleSyncRepeatingTask(timer, 1000, 50);
scheduleGlobalRepeatingTask(timer, 1000, 50);
Economy.setEss(this);
execTimer.mark("RegHandler");
@@ -481,8 +497,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
private void registerListeners(final PluginManager pm) {
HandlerList.unregisterAll(this);
if (getSettings().isDebug()) {
LOGGER.log(Level.INFO, "Registering Listeners");
}
@@ -602,9 +616,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
}
final PluginManager pm = getServer().getPluginManager();
registerListeners(pm);
initAdventureFacet();
}
@@ -898,11 +909,6 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
}
@Override
public BukkitScheduler getScheduler() {
return this.getServer().getScheduler();
}
@Override
public IJails getJails() {
return jails;
@@ -1226,33 +1232,135 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
}
@Override
public BukkitTask runTaskAsynchronously(final Runnable run) {
return this.getScheduler().runTaskAsynchronously(this, run);
public void scheduleInitTask(Runnable runnable) {
provider(SchedulingProvider.class).registerInitTask(runnable);
}
@Override
public BukkitTask runTaskLaterAsynchronously(final Runnable run, final long delay) {
return this.getScheduler().runTaskLaterAsynchronously(this, run, delay);
public void runTaskAsynchronously(final Runnable run) {
provider(SchedulingProvider.class).runAsyncTask(run);
}
@Override
public BukkitTask runTaskTimerAsynchronously(final Runnable run, final long delay, final long period) {
return this.getScheduler().runTaskTimerAsynchronously(this, run, delay, period);
public void runTaskLaterAsynchronously(final Runnable run, final long delay) {
provider(SchedulingProvider.class).runAsyncTaskLater(run, delay);
}
@Override
public int scheduleSyncDelayedTask(final Runnable run) {
return this.getScheduler().scheduleSyncDelayedTask(this, run);
public SchedulingProvider.EssentialsTask runTaskTimerAsynchronously(final Runnable run, final long delay, final long period) {
return provider(SchedulingProvider.class).runAsyncTaskRepeating(run, delay, period);
}
@Override
public int scheduleSyncDelayedTask(final Runnable run, final long delay) {
return this.getScheduler().scheduleSyncDelayedTask(this, run, delay);
public void scheduleEntityDelayedTask(Entity entity, Runnable run) {
provider(SchedulingProvider.class).runEntityTask(entity, run);
}
@Override
public int scheduleSyncRepeatingTask(final Runnable run, final long delay, final long period) {
return this.getScheduler().scheduleSyncRepeatingTask(this, run, delay, period);
public SchedulingProvider.EssentialsTask scheduleEntityDelayedTask(Entity entity, Runnable run, long delay) {
return provider(SchedulingProvider.class).runEntityTask(entity, run, delay);
}
@Override
public SchedulingProvider.EssentialsTask scheduleEntityRepeatingTask(Entity entity, Runnable run, long delay, long period) {
return provider(SchedulingProvider.class).runEntityTaskRepeating(entity, run, delay, period);
}
@Override
public void scheduleLocationDelayedTask(Location location, Runnable run) {
provider(SchedulingProvider.class).runLocationalTask(location, run);
}
@Override
public void scheduleLocationDelayedTask(Location location, Runnable run, long delay) {
provider(SchedulingProvider.class).runLocationalTask(location, run, delay);
}
@Override
public SchedulingProvider.EssentialsTask scheduleLocationRepeatingTask(Location location, Runnable run, long delay, long period) {
return provider(SchedulingProvider.class).runLocationalTaskRepeating(location, run, delay, period);
}
@Override
public void scheduleGlobalDelayedTask(Runnable run, long delay) {
provider(SchedulingProvider.class).runGlobalLocationalTask(run, delay);
}
@Override
public SchedulingProvider.EssentialsTask scheduleGlobalRepeatingTask(Runnable run, long delay, long period) {
return provider(SchedulingProvider.class).runGlobalLocationalTaskRepeating(run, delay, period);
}
@Override
public boolean isEntityThread(Entity entity) {
return provider(SchedulingProvider.class).isEntityThread(entity);
}
@Override
public boolean isRegionThread(Location location) {
return provider(SchedulingProvider.class).isRegionThread(location);
}
@Override
public boolean isGlobalThread() {
return provider(SchedulingProvider.class).isGlobalThread();
}
@Override
public void ensureEntity(Entity entity, Runnable runnable) {
if (isEntityThread(entity)) {
runnable.run();
return;
}
final CompletableFuture<Object> taskLock = new CompletableFuture<>();
scheduleEntityDelayedTask(entity, () -> {
runnable.run();
taskLock.complete(new Object());
});
try {
taskLock.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
public void ensureRegion(Location location, Runnable runnable) {
if (isRegionThread(location)) {
runnable.run();
return;
}
final CompletableFuture<Object> taskLock = new CompletableFuture<>();
scheduleLocationDelayedTask(location, () -> {
runnable.run();
taskLock.complete(new Object());
});
try {
taskLock.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
public void ensureGlobal(Runnable runnable) {
if (isGlobalThread()) {
runnable.run();
return;
}
final CompletableFuture<Object> taskLock = new CompletableFuture<>();
scheduleGlobalDelayedTask(() -> {
runnable.run();
taskLock.complete(new Object());
});
try {
taskLock.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
@@ -44,7 +44,7 @@ public class EssentialsBlockListener implements Listener {
final User user = ess.getUser(event.getPlayer());
if (user.hasUnlimited(is) && user.getBase().getGameMode() == GameMode.SURVIVAL) {
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleEntityDelayedTask(user.getBase(), () -> {
if (is != null && is.getType() != null && !MaterialUtil.isAir(is.getType())) {
final ItemStack cloneIs = is.clone();
cloneIs.setAmount(1);
@@ -110,7 +110,7 @@ public class EssentialsEntityListener implements Listener {
}
}
ess.scheduleSyncDelayedTask(new PowerToolInteractTask());
ess.scheduleEntityDelayedTask(attacker.getBase(), new PowerToolInteractTask());
event.setCancelled(true);
return;
@@ -22,6 +22,7 @@ import io.papermc.paper.event.player.PlayerServerFullCheckEvent;
import net.ess3.api.IEssentials;
import net.ess3.api.events.AfkStatusChangeEvent;
import net.ess3.provider.CommandSendListenerProvider;
import net.ess3.provider.SchedulingProvider;
import net.ess3.provider.FormattedCommandAliasProvider;
import net.ess3.provider.InventoryViewProvider;
import net.ess3.provider.KnownCommandsProvider;
@@ -94,7 +95,7 @@ import static com.earth2me.essentials.I18n.tlLiteral;
public class EssentialsPlayerListener implements Listener {
private final transient IEssentials ess;
private final ConcurrentHashMap<UUID, Integer> pendingMotdTasks = new ConcurrentHashMap<>();
private final ConcurrentHashMap<UUID, SchedulingProvider.EssentialsTask> pendingMotdTasks = new ConcurrentHashMap<>();
public EssentialsPlayerListener(final IEssentials parent) {
this.ess = parent;
@@ -289,9 +290,9 @@ public class EssentialsPlayerListener implements Listener {
public void onPlayerQuit(final PlayerQuitEvent event) {
final User user = ess.getUser(event.getPlayer());
final Integer pendingId = pendingMotdTasks.remove(user.getUUID());
if (pendingId != null) {
ess.getScheduler().cancelTask(pendingId);
final SchedulingProvider.EssentialsTask pendingTask = pendingMotdTasks.remove(user.getUUID());
if (pendingTask != null) {
pendingTask.cancel();
}
if (hideJoinQuitMessages() || ess.getSettings().allowSilentJoinQuit() && user.isAuthorized("essentials.silentquit")) {
@@ -479,7 +480,7 @@ public class EssentialsPlayerListener implements Listener {
final int motdDelay = ess.getSettings().getMotdDelay() / 50;
final Runnable motdTask = () -> motdFlow(user);
if (motdDelay > 0) {
pendingMotdTasks.put(user.getUUID(), ess.scheduleSyncDelayedTask(motdTask, motdDelay));
pendingMotdTasks.put(user.getUUID(), ess.scheduleEntityDelayedTask(user.getBase(), motdTask, motdDelay));
} else {
motdTask.run();
}
@@ -581,7 +582,7 @@ public class EssentialsPlayerListener implements Listener {
dUser.updateActivity(false, AfkStatusChangeEvent.Cause.JOIN);
dUser.stopTransaction();
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleEntityDelayedTask(player, () -> {
final User user = ess.getUser(player);
if (!user.getBase().isOnline()) {
@@ -751,7 +752,7 @@ public class EssentialsPlayerListener implements Listener {
final User user = ess.getUser(event.getPlayer());
if (user.hasUnlimited(new ItemStack(event.getBucket()))) {
event.getItemStack().setType(event.getBucket());
ess.scheduleSyncDelayedTask(user.getBase()::updateInventory);
ess.scheduleEntityDelayedTask(user.getBase(), user.getBase()::updateInventory);
}
}
@@ -1012,7 +1013,7 @@ public class EssentialsPlayerListener implements Listener {
}
}
ess.scheduleSyncDelayedTask(new DelayedClickJumpTask());
ess.scheduleEntityDelayedTask(user.getBase(), new DelayedClickJumpTask());
} catch (final Exception ex) {
if (ess.getSettings().isDebug()) {
ess.getLogger().log(Level.WARNING, ex.getMessage(), ex);
@@ -1043,7 +1044,7 @@ public class EssentialsPlayerListener implements Listener {
}
}
ess.scheduleSyncDelayedTask(new PowerToolUseTask());
ess.scheduleEntityDelayedTask(user.getBase(), new PowerToolUseTask());
}
}
@@ -1105,7 +1106,7 @@ public class EssentialsPlayerListener implements Listener {
}
if (refreshPlayer != null) {
ess.scheduleSyncDelayedTask(refreshPlayer::updateInventory, 1);
ess.scheduleEntityDelayedTask(refreshPlayer, refreshPlayer::updateInventory, 1);
}
}
@@ -1168,7 +1169,7 @@ public class EssentialsPlayerListener implements Listener {
}
if (refreshPlayer != null) {
ess.scheduleSyncDelayedTask(refreshPlayer::updateInventory, 1);
ess.scheduleEntityDelayedTask(refreshPlayer, refreshPlayer::updateInventory, 1);
}
}
@@ -1192,7 +1193,7 @@ public class EssentialsPlayerListener implements Listener {
final Player player = event.getPlayer();
if (player.isFlying() && player.getAllowFlight() && user.isAuthorized("essentials.fly")) {
// The gamemode change happens after the event, so we need to delay the flight enable
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleEntityDelayedTask(player, () -> {
player.setAllowFlight(true);
player.setFlying(true);
}, 1);
@@ -5,7 +5,6 @@ import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
@@ -13,36 +12,19 @@ import java.util.logging.Level;
public class EssentialsTimer implements Runnable {
private final transient IEssentials ess;
private final transient Set<UUID> onlineUsers = new HashSet<>(); // Field is necessary for hidden users
private final LinkedList<Double> history = new LinkedList<>();
@SuppressWarnings("FieldCanBeLocal")
private final long maxTime = 10 * 1000000;
@SuppressWarnings("FieldCanBeLocal")
private final long tickInterval = 50;
private transient long lastPoll = System.nanoTime();
private static final long maxTime = 10 * 1000000;
private int skip1 = 0;
private int skip2 = 0;
EssentialsTimer(final IEssentials ess) {
this.ess = ess;
history.add(20d);
}
@Override
public void run() {
final long startTime = System.nanoTime();
final long currentTime = System.currentTimeMillis();
long timeSpent = (startTime - lastPoll) / 1000;
if (timeSpent == 0) {
timeSpent = 1;
}
if (history.size() > 10) {
history.remove();
}
final double tps = tickInterval * 1000000.0 / timeSpent;
if (tps <= 21) {
history.add(tps);
}
lastPoll = startTime;
int count = 0;
onlineUsers.clear();
for (final Player player : ess.getOnlinePlayers()) {
@@ -99,14 +81,4 @@ public class EssentialsTimer implements Runnable {
user.resetInvulnerabilityAfterTeleport();
}
}
public double getAverageTPS() {
double avg = 0;
for (final Double f : history) {
if (f != null) {
avg += f;
}
}
return avg / history.size();
}
}
@@ -9,18 +9,19 @@ import com.earth2me.essentials.commands.PlayerNotFoundException;
import com.earth2me.essentials.perm.PermissionsHandler;
import com.earth2me.essentials.updatecheck.UpdateChecker;
import com.earth2me.essentials.userstorage.IUserMap;
import net.ess3.provider.SchedulingProvider;
import net.ess3.provider.Provider;
import net.essentialsx.api.v2.services.BalanceTop;
import net.essentialsx.api.v2.services.mail.MailService;
import org.bukkit.Location;
import org.bukkit.Server;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;
import java.util.Collection;
import java.util.List;
@@ -80,8 +81,6 @@ public interface IEssentials extends Plugin {
ISettings getSettings();
BukkitScheduler getScheduler();
IJails getJails();
IWarps getWarps();
@@ -96,17 +95,45 @@ public interface IEssentials extends Plugin {
UpdateChecker getUpdateChecker();
BukkitTask runTaskAsynchronously(Runnable run);
void runTaskAsynchronously(Runnable run);
BukkitTask runTaskLaterAsynchronously(Runnable run, long delay);
void runTaskLaterAsynchronously(Runnable run, long delay);
BukkitTask runTaskTimerAsynchronously(Runnable run, long delay, long period);
SchedulingProvider.EssentialsTask runTaskTimerAsynchronously(Runnable run, long delay, long period);
int scheduleSyncDelayedTask(Runnable run);
void scheduleEntityDelayedTask(Entity entity, Runnable run);
int scheduleSyncDelayedTask(Runnable run, long delay);
SchedulingProvider.EssentialsTask scheduleEntityDelayedTask(Entity entity, Runnable run, long delay);
int scheduleSyncRepeatingTask(Runnable run, long delay, long period);
SchedulingProvider.EssentialsTask scheduleEntityRepeatingTask(Entity entity, Runnable run, long delay, long period);
void scheduleLocationDelayedTask(Location location, Runnable run);
void scheduleLocationDelayedTask(Location location, Runnable run, long delay);
SchedulingProvider.EssentialsTask scheduleLocationRepeatingTask(Location location, Runnable run, long delay, long period);
default void scheduleGlobalDelayedTask(Runnable run) {
scheduleGlobalDelayedTask(run, 1);
}
void scheduleGlobalDelayedTask(Runnable run, long delay);
SchedulingProvider.EssentialsTask scheduleGlobalRepeatingTask(Runnable run, long delay, long period);
void scheduleInitTask(Runnable runnable);
boolean isEntityThread(Entity entity);
boolean isRegionThread(Location location);
boolean isGlobalThread();
void ensureEntity(Entity entity, Runnable runnable);
void ensureRegion(Location location, Runnable runnable);
void ensureGlobal(Runnable runnable);
PermissionsHandler getPermissionsHandler();
@@ -156,7 +156,7 @@ public class RandomTeleport implements IConf {
// Prompts caching random valid locations, up to a maximum number of attempts.
public void cacheRandomLocations(final String name) {
ess.getServer().getScheduler().scheduleSyncDelayedTask(ess, () -> {
ess.runTaskAsynchronously(() -> {
for (int i = 0; i < this.getFindAttempts(); ++i) {
calculateRandomLocation(getCenter(name), getMinRange(name), getMaxRange(name)).thenAccept(location -> {
if (isValidRandomLocation(location)) {
@@ -186,7 +186,6 @@ public class RandomTeleport implements IConf {
// Calculates a random location asynchronously.
private CompletableFuture<Location> calculateRandomLocation(final Location center, final double minRange, final double maxRange) {
final CompletableFuture<Location> future = new CompletableFuture<>();
// Find an equally distributed offset by randomly rotating a point inside a rectangle about the origin
final double rectX = RANDOM.nextDouble() * (maxRange - minRange) + minRange;
final double rectZ = RANDOM.nextDouble() * (maxRange + minRange) - minRange;
@@ -214,15 +213,14 @@ public class RandomTeleport implements IConf {
360 * RANDOM.nextFloat() - 180,
0
);
PaperLib.getChunkAtAsync(location).thenAccept(chunk -> {
return PaperLib.getChunkAtAsync(location).thenApply(chunk -> { // FIXME: use thenApplyAsync + an Executor that runs tasks on the correct region thread to be fully safe.
if (World.Environment.NETHER.equals(center.getWorld().getEnvironment())) {
location.setY(getNetherYAt(location));
} else {
location.setY(center.getWorld().getHighestBlockYAt(location) + HIGHEST_BLOCK_Y_OFFSET);
}
future.complete(location);
return location;
});
return future;
}
// Returns an appropriate elevation for a given location in the nether, or MIN_VALUE if none is found
@@ -837,7 +837,7 @@ public class Settings implements net.ess3.api.ISettings {
if (reloadCount.get() < 2) {
// on startup: add plugins again in case they registered commands with the new API
// we need to schedule this task before any of the below tasks using _addAlternativeCommand.
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleGlobalDelayedTask(() -> {
for (final Plugin plugin : ess.getServer().getPluginManager().getPlugins()) {
if (plugin.isEnabled()) {
ess.getAlternativeCommandsHandler().addPlugin(plugin);
@@ -863,7 +863,7 @@ public class Settings implements net.ess3.api.ISettings {
// This is 2 because Settings are reloaded twice in the startup lifecycle
if (reloadCount.get() < 2) {
ess.scheduleSyncDelayedTask(() -> _addAlternativeCommand(effectiveAlias, toDisable));
ess.scheduleGlobalDelayedTask(() -> _addAlternativeCommand(effectiveAlias, toDisable));
} else {
_addAlternativeCommand(effectiveAlias, toDisable);
}
@@ -878,7 +878,7 @@ public class Settings implements net.ess3.api.ISettings {
ess.getLogger().log(Level.INFO, "Syncing commands");
}
if (reloadCount.get() < 2) {
ess.scheduleSyncDelayedTask(syncCommandsProvider::syncCommands);
ess.scheduleGlobalDelayedTask(syncCommandsProvider::syncCommands);
} else {
syncCommandsProvider.syncCommands();
}
@@ -821,7 +821,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
public void updateActivityOnChat(final boolean broadcast) {
if (ess.getSettings().cancelAfkOnChat()) {
//Chat happens async, make sure we have a sync context
ess.scheduleSyncDelayedTask(() -> updateActivity(broadcast, AfkStatusChangeEvent.Cause.CHAT));
ess.scheduleEntityDelayedTask(base, () -> updateActivity(broadcast, AfkStatusChangeEvent.Cause.CHAT));
}
}
@@ -44,7 +44,7 @@ public class Commandbalancetop extends EssentialsCommand {
new TextPager(cache).showPage(Integer.toString(page), null, "balancetop", sender);
};
if (sender.getSender() instanceof BlockCommandSender) {
ess.scheduleSyncDelayedTask(runnable);
ess.scheduleGlobalDelayedTask(runnable);
} else {
runnable.run();
}
@@ -23,7 +23,7 @@ public class Commandbeezooka extends EssentialsCommand {
final Entity bee = Mob.BEE.spawn(user.getWorld(), server, user.getBase().getEyeLocation());
bee.setVelocity(user.getBase().getEyeLocation().getDirection().multiply(2));
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleEntityDelayedTask(bee, () -> {
final Location loc = bee.getLocation();
bee.remove();
loc.getWorld().createExplosion(loc, 0F);
@@ -3,15 +3,13 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.provider.TileEntityProvider;
import net.ess3.provider.WorldTileEntityCountProvider;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Server;
import org.bukkit.World;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.logging.Level;
public class Commandgc extends EssentialsCommand {
public Commandgc() {
@@ -20,7 +18,7 @@ public class Commandgc extends EssentialsCommand {
@Override
protected void run(final Server server, final CommandSource sender, final String commandLabel, final String[] args) throws Exception {
final double tps = ess.getTimer().getAverageTPS();
final double tps = 20d; //TODO
final ChatColor color;
if (tps >= 18.0) {
color = ChatColor.GREEN;
@@ -37,7 +35,7 @@ public class Commandgc extends EssentialsCommand {
sender.sendTl("gcfree", Runtime.getRuntime().freeMemory() / 1024 / 1024);
final List<World> worlds = server.getWorlds();
final TileEntityProvider tileEntityProvider = ess.provider(TileEntityProvider.class);
final WorldTileEntityCountProvider worldTileEntityCountProvider = ess.provider(WorldTileEntityCountProvider.class);
for (final World w : worlds) {
String worldType = "World";
switch (w.getEnvironment()) {
@@ -49,15 +47,7 @@ public class Commandgc extends EssentialsCommand {
break;
}
int tileEntities = 0;
try {
for (final Chunk chunk : w.getLoadedChunks()) {
tileEntities += tileEntityProvider.getTileEntities(chunk).length;
}
} catch (final java.lang.ClassCastException ex) {
ess.getLogger().log(Level.SEVERE, "Corrupted chunk data on world " + w, ex);
}
final int tileEntities = worldTileEntityCountProvider.getTileEntityCount(w);
sender.sendTl("gcWorld", worldType, w.getName(), w.getLoadedChunks().length, w.getEntities().size(), tileEntities);
}
@@ -32,13 +32,15 @@ public class Commandkill extends EssentialsLoopCommand {
}
final DamageEventProvider provider = ess.provider(DamageEventProvider.class);
final EntityDamageEvent ede = provider.callDamageEvent(matchPlayer, sender.isPlayer() && sender.getPlayer().getName().equals(matchPlayer.getName()) ? EntityDamageEvent.DamageCause.SUICIDE : EntityDamageEvent.DamageCause.CUSTOM, Float.MAX_VALUE);
if (ede.isCancelled() && sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.kill.force")) {
return;
}
ede.getEntity().setLastDamageCause(ede);
matchPlayer.setHealth(0);
sender.sendTl("kill", matchPlayer.getDisplayName());
ess.scheduleEntityDelayedTask(matchPlayer, () -> {
final EntityDamageEvent ede = provider.callDamageEvent(matchPlayer, sender.isPlayer() && sender.getPlayer().getName().equals(matchPlayer.getName()) ? EntityDamageEvent.DamageCause.SUICIDE : EntityDamageEvent.DamageCause.CUSTOM, Float.MAX_VALUE);
if (ede.isCancelled() && sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.kill.force")) {
return;
}
ede.getEntity().setLastDamageCause(ede);
matchPlayer.setHealth(0);
sender.sendTl("kill", matchPlayer.getDisplayName());
});
}
@Override
@@ -49,7 +49,7 @@ public class Commandkittycannon extends EssentialsCommand {
@Override
protected void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final Entity ocelot = Mob.CAT.getType() == null ? spawnOcelot(server, user) : spawnCat(server, user);
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleEntityDelayedTask(ocelot, () -> {
final Location loc = ocelot.getLocation();
ocelot.remove();
loc.getWorld().createExplosion(loc, 0F);
@@ -33,15 +33,17 @@ public class Commandlightning extends EssentialsLoopCommand {
}
final int finalPower = power;
loopOnlinePlayersConsumer(server, sender, false, true, args[0], player -> {
sender.sendTl("lightningUse", player.getDisplayName());
final LightningStrike strike = player.getBase().getWorld().strikeLightningEffect(player.getBase().getLocation());
ess.scheduleEntityDelayedTask(player.getBase(), () -> {
sender.sendTl("lightningUse", player.getDisplayName());
final LightningStrike strike = player.getBase().getWorld().strikeLightningEffect(player.getBase().getLocation());
if (!player.isGodModeEnabled()) {
player.getBase().damage(finalPower, strike);
}
if (ess.getSettings().warnOnSmite()) {
player.sendTl("lightningSmited");
}
if (!player.isGodModeEnabled()) {
player.getBase().damage(finalPower, strike);
}
if (ess.getSettings().warnOnSmite()) {
player.sendTl("lightningSmited");
}
});
});
loopOnlinePlayers(server, sender, true, true, args[0], null);
}
@@ -35,17 +35,20 @@ public class Commandnuke extends EssentialsCommand {
if (user == null) {
continue;
}
user.sendTl("nuke");
final Location loc = user.getLocation();
final World world = loc.getWorld();
if (world != null) {
for (int x = -10; x <= 10; x += 5) {
for (int z = -10; z <= 10; z += 5) {
final TNTPrimed entity = world.spawn(new Location(world, loc.getBlockX() + x, world.getHighestBlockYAt(loc) + 64, loc.getBlockZ() + z), TNTPrimed.class);
entity.setMetadata(NUKE_META_KEY, new FixedMetadataValue(ess, true));
ess.scheduleEntityDelayedTask(user.getBase(), () -> {
user.sendTl("nuke");
final Location loc = user.getLocation();
final World world = loc.getWorld();
if (world != null) {
for (int x = -10; x <= 10; x += 5) {
for (int z = -10; z <= 10; z += 5) {
final TNTPrimed entity = world.spawn(new Location(world, loc.getBlockX() + x, world.getHighestBlockYAt(loc) + 64, loc.getBlockZ() + z), TNTPrimed.class);
entity.setMetadata(NUKE_META_KEY, new FixedMetadataValue(ess, true));
}
}
}
}
});
}
}
@@ -61,7 +61,7 @@ public class Commandseen extends EssentialsCommand {
return;
}
}
ess.getScheduler().runTaskAsynchronously(ess, new Runnable() {
ess.runTaskAsynchronously(new Runnable() {
@Override
public void run() {
final User userFromBukkit = ess.getUsers().getUser(args[0]);
@@ -159,7 +159,7 @@ public class Commandskull extends EssentialsCommand {
final String shortNameFinal = shortOwnerName;
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleEntityDelayedTask(user.getBase(), () -> {
stack.setItemMeta(skullMeta);
if (spawn) {
Inventories.addItem(receive.getBase(), stack);
@@ -53,7 +53,7 @@ public class Commandsudo extends EssentialsLoopCommand {
}
}
ess.scheduleSyncDelayedTask(new SudoCommandTask());
ess.scheduleEntityDelayedTask(user.getBase(), new SudoCommandTask());
}
}
}
@@ -22,13 +22,15 @@ public class Commandthunder extends EssentialsCommand {
final World world = user.getWorld();
final boolean setThunder = args[0].equalsIgnoreCase("true");
if (args.length == 1) {
world.setThundering(setThunder);
ess.scheduleGlobalDelayedTask(() -> world.setThundering(setThunder));
user.sendTl("thunder", setThunder ? user.playerTl("enabled") : user.playerTl("disabled"));
return;
}
world.setThundering(setThunder);
world.setThunderDuration(Integer.parseInt(args[1]) * 20);
ess.scheduleGlobalDelayedTask(() -> {
world.setThundering(setThunder);
world.setThunderDuration(Integer.parseInt(args[1]) * 20);
});
user.sendTl("thunderDuration", setThunder ? user.playerTl("enabled") : user.playerTl("disabled"), Integer.parseInt(args[1]));
}
@@ -81,13 +81,16 @@ public class Commandtime extends EssentialsCommand {
}
final StringJoiner joiner = new StringJoiner(", ");
final boolean timeAdd = add;
for (final World world : worlds) {
long time = world.getTime();
if (!add) {
time -= time % 24000;
}
world.setTime(time + (add ? 0 : 24000) + timeTick);
joiner.add(world.getName());
ess.scheduleGlobalDelayedTask(() -> {
long time = world.getTime();
if (!timeAdd) {
time -= time % 24000;
}
world.setTime(time + (timeAdd ? 0 : 24000) + timeTick);
});
}
sender.sendTl(add ? "timeWorldAdd" : "timeWorldSet", DescParseTickFormat.formatTicks(timeTick), joiner.toString());
@@ -30,16 +30,18 @@ public class Commandweather extends EssentialsCommand {
isStorm = args[0].equalsIgnoreCase("storm");
}
final World world = user.getWorld();
ess.scheduleGlobalDelayedTask(() -> {
final World world = user.getWorld();
if (args.length > 1) {
if (args.length > 1) {
world.setStorm(isStorm);
world.setWeatherDuration(Integer.parseInt(args[1]) * 20);
user.sendTl(isStorm ? "weatherStormFor" : "weatherSunFor", world.getName(), args[1]);
return;
}
world.setStorm(isStorm);
world.setWeatherDuration(Integer.parseInt(args[1]) * 20);
user.sendTl(isStorm ? "weatherStormFor" : "weatherSunFor", world.getName(), args[1]);
return;
}
world.setStorm(isStorm);
user.sendTl(isStorm ? "weatherStorm" : "weatherSun", world.getName());
user.sendTl(isStorm ? "weatherStorm" : "weatherSun", world.getName());
});
}
@Override
@@ -54,14 +56,16 @@ public class Commandweather extends EssentialsCommand {
throw new TranslatableException("weatherInvalidWorld", args[0]);
}
if (args.length > 2) {
ess.scheduleLocationDelayedTask(world.getSpawnLocation(), () -> {
if (args.length > 2) {
world.setStorm(isStorm);
world.setWeatherDuration(Integer.parseInt(args[2]) * 20);
sender.sendTl(isStorm ? "weatherStormFor" : "weatherSunFor", world.getName(), args[2]);
return;
}
world.setStorm(isStorm);
world.setWeatherDuration(Integer.parseInt(args[2]) * 20);
sender.sendTl(isStorm ? "weatherStormFor" : "weatherSunFor", world.getName(), args[2]);
return;
}
world.setStorm(isStorm);
sender.sendTl(isStorm ? "weatherStorm" : "weatherSun", world.getName());
sender.sendTl(isStorm ? "weatherStorm" : "weatherSun", world.getName());
});
}
@Override
@@ -32,7 +32,7 @@ public final class EconomyLayers {
}
public static void onEnable(final Essentials ess) {
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleInitTask(() -> {
serverStarted = true;
for (final Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
if (!plugin.isEnabled()) {
@@ -346,7 +346,7 @@ public class KeywordReplacer implements IText {
}
break;
case TPS:
replacer = NumberUtil.formatDouble(ess.getTimer().getAverageTPS());
replacer = NumberUtil.formatDouble(20d); //todo
break;
case UPTIME:
replacer = DateUtil.formatDateDiff(ManagementFactory.getRuntimeMXBean().getStartTime());
@@ -50,6 +50,7 @@ public final class VersionUtil {
private static final Set<BukkitVersion> supportedVersions = ImmutableSet.of(v1_8_8_R01, v1_9_4_R01, v1_10_2_R01, v1_11_2_R01, v1_12_2_R01, v1_13_2_R01, v1_14_4_R01, v1_15_2_R01, v1_16_5_R01, v1_17_1_R01, v1_18_2_R01, v1_19_4_R01, v1_20_6_R01, v1_21_11_R01);
public static final boolean PRE_FLATTENING = VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01);
public static final boolean FOLIA;
public static final List<String> officialPlugins = Arrays.asList(
"EssentialsAntiBuild",
@@ -75,6 +76,15 @@ public final class VersionUtil {
private static final String PFX = make("8(;4>`");
static {
boolean isFolia;
try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
isFolia = true;
} catch (Throwable ignored) {
isFolia = false;
}
FOLIA = isFolia;
final ImmutableMap.Builder<String, SupportStatus> builder = new ImmutableMap.Builder<>();
// Leaf, yet another "High Performance" fork of Paper. Not supported by EssentialsX.
@@ -1523,6 +1523,7 @@ versionErrorPlayer=<primary>Error while checking EssentialsX version information
versionFetching=<primary>Fetching version information...
versionOutputVaultMissing=<dark_red>Vault is not installed. Chat and permissions may not work.
versionOutputFine=<primary>{0} version\: <green>{1}
versionOutputFlags=<primary>Feature Flags: <green>{0}
versionOutputWarn=<primary>{0} version\: <secondary>{1}
versionOutputUnsupported=<light_purple>{0} <primary>version\: <light_purple>{1}
versionOutputUnsupportedPlugins=<primary>You are running <light_purple>unsupported plugins<primary>\!
+1
View File
@@ -7,6 +7,7 @@ description: Provides an essential, core set of commands for Bukkit.
softdepend: [Vault, LuckPerms]
authors: [Zenexer, ementalo, Aelux, Brettflan, KimKandor, snowleo, ceulemans, Xeology, KHobbits, md_5, Iaccidentally, drtshock, vemacs, SupaHam, mdcfe, JRoy, pop4959]
api-version: "1.13"
folia-supported: true
commands:
afk:
description: Marks you as away-from-keyboard.
@@ -7,7 +7,7 @@ description: Provides build protection.
authors: [Zenexer, ementalo, Aelux, Brettflan, KimKandor, snowleo, ceulemans, Xeology, KHobbits, Iaccidentally, drtshock, mdcfe]
depend: [Essentials]
api-version: "1.13"
folia-supported: true
permissions:
essentials.build:
description: Allows the bearer to build
@@ -7,6 +7,7 @@ description: Provides chat control features for Essentials. Requires Permission
authors: [Zenexer, ementalo, Aelux, Brettflan, KimKandor, snowleo, ceulemans, Xeology, KHobbits, md_5, Okamosy, Iaccidentally, mdcfe, JRoy, triagonal]
depend: [Essentials]
api-version: 1.13
folia-supported: true
commands:
toggleshout:
description: Toggles whether you are talking in shout mode
@@ -1,6 +1,7 @@
package net.essentialsx.api.v2.events.discord;
import net.essentialsx.api.v2.services.discord.MessageType;
import org.bukkit.Bukkit;
import org.bukkit.event.Cancellable;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
@@ -10,6 +11,8 @@ import java.util.UUID;
/**
* Fired before a message is about to be sent to a Discord channel.
* <p>
* Note: This event has no guarantee of the thread it is fired on, please use {@link #isAsynchronous()}} to see if this event is off the main Bukkit thread.
*/
public class DiscordMessageEvent extends Event implements Cancellable {
private static final HandlerList handlers = new HandlerList();
@@ -40,6 +43,7 @@ public class DiscordMessageEvent extends Event implements Cancellable {
* @param uuid The UUID of the player which caused this event or null if this wasn't a player triggered event.
*/
public DiscordMessageEvent(final MessageType type, final String message, final boolean allowGroupMentions, final String avatarUrl, final String name, final UUID uuid) {
super(!Bukkit.isPrimaryThread());
this.type = type;
this.message = message;
this.allowGroupMentions = allowGroupMentions;
@@ -60,7 +60,7 @@ public class EssentialsDiscord extends JavaPlugin implements IEssentialsModule {
jda = new JDADiscordService(this);
try {
jda.startup();
ess.scheduleSyncDelayedTask(() -> ((InteractionControllerImpl) jda.getInteractionController()).processBatchRegistration());
ess.scheduleInitTask(() -> ((InteractionControllerImpl) jda.getInteractionController()).processBatchRegistration());
} catch (Exception e) {
getLogger().log(Level.SEVERE, ess.getAdventureFacet().miniToLegacy(tlLiteral("discordErrorLogin", e.getMessage())));
if (ess.getSettings().isDebug()) {
@@ -260,7 +260,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
logger.log(Level.WARNING, "Error while loading the achievement/advancement listener. You will not receive achievement/advancement notifications on Discord.", e);
}
getPlugin().getEss().scheduleSyncDelayedTask(() -> DiscordUtil.dispatchDiscordMessage(JDADiscordService.this, MessageType.DefaultTypes.SERVER_START, getSettings().getStartMessage(), true, null, null, null));
getPlugin().getEss().scheduleInitTask(() -> DiscordUtil.dispatchDiscordMessage(JDADiscordService.this, MessageType.DefaultTypes.SERVER_START, getSettings().getStartMessage(), true, null, null, null));
Bukkit.getServicesManager().register(DiscordService.class, this, plugin, ServicePriority.Normal);
}
@@ -289,11 +289,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
logger.warning("Sending message to channel \"" + type.getKey() + "\" which is an unregistered type! If you are a plugin author, you should be registering your MessageType before using them.");
}
final DiscordMessageEvent event = new DiscordMessageEvent(type, FormatUtil.stripFormat(message), allowGroupMentions);
if (Bukkit.getServer().isPrimaryThread()) {
Bukkit.getPluginManager().callEvent(event);
} else {
Bukkit.getScheduler().runTask(plugin, () -> Bukkit.getPluginManager().callEvent(event));
}
Bukkit.getPluginManager().callEvent(event);
}
@Override
@@ -64,7 +64,8 @@ public class InteractionControllerImpl extends ListenerAdapter implements Intera
interactionEvent.replyTl("noAccessCommand");
return;
}
jda.getPlugin().getEss().scheduleSyncDelayedTask(() -> command.onCommand(interactionEvent));
command.onCommand(interactionEvent);
}
@Override
@@ -22,7 +22,7 @@ public class ExecuteCommand extends InteractionCommandImpl {
public void onCommand(final InteractionEvent event) {
final String command = event.getStringArgument("command");
event.replyTl("discordCommandExecuteReply", command);
Bukkit.getScheduler().runTask(jda.getPlugin(), () -> {
jda.getPlugin().getEss().scheduleGlobalDelayedTask(() -> {
try {
Bukkit.dispatchCommand(new DiscordCommandSender(jda, Bukkit.getConsoleSender(), message -> event.reply(MessageUtil.sanitizeDiscordMarkdown(message))).getSender(), command);
} catch (CommandException e) {
@@ -30,7 +30,7 @@ public class DiscordCommandDispatcher extends ListenerAdapter {
}
final String command = event.getMessage().getContentRaw();
Bukkit.getScheduler().runTask(jda.getPlugin(), () -> {
jda.getPlugin().getEss().scheduleGlobalDelayedTask(() -> {
try {
Bukkit.dispatchCommand(new DiscordCommandSender(jda, Bukkit.getConsoleSender(), message ->
event.getMessage().reply(message).queue()).getSender(), command);
@@ -4,6 +4,7 @@ import com.earth2me.essentials.utils.FormatUtil;
import com.google.common.base.Splitter;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.utils.TimeFormat;
import net.ess3.provider.SchedulingProvider;
import net.essentialsx.discord.EssentialsDiscord;
import net.essentialsx.discord.JDADiscordService;
import org.apache.logging.log4j.LogManager;
@@ -11,7 +12,6 @@ import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.bukkit.Bukkit;
import java.time.Instant;
import java.util.concurrent.BlockingQueue;
@@ -30,7 +30,7 @@ public class ConsoleInjector extends AbstractAppender {
private final JDADiscordService jda;
private final BlockingQueue<String> messageQueue = new LinkedBlockingQueue<>();
private final int taskId;
private final SchedulingProvider.EssentialsTask task;
private boolean removed = false;
private final AtomicLong lastRateLimitTime = new AtomicLong(0);
@@ -41,7 +41,7 @@ public class ConsoleInjector extends AbstractAppender {
super("EssentialsX-ConsoleInjector", null, null, false);
this.jda = jda;
((Logger) LogManager.getRootLogger()).addAppender(this);
taskId = Bukkit.getScheduler().runTaskTimerAsynchronously(jda.getPlugin(), () -> {
task = jda.getPlugin().getEss().runTaskTimerAsynchronously(() -> {
// Check to see if we're supposed to be backing off, preform backoff if the case.
if (recentRateLimit.get() < 0) {
if (totalBackoffEvents.get() * 20 >= jda.getSettings().getConsoleSkipDelay() * 60) {
@@ -60,7 +60,6 @@ public class ConsoleInjector extends AbstractAppender {
}
return;
}
final StringBuilder buffer = new StringBuilder();
String curLine;
while ((curLine = messageQueue.peek()) != null) {
@@ -74,7 +73,7 @@ public class ConsoleInjector extends AbstractAppender {
if (buffer.length() != 0) {
sendMessage(buffer.toString());
}
}, 20, 20 * QUEUE_PROCESS_PERIOD_SECONDS).getTaskId();
}, 20, 20 * QUEUE_PROCESS_PERIOD_SECONDS);
}
private void sendMessage(String content) {
@@ -148,7 +147,7 @@ public class ConsoleInjector extends AbstractAppender {
public void remove() {
((Logger) LogManager.getRootLogger()).removeAppender(this);
Bukkit.getScheduler().cancelTask(taskId);
task.cancel();
messageQueue.clear();
if (jda.getConsoleWebhook() != null && !jda.getConsoleWebhook().isShutdown()) {
jda.getConsoleWebhook().close();
@@ -2,17 +2,16 @@ package net.essentialsx.discord.util;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.provider.SchedulingProvider;
import net.ess3.provider.providers.BukkitSenderProvider;
import net.ess3.provider.providers.PaperCommandSender;
import net.essentialsx.discord.JDADiscordService;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.scheduler.BukkitTask;
public class DiscordCommandSender {
private final CommandSender sender;
private BukkitTask task;
private SchedulingProvider.EssentialsTask task;
private String responseBuffer = "";
private long lastTime = System.currentTimeMillis();
@@ -23,7 +22,7 @@ public class DiscordCommandSender {
};
this.sender = getCustomSender(sender, hook);
task = Bukkit.getScheduler().runTaskTimerAsynchronously(jda.getPlugin(), () -> {
task = jda.getPlugin().getEss().runTaskTimerAsynchronously(() -> {
if (!responseBuffer.isEmpty() && System.currentTimeMillis() - lastTime >= 1000) {
callback.onMessage(responseBuffer);
responseBuffer = "";
@@ -242,10 +242,6 @@ public final class DiscordUtil {
return;
}
if (Bukkit.getServer().isPrimaryThread()) {
Bukkit.getPluginManager().callEvent(event);
} else {
Bukkit.getScheduler().runTask(jda.getPlugin(), () -> Bukkit.getPluginManager().callEvent(event));
}
Bukkit.getPluginManager().callEvent(event);
}
}
@@ -8,6 +8,7 @@ authors: [mdcfe, JRoy, pop4959, Glare]
depend: [Essentials]
softdepend: [EssentialsChat, PlaceholderAPI]
api-version: 1.13
folia-supported: true
commands:
discordbroadcast:
description: Broadcasts a message to the specified Discord channel.
@@ -137,7 +137,7 @@ public class AccountLinkManager implements IEssentialsModule, DiscordLinkService
runnable.run();
return;
}
ess.getEss().scheduleSyncDelayedTask(runnable);
ess.getEss().scheduleGlobalDelayedTask(runnable);
}
private void ensureAsync(final Runnable runnable) {
@@ -163,7 +163,7 @@ public class LinkBukkitListener implements Listener {
if (Bukkit.isPrimaryThread()) {
kickTask.run();
} else {
ess.getEss().scheduleSyncDelayedTask(kickTask);
ess.getEss().scheduleEntityDelayedTask(event.getUser().getBase(), kickTask);
}
break;
}
@@ -7,6 +7,7 @@ description: EssentialsX Discord addon which allows you link your Minecraft and
authors: [JRoy]
depend: [EssentialsDiscord]
api-version: 1.13
folia-supported: true
commands:
link:
description: Generates a code to link your Minecraft account to Discord.
@@ -7,6 +7,8 @@ description: Shows the country or city of a user on login and /whois.
authors: [Zenexer, ementalo, Aelux, Brettflan, KimKandor, snowleo, ceulemans, Xeology, kjiang, pop4959]
depend: [Essentials]
api-version: 1.13
folia-supported: true
permissions:
essentials.geoip.show:
description: Shows the country or city of a user on login and /whois.
@@ -7,6 +7,8 @@ description: Provides protection for various parts of the world.
authors: [Zenexer, ementalo, Aelux, Brettflan, KimKandor, snowleo, ceulemans, Xeology, KHobbits, drtshock]
softdepend: [Essentials]
api-version: 1.13
folia-supported: true
permissions:
essentials.protect.entitytarget.bypass:
description: Allows the bearer to be targeted by entities
@@ -88,7 +88,7 @@ class EssentialsSpawnPlayerListener implements Listener {
final User user = ess.getUser(player);
if (ess.getSettings().isUserInSpawnOnJoinGroup(user) && !user.isAuthorized("essentials.spawn-on-join.exempt")) {
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleEntityDelayedTask(player, () -> {
final Location spawn = spawns.getSpawn(user.getGroup());
if (spawn == null) {
return;
@@ -111,10 +111,10 @@ class EssentialsSpawnPlayerListener implements Listener {
final boolean spawnRandomly = tryRandomTeleport(user, ess.getSettings().getRandomSpawnLocation());
if (!spawnRandomly && !"none".equalsIgnoreCase(ess.getSettings().getNewbieSpawn())) {
ess.scheduleSyncDelayedTask(new NewPlayerTeleport(user), 1L);
ess.scheduleEntityDelayedTask(player, new NewPlayerTeleport(user), 1L);
}
ess.scheduleSyncDelayedTask(() -> {
ess.scheduleEntityDelayedTask(player, () -> {
if (!user.getBase().isOnline()) {
return;
}
@@ -7,6 +7,7 @@ description: Provides spawn control commands, utilizing Essentials.
authors: [Zenexer, ementalo, Aelux, Brettflan, KimKandor, snowleo, ceulemans, Xeology, KHobbits, SupaHam, mdcfe, DoNotSpamPls, JRoy]
depend: [Essentials]
api-version: 1.13
folia-supported: true
commands:
setspawn:
description: Sets the spawn point to your current position.
@@ -0,0 +1,40 @@
package net.ess3.provider;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
public interface SchedulingProvider extends Provider {
void registerInitTask(Runnable runnable);
boolean isEntityThread(Entity entity);
boolean isRegionThread(Location location);
boolean isGlobalThread();
void runEntityTask(Entity entity, Runnable runnable);
EssentialsTask runEntityTask(Entity entity, Runnable runnable, long delay);
EssentialsTask runEntityTaskRepeating(Entity entity, Runnable runnable, long delay, long period);
void runLocationalTask(Location location, Runnable runnable);
void runLocationalTask(Location location, Runnable runnable, long delay);
EssentialsTask runLocationalTaskRepeating(Location location, Runnable runnable, long delay, long period);
void runGlobalLocationalTask(Runnable runnable, long delay);
EssentialsTask runGlobalLocationalTaskRepeating(Runnable runnable, long delay, long period);
void runAsyncTask(Runnable runnable);
void runAsyncTaskLater(Runnable runnable, long delay);
EssentialsTask runAsyncTaskRepeating(Runnable runnable, long delay, long period);
interface EssentialsTask {
void cancel();
}
}
@@ -0,0 +1,7 @@
package net.ess3.provider;
import org.bukkit.World;
public interface WorldTileEntityCountProvider extends Provider {
int getTileEntityCount(final World world);
}
@@ -0,0 +1,104 @@
package net.ess3.provider.providers;
import net.ess3.provider.SchedulingProvider;
import net.essentialsx.providers.ProviderData;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitTask;
@ProviderData(description = "Bukkit Scheduling Provider")
public class BukkitSchedulingProvider implements SchedulingProvider {
private final Plugin plugin;
public BukkitSchedulingProvider(final Plugin plugin) {
this.plugin = plugin;
}
@Override
public void registerInitTask(Runnable runnable) {
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, runnable);
}
@Override
public boolean isEntityThread(Entity entity) {
return plugin.getServer().isPrimaryThread();
}
@Override
public boolean isRegionThread(Location location) {
return plugin.getServer().isPrimaryThread();
}
@Override
public boolean isGlobalThread() {
return Bukkit.isPrimaryThread();
}
@Override
public void runEntityTask(Entity entity, Runnable runnable) {
runEntityTask(entity, runnable, 1);
}
@Override
public EssentialsTask runEntityTask(Entity entity, Runnable runnable, long delay) {
return scheduleSyncTask(runnable, delay);
}
@Override
public EssentialsTask runEntityTaskRepeating(Entity entity, Runnable runnable, long delay, long period) {
return scheduleSyncTaskRepeating(runnable, delay, period);
}
@Override
public void runLocationalTask(Location location, Runnable runnable) {
runGlobalLocationalTask(runnable, 1);
}
@Override
public void runLocationalTask(Location location, Runnable runnable, long delay) {
runGlobalLocationalTask(runnable, delay);
}
@Override
public EssentialsTask runLocationalTaskRepeating(Location location, Runnable runnable, long delay, long period) {
return scheduleSyncTaskRepeating(runnable, delay, period);
}
@Override
public void runGlobalLocationalTask(Runnable runnable, long delay) {
scheduleSyncTask(runnable, delay);
}
@Override
public EssentialsTask runGlobalLocationalTaskRepeating(Runnable runnable, long delay, long period) {
return scheduleSyncTaskRepeating(runnable, delay, period);
}
private EssentialsTask scheduleSyncTask(Runnable runnable, long delay) {
final int task = plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, runnable, delay);
return () -> plugin.getServer().getScheduler().cancelTask(task);
}
private EssentialsTask scheduleSyncTaskRepeating(Runnable runnable, long delay, long period) {
final BukkitTask task = plugin.getServer().getScheduler().runTaskTimer(plugin, runnable, delay, period);
return task::cancel;
}
@Override
public void runAsyncTask(Runnable runnable) {
runAsyncTaskLater(runnable, 0);
}
@Override
public void runAsyncTaskLater(Runnable runnable, long delay) {
plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, runnable, delay);
}
@Override
public EssentialsTask runAsyncTaskRepeating(Runnable runnable, long delay, long period) {
final BukkitTask task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period);
return task::cancel;
}
}
@@ -0,0 +1,20 @@
package net.ess3.provider.providers;
import net.ess3.provider.WorldTileEntityCountProvider;
import net.essentialsx.providers.ProviderData;
import org.bukkit.Chunk;
import org.bukkit.World;
@ProviderData(description = "Bukkit World Tile Entity Count Provider")
public class BukkitWorldTileEntityCountProvider implements WorldTileEntityCountProvider {
@Override
public int getTileEntityCount(World world) {
int tileEntities = 0;
for (final Chunk chunk : world.getLoadedChunks()) {
tileEntities += chunk.getTileEntities().length;
}
return tileEntities;
}
}
+19
View File
@@ -0,0 +1,19 @@
plugins {
id("essentials.base-conventions")
}
java {
disableAutoTargetJvm()
}
dependencies {
implementation(project(':providers:BaseProviders')) {
exclude(module: 'spigot-api')
}
compileOnly 'dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT'
}
essentials {
injectBukkitApi.set(false)
injectBstats.set(false)
}
@@ -0,0 +1,134 @@
package net.ess3.provider.providers;
import io.papermc.paper.threadedregions.RegionizedServerInitEvent;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
import net.ess3.provider.SchedulingProvider;
import net.essentialsx.providers.ProviderData;
import net.essentialsx.providers.ProviderTest;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@ProviderData(description = "Folia Scheduling Provider")
public class FoliaSchedulingProvider implements SchedulingProvider, Listener {
private final Plugin plugin;
private List<Runnable> initTasks = new ArrayList<>();
public FoliaSchedulingProvider(Plugin plugin) {
this.plugin = plugin;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
@EventHandler
public void onServerInit(RegionizedServerInitEvent event) {
for (final Runnable tasks : initTasks) {
tasks.run();
}
initTasks = null;
}
@Override
public void registerInitTask(Runnable runnable) {
if (initTasks == null) {
throw new IllegalStateException();
}
initTasks.add(runnable);
}
@Override
public boolean isEntityThread(Entity entity) {
return plugin.getServer().isOwnedByCurrentRegion(entity);
}
@Override
public boolean isRegionThread(Location location) {
return plugin.getServer().isOwnedByCurrentRegion(location);
}
@Override
public boolean isGlobalThread() {
return plugin.getServer().isGlobalTickThread();
}
@Override
public void runEntityTask(Entity entity, Runnable runnable) {
runEntityTask(entity, runnable, 1);
}
@Override
public EssentialsTask runEntityTask(Entity entity, Runnable runnable, long delay) {
final ScheduledTask task = entity.getScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), null, delay);
if (task == null) {
throw new IllegalArgumentException("entity is removed!");
}
return task::cancel;
}
@Override
public EssentialsTask runEntityTaskRepeating(Entity entity, Runnable runnable, long delay, long period) {
final ScheduledTask task = entity.getScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), null, delay, period);
if (task == null) {
throw new IllegalArgumentException("entity is removed!");
}
return task::cancel;
}
@Override
public void runLocationalTask(Location location, Runnable runnable) {
plugin.getServer().getRegionScheduler().execute(plugin, location, runnable);
}
@Override
public void runLocationalTask(Location location, Runnable runnable, long delay) {
plugin.getServer().getRegionScheduler().runDelayed(plugin, location, scheduledTask -> runnable.run(), delay);
}
@Override
public EssentialsTask runLocationalTaskRepeating(Location location, Runnable runnable, long delay, long period) {
final ScheduledTask task = plugin.getServer().getRegionScheduler().runAtFixedRate(plugin, location, scheduledTask -> runnable.run(), delay, period);;
return task::cancel;
}
@Override
public void runGlobalLocationalTask(Runnable runnable, long delay) {
plugin.getServer().getGlobalRegionScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), delay);
}
@Override
public EssentialsTask runGlobalLocationalTaskRepeating(Runnable runnable, long delay, long period) {
final ScheduledTask task = plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), delay, period);
return task::cancel;
}
@Override
public void runAsyncTask(Runnable runnable) {
plugin.getServer().getAsyncScheduler().runNow(plugin, scheduledTask -> runnable.run());
}
@Override
public void runAsyncTaskLater(Runnable runnable, long delay) {
plugin.getServer().getAsyncScheduler().runDelayed(plugin, scheduledTask -> runnable.run(), delay * 50L, TimeUnit.MILLISECONDS);
}
@Override
public EssentialsTask runAsyncTaskRepeating(Runnable runnable, long delay, long period) {
final ScheduledTask task = plugin.getServer().getAsyncScheduler().runAtFixedRate(plugin, scheduledTask -> runnable.run(), delay, period * 50, TimeUnit.MILLISECONDS);
return task::cancel;
}
@ProviderTest
public static boolean test() {
try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}
@@ -0,0 +1,13 @@
package net.ess3.provider.providers;
import net.ess3.provider.WorldTileEntityCountProvider;
import net.essentialsx.providers.ProviderData;
import org.bukkit.World;
@ProviderData(description = "Paper 1.11+ World Tile Entity Count Provider", weight = 1)
public class PaperWorldTileEntityCountProvider implements WorldTileEntityCountProvider {
@Override
public int getTileEntityCount(World world) {
return world.getTileEntityCount();
}
}
+1
View File
@@ -58,5 +58,6 @@ sequenceOf(
include(":providers:BaseProviders")
include(":providers:NMSReflectionProvider")
include(":providers:PaperProvider")
include(":providers:FoliaProvider")
include(":providers:1_8Provider")
include(":providers:1_12Provider")