This commit is contained in:
Sekwah 2023-11-05 06:53:21 -07:00 committed by GitHub
commit fc94fe9896
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 248 additions and 46 deletions

View File

@ -25,7 +25,7 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: 8
java-version: 17
- name: Use Node.js 12.x
uses: actions/setup-node@v2
with:

View File

@ -47,10 +47,11 @@ def isCanary = version.toString().contains('canary')
group = 'com.sekwah.advancedportals'
archivesBaseName = "Advanced-Portals"
description = ""
sourceCompatibility = 1.8
targetCompatibility = 1.8
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
@ -79,7 +80,7 @@ repositories {
maven { url "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" }
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
maven { url "https://nexus.velocitypowered.com/repository/maven-public/" }
maven { url 'https://papermc.io/repo/repository/maven-public/' }
maven { url 'https://repo.papermc.io/repository/maven-public/' }
maven { url 'https://maven.enginehub.org/repo/' } // WorldEdit
}
@ -94,7 +95,9 @@ dependencies {
annotationProcessor "com.velocitypowered:velocity-api:3.1.1"
implementation "io.netty:netty-all:4.1.91.Final"
compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT'
//compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT'
//compileOnly 'io.papermc.paper:paper-api:1.19-R0.1-SNAPSHOT'
compileOnly "dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT"
implementation "com.sk89q.worldedit:worldedit-bukkit:7.2.14"
//compile fileTree(dir: 'libs', include: ['*.jar'])
@ -142,8 +145,12 @@ task discordupload {
}
minecraftServerConfig {
//jarUrl.set('https://download.getbukkit.org/spigot/spigot-1.19.3.jar')
jarUrl.set('https://api.papermc.io/v2/projects/paper/versions/1.19.3/builds/381/downloads/paper-1.19.3-381.jar')
// The oldest version of spigot currently supported.
//jarUrl.set('https://cdn.getbukkit.org/spigot/spigot-1.17.jar')
//jarUrl.set('https://cdn.getbukkit.org/spigot/spigot-1.20.1.jar')
//jarUrl.set('https://api.papermc.io/v2/projects/paper/versions/1.13.2/builds/657/downloads/paper-1.13.2-657.jar')
//jarUrl.set('https://api.papermc.io/v2/projects/paper/versions/1.20.1/builds/83/downloads/paper-1.20.1-83.jar')
jarUrl.set('https://api.papermc.io/v2/projects/folia/versions/1.20.1/builds/10/downloads/folia-1.20.1-10.jar')
jvmArgument = ["-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005", "-DIReallyKnowWhatIAmDoingISwear=true"]
}
@ -262,12 +269,17 @@ task curseforge {
def versions = gameVersions.findAll { it.gameVersionTypeID == gameVersionTypeID }
String[] supportedVersions = [
"1.20.1",
"1.20",
"1.19.4",
"1.19.3",
"1.19.2",
"1.19.1",
"1.19",
"1.18.2",
"1.18.1",
"1.18",
"1.17",
"1.16",
"1.15",
"1.14",
"1.13"
]
def supportedGameVersions = versions.findAll { supportedVersions.contains(it.name) }
@ -298,24 +310,21 @@ task curseforge {
// releaseType = 'release'
}
task copyPlugin {
task copyPlugin() {
doLast {
copy {
if (System.env.MC_SERVER_LOC == null) {
throw new Exception('You must set the server location and jar to use')
}
println "$buildDir/libs/Advanced-Portals-${version}.jar"
println "${System.env.MC_SERVER_LOC}/plugins/Advanced-Portals-${version}.jar"
println "$buildDir/libs/Advanced-Portals-${getVersion()}.jar"
println "$buildDir/MinecraftServer/plugins/Advanced-Portals-${getVersion()}.jar"
try {
delete fileTree("${System.env.MC_SERVER_LOC}/plugins/") {
delete fileTree("$buildDir/MinecraftServer/plugins/") {
include "*.jar"
}
}
catch (RuntimeException e) {
println e.getLocalizedMessage()
}
from file("$buildDir/libs/Advanced-Portals-${version}.jar")
into file("${System.env.MC_SERVER_LOC}/plugins/")
from file("$buildDir/libs/Advanced-Portals-${getVersion()}.jar")
into file("$buildDir/MinecraftServer/plugins")
}
}
}

View File

@ -8,6 +8,7 @@ import com.sekwah.advancedportals.bukkit.effects.WarpEffects;
import com.sekwah.advancedportals.bukkit.listeners.*;
import com.sekwah.advancedportals.bukkit.metrics.Metrics;
import com.sekwah.advancedportals.bukkit.portals.Portal;
import com.sekwah.advancedportals.bukkit.util.ForkDetector;
import com.sekwah.advancedportals.bungee.BungeeMessages;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
@ -15,8 +16,8 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.awt.print.Paper;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
@ -81,7 +82,6 @@ public class AdvancedPortalsPlugin extends JavaPlugin {
for (Player player:
this.getServer().getOnlinePlayers()) {
player.removeMetadata(Listeners.HAS_WARPED, this);
player.removeMetadata(Listeners.LAVA_WARPED, this);
}
@ -137,9 +137,7 @@ public class AdvancedPortalsPlugin extends JavaPlugin {
private boolean checkIfBungee()
{
// we check if the server is Spigot/Paper (because of the spigot.yml file)
try {
Class.forName("org.spigotmc.SpigotConfig");
} catch (ClassNotFoundException e) {
if(!ForkDetector.isSpigot()) {
this.getServer().getConsoleSender().sendMessage( "\u00A7ePossibly unsupported version for bungee messages detected, channels won't be enabled." );
getLogger().info("If you believe this shouldn't be the case please contact us on discord https://discord.sekwah.com/");
return false;

View File

@ -1,6 +1,9 @@
package com.sekwah.advancedportals.bukkit;
import com.sekwah.advancedportals.bukkit.config.ConfigAccessor;
import com.sekwah.advancedportals.bukkit.listeners.Listeners;
import com.sekwah.advancedportals.bukkit.util.FoliaHandler;
import com.sekwah.advancedportals.bukkit.util.ForkDetector;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@ -133,11 +136,12 @@ public class Selection {
}
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
public void run() {
Selection.hide(player, plugin, pos1, pos2);
}
}, timeout * 20);
Runnable hideRun = () -> Selection.hide(player, plugin, pos1, pos2);
if(ForkDetector.isFolia()) {
FoliaHandler.scheduleEntityTask(plugin, player, hideRun, 10);
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, hideRun, timeout * 20);
}
}

View File

@ -6,6 +6,7 @@ import com.sekwah.advancedportals.bukkit.config.ConfigAccessor;
import com.sekwah.advancedportals.bukkit.effects.WarpEffects;
import com.sekwah.advancedportals.bukkit.portals.AdvancedPortal;
import com.sekwah.advancedportals.bukkit.portals.Portal;
import com.sekwah.advancedportals.bukkit.util.ForkDetector;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
@ -14,8 +15,10 @@ import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Level;
public class Destination {
@ -146,12 +149,29 @@ public class Destination {
if (player.getVehicle() != null && TELEPORT_RIDING) {
riding.eject();
riding.teleport(loc, PlayerTeleportEvent.TeleportCause.PLUGIN);
player.teleport(loc, PlayerTeleportEvent.TeleportCause.PLUGIN);
riding.setPassenger(player);
if(ForkDetector.isFolia()) {
riding.teleportAsync(loc, PlayerTeleportEvent.TeleportCause.PLUGIN).thenAccept((result) -> {
if(result) {
player.teleportAsync(loc, PlayerTeleportEvent.TeleportCause.PLUGIN).thenAccept((result2) -> {
if(result2) {
riding.setPassenger(player);
}
});
}
});
} else {
riding.teleport(loc, PlayerTeleportEvent.TeleportCause.PLUGIN);
player.teleport(loc, PlayerTeleportEvent.TeleportCause.PLUGIN);
riding.setPassenger(player);
}
} else {
player.teleport(loc, PlayerTeleportEvent.TeleportCause.PLUGIN);
if(ForkDetector.isFolia()) {
player.teleportAsync(loc, PlayerTeleportEvent.TeleportCause.PLUGIN);
} else {
player.teleport(loc, PlayerTeleportEvent.TeleportCause.PLUGIN);
}
}
if (disp != null && disp.getArg("particleout") != null) {

View File

@ -7,6 +7,7 @@ import com.sekwah.advancedportals.bukkit.config.ConfigAccessor;
import com.sekwah.advancedportals.bukkit.destinations.Destination;
import com.sekwah.advancedportals.bukkit.portals.AdvancedPortal;
import com.sekwah.advancedportals.bukkit.portals.Portal;
import com.sekwah.advancedportals.bukkit.util.ForkDetector;
import org.bukkit.*;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.Orientable;
@ -26,6 +27,7 @@ import org.bukkit.metadata.FixedMetadataValue;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import com.sekwah.advancedportals.bukkit.util.FoliaHandler;
public class Listeners implements Listener {
@ -36,6 +38,8 @@ public class Listeners implements Listener {
public static String HAS_WARPED = "hasWarped";
public static String LAVA_WARPED = "lavaWarped";
// Just a backup in case it doesn't get removed.
public static long MAX_SAFETY_TIME = 1000;
@SuppressWarnings("deprecation")
public Listeners(AdvancedPortalsPlugin plugin) {
@ -56,7 +60,12 @@ public class Listeners implements Listener {
int cleanPeriod = config.getConfig().getInt("CleanUpPeriod", 120);
int period = 20 * 60 * cleanPeriod;
Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, new CooldownDataRemovalTask(), period, period);
if(ForkDetector.isFolia()) {
FoliaHandler.repeatingTask(plugin, new CooldownDataRemovalTask(), period);
} else {
plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, new CooldownDataRemovalTask(),
period, period);
}
}
@SuppressWarnings("deprecation")
@ -80,7 +89,9 @@ public class Listeners implements Listener {
@EventHandler
public void onWorldChangeEvent(PlayerChangedWorldEvent event) {
Portal.joinCooldownLock.writeLock().lock();
Portal.joinCooldown.put(event.getPlayer().getName(), System.currentTimeMillis());
Portal.joinCooldownLock.writeLock().unlock();
}
@EventHandler
@ -96,7 +107,9 @@ public class Listeners implements Listener {
public void onJoinEvent(PlayerJoinEvent event) {
Player player = event.getPlayer();
Portal.joinCooldownLock.writeLock().lock();
Portal.joinCooldown.put(player.getName(), System.currentTimeMillis());
Portal.joinCooldownLock.writeLock().unlock();
Location loc = player.getLocation();
Location eyeLoc = player.getEyeLocation();
@ -137,11 +150,20 @@ public class Listeners implements Listener {
if (delayed ? Portal.locationInPortal(portal, loc, 1)
: Portal.locationInPortalTrigger(portal, loc)) {
player.setMetadata(HAS_WARPED, new FixedMetadataValue(plugin, true));
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveWarpData(player), 10);
player.setMetadata(HAS_WARPED, new FixedMetadataValue(plugin, System.currentTimeMillis()));
if(ForkDetector.isFolia()) {
FoliaHandler.scheduleEntityTask(plugin, player, new RemoveWarpData(player), 10);
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveWarpData(player), 10);
}
if (portal.getTriggers().contains(Material.LAVA)) {
player.setMetadata(LAVA_WARPED, new FixedMetadataValue(plugin, true));
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveLavaData(player), 10);
player.setMetadata(LAVA_WARPED, new FixedMetadataValue(plugin, System.currentTimeMillis()));
if(ForkDetector.isFolia()) {
FoliaHandler.scheduleEntityTask(plugin, player, new RemoveLavaData(player), 10);
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, new RemoveLavaData(player), 10);
}
}
if (portal.inPortal.contains(player.getUniqueId()))
return;
@ -210,13 +232,18 @@ public class Listeners implements Listener {
}
private void resizeMaps() {
Portal.cooldownLock.writeLock().lock();
HashMap<String, HashMap<String, Long>> newCooldowns = new HashMap<String, HashMap<String, Long>>(Math.max(Portal.cooldown.size() * 2, 10));
newCooldowns.putAll(Portal.cooldown);
Portal.cooldown = newCooldowns;
Portal.cooldownLock.writeLock().unlock();
Portal.joinCooldownLock.writeLock().lock();
HashMap<String, Long> newJoinCooldowns = new HashMap<String, Long>(Math.max(Portal.joinCooldown.size() * 2, 10));
newJoinCooldowns.putAll(Portal.joinCooldown);
Portal.joinCooldown = newJoinCooldowns;
Portal.joinCooldownLock.writeLock().unlock();
}
}
@ -263,7 +290,7 @@ public class Listeners implements Listener {
if (event.getEntity() instanceof Player && (event.getCause() == EntityDamageEvent.DamageCause.LAVA
|| event.getCause() == EntityDamageEvent.DamageCause.FIRE
|| event.getCause() == EntityDamageEvent.DamageCause.FIRE_TICK)) {
if (event.getEntity().hasMetadata(LAVA_WARPED)
if ((event.getEntity().hasMetadata(LAVA_WARPED) && event.getEntity().getMetadata(LAVA_WARPED).get(0).asLong() + MAX_SAFETY_TIME > System.currentTimeMillis())
| Portal.inPortalTriggerRegion(event.getEntity().getLocation()))
event.setCancelled(true);
}
@ -283,15 +310,33 @@ public class Listeners implements Listener {
checkTriggerLocations(player, true, loc, eyeLoc);
}
if (player.hasMetadata(HAS_WARPED) | Portal.inPortalRegion(event.getFrom(), 1))
if ((player.hasMetadata(HAS_WARPED) && player.getMetadata(HAS_WARPED).get(0).asLong() + MAX_SAFETY_TIME > System.currentTimeMillis()) | Portal.inPortalRegion(event.getFrom(), 1))
event.setCancelled(true);
}
@EventHandler(ignoreCancelled = true)
public void onTeleport(PlayerTeleportEvent event) {
Player player = event.getPlayer();
if((event.getCause() == PlayerTeleportEvent.TeleportCause.END_GATEWAY
|| event.getCause() == PlayerTeleportEvent.TeleportCause.END_PORTAL
|| event.getCause() == PlayerTeleportEvent.TeleportCause.NETHER_PORTAL)
&& (Portal.locationInPortal(event.getFrom(), 1) || player.hasMetadata(HAS_WARPED))) {
event.setCancelled(true);
}
Location loc = event.getFrom();
Location eyeLoc = new Location(loc.getWorld(), loc.getX(), loc.getY() + player.getEyeHeight(), loc.getZ());
checkTriggerLocations(player, true, loc, eyeLoc);
}
@EventHandler(ignoreCancelled = true)
public void onEntityPortalEvent(EntityPortalEvent event) {
if (event.isCancelled()) {
return;
}
if(Portal.locationInPortal(event.getFrom(), 2)) {
event.setCancelled(true);
}

View File

@ -3,6 +3,7 @@ package com.sekwah.advancedportals.bukkit.listeners;
import com.sekwah.advancedportals.bukkit.AdvancedPortalsPlugin;
import com.sekwah.advancedportals.bukkit.config.ConfigAccessor;
import com.sekwah.advancedportals.bukkit.portals.Portal;
import com.sekwah.advancedportals.bukkit.util.ForkDetector;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
@ -66,7 +67,8 @@ public class PortalPlacer implements Listener {
if(!this.DISABLE_GATEWAY_BEAM) {
return;
}
BlockState[] tileEntities = event.getChunk().getTileEntities();
// TODO take a look at potentially switching to the paper logic if paper is in use, also you can check if the chunk even contains a portal.
BlockState[] tileEntities = ForkDetector.isPaper() ? event.getChunk().getTileEntities(false) : event.getChunk().getTileEntities();
for(BlockState block : tileEntities) {
if(block.getType() == Material.END_GATEWAY) {
if(Portal.inPortalRegion(block.getLocation(), 5)) {

View File

@ -3,6 +3,8 @@ package com.sekwah.advancedportals.bukkit.metrics;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.sekwah.advancedportals.bukkit.util.FoliaHandler;
import com.sekwah.advancedportals.bukkit.util.ForkDetector;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
@ -173,7 +175,11 @@ public class Metrics {
}
// Nevertheless we want our code to run in the Bukkit main thread, so we have to use the Bukkit scheduler
// Don't be afraid! The connection to the bStats server is still async, only the stats collection is sync ;)
Bukkit.getScheduler().runTask(plugin, () -> submitData());
if(ForkDetector.isFolia()) {
FoliaHandler.runAsyncTask(plugin, () -> submitData());
} else {
Bukkit.getScheduler().runTask(plugin, () -> submitData());
}
}
}, 1000 * 60 * 5, 1000 * 60 * 30);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start

View File

@ -4,11 +4,14 @@ import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import com.sekwah.advancedportals.bukkit.AdvancedPortalsPlugin;
import com.sekwah.advancedportals.bukkit.PluginMessages;
import com.sekwah.advancedportals.bukkit.Selection;
import com.sekwah.advancedportals.bukkit.api.portaldata.PortalArg;
import com.sekwah.advancedportals.bukkit.config.ConfigAccessor;
import com.sekwah.advancedportals.bukkit.config.ConfigHelper;
import com.sekwah.advancedportals.bukkit.destinations.Destination;
import com.sekwah.advancedportals.bukkit.effects.WarpEffects;
import com.sekwah.advancedportals.bukkit.util.FoliaHandler;
import com.sekwah.advancedportals.bukkit.util.ForkDetector;
import com.sekwah.advancedportals.bungee.BungeeMessages;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
@ -20,12 +23,22 @@ import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.util.Vector;
import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.stream.Collectors;
public class Portal {
/**
* Only used for Folia
*/
public static final ReentrantReadWriteLock joinCooldownLock = new ReentrantReadWriteLock();
public static HashMap<String, Long> joinCooldown = new HashMap<String, Long>();
/**
* Only used for Folia
*/
public static final ReentrantReadWriteLock cooldownLock = new ReentrantReadWriteLock();
public static HashMap<String, HashMap<String, Long>> cooldown = new HashMap<String, HashMap<String, Long>>();
// Config values
public static boolean portalsActive = false;
@ -467,7 +480,10 @@ public class Portal {
return false;
}
Portal.joinCooldownLock.readLock().lock();
Long joinCD = joinCooldown.get(player.getName());
Portal.joinCooldownLock.readLock().unlock();
if (joinCD != null) {
int diff = (int) ((System.currentTimeMillis() - joinCD) / 1000);
if (diff < joinCooldownDelay) {
@ -478,9 +494,12 @@ public class Portal {
throwPlayerBack(player);
return false;
}
Portal.joinCooldownLock.writeLock().lock();
joinCooldown.remove(player.getName());
Portal.joinCooldownLock.writeLock().unlock();
}
cooldownLock.writeLock().lock();
HashMap<String, Long> cds = cooldown.get(player.getName());
if (cds != null) {
if (cds.get(portal.getName()) != null) {
@ -507,6 +526,7 @@ public class Portal {
}
cds.put(portal.getName(), System.currentTimeMillis());
cooldown.put(player.getName(), cds);
cooldownLock.writeLock().unlock();
boolean showFailMessage = !portal.hasArg("command.1");
@ -524,9 +544,14 @@ public class Portal {
if(portal.hasArg("leavedesti")) {
player.setMetadata("leaveDesti", new FixedMetadataValue(plugin, portal.getArg("leavedesti")));
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, () -> {
Runnable removeMeta = () -> {
player.removeMetadata("leaveDesti", plugin);
}, 20 * 10);
};
if(ForkDetector.isFolia()) {
FoliaHandler.scheduleEntityTask(plugin, player, removeMeta, 20 * 10);
} else {
Bukkit.getScheduler().scheduleSyncDelayedTask(plugin, removeMeta, 20 * 10);
}
}
if (portal.getDestinations().length != 0) {

View File

@ -0,0 +1,53 @@
package com.sekwah.advancedportals.bukkit.util;
import com.sekwah.advancedportals.bukkit.AdvancedPortalsPlugin;
import org.bukkit.entity.Entity;
import org.bukkit.plugin.Plugin;
import java.util.concurrent.TimeUnit;
/**
* This is to stop jars such as spigot complaining about folia imports
*/
public class FoliaHandler {
public static void repeatingTask(AdvancedPortalsPlugin plugin, Runnable runnable, int ticks) {
plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, (task) -> {
runnable.run();
}, ticks, ticks);
}
public static void scheduleTask(AdvancedPortalsPlugin plugin, Runnable runnable, int ticks) {
plugin.getServer().getGlobalRegionScheduler().runDelayed(plugin, (task) -> {
runnable.run();
}, ticks);
}
public static void scheduleAsyncTask(Plugin plugin, Runnable runnable, int ticks) {
plugin.getServer().getAsyncScheduler().runDelayed(plugin, (task) -> {
runnable.run();
}, ticks * 1000L / 20L, TimeUnit.MILLISECONDS);
}
public static void runAsyncTask(Plugin plugin, Runnable runnable) {
plugin.getServer().getAsyncScheduler().runNow(plugin, (task) -> {
runnable.run();
});
}
/**
* Will run if the entity isn't destroyed, if you want to run something different in that case also supply a retired runnable.
* @param plugin
* @param entity
* @param runnable
* @param ticks
*/
public static void scheduleEntityTask(Plugin plugin, Entity entity, Runnable runnable, int ticks) {
scheduleEntityTask(plugin, entity, runnable, null, ticks);
}
public static void scheduleEntityTask(Plugin plugin, Entity entity, Runnable runnable, Runnable retired, int ticks) {
entity.getScheduler().runDelayed(plugin, (task) -> {
runnable.run();
}, retired, ticks);
}
}

View File

@ -0,0 +1,38 @@
package com.sekwah.advancedportals.bukkit.util;
public class ForkDetector {
public static boolean isSpigot() {
try {
Class.forName("org.spigotmc.SpigotConfig");
}
catch (Exception e) {
return false;
}
return true;
}
public static boolean isPaper() {
try {
Class.forName("com.destroystokyo.paper.PaperConfig");
}
catch (Exception e) {
return false;
}
return true;
}
public static boolean isFolia() {
try {
Class.forName("io.papermc.paper.threadedregions.scheduler.AsyncScheduler");
}
catch (Exception e) {
return false;
}
return true;
}
}

View File

@ -4,6 +4,8 @@ version: 0.9.3
author: sekwah41
description: An advanced portals plugin for bukkit.
api-version: 1.13
folia-supported: true
website: https://advancedportals.sekwah.com/
softdepend:
- WorldEdit