feat: add save-all support

This commit is contained in:
Helvetica Volubi
2026-01-16 02:41:01 +08:00
parent e49ab25111
commit 20acc9ccf5
41 changed files with 239 additions and 44 deletions
@@ -0,0 +1,94 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Fri, 16 Jan 2026 02:34:43 +0800
Subject: [PATCH] Add config to enable save-all command
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index b3bc39ebe8d2f48d976de9cd4fcae46095523514..8d20f7e3d89c42e7b92bbaac5da85ac97fecc459 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -350,6 +350,8 @@ public final class RegionizedServer {
// tick player ping sample
this.tickPlayerSample();
+ fun.bm.lophine.utils.SaveAllUtil.checkTimeout(); // Lophine - save-all fix
+
// tick worlds
for (final ServerLevel world : this.worlds) {
this.globalTick(world, tickCount);
diff --git a/io/papermc/paper/threadedregions/TickRegions.java b/io/papermc/paper/threadedregions/TickRegions.java
index 44e59c373538e3ab19cb25cdcbd9b51b6ab86e21..68c9e32ba6cccbcecfb71058a4bfd5130b572fd0 100644
--- a/io/papermc/paper/threadedregions/TickRegions.java
+++ b/io/papermc/paper/threadedregions/TickRegions.java
@@ -190,6 +190,8 @@ public final class TickRegions implements ThreadedRegionizer.RegionCallbacks<Tic
public final ThreadedRegionizer.ThreadedRegion<TickRegionData, TickRegionSectionData> region;
public final ServerLevel world;
+ public long lastSavedTime = 0; // Lophine - save-all fix
+
// generic regionised data
private final Reference2ReferenceOpenHashMap<RegionizedData<?>, Object> regionizedData = new Reference2ReferenceOpenHashMap<>();
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index b95d144dd479d339cc4b0f92cc4c3bade9af4927..097e5b6a14fd148c93ca3894295a4a6b1e9aa870 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -294,7 +294,11 @@ public class Commands {
PardonCommand.register(this.dispatcher);
PardonIpCommand.register(this.dispatcher);
//PerfCommand.register(this.dispatcher); // Folia - region threading - TODO later
- //SaveAllCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ // Lophine start - Add a config to enable save all command
+ if (fun.bm.lophine.config.modules.experiment.CommandConfig.saveAll) {
+ SaveAllCommand.register(this.dispatcher); // Folia - region threading - TODO later
+ }
+ // Lophine end - Add a config to enable save all command
SaveOffCommand.register(this.dispatcher);
SaveOnCommand.register(this.dispatcher);
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 491c78bffae2917f1f7f0b1fce0376a987319537..1600296f134c84ae8eee4e54f5ea54f19e6ed258 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1658,6 +1658,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
// Folia start - region threading
public void tickServer(long startTime, long scheduledEnd, long targetBuffer,
io.papermc.paper.threadedregions.TickRegions.TickRegionData region) {
+ // Lophine start - save-all fix
+ if (fun.bm.lophine.utils.SaveAllUtil.isSaving()) {
+ fun.bm.lophine.utils.SaveAllUtil.postRegionSave(region);
+ }
+ // Lophine end - save-all fix
final ca.spottedleaf.leafprofiler.RegionizedProfiler.Handle foliaProfiler = io.papermc.paper.threadedregions.TickRegionScheduler.getProfiler(); // Folia - profiler
// Folia end - region threading
org.spigotmc.WatchdogThread.tick(); // Spigot
diff --git a/net/minecraft/server/commands/SaveAllCommand.java b/net/minecraft/server/commands/SaveAllCommand.java
index e37b71402179c73146ff67babc228ccfb996f8f4..cfdb60bd89d83282f2202a5585bac22a6002e138 100644
--- a/net/minecraft/server/commands/SaveAllCommand.java
+++ b/net/minecraft/server/commands/SaveAllCommand.java
@@ -21,7 +21,9 @@ public class SaveAllCommand {
}
private static int saveAll(CommandSourceStack source, boolean flush) throws CommandSyntaxException {
- source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
+ // Lophine start - save all
+ fun.bm.lophine.utils.SaveAllUtil.preSaveAll(source, flush);
+/* source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
MinecraftServer server = source.getServer();
boolean flag = server.saveEverything(true, flush, true);
if (!flag) {
@@ -29,6 +31,12 @@ public class SaveAllCommand {
} else {
source.sendSuccess(() -> Component.translatable("commands.save.success"), true);
return 1;
- }
+ }*/
+ return 1;
}
+
+ public static SimpleCommandExceptionType getErrorFailed() {
+ return ERROR_FAILED;
+ }
+ // Lophine end - save all
}
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable scoreboard command
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index b95d144dd479d339cc4b0f92cc4c3bade9af4927..44f469b1fc5169adf3214ac52b8e2647d26e7974 100644
index 097e5b6a14fd148c93ca3894295a4a6b1e9aa870..bd8d98aa813b575e83138e79726bd3143268913c 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -241,7 +241,11 @@ public class Commands {
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config to enable tick command
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index b3bc39ebe8d2f48d976de9cd4fcae46095523514..6df2b8cf3b902bb157ed5fa9eaf9ca062d9e5a39 100644
index 8d20f7e3d89c42e7b92bbaac5da85ac97fecc459..f3be5b71abde2d9833e3b513845485d3030ef2c6 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -332,6 +332,11 @@ public final class RegionizedServer {
@@ -20,7 +20,7 @@ index b3bc39ebe8d2f48d976de9cd4fcae46095523514..6df2b8cf3b902bb157ed5fa9eaf9ca06
// expire invalid click command callbacks
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.ADVENTURE_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.DIALOG_CLICK_MANAGER.handleQueue((int)this.tickCount); // Paper // Folia - region threading - moved to global tick
@@ -355,6 +360,13 @@ public final class RegionizedServer {
@@ -357,6 +362,13 @@ public final class RegionizedServer {
this.globalTick(world, tickCount);
}
@@ -34,7 +34,7 @@ index b3bc39ebe8d2f48d976de9cd4fcae46095523514..6df2b8cf3b902bb157ed5fa9eaf9ca06
// tick connections
this.tickConnections();
@@ -488,7 +500,7 @@ public final class RegionizedServer {
@@ -490,7 +502,7 @@ public final class RegionizedServer {
}
private void tickTime(final ServerLevel world, final int tickCount) {
@@ -97,7 +97,7 @@ index e3df94bfd26b118cb8a7bdece75d611aaf27c606..bae2385b725c0ce551768f22945393cc
this.scheduler.regionFailed(this, false, thr);
// regionFailed will schedule a shutdown, so we should avoid letting this region tick further
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 8d77d6f165a5883e997122d1c2f231287e0caebe..23f047a47cdccc90a96153cc52bdedf91cd15db9 100644
index bd8d98aa813b575e83138e79726bd3143268913c..65f200381f486146ce8d893378f0591a82f6076b 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -262,7 +262,11 @@ public class Commands {
@@ -114,7 +114,7 @@ index 8d77d6f165a5883e997122d1c2f231287e0caebe..23f047a47cdccc90a96153cc52bdedf9
TitleCommand.register(this.dispatcher, context);
//TriggerCommand.register(this.dispatcher); // Folia - region threading - TODO later
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 1627a8f3ebf7bf1a750a62802f1187ad8c1a6a0f..6e18d988104c121d9683eb57e77a78acfdee3907 100644
index 1600296f134c84ae8eee4e54f5ea54f19e6ed258..e40ce457fc046b3b244c67afa79e4f637cc73fde 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -270,7 +270,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -6,7 +6,7 @@ Subject: [PATCH] Add config to enable waypoint command & bar
use concurrent method to fix it (now, they are thread safe)
diff --git a/net/minecraft/commands/Commands.java b/net/minecraft/commands/Commands.java
index 0c31144e1f18fe92065f0c167aaaaa809363cc4c..65d45f7abe95d9492620ea53ab87797a0ebc0ec7 100644
index 65f200381f486146ce8d893378f0591a82f6076b..8362b6a92b27e908024077e564b98d4b681cb2b0 100644
--- a/net/minecraft/commands/Commands.java
+++ b/net/minecraft/commands/Commands.java
@@ -270,7 +270,11 @@ public class Commands {
@@ -5,10 +5,10 @@ Subject: [PATCH] Fix datapack command save function
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index ad8a0130069ae06f8e9fdd4cceed9b9028c8e727..1124987a47bcdb4c64bcc842f30675f4da866261 100644
index e40ce457fc046b3b244c67afa79e4f637cc73fde..0a11c9b42d55d1077d09bcbf73e1fc7736f230fb 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2428,6 +2428,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2433,6 +2433,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.reloadResources(selectedIds, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN);
}
@@ -8,10 +8,10 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/io/papermc/paper/threadedregions/RegionizedServer.java b/io/papermc/paper/threadedregions/RegionizedServer.java
index 6df2b8cf3b902bb157ed5fa9eaf9ca062d9e5a39..057f60cd24876bf44cf3efccbc8a61b030a2a381 100644
index f3be5b71abde2d9833e3b513845485d3030ef2c6..365988c9a46d4f980de1123eeba8f65cbca95df5 100644
--- a/io/papermc/paper/threadedregions/RegionizedServer.java
+++ b/io/papermc/paper/threadedregions/RegionizedServer.java
@@ -367,6 +367,8 @@ public final class RegionizedServer {
@@ -369,6 +369,8 @@ public final class RegionizedServer {
}
// Luminol end - Add a config to enable tick command
@@ -129,7 +129,7 @@ index 0bf2173c5445de021090c2d0264afc440b005bdc..076bfe7a7b57f8d3b29ef0aaad117707
this.connection.setReadOnly();
// CraftBukkit - Don't wait
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index fe58993c3fb98189141120f849c7750ce1e24ebd..d9b20f3b099eea4862774da79929bb71f8dede53 100644
index d2b2bf35b3f5704f3bca94d0fe3b70206c2fbf96..c8be04b8a50bac52150a1fdd238634e630e1765e 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -315,6 +315,8 @@ public abstract class PlayerList {
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/3e96b237749a960f2
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
index c8fa9a9ae29ecf9b2d6234e7efee61d05c8bc0ae..336daa3f7e2c957286d245746af47603a98438bc 100644
index 08a1be57e1057a9e961eeb8f59cd12e98ed52bab..33ee967d8a7d4ce2c455db9ffaac740cd589e6f3 100644
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -717,6 +717,7 @@ public class ServerExplosion implements Explosion {
@@ -24,7 +24,7 @@ index 80f17f33f670018240c854df589cf90cdeab6e70..c9af615ff9120c07787f436dbb6024e5
if (raidAt == null || raidAt.getRaidOmenLevel() < raidAt.getMaxRaidOmenLevel()) {
serverPlayer.addEffect(new MobEffectInstance(MobEffects.RAID_OMEN, 600, amplifier));
diff --git a/net/minecraft/world/entity/raid/Raid.java b/net/minecraft/world/entity/raid/Raid.java
index 4deb9e4688a04b25e862572b70bf91e3ace9841e..2f31fae204dbeeeec1d188b6908aec5ad937e62e 100644
index dcdd6f230ff153a7b58d13b963d32376b1905b72..be9c78f2cf121e8ae55c1b18685877637a25ec80 100644
--- a/net/minecraft/world/entity/raid/Raid.java
+++ b/net/minecraft/world/entity/raid/Raid.java
@@ -264,7 +264,7 @@ public class Raid {
@@ -167,7 +167,7 @@ index 4deb9e4688a04b25e862572b70bf91e3ace9841e..2f31fae204dbeeeec1d188b6908aec5a
+ // Leaves end - old FindSpawnPosition
}
diff --git a/net/minecraft/world/entity/raid/Raider.java b/net/minecraft/world/entity/raid/Raider.java
index 29ddff87216069cdf423f96f3fe835e0802d9ab5..18c4dffb5942b17dc1f2e9d9124c4f3ba3271360 100644
index 5e8245e6dd8a07ece83dd1bc20e351a92044e7a0..2b7894a4104d4cb237746a3e66d4368b6f8f3c1e 100644
--- a/net/minecraft/world/entity/raid/Raider.java
+++ b/net/minecraft/world/entity/raid/Raider.java
@@ -127,6 +127,43 @@ public abstract class Raider extends PatrollingMonster {
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/79d9ef74c2684eb49
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/item/ShearsItem.java b/net/minecraft/world/item/ShearsItem.java
index 8cf3e51e12f9cf98836657e722edb23943f9e866..5fd5e9fd4e1a79dd1a9d62a5cf0c308805979420 100644
index 5e25ddf78f72ada318ef28d29199de9b93fe667e..6f48162a25e20d2439935e8995cede9497626322 100644
--- a/net/minecraft/world/item/ShearsItem.java
+++ b/net/minecraft/world/item/ShearsItem.java
@@ -80,7 +80,10 @@ public class ShearsItem extends Item {
@@ -5,7 +5,7 @@ Subject: [PATCH] LeavesHooks
diff --git a/ca/spottedleaf/moonrise/paper/PaperHooks.java b/ca/spottedleaf/moonrise/paper/PaperHooks.java
index d9fd093f59987f471627ff20cfd2eb1a3c0dea64..78c6d425589b8147c33583ac46d6f21ec5dbefaa 100644
index 3152b791354327867629b42cd9453f022a27b246..9404f98c7c09934f6ddae4f92d82aa1113d42322 100644
--- a/ca/spottedleaf/moonrise/paper/PaperHooks.java
+++ b/ca/spottedleaf/moonrise/paper/PaperHooks.java
@@ -29,7 +29,7 @@ import net.minecraft.world.phys.AABB;
@@ -8,7 +8,7 @@ As part of: Purpur (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18
Licensed under: MIT (https://github.com/PurpurMC/Purpur/blob/09f547de09fc5d886f18f6d99ff389289766ec9d/LICENSE)
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 3c27af5cf768eaa0591846923590a88606dee589..66e7b62a57eada0f0db7d9cc1be6362ac1e3ee85 100644
index 2eb551390aa66d89988df9ca23cf0dd7ccfd6577..0d322ef4aa3e70c9edbb9fa8ba368bef916eb93d 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -963,6 +963,10 @@ public abstract class PlayerList {
@@ -23,7 +23,7 @@ index 3c27af5cf768eaa0591846923590a88606dee589..66e7b62a57eada0f0db7d9cc1be6362a
// Paper start - whitelist verify event / login event
diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java
index 3a8ac0765b8a988c281a2ded8c40ec044781cda2..1e3ac806c3f111ee0a4f8ef47134941ec85fbe6e 100644
index 212536b5a7b2b0196ef05dbb383bd5ac52b6978e..6bbec212142ed1ddb312c403c6c7fc258310b192 100644
--- a/net/minecraft/world/entity/player/Player.java
+++ b/net/minecraft/world/entity/player/Player.java
@@ -179,6 +179,7 @@ public abstract class Player extends Avatar implements ContainerUser {
@@ -5,7 +5,7 @@ Subject: [PATCH] Old zombie reinforcement
diff --git a/net/minecraft/world/entity/monster/zombie/Zombie.java b/net/minecraft/world/entity/monster/zombie/Zombie.java
index 1f359cf31dfd1a7bb9e1a9c8c830a4a4aa88ed00..206b725c9d1dffb185a466746544324135b14f23 100644
index 67a77b253e7761873f35e0b2725df16ffc4db36c..d3b8433b0992057bb0bab3acc339b50b83a5820a 100644
--- a/net/minecraft/world/entity/monster/zombie/Zombie.java
+++ b/net/minecraft/world/entity/monster/zombie/Zombie.java
@@ -314,7 +314,7 @@ public class Zombie extends Monster {
@@ -5,7 +5,7 @@ Subject: [PATCH] Spawn invulnerable time
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index 93bc76af4d0abbe1c526434991e74c4465764ac6..7b8dc8db175d905790462bbf6d0802ca416d7b36 100644
index d17ad8bf49c4911e5939ad25c1822bb4bdd0d71c..8b1fd4a3ff2aa75230e045fed6653382fa8c8c4b 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -240,6 +240,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
@@ -33,7 +33,7 @@ index 9f444988d40208a1bfa9f147ef80489f81115e93..ab2fa0b86564622501238305714fff01
private boolean encrypted;
private final java.util.concurrent.atomic.AtomicBoolean disconnectionHandled = new java.util.concurrent.atomic.AtomicBoolean(false); // Folia - region threading - may be called concurrently during configuration stage
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 1124987a47bcdb4c64bcc842f30675f4da866261..e6c55ee206e7bf35fa2a3d8ce400a13932f249c8 100644
index 0a11c9b42d55d1077d09bcbf73e1fc7736f230fb..ca199e6334f39d8598ccc22ef5aca36ecfbb4939 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -425,6 +425,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -57,7 +57,7 @@ index 1124987a47bcdb4c64bcc842f30675f4da866261..e6c55ee206e7bf35fa2a3d8ce400a139
// Folia start - region threading
// halt scheduler
// don't wait, we may be on a scheduler thread
@@ -1665,7 +1672,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1670,7 +1677,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
int i = this.pauseWhenEmptySeconds() * 20;
this.removeDisabledPluginsBlockingSleep(); // Paper - API to allow/disallow tick sleeping
if (false && i > 0) { // Folia - region threading - this is complicated to implement, and even if done correctly is messy
@@ -66,7 +66,7 @@ index 1124987a47bcdb4c64bcc842f30675f4da866261..e6c55ee206e7bf35fa2a3d8ce400a139
this.emptyTicks++;
} else {
this.emptyTicks = 0;
@@ -1798,6 +1805,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1803,6 +1810,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.isSaving = true;
if (playerSaveInterval > 0) {
this.playerList.saveAll(playerSaveInterval);
@@ -74,7 +74,7 @@ index 1124987a47bcdb4c64bcc842f30675f4da866261..e6c55ee206e7bf35fa2a3d8ce400a139
}
for (final ServerLevel level : (region == null ? this.getAllLevels() : Arrays.asList(region.world))) { // Folia - region threading
if (level.paperConfig().chunks.autoSaveInterval.value() > 0) {
@@ -2018,6 +2026,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2023,6 +2031,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public void tickConnection() {
this.getConnection().tick();
@@ -82,7 +82,7 @@ index 1124987a47bcdb4c64bcc842f30675f4da866261..e6c55ee206e7bf35fa2a3d8ce400a139
}
private void synchronizeTime(ServerLevel level) {
@@ -3152,6 +3161,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -3157,6 +3166,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
return this.debugSubscribers;
}
@@ -9,7 +9,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index df6ad5831f83fcc869b0b4ed844a73b3cb81c469..5c81be29f7ecc3389b5b578f85774035def96e26 100644
index 3a40cf4c559b134c67cad9fbbf986b15ed986558..b44f0ac98d52616bc8405995180844a9af2210f9 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -338,9 +338,12 @@ public class ServerGamePacketListenerImpl
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 173a55715b9c459eeb93cdc065c69e64fc704b43..b2694cb60505766877398fa526b9bfe60e6b6404 100644
index 435acf0fe5e80ca371d1145befc2cfaa917a89e3..77577d0df9b14a7ad55b2866c2ac31863226458b 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -758,6 +758,11 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -84,10 +84,10 @@ index af71e0e1eb1c93745f3e4954ecc8fbd2ad4808a3..f3829564681faff3ae8971ed90b947b4
players.add(serverPlayer1);
if (players.size() >= resultLimit) {
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index e6c55ee206e7bf35fa2a3d8ce400a13932f249c8..30dccb37822c2267c4759804164cc4871fdb8c61 100644
index ca199e6334f39d8598ccc22ef5aca36ecfbb4939..a32a32e19cfc07df86587cb8f7c7eabff19d97cd 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1893,7 +1893,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1898,7 +1898,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
private ServerStatus.Players buildPlayerStatus() {
@@ -96,7 +96,7 @@ index e6c55ee206e7bf35fa2a3d8ce400a13932f249c8..30dccb37822c2267c4759804164cc487
int maxPlayers = this.getMaxPlayers();
if (this.hidesOnlinePlayers()) {
return new ServerStatus.Players(maxPlayers, players.size(), List.of());
@@ -2102,7 +2102,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2107,7 +2107,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@Override
public int getPlayerCount() {
@@ -105,7 +105,7 @@ index e6c55ee206e7bf35fa2a3d8ce400a13932f249c8..30dccb37822c2267c4759804164cc487
}
public String[] getPlayerNames() {
@@ -2306,7 +2306,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2311,7 +2311,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
} else {
int i = 0;
@@ -114,7 +114,7 @@ index e6c55ee206e7bf35fa2a3d8ce400a13932f249c8..30dccb37822c2267c4759804164cc487
serverPlayer.getBukkitEntity().taskScheduler.schedule((ServerPlayer player) -> { // Folia - region threading
// Paper start - Expand PlayerGameModeChangeEvent
org.bukkit.event.player.PlayerGameModeChangeEvent event = player.setGameMode(gameMode, org.bukkit.event.player.PlayerGameModeChangeEvent.Cause.DEFAULT_GAMEMODE, null); // Folia - region threading
@@ -2491,7 +2491,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2496,7 +2496,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
if (Thread.currentThread() != this.serverThread) return; // Paper
// Paper start - we don't need to save everything, just advancements
// this.getPlayerList().saveAll();
@@ -123,7 +123,7 @@ index e6c55ee206e7bf35fa2a3d8ce400a13932f249c8..30dccb37822c2267c4759804164cc487
player.getAdvancements().save();
}
// Paper end - we don't need to save everything, just advancements
@@ -2629,7 +2629,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -2634,7 +2634,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
PlayerList playerList = this.getPlayerList();
UserWhiteList whiteList = playerList.getWhiteList();
@@ -46,10 +46,10 @@ index ab80a66646a7ebe2862221ac342b06c14fcfc734..7834f3da4d0ff4a5cdec46b023d73483
fillCrashReport(reportedException.getReport(), packetListener, packet);
return reportedException;
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 30dccb37822c2267c4759804164cc4871fdb8c61..c1f4965222b591d367cb1a2bb13e522701724b78 100644
index a32a32e19cfc07df86587cb8f7c7eabff19d97cd..818078aee685f6c1c4e94f54377c20b63da3aec3 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1972,8 +1972,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -1977,8 +1977,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
try {
profiler.startTimer(serverLevel.tickTimerId); try { // Folia - profiler
serverLevel.tick(hasTimeLeft, region); // Folia - region threading
@@ -27,7 +27,7 @@ index 56e09b99c2901882483c5f2b3216bf0a11406e2e..1480bd04597001cd7c54e53ded46d7f7
this.wireHandler = new alternate.current.wire.WireHandler(world);
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index b878f5a8316dfee582180a6bbe7122a78581fae2..a906e7a34d048369f9357b0371339b4cccac5f25 100644
index 68ec2a0bca780f7556873a3f17fbb2c19a946f70..7f8774ef5a5875638273bb561a731b08a47c80b4 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -911,12 +911,16 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -9,7 +9,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc1
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
index 8d28b29348c255c901375af161210a2041de1985..86f7cfd5816917bd03aca0a796f1eaca938d65aa 100644
index 3301e521a79adbc6dd76be05e69cce1c97f8697e..8dc1db0e6bafba19e07a7fa78f3920d572d38466 100644
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -386,7 +386,18 @@ public class ServerPlayerGameMode {
@@ -553,7 +553,7 @@ index d1dbfc821f068f14bf975842f66251816ea5c985..fe13504a7d2d685e43183dd7b3219f16
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java
index 5ef593a61c74af7077d02f4b18d936bf9b2507b9..a94d69927b78089b2e9eb0ee74f693821c3d93fc 100644
index 80e6ba8f026a6565696f18304507b2d0a347650c..593fab3d2a70bcd6832dd777afa4973f22abbaeb 100644
--- a/net/minecraft/world/level/block/SculkSensorBlock.java
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
@@ -128,6 +128,18 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg
@@ -732,7 +732,7 @@ index b369e80a4fc371a3762e34e7d4d180b86d1d190f..0b412e360b090dc85d1726eb8f51c69b
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
index 10f9f617123e7ef582707038230f43350d5c5810..d96385dc19b7d6409d65ae37549b6d8f3f955cd2 100644
index 418517faeaf40ae2f7dea5635e4232cd89db3ead..0de2f6627fb6295d7927ac3e37026f4daf68cfd3 100644
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -171,6 +171,15 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
@@ -765,7 +765,7 @@ index 10f9f617123e7ef582707038230f43350d5c5810..d96385dc19b7d6409d65ae37549b6d8f
this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston);
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 7c354894f48a5540eb2554d8b1428306e8929066..de82e9a7f0cc190f8cf8c66eee9dc178241f6a27 100644
index 5551d80a81c2878136f96b3e695c4888c7105a49..73dd8e67938fbfff745b189c06a93174976ba1bf 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -406,22 +406,28 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -46,7 +46,7 @@ index a5d3caab2072b2c9bf8fdcbdb7c52c2dee16cfaf..4bb36d2965785fadf628a9bfac4fa2aa
// CraftBukkit start
if (bukkitState != null) {
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index de82e9a7f0cc190f8cf8c66eee9dc178241f6a27..f5b128a993fab7af71a098b2128537ac749edc2f 100644
index 73dd8e67938fbfff745b189c06a93174976ba1bf..8e56c2237f9d49d0b09b62c0933283f77aaae679 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -1001,12 +1001,14 @@ public class LevelChunk extends ChunkAccess implements DebugValueSource, ca.spot
@@ -97,7 +97,7 @@ index f4c9c551fc39bae38e283ccbbc3cd116f0536a64..db13211b24208d8addd3c210155bc244
NaturalSpawner.spawnForChunk(this.level, chunk, spawnState, spawnCategories);
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index a906e7a34d048369f9357b0371339b4cccac5f25..b5be74243607fb34812dcbad26aad76e44bf0b19 100644
index 7f8774ef5a5875638273bb561a731b08a47c80b4..d91961c3eb8d964eb56845f0e2913f9de8f687aa 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -763,6 +763,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -22,11 +22,21 @@ public class CommandConfig implements IConfigModule {
@TransformedConfig(name = "enable-waypoint", directory = {"experiment", "waypoint_bar"})
@ConfigInfo(name = "waypoint_command_enabled", comments =
"""
Allow to use waypoint command""")
Allow to use waypoint command and locator bar""")
public static boolean waypoint = false;
@ConfigInfo(name = "scoreboard_command_enabled", comments =
"""
Allow to use scoreboard command""")
public static boolean scoreboard = false;
@ConfigInfo(name = "enabled", directory = {"save_all_command"}, comments =
"""
Allow to use save-all command""")
public static boolean saveAll = false;
@ConfigInfo(name = "log_all_process", directory = {"save_all_command"}, comments =
"""
Log all process of save-all command to console""")
public static boolean logAllProcess = false;
}
@@ -0,0 +1,91 @@
package fun.bm.lophine.utils;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.datafixers.util.Pair;
import fun.bm.lophine.config.modules.experiment.CommandConfig;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.commands.SaveAllCommand;
import net.minecraft.server.level.ServerLevel;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class SaveAllUtil {
private static final long TIMEOUT = 1000 * 30; // 30 seconds
public static final Object lock = new Object();
public static volatile long lastSaveAllTime = 0;
private static volatile Pair<CommandSourceStack, Boolean> currentSaveAll = null;
private static volatile int regionCount = 0;
private static final AtomicInteger savedRegionCount = new AtomicInteger(0);
private static final AtomicBoolean withError = new AtomicBoolean(false);
public static void preSaveAll(CommandSourceStack source, boolean flush) {
synchronized (lock) {
if (isSaving()) {
source.sendFailure(Component.literal("Server is already in saving! Please wait..."));
} else {
source.sendSuccess(() -> Component.translatable("commands.save.saving"), false);
currentSaveAll = Pair.of(source, flush);
// we need to count how many regions we need to save
AtomicInteger count = new AtomicInteger();
for (ServerLevel world : source.getServer().getAllLevels()) {
world.regioniser.computeForAllRegions(unused -> {
count.getAndIncrement();
});
}
regionCount = count.get();
savedRegionCount.set(0);
withError.set(false);
lastSaveAllTime = System.currentTimeMillis();
}
}
}
public static void postRegionSave(io.papermc.paper.threadedregions.TickRegions.TickRegionData region) {
Pair<CommandSourceStack, Boolean> currentSaveAll = SaveAllUtil.currentSaveAll;
synchronized (lock) {
if (lastSaveAllTime < region.lastSavedTime) return; // already saved
}
try {
region.world.moonrise$getChunkTaskScheduler().chunkHolderManager.saveAllChunksRegionised(currentSaveAll.getSecond(), false, CommandConfig.logAllProcess, false, false, true, false);
currentSaveAll.getFirst().getServer().getPlayerList().saveAll();
MinecraftServer.LOGGER.info("Saved chunks in region around chunk {} in world '{}'", region.region.getCenterChunk(), region.region.regioniser.world.getWorld().getName());
} catch (final Throwable thr) {
CommandSyntaxException error = SaveAllCommand.getErrorFailed().create();
currentSaveAll.getFirst().sendFailure(Component.literal(error.getMessage()));
MinecraftServer.LOGGER.error(error.getMessage(), thr);
withError.set(true);
}
region.lastSavedTime = System.currentTimeMillis();
int saved;
synchronized (savedRegionCount) {
saved = savedRegionCount.incrementAndGet();
}
if (saved >= regionCount) {
if (withError.get()) {
currentSaveAll.getFirst().sendFailure(Component.literal("At least one region failed to save!"));
} else if (saved == regionCount) {
currentSaveAll.getFirst().sendSuccess(() -> Component.translatable("commands.save.success"), true);
SaveAllUtil.currentSaveAll = null;
}
}
}
public static void checkTimeout() {
Pair<CommandSourceStack, Boolean> currentSaveAll = SaveAllUtil.currentSaveAll;
if (!isSaving()) return;
if (System.currentTimeMillis() - lastSaveAllTime > TIMEOUT) {
currentSaveAll.getFirst().sendFailure(Component.literal("At least one region save data timeout!"));
currentSaveAll.getFirst().sendFailure(Component.literal("Regions need to save expect is " + regionCount + ", but only " + savedRegionCount.get() + " saved!"));
SaveAllUtil.currentSaveAll = null;
}
}
public static boolean isSaving() {
synchronized (lock) {
return currentSaveAll != null;
}
}
}