Skip to content

Commit

Permalink
fixed: singlePlayer backups do not independent
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyDynamic committed Dec 22, 2023
1 parent 3dcf220 commit f5721d1
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 65 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ loader_version=0.14.24

mod_id=quickbackupmulti
mod_name=QuickBackupMulti
mod_version=1.0.2
mod_version=1.0.1
maven_group=dev.skydynamic
archives_base_name=QuickBackupMulti
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package dev.skydynamic.quickbackupmulti;

import dev.skydynamic.quickbackupmulti.i18n.Translate;
import dev.skydynamic.quickbackupmulti.utils.config.Config;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.ModContainer;
//#if MC>=11900
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
//#else
Expand All @@ -19,18 +21,29 @@
import static dev.skydynamic.quickbackupmulti.command.QuickBackupMultiCommand.RegisterCommand;

public final class QuickBackupMulti implements ModInitializer {
public static final String MODID = "quickbackupmulti";

public static final Logger LOGGER = LoggerFactory.getLogger("QuickBackupMulti");

EnvType env = FabricLoader.getInstance().getEnvironmentType();

@Override
public void onInitialize() {
ModContainer qbm = FabricLoader.getInstance().getModContainer(MODID)
.orElseThrow(() -> new IllegalStateException("Couldn't find the mod container for QuickBackupMulti"));

Config.INSTANCE.load();
Translate.handleResourceReload(Config.INSTANCE.getLang());

//#if MC>=11900
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> RegisterCommand(dispatcher));
//#else
//$$ CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> RegisterCommand(dispatcher));
//#endif
ServerLifecycleEvents.SERVER_STARTED.register(server -> Config.TEMP_CONFIG.setServerValue(server));
ServerLifecycleEvents.SERVER_STARTED.register(server -> {
Config.TEMP_CONFIG.setServerValue(server);
Config.TEMP_CONFIG.setEnv(env);
});
ServerLifecycleEvents.SERVER_STOPPED.register(server -> {
if (Config.TEMP_CONFIG.isBackup) {
if (env == EnvType.SERVER) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package dev.skydynamic.quickbackupmulti.command;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.tree.LiteralCommandNode;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
Expand Down Expand Up @@ -109,7 +108,7 @@ private static int deleteSaveBackup(ServerCommandSource commandSource, int slot)
}

private static int restoreSaveBackup(ServerCommandSource commandSource, int slot) {
if (!backupDir.resolve("Slot" + slot + "_info.json").toFile().exists()) {
if (!getBackupDir().resolve("Slot" + slot + "_info.json").toFile().exists()) {
Messenger.sendMessage(commandSource, Text.of(tr("quickbackupmulti.restore.fail")));
return 0;
}
Expand All @@ -131,7 +130,7 @@ private static void executeRestore(ServerCommandSource commandSource) {
//#endif
synchronized (QbDataHashMap) {
if (QbDataHashMap.containsKey("QBM")) {
if (!backupDir.resolve("Slot" + QbDataHashMap.get("QBM").get("Slot") + "_info.json").toFile().exists()) {
if (!getBackupDir().resolve("Slot" + QbDataHashMap.get("QBM").get("Slot") + "_info.json").toFile().exists()) {
Messenger.sendMessage(commandSource, Text.of(tr("quickbackupmulti.restore.fail")));
QbDataHashMap.clear();
return;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package dev.skydynamic.quickbackupmulti.mixin;

import dev.skydynamic.quickbackupmulti.utils.config.Config;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.server.MinecraftServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.nio.file.Path;

import static dev.skydynamic.quickbackupmulti.utils.QbmManager.createBackupDir;

@Environment(EnvType.CLIENT)
@Mixin(MinecraftServer.class)
public abstract class MinecraftServer_ClientMixin {

@Inject(method = "loadWorld", at = @At("RETURN"))
private void initQuickBackupMultiClient(CallbackInfo ci) {
MinecraftServer server = (MinecraftServer) (Object) this;
Config.TEMP_CONFIG.setServerValue(server);
String worldName = server.getSaveProperties().getLevelName();
Config.TEMP_CONFIG.setWorldName(worldName);
Path backupDir = Path.of(System.getProperty("user.dir") + "/QuickBackupMulti/").resolve(worldName);
createBackupDir(backupDir);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dev.skydynamic.quickbackupmulti.mixin;

import net.fabricmc.api.Environment;
import net.fabricmc.api.EnvType;
import net.minecraft.server.MinecraftServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.nio.file.Path;

import static dev.skydynamic.quickbackupmulti.utils.QbmManager.createBackupDir;

@Environment(EnvType.SERVER)
@Mixin(MinecraftServer.class)
public abstract class MinecraftServer_ServerMixin {
@Inject(method = "loadWorld", at = @At("RETURN"))
private void initQuickBackupMulti(CallbackInfo ci) {
Path backupDir = Path.of(System.getProperty("user.dir") + "/QuickBackupMulti/");
createBackupDir(backupDir);
}

}
49 changes: 35 additions & 14 deletions src/main/java/dev/skydynamic/quickbackupmulti/utils/QbmManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import dev.skydynamic.quickbackupmulti.utils.config.Config;

import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.world.ServerWorld;
Expand All @@ -26,16 +28,24 @@
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

import static dev.skydynamic.quickbackupmulti.QuickBackupMulti.LOGGER;
import static dev.skydynamic.quickbackupmulti.i18n.Translate.tr;

public class QbmManager {

public static Path backupDir = Path.of(System.getProperty("user.dir") + "/QuickBackupMulti/");
public static Path savePath = Config.TEMP_CONFIG.server.getSavePath(WorldSavePath.ROOT);
public static IOFileFilter fileFilter = new NotFileFilter(new NameFileFilter(Config.INSTANCE.getIgnoredFiles()));

static Gson gson = new GsonBuilder().serializeNulls().setPrettyPrinting().create();

public static Path getBackupDir() {
if (Config.TEMP_CONFIG.env == EnvType.SERVER) {
return backupDir;
} else {
return backupDir.resolve(Config.TEMP_CONFIG.worldName);
}
}

private static class SlotInfoStorage {
String desc;
long timestamp;
Expand All @@ -59,7 +69,7 @@ private static void writeBackupInfo(int slot, String desc) {
ConcurrentHashMap<String, Object> data = new ConcurrentHashMap<>();
data.put("desc", desc);
data.put("timestamp", System.currentTimeMillis());
var writer = new FileWriter(backupDir.resolve("Slot" + slot + "_info.json").toFile());
var writer = new FileWriter(getBackupDir().resolve("Slot" + slot + "_info.json").toFile());
gson.toJson(data, writer);
writer.close();
} catch (Exception e) {
Expand All @@ -73,11 +83,11 @@ private static long getDirSize(File dir) {
}

private static boolean checkSlotExist(int slot) {
return backupDir.resolve("Slot" + slot + "_info.json").toFile().exists();
return getBackupDir().resolve("Slot" + slot + "_info.json").toFile().exists();
}

public static void restoreClient(int slot) {
File targetBackupSlot = backupDir.resolve("Slot" + slot).toFile();
File targetBackupSlot = getBackupDir().resolve("Slot" + slot).toFile();
try {
savePath.resolve("level.dat").toFile().delete();
savePath.resolve("level.dat_old").toFile().delete();
Expand All @@ -103,7 +113,7 @@ public static void restoreClient(int slot) {
}

public static void restore(int slot) {
File targetBackupSlot = backupDir.resolve("Slot" + slot).toFile();
File targetBackupSlot = getBackupDir().resolve("Slot" + slot).toFile();
try {
// var it = Files.walk(savePath,5).sorted(Comparator.reverseOrder()).iterator();
// while (it.hasNext()){
Expand Down Expand Up @@ -145,9 +155,9 @@ public static int make(ServerCommandSource commandSource, int slot, String desc)
if (serverWorld == null || serverWorld.savingDisabled) continue;
serverWorld.savingDisabled = true;
}
if (!backupDir.resolve("Slot" + slot).toFile().exists()) backupDir.resolve("Slot" + slot).toFile().mkdir();
if (Objects.requireNonNull(backupDir.resolve("Slot" + slot).toFile().listFiles()).length > 0) FileUtils.deleteDirectory(backupDir.resolve("Slot" + slot).toFile());
FileUtils.copyDirectory(savePath.toFile(), backupDir.resolve("Slot" + slot).toFile(), fileFilter);
if (!getBackupDir().resolve("Slot" + slot).toFile().exists()) getBackupDir().resolve("Slot" + slot).toFile().mkdir();
if (Objects.requireNonNull(getBackupDir().resolve("Slot" + slot).toFile().listFiles()).length > 0) FileUtils.deleteDirectory(getBackupDir().resolve("Slot" + slot).toFile());
FileUtils.copyDirectory(savePath.toFile(), getBackupDir().resolve("Slot" + slot).toFile(), fileFilter);
long endTime = System.currentTimeMillis();
double intervalTime = (endTime - startTime) / 1000.0;
Messenger.sendMessage(commandSource, Text.of(tr("quickbackupmulti.make.success", intervalTime)));
Expand All @@ -169,7 +179,7 @@ public static MutableText list() {
try {
MutableText backText = Messenger.literal("§2[▷] ");
MutableText deleteText = Messenger.literal("§c[×] ");
var reader = new FileReader(backupDir.resolve("Slot" + j + "_info.json").toFile());
var reader = new FileReader(getBackupDir().resolve("Slot" + j + "_info.json").toFile());
var result = gson.fromJson(reader, SlotInfoStorage.class);
reader.close();
int finalJ = j;
Expand All @@ -179,7 +189,7 @@ public static MutableText list() {
.styled(style -> style.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.of(tr("quickbackupmulti.list_backup.slot.delete", finalJ)))));
String desc = result.desc;
if (Objects.equals(result.desc, "")) desc = tr("quickbackupmulti.empty_comment");
long backupSizeB = getDirSize(backupDir.resolve("Slot" + j).toFile());
long backupSizeB = getDirSize(getBackupDir().resolve("Slot" + j).toFile());
totalBackupSizeB += backupSizeB;
double backupSizeMB = (double) backupSizeB / FileUtils.ONE_MB;
double backupSizeGB = (double) backupSizeB / FileUtils.ONE_GB;
Expand All @@ -190,7 +200,7 @@ public static MutableText list() {
.append("§a" + sizeString)
.append(String.format(" §b%s§7: §r%s", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(result.timestamp), desc));
} catch (IOException e) {
resultText.append(Messenger.literal("\n"+ tr("quickbackupmulti.list_backup.slot.header", j) + " §2[▷] §c[×] §r") + tr("quickbackupmulti.empty_comment"));
resultText.append("\n"+ tr("quickbackupmulti.list_backup.slot.header", j) + " §2[▷] §c[×] §r" + tr("quickbackupmulti.empty_comment"));
}
}
double totalBackupSizeMB = (double) totalBackupSizeB / FileUtils.ONE_MB;
Expand All @@ -201,15 +211,26 @@ public static MutableText list() {
}

public static boolean delete(int slot) {
if (backupDir.resolve("Slot" + slot + "_info.json").toFile().exists() || backupDir.resolve("Slot" + slot).toFile().exists()) {
if (getBackupDir().resolve("Slot" + slot + "_info.json").toFile().exists() || getBackupDir().resolve("Slot" + slot).toFile().exists()) {
try {
backupDir.resolve("Slot" + slot + "_info.json").toFile().delete();
FileUtils.deleteDirectory(backupDir.resolve("Slot" + slot).toFile());
getBackupDir().resolve("Slot" + slot + "_info.json").toFile().delete();
FileUtils.deleteDirectory(getBackupDir().resolve("Slot" + slot).toFile());
return true;
} catch (SecurityException | IOException e) {
return false;
}
} else return false;
}

public static void createBackupDir(Path path) {
if (!path.toFile().exists()) {
LOGGER.info(tr("quickbackupmulti.init.start"));
path.toFile().mkdirs();
LOGGER.info(tr("quickbackupmulti.init.finish"));
}
for(int j = 1; j<= Config.INSTANCE.getNumOfSlot(); j++) {
if (!path.resolve("Slot" + j).toFile().exists()) path.resolve("Slot" + j).toFile().mkdir();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@

public class ConfigStorage {
@Ignore
public static final ConfigStorage DEFAULT = new ConfigStorage(5, new ArrayList<>(List.of("session.lock")), "zh_cn");
public static final ConfigStorage DEFAULT = new ConfigStorage(5, new ArrayList<>(List.of("session.lock")), "zh_cn", true);
int numOfSlots;
ArrayList<String> ignoredFiles;
String lang;
boolean shouldCheckUpdate;

public ConfigStorage(int NumOfSlots, ArrayList<String> IgnoredFiles, String lang) {
public ConfigStorage(int NumOfSlots, ArrayList<String> IgnoredFiles, String lang, boolean shouldCheckUpdate) {
this.numOfSlots = NumOfSlots;
this.ignoredFiles = IgnoredFiles;
this.lang = lang;
this.shouldCheckUpdate = shouldCheckUpdate;
}

public int getNumOfSlots() {
Expand All @@ -27,8 +29,12 @@ public String getLang() {
return this.lang;
}

public boolean getShouldCheckUpdate() {
return this.shouldCheckUpdate;
}

@Override
public int hashCode() {
return Objects.hash(getNumOfSlots(), getIgnoredFiles(), getLang());
return Objects.hash(getNumOfSlots(), getIgnoredFiles(), getLang(), getShouldCheckUpdate());
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package dev.skydynamic.quickbackupmulti.utils.config;

import net.fabricmc.api.EnvType;
import net.minecraft.server.MinecraftServer;

public class QbmTempConfig {
public Boolean isBackup = false;
public MinecraftServer server;
public int backupSlot;
public EnvType env;
public String worldName;

public void setIsBackupValue(Boolean value) {
this.isBackup = value;
Expand All @@ -19,4 +22,12 @@ public void setBackupSlot(int slot) {
this.backupSlot = slot;
}

public void setEnv(EnvType env) {
this.env = env;
}

public void setWorldName(String worldName) {
this.worldName = worldName;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ public String getLang() {
}
}

public boolean getShouldCheckUpdate() {
synchronized (lock) {
return configStorage.shouldCheckUpdate;
}
}

public void setLang(String lang) {
synchronized (lock) {
configStorage.lang = lang;
Expand Down
Loading

0 comments on commit f5721d1

Please sign in to comment.