Skip to content

Commit

Permalink
Changed the automated backup timer logic and config.
Browse files Browse the repository at this point in the history
  • Loading branch information
MehradN committed Mar 6, 2023
1 parent bb7a47b commit b46452e
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 58 deletions.
43 changes: 20 additions & 23 deletions src/main/java/ir/mehradn/rollback/config/RollbackConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,24 @@ public static void register() {
MidnightConfig.init("rollback", _RollbackConfig.class);
}

public static int getMaxBackupsPerWorld() {
public static int maxBackupsPerWorld() {
return _RollbackConfig.backupsPerWorld;
}

public static BackupMode backupMode() {
switch (_RollbackConfig.backupFrequency) {
case ONE_PER_DAY, TWO_PER_DAY, FOUR_PER_DAY -> {return BackupMode.IN_GAME_DAY;}
case TWENTY_MINUTES, TEN_MINUTES, FIVE_MINUTES -> {return BackupMode.REAL_TIME;}
}
return BackupMode.REAL_TIME;
public static int daysPerBackup() {
return _RollbackConfig.backupFrequency;
}

public static int ticksPerBackup() {
switch (_RollbackConfig.backupFrequency) {
case ONE_PER_DAY, TWENTY_MINUTES -> {return 24000;}
case TWO_PER_DAY, TEN_MINUTES -> {return 12000;}
case FOUR_PER_DAY, FIVE_MINUTES -> {return 6000;}
return _RollbackConfig.backupFrequency * 24000;
}

public static TimerMode timerMode() {
switch (_RollbackConfig.timerMode) {
case DAYLIGHT_CYCLE -> {return TimerMode.DAYLIGHT_CYCLE;}
case IN_GAME_TIME -> {return TimerMode.IN_GAME_TIME;}
}
return 24000;
return TimerMode.IN_GAME_TIME;
}

public static CommandAccess commandAccess() {
Expand All @@ -47,9 +46,9 @@ public static boolean replaceGameRulesButton() {
return _RollbackConfig.replaceGameRulesButton;
}

public enum BackupMode {
IN_GAME_DAY,
REAL_TIME
public enum TimerMode {
DAYLIGHT_CYCLE,
IN_GAME_TIME
}

public enum CommandAccess {
Expand All @@ -60,13 +59,9 @@ public enum CommandAccess {
// DO NOT USE OUTSIDE OF THIS CLASS
// I am forced to keep it public.
public static final class _RollbackConfig extends MidnightConfig {
public enum _BackupFrequency {
ONE_PER_DAY,
TWO_PER_DAY,
FOUR_PER_DAY,
TWENTY_MINUTES,
TEN_MINUTES,
FIVE_MINUTES
public enum _TimerMode {
DAYLIGHT_CYCLE,
IN_GAME_TIME
}

public enum _CommandAccess {
Expand All @@ -76,8 +71,10 @@ public enum _CommandAccess {

@Entry(min = 1, max = 10, isSlider = true)
public static int backupsPerWorld = 5;
@Entry(min = 1, max = 15, isSlider = true)
public static int backupFrequency = 1;
@Entry
public static _BackupFrequency backupFrequency = _BackupFrequency.ONE_PER_DAY;
public static _TimerMode timerMode = _TimerMode.DAYLIGHT_CYCLE;
@Entry
public static _CommandAccess commandAccess = _CommandAccess.ON_CHEATS;
@Entry
Expand Down
81 changes: 64 additions & 17 deletions src/main/java/ir/mehradn/rollback/event/AutomatedBackup.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,90 @@
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Triple;

@Environment(EnvType.CLIENT)
public final class AutomatedBackup {
private static int latestBackup;
private static int latestUpdate;
private static int daysPassed;
private static int sinceDay;
private static int sinceBackup;

public static void register() {
ServerLifecycleEvents.SERVER_STARTED.register(AutomatedBackup::onServerStarted);
ServerTickEvents.END_SERVER_TICK.register(AutomatedBackup::onEndTick);
ServerLifecycleEvents.SERVER_STOPPING.register(AutomatedBackup::onServerStopping);
}

public static void onServerStarted(MinecraftServer server) {
latestBackup = server.getTicks();
Rollback.LOGGER.info("Reading the timer information...");
BackupManager backupManager = ((MinecraftServerExpanded)server).getBackupManager();
String worldName = ((MinecraftServerExpanded)server).getSession().getLevelSummary().getName();
Triple<Integer, Integer, Integer> info = backupManager.getTimerInformation(worldName);

latestUpdate = server.getTicks();
daysPassed = info.getLeft();
sinceDay = info.getMiddle();
sinceBackup = info.getRight();
}

public static void onEndTick(MinecraftServer server) {
if (shouldCreateBackup(server)) {
Rollback.LOGGER.info("Creating an automated backup...");
int serverTick = server.getTicks();
int worldTick = (int)server.getWorld(World.OVERWORLD).getTimeOfDay();

if (shouldUpdate(serverTick, worldTick)) {
Rollback.LOGGER.info("Updating the timer information...");
BackupManager backupManager = ((MinecraftServerExpanded)server).getBackupManager();
backupManager.createRollbackBackup(server);
latestBackup = server.getTicks();
String worldName = ((MinecraftServerExpanded)server).getSession().getLevelSummary().getName();

int timePassed = serverTick - latestUpdate;
latestUpdate = serverTick;
sinceDay += timePassed;
sinceBackup += timePassed;
if (isMorning(worldTick) && sinceDay >= 11900) {
daysPassed++;
sinceDay = 0;
}

if (shouldCreateBackup(worldTick, backupManager, worldName)) {
Rollback.LOGGER.info("Creating an automated backup...");
backupManager.createRollbackBackup(server, true);
daysPassed = 0;
sinceDay = 0;
sinceBackup = 0;
} else {
backupManager.setTimerInformation(worldName, daysPassed, sinceBackup);
}
}
}

private static boolean shouldCreateBackup(MinecraftServer server) {
public static void onServerStopping(MinecraftServer server) {
int serverTick = server.getTicks();
int worldTick = (int)server.getWorld(World.OVERWORLD).getTimeOfDay();
BackupManager backupManager = ((MinecraftServerExpanded)server).getBackupManager();
String worldName = ((MinecraftServerExpanded)server).getSession().getLevelSummary().getName();

if (!backupManager.getAutomated(worldName))
return false;
if (RollbackConfig.backupMode() == RollbackConfig.BackupMode.REAL_TIME)
return (serverTick - latestBackup) >= (RollbackConfig.ticksPerBackup() + 20);
else
return (
((serverTick - latestBackup) >= (RollbackConfig.ticksPerBackup() / 2 - 20))
&& (((worldTick - 20) % RollbackConfig.ticksPerBackup()) == 0)
);
int timePassed = serverTick - latestUpdate;
sinceDay += timePassed;
sinceBackup += timePassed;

backupManager.setTimerInformation(worldName, daysPassed, sinceDay, sinceBackup);
}

private static boolean isMorning(int worldTick) {
return ((worldTick - 20) % 24000 == 0);
}

private static boolean shouldUpdate(int serverTick, int worldTick) {
return (isMorning(worldTick) || (serverTick - latestUpdate + sinceBackup) % 24000 == 0);
}

private static boolean shouldCreateBackup(int worldTick, BackupManager backupManager, String worldName) {
if (backupManager.getAutomated(worldName)) {
switch (RollbackConfig.timerMode()) {
case DAYLIGHT_CYCLE -> {return (isMorning(worldTick) && daysPassed >= RollbackConfig.daysPerBackup());}
case IN_GAME_TIME -> {return (sinceBackup >= RollbackConfig.ticksPerBackup());}
}
}
return false;
}
}
4 changes: 2 additions & 2 deletions src/main/java/ir/mehradn/rollback/event/RollbackCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static void register() {
.executes((context) -> deleteBackup(context, 0)))
.then(CommandManager.literal("latest")
.executes((context) -> deleteBackup(context, 1)))
.then(CommandManager.argument("number", IntegerArgumentType.integer(1, RollbackConfig.getMaxBackupsPerWorld()))
.then(CommandManager.argument("number", IntegerArgumentType.integer(1, RollbackConfig.maxBackupsPerWorld()))
.executes((context) -> deleteBackup(context, 2))))
.then(CommandManager.literal("list")
.executes(RollbackCommand::listBackups)));
Expand All @@ -55,7 +55,7 @@ public static int backupNow(CommandContext<ServerCommandSource> context) throws
MinecraftServer server = context.getSource().getServer();
BackupManager backupManager = ((MinecraftServerExpanded)server).getBackupManager();

boolean f = backupManager.createRollbackBackup(server);
boolean f = backupManager.createRollbackBackup(server, false);
if (!f)
throw new SimpleCommandExceptionType(Text.translatable("rollback.createBackup.failed")).create();

Expand Down
39 changes: 37 additions & 2 deletions src/main/java/ir/mehradn/rollback/util/backup/BackupManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.level.storage.LevelStorage;
import net.minecraft.world.level.storage.LevelSummary;
import org.apache.commons.lang3.tuple.Triple;

import java.io.*;
import java.nio.file.Files;
Expand Down Expand Up @@ -75,6 +76,29 @@ public void setPromptAnswer(String worldName, boolean automated) {
saveMetadata();
}

public Triple<Integer, Integer, Integer> getTimerInformation(String worldName) {
JsonObject worldObject = getWorldObject(worldName);
int daysPassed = worldObject.get("days_passed").getAsInt();
int sinceDay = worldObject.get("since_day").getAsInt();
int sinceBackup = worldObject.get("since_backup").getAsInt();
return Triple.of(daysPassed, sinceDay, sinceBackup);
}

public void setTimerInformation(String worldName, int daysPassed, int sinceBackup) {
JsonObject worldObject = getWorldObject(worldName);
worldObject.addProperty("days_passed", daysPassed);
worldObject.addProperty("since_backup", sinceBackup);
saveMetadata();
}

public void setTimerInformation(String worldName, int daysPassed, int sinceDay, int sinceBackup) {
JsonObject worldObject = getWorldObject(worldName);
worldObject.addProperty("days_passed", daysPassed);
worldObject.addProperty("since_day", sinceDay);
worldObject.addProperty("since_backup", sinceBackup);
saveMetadata();
}

public List<RollbackBackup> getRollbacksFor(String worldName) {
ArrayList<RollbackBackup> list = new ArrayList<>();
JsonArray array = getWorldObject(worldName).getAsJsonArray("backups");
Expand All @@ -99,15 +123,15 @@ public boolean createNormalBackup(LevelSummary summary) {
}
}

public boolean createRollbackBackup(MinecraftServer server) {
public boolean createRollbackBackup(MinecraftServer server, boolean automated) {
Rollback.LOGGER.info("Creating a rollback backup...");
LevelStorage.Session session = ((MinecraftServerExpanded)server).getSession();
String worldName = session.getLevelSummary().getName();
LocalDateTime now = LocalDateTime.now();
JsonObject worldObject = getWorldObject(worldName);
JsonArray array = worldObject.getAsJsonArray("backups");

while (array.size() >= RollbackConfig.getMaxBackupsPerWorld())
while (array.size() >= RollbackConfig.maxBackupsPerWorld())
deleteBackup(worldName, 0);
deleteNonexistentIcons(worldName);

Expand Down Expand Up @@ -162,6 +186,11 @@ public boolean createRollbackBackup(MinecraftServer server) {
path3 = this.rollbackDirectory.relativize(path3);
RollbackBackup backup = new RollbackBackup(worldName, path2, path3, LocalDateTime.now(), daysPlayed);
array.add(backup.toObject());
if (automated) {
worldObject.addProperty("days_passed", 0);
worldObject.addProperty("since_day", 0);
worldObject.addProperty("since_backup", 0);
}
saveMetadata();

return true;
Expand Down Expand Up @@ -256,6 +285,12 @@ private JsonObject getWorldObject(String worldName) {
worldObject.addProperty("automated", false);
if (!worldObject.has("prompted"))
worldObject.addProperty("prompted", false);
if (!worldObject.has("days_passed"))
worldObject.addProperty("days_passed", 0);
if (!worldObject.has("since_day"))
worldObject.addProperty("since_day", 0);
if (!worldObject.has("since_backup"))
worldObject.addProperty("since_backup", 0);
if (!worldObject.has("backups"))
worldObject.add("backups", new JsonArray());

Expand Down
20 changes: 6 additions & 14 deletions src/main/resources/assets/rollback/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,15 @@
"rollback.command.list.title": "Backups:",
"rollback.command.list.noBackups": "There are no backups available for this world.",
"rollback.command.unavailable": "This command is only available to server host.",
"rollback.midnightconfig.title": "Rollback Config Menu",
"rollback.midnightconfig.title": "Rollback Options",
"rollback.midnightconfig.backupsPerWorld": "Maximum Backups Per World:",
"rollback.midnightconfig.backupFrequency": "Automated Backup Frequency:",
"rollback.midnightconfig.allowedWorldTypes": "Create Automated Backup For:",
"rollback.midnightconfig.backupFrequency": "Minecraft Days Per Backup:",
"rollback.midnightconfig.timerMode": "Backup Timer Is Based On:",
"rollback.midnightconfig.commandAccess": "Rollback Command Access:",
"rollback.midnightconfig.replaceReCreateButton": "Replace Re-Create Button:",
"rollback.midnightconfig.replaceGameRulesButton": "Replace GameRules Button:",
"rollback.midnightconfig.enum._BackupFrequency.ONE_PER_DAY": "1 Per Day",
"rollback.midnightconfig.enum._BackupFrequency.TWO_PER_DAY": "2 Per Day",
"rollback.midnightconfig.enum._BackupFrequency.FOUR_PER_DAY": "4 Per Day",
"rollback.midnightconfig.enum._BackupFrequency.TWENTY_MINUTES": "20 Minutes",
"rollback.midnightconfig.enum._BackupFrequency.TEN_MINUTES": "10 Minutes",
"rollback.midnightconfig.enum._BackupFrequency.FIVE_MINUTES": "5 Minutes",
"rollback.midnightconfig.enum._TimerMode.DAYLIGHT_CYCLE": "Daylight Cycle",
"rollback.midnightconfig.enum._TimerMode.IN_GAME_TIME": "In-Game Time",
"rollback.midnightconfig.enum._CommandAccess.ON_CHEATS": "On Cheats",
"rollback.midnightconfig.enum._CommandAccess.ALWAYS": "Always",
"rollback.midnightconfig.enum._AllowedWorldTypes.NONE": "None",
"rollback.midnightconfig.enum._AllowedWorldTypes.SURVIVAL": "Survival Only",
"rollback.midnightconfig.enum._AllowedWorldTypes.ADVENTURE": "Survival & Adventure",
"rollback.midnightconfig.enum._AllowedWorldTypes.ALL_TYPES": "All World Types"
"rollback.midnightconfig.enum._CommandAccess.ALWAYS": "Always"
}

0 comments on commit b46452e

Please sign in to comment.