Start hard-fork from Luminol

This commit is contained in:
Helvetica Volubi
2026-07-18 01:27:14 +08:00
parent f4aea025c1
commit 0678cc6e46
365 changed files with 28337 additions and 657 deletions
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 10:18:38 +0800
Subject: [PATCH] Rebrand to Luminol
diff --git a/src/main/java/io/papermc/paper/ServerBuildInfo.java b/src/main/java/io/papermc/paper/ServerBuildInfo.java
index 652ff54e7c50412503725d628bfe72ed03059790..db5e2f10278c20286779362cfdfadb2f42c724e0 100644
--- a/src/main/java/io/papermc/paper/ServerBuildInfo.java
+++ b/src/main/java/io/papermc/paper/ServerBuildInfo.java
@@ -19,6 +19,17 @@ public interface ServerBuildInfo {
*/
Key BRAND_PAPER_ID = Key.key("papermc", "paper");
+ // Luminol start
+ /**
+ * The brand id for folia
+ */
+ Key BRAND_FOLIA_ID = Key.key("papermc", "folia");
+ /**
+ * The brand id for Luminol.
+ */
+ Key BRAND_LUMINOL_ID = Key.key("luminolmc", "luminol");
+ // Luminol end
+
/**
* Gets the {@code ServerBuildInfo}.
*
@@ -0,0 +1,22 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 14 Jun 2026 18:10:20 +0800
Subject: [PATCH] Luminol Config System
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index fb5ca3ab0ddba433a39e65572beeb955b50d6f72..42335e351e0cb4f82f46501503a15349f8a82e1b 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2776,6 +2776,11 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
*/
void allowPausing(@NotNull org.bukkit.plugin.Plugin plugin, boolean value);
// Paper end - API to check if the server is sleeping
+
+ // Luminol start - Luminol Config API
+ me.earthme.luminol.api.config.LuminolConfigsInstance getLuminolConfigs(String name);
+ // Luminol end - Luminol Config API
+
// Folia start - region TPS API
/**
* Gets the TPS from the region which owns the specified location, or {@code null} if no region owns
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 28 Jun 2026 16:40:49 +0800
Subject: [PATCH] KioCG Chunk API
diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java
index d873b78f6935a23ff8f6092b80968267b182cc0f..b4323370859dd4d9e86614484cdb9d2e35c45b40 100644
--- a/src/main/java/org/bukkit/Chunk.java
+++ b/src/main/java/org/bukkit/Chunk.java
@@ -392,4 +392,6 @@ public interface Chunk extends PersistentDataHolder {
*/
UNLOADED;
}
+
+ long getChunkHotAvg(); // KioCG
}
diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
index 7a719d31fbc7633a9bb87ea97338190ee3a6047a..b79b9a2ad108c0488d3cc3862f72985059bb4988 100644
--- a/src/main/java/org/bukkit/entity/Player.java
+++ b/src/main/java/org/bukkit/entity/Player.java
@@ -4020,4 +4020,6 @@ public interface Player extends HumanEntity, Conversable, OfflinePlayer, PluginM
default ObjectContents asObjectContents() {
return this.getPlayerProfile().asObjectContents();
}
+
+ long getNearbyChunkHot(); // KioCG
}
@@ -0,0 +1,45 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 12:22:53 +0800
Subject: [PATCH] Disable timings warn msg and commands
diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java
index 89017af09ce32e7a66014fc3aeb50155921252a5..b862779b48176dd7e67a2f1a3e7f24bc8c84e993 100644
--- a/src/main/java/co/aikar/timings/Timings.java
+++ b/src/main/java/co/aikar/timings/Timings.java
@@ -147,7 +147,7 @@ public final class Timings {
public static void setTimingsEnabled(boolean enabled) {
enabled = false; // Folia - region threading - disable timings
if (enabled && !warnedAboutDeprecationOnEnable) {
- Bukkit.getLogger().severe(PlainTextComponentSerializer.plainText().serialize(deprecationMessage()));
+ // Bukkit.getLogger().severe(PlainTextComponentSerializer.plainText().serialize(deprecationMessage())); // Luminol - Disable timings warn msg and commands
warnedAboutDeprecationOnEnable = true;
}
}
diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
index ad1330d87223dfcf3c9da40aa5ece8c21141f0d6..22edf161ba1ca8c31140e25e8c4fe1503c44dba8 100644
--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
@@ -34,7 +34,7 @@ public class SimpleCommandMap implements CommandMap {
final ReloadCommand reload = new ReloadCommand("reload");
this.knownCommands.put("bukkit:reload", reload);
this.knownCommands.put("bukkit:rl", reload);
- register("bukkit", new co.aikar.timings.TimingsCommand("timings"));
+ //register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Luminol - Disable timings warn msg and commands
}
public void setFallbackCommands() {
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
index 457e75bbecb70ac3da4c21382f97d68de5a00547..cf22ea227f6dcc13702fb5f6f94bba5b6e326b97 100644
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
@@ -960,7 +960,7 @@ public final class SimplePluginManager implements PluginManager {
*/
@Deprecated(forRemoval = true)
public void useTimings(boolean use) {
- co.aikar.timings.Timings.setTimingsEnabled(use); // Paper
+ // co.aikar.timings.Timings.setTimingsEnabled(use); // Paper // Luminol - Disable timings warn msg and commands
}
// Paper start
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Thu, 23 Jan 2025 12:04:04 +0800
Subject: [PATCH] Force disable reload command
diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
index 22edf161ba1ca8c31140e25e8c4fe1503c44dba8..50384eb221ad96e766b91335ff57b082410885e9 100644
--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
@@ -31,9 +31,9 @@ public class SimpleCommandMap implements CommandMap {
}
private void setDefaultCommands() {
- final ReloadCommand reload = new ReloadCommand("reload");
- this.knownCommands.put("bukkit:reload", reload);
- this.knownCommands.put("bukkit:rl", reload);
+ //final ReloadCommand reload = new ReloadCommand("reload"); // Luminol - Force disable reload command
+ //this.knownCommands.put("bukkit:reload", reload); // Luminol - Force disable reload command
+ //this.knownCommands.put("bukkit:rl", reload); // Luminol - Force disable reload command
//register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Luminol - Disable timings warn msg and commands
}
@@ -0,0 +1,62 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 13:27:38 +0800
Subject: [PATCH] Pufferfish: Sentry
As part of: Pufferfish
Licensed under: GPL-3.0 (https://github.com/pufferfish-gg/Pufferfish/blob/04bc249f9eee6157338b6884113b6fa3192bf59b/PATCH-LICENSE)
diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
index cf22ea227f6dcc13702fb5f6f94bba5b6e326b97..71ef6055df30506bb0d6648a2300d1cab7b0d026 100644
--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
@@ -596,7 +596,9 @@ public final class SimplePluginManager implements PluginManager {
// Paper start
private void handlePluginException(String msg, Throwable ex, Plugin plugin) {
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
server.getLogger().log(Level.SEVERE, msg, ex);
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerPluginEnableDisableException(msg, ex, plugin)));
}
// Paper end
@@ -666,9 +668,11 @@ public final class SimplePluginManager implements PluginManager {
));
}
} catch (Throwable ex) {
+ gg.pufferfish.pufferfish.sentry.SentryContext.setEventContext(event, registration); // Pufferfish
// Paper start - error reporting
String msg = "Could not pass event " + event.getEventName() + " to " + registration.getPlugin().getDescription().getFullName();
server.getLogger().log(Level.SEVERE, msg, ex);
+ gg.pufferfish.pufferfish.sentry.SentryContext.removeEventContext(); // Pufferfish
if (!(event instanceof com.destroystokyo.paper.event.server.ServerExceptionEvent)) { // We don't want to cause an endless event loop
callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerEventException(msg, ex, registration.getPlugin(), registration.getListener(), event)));
}
diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
index 9023a39c6481710478747482f0b16c21274afd15..0755065f86aba3ef5ecdf045620878eb045f4999 100644
--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
@@ -329,7 +329,13 @@ public final class JavaPluginLoader implements PluginLoader {
try {
jPlugin.setEnabled(true);
} catch (Throwable ex) {
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
server.getLogger().log(Level.SEVERE, "Error occurred while enabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
+ // Paper start - Disable plugins that fail to load
+ this.server.getPluginManager().disablePlugin(jPlugin);
+ return;
+ // Paper end
}
// Perhaps abort here, rather than continue going, but as it stands,
@@ -354,7 +360,9 @@ public final class JavaPluginLoader implements PluginLoader {
try {
jPlugin.setEnabled(false);
} catch (Throwable ex) {
+ gg.pufferfish.pufferfish.sentry.SentryContext.setPluginContext(plugin); // Pufferfish
server.getLogger().log(Level.SEVERE, "Error occurred while disabling " + plugin.getDescription().getFullName() + " (Is it up to date?)", ex);
+ gg.pufferfish.pufferfish.sentry.SentryContext.removePluginContext(); // Pufferfish
}
if (cloader instanceof PluginClassLoader) {
@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Sun, 12 Jan 2025 14:00:28 +0800
Subject: [PATCH] Pufferfish: SIMD Utilities
As part of: Pufferfish
Licensed under: GPL-3.0 (https://github.com/pufferfish-gg/Pufferfish/blob/04bc249f9eee6157338b6884113b6fa3192bf59b/PATCH-LICENSE)
diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java
index 76ae2750ff7b04a281d4b794dc1f48dd832db2b6..fc9cd106b1ed2e92aced783e9cb0bc8867828df3 100644
--- a/src/main/java/org/bukkit/map/MapPalette.java
+++ b/src/main/java/org/bukkit/map/MapPalette.java
@@ -35,7 +35,7 @@ public final class MapPalette {
}
@NotNull
- static final Color[] colors = {
+ public static final Color[] colors = { // Luminol - package-private -> public
// Start generate - MapPalette#colors
new Color(0x00000000, true),
new Color(0x00000000, true),
@@ -394,9 +394,11 @@ public final class MapPalette {
temp.getRGB(0, 0, temp.getWidth(), temp.getHeight(), pixels, 0, temp.getWidth());
byte[] result = new byte[temp.getWidth() * temp.getHeight()];
+ if ((mapColorCache != null && mapColorCache.isCached()) || !gg.pufferfish.pufferfish.simd.SIMDDetection.isEnabled) { // Luminol - Pufferfish - vectorized map color conversion
for (int i = 0; i < pixels.length; i++) {
result[i] = matchColor(new Color(pixels[i], true));
}
+ } else gg.pufferfish.pufferfish.simd.VectorMapPalette.matchColorVectorized(pixels, result); // Luminol - Pufferfish - vectorized map color conversion
return result;
}
@@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <wangxyper@163.com>
Date: Mon, 27 Jan 2025 13:01:59 +0800
Subject: [PATCH] Tick regions api
diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java
index c66cd17fd037b73d8ff04dd2ed328ca25e8b0f1a..b86cd3b37ec3fd63f34acd6bf17f6a91c24b5038 100644
--- a/src/main/java/org/bukkit/World.java
+++ b/src/main/java/org/bukkit/World.java
@@ -4708,4 +4708,8 @@ public interface World extends RegionAccessor, WorldInfo, PluginMessageRecipient
}
}
}
+
+ // Luminol start - Tick regions api
+ me.earthme.luminol.api.ThreadedRegionizer getThreadedRegionizer();
+ // Luminol end - Tick regions api
}
@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Wed, 22 Apr 2026 12:59:08 +0800
Subject: [PATCH] Leaves: Leaves plugin
Co-authored by: MC_XiaoHei <xiaohei.xor7@outlook.com>
As part of: Leaves (https://github.com/HyacinthHaru/Leaves/blob/90080d238e2fcfc14a9293150dc351a4f0f696e6/leaves-api/paper-patches/features/0009-Leaves-Plugin.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
index 8a24b84db656da4cec59e9bccac306467c8155b0..0ac1e049fad85de8365380b03e60d915ee643f16 100644
--- a/src/main/java/org/bukkit/Bukkit.java
+++ b/src/main/java/org/bukkit/Bukkit.java
@@ -3046,4 +3046,10 @@ public final class Bukkit {
public static void restart() {
server.restart();
}
+
+ // Leaves start - Feature API
+ public static org.leavesmc.leaves.plugin.FeatureManager getFeatureManager() {
+ return server.getFeatureManager();
+ }
+ // Leaves end - Feature API
}
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index 42335e351e0cb4f82f46501503a15349f8a82e1b..cd5f47f6d7fa15c1533724673b8bc2c75394795b 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -2781,6 +2781,10 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
me.earthme.luminol.api.config.LuminolConfigsInstance getLuminolConfigs(String name);
// Luminol end - Luminol Config API
+ // Leaves start - Feature API
+ org.leavesmc.leaves.plugin.FeatureManager getFeatureManager();
+ // Leaves End - Feature API
+
// Folia start - region TPS API
/**
* Gets the TPS from the region which owns the specified location, or {@code null} if no region owns
@@ -0,0 +1,86 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sat, 24 May 2025 01:25:10 +0800
Subject: [PATCH] Leaves: Fix SculkCatalyst exp skip
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As part of: Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc14e2e0225009cf9919072f7f/leaves-api/paper-patches/features/0007-Fix-SculkCatalyst-exp-skip.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java
index 76c08499b704a6cb0cb95ce69b9a9248d69cc127..d516595a8675a9f3d9c14658b66160ba4b3c4278 100644
--- a/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java
+++ b/src/main/java/org/bukkit/event/entity/EntityDeathEvent.java
@@ -27,6 +27,7 @@ public class EntityDeathEvent extends EntityEvent implements Cancellable {
@Nullable private org.bukkit.SoundCategory deathSoundCategory;
private float deathSoundVolume;
private float deathSoundPitch;
+ private int rewardExp; // Leaves - exp fix
private boolean cancelled;
@@ -35,13 +36,20 @@ public class EntityDeathEvent extends EntityEvent implements Cancellable {
this(livingEntity, damageSource, drops, 0);
}
- @ApiStatus.Internal
public EntityDeathEvent(@NotNull final LivingEntity livingEntity, @NotNull DamageSource damageSource, @NotNull final List<ItemStack> drops, final int droppedExp) {
+ // Leaves start - exp fix
+ this(livingEntity, damageSource, drops, droppedExp, droppedExp);
+ }
+
+ @ApiStatus.Internal
+ public EntityDeathEvent(@NotNull final LivingEntity livingEntity, @NotNull DamageSource damageSource, @NotNull final List<ItemStack> drops, final int droppedExp, final int rewardExp) {
super(livingEntity);
this.damageSource = damageSource;
this.drops = drops;
this.dropExp = droppedExp;
+ this.rewardExp = rewardExp;
}
+ // Leaves end - exp fix
@NotNull
@Override
@@ -230,4 +238,14 @@ public class EntityDeathEvent extends EntityEvent implements Cancellable {
public static HandlerList getHandlerList() {
return HANDLER_LIST;
}
+
+ // Leaves start - exp fix
+ public int getRewardExp() {
+ return rewardExp;
+ }
+
+ public void setRewardExp(int rewardExp) {
+ this.rewardExp = rewardExp;
+ }
+ // Leaves end - exp fix
}
diff --git a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java
index 78497c423edaff9550315610ccc2f3d4d3614dce..187fb47ba43d300997f19ecb82ddc41fdd312ec1 100644
--- a/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java
+++ b/src/main/java/org/bukkit/event/entity/PlayerDeathEvent.java
@@ -25,6 +25,7 @@ public class PlayerDeathEvent extends EntityDeathEvent {
private boolean doExpDrop;
private boolean keepLevel = false;
private boolean keepInventory = false;
+ private boolean useApiExpDropStatus = false; // Leaves - exp fix
@Deprecated
private final List<ItemStack> itemsToKeep = new ArrayList<>();
@@ -82,8 +83,15 @@ public class PlayerDeathEvent extends EntityDeathEvent {
this.showDeathMessages = true;
this.deathMessage = LegacyComponentSerializer.legacySection().deserializeOrNull(deathMessage);
this.doExpDrop = doExpDrop;
+ this.useApiExpDropStatus = true; // Leaves - exp fix
}
+ // Leaves start - exp fix
+ public boolean forceUseEventDropStatus() {
+ return this.useApiExpDropStatus;
+ }
+ // Leaves end - exp fix
+
@NotNull
@Override
public Player getEntity() {
@@ -0,0 +1,27 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <mrhua269@gmail.com>
Date: Thu, 12 Jun 2025 08:00:15 +0800
Subject: [PATCH] Purpur: Lobotomize stuck villagers
Co-authored by: William Blake Galbreath <Blake.Galbreath@GMail.com>
As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/purpur-server/minecraft-patches/features/0001-Ridables.patch)
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
diff --git a/src/main/java/org/bukkit/entity/Villager.java b/src/main/java/org/bukkit/entity/Villager.java
index a2024b5dda030a7724c13b2446224903ae837339..71f34a40b136f7f08a4820056c00692b986f63bd 100644
--- a/src/main/java/org/bukkit/entity/Villager.java
+++ b/src/main/java/org/bukkit/entity/Villager.java
@@ -405,4 +405,13 @@ public interface Villager extends AbstractVillager {
* Demand is still updated even if all events are canceled.
*/
public void restock();
+ // Purpur start
+
+ /**
+ * Check if villager is currently lobotomized
+ *
+ * @return True if lobotomized
+ */
+ boolean isLobotomized();
+ // Purpur end
}
@@ -0,0 +1,28 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <mrhua269@gmail.com>
Date: Fri, 5 Jun 2026 09:12:20 +0800
Subject: [PATCH] World load/unload APIs
diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
index cd5f47f6d7fa15c1533724673b8bc2c75394795b..48e53223ba7edeca5256244480441a56a6657075 100644
--- a/src/main/java/org/bukkit/Server.java
+++ b/src/main/java/org/bukkit/Server.java
@@ -775,6 +775,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi
* @throws IllegalStateException when {@link #isTickingWorlds() isTickingWorlds} is true
*/
public boolean unloadWorld(@NotNull World world, boolean save);
+ // Luminol start - Async world unloading api
+
+ /**
+ * Unloads the given world asynchronously
+ *
+ * @param world the world to unload
+ * @param save whether to save the chunks before unloading
+ * @param callback the callback to accept the result, true if successful, false otherwise
+ */
+ public void unloadWorld(World world, boolean save, java.util.concurrent.CompletableFuture<Boolean> callback);
+ // Luminol end
/**
* Gets the world that players respawn in.