migrate mappings to mojmap
This commit is contained in:
9 files changed
+81
-80
No files matched your search
+1
-1
@@ -58,7 +58,7 @@ loom {
|
|||||||
dependencies {
|
dependencies {
|
||||||
// To change the versions see the gradle.properties file
|
// To change the versions see the gradle.properties file
|
||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
mappings loom.officialMojangMappings()
|
||||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||||
|
|
||||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||||
|
|||||||
+10
-4
@@ -8,11 +8,10 @@ plugins {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api 'com.github.luben:zstd-jni:1.5.7-4'
|
api 'com.github.luben:zstd-jni:1.5.7-4'
|
||||||
testCompileOnly 'io.netty:netty-all:4.2.6.Final'
|
|
||||||
api "io.ib67.kiwi:lang:1.2.3-SNAPSHOT"
|
api "io.ib67.kiwi:lang:1.2.3-SNAPSHOT"
|
||||||
implementation 'io.netty:netty-all:4.2.6.Final'
|
compileOnly 'io.netty:netty-all:4.2.6.Final'
|
||||||
implementation 'it.unimi.dsi:fastutil:8.5.15'
|
compileOnly 'it.unimi.dsi:fastutil:8.5.15'
|
||||||
implementation 'org.lz4:lz4-java:1.8.0'
|
compileOnly 'org.lz4:lz4-java:1.8.0'
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter:5.13.4'
|
testImplementation 'org.junit.jupiter:junit-jupiter:5.13.4'
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||||
}
|
}
|
||||||
@@ -21,6 +20,13 @@ configurations {
|
|||||||
testRuntimeOnly {
|
testRuntimeOnly {
|
||||||
extendsFrom compileOnly
|
extendsFrom compileOnly
|
||||||
}
|
}
|
||||||
|
testCompileOnly {
|
||||||
|
extendsFrom compileOnly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
minimize()
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
package io.ib67.bundler;
|
package io.ib67.bundler;
|
||||||
|
|
||||||
import io.ib67.sfcraft.bundler.BundleWriter;
|
import io.ib67.sfcraft.bundler.BundleWriter;
|
||||||
import io.netty.buffer.ByteBufAllocator;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package io.ib67.sfcraft;
|
package io.ib67.sfcraft;
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
public record Backup(
|
public record Backup(
|
||||||
String name,
|
String name,
|
||||||
@@ -10,8 +10,8 @@ public record Backup(
|
|||||||
boolean incremental,
|
boolean incremental,
|
||||||
long sizeTotal
|
long sizeTotal
|
||||||
) {
|
) {
|
||||||
public Text toText(){
|
public Component toText(){
|
||||||
return Text.of("sizeTotal: "+Math.round(((sizeTotal / 1024.0) / 1024.0) * 100) * 0.01 + "MiB, "+
|
return Component.nullToEmpty("sizeTotal: "+Math.round(((sizeTotal / 1024.0) / 1024.0) * 100) * 0.01 + "MiB, "+
|
||||||
(incremental ? "incremental" :"") + ", type: "+type+"."
|
(incremental ? "incremental" :"") + ", type: "+type+"."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,12 @@ import com.mojang.brigadier.arguments.StringArgumentType;
|
|||||||
import com.mojang.brigadier.context.CommandContext;
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
import com.mojang.brigadier.suggestion.Suggestions;
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
import io.ib67.sfcraft.bundler.BundleReader;
|
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import net.minecraft.command.CommandRegistryAccess;
|
import net.minecraft.commands.CommandBuildContext;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.commands.Commands;
|
||||||
import net.minecraft.text.ClickEvent;
|
import net.minecraft.network.chat.ClickEvent;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@@ -24,8 +22,8 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
import static net.minecraft.server.command.CommandManager.argument;
|
import static net.minecraft.commands.Commands.argument;
|
||||||
import static net.minecraft.server.command.CommandManager.literal;
|
import static net.minecraft.commands.Commands.literal;
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
public class BackupCommands {
|
public class BackupCommands {
|
||||||
@@ -57,10 +55,10 @@ public class BackupCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void registerCommand(
|
public void registerCommand(
|
||||||
CommandDispatcher<ServerCommandSource> dispatcher,
|
CommandDispatcher<CommandSourceStack> dispatcher,
|
||||||
CommandRegistryAccess registry, CommandManager.RegistrationEnvironment env) {
|
CommandBuildContext registry, Commands.CommandSelection env) {
|
||||||
dispatcher.register(literal("backup")
|
dispatcher.register(literal("backup")
|
||||||
.requires(it -> it.hasPermissionLevel(3))
|
.requires(it -> it.hasPermission(3))
|
||||||
.then(literal("help").executes(this::cmdHelp))
|
.then(literal("help").executes(this::cmdHelp))
|
||||||
.then(literal("list").executes(this::cmdList))
|
.then(literal("list").executes(this::cmdList))
|
||||||
.then(literal("cancelrestore").executes(this::cmdCancelRestore))
|
.then(literal("cancelrestore").executes(this::cmdCancelRestore))
|
||||||
@@ -81,61 +79,61 @@ public class BackupCommands {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int createBackupBySubject(CommandContext<ServerCommandSource> context) {
|
private int createBackupBySubject(CommandContext<CommandSourceStack> context) {
|
||||||
var incremental = BoolArgumentType.getBool(context, "incremental");
|
var incremental = BoolArgumentType.getBool(context, "incremental");
|
||||||
var subject = StringArgumentType.getString(context, "subject");
|
var subject = StringArgumentType.getString(context, "subject");
|
||||||
var s = context.getSource();
|
var s = context.getSource();
|
||||||
s.sendMessage(Text.literal("The issued backup has been scheduled.").withColor(Color.CYAN.getRGB()));
|
s.sendSystemMessage(Component.literal("The issued backup has been scheduled.").withColor(Color.CYAN.getRGB()));
|
||||||
mod.issueBackup(subject, incremental);
|
mod.issueBackup(subject, incremental);
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int fullBackup(CommandContext<ServerCommandSource> context) {
|
private int fullBackup(CommandContext<CommandSourceStack> context) {
|
||||||
var incremental = BoolArgumentType.getBool(context, "incremental");
|
var incremental = BoolArgumentType.getBool(context, "incremental");
|
||||||
var s = context.getSource();
|
var s = context.getSource();
|
||||||
s.sendMessage(Text.literal("The issued backup has been scheduled.").withColor(Color.CYAN.getRGB()));
|
s.sendSystemMessage(Component.literal("The issued backup has been scheduled.").withColor(Color.CYAN.getRGB()));
|
||||||
var weakRef = new WeakReference<>(s);
|
var weakRef = new WeakReference<>(s);
|
||||||
mod.backupAll(incremental).thenAccept(result -> {
|
mod.backupAll(incremental).thenAccept(result -> {
|
||||||
var ref = weakRef.get();
|
var ref = weakRef.get();
|
||||||
if (ref == null) {
|
if (ref == null) {
|
||||||
ref = mod.server.getCommandSource();
|
ref = mod.server.createCommandSourceStack();
|
||||||
}
|
}
|
||||||
ref.sendMessage(Text.literal("-- BACKUP RESULT SUMMARY --"));
|
ref.sendSystemMessage(Component.literal("-- BACKUP RESULT SUMMARY --"));
|
||||||
for (var entry : result.entrySet()) {
|
for (var entry : result.entrySet()) {
|
||||||
var k = entry.getKey();
|
var k = entry.getKey();
|
||||||
var v = entry.getValue();
|
var v = entry.getValue();
|
||||||
ref.sendMessage(Text.literal(" - [" + k + "]: ").append(v.toText()));
|
ref.sendSystemMessage(Component.literal(" - [" + k + "]: ").append(v.toText()));
|
||||||
ref.sendMessage(Text.literal("BACKUP KEY: " + v.backupKey()).withColor(Color.GRAY.getRGB()));
|
ref.sendSystemMessage(Component.literal("BACKUP KEY: " + v.backupKey()).withColor(Color.GRAY.getRGB()));
|
||||||
ref.sendMessage(Text.literal("GENERATED FROM: " + v.from()).withColor(Color.GRAY.getRGB()));
|
ref.sendSystemMessage(Component.literal("GENERATED FROM: " + v.from()).withColor(Color.GRAY.getRGB()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int cmdSuspend(CommandContext<ServerCommandSource> context) {
|
private int cmdSuspend(CommandContext<CommandSourceStack> context) {
|
||||||
var s = context.getSource();
|
var s = context.getSource();
|
||||||
// this is safe as we are the only writer here.
|
// this is safe as we are the only writer here.
|
||||||
var suspend = mod.suspend;
|
var suspend = mod.suspend;
|
||||||
mod.suspend = !suspend;
|
mod.suspend = !suspend;
|
||||||
if (suspend) {
|
if (suspend) {
|
||||||
s.sendMessage(Text.of("The automatic backup system is now re-enabled."));
|
s.sendSystemMessage(Component.nullToEmpty("The automatic backup system is now re-enabled."));
|
||||||
} else {
|
} else {
|
||||||
s.sendMessage(Text.of("The automatic backup system is now disabled."));
|
s.sendSystemMessage(Component.nullToEmpty("The automatic backup system is now disabled."));
|
||||||
}
|
}
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int cmdRestore(CommandContext<ServerCommandSource> context) {
|
private int cmdRestore(CommandContext<CommandSourceStack> context) {
|
||||||
var s = context.getSource();
|
var s = context.getSource();
|
||||||
if (restoreIssued != null) {
|
if (restoreIssued != null) {
|
||||||
s.sendMessage(Text.literal("Another restore request is already present.").withColor(Color.RED.getRGB()));
|
s.sendSystemMessage(Component.literal("Another restore request is already present.").withColor(Color.RED.getRGB()));
|
||||||
s.sendMessage(Text.of("TIP: Use `/backup cancelrestore` to cancel that request."));
|
s.sendSystemMessage(Component.nullToEmpty("TIP: Use `/backup cancelrestore` to cancel that request."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
var backupKey = StringArgumentType.getString(context, "backupKey");
|
var backupKey = StringArgumentType.getString(context, "backupKey");
|
||||||
var backup = mod.tracker.getTrackedBackups().get(backupKey);
|
var backup = mod.tracker.getTrackedBackups().get(backupKey);
|
||||||
if (backup == null) {
|
if (backup == null) {
|
||||||
s.sendMessage(Text.of("Invalid backup " + backupKey + ". Note: Use backupKey instead of backupName!"));
|
s.sendSystemMessage(Component.literal("Invalid backup " + backupKey + ". Note: Use backupKey instead of backupName!"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
restoreIssued = () -> {
|
restoreIssued = () -> {
|
||||||
@@ -164,46 +162,46 @@ public class BackupCommands {
|
|||||||
mod.tracker.recoverBackup(backup, destination);
|
mod.tracker.recoverBackup(backup, destination);
|
||||||
log.info("Backup has been recovered.");
|
log.info("Backup has been recovered.");
|
||||||
};
|
};
|
||||||
s.sendMessage(Text.of("Backup restoration task has been scheduled!"));
|
s.sendSystemMessage(Component.literal("Backup restoration task has been scheduled!"));
|
||||||
s.sendMessage(Text.of("Restart your server to take changes."));
|
s.sendSystemMessage(Component.literal("Restart your server to take changes."));
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int cmdDelete(CommandContext<ServerCommandSource> context) {
|
private int cmdDelete(CommandContext<CommandSourceStack> context) {
|
||||||
var backupKey = StringArgumentType.getString(context, "backupKey");
|
var backupKey = StringArgumentType.getString(context, "backupKey");
|
||||||
var backup = mod.tracker.getTrackedBackups().get(backupKey);
|
var backup = mod.tracker.getTrackedBackups().get(backupKey);
|
||||||
var source = context.getSource();
|
var source = context.getSource();
|
||||||
if (backup == null) {
|
if (backup == null) {
|
||||||
source.sendMessage(Text.of("Invalid backup. No backups are named '" + backupKey + "'"));
|
source.sendSystemMessage(Component.nullToEmpty("Invalid backup. No backups are named '" + backupKey + "'"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mod.tracker.deleteBackup(backup);
|
mod.tracker.deleteBackup(backup);
|
||||||
source.sendMessage(Text.of("Backup has been deleted."));
|
source.sendSystemMessage(Component.nullToEmpty("Backup has been deleted."));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
source.sendMessage(Text.of("Backup has not been deleted successfully. ERROR: " + e));
|
source.sendSystemMessage(Component.nullToEmpty("Backup has not been deleted successfully. ERROR: " + e));
|
||||||
log.error(e);
|
log.error(e);
|
||||||
}
|
}
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int cmdList(CommandContext<ServerCommandSource> context) {
|
private int cmdList(CommandContext<CommandSourceStack> context) {
|
||||||
var source = context.getSource();
|
var source = context.getSource();
|
||||||
var trackedBackups = mod.tracker.getTrackedBackups();
|
var trackedBackups = mod.tracker.getTrackedBackups();
|
||||||
if (trackedBackups.isEmpty()) {
|
if (trackedBackups.isEmpty()) {
|
||||||
source.sendMessage(Text.of("No backups are neither created nor tracked yet."));
|
source.sendSystemMessage(Component.nullToEmpty("No backups are neither created nor tracked yet."));
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
source.sendMessage(Text.of("ALL TRACKED BACKUPS:"));
|
source.sendSystemMessage(Component.nullToEmpty("ALL TRACKED BACKUPS:"));
|
||||||
for (var entry : trackedBackups.entrySet()) {
|
for (var entry : trackedBackups.entrySet()) {
|
||||||
var backupKey = entry.getKey();
|
var backupKey = entry.getKey();
|
||||||
var backup = entry.getValue();
|
var backup = entry.getValue();
|
||||||
source.sendMessage(Text.literal(" - [" + backup.name() + "] ").append(backup.toText()));
|
source.sendSystemMessage(Component.literal(" - [" + backup.name() + "] ").append(backup.toText()));
|
||||||
source.sendMessage(Text.literal(" ").append(
|
source.sendSystemMessage(Component.literal(" ").append(
|
||||||
Text.literal("[DELETE]").withColor(Color.RED.getRGB()).styled(it -> it.withClickEvent(
|
Component.literal("[DELETE]").withColor(Color.RED.getRGB()).withStyle(it -> it.withClickEvent(
|
||||||
new ClickEvent.SuggestCommand("/backup delete " + backupKey)
|
new ClickEvent.SuggestCommand("/backup delete " + backupKey)
|
||||||
))).append(Text.literal(" ")).append(
|
))).append(Component.literal(" ")).append(
|
||||||
Text.literal("[RESTORE]").withColor(Color.CYAN.getRGB()).styled(it -> it.withClickEvent(
|
Component.literal("[RESTORE]").withColor(Color.CYAN.getRGB()).withStyle(it -> it.withClickEvent(
|
||||||
new ClickEvent.SuggestCommand("/backup restore " + backupKey)
|
new ClickEvent.SuggestCommand("/backup restore " + backupKey)
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
@@ -212,30 +210,30 @@ public class BackupCommands {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int cmdCancelRestore(CommandContext<ServerCommandSource> context) {
|
private int cmdCancelRestore(CommandContext<CommandSourceStack> context) {
|
||||||
var source = context.getSource();
|
var source = context.getSource();
|
||||||
if (restoreIssued != null) {
|
if (restoreIssued != null) {
|
||||||
restoreIssued = null;
|
restoreIssued = null;
|
||||||
source.sendMessage(Text.of("The backup restoration request has been cancelled."));
|
source.sendSystemMessage(Component.nullToEmpty("The backup restoration request has been cancelled."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
source.sendMessage(Text.of("You have no backup restoration request in flight."));
|
source.sendSystemMessage(Component.nullToEmpty("You have no backup restoration request in flight."));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int cmdHelp(CommandContext<ServerCommandSource> ctx) {
|
private int cmdHelp(CommandContext<CommandSourceStack> ctx) {
|
||||||
var source = ctx.getSource();
|
var source = ctx.getSource();
|
||||||
for (String s : helpMessage) {
|
for (String s : helpMessage) {
|
||||||
if (s.startsWith(" /")) {
|
if (s.startsWith(" /")) {
|
||||||
source.sendMessage(Text.literal(s).withColor(Color.CYAN.getRGB()));
|
source.sendSystemMessage(Component.literal(s).withColor(Color.CYAN.getRGB()));
|
||||||
} else {
|
} else {
|
||||||
source.sendMessage(Text.of(s));
|
source.sendSystemMessage(Component.literal(s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Command.SINGLE_SUCCESS;
|
return Command.SINGLE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Suggestions> suggestBackups(CommandContext<ServerCommandSource> serverCommandSourceCommandContext, SuggestionsBuilder suggestionsBuilder) {
|
private CompletableFuture<Suggestions> suggestBackups(CommandContext<CommandSourceStack> serverCommandSourceCommandContext, SuggestionsBuilder suggestionsBuilder) {
|
||||||
for (Backup value : mod.tracker.getTrackedBackups().values()) {
|
for (Backup value : mod.tracker.getTrackedBackups().values()) {
|
||||||
suggestionsBuilder = suggestionsBuilder.suggest(value.backupKey());
|
suggestionsBuilder = suggestionsBuilder.suggest(value.backupKey());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public record BackupWorker(
|
|||||||
if (server == null) {
|
if (server == null) {
|
||||||
throw new IllegalStateException("MinecraftServer is not initialized yet, not doing backup");
|
throw new IllegalStateException("MinecraftServer is not initialized yet, not doing backup");
|
||||||
}
|
}
|
||||||
server.saveAll(true, true, false);
|
server.saveEverything(true, true, false);
|
||||||
while (!BACKUP_LOCK.compareAndSet(IOState.IDLE, IOState.BACKUP)) {
|
while (!BACKUP_LOCK.compareAndSet(IOState.IDLE, IOState.BACKUP)) {
|
||||||
log.info("Server is saving world while performing backup! waiting...");
|
log.info("Server is saving world while performing backup! waiting...");
|
||||||
Thread.sleep(2000);
|
Thread.sleep(2000);
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ import net.fabricmc.api.ModInitializer;
|
|||||||
|
|
||||||
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
|
||||||
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import org.jetbrains.annotations.UnknownNullability;
|
import org.jetbrains.annotations.UnknownNullability;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -110,12 +110,12 @@ public class JustBackupMod implements ModInitializer {
|
|||||||
backupAll(false);
|
backupAll(false);
|
||||||
}
|
}
|
||||||
scheduledBackupExecutor.scheduleAtFixedRate(() -> {
|
scheduledBackupExecutor.scheduleAtFixedRate(() -> {
|
||||||
if (lastBackupServerTicks > 0 && lastBackupServerTicks == server.getTicks()) {
|
if (lastBackupServerTicks > 0 && lastBackupServerTicks == server.getTickCount()) {
|
||||||
// the server is idling
|
// the server is idling
|
||||||
LOGGER.debug("Server is idling, not backing up.");
|
LOGGER.debug("Server is idling, not backing up.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastBackupServerTicks = server.getTicks();
|
lastBackupServerTicks = server.getTickCount();
|
||||||
if (!suspend) backupAll(config.incremental()).thenAccept(it -> {
|
if (!suspend) backupAll(config.incremental()).thenAccept(it -> {
|
||||||
LOGGER.info("Backup success!");
|
LOGGER.info("Backup success!");
|
||||||
it.forEach((k, v) -> LOGGER.info(k + ": " + v));
|
it.forEach((k, v) -> LOGGER.info(k + ": " + v));
|
||||||
@@ -145,9 +145,9 @@ public class JustBackupMod implements ModInitializer {
|
|||||||
public CompletableFuture<Map<String, Backup>> backupAll(boolean incremental) {
|
public CompletableFuture<Map<String, Backup>> backupAll(boolean incremental) {
|
||||||
if (backupSubjects.isEmpty()) return CompletableFuture.completedFuture(Map.of());
|
if (backupSubjects.isEmpty()) return CompletableFuture.completedFuture(Map.of());
|
||||||
var map = new HashMap<String, CompletableFuture<Backup>>();
|
var map = new HashMap<String, CompletableFuture<Backup>>();
|
||||||
server.getPlayerManager().broadcast(
|
server.getPlayerList().broadcastSystemMessage(
|
||||||
Text.literal(" BACKUP >> ").withColor(Color.RED.getRGB()).styled(it -> it.withBold(true))
|
Component.literal(" BACKUP >> ").withColor(Color.RED.getRGB()).withStyle(it -> it.withBold(true))
|
||||||
.append(Text.of("The server is performing a backup, you may experience some lag.")),
|
.append(Component.nullToEmpty("The server is performing a backup, you may experience some lag.")),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
for (var entry : backupSubjects.entrySet()) {
|
for (var entry : backupSubjects.entrySet()) {
|
||||||
@@ -195,11 +195,11 @@ public class JustBackupMod implements ModInitializer {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
private void onBackupComplete(@UnknownNullability Backup backup, @UnknownNullability Throwable throwable) {
|
private void onBackupComplete(@UnknownNullability Backup backup, @UnknownNullability Throwable throwable) {
|
||||||
if (throwable != null) {
|
if (throwable != null) {
|
||||||
server.getPlayerManager().broadcast(Text.literal("Backup failed. For administrators, please check your server console."), false);
|
server.getPlayerList().broadcastSystemMessage(Component.literal("Backup failed. For administrators, please check your server console."), false);
|
||||||
LOGGER.error(throwable.getMessage(), throwable);
|
LOGGER.error(throwable.getMessage(), throwable);
|
||||||
} else {
|
} else {
|
||||||
Files.writeString(backupIndexPath, Globals.GSON.toJson(tracker.getTrackedBackups()));
|
Files.writeString(backupIndexPath, Globals.GSON.toJson(tracker.getTrackedBackups()));
|
||||||
server.getPlayerManager().broadcast(Text.literal("Backup success. " + backup), false);
|
server.getPlayerList().broadcastSystemMessage(Component.literal("Backup success. " + backup), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ public abstract class MixinMinecraftServer {
|
|||||||
private int ticksUntilAutosave;
|
private int ticksUntilAutosave;
|
||||||
|
|
||||||
@Shadow
|
@Shadow
|
||||||
protected abstract int getAutosaveInterval();
|
protected abstract int computeNextAutosaveInterval();
|
||||||
|
|
||||||
@Inject(method = "runAutosave", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "autoSave", at = @At("HEAD"), cancellable = true)
|
||||||
private void backup$checkSaving(CallbackInfo ci) {
|
private void backup$checkSaving(CallbackInfo ci) {
|
||||||
// is already backing up
|
// is already backing up
|
||||||
this.ticksUntilAutosave = getAutosaveInterval();
|
this.ticksUntilAutosave = computeNextAutosaveInterval();
|
||||||
IOState witness;
|
IOState witness;
|
||||||
while ((witness = Globals.BACKUP_LOCK.compareAndExchange(IOState.IDLE, IOState.SAVING_WORLD)) == IOState.STORAGE_SYNC) {
|
while ((witness = Globals.BACKUP_LOCK.compareAndExchange(IOState.IDLE, IOState.SAVING_WORLD)) == IOState.STORAGE_SYNC) {
|
||||||
try {
|
try {
|
||||||
@@ -34,7 +34,7 @@ public abstract class MixinMinecraftServer {
|
|||||||
if (witness == IOState.BACKUP) ci.cancel();
|
if (witness == IOState.BACKUP) ci.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "runAutosave", at = @At("RETURN"))
|
@Inject(method = "autoSave", at = @At("RETURN"))
|
||||||
private void backup$disableProtect(CallbackInfo ci) {
|
private void backup$disableProtect(CallbackInfo ci) {
|
||||||
Globals.BACKUP_LOCK.setRelease(IOState.IDLE);
|
Globals.BACKUP_LOCK.setRelease(IOState.IDLE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,18 +4,18 @@ import io.ib67.sfcraft.Globals;
|
|||||||
import io.ib67.sfcraft.IOState;
|
import io.ib67.sfcraft.IOState;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.minecraft.world.storage.RegionBasedStorage;
|
import net.minecraft.world.level.chunk.storage.RegionFile;
|
||||||
import net.minecraft.world.storage.RegionFile;
|
import net.minecraft.world.level.chunk.storage.RegionFileStorage;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Overwrite;
|
import org.spongepowered.asm.mixin.Overwrite;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
@Mixin(RegionBasedStorage.class)
|
@Mixin(RegionFileStorage.class)
|
||||||
public abstract class MixinRegionBasedStorage {
|
public abstract class MixinRegionBasedStorage {
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private Long2ObjectLinkedOpenHashMap<RegionFile> cachedRegionFiles;
|
private Long2ObjectLinkedOpenHashMap<RegionFile> regionCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author iceBear67
|
* @author iceBear67
|
||||||
@@ -23,7 +23,7 @@ public abstract class MixinRegionBasedStorage {
|
|||||||
*/
|
*/
|
||||||
@Overwrite
|
@Overwrite
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public void sync() {
|
public void flush() {
|
||||||
// allowed states:
|
// allowed states:
|
||||||
// STORAGE_SYNC, AUTO_SAVE, IDLE
|
// STORAGE_SYNC, AUTO_SAVE, IDLE
|
||||||
// we try
|
// we try
|
||||||
@@ -48,8 +48,8 @@ public abstract class MixinRegionBasedStorage {
|
|||||||
}
|
}
|
||||||
// program point: IDLE, AUTOSAVE, STORAGESYNC
|
// program point: IDLE, AUTOSAVE, STORAGESYNC
|
||||||
try {
|
try {
|
||||||
for (RegionFile value : this.cachedRegionFiles.values()) {
|
for (RegionFile value : this.regionCache.values()) {
|
||||||
value.sync();
|
value.flush();
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// we assert that there are no other threads calling sync()
|
// we assert that there are no other threads calling sync()
|
||||||
|
|||||||
Reference in new issue
Block a user