Project refactor.

This commit is contained in:
Jinks 2024-12-06 23:53:28 +01:00
parent 9796c6c583
commit cd67e94787
21 changed files with 226 additions and 172 deletions

2
.gitignore vendored
View file

@ -20,9 +20,11 @@ build
# other # other
eclipse eclipse
run run
/logs
# Files from Forge MDK # Files from Forge MDK
forge*changelog.txt forge*changelog.txt
/src/generated/resources/.cache
# VSCode # VSCode
.vscode .vscode

View file

@ -1,8 +1,22 @@
# Simple Backups # ExtBackup
A simple mod to create scheduled backups. Minimal Minecraft backup mod, relying on external backup tools.
[![Modrinth](https://badges.moddingx.org/modrinth/versions/fzSKSXVK)](https://modrinth.com/mod/simple-backups) ## Why?
[![Modrinth](https://badges.moddingx.org/modrinth/downloads/fzSKSXVK)](https://modrinth.com/mod/simple-backups) The regular well-known backup mods lack the sophistication of dedicated backup tools.
[![Curseforge](https://badges.moddingx.org/curseforge/versions/583228)](https://www.curseforge.com/minecraft/mc-mods/simple-backups) ExtBackup does not care about storage, retention, rotating old backups, freeing up space or any of that stuff.
[![CurseForge](https://badges.moddingx.org/curseforge/downloads/583228)](https://www.curseforge.com/minecraft/mc-mods/simple-backups) All it does is save the world to disk and then call a script or program on a configurable schedule. The external
program can be as simple or as complicated as you want it to be. Connect your Minecraft to borg, restic, Veeam or
whatever you like and backup your worlds however you like.
## Target audience
ExtBackup is aimed at server owners. It's so far only tested on Linux and does not offer much configuration. It just
runs the program with the Minecraft directory as current working directory. It may well work on Windows, or it may not.
## Acknowledgements
* [MelanX](https://modrinth.com/user/MelanX) for [Simple Backups](https://modrinth.com/mod/simple-backups) which formed
the base for ExtBackup 2.0, the NeoForge version.
* [LatvianModder](https://github.com/LatvianModder) for his work on [FTB-Backups](https://github.com/FTBTeam/FTB-Backups)
where I stole a lot of the code for the Forge Version.
* [alexbobp](https://github.com/alexbobp) and the [elytra](https://github.com/elytra) group for
[BTFU](https://github.com/elytra/BTFU), which gave me the idea but didn't go quite far enough.

View file

@ -15,7 +15,7 @@ plugins {
id 'net.neoforged.moddev' version '[2.0,2.1)' id 'net.neoforged.moddev' version '[2.0,2.1)'
} }
version = getVersion(minecraft_version + "-" + base_version, new URL(remote_maven + "/" + group.replace('.', '/') + "/" + name + "/maven-metadata.xml")) version = minecraft_version + "-" + mod_version
repositories { repositories {
mavenLocal() mavenLocal()
@ -103,34 +103,6 @@ tasks.withType(ProcessResources).configureEach {
} }
} }
publishing {
publications {
mavenJava(MavenPublication) {
groupId = project.group
artifactId = project.name
version = project.version
artifact(jar)
pom {
licenses {
license {
name = license
url = license_url
}
}
}
}
}
repositories {
maven {
url "https://maven.melanx.de/release"
credentials {
username = project.findProperty('mavenUsername') ?: System.getenv('MAVEN_USERNAME')
password = project.findProperty('mavenPassword') ?: System.getenv('MAVEN_PASSWORD')
}
}
}
}
tasks.withType(JavaCompile).configureEach { tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' options.encoding = 'UTF-8'
} }

View file

@ -3,30 +3,24 @@ org.gradle.daemon=true
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.caching=true org.gradle.caching=true
org.gradle.configuration-cache=true org.gradle.configuration-cache=true
## Mappings ## Mappings
parchment_minecraft_version=1.21 parchment_minecraft_version=1.21
parchment_mappings_version=2024.07.28 parchment_mappings_version=2024.07.28
## Loader Properties ## Loader Properties
minecraft_version=1.21 minecraft_version=1.21
neo_version=21.0.167 neo_version=21.0.167
loader_version_range=[4,) loader_version_range=[4,)
## Mod Properties ## Mod Properties
modid=simplebackups modid=extbackup
mod_name=Simple Backups mod_name=ExtBackup
group=de.melanx group=net.sweevo
base_version=2.0 mod_version=2.0.0
## Upload Properties ## Upload Properties
upload_versions=1.21, 1.21.1 upload_versions=1.21, 1.21.1
upload_release=release upload_release=release
modrinth_project=fzSKSXVK #modrinth_project=fzSKSXVK
curse_project=583228 #curse_project=583228
## Misc ## Misc
remote_maven=https://maven.melanx.de/release
license=The Apache License, Version 2.0 license=The Apache License, Version 2.0
license_url=https://www.apache.org/licenses/LICENSE-2.0.txt license_url=https://www.apache.org/licenses/LICENSE-2.0.txt
changelog_repository=https://github.com/ChaoticTrials/SimpleBackups/commit/%H changelog_repository=https://github.com/Jinks/ExtBackup/commit/%H

View file

@ -10,4 +10,4 @@ plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
} }
rootProject.name = 'SimpleBackups' rootProject.name = 'ExtBackup'

View file

@ -1,4 +1,4 @@
package de.melanx.simplebackups; package net.sweevo.jinks;
import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
@ -17,6 +17,18 @@ public class BackupData extends SavedData {
// use BackupData.get // use BackupData.get
} }
public static BackupData get(ServerLevel level) {
return BackupData.get(level.getServer());
}
public static BackupData get(MinecraftServer server) {
return server.overworld().getDataStorage().computeIfAbsent(BackupData.factory(), "extbackup");
}
private static SavedData.Factory<BackupData> factory() {
return new SavedData.Factory<>(BackupData::new, (nbt, provider) -> new BackupData().load(nbt, provider));
}
@Nonnull @Nonnull
@Override @Override
public CompoundTag save(@Nonnull CompoundTag nbt, @Nonnull HolderLookup.Provider provider) { public CompoundTag save(@Nonnull CompoundTag nbt, @Nonnull HolderLookup.Provider provider) {
@ -25,29 +37,21 @@ public class BackupData extends SavedData {
return nbt; return nbt;
} }
public static BackupData get(ServerLevel level) {
return BackupData.get(level.getServer());
}
public static BackupData get(MinecraftServer server) {
return server.overworld().getDataStorage().computeIfAbsent(BackupData.factory(), "simplebackups");
}
public BackupData load(@Nonnull CompoundTag nbt, @Nonnull HolderLookup.Provider provider) { public BackupData load(@Nonnull CompoundTag nbt, @Nonnull HolderLookup.Provider provider) {
this.lastSaved = nbt.getLong("lastSaved"); this.lastSaved = nbt.getLong("lastSaved");
this.paused = nbt.getBoolean("paused"); this.paused = nbt.getBoolean("paused");
return this; return this;
} }
public boolean isPaused() {
return this.paused;
}
public void setPaused(boolean paused) { public void setPaused(boolean paused) {
this.paused = paused; this.paused = paused;
this.setDirty(); this.setDirty();
} }
public boolean isPaused() {
return this.paused;
}
public long getLastSaved() { public long getLastSaved() {
return this.lastSaved; return this.lastSaved;
} }
@ -56,8 +60,4 @@ public class BackupData extends SavedData {
this.lastSaved = time; this.lastSaved = time;
this.setDirty(); this.setDirty();
} }
private static SavedData.Factory<BackupData> factory() {
return new SavedData.Factory<>(BackupData::new, (nbt, provider) -> new BackupData().load(nbt, provider));
}
} }

View file

@ -1,8 +1,5 @@
package de.melanx.simplebackups; package net.sweevo.jinks;
import de.melanx.simplebackups.config.CommonConfig;
import de.melanx.simplebackups.config.ServerConfig;
import de.melanx.simplebackups.network.Pause;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.DefaultUncaughtExceptionHandler; import net.minecraft.DefaultUncaughtExceptionHandler;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@ -10,24 +7,29 @@ import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Style; import net.minecraft.network.chat.Style;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
//import net.minecraft.world.level.storage.LevelStorageSource;
import net.neoforged.fml.i18n.I18nManager; import net.neoforged.fml.i18n.I18nManager;
import net.neoforged.neoforge.network.registration.NetworkRegistry; import net.neoforged.neoforge.network.registration.NetworkRegistry;
import net.sweevo.jinks.config.CommonConfig;
import net.sweevo.jinks.config.ServerConfig;
import net.sweevo.jinks.network.Pause;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder; import java.time.format.DateTimeFormatterBuilder;
import java.time.format.SignStyle; import java.time.format.SignStyle;
import java.time.temporal.ChronoField; import java.time.temporal.ChronoField;
import java.util.*; import java.util.Date;
import java.util.Optional;
public class BackupThread extends Thread { public class BackupThread extends Thread {
public static final Logger LOGGER = LoggerFactory.getLogger(BackupThread.class);
private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder() private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
.appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD).appendLiteral('-') .appendValue(ChronoField.YEAR, 4, 10, SignStyle.EXCEEDS_PAD).appendLiteral('-')
.appendValue(ChronoField.MONTH_OF_YEAR, 2).appendLiteral('-') .appendValue(ChronoField.MONTH_OF_YEAR, 2).appendLiteral('-')
@ -36,14 +38,16 @@ public class BackupThread extends Thread {
.appendValue(ChronoField.MINUTE_OF_HOUR, 2).appendLiteral('-') .appendValue(ChronoField.MINUTE_OF_HOUR, 2).appendLiteral('-')
.appendValue(ChronoField.SECOND_OF_MINUTE, 2) .appendValue(ChronoField.SECOND_OF_MINUTE, 2)
.toFormatter(); .toFormatter();
public static final Logger LOGGER = LoggerFactory.getLogger(BackupThread.class);
private final MinecraftServer server; private final MinecraftServer server;
private final boolean quiet; private final boolean quiet;
private final File script;
private BackupThread(@Nonnull MinecraftServer server, boolean quiet, BackupData backupData) { private BackupThread(@Nonnull MinecraftServer server, boolean quiet, BackupData backupData) {
this.server = server; this.server = server;
this.quiet = quiet; this.quiet = quiet;
this.setName("SimpleBackups"); this.setName("ExtBackup");
this.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); this.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER));
this.script = CommonConfig.getScript();
} }
public static boolean tryCreateBackup(MinecraftServer server) { public static boolean tryCreateBackup(MinecraftServer server) {
@ -74,16 +78,29 @@ public class BackupThread extends Thread {
thread.start(); thread.start();
} }
@SuppressWarnings("null")
public static MutableComponent component(@Nullable ServerPlayer player, String key, Object... parameters) {
if (player != null) {
//noinspection UnstableApiUsage
if (NetworkRegistry.hasChannel(player.connection.connection, null, Pause.ID)) {
return Component.translatable(key, parameters);
}
}
return Component.literal(String.format(Optional.ofNullable(I18nManager.loadTranslations("en_us").get(key)).orElse(key), parameters));
}
@Override @Override
public void run() { public void run() {
try { try {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
this.broadcast("simplebackups.backup_started", Style.EMPTY.withColor(ChatFormatting.GOLD)); this.broadcast("extbackup.backup_started", Style.EMPTY.withColor(ChatFormatting.GOLD));
this.makeWorldBackup();
long end = System.currentTimeMillis(); long end = System.currentTimeMillis();
String time = Timer.getTimer(end - start); String time = Timer.getTimer(end - start);
this.broadcast("simplebackups.backup_finished", Style.EMPTY.withColor(ChatFormatting.GOLD), time); this.broadcast("extbackup.backup_finished", Style.EMPTY.withColor(ChatFormatting.GOLD), time);
} catch (Exception e) { } catch (Exception e) {
SimpleBackups.LOGGER.error("Error backing up", e); ExtBackup.LOGGER.error("Error backing up", e);
} }
} }
@ -99,21 +116,23 @@ public class BackupThread extends Thread {
} }
} }
@SuppressWarnings("null")
public static MutableComponent component(@Nullable ServerPlayer player, String key, Object... parameters) {
if (player != null) {
//noinspection UnstableApiUsage
if (NetworkRegistry.hasChannel(player.connection.connection, null, Pause.ID)) {
return Component.translatable(key, parameters);
}
}
return Component.literal(String.format(Optional.ofNullable(I18nManager.loadTranslations("en_us").get(key)).orElse(key), parameters));
}
// vanilla copy with modifications // vanilla copy with modifications
private long makeWorldBackup() throws IOException { private void makeWorldBackup() throws IOException {
return 0; if (!script.exists() || !script.canExecute()) {
ExtBackup.LOGGER.error("Cannot access or execute backup script. Bailing out!");
}
ProcessBuilder pb = new ProcessBuilder(script.getAbsolutePath());
int returnValue = -1;
pb.redirectErrorStream(true);
try {
Process backup = pb.start();
returnValue = backup.waitFor();
} catch (Exception ex) {
ExtBackup.LOGGER.error("Something went wrong with the Backup script!");
ExtBackup.LOGGER.error("Check your Backups.");
ex.printStackTrace();
}
} }
private static class Timer { private static class Timer {

View file

@ -1,20 +1,25 @@
package de.melanx.simplebackups; package net.sweevo.jinks;
import de.melanx.simplebackups.commands.BackupCommand;
import de.melanx.simplebackups.commands.PauseCommand;
import de.melanx.simplebackups.config.CommonConfig;
import de.melanx.simplebackups.config.ServerConfig;
import de.melanx.simplebackups.network.Pause;
import net.minecraft.commands.Commands; import net.minecraft.commands.Commands;
//import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.neoforge.event.RegisterCommandsEvent; import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.server.ServerAboutToStartEvent;
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
import net.neoforged.neoforge.event.tick.LevelTickEvent; import net.neoforged.neoforge.event.tick.LevelTickEvent;
import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.PacketDistributor;
import net.neoforged.neoforge.network.registration.NetworkRegistry; import net.neoforged.neoforge.network.registration.NetworkRegistry;
import net.sweevo.jinks.commands.BackupCommand;
import net.sweevo.jinks.commands.PauseCommand;
import net.sweevo.jinks.config.CommonConfig;
import net.sweevo.jinks.config.ServerConfig;
import net.sweevo.jinks.network.Pause;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
public class EventListener { public class EventListener {
@ -22,12 +27,31 @@ public class EventListener {
@SubscribeEvent @SubscribeEvent
public void registerCommands(RegisterCommandsEvent event) { public void registerCommands(RegisterCommandsEvent event) {
event.getDispatcher().register(Commands.literal(SimpleBackups.MODID) event.getDispatcher().register(Commands.literal(ExtBackup.MODID)
.requires(stack -> ServerConfig.commandsCheatsDisabled() || stack.hasPermission(2)) .requires(stack -> ServerConfig.commandsCheatsDisabled() || stack.hasPermission(2))
.then(BackupCommand.register()) .then(BackupCommand.register())
.then(PauseCommand.register())); .then(PauseCommand.register()));
} }
@SuppressWarnings("ResultOfMethodCallIgnored")
@SubscribeEvent
public void onServerStart(ServerAboutToStartEvent event) {
File script = CommonConfig.getScript();
if (!script.exists()) {
try {
script.getParentFile().mkdirs();
Files.writeString(script.toPath(), "#!/bin/bash\n# Put your backup script here!\n\nexit 0");
script.setExecutable(true);
ExtBackup.LOGGER.info("No backup script was found, a script has been created at {}, please modify it to your liking.", script.getAbsolutePath());
} catch (IOException | SecurityException e) {
ExtBackup.LOGGER.error("Backup script does not exist and cannot be created!");
ExtBackup.LOGGER.error("Disabling ExtBackup!");
CommonConfig.setEnabled(false);
}
}
ExtBackup.LOGGER.info("Active script: {}", script.getAbsolutePath());
}
@SubscribeEvent @SubscribeEvent
public void onServerTick(LevelTickEvent.Post event) { public void onServerTick(LevelTickEvent.Post event) {
if (event.getLevel() instanceof ServerLevel level && !level.isClientSide if (event.getLevel() instanceof ServerLevel level && !level.isClientSide
@ -38,7 +62,7 @@ public class EventListener {
boolean done = BackupThread.tryCreateBackup(level.getServer()); boolean done = BackupThread.tryCreateBackup(level.getServer());
if (done) { if (done) {
SimpleBackups.LOGGER.info("Backup done."); ExtBackup.LOGGER.info("Backup done.");
} }
} }
} }
@ -64,4 +88,14 @@ public class EventListener {
} }
} }
} }
@SubscribeEvent
public void onServerShutdown(ServerStoppingEvent event) {
if (CommonConfig.doRunOnShutDown()) {
boolean done = BackupThread.tryCreateBackup(event.getServer());
if (done) {
ExtBackup.LOGGER.info("Backup done.");
}
}
}
} }

View file

@ -1,9 +1,5 @@
package de.melanx.simplebackups; package net.sweevo.jinks;
import de.melanx.simplebackups.client.ClientEventHandler;
import de.melanx.simplebackups.config.CommonConfig;
import de.melanx.simplebackups.config.ServerConfig;
import de.melanx.simplebackups.network.Pause;
import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModContainer; import net.neoforged.fml.ModContainer;
@ -13,16 +9,20 @@ import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent;
import net.neoforged.neoforge.network.registration.PayloadRegistrar; import net.neoforged.neoforge.network.registration.PayloadRegistrar;
import net.sweevo.jinks.client.ClientEventHandler;
import net.sweevo.jinks.config.CommonConfig;
import net.sweevo.jinks.config.ServerConfig;
import net.sweevo.jinks.network.Pause;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@Mod(SimpleBackups.MODID) @Mod(ExtBackup.MODID)
public class SimpleBackups { public class ExtBackup {
public static final Logger LOGGER = LoggerFactory.getLogger(SimpleBackups.class); public static final Logger LOGGER = LoggerFactory.getLogger(ExtBackup.class);
public static final String MODID = "simplebackups"; public static final String MODID = "extbackup";
public SimpleBackups(IEventBus modEventBus, ModContainer modContainer, Dist dist) { public ExtBackup(IEventBus modEventBus, ModContainer modContainer, Dist dist) {
modContainer.registerConfig(ModConfig.Type.COMMON, CommonConfig.CONFIG); modContainer.registerConfig(ModConfig.Type.COMMON, CommonConfig.CONFIG);
modContainer.registerConfig(ModConfig.Type.SERVER, ServerConfig.CONFIG); modContainer.registerConfig(ModConfig.Type.SERVER, ServerConfig.CONFIG);
NeoForge.EVENT_BUS.register(new EventListener()); NeoForge.EVENT_BUS.register(new EventListener());
@ -35,7 +35,7 @@ public class SimpleBackups {
} }
private void onRegisterPayloadHandler(RegisterPayloadHandlersEvent event) { private void onRegisterPayloadHandler(RegisterPayloadHandlersEvent event) {
PayloadRegistrar registrar = event.registrar(SimpleBackups.MODID) PayloadRegistrar registrar = event.registrar(ExtBackup.MODID)
.versioned("1.0") .versioned("1.0")
.optional(); .optional();

View file

@ -1,4 +1,4 @@
package de.melanx.simplebackups; package net.sweevo.jinks;
import java.util.Locale; import java.util.Locale;

View file

@ -1,4 +1,4 @@
package de.melanx.simplebackups.client; package net.sweevo.jinks.client;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
@ -11,17 +11,17 @@ import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent;
public class ClientEventHandler { public class ClientEventHandler {
private static final MutableComponent COMPONENT = Component.translatable("simplebackups.backups_paused").withStyle(ChatFormatting.RED); private static final MutableComponent COMPONENT = Component.translatable("extbackup.backups_paused").withStyle(ChatFormatting.RED);
private static boolean isPaused = false; private static boolean isPaused = false;
public static void setPaused(boolean paused) {
isPaused = paused;
}
public static boolean isPaused() { public static boolean isPaused() {
return isPaused; return isPaused;
} }
public static void setPaused(boolean paused) {
isPaused = paused;
}
@SuppressWarnings("resource") @SuppressWarnings("resource")
@SubscribeEvent @SubscribeEvent
public void onRenderText(CustomizeGuiOverlayEvent.DebugText event) { public void onRenderText(CustomizeGuiOverlayEvent.DebugText event) {

View file

@ -1,13 +1,13 @@
package de.melanx.simplebackups.commands; package net.sweevo.jinks.commands;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import de.melanx.simplebackups.BackupThread;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands; import net.minecraft.commands.Commands;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.sweevo.jinks.BackupThread;
public class BackupCommand implements Command<CommandSourceStack> { public class BackupCommand implements Command<CommandSourceStack> {

View file

@ -1,13 +1,13 @@
package de.melanx.simplebackups.commands; package net.sweevo.jinks.commands;
import com.mojang.brigadier.Command; import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContext;
import de.melanx.simplebackups.BackupData;
import de.melanx.simplebackups.network.Pause;
import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands; import net.minecraft.commands.Commands;
import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.PacketDistributor;
import net.sweevo.jinks.BackupData;
import net.sweevo.jinks.network.Pause;
public class PauseCommand implements Command<CommandSourceStack> { public class PauseCommand implements Command<CommandSourceStack> {

View file

@ -1,32 +1,42 @@
package de.melanx.simplebackups.config; package net.sweevo.jinks.config;
import net.neoforged.neoforge.common.ModConfigSpec; import net.neoforged.neoforge.common.ModConfigSpec;
import java.io.File;
import static net.neoforged.fml.loading.FMLPaths.GAMEDIR;
public class CommonConfig { public class CommonConfig {
public static final ModConfigSpec CONFIG; public static final ModConfigSpec CONFIG;
private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder(); private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder();
private static ModConfigSpec.BooleanValue enabled;
private static ModConfigSpec.IntValue timer;
private static ModConfigSpec.BooleanValue sendMessages;
private static ModConfigSpec.BooleanValue noPlayerBackups;
private static ModConfigSpec.BooleanValue runOnShutdown;
private static ModConfigSpec.ConfigValue<String> script;
private static File cachedScript;
static { static {
init(BUILDER); init(BUILDER);
CONFIG = BUILDER.build(); CONFIG = BUILDER.build();
} }
private static ModConfigSpec.BooleanValue enabled;
private static ModConfigSpec.IntValue timer;
private static ModConfigSpec.BooleanValue sendMessages;
private static ModConfigSpec.BooleanValue noPlayerBackups;
public static void init(ModConfigSpec.Builder builder) { public static void init(ModConfigSpec.Builder builder) {
enabled = builder.comment("If set false, no backups are being made.") enabled = builder.comment("If set false, no backups are being made.")
.define("enabled", true); .define("enabled", true);
timer = builder.comment("The time between two backups in minutes", "5 = each 5 minutes", "60 = each hour", "1440 = each day") timer = builder.comment("The time between two backups in minutes", "5 = each 5 minutes", "60 = each hour", "1440 = each day")
.defineInRange("timer", 120, 1, Short.MAX_VALUE); .defineInRange("timer", 10, 1, Short.MAX_VALUE);
sendMessages = builder.comment("Should message be sent when backup is in the making?") sendMessages = builder.comment("Should message be sent when backup is in the making?")
.define("sendMessages", true); .define("sendMessages", true);
noPlayerBackups = builder.comment("Create backups, even if nobody is online") noPlayerBackups = builder.comment("Create backups, even if nobody is online")
.define("noPlayerBackups", false); .define("noPlayerBackups", false);
runOnShutdown = builder.comment("Create backup on server shutdown")
.define("runOnShutdown", true);
script = builder.comment("Script location - this script is run on each interval")
.define("script", "local/extbackup/runbackup.sh");
builder.push("mod_compat"); builder.push("mod_compat");
builder.pop(); builder.pop();
@ -36,6 +46,10 @@ public class CommonConfig {
return enabled.get(); return enabled.get();
} }
public static void setEnabled(boolean value) {
enabled.set(value);
}
// converts config value from milliseconds to minutes // converts config value from milliseconds to minutes
public static int getTimer() { public static int getTimer() {
return timer.get() * 60 * 1000; return timer.get() * 60 * 1000;
@ -45,7 +59,19 @@ public class CommonConfig {
return noPlayerBackups.get(); return noPlayerBackups.get();
} }
public static boolean doRunOnShutDown() {
return runOnShutdown.get();
}
public static boolean sendMessages() { public static boolean sendMessages() {
return sendMessages.get(); return sendMessages.get();
} }
public static File getScript() {
String scr = script.get();
if (cachedScript == null) {
cachedScript = scr.trim().isEmpty() ? new File(GAMEDIR.get() + "local/extbackup/runbackup.sh") : new File(scr.trim());
}
return cachedScript;
}
} }

View file

@ -1,4 +1,4 @@
package de.melanx.simplebackups.config; package net.sweevo.jinks.config;
import net.neoforged.neoforge.common.ModConfigSpec; import net.neoforged.neoforge.common.ModConfigSpec;
@ -6,15 +6,14 @@ public class ServerConfig {
public static final ModConfigSpec CONFIG; public static final ModConfigSpec CONFIG;
private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder(); private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder();
private static ModConfigSpec.BooleanValue commandsCheatsDisabled;
private static ModConfigSpec.BooleanValue messagesForEveryone;
static { static {
init(BUILDER); init(BUILDER);
CONFIG = BUILDER.build(); CONFIG = BUILDER.build();
} }
private static ModConfigSpec.BooleanValue commandsCheatsDisabled;
private static ModConfigSpec.BooleanValue messagesForEveryone;
public static void init(ModConfigSpec.Builder builder) { public static void init(ModConfigSpec.Builder builder) {
commandsCheatsDisabled = builder.comment("Should commands work without cheats enabled? Mainly recommended for single player, otherwise all users on servers can trigger commands.") commandsCheatsDisabled = builder.comment("Should commands work without cheats enabled? Mainly recommended for single player, otherwise all users on servers can trigger commands.")
.define("commandsCheatsDisabled", false); .define("commandsCheatsDisabled", false);

View file

@ -1,19 +1,19 @@
package de.melanx.simplebackups.network; package net.sweevo.jinks.network;
import de.melanx.simplebackups.SimpleBackups;
import de.melanx.simplebackups.client.ClientEventHandler;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs; import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec; import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.neoforged.neoforge.network.handling.IPayloadContext; import net.neoforged.neoforge.network.handling.IPayloadContext;
import net.sweevo.jinks.ExtBackup;
import net.sweevo.jinks.client.ClientEventHandler;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public record Pause(boolean pause) implements CustomPacketPayload { public record Pause(boolean pause) implements CustomPacketPayload {
public static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(SimpleBackups.MODID, "pause"); public static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(ExtBackup.MODID, "pause");
public static final CustomPacketPayload.Type<Pause> TYPE = new Type<>(ID); public static final CustomPacketPayload.Type<Pause> TYPE = new Type<>(ID);
public static final StreamCodec<FriendlyByteBuf, Pause> CODEC = StreamCodec.composite( public static final StreamCodec<FriendlyByteBuf, Pause> CODEC = StreamCodec.composite(

View file

@ -1,15 +1,15 @@
modLoader = "javafml" modLoader = "javafml"
loaderVersion = "${loader_version_range}" loaderVersion = "${loader_version_range}"
license = "${license}" license = "${license}"
issueTrackerURL = "https://github.com/ChaoticTrials/SimpleBackups/issues" issueTrackerURL = "https://git.sweevo.net/jinks/ExtBackup/issues"
[[mods]] [[mods]]
modId = "${modid}" modId = "${modid}"
version = "${mod_version}" version = "${mod_version}"
displayName = "Simple Backups" displayName = "ExtBackup"
updateJSONURL = "https://assets.melanx.de/updates/simple-backups.json" #updateJSONURL = "N/A"
displayURL = "https://modrinth.com/user/MelanX" displayURL = "https://git.sweevo.net/jinks/ExtBackup"
authors = "MelanX" authors = "MelanX, jinks"
displayTest = "IGNORE_ALL_VERSION" displayTest = "IGNORE_ALL_VERSION"
description = ''' description = '''
A simple mod to create scheduled backups. A simple mod to create scheduled backups.

View file

@ -0,0 +1,5 @@
{
"extbackup.backup_started": "Backup gestartet...",
"extbackup.backup_finished": "Backup fertiggestellt in %s",
"extbackup.backups_paused": "Backups pausiert"
}

View file

@ -0,0 +1,5 @@
{
"extbackup.backup_started": "Backup started...",
"extbackup.backup_finished": "Backup completed in %s",
"extbackup.backups_paused": "Backups paused"
}

View file

@ -1,8 +0,0 @@
{
"simplebackups.backup_started": "Backup gestartet...",
"simplebackups.backup_finished": "Backup fertiggestellt in %s",
"simplebackups.backups_paused": "Backups pausiert",
"simplebackups.commands.only_modified": "Es werden nicht nur veränderte Dateien gesichert, prüfe deine Konfigurationsdatei",
"simplebackups.commands.is_merging": "Ein Zusammenführungsvorgang ist bereits im Gange",
"simplebackups.commands.finished": "Zusammenführen der Backups erfolgreich abgeschlossen"
}

View file

@ -1,8 +0,0 @@
{
"simplebackups.backup_started": "Backup started...",
"simplebackups.backup_finished": "Backup completed in %s",
"simplebackups.backups_paused": "Backups paused",
"simplebackups.commands.only_modified": "Not only modified files are being backed up, please check your configuration file",
"simplebackups.commands.is_merging": "A merge operation is already in progress",
"simplebackups.commands.finished": "Merging backups completed successfully"
}