diff --git a/pom.xml b/pom.xml index 89e622b..3de2a3d 100644 --- a/pom.xml +++ b/pom.xml @@ -246,9 +246,9 @@ - org.spigotmc - spigot-api - 1.19-R0.1-SNAPSHOT + dev.folia + folia-api + 1.19.4-R0.1-SNAPSHOT provided diff --git a/resources/plugin.yml b/resources/plugin.yml index 99ea4f8..6260f06 100644 --- a/resources/plugin.yml +++ b/resources/plugin.yml @@ -4,6 +4,7 @@ main: com.dre.brewery.P softdepend: [LWC, LogBlock, WorldGuard, GriefPrevention, Vault, ChestShop, Shopkeepers, Towny, BlockLocker, Slimefun] authors: [Milan Albrecht, Frank Baumann, ProgrammerDan, Daniel Saukel] api-version: 1.13 +folia-supported: true commands: brewery: description: Mostly admin commands to create/modify Brews and drunkeness diff --git a/src/com/dre/brewery/BCauldron.java b/src/com/dre/brewery/BCauldron.java index a98ec1a..1c8818f 100644 --- a/src/com/dre/brewery/BCauldron.java +++ b/src/com/dre/brewery/BCauldron.java @@ -24,6 +24,7 @@ import org.mini2Dx.gettext.GetText; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; public class BCauldron { public enum LiquidType { @@ -60,8 +61,8 @@ public static LiquidType fromString(String string) { public static final byte EMPTY = 0, SOME = 1, FULL = 2; public static final int PARTICLEPAUSE = 15; public static Random particleRandom = new Random(); - private static Set plInteracted = new HashSet<>(); // Interact Event helper - public static Map bcauldrons = new HashMap<>(); // All active cauldrons. Mapped to their block for fast retrieve + private static Set plInteracted = ConcurrentHashMap.newKeySet(); // Interact Event helper + public static Map bcauldrons = new ConcurrentHashMap<>(); // All active cauldrons. Mapped to their block for fast retrieve private BIngredients ingredients = new BIngredients(); private final Block block; @@ -294,7 +295,12 @@ public static void printTime(Player player, Block block) { } public void cookEffect() { - if (BUtil.isChunkLoaded(block) && LegacyUtil.isCauldronHeatsource(block.getRelative(BlockFace.DOWN))) { + P.p.scheduler.runTaskAt(block.getLocation(), sched -> { + boolean valid = BUtil.isChunkLoaded(block) && LegacyUtil.isCauldronHeatsource(block.getRelative(BlockFace.DOWN)); + if (!valid) { + return; + } + Color color = getParticleColor(); // Colorable spirally spell, 0 count enables color instead of the offset variables // Configurable RGB color. The last parameter seems to control the hue and motion, but i couldn't find @@ -323,7 +329,7 @@ public void cookEffect() { // Two hovering pixely dust clouds, a bit offset and with DustOptions to give some color and size block.getWorld().spawnParticle(Particle.REDSTONE, particleLocation, 2, 0.15, 0.2, 0.15, new Particle.DustOptions(color, 1.5f)); } - } + }, 0); } private Location getRandParticleLoc() { @@ -486,7 +492,7 @@ public static void clickCauldron(PlayerInteractEvent event) { if (event.getHand() == EquipmentSlot.HAND) { final UUID id = player.getUniqueId(); plInteracted.add(id); - P.p.getServer().getScheduler().runTask(P.p, () -> plInteracted.remove(id)); + P.p.scheduler.runTaskFor(event.getPlayer(), sched -> plInteracted.remove(id), 0); } else if (event.getHand() == EquipmentSlot.OFF_HAND) { if (!plInteracted.remove(player.getUniqueId())) { item = player.getInventory().getItemInMainHand(); @@ -608,7 +614,7 @@ public static void save(ConfigurationSection config, ConfigurationSection oldDat // bukkit bug not updating the inventory while executing event, have to // schedule the give public static void giveItem(final Player player, final ItemStack item) { - P.p.getServer().getScheduler().runTaskLater(P.p, () -> player.getInventory().addItem(item), 1L); + P.p.scheduler.runTaskFor(player, sched -> player.getInventory().addItem(item), 1L); } } diff --git a/src/com/dre/brewery/BDistiller.java b/src/com/dre/brewery/BDistiller.java index bdafa87..1a67acf 100644 --- a/src/com/dre/brewery/BDistiller.java +++ b/src/com/dre/brewery/BDistiller.java @@ -1,6 +1,8 @@ package com.dre.brewery; import com.dre.brewery.lore.BrewLore; +import com.dre.brewery.utility.BTask; + import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; @@ -14,6 +16,8 @@ import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; /** * Updated for 1.9 to replicate the "Brewing" process for distilling. @@ -27,9 +31,9 @@ public class BDistiller { private static final int DISTILLTIME = 400; - private static Map trackedDistillers = new HashMap<>(); + private static Map trackedDistillers = new ConcurrentHashMap<>(); - private int taskId; + private BTask task; private int runTime = -1; private int brewTime = -1; private Block standBlock; @@ -41,11 +45,11 @@ public BDistiller(Block standBlock, int fuel) { } public void cancelDistill() { - Bukkit.getScheduler().cancelTask(taskId); // cancel prior + task.cancel(); } public void start() { - taskId = new DistillRunnable().runTaskTimer(P.p, 2L, 1L).getTaskId(); + task = P.p.scheduler.runAsyncTaskOnTimer(new DistillRunnable(), 2L, 2L); } public static void distillerClick(InventoryClickEvent event) { @@ -167,13 +171,20 @@ public static void showAlc(BrewerInventory inv, Brew[] contents) { } } - public class DistillRunnable extends BukkitRunnable { + public class DistillRunnable implements Consumer { private Brew[] contents = null; @Override - public void run() { - BlockState now = standBlock.getState(); - if (now instanceof BrewingStand) { + public void accept(BTask task) { + P.p.scheduler.runTaskAt(standBlock.getLocation(), sched -> { + BlockState now = standBlock.getState(); + if (!(now instanceof BrewingStand)) { + task.cancel(); + trackedDistillers.remove(standBlock); + P.p.debugLog("The block was replaced; not a brewing stand."); + return; + } + BrewingStand stand = (BrewingStand) now; if (brewTime == -1) { // check at the beginning for distillables if (!prepareForDistillables(stand)) { @@ -189,7 +200,7 @@ public void run() { stand.setBrewingTime(0); stand.update(); if (!runDistill(stand.getInventory(), contents)) { - this.cancel(); + task.cancel(); trackedDistillers.remove(standBlock); P.p.debugLog("All done distilling"); } else { @@ -199,11 +210,7 @@ public void run() { } else { stand.update(); } - } else { - this.cancel(); - trackedDistillers.remove(standBlock); - P.p.debugLog("The block was replaced; not a brewing stand."); - } + }, 0); } private boolean prepareForDistillables(BrewingStand stand) { @@ -233,7 +240,7 @@ private boolean prepareForDistillables(BrewingStand stand) { } case 0: // No custom potion, cancel and ignore - this.cancel(); + task.cancel(); trackedDistillers.remove(standBlock); showAlc(inventory, contents); P.p.debugLog("nothing to distill"); diff --git a/src/com/dre/brewery/BPlayer.java b/src/com/dre/brewery/BPlayer.java index 219d8e9..908226e 100644 --- a/src/com/dre/brewery/BPlayer.java +++ b/src/com/dre/brewery/BPlayer.java @@ -8,6 +8,7 @@ import com.dre.brewery.lore.BrewLore; import com.dre.brewery.recipe.BEffect; import com.dre.brewery.recipe.BPotionEffect; +import com.dre.brewery.utility.BTask; import com.dre.brewery.utility.BUtil; import com.dre.brewery.utility.PermissionUtil; import net.md_5.bungee.api.ChatMessageType; @@ -34,7 +35,7 @@ public class BPlayer { private static Map players = new HashMap<>();// Players uuid and BPlayer private static Map pTasks = new HashMap<>();// Player and count - private static int taskId; + private static BTask task; private static Random pukeRand; private final String uuid; @@ -223,8 +224,8 @@ public void showDrunkeness(Player player) { try { // It this returns false, then the Action Bar is not supported. Do not repeat the message as it was sent into chat if (sendDrunkenessMessage(player)) { - P.p.getServer().getScheduler().scheduleSyncDelayedTask(P.p, () -> sendDrunkenessMessage(player), 40); - P.p.getServer().getScheduler().scheduleSyncDelayedTask(P.p, () -> sendDrunkenessMessage(player), 80); + P.p.scheduler.runTaskFor(player, sched -> sendDrunkenessMessage(player), 40); + P.p.scheduler.runTaskFor(player, sched -> sendDrunkenessMessage(player), 80); } } catch (Exception e) { e.printStackTrace(); @@ -308,7 +309,7 @@ public boolean sendDrunkenessMessage(Player player) { b.append("ยง7]"); final String text = b.toString(); if (hangover && P.use1_11) { - P.p.getServer().getScheduler().scheduleSyncDelayedTask(P.p, () -> player.sendTitle("", text, 30, 100, 90), 160); + P.p.scheduler.runTaskFor(player, sched -> player.sendTitle("", text, 30, 100, 90), 160); return false; } try { @@ -326,7 +327,7 @@ public void drinkCap(Player player) { drunkeness = 100; syncToSQL(false); if (BConfig.overdrinkKick && !player.hasPermission("brewery.bypass.overdrink")) { - P.p.getServer().getScheduler().scheduleSyncDelayedTask(P.p, () -> passOut(player), 1); + P.p.scheduler.runTaskFor(player, sched -> passOut(player), 1); } else { addPuke(player, 60 + (int) (Math.random() * 60.0)); P.p.msg(player, GetText.tr("You can't drink any more.")); @@ -472,7 +473,7 @@ public void join(final Player player) { return; } // delayed login event as the player is not fully accessible pre login - P.p.getServer().getScheduler().runTaskLater(P.p, () -> login(player), 1L); + P.p.scheduler.runTaskLater((task) -> login(player), 1L); } // he may be having a hangover @@ -578,7 +579,7 @@ public static void addPuke(Player player, int count) { BUtil.reapplyPotionEffect(player, PotionEffectType.HUNGER.createEffect(80, 4), true); if (pTasks.isEmpty()) { - taskId = P.p.getServer().getScheduler().scheduleSyncRepeatingTask(P.p, BPlayer::pukeTask, 1L, 1L); + task = P.p.scheduler.runAsyncTaskOnTimer(sched -> pukeTask(), 1L, 1L); } pTasks.put(player, event.getCount()); } @@ -591,7 +592,7 @@ public static void pukeTask() { if (!player.isValid() || !player.isOnline()) { iter.remove(); } - puke(player); + P.p.scheduler.runTaskFor(player, sched -> puke(player), 0); if (count <= 1) { iter.remove(); } else { @@ -599,7 +600,7 @@ public static void pukeTask() { } } if (pTasks.isEmpty()) { - P.p.getServer().getScheduler().cancelTask(taskId); + task.cancel(); } } @@ -765,13 +766,13 @@ public static void drunkeness() { if (bplayer.offlineDrunk == 0) { Player player = BUtil.getPlayerfromString(name); if (player != null) { + P.p.scheduler.runTaskFor(player, (task) -> { + bplayer.drunkEffects(player); - bplayer.drunkEffects(player); - - if (BConfig.enablePuke) { - bplayer.drunkPuke(player); - } - + if (BConfig.enablePuke) { + bplayer.drunkPuke(player); + } + }, 0); } } } diff --git a/src/com/dre/brewery/BSealer.java b/src/com/dre/brewery/BSealer.java index 5cba4ac..8dd66b9 100644 --- a/src/com/dre/brewery/BSealer.java +++ b/src/com/dre/brewery/BSealer.java @@ -12,12 +12,14 @@ import org.bukkit.inventory.*; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataType; -import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import org.mini2Dx.gettext.GetText; +import com.dre.brewery.utility.BTask; + import java.util.Iterator; +// TODO: this class may be very bork under Folia because of inventory shenaniganery /** * The Sealing Inventory that is being checked for Brews and seals them after a second. *

Class doesn't load in mc 1.12 and lower (Can't find RecipeChoice, BlockData and NamespacedKey) @@ -31,7 +33,7 @@ public class BSealer implements InventoryHolder { private final Player player; private short[] slotTime = new short[9]; private ItemStack[] contents = null; - private BukkitTask task; + private BTask task; public BSealer(Player player) { this.player = player; @@ -57,7 +59,7 @@ public BSealer(Player player) { public void clickInv() { contents = null; if (task == null) { - task = P.p.getServer().getScheduler().runTaskTimer(P.p, this::itemChecking, 1, 1); + task = P.p.scheduler.runAsyncTaskOnTimer(sched -> itemChecking(), 1, 1); } } diff --git a/src/com/dre/brewery/Barrel.java b/src/com/dre/brewery/Barrel.java index 77c190d..bc60290 100644 --- a/src/com/dre/brewery/Barrel.java +++ b/src/com/dre/brewery/Barrel.java @@ -7,9 +7,11 @@ import com.dre.brewery.filedata.BConfig; import com.dre.brewery.integration.barrel.LogBlockBarrel; import com.dre.brewery.lore.BrewLore; +import com.dre.brewery.utility.BTask; import com.dre.brewery.utility.BUtil; import com.dre.brewery.utility.BoundingBox; import com.dre.brewery.utility.LegacyUtil; + import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Sound; @@ -24,21 +26,23 @@ import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.PotionMeta; -import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.mini2Dx.gettext.GetText; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.Consumer; +import java.util.Collection; /** * A Multi Block Barrel with Inventory */ public class Barrel implements InventoryHolder { - public static List barrels = new ArrayList<>(); + public static List barrels = Collections.synchronizedList(new ArrayList<>()); private static int check = 0; // Which Barrel was last checked private final Block spigot; @@ -108,7 +112,7 @@ public static void onUpdate() { randomInTheBack.checked = false; } } - new BarrelCheck().runTaskTimer(P.p, 1, 1); + P.p.scheduler.runAsyncTaskOnTimer(new BarrelCheck(barrels.stream().filter((barrel) -> !barrel.checked).toList()), 1, 1); } } @@ -552,38 +556,33 @@ public static void save(ConfigurationSection config, ConfigurationSection oldDat } } - public static class BarrelCheck extends BukkitRunnable { + public static class BarrelCheck implements Consumer { + private Collection barrelsToCheck; + + public BarrelCheck(Collection barrels) { + this.barrelsToCheck = barrels; + } + @Override - public void run() { - boolean repeat = true; - while (repeat) { - if (check < barrels.size()) { - Barrel barrel = barrels.get(check); - if (!barrel.checked) { - Block broken = barrel.body.getBrokenBlock(false); - if (broken != null) { - P.p.debugLog("Barrel at " - + broken.getWorld().getName() + "/" + broken.getX() + "/" + broken.getY() + "/" + broken.getZ() - + " has been destroyed unexpectedly, contents will drop"); - // remove the barrel if it was destroyed - barrel.remove(broken, null, true); - } else { - // Dont check this barrel again, its enough to check it once after every restart (and when randomly chosen) - // as now this is only the backup if we dont register the barrel breaking, - // for example when removing it with some world editor - barrel.checked = true; - } - repeat = false; + public void accept(BTask task) { + for (Barrel barrel : barrelsToCheck) { + P.p.scheduler.runTaskAt(barrel.body.getSpigot().getLocation(), (task) -> { + Block broken = barrel.body.getBrokenBlock(false); + if (broken != null) { + P.p.debugLog("Barrel at " + + broken.getWorld().getName() + "/" + broken.getX() + "/" + broken.getY() + "/" + broken.getZ() + + " has been destroyed unexpectedly, contents will drop"); + // remove the barrel if it was destroyed + barrel.remove(broken, null, true); + } else { + // Dont check this barrel again, its enough to check it once after every restart (and when randomly chosen) + // as now this is only the backup if we dont register the barrel breaking, + // for example when removing it with some world editor + barrel.checked = true; } - check++; - } else { - check = 0; - repeat = false; - cancel(); - } + }, 0); } } - } } diff --git a/src/com/dre/brewery/P.java b/src/com/dre/brewery/P.java index 9f9145f..2315faa 100644 --- a/src/com/dre/brewery/P.java +++ b/src/com/dre/brewery/P.java @@ -36,6 +36,8 @@ import com.dre.brewery.integration.barrel.LogBlockBarrel; import com.dre.brewery.listeners.*; import com.dre.brewery.recipe.*; +import com.dre.brewery.utility.BScheduler; +import com.dre.brewery.utility.BTask; import com.dre.brewery.utility.BUtil; import com.dre.brewery.utility.LegacyUtil; import com.dre.brewery.utility.Stats; @@ -53,6 +55,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.function.Consumer; import java.util.function.Function; public class P extends JavaPlugin { @@ -82,6 +85,9 @@ public class P extends JavaPlugin { // Metrics public Stats stats = new Stats(); + // Scheduling + public BScheduler scheduler = BScheduler.getScheduler(this); + @Override public void onEnable() { p = this; @@ -166,17 +172,17 @@ public void onEnable() { } // Heartbeat - p.getServer().getScheduler().runTaskTimer(p, new BreweryRunnable(), 650, 1200); - p.getServer().getScheduler().runTaskTimer(p, new DrunkRunnable(), 120, 120); + p.scheduler.runAsyncTaskOnTimer(new BreweryRunnable(), 650, 1200); + p.scheduler.runAsyncTaskOnTimer(new DrunkRunnable(), 120, 120); if (use1_9) { - p.getServer().getScheduler().runTaskTimer(p, new CauldronParticles(), 1, 1); + p.scheduler.runAsyncTaskOnTimer(new CauldronParticles(), 1, 1); } // Disable Update Check for older mc versions if (use1_14 && BConfig.updateCheck) { try { - p.getServer().getScheduler().runTaskLaterAsynchronously(p, new UpdateChecker(), 135); + p.scheduler.runTaskLater(new UpdateChecker(), 135); } catch (Exception e) { e.printStackTrace(); } @@ -191,9 +197,6 @@ public void onDisable() { // Disable listeners HandlerList.unregisterAll(this); - // Stop shedulers - getServer().getScheduler().cancelTasks(this); - if (p == null) { return; } @@ -372,18 +375,18 @@ public String color(String msg) { // Runnables - public static class DrunkRunnable implements Runnable { + public static class DrunkRunnable implements Consumer { @Override - public void run() { + public void accept(BTask it) { if (!BPlayer.isEmpty()) { BPlayer.drunkeness(); } } } - public class BreweryRunnable implements Runnable { + public class BreweryRunnable implements Consumer { @Override - public void run() { + public void accept(BTask it) { long t1 = System.nanoTime(); BConfig.reloader = null; Iterator iter = BCauldron.bcauldrons.values().iterator(); @@ -415,9 +418,9 @@ public void run() { } - public class CauldronParticles implements Runnable { + public class CauldronParticles implements Consumer { @Override - public void run() { + public void accept(BTask it) { if (!BConfig.enableCauldronParticles) return; if (BConfig.minimalParticles && BCauldron.particleRandom.nextFloat() > 0.5f) { return; diff --git a/src/com/dre/brewery/filedata/BData.java b/src/com/dre/brewery/filedata/BData.java index d29ffd7..bc97ba4 100644 --- a/src/com/dre/brewery/filedata/BData.java +++ b/src/com/dre/brewery/filedata/BData.java @@ -185,7 +185,7 @@ public static void readData() { final List worlds = P.p.getServer().getWorlds(); if (BConfig.loadDataAsync) { - P.p.getServer().getScheduler().runTaskAsynchronously(P.p, () -> lwDataTask(worlds)); + P.p.scheduler.runAsyncTaskLater((task) -> lwDataTask(worlds), 0); } else { lwDataTask(worlds); } @@ -425,30 +425,27 @@ public static void loadWorldData(String uuid, World world) { } } - // Merge Loaded Data in Main Thread - P.p.getServer().getScheduler().runTask(P.p, () -> { - if (P.p.getServer().getWorld(world.getUID()) == null) { - return; - } - if (!initCauldrons.isEmpty()) { - BCauldron.bcauldrons.putAll(initCauldrons); - } - if (!initBarrels.isEmpty()) { - Barrel.barrels.addAll(initBarrels); - } - if (!initBadBarrels.isEmpty()) { - for (Barrel badBarrel : initBadBarrels) { - if (badBarrel.getBody().regenerateBounds()) { - Barrel.barrels.add(badBarrel); - } - // In case Barrel Block locations were missing and could not be recreated: do not add the barrel + if (P.p.getServer().getWorld(world.getUID()) == null) { + return; + } + if (!initCauldrons.isEmpty()) { + BCauldron.bcauldrons.putAll(initCauldrons); + } + if (!initBarrels.isEmpty()) { + Barrel.barrels.addAll(initBarrels); + } + if (!initBadBarrels.isEmpty()) { + for (Barrel badBarrel : initBadBarrels) { + if (badBarrel.getBody().regenerateBounds()) { + Barrel.barrels.add(badBarrel); } - - } - if (!initWakeups.isEmpty()) { - Wakeup.wakeups.addAll(initWakeups); + // In case Barrel Block locations were missing and could not be recreated: do not add the barrel } - }); + + } + if (!initWakeups.isEmpty()) { + Wakeup.wakeups.addAll(initWakeups); + } } public static boolean acquireDataLoadMutex() { diff --git a/src/com/dre/brewery/filedata/DataSave.java b/src/com/dre/brewery/filedata/DataSave.java index e2c9745..03bd633 100644 --- a/src/com/dre/brewery/filedata/DataSave.java +++ b/src/com/dre/brewery/filedata/DataSave.java @@ -131,9 +131,9 @@ public void run() { P.p.debugLog("saving: " + ((System.nanoTime() - saveTime) / 1000000.0) + "ms"); if (P.p.isEnabled()) { - P.p.getServer().getScheduler().runTaskAsynchronously(P.p, new WriteData(data, worldData)); + P.p.scheduler.runAsyncTaskLater(new WriteData(data, worldData), 0); } else { - new WriteData(data, worldData).run(); + new WriteData(data, worldData).accept(null); } // Mutex will be released in WriteData } catch (Exception e) { diff --git a/src/com/dre/brewery/filedata/UpdateChecker.java b/src/com/dre/brewery/filedata/UpdateChecker.java index 73ab0fd..cbda45c 100644 --- a/src/com/dre/brewery/filedata/UpdateChecker.java +++ b/src/com/dre/brewery/filedata/UpdateChecker.java @@ -1,6 +1,7 @@ package com.dre.brewery.filedata; import com.dre.brewery.P; +import com.dre.brewery.utility.BTask; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -12,13 +13,14 @@ import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; +import java.util.function.Consumer; /** * Update Checker modified from the Gravity Update Checker Example: * https://github.com/gravitylow/ServerModsAPI-Example/blob/master/Update.java */ -public class UpdateChecker implements Runnable { +public class UpdateChecker implements Consumer { // The project's unique ID private static final int projectID = 68006; @@ -46,7 +48,7 @@ public static void notify(final Player player) { } @Override - public void run() { + public void accept(BTask it) { query(); } diff --git a/src/com/dre/brewery/filedata/WriteData.java b/src/com/dre/brewery/filedata/WriteData.java index e56805b..2bbcfc3 100644 --- a/src/com/dre/brewery/filedata/WriteData.java +++ b/src/com/dre/brewery/filedata/WriteData.java @@ -2,15 +2,17 @@ import java.io.File; +import java.util.function.Consumer; import org.bukkit.configuration.file.FileConfiguration; import com.dre.brewery.P; +import com.dre.brewery.utility.BTask; /** * Writes the collected Data to file in Async Thread */ -public class WriteData implements Runnable { +public class WriteData implements Consumer { private FileConfiguration data; private FileConfiguration worldData; @@ -21,7 +23,7 @@ public WriteData(FileConfiguration data, FileConfiguration worldData) { } @Override - public void run() { + public void accept(BTask task) { File datafile = new File(P.p.getDataFolder(), "data.yml"); File worlddatafile = new File(P.p.getDataFolder(), "worlddata.yml"); diff --git a/src/com/dre/brewery/listeners/PlayerListener.java b/src/com/dre/brewery/listeners/PlayerListener.java index 26693c2..181c404 100644 --- a/src/com/dre/brewery/listeners/PlayerListener.java +++ b/src/com/dre/brewery/listeners/PlayerListener.java @@ -143,7 +143,7 @@ public void onPlayerInteract(PlayerInteractEvent event) { } if (useSlot != -1) { inv.setHeldItemSlot(useSlot); - P.p.getServer().getScheduler().scheduleSyncDelayedTask(P.p, () -> player.getInventory().setHeldItemSlot(held), 2); + P.p.scheduler.runTaskFor(player, (task) -> player.getInventory().setHeldItemSlot(held), 2); } } diff --git a/src/com/dre/brewery/listeners/WorldListener.java b/src/com/dre/brewery/listeners/WorldListener.java index 1455b2c..16f0551 100644 --- a/src/com/dre/brewery/listeners/WorldListener.java +++ b/src/com/dre/brewery/listeners/WorldListener.java @@ -21,7 +21,7 @@ public class WorldListener implements Listener { public void onWorldLoad(WorldLoadEvent event) { final World world = event.getWorld(); if (BConfig.loadDataAsync) { - P.p.getServer().getScheduler().runTaskAsynchronously(P.p, () -> lwDataTask(world)); + P.p.scheduler.runAsyncTaskLater((task) -> lwDataTask(world), 0); } else { lwDataTask(world); } diff --git a/src/com/dre/brewery/utility/BScheduler.java b/src/com/dre/brewery/utility/BScheduler.java new file mode 100644 index 0000000..27bd31a --- /dev/null +++ b/src/com/dre/brewery/utility/BScheduler.java @@ -0,0 +1,115 @@ +package com.dre.brewery.utility; + +import java.util.concurrent.TimeUnit; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; +import java.util.function.Consumer; + +public interface BScheduler { + BTask runTaskAt(Location location, Consumer task, long delay); + BTask runTaskFor(Entity entity, Consumer task, long delay); + BTask runAsyncTaskOnTimer(Consumer task, long initialDelayTicks, long intervalTicks); + BTask runTaskLater(Consumer task, long delay); + BTask runAsyncTaskLater(Consumer task, long delay); + + public static BScheduler getScheduler(Plugin p) { + try { + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); + return new FoliaScheduler(p); + } catch (ClassNotFoundException e) { + return new BukkitScheduler(p); + } + } + + public record FoliaScheduler(Plugin p) implements BScheduler { + @Override + public BTask runTaskAt(Location location, Consumer task, long delay) { + var ret = p.getServer().getRegionScheduler().runDelayed(p, location, sched -> task.accept(BTask.from(sched)), delay); + return BTask.from(ret); + } + + @Override + public BTask runTaskFor(Entity entity, Consumer task, long delay) { + var ret = entity.getScheduler().runDelayed(p, sched -> task.accept(BTask.from(sched)), null, delay); + return BTask.from(ret); + } + + @Override + public BTask runAsyncTaskOnTimer(Consumer task, long initialDelayTicks, long intervalTicks) { + var ret = p.getServer().getAsyncScheduler().runAtFixedRate(p, sched -> task.accept(BTask.from(sched)), initialDelayTicks * 50, intervalTicks * 50, TimeUnit.MILLISECONDS); + return BTask.from(ret); + } + + @Override + public BTask runTaskLater(Consumer task, long delay) { + var ret = p.getServer().getAsyncScheduler().runDelayed(p, sched -> task.accept(BTask.from(sched)), delay * 50, TimeUnit.MILLISECONDS); + return BTask.from(ret); + } + + @Override + public BTask runAsyncTaskLater(Consumer task, long delay) { + var ret = p.getServer().getAsyncScheduler().runDelayed(p, sched -> task.accept(BTask.from(sched)), delay * 50, TimeUnit.MILLISECONDS); + return BTask.from(ret); + } + } + + public record BukkitScheduler(Plugin p) implements BScheduler { + private class Runner extends BukkitRunnable { + Consumer task; + public Runner(Consumer task) { + this.task = task; + } + @Override + public void run() { + try { + var field = getClass().getSuperclass().getDeclaredField("task"); + field.setAccessible(true); + var task = (BukkitTask)field.get(this); + + this.task.accept(BTask.from(task)); + } catch (Throwable it) { + forciblyThrow(it); + } + } + @SuppressWarnings("unchecked") + private static T forciblyThrow(Throwable t) throws T { + throw (T)t; + } + } + + @Override + public BTask runTaskAt(Location location, Consumer task, long delay) { + var ret = p.getServer().getScheduler().runTaskLater(p, new Runner(task), delay); + return BTask.from(ret); + } + + + @Override + public BTask runTaskFor(Entity entity, Consumer task, long delay) { + var ret = p.getServer().getScheduler().runTaskLater(p, new Runner(task), delay); + return BTask.from(ret); + } + + @Override + public BTask runAsyncTaskOnTimer(Consumer task, long initialDelayTicks, long intervalTicks) { + var ret = p.getServer().getScheduler().runTaskTimer(p, new Runner(task), initialDelayTicks, intervalTicks); + return BTask.from(ret); + } + + @Override + public BTask runTaskLater(Consumer task, long delay) { + var ret = p.getServer().getScheduler().runTaskLater(p, new Runner(task), delay); + return BTask.from(ret); + } + + @Override + public BTask runAsyncTaskLater(Consumer task, long delay) { + var ret = p.getServer().getScheduler().runTaskLaterAsynchronously(p, new Runner(task), delay); + return BTask.from(ret); + } + } +} diff --git a/src/com/dre/brewery/utility/BTask.java b/src/com/dre/brewery/utility/BTask.java new file mode 100644 index 0000000..86d2ebe --- /dev/null +++ b/src/com/dre/brewery/utility/BTask.java @@ -0,0 +1,29 @@ +package com.dre.brewery.utility; + +import org.bukkit.scheduler.BukkitTask; + +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; + +public interface BTask { + void cancel(); + + public static BTask from(BukkitTask task) { + return new BBukkitTask(task); + } + public static BTask from(ScheduledTask task) { + return new BFoliaTask(task); + } + + public record BBukkitTask(BukkitTask task) implements BTask { + @Override + public void cancel() { + task.cancel(); + } + } + public record BFoliaTask(ScheduledTask task) implements BTask { + @Override + public void cancel() { + task.cancel(); + } + } +} diff --git a/src/com/dre/brewery/utility/SQLSync.java b/src/com/dre/brewery/utility/SQLSync.java index 3087b01..02ff8f8 100644 --- a/src/com/dre/brewery/utility/SQLSync.java +++ b/src/com/dre/brewery/utility/SQLSync.java @@ -9,6 +9,7 @@ import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; +import java.util.function.Consumer; public class SQLSync { private BlockingQueue saveDataQueue = new ArrayBlockingQueue<>(64); @@ -80,17 +81,17 @@ public void fetchPlayerLoginData(final UUID uuid) { if (statement.execute("SELECT * FROM Brewery_Z_BPlayers WHERE uuid = '" + uuid.toString() + "';")) { final ResultSet result = statement.getResultSet(); if (result.next()) { - P.p.getServer().getScheduler().runTask(P.p, () -> { + P.p.scheduler.runTaskLater((task) -> { try { new BPlayer(uuid.toString(), result.getInt("quality"), result.getInt("drunkeness"), result.getInt("offlineDrunk")); } catch (SQLException e) { e.printStackTrace(); } - }); + }, 0); return; } } - P.p.getServer().getScheduler().runTask(P.p, () -> BPlayer.sqlRemoved(uuid)); + P.p.scheduler.runTaskLater((task) -> BPlayer.sqlRemoved(uuid), 0); } catch (Exception e) { e.printStackTrace(); } @@ -99,7 +100,7 @@ public void fetchPlayerLoginData(final UUID uuid) { private void initAsyncTask() { if (sqlTaskRunning) return; sqlTaskRunning = true; - P.p.getServer().getScheduler().runTaskAsynchronously(P.p, new SQLSaver()); + P.p.scheduler.runAsyncTaskLater(new SQLSaver(), 0L); } @@ -198,10 +199,10 @@ private static class SQLRemove_BD { public String name; } - private class SQLSaver implements Runnable { + private class SQLSaver implements Consumer { @Override - public void run() { + public void accept(BTask it) { try { while (true) { try { @@ -230,7 +231,7 @@ public void run() { if (storedOfflineDrunk != d.offlineDrunk) { // The player is not offlineDrunk anymore, // Someone else is changing the mysql data - P.p.getServer().getScheduler().runTask(P.p, () -> BPlayer.sqlRemoved(d.uuid)); + P.p.scheduler.runTaskLater((task) -> BPlayer.sqlRemoved(d.uuid), 0); continue; } }