feat: add save-all support
This commit is contained in:
+11
-1
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user