Experimental Folia support (#30)

Current implementation is not 100% safe. (may have issue on config
reload while someone triggered an anvil event). And GUI do not work. But
main functionalities should work (as most of it is read of the
config/config holder objects. Concurrent read should be fine)
This commit is contained in:
alexcrea 2024-09-13 13:47:39 +02:00 committed by GitHub
commit 694ece5443
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 163 additions and 50 deletions

View file

@ -0,0 +1,18 @@
package xyz.alexcrea.cuanvil.dependency.scheduler
import org.bukkit.entity.Entity
import org.bukkit.plugin.Plugin
interface TaskScheduler {
fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any?
fun scheduleGlobally(plugin: Plugin, task: Runnable): Any?{
return scheduleGlobally(plugin, task, 0L)
}
fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable, time: Long): Any?
fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable): Any?{
return scheduleOnEntity(plugin, entity, task, 0L)
}
}

View file

@ -0,0 +1,52 @@
package xyz.alexcrea.cuanvil.dependency.scheduler
import io.papermc.paper.threadedregions.scheduler.ScheduledTask
import org.bukkit.Bukkit
import org.bukkit.entity.Entity
import org.bukkit.plugin.Plugin
import java.util.function.Consumer
class FoliaScheduler : TaskScheduler {
override fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any? {
if(time < 1){
return Bukkit.getGlobalRegionScheduler().run(
plugin,
Consumer { scheduledTask: ScheduledTask? -> task.run() }
)
}
return Bukkit.getGlobalRegionScheduler().runDelayed(
plugin,
Consumer { scheduledTask: ScheduledTask? -> task.run() },
time
)
}
override fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable, time: Long): Any? {
if(time < 1){
return entity.scheduler.run(
plugin,
Consumer { scheduledTask: ScheduledTask? -> task.run() },
Runnable {}
)
}
return entity.scheduler.runDelayed(
plugin,
Consumer { scheduledTask: ScheduledTask? -> task.run() },
Runnable {},
time
)
}
companion object {
fun isFolia(): Boolean {
try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServer")
return true
} catch (e: ClassNotFoundException) {
return false
}
}
}
}

View file

@ -1,11 +1,11 @@
package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
import xyz.alexcrea.cuanvil.gui.config.global.EnchantConflictGui;
@ -21,8 +21,8 @@ public class ConflictAPI {
private ConflictAPI() {}
private static int saveChangeTask = -1;
private static int reloadChangeTask = -1;
private static Object saveChangeTask = null;
private static Object reloadChangeTask = null;
/**
* Write and add a conflict.
@ -151,27 +151,27 @@ public class ConflictAPI {
* Prepare a task to save conflict configuration.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.CONFLICT_HOLDER.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**
* Prepare a task to reload every conflict.
*/
private static void prepareUpdateTask() {
if(reloadChangeTask != -1) return;
if(reloadChangeTask != null) return;
reloadChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
reloadChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.CONFLICT_HOLDER.reload();
EnchantConflictGui conflictGui = EnchantConflictGui.getCurrentInstance();
if(conflictGui != null) conflictGui.reloadValues();
reloadChangeTask = -1;
}, 0L);
reloadChangeTask = null;
});
}

View file

@ -1,10 +1,10 @@
package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.gui.config.global.CustomRecipeConfigGui;
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
@ -19,7 +19,7 @@ public class CustomAnvilRecipeApi {
private CustomAnvilRecipeApi(){}
private static int saveChangeTask = -1;
private static Object saveChangeTask = null;
/**
* Write and add a custom anvil recipe.
@ -103,12 +103,12 @@ public class CustomAnvilRecipeApi {
* Prepare a task to save custom recipe configuration.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.CONFLICT_HOLDER.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**

View file

@ -1,13 +1,13 @@
package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry;
import xyz.alexcrea.cuanvil.enchant.EnchantmentRarity;
@ -26,7 +26,7 @@ import java.util.Map;
@SuppressWarnings("unused")
public class EnchantmentApi {
private static int saveChangeTask = -1;
private static Object saveChangeTask = null;
private EnchantmentApi() {}
@ -180,12 +180,12 @@ public class EnchantmentApi {
* Prepare a task to save custom recipe configuration.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.DEFAULT_CONFIG.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**

View file

@ -2,12 +2,12 @@ package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import io.delilaheve.util.ConfigOptions;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.group.AbstractMaterialGroup;
import xyz.alexcrea.cuanvil.group.ExcludeGroup;
import xyz.alexcrea.cuanvil.group.IncludeGroup;
@ -24,8 +24,8 @@ public class MaterialGroupApi {
private MaterialGroupApi(){}
private static int saveChangeTask = -1;
private static int reloadChangeTask = -1;
private static Object saveChangeTask = null;
private static Object reloadChangeTask = null;
/**
@ -180,28 +180,28 @@ public class MaterialGroupApi {
* Prepare a task to reload every conflict.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.ITEM_GROUP_HOLDER.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**
* Prepare a task to save configuration.
*/
private static void prepareUpdateTask() {
if(reloadChangeTask != -1) return;
if(reloadChangeTask != null) return;
reloadChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
reloadChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.ITEM_GROUP_HOLDER.reload();
GroupConfigGui configGui = GroupConfigGui.getCurrentInstance();
if(configGui != null) configGui.reloadValues();
reloadChangeTask = -1;
}, 0L);
reloadChangeTask = null;
});
}

View file

@ -2,12 +2,12 @@ package xyz.alexcrea.cuanvil.api;
import io.delilaheve.CustomAnvil;
import kotlin.Triple;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import xyz.alexcrea.cuanvil.config.ConfigHolder;
import xyz.alexcrea.cuanvil.dependency.DependencyManager;
import xyz.alexcrea.cuanvil.gui.config.global.UnitRepairConfigGui;
import xyz.alexcrea.cuanvil.gui.config.list.UnitRepairElementListGui;
@ -23,7 +23,7 @@ public class UnitRepairApi {
private UnitRepairApi(){}
private static int saveChangeTask = -1;
private static Object saveChangeTask = null;
/**
* Write and add a custom anvil unit repair recipe.
@ -161,12 +161,12 @@ public class UnitRepairApi {
* Prepare a task to save custom unit repair recipe configuration.
*/
private static void prepareSaveTask() {
if(saveChangeTask != -1) return;
if(saveChangeTask != null) return;
saveChangeTask = Bukkit.getScheduler().scheduleSyncDelayedTask(CustomAnvil.instance, ()->{
saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{
ConfigHolder.UNIT_REPAIR_HOLDER.saveToDisk(true);
saveChangeTask = -1;
}, 0L);
saveChangeTask = null;
});
}
/**

View file

@ -115,7 +115,7 @@ class CustomAnvil : JavaPlugin() {
// Load other thing later.
// It is so other dependent plugins can implement there event listener before we fire them.
Bukkit.getScheduler().scheduleSyncDelayedTask(this, {loadEnchantmentSystem()}, 0L)
DependencyManager.scheduler.scheduleGlobally(this, {loadEnchantmentSystem()})
}
private fun loadEnchantmentSystem(){

View file

@ -5,6 +5,7 @@ import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
import org.bukkit.entity.HumanEntity
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui
import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions
@ -15,6 +16,15 @@ class EditConfigExecutor : CommandExecutor {
sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM)
return false
}
if(DependencyManager.isFolia){
sender.sendMessage("§cIt look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia.")
sender.sendMessage("§eIt is may come in a future version.")
sender.sendMessage("")
sender.sendMessage("§eCurrently you need to edit manually the config or copy from another server (spigot or better)")
sender.sendMessage("§eThen /anvilconfigreload after config file is edited")
return false
}
if (sender !is HumanEntity) return false
MainConfigGui.getInstance().show(sender)

View file

@ -1,5 +1,6 @@
package xyz.alexcrea.cuanvil.dependency
import io.delilaheve.CustomAnvil
import org.bukkit.Bukkit
import org.bukkit.event.inventory.InventoryClickEvent
import org.bukkit.event.inventory.PrepareAnvilEvent
@ -7,9 +8,14 @@ import org.bukkit.inventory.AnvilInventory
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerSelector
import xyz.alexcrea.cuanvil.dependency.scheduler.BukkitScheduler
import xyz.alexcrea.cuanvil.dependency.scheduler.FoliaScheduler
import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler
object DependencyManager {
var isFolia: Boolean = false
lateinit var scheduler: TaskScheduler
lateinit var packetManager: PacketManager
var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null
var ecoEnchantCompatibility: EcoEnchantDependency? = null
@ -18,6 +24,14 @@ object DependencyManager {
fun loadDependency(){
val pluginManager = Bukkit.getPluginManager()
// Bukkit or Paper scheduler ?
isFolia = FoliaScheduler.isFolia()
scheduler = if(isFolia) {
CustomAnvil.instance.logger.info("Folia detected... Custom Anvil Folia support is experimental. issues are more likely to happens.")
FoliaScheduler()
} else BukkitScheduler()
// Packet Manager
val forceProtocolib = ConfigHolder.DEFAULT_CONFIG.config.getBoolean("force_protocolib", false)
packetManager = PacketManagerSelector.selectPacketManager(forceProtocolib)

View file

@ -0,0 +1,17 @@
package xyz.alexcrea.cuanvil.dependency.scheduler
import org.bukkit.Bukkit
import org.bukkit.entity.Entity
import org.bukkit.plugin.Plugin
class BukkitScheduler : TaskScheduler {
override fun scheduleGlobally(plugin: Plugin, task: Runnable, time: Long): Any? {
return Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, task, time)
}
override fun scheduleOnEntity(plugin: Plugin, entity: Entity, task: Runnable, time: Long): Any? {
return Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, task, time)
}
}

View file

@ -1,12 +1,12 @@
package xyz.alexcrea.cuanvil.listener
import io.delilaheve.CustomAnvil
import org.bukkit.Bukkit
import org.bukkit.entity.HumanEntity
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.AsyncPlayerChatEvent
import org.bukkit.event.player.PlayerQuitEvent
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.function.Consumer
@ -39,9 +39,11 @@ class ChatEventListener : Listener {
event.isCancelled = true
// sync callback with default server thread
Bukkit.getScheduler().runTask(CustomAnvil.instance, Runnable {
DependencyManager.scheduler.scheduleOnEntity(
CustomAnvil.instance, player,
Runnable {
eventCallback.accept(event.message)
})
}, 0L)
}
}

View file

@ -38,21 +38,20 @@ object AnvilXpUtil {
anvilCost
}
val player = view.player
/* Because Minecraft likes to have the final say in the repair cost displayed
* we need to wait for the event to end before overriding it, this ensures that
* we have the final say in the process. */
CustomAnvil.instance
.server
.scheduler
.runTask(CustomAnvil.instance, Runnable {
DependencyManager.scheduler.scheduleOnEntity(
CustomAnvil.instance, player,
Runnable {
inventory.maximumRepairCost =
if (ConfigOptions.doRemoveCostLimit || ignoreRules)
{ Int.MAX_VALUE }
else
{ ConfigOptions.maxAnvilCost + 1 }
val player = view.player
inventory.repairCost = finalAnvilCost
view.setProperty(REPAIR_COST, finalAnvilCost)
player.openInventory.setProperty(REPAIR_COST, finalAnvilCost)

View file

@ -2,6 +2,7 @@ main: io.delilaheve.CustomAnvil
name: CustomAnvil
prefix: "Custom Anvil"
version: 1.6.0
folia-supported: true
description: Allow to customise anvil mechanics
api-version: 1.16
load: POSTWORLD