diff --git a/api/src/main/java/com/viaversion/viaversion/api/ViaAPI.java b/api/src/main/java/com/viaversion/viaversion/api/ViaAPI.java index 6a8922915..282282389 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/ViaAPI.java +++ b/api/src/main/java/com/viaversion/viaversion/api/ViaAPI.java @@ -63,7 +63,7 @@ public interface ViaAPI { * @return API version incremented with meaningful API changes */ default int apiVersion() { - return 18; + return 19; } /** diff --git a/api/src/main/java/com/viaversion/viaversion/api/ViaManager.java b/api/src/main/java/com/viaversion/viaversion/api/ViaManager.java index af8d1b792..97b639ca0 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/ViaManager.java +++ b/api/src/main/java/com/viaversion/viaversion/api/ViaManager.java @@ -30,6 +30,7 @@ import com.viaversion.viaversion.api.platform.ViaPlatform; import com.viaversion.viaversion.api.platform.ViaPlatformLoader; import com.viaversion.viaversion.api.platform.providers.ViaProviders; import com.viaversion.viaversion.api.protocol.ProtocolManager; +import com.viaversion.viaversion.api.scheduler.Scheduler; import java.util.Set; public interface ViaManager { @@ -83,6 +84,13 @@ public interface ViaManager { */ ViaPlatformLoader getLoader(); + /** + * Returns the async task scheduler. + * + * @return async task scheduler + */ + Scheduler getScheduler(); + /** * If debug is enabled, packets and other otherwise suppressed warnings will be logged. * diff --git a/api/src/main/java/com/viaversion/viaversion/api/platform/PlatformTask.java b/api/src/main/java/com/viaversion/viaversion/api/platform/PlatformTask.java index f7a9174cb..da6c6e9c2 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/platform/PlatformTask.java +++ b/api/src/main/java/com/viaversion/viaversion/api/platform/PlatformTask.java @@ -35,6 +35,7 @@ public interface PlatformTask { * * @return platform based object, or null if not tracked/cancellable */ + @Deprecated/*(forRemoval = true)*/ @Nullable T getObject(); /** diff --git a/api/src/main/java/com/viaversion/viaversion/api/platform/ViaPlatform.java b/api/src/main/java/com/viaversion/viaversion/api/platform/ViaPlatform.java index 18955664f..7e5b0ca90 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/platform/ViaPlatform.java +++ b/api/src/main/java/com/viaversion/viaversion/api/platform/ViaPlatform.java @@ -86,6 +86,15 @@ public interface ViaPlatform { */ PlatformTask runAsync(Runnable runnable); + /** + * Run a task async at a repeating interval. + * + * @param runnable The task to run + * @param ticks The interval to run it at + * @return The Task ID + */ + PlatformTask runRepeatingAsync(Runnable runnable, long ticks); + /** * Run a task Sync * @@ -106,7 +115,6 @@ public interface ViaPlatform { /** * Run a task at a repeating interval. - * Initial interval is the same as repeat. * * @param runnable The task to run * @param ticks The interval to run it at diff --git a/api/src/main/java/com/viaversion/viaversion/api/scheduler/Scheduler.java b/api/src/main/java/com/viaversion/viaversion/api/scheduler/Scheduler.java new file mode 100644 index 000000000..e77019b01 --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/scheduler/Scheduler.java @@ -0,0 +1,59 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2023-2023 ViaVersion and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.viaversion.viaversion.api.scheduler; + +import java.util.concurrent.TimeUnit; + +public interface Scheduler { + + /** + * Executes the given runnable asynchronously. + * + * @param runnable runnable to execute + */ + Task execute(Runnable runnable); + + /** + * Schedules the given runnable to be executed asynchronously after the given delay. + * + * @param runnable runnable to execute + * @param delay delay before execution + * @param timeUnit time unit of the delay + */ + Task schedule(Runnable runnable, long delay, TimeUnit timeUnit); + + /** + * Schedules the given runnable to be executed asynchronously after a delay and then repeatedly with a period. + * + * @param runnable runnable to execute + * @param delay delay before execution + * @param period period between executions + * @param timeUnit time unit of the delay and period + */ + Task scheduleRepeating(Runnable runnable, long delay, long period, TimeUnit timeUnit); + + /** + * Shuts down the scheduler and awaits task termination. + */ + void shutdown(); +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/scheduler/Task.java b/api/src/main/java/com/viaversion/viaversion/api/scheduler/Task.java new file mode 100644 index 000000000..cb20cf127 --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/scheduler/Task.java @@ -0,0 +1,38 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2023 ViaVersion and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.viaversion.viaversion.api.scheduler; + +public interface Task { + + /** + * Returns the current status of the task. + * + * @return status of the task + */ + TaskStatus status(); + + /** + * Cancels the task. This will still let the current task finish if already running. + */ + void cancel(); +} diff --git a/api/src/main/java/com/viaversion/viaversion/api/scheduler/TaskStatus.java b/api/src/main/java/com/viaversion/viaversion/api/scheduler/TaskStatus.java new file mode 100644 index 000000000..700e4d691 --- /dev/null +++ b/api/src/main/java/com/viaversion/viaversion/api/scheduler/TaskStatus.java @@ -0,0 +1,39 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2023 ViaVersion and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.viaversion.viaversion.api.scheduler; + +public enum TaskStatus { + + /** + * The task has been scheduled but not yet started. + */ + SCHEDULED, + /** + * The task is currently running. + */ + RUNNING, + /** + * The task has finished running or has been cancelled. + */ + STOPPED +} diff --git a/bukkit/src/main/java/com/viaversion/viaversion/ViaVersionPlugin.java b/bukkit/src/main/java/com/viaversion/viaversion/ViaVersionPlugin.java index b11e0a75c..f6145aac7 100644 --- a/bukkit/src/main/java/com/viaversion/viaversion/ViaVersionPlugin.java +++ b/bukkit/src/main/java/com/viaversion/viaversion/ViaVersionPlugin.java @@ -32,6 +32,8 @@ import com.viaversion.viaversion.bukkit.platform.BukkitViaConfig; import com.viaversion.viaversion.bukkit.platform.BukkitViaInjector; import com.viaversion.viaversion.bukkit.platform.BukkitViaLoader; import com.viaversion.viaversion.bukkit.platform.BukkitViaTask; +import com.viaversion.viaversion.bukkit.platform.BukkitViaTaskTask; +import com.viaversion.viaversion.bukkit.platform.PaperViaInjector; import com.viaversion.viaversion.dump.PluginInfo; import com.viaversion.viaversion.unsupported.UnsupportedPlugin; import com.viaversion.viaversion.unsupported.UnsupportedServerSoftware; @@ -41,19 +43,22 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.UUID; +import java.util.concurrent.TimeUnit; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform { + private static final boolean FOLIA = PaperViaInjector.hasClass("io.papermc.paper.threadedregions.RegionisedServer"); private static ViaVersionPlugin instance; private final BukkitCommandHandler commandHandler; private final BukkitViaConfig conf; private final ViaAPI api = new BukkitViaAPI(this); - private final List queuedTasks = new ArrayList<>(); - private final List asyncQueuedTasks = new ArrayList<>(); private boolean protocolSupport; private boolean lateBind; @@ -91,25 +96,30 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform @Override public void onEnable() { + final ViaManagerImpl manager = (ViaManagerImpl) Via.getManager(); if (lateBind) { getLogger().info("Registering protocol transformers and injecting..."); - ((ViaManagerImpl) Via.getManager()).init(); + manager.init(); + } + + if (FOLIA) { + // Use Folia's RegionisedServerInitEvent to run code after the server has loaded + final Class serverInitEventClass; + try { + //noinspection unchecked + serverInitEventClass = (Class) Class.forName("io.papermc.paper.threadedregions.RegionisedServerInitEvent"); + } catch (final ReflectiveOperationException e) { + throw new RuntimeException(e); + } + + getServer().getPluginManager().registerEvent(serverInitEventClass, new Listener() { + }, EventPriority.HIGHEST, (listener, event) -> manager.onServerLoaded(), this); + } else { + manager.onServerLoaded(); } getCommand("viaversion").setExecutor(commandHandler); getCommand("viaversion").setTabCompleter(commandHandler); - - // Run queued tasks - for (Runnable r : queuedTasks) { - Bukkit.getScheduler().runTask(this, r); - } - queuedTasks.clear(); - - // Run async queued tasks - for (Runnable r : asyncQueuedTasks) { - Bukkit.getScheduler().runTaskAsynchronously(this, r); - } - asyncQueuedTasks.clear(); } @Override @@ -134,22 +144,27 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform @Override public PlatformTask runAsync(Runnable runnable) { - if (isPluginEnabled()) { - return new BukkitViaTask(getServer().getScheduler().runTaskAsynchronously(this, runnable)); - } else { - asyncQueuedTasks.add(runnable); - return new BukkitViaTask(null); + if (FOLIA) { + return new BukkitViaTaskTask(Via.getManager().getScheduler().execute(runnable)); } + return new BukkitViaTask(getServer().getScheduler().runTaskAsynchronously(this, runnable)); + } + + @Override + public PlatformTask runRepeatingAsync(final Runnable runnable, final long ticks) { + if (FOLIA) { + return new BukkitViaTaskTask(Via.getManager().getScheduler().schedule(runnable, ticks * 50, TimeUnit.MILLISECONDS)); + } + return new BukkitViaTask(getServer().getScheduler().runTaskTimerAsynchronously(this, runnable, 0, ticks)); } @Override public PlatformTask runSync(Runnable runnable) { - if (isPluginEnabled()) { - return new BukkitViaTask(getServer().getScheduler().runTask(this, runnable)); - } else { - queuedTasks.add(runnable); - return new BukkitViaTask(null); + if (FOLIA) { + // We just need to make sure everything put here is actually thread safe; currently, this is the case, at least on Folia + return runAsync(runnable); } + return new BukkitViaTask(getServer().getScheduler().runTask(this, runnable)); } @Override diff --git a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaTaskTask.java b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaTaskTask.java new file mode 100644 index 000000000..3e86b518e --- /dev/null +++ b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/BukkitViaTaskTask.java @@ -0,0 +1,40 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2016-2023 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.viaversion.viaversion.bukkit.platform; + +import com.viaversion.viaversion.api.platform.PlatformTask; +import com.viaversion.viaversion.api.scheduler.Task; +import org.checkerframework.checker.nullness.qual.Nullable; + +public class BukkitViaTaskTask implements PlatformTask { + private final Task task; + + public BukkitViaTaskTask(final Task task) { + this.task = task; + } + + @Override + public @Nullable Task getObject() { + return task; + } + + @Override + public void cancel() { + task.cancel(); + } +} diff --git a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/PaperViaInjector.java b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/PaperViaInjector.java index 7ace83621..f8496d5c2 100644 --- a/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/PaperViaInjector.java +++ b/bukkit/src/main/java/com/viaversion/viaversion/bukkit/platform/PaperViaInjector.java @@ -71,7 +71,7 @@ public final class PaperViaInjector { return hasClass("com.destroystokyo.paper.PaperConfig$PacketLimit") || hasClass("io.papermc.paper.configuration.GlobalConfiguration$PacketLimiter"); } - private static boolean hasClass(final String className) { + public static boolean hasClass(final String className) { try { Class.forName(className); return true; diff --git a/bukkit/src/main/resources/plugin.yml b/bukkit/src/main/resources/plugin.yml index aeb594875..1767de3df 100644 --- a/bukkit/src/main/resources/plugin.yml +++ b/bukkit/src/main/resources/plugin.yml @@ -4,6 +4,7 @@ authors: [ _MylesC, creeper123123321, Gerrygames, kennytv, Matsv ] version: ${version} description: ${description} api-version: 1.13 +folia-supported: true loadbefore: [ ProtocolLib, ProxyPipe, SpigotLib, SkinRestorer ] softdepend: [ ProtocolSupport, PacketListenerApi ] commands: diff --git a/bungee/src/main/java/com/viaversion/viaversion/BungeePlugin.java b/bungee/src/main/java/com/viaversion/viaversion/BungeePlugin.java index 1a90ab2eb..5e37de30a 100644 --- a/bungee/src/main/java/com/viaversion/viaversion/BungeePlugin.java +++ b/bungee/src/main/java/com/viaversion/viaversion/BungeePlugin.java @@ -85,7 +85,9 @@ public class BungeePlugin extends Plugin implements ViaServerProxyPlatform platform; private final ViaInjector injector; private final ViaCommandHandler commandHandler; @@ -77,10 +80,6 @@ public class ViaManagerImpl implements ViaManager { // Reload? platform.onReload(); } - // Check for updates - if (platform.getConf().isCheckForUpdates()) { - UpdateUtil.sendUpdateMessage(); - } // Load supported protocol versions if we can if (!injector.lateProtocolVersionSetting()) { @@ -106,12 +105,14 @@ public class ViaManagerImpl implements ViaManager { listener.run(); } enableListeners = null; - - // If successful - platform.runSync(this::onServerLoaded); } public void onServerLoaded() { + // Check for updates + if (platform.getConf().isCheckForUpdates()) { + UpdateUtil.sendUpdateMessage(); + } + if (!protocolManager.getServerProtocolVersion().isKnown()) { // Try again loadServerProtocol(); @@ -154,7 +155,7 @@ public class ViaManagerImpl implements ViaManager { // Load Platform loader.load(); // Common tasks - mappingLoadingTask = Via.getPlatform().runRepeatingSync(() -> { + mappingLoadingTask = Via.getPlatform().runRepeatingAsync(() -> { if (protocolManager.checkForMappingCompletion() && mappingLoadingTask != null) { mappingLoadingTask.cancel(); mappingLoadingTask = null; @@ -205,11 +206,11 @@ public class ViaManagerImpl implements ViaManager { e.printStackTrace(); } - // Unload loader.unload(); + scheduler.shutdown(); } - private final void checkJavaVersion() { // Stolen from Paper + private void checkJavaVersion() { // Stolen from Paper String javaVersion = System.getProperty("java.version"); Matcher matcher = Pattern.compile("(?:1\\.)?(\\d+)").matcher(javaVersion); if (!matcher.find()) { @@ -299,6 +300,11 @@ public class ViaManagerImpl implements ViaManager { return loader; } + @Override + public Scheduler getScheduler() { + return scheduler; + } + /** * Returns a mutable set of self-added subplatform version strings. * This set is expanded by the subplatform itself (e.g. ViaBackwards), and may not contain all running ones. diff --git a/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java b/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java index 4fc6f39c6..d4639705a 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java +++ b/common/src/main/java/com/viaversion/viaversion/protocol/ProtocolManagerImpl.java @@ -508,7 +508,7 @@ public class ProtocolManagerImpl implements ProtocolManager { registerList.clear(); } - private void shutdownLoaderExecutor() { + public void shutdownLoaderExecutor() { Preconditions.checkArgument(!mappingsLoaded); // If this log message is missing, something is wrong diff --git a/common/src/main/java/com/viaversion/viaversion/scheduler/ScheduledTask.java b/common/src/main/java/com/viaversion/viaversion/scheduler/ScheduledTask.java new file mode 100644 index 000000000..0d64030fa --- /dev/null +++ b/common/src/main/java/com/viaversion/viaversion/scheduler/ScheduledTask.java @@ -0,0 +1,45 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2023 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.viaversion.viaversion.scheduler; + +import com.viaversion.viaversion.api.scheduler.Task; +import com.viaversion.viaversion.api.scheduler.TaskStatus; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +public final class ScheduledTask implements Task { + + private final ScheduledFuture future; + + public ScheduledTask(final ScheduledFuture future) { + this.future = future; + } + + @Override + public TaskStatus status() { + if (future.getDelay(TimeUnit.MILLISECONDS) > 0) { + return TaskStatus.SCHEDULED; + } + return future.isDone() ? TaskStatus.STOPPED : TaskStatus.RUNNING; + } + + @Override + public void cancel() { + future.cancel(false); + } +} diff --git a/common/src/main/java/com/viaversion/viaversion/scheduler/SubmittedTask.java b/common/src/main/java/com/viaversion/viaversion/scheduler/SubmittedTask.java new file mode 100644 index 000000000..5ad44b664 --- /dev/null +++ b/common/src/main/java/com/viaversion/viaversion/scheduler/SubmittedTask.java @@ -0,0 +1,41 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2023 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.viaversion.viaversion.scheduler; + +import com.viaversion.viaversion.api.scheduler.Task; +import com.viaversion.viaversion.api.scheduler.TaskStatus; +import java.util.concurrent.Future; + +public final class SubmittedTask implements Task { + + private final Future future; + + public SubmittedTask(final Future future) { + this.future = future; + } + + @Override + public TaskStatus status() { + return future.isDone() ? TaskStatus.STOPPED : TaskStatus.RUNNING; + } + + @Override + public void cancel() { + future.cancel(false); + } +} diff --git a/common/src/main/java/com/viaversion/viaversion/scheduler/TaskScheduler.java b/common/src/main/java/com/viaversion/viaversion/scheduler/TaskScheduler.java new file mode 100644 index 000000000..7094f073e --- /dev/null +++ b/common/src/main/java/com/viaversion/viaversion/scheduler/TaskScheduler.java @@ -0,0 +1,63 @@ +/* + * This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion + * Copyright (C) 2023 ViaVersion and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package com.viaversion.viaversion.scheduler; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.viaversion.viaversion.api.scheduler.Scheduler; +import com.viaversion.viaversion.api.scheduler.Task; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public final class TaskScheduler implements Scheduler { + + private final ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("Via Async Task %d").build()); + private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool( + 0, + new ThreadFactoryBuilder().setNameFormat("Via Async Scheduler %d").build() + ); + + @Override + public Task execute(final Runnable runnable) { + return new SubmittedTask(executorService.submit(runnable)); + } + + @Override + public Task schedule(final Runnable runnable, final long delay, final TimeUnit timeUnit) { + return new ScheduledTask(scheduledExecutorService.schedule(runnable, delay, timeUnit)); + } + + @Override + public Task scheduleRepeating(final Runnable runnable, final long delay, final long period, final TimeUnit timeUnit) { + return new ScheduledTask(scheduledExecutorService.scheduleAtFixedRate(runnable, delay, period, timeUnit)); + } + + @Override + public void shutdown() { + executorService.shutdown(); + scheduledExecutorService.shutdown(); + + try { + executorService.awaitTermination(2, TimeUnit.SECONDS); + scheduledExecutorService.awaitTermination(2, TimeUnit.SECONDS); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/common/src/main/java/com/viaversion/viaversion/update/UpdateUtil.java b/common/src/main/java/com/viaversion/viaversion/update/UpdateUtil.java index ed50a7632..915a4e675 100644 --- a/common/src/main/java/com/viaversion/viaversion/update/UpdateUtil.java +++ b/common/src/main/java/com/viaversion/viaversion/update/UpdateUtil.java @@ -30,7 +30,7 @@ import java.util.Locale; import java.util.UUID; import org.checkerframework.checker.nullness.qual.Nullable; -public class UpdateUtil { +public final class UpdateUtil { private static final String PREFIX = "§a§l[ViaVersion] §a"; private static final String URL = "https://api.spiget.org/v2/resources/"; diff --git a/common/src/test/java/com/viaversion/viaversion/common/dummy/TestPlatform.java b/common/src/test/java/com/viaversion/viaversion/common/dummy/TestPlatform.java index 210aba024..f11e7a23c 100644 --- a/common/src/test/java/com/viaversion/viaversion/common/dummy/TestPlatform.java +++ b/common/src/test/java/com/viaversion/viaversion/common/dummy/TestPlatform.java @@ -60,6 +60,11 @@ public final class TestPlatform implements ViaPlatform { return null; } + @Override + public PlatformTask runRepeatingAsync(final Runnable runnable, final long ticks) { + return null; + } + @Override public PlatformTask runSync(Runnable runnable) { return null; diff --git a/sponge/src/main/java/com/viaversion/viaversion/SpongePlugin.java b/sponge/src/main/java/com/viaversion/viaversion/SpongePlugin.java index 91687eabc..35c03da58 100644 --- a/sponge/src/main/java/com/viaversion/viaversion/SpongePlugin.java +++ b/sponge/src/main/java/com/viaversion/viaversion/SpongePlugin.java @@ -53,6 +53,7 @@ import org.spongepowered.api.entity.living.player.Player; import org.spongepowered.api.entity.living.player.server.ServerPlayer; import org.spongepowered.api.event.Listener; import org.spongepowered.api.event.lifecycle.ConstructPluginEvent; +import org.spongepowered.api.event.lifecycle.StartedEngineEvent; import org.spongepowered.api.event.lifecycle.StartingEngineEvent; import org.spongepowered.api.event.lifecycle.StoppingEngineEvent; import org.spongepowered.api.scheduler.Task; @@ -102,7 +103,15 @@ public class SpongePlugin implements ViaPlatform { public void onServerStart(StartingEngineEvent event) { // Can't use the command register event for raw commands... Sponge.server().commandManager().registrar(Command.Raw.class).get().register(container, (Command.Raw) Via.getManager().getCommandHandler(), "viaversion", "viaver", "vvsponge"); - ((ViaManagerImpl) Via.getManager()).init(); + + final ViaManagerImpl manager = (ViaManagerImpl) Via.getManager(); + manager.init(); + } + + @Listener + public void onServerStarted(StartedEngineEvent event) { + final ViaManagerImpl manager = (ViaManagerImpl) Via.getManager(); + manager.onServerLoaded(); } @Listener @@ -131,6 +140,12 @@ public class SpongePlugin implements ViaPlatform { return new SpongeViaTask(game.asyncScheduler().submit(task)); } + @Override + public PlatformTask runRepeatingAsync(final Runnable runnable, final long ticks) { + final Task task = Task.builder().plugin(container).execute(runnable).interval(Ticks.of(ticks)).build(); + return new SpongeViaTask(game.asyncScheduler().submit(task)); + } + @Override public PlatformTask runSync(Runnable runnable) { final Task task = Task.builder().plugin(container).execute(runnable).build(); diff --git a/velocity/src/main/java/com/viaversion/viaversion/VelocityPlugin.java b/velocity/src/main/java/com/viaversion/viaversion/VelocityPlugin.java index d3d632e7e..7d796afc4 100644 --- a/velocity/src/main/java/com/viaversion/viaversion/VelocityPlugin.java +++ b/velocity/src/main/java/com/viaversion/viaversion/VelocityPlugin.java @@ -108,7 +108,9 @@ public class VelocityPlugin implements ViaServerProxyPlatform { @Subscribe(order = PostOrder.LAST) public void onProxyLateInit(ProxyInitializeEvent e) { - ((ViaManagerImpl) Via.getManager()).init(); + final ViaManagerImpl manager = (ViaManagerImpl) Via.getManager(); + manager.init(); + manager.onServerLoaded(); } @Override @@ -138,6 +140,15 @@ public class VelocityPlugin implements ViaServerProxyPlatform { return runSync(runnable); } + @Override + public PlatformTask runRepeatingAsync(final Runnable runnable, final long ticks) { + return new VelocityViaTask( + PROXY.getScheduler() + .buildTask(this, runnable) + .repeat(ticks * 50, TimeUnit.MILLISECONDS).schedule() + ); + } + @Override public PlatformTask runSync(Runnable runnable) { return runSync(runnable, 0L); @@ -154,11 +165,7 @@ public class VelocityPlugin implements ViaServerProxyPlatform { @Override public PlatformTask runRepeatingSync(Runnable runnable, long ticks) { - return new VelocityViaTask( - PROXY.getScheduler() - .buildTask(this, runnable) - .repeat(ticks * 50, TimeUnit.MILLISECONDS).schedule() - ); + return runRepeatingAsync(runnable, ticks); } @Override diff --git a/velocity/src/main/java/com/viaversion/viaversion/velocity/platform/VelocityViaLoader.java b/velocity/src/main/java/com/viaversion/viaversion/velocity/platform/VelocityViaLoader.java index 53989cc02..3ab983496 100644 --- a/velocity/src/main/java/com/viaversion/viaversion/velocity/platform/VelocityViaLoader.java +++ b/velocity/src/main/java/com/viaversion/viaversion/velocity/platform/VelocityViaLoader.java @@ -50,7 +50,7 @@ public class VelocityViaLoader implements ViaPlatformLoader { int pingInterval = ((VelocityViaConfig) Via.getPlatform().getConf()).getVelocityPingInterval(); if (pingInterval > 0) { - Via.getPlatform().runRepeatingSync( + Via.getPlatform().runRepeatingAsync( () -> Via.proxyPlatform().protocolDetectorService().probeAllServers(), pingInterval * 20L); }