diff --git a/build.gradle b/build.gradle index 7472abe..54c3d50 100644 --- a/build.gradle +++ b/build.gradle @@ -19,9 +19,7 @@ java.toolchain.languageVersion = JavaLanguageVersion.of(8) dependencies { implementation fileTree(dir: "libs", includes: ["*.jar"]) - implementation "org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT" implementation "org.spigotmc:spigot-api:1.16.5-R0.1-SNAPSHOT" - implementation "org.bukkit:bukkit:1.16.5-R0.1-SNAPSHOT" implementation "com.aystudio.core:AyCore:1.0.3-BETA" implementation "de.tr7zw:item-nbt-api-plugin:2.11.1" @@ -40,7 +38,6 @@ processResources { } } - tasks.withType(JavaCompile).configureEach { options.encoding = "UTF-8" } \ No newline at end of file diff --git a/folia/build.gradle b/folia/build.gradle new file mode 100644 index 0000000..477a0ba --- /dev/null +++ b/folia/build.gradle @@ -0,0 +1,26 @@ +plugins { + id 'java' +} + +repositories { + maven { + name = "AyStudio-Repository" + url = "https://repo.mc9y.com/snapshots" + } + maven { + url = "https://repo.papermc.io/repository/maven-public/" + } +} + +java.toolchain.languageVersion = JavaLanguageVersion.of(17) + +dependencies { + implementation(project(":")) + compileOnly("io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT") + compileOnly("org.projectlombok:lombok:1.18.24") + annotationProcessor("org.projectlombok:lombok:1.18.24") +} + +tasks.withType(JavaCompile).configureEach { + options.encoding = "UTF-8" +} \ No newline at end of file diff --git a/folia/src/main/java/com/blank038/servermarket/internal/platform/folia/FoliaPlatformApi.java b/folia/src/main/java/com/blank038/servermarket/internal/platform/folia/FoliaPlatformApi.java new file mode 100644 index 0000000..77d3516 --- /dev/null +++ b/folia/src/main/java/com/blank038/servermarket/internal/platform/folia/FoliaPlatformApi.java @@ -0,0 +1,28 @@ +package com.blank038.servermarket.internal.platform.folia; + +import com.blank038.servermarket.api.platform.IPlatformApi; +import com.blank038.servermarket.api.platform.wrapper.ITaskWrapper; +import com.blank038.servermarket.internal.platform.folia.wrapper.FoliaTaskWrapper; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.concurrent.TimeUnit; + +/** + * @author Blank038 + */ +public class FoliaPlatformApi implements IPlatformApi { + + @Override + public ITaskWrapper runTask(JavaPlugin plugin, Runnable runnable) { + ScheduledTask task = Bukkit.getServer().getGlobalRegionScheduler().run(plugin, (t) -> runnable.run()); + return new FoliaTaskWrapper(task); + } + + @Override + public ITaskWrapper runTaskTimerAsynchronously(JavaPlugin plugin, Runnable runnable, long delay, long period) { + ScheduledTask task = Bukkit.getServer().getAsyncScheduler().runAtFixedRate(plugin, (t) -> runnable.run(), delay / 20, period / 20, TimeUnit.SECONDS); + return new FoliaTaskWrapper(task); + } +} diff --git a/folia/src/main/java/com/blank038/servermarket/internal/platform/folia/wrapper/FoliaTaskWrapper.java b/folia/src/main/java/com/blank038/servermarket/internal/platform/folia/wrapper/FoliaTaskWrapper.java new file mode 100644 index 0000000..cadc7e2 --- /dev/null +++ b/folia/src/main/java/com/blank038/servermarket/internal/platform/folia/wrapper/FoliaTaskWrapper.java @@ -0,0 +1,18 @@ +package com.blank038.servermarket.internal.platform.folia.wrapper; + +import com.blank038.servermarket.api.platform.wrapper.ITaskWrapper; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import lombok.AllArgsConstructor; + +/** + * @author Blank038 + */ +@AllArgsConstructor +public class FoliaTaskWrapper implements ITaskWrapper { + private final ScheduledTask task; + + @Override + public void cancel() { + this.task.cancel(); + } +} diff --git a/settings.gradle b/settings.gradle index 82b6e83..9c76a85 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,3 @@ rootProject.name = 'ServerMarket' + +include 'folia' \ No newline at end of file diff --git a/src/main/java/com/blank038/servermarket/api/ServerMarketApi.java b/src/main/java/com/blank038/servermarket/api/ServerMarketApi.java index b372ba7..29be216 100644 --- a/src/main/java/com/blank038/servermarket/api/ServerMarketApi.java +++ b/src/main/java/com/blank038/servermarket/api/ServerMarketApi.java @@ -1,5 +1,6 @@ package com.blank038.servermarket.api; +import com.blank038.servermarket.api.platform.IPlatformApi; import com.blank038.servermarket.internal.plugin.ServerMarket; import com.blank038.servermarket.internal.data.DataContainer; import com.blank038.servermarket.api.entity.MarketData; @@ -7,6 +8,8 @@ import com.blank038.servermarket.internal.enums.PayType; import com.blank038.servermarket.api.handler.filter.FilterHandler; import com.blank038.servermarket.internal.gui.impl.MarketGui; +import lombok.Getter; +import lombok.Setter; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; @@ -20,6 +23,9 @@ * @date 2021/03/05 */ public class ServerMarketApi { + @Getter + @Setter + private static IPlatformApi platformApi; public static List getMarketList() { return new ArrayList<>(DataContainer.MARKET_DATA.keySet()); diff --git a/src/main/java/com/blank038/servermarket/api/platform/IPlatformApi.java b/src/main/java/com/blank038/servermarket/api/platform/IPlatformApi.java new file mode 100644 index 0000000..3272ddc --- /dev/null +++ b/src/main/java/com/blank038/servermarket/api/platform/IPlatformApi.java @@ -0,0 +1,11 @@ +package com.blank038.servermarket.api.platform; + +import com.blank038.servermarket.api.platform.wrapper.ITaskWrapper; +import org.bukkit.plugin.java.JavaPlugin; + +public interface IPlatformApi { + + ITaskWrapper runTask(JavaPlugin plugin, Runnable runnable); + + ITaskWrapper runTaskTimerAsynchronously(JavaPlugin plugin, Runnable runnable, long delay, long period); +} diff --git a/src/main/java/com/blank038/servermarket/api/platform/wrapper/ITaskWrapper.java b/src/main/java/com/blank038/servermarket/api/platform/wrapper/ITaskWrapper.java new file mode 100644 index 0000000..a9d6744 --- /dev/null +++ b/src/main/java/com/blank038/servermarket/api/platform/wrapper/ITaskWrapper.java @@ -0,0 +1,6 @@ +package com.blank038.servermarket.api.platform.wrapper; + +public interface ITaskWrapper { + + void cancel(); +} diff --git a/src/main/java/com/blank038/servermarket/dto/impl/YamlStorageHandlerImpl.java b/src/main/java/com/blank038/servermarket/dto/impl/YamlStorageHandlerImpl.java index 851ea59..dc5e81f 100644 --- a/src/main/java/com/blank038/servermarket/dto/impl/YamlStorageHandlerImpl.java +++ b/src/main/java/com/blank038/servermarket/dto/impl/YamlStorageHandlerImpl.java @@ -1,5 +1,6 @@ package com.blank038.servermarket.dto.impl; +import com.blank038.servermarket.api.ServerMarketApi; import com.blank038.servermarket.dto.AbstractStorageHandler; import com.blank038.servermarket.internal.plugin.ServerMarket; import com.blank038.servermarket.internal.data.DataContainer; @@ -75,7 +76,7 @@ private void saveLogs() { @Override public void initialize() { - Bukkit.getScheduler().runTaskTimerAsynchronously(ServerMarket.getInstance(), this::saveLogs, 60L, 60L); + ServerMarketApi.getPlatformApi().runTaskTimerAsynchronously(ServerMarket.getInstance(), this::saveLogs, 60L, 60L); } @Override diff --git a/src/main/java/com/blank038/servermarket/internal/gui/AbstractGui.java b/src/main/java/com/blank038/servermarket/internal/gui/AbstractGui.java index 98edb52..d672d7c 100644 --- a/src/main/java/com/blank038/servermarket/internal/gui/AbstractGui.java +++ b/src/main/java/com/blank038/servermarket/internal/gui/AbstractGui.java @@ -1,5 +1,6 @@ package com.blank038.servermarket.internal.gui; +import com.blank038.servermarket.api.ServerMarketApi; import com.blank038.servermarket.internal.plugin.ServerMarket; import org.bukkit.Bukkit; @@ -14,7 +15,7 @@ public abstract class AbstractGui { protected static final Map COOLDOWN = new HashMap<>(); static { - Bukkit.getScheduler().runTaskTimerAsynchronously(ServerMarket.getInstance(), () -> { + ServerMarketApi.getPlatformApi().runTaskTimerAsynchronously(ServerMarket.getInstance(), () -> { synchronized (COOLDOWN) { COOLDOWN.entrySet().removeIf((entry) -> System.currentTimeMillis() > entry.getValue()); } diff --git a/src/main/java/com/blank038/servermarket/internal/listen/impl/PlayerCommonListener.java b/src/main/java/com/blank038/servermarket/internal/listen/impl/PlayerCommonListener.java index 5bf2aab..97cd73b 100644 --- a/src/main/java/com/blank038/servermarket/internal/listen/impl/PlayerCommonListener.java +++ b/src/main/java/com/blank038/servermarket/internal/listen/impl/PlayerCommonListener.java @@ -1,18 +1,12 @@ package com.blank038.servermarket.internal.listen.impl; import com.blank038.servermarket.internal.plugin.ServerMarket; -import com.blank038.servermarket.internal.data.DataContainer; -import com.blank038.servermarket.internal.economy.BaseEconomy; -import com.blank038.servermarket.internal.i18n.I18n; -import com.blank038.servermarket.api.entity.MarketData; import com.blank038.servermarket.internal.listen.AbstractListener; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerQuitEvent; -import java.text.DecimalFormat; import java.util.UUID; import java.util.concurrent.CompletableFuture; @@ -29,8 +23,6 @@ public class PlayerCommonListener extends AbstractListener { public void onPlayerJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); ServerMarket.getStorageHandler().getOrLoadPlayerCache(player.getUniqueId(), false); - // check player offline transactions - Bukkit.getScheduler().runTaskAsynchronously(ServerMarket.getInstance(), () -> this.checkResult(player)); } /** @@ -50,23 +42,4 @@ public void onPlayerQuit(PlayerQuitEvent event) { } }); } - - private synchronized void checkResult(Player player) { - ServerMarket.getStorageHandler().getOfflineTransactionByPlayer(player.getUniqueId()).forEach((k, v) -> { - if (ServerMarket.getStorageHandler().removeOfflineTransaction(k)) { - // 获取市场数据 - MarketData marketData = DataContainer.MARKET_DATA.getOrDefault(v.getSourceMarket(), null); - // 获取可获得货币 - double price = v.getAmount(), last = marketData == null ? price : (price - price * marketData.getPermsValueForPlayer(marketData.getTaxSection(), player, false)); - // 判断货币桥是否存在 - if (BaseEconomy.PAY_TYPES.containsKey(v.getPayType())) { - DecimalFormat df = new DecimalFormat("#0.00"); - BaseEconomy.getEconomyBridge(v.getPayType()).give(player, v.getEconomyType(), last); - player.sendMessage(I18n.getStrAndHeader("sale-sell") - .replace("%economy%", marketData == null ? "" : marketData.getDisplayName()) - .replace("%money%", df.format(price)).replace("%last%", df.format(last))); - } - } - }); - } } diff --git a/src/main/java/com/blank038/servermarket/internal/metrics/Metrics.java b/src/main/java/com/blank038/servermarket/internal/metrics/Metrics.java index bca2818..7434e76 100644 --- a/src/main/java/com/blank038/servermarket/internal/metrics/Metrics.java +++ b/src/main/java/com/blank038/servermarket/internal/metrics/Metrics.java @@ -27,6 +27,8 @@ import java.util.stream.Collectors; import java.util.zip.GZIPOutputStream; import javax.net.ssl.HttpsURLConnection; + +import com.blank038.servermarket.api.ServerMarketApi; import org.bukkit.Bukkit; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; @@ -87,7 +89,7 @@ public Metrics(JavaPlugin plugin, int serviceId) { enabled, this::appendPlatformData, this::appendServiceData, - submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask), + submitDataTask -> ServerMarketApi.getPlatformApi().runTask(plugin, submitDataTask), plugin::isEnabled, (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error), (message) -> this.plugin.getLogger().log(Level.INFO, message), diff --git a/src/main/java/com/blank038/servermarket/internal/platform/PlatformHandler.java b/src/main/java/com/blank038/servermarket/internal/platform/PlatformHandler.java new file mode 100644 index 0000000..341c65b --- /dev/null +++ b/src/main/java/com/blank038/servermarket/internal/platform/PlatformHandler.java @@ -0,0 +1,32 @@ +package com.blank038.servermarket.internal.platform; + +import com.blank038.servermarket.api.ServerMarketApi; +import com.blank038.servermarket.api.platform.IPlatformApi; +import com.blank038.servermarket.internal.platform.bukkit.BukkitPlatformApi; +import com.blank038.servermarket.internal.plugin.ServerMarket; +import com.blank038.servermarket.internal.util.CoreUtil; + +import java.util.logging.Level; + +/** + * @author Blank038 + */ +public class PlatformHandler { + + public static void initPlatform() { + if (CoreUtil.isFolia()) { + try { + Class classes = (Class) Class.forName("com.blank038.servermarket.internal.platform.folia.FoliaPlatformApi"); + setPlatform(classes.newInstance()); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + ServerMarket.getInstance().getLogger().log(Level.SEVERE, "Failed to initialize platform for Folia"); + } + } else { + setPlatform(new BukkitPlatformApi()); + } + } + + public static void setPlatform(IPlatformApi platform) { + ServerMarketApi.setPlatformApi(platform); + } +} diff --git a/src/main/java/com/blank038/servermarket/internal/platform/bukkit/BukkitPlatformApi.java b/src/main/java/com/blank038/servermarket/internal/platform/bukkit/BukkitPlatformApi.java new file mode 100644 index 0000000..4ce1277 --- /dev/null +++ b/src/main/java/com/blank038/servermarket/internal/platform/bukkit/BukkitPlatformApi.java @@ -0,0 +1,26 @@ +package com.blank038.servermarket.internal.platform.bukkit; + +import com.blank038.servermarket.api.platform.IPlatformApi; +import com.blank038.servermarket.api.platform.wrapper.ITaskWrapper; +import com.blank038.servermarket.internal.platform.bukkit.warpper.BukkitTaskWrapper; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitTask; + +/** + * @author Blank038 + */ +public class BukkitPlatformApi implements IPlatformApi { + + @Override + public ITaskWrapper runTask(JavaPlugin plugin, Runnable runnable) { + BukkitTask bukkitTask = Bukkit.getScheduler().runTask(plugin, runnable); + return new BukkitTaskWrapper(bukkitTask); + } + + @Override + public ITaskWrapper runTaskTimerAsynchronously(JavaPlugin plugin, Runnable runnable, long delay, long period) { + BukkitTask bukkitTask = Bukkit.getScheduler().runTaskTimerAsynchronously(plugin, runnable, delay, period); + return new BukkitTaskWrapper(bukkitTask); + } +} diff --git a/src/main/java/com/blank038/servermarket/internal/platform/bukkit/warpper/BukkitTaskWrapper.java b/src/main/java/com/blank038/servermarket/internal/platform/bukkit/warpper/BukkitTaskWrapper.java new file mode 100644 index 0000000..9a0d0e5 --- /dev/null +++ b/src/main/java/com/blank038/servermarket/internal/platform/bukkit/warpper/BukkitTaskWrapper.java @@ -0,0 +1,19 @@ +package com.blank038.servermarket.internal.platform.bukkit.warpper; + +import com.blank038.servermarket.api.platform.wrapper.ITaskWrapper; +import lombok.AllArgsConstructor; +import org.bukkit.scheduler.BukkitTask; + +/** + * @author Blank038 + */ +@AllArgsConstructor +public class BukkitTaskWrapper implements ITaskWrapper { + + public final BukkitTask bukkitTask; + + @Override + public void cancel() { + bukkitTask.cancel(); + } +} diff --git a/src/main/java/com/blank038/servermarket/internal/plugin/ServerMarket.java b/src/main/java/com/blank038/servermarket/internal/plugin/ServerMarket.java index cf75455..afc18b0 100644 --- a/src/main/java/com/blank038/servermarket/internal/plugin/ServerMarket.java +++ b/src/main/java/com/blank038/servermarket/internal/plugin/ServerMarket.java @@ -1,6 +1,7 @@ package com.blank038.servermarket.internal.plugin; import com.aystudio.core.bukkit.plugin.AyPlugin; +import com.blank038.servermarket.api.ServerMarketApi; import com.blank038.servermarket.api.handler.sort.AbstractSortHandler; import com.blank038.servermarket.internal.data.convert.LegacyBackup; import com.blank038.servermarket.dto.AbstractStorageHandler; @@ -13,10 +14,11 @@ import com.blank038.servermarket.internal.listen.impl.PlayerCommonListener; import com.blank038.servermarket.internal.listen.impl.PlayerLatestListener; import com.blank038.servermarket.internal.metrics.Metrics; +import com.blank038.servermarket.internal.platform.PlatformHandler; +import com.blank038.servermarket.internal.task.OfflineTransactionTask; import de.tr7zw.nbtapi.utils.MinecraftVersion; import lombok.Getter; import lombok.Setter; -import org.bukkit.Bukkit; /** * Global market plugin for Bukkit. @@ -36,6 +38,8 @@ public class ServerMarket extends AyPlugin { @Override public void onEnable() { instance = this; + // initialize platform + PlatformHandler.initPlatform(); // begin loading this.getConsoleLogger().setPrefix("&f[&eServerMarket&f] &8"); this.loadConfig(true); @@ -50,8 +54,8 @@ public void onEnable() { // register sort handler AbstractSortHandler.registerDefaults(); // start tasks - Bukkit.getScheduler().runTaskTimerAsynchronously(this, storageHandler::removeTimeOutItem, 200L, 200L); - Bukkit.getScheduler().runTaskTimerAsynchronously(this, storageHandler::saveAll, 1200L, 1200L); + ServerMarketApi.getPlatformApi().runTaskTimerAsynchronously(this, storageHandler::removeTimeOutItem, 200L, 200L); + ServerMarketApi.getPlatformApi().runTaskTimerAsynchronously(this, storageHandler::saveAll, 1200L, 1200L); // inject metrics new Metrics(this, 20031); } @@ -74,6 +78,8 @@ public void loadConfig(boolean start) { this.reloadConfig(); // Initialize I18n new I18n(this.getConfig().getString("language", "zh_CN")); + // restart the task for offline transaction + OfflineTransactionTask.restart(); // Run legacy converter LegacyBackup.check(); if (this.isEnabled()) { diff --git a/src/main/java/com/blank038/servermarket/internal/task/OfflineTransactionTask.java b/src/main/java/com/blank038/servermarket/internal/task/OfflineTransactionTask.java new file mode 100644 index 0000000..50b3a41 --- /dev/null +++ b/src/main/java/com/blank038/servermarket/internal/task/OfflineTransactionTask.java @@ -0,0 +1,62 @@ +package com.blank038.servermarket.internal.task; + +import com.blank038.servermarket.api.ServerMarketApi; +import com.blank038.servermarket.api.entity.MarketData; +import com.blank038.servermarket.api.platform.wrapper.ITaskWrapper; +import com.blank038.servermarket.internal.data.DataContainer; +import com.blank038.servermarket.internal.economy.BaseEconomy; +import com.blank038.servermarket.internal.i18n.I18n; +import com.blank038.servermarket.internal.plugin.ServerMarket; +import org.bukkit.entity.Player; + +import java.text.DecimalFormat; + +/** + * @author Blank038 + */ +public class OfflineTransactionTask implements Runnable { + private static ITaskWrapper taskWrapper; + + public OfflineTransactionTask() { + ServerMarketApi.getPlatformApi().runTaskTimerAsynchronously(ServerMarket.getInstance(), () -> { + + }, 1200L, 1200L); + } + + @Override + public synchronized void run() { + + } + + private void checkResult(Player player) { + ServerMarket.getStorageHandler().getOfflineTransactionByPlayer(player.getUniqueId()).forEach((k, v) -> { + if (ServerMarket.getStorageHandler().removeOfflineTransaction(k)) { + // 获取市场数据 + MarketData marketData = DataContainer.MARKET_DATA.getOrDefault(v.getSourceMarket(), null); + // 获取可获得货币 + double price = v.getAmount(), last = marketData == null ? price : (price - price * marketData.getPermsValueForPlayer(marketData.getTaxSection(), player, false)); + // 判断货币桥是否存在 + if (BaseEconomy.PAY_TYPES.containsKey(v.getPayType())) { + DecimalFormat df = new DecimalFormat("#0.00"); + BaseEconomy.getEconomyBridge(v.getPayType()).give(player, v.getEconomyType(), last); + player.sendMessage(I18n.getStrAndHeader("sale-sell") + .replace("%economy%", marketData == null ? "" : marketData.getDisplayName()) + .replace("%money%", df.format(price)).replace("%last%", df.format(last))); + } + } + }); + } + + public static void restart() { + if (taskWrapper != null) { + taskWrapper.cancel(); + } + int interval = ServerMarket.getInstance().getConfig().getInt("settings.offline-transaction-interval"); + taskWrapper = ServerMarketApi.getPlatformApi().runTaskTimerAsynchronously( + ServerMarket.getInstance(), + new OfflineTransactionTask(), + interval, + interval + ); + } +} diff --git a/src/main/java/com/blank038/servermarket/internal/util/CoreUtil.java b/src/main/java/com/blank038/servermarket/internal/util/CoreUtil.java new file mode 100644 index 0000000..4ef843a --- /dev/null +++ b/src/main/java/com/blank038/servermarket/internal/util/CoreUtil.java @@ -0,0 +1,16 @@ +package com.blank038.servermarket.internal.util; + +/** + * @author Blank038 + */ +public class CoreUtil { + + public static boolean isFolia() { + try { + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); + return true; + } catch (ClassNotFoundException e) { + return false; + } + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index cb30737..3dcc345 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -17,6 +17,10 @@ data-option: default-market: "example" # 是否启用命令短写帮助 command-help: true +# 通用参数设定 +settings: + # 玩家离线交易检测间隔, 单位: 秒 + offline-transaction-interval: 60 # 冷却设定, 单位: 秒 cooldown: action: 3