diff --git a/gradle.properties b/gradle.properties index b68748c..81dcb4b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,7 @@ parchment_version=2023.02.26 loader_version=0.14.14 # Mod Properties -mod_version=0.5.0 +mod_version=0.6.0 maven_group=ir.mehradn archives_base_name=rollback diff --git a/screenshots/ConfigScreen.png b/screenshots/ConfigScreen.png index bc516be..9e262f9 100644 Binary files a/screenshots/ConfigScreen.png and b/screenshots/ConfigScreen.png differ diff --git a/src/main/java/ir/mehradn/rollback/Rollback.java b/src/main/java/ir/mehradn/rollback/Rollback.java index 284fe30..e3cc1a5 100644 --- a/src/main/java/ir/mehradn/rollback/Rollback.java +++ b/src/main/java/ir/mehradn/rollback/Rollback.java @@ -13,7 +13,6 @@ public class Rollback implements ClientModInitializer { public static final Logger LOGGER = LoggerFactory.getLogger("rollback"); - @Override public void onInitializeClient() { LOGGER.info("Registering MidnightConfig..."); RollbackConfig.register(); diff --git a/src/main/java/ir/mehradn/rollback/RollbackPreLaunch.java b/src/main/java/ir/mehradn/rollback/RollbackPreLaunch.java index 38d0b69..e23f534 100644 --- a/src/main/java/ir/mehradn/rollback/RollbackPreLaunch.java +++ b/src/main/java/ir/mehradn/rollback/RollbackPreLaunch.java @@ -1,10 +1,12 @@ package ir.mehradn.rollback; import com.llamalad7.mixinextras.MixinExtrasBootstrap; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; +@Environment(EnvType.CLIENT) public class RollbackPreLaunch implements PreLaunchEntrypoint { - @Override public void onPreLaunch() { MixinExtrasBootstrap.init(); } diff --git a/src/main/java/ir/mehradn/rollback/config/RollbackConfig.java b/src/main/java/ir/mehradn/rollback/config/RollbackConfig.java index c7c6f59..29163f2 100644 --- a/src/main/java/ir/mehradn/rollback/config/RollbackConfig.java +++ b/src/main/java/ir/mehradn/rollback/config/RollbackConfig.java @@ -24,16 +24,16 @@ public static int ticksPerBackup() { public static TimerMode timerMode() { switch (_RollbackConfig.timerMode) { - case DAYLIGHT_CYCLE -> {return TimerMode.DAYLIGHT_CYCLE;} - case IN_GAME_TIME -> {return TimerMode.IN_GAME_TIME;} + case DAYLIGHT_CYCLE -> { return TimerMode.DAYLIGHT_CYCLE; } + case IN_GAME_TIME -> { return TimerMode.IN_GAME_TIME; } } return TimerMode.IN_GAME_TIME; } public static CommandAccess commandAccess() { switch (_RollbackConfig.commandAccess) { - case ON_CHEATS -> {return CommandAccess.ON_CHEATS;} - case ALWAYS -> {return CommandAccess.ALWAYS;} + case ON_CHEATS -> { return CommandAccess.ON_CHEATS; } + case ALWAYS -> { return CommandAccess.ALWAYS; } } return CommandAccess.ON_CHEATS; } diff --git a/src/main/java/ir/mehradn/rollback/event/AutomatedBackup.java b/src/main/java/ir/mehradn/rollback/event/AutomatedBackup.java index 740bfa6..793f81c 100644 --- a/src/main/java/ir/mehradn/rollback/event/AutomatedBackup.java +++ b/src/main/java/ir/mehradn/rollback/event/AutomatedBackup.java @@ -9,6 +9,7 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; import org.apache.commons.lang3.tuple.Triple; @@ -39,7 +40,8 @@ public static void onServerStarted(MinecraftServer server) { public static void onEndTick(MinecraftServer server) { int serverTick = server.getTickCount(); - int worldTick = (int)server.getLevel(Level.OVERWORLD).getDayTime(); + ServerLevel overworld = server.getLevel(Level.OVERWORLD); + int worldTick = (overworld == null ? -1 : (int)overworld.getDayTime()); if (shouldUpdate(serverTick, worldTick)) { Rollback.LOGGER.info("Updating the timer information..."); @@ -80,6 +82,8 @@ public static void onServerStopping(MinecraftServer server) { } private static boolean isMorning(int worldTick) { + if (worldTick == -1) + return false; return ((worldTick - 20) % 24000 == 0); } @@ -90,8 +94,8 @@ private static boolean shouldUpdate(int serverTick, int worldTick) { 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());} + case DAYLIGHT_CYCLE -> { return (isMorning(worldTick) && daysPassed >= RollbackConfig.daysPerBackup()); } + case IN_GAME_TIME -> { return (sinceBackup >= RollbackConfig.ticksPerBackup()); } } } return false; diff --git a/src/main/java/ir/mehradn/rollback/event/RollbackCommand.java b/src/main/java/ir/mehradn/rollback/event/RollbackCommand.java index 950e747..3c09289 100644 --- a/src/main/java/ir/mehradn/rollback/event/RollbackCommand.java +++ b/src/main/java/ir/mehradn/rollback/event/RollbackCommand.java @@ -2,8 +2,6 @@ import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import ir.mehradn.rollback.Rollback; import ir.mehradn.rollback.config.RollbackConfig; import ir.mehradn.rollback.util.backup.BackupManager; @@ -13,11 +11,13 @@ import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.level.storage.LevelStorageSource; import java.util.List; @@ -31,7 +31,7 @@ public static void register() { dispatcher.register(Commands.literal("rollback") .requires(RollbackCommand::hasAccessToCommand) .then(Commands.literal("create") - .executes(RollbackCommand::backupNow)) + .executes(RollbackCommand::createBackup)) .then(Commands.literal("delete") .then(Commands.literal("oldest") .executes((context) -> deleteBackup(context, 0))) @@ -48,23 +48,27 @@ public static boolean hasAccessToCommand(CommandSourceStack source) { return ((RollbackConfig.commandAccess() == RollbackConfig.CommandAccess.ALWAYS) || source.hasPermission(4)); } - public static int backupNow(CommandContext context) throws CommandSyntaxException { - checkIsServerHost(context); + public static int createBackup(CommandContext context) { + if (isNotServerHost(context)) + return 0; Rollback.LOGGER.info("Executing the \"backup new\" command..."); MinecraftServer server = context.getSource().getServer(); BackupManager backupManager = ((MinecraftServerExpanded)server).getBackupManager(); boolean f = backupManager.createRollbackBackup(server, false); - if (!f) - throw new SimpleCommandExceptionType(Component.translatable("rollback.createBackup.failed")).create(); + if (!f) { + context.getSource().sendFailure(Component.translatable("rollback.createBackup.failed")); + return 0; + } context.getSource().sendSuccess(Component.translatable("rollback.createBackup.success"), true); return 1; } - public static int deleteBackup(CommandContext context, int position) throws CommandSyntaxException { - checkIsServerHost(context); + public static int deleteBackup(CommandContext context, int position) { + if (isNotServerHost(context)) + return 0; Rollback.LOGGER.info("Executing the \"backup delete\" command..."); MinecraftServer server = context.getSource().getServer(); @@ -80,15 +84,18 @@ public static int deleteBackup(CommandContext context, int p } boolean f = backupManager.deleteBackup(worldName, index); - if (!f) - throw new SimpleCommandExceptionType(Component.translatable("rollback.deleteBackup.failed")).create(); + if (!f) { + context.getSource().sendFailure(Component.translatable("rollback.deleteBackup.failed")); + return 0; + } context.getSource().sendSuccess(Component.translatable("rollback.deleteBackup.success"), true); return 1; } - public static int listBackups(CommandContext context) throws CommandSyntaxException { - checkIsServerHost(context); + public static int listBackups(CommandContext context) { + if (isNotServerHost(context)) + return 0; MinecraftServer server = context.getSource().getServer(); BackupManager backupManager = ((MinecraftServerExpanded)server).getBackupManager(); @@ -106,16 +113,26 @@ public static int listBackups(CommandContext context) throws MutableComponent part1, part2, part3; part1 = Component.literal(String.format(" #%-2d ", i)); part2 = Component.translatable("rollback.created", backup.getDateAsString()).append(Component.literal(" ")); - part3 = Component.translatable("rollback.day", backup.daysPlayed); + part3 = Component.translatable("rollback.day", backup.getDaysPlayedAsString()); context.getSource().sendSystemMessage(part1.append(part2.append(part3))); } return 1; } - private static void checkIsServerHost(CommandContext context) throws CommandSyntaxException { - Component user1 = Minecraft.getInstance().player.getName(); - Component user2 = context.getSource().getPlayer().getName(); - if (!user1.equals(user2)) - throw new SimpleCommandExceptionType(Component.translatable("rollback.command.unavailable")).create(); + private static boolean isNotServerHost(CommandContext context) { + LocalPlayer player1 = Minecraft.getInstance().player; + ServerPlayer player2 = context.getSource().getPlayer(); + if (player1 == null || player2 == null) { + context.getSource().sendFailure(Component.literal("This command can only be used by a player")); + return true; + } + + Component name1 = player1.getName(); + Component name2 = player2.getName(); + if (!name1.equals(name2)) { + context.getSource().sendFailure(Component.translatable("rollback.command.unavailable")); + return true; + } + return false; } } diff --git a/src/main/java/ir/mehradn/rollback/gui/RollbackScreen.java b/src/main/java/ir/mehradn/rollback/gui/RollbackScreen.java index d2da923..b13602a 100644 --- a/src/main/java/ir/mehradn/rollback/gui/RollbackScreen.java +++ b/src/main/java/ir/mehradn/rollback/gui/RollbackScreen.java @@ -54,6 +54,8 @@ public void removed() { } protected void init() { + assert this.minecraft != null; + this.rollbackList = new RollbackSelectionList( this, this.backupManager, this.levelSummary, this.minecraft, this.width, this.height, 22, this.height - 84, 36 diff --git a/src/main/java/ir/mehradn/rollback/gui/RollbackSelectionList.java b/src/main/java/ir/mehradn/rollback/gui/RollbackSelectionList.java index 9335a67..6d16174 100644 --- a/src/main/java/ir/mehradn/rollback/gui/RollbackSelectionList.java +++ b/src/main/java/ir/mehradn/rollback/gui/RollbackSelectionList.java @@ -169,7 +169,7 @@ public void playBackup() { RollbackSelectionList.this.screen.doAction(WorldSelectionListCallbackAction.JOIN_WORLD); } - public void deleteBackup() {} + public void deleteBackup() { } private DynamicTexture getIconTexture() { Path path = this.summary.getIcon(); @@ -213,14 +213,14 @@ public RollbackEntry(int backupNumber, RollbackBackup rollbackBackup) { "rollback.narrator.selectRollback", this.backupNumber, this.backup.getDateAsString(), - this.backup.daysPlayed + this.backup.getDaysPlayedAsString() ); } public void render(PoseStack poseStack, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { super.render( - Component.translatable("rollback.day", this.backup.daysPlayed), + Component.translatable("rollback.day", this.backup.getDaysPlayedAsString()), Component.translatable("rollback.created", this.backup.getDateAsString()), poseStack, y, x, mouseX, hovered ); diff --git a/src/main/java/ir/mehradn/rollback/mixin/CreateWorldScreenMixin.java b/src/main/java/ir/mehradn/rollback/mixin/CreateWorldScreenMixin.java index b2a6311..4284226 100644 --- a/src/main/java/ir/mehradn/rollback/mixin/CreateWorldScreenMixin.java +++ b/src/main/java/ir/mehradn/rollback/mixin/CreateWorldScreenMixin.java @@ -42,6 +42,7 @@ private void promptFeature(PrimaryLevelData.SpecialWorldProperty specialWorldPro this.redirectCreateNewWorld = true; return; } + assert this.minecraft != null; this.minecraft.setScreen(new ConfirmScreen( (confirmed) -> { this.redirectCreateNewWorld = false; diff --git a/src/main/java/ir/mehradn/rollback/mixin/EditWorldScreenMixin.java b/src/main/java/ir/mehradn/rollback/mixin/EditWorldScreenMixin.java index 2612942..fed62e6 100644 --- a/src/main/java/ir/mehradn/rollback/mixin/EditWorldScreenMixin.java +++ b/src/main/java/ir/mehradn/rollback/mixin/EditWorldScreenMixin.java @@ -6,9 +6,9 @@ import it.unimi.dsi.fastutil.booleans.BooleanConsumer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.worldselection.EditWorldScreen; -import net.minecraft.client.gui.components.Button; import net.minecraft.network.chat.Component; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/ir/mehradn/rollback/mixin/SelectWorldScreenMixin.java b/src/main/java/ir/mehradn/rollback/mixin/SelectWorldScreenMixin.java index 9efa2ac..fdb25ed 100644 --- a/src/main/java/ir/mehradn/rollback/mixin/SelectWorldScreenMixin.java +++ b/src/main/java/ir/mehradn/rollback/mixin/SelectWorldScreenMixin.java @@ -5,10 +5,10 @@ import ir.mehradn.rollback.util.mixin.WorldListEntryExpanded; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; +import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.worldselection.SelectWorldScreen; import net.minecraft.client.gui.screens.worldselection.WorldSelectionList; -import net.minecraft.client.gui.components.Button; import net.minecraft.network.chat.Component; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; diff --git a/src/main/java/ir/mehradn/rollback/util/backup/BackupManager.java b/src/main/java/ir/mehradn/rollback/util/backup/BackupManager.java index 4afca9e..8fa17ba 100644 --- a/src/main/java/ir/mehradn/rollback/util/backup/BackupManager.java +++ b/src/main/java/ir/mehradn/rollback/util/backup/BackupManager.java @@ -11,6 +11,7 @@ import net.minecraft.FileUtil; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.components.toasts.SystemToast; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.network.chat.Component; import net.minecraft.server.MinecraftServer; @@ -176,7 +177,8 @@ public boolean createRollbackBackup(MinecraftServer server, boolean automated) { return false; } - int daysPlayed = (int)(Minecraft.getInstance().level.getDayTime() / 24000); + ClientLevel level = Minecraft.getInstance().level; + int daysPlayed = (level == null ? -1 : (int)level.getDayTime() / 24000); Rollback.LOGGER.debug("Adding the metadata..."); path2 = this.rollbackDirectory.relativize(path2); diff --git a/src/main/java/ir/mehradn/rollback/util/backup/RollbackBackup.java b/src/main/java/ir/mehradn/rollback/util/backup/RollbackBackup.java index 9230452..207992d 100644 --- a/src/main/java/ir/mehradn/rollback/util/backup/RollbackBackup.java +++ b/src/main/java/ir/mehradn/rollback/util/backup/RollbackBackup.java @@ -60,6 +60,10 @@ public JsonObject toObject() { return obj; } + public String getDaysPlayedAsString() { + return (this.daysPlayed == -1 ? "???" : String.valueOf(this.daysPlayed)); + } + public String getDateAsString() { Date date = Date.from(this.backupTime.atZone(ZoneId.systemDefault()).toInstant()); return DATE_FORMAT.format(date); diff --git a/src/main/java/ir/mehradn/rollback/util/mixin/EditWorldScreenExpanded.java b/src/main/java/ir/mehradn/rollback/util/mixin/EditWorldScreenExpanded.java index c1592f2..e6e1a79 100644 --- a/src/main/java/ir/mehradn/rollback/util/mixin/EditWorldScreenExpanded.java +++ b/src/main/java/ir/mehradn/rollback/util/mixin/EditWorldScreenExpanded.java @@ -1,9 +1,12 @@ package ir.mehradn.rollback.util.mixin; import it.unimi.dsi.fastutil.booleans.BooleanConsumer; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import java.util.function.Consumer; +@Environment(EnvType.CLIENT) public interface EditWorldScreenExpanded { BooleanConsumer getCallback(); diff --git a/src/main/resources/assets/rollback/lang/en_us.json b/src/main/resources/assets/rollback/lang/en_us.json index 9925dcc..a472a26 100644 --- a/src/main/resources/assets/rollback/lang/en_us.json +++ b/src/main/resources/assets/rollback/lang/en_us.json @@ -1,11 +1,11 @@ { - "rollback.day": "Day %d", + "rollback.day": "Day %s", "rollback.created": "Created: %s", "rollback.button": "Rollback", - "rollback.createBackup.failed": "Failed to create a rollback backup!", - "rollback.createBackup.success": "Created a rollback backup successfully.", - "rollback.deleteBackup.failed": "Failed to delete a rollback backup!", - "rollback.deleteBackup.success": "Deleted the backup successfully.", + "rollback.createBackup.failed": "Failed to create a rollback backup", + "rollback.createBackup.success": "Created a rollback backup successfully", + "rollback.deleteBackup.failed": "Failed to delete a rollback backup", + "rollback.deleteBackup.success": "Deleted the backup successfully", "rollback.editWorld.button": "Backups & Rollback", "rollback.editWorld.recreateButton": "Re-Create World", "rollback.screen.title": "Select Backup", @@ -18,16 +18,16 @@ "rollback.screen.rollbackQuestion": "Are you sure you want to rollback to this backup?", "rollback.screen.rollbackWarning": "Any not backed up progress will be lost!", "rollback.screen.enableAutomatedQuestion": "Do you want to enable automated backups for this world?", - "rollback.narrator.selectRollback": "Selected backup %d, created: %s, day: %d", + "rollback.narrator.selectRollback": "Selected backup %d, created: %s, day: %s", "rollback.narrator.selectCurrentSave": "Current save, last played: %s", "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.command.list.noBackups": "There are no backups available for this world", + "rollback.command.unavailable": "This command is only available to the server host", "rollback.midnightconfig.title": "Rollback Options", "rollback.midnightconfig.backupsPerWorld": "Maximum Backups Per World:", "rollback.midnightconfig.backupFrequency": "Minecraft Days Per Backup:", "rollback.midnightconfig.timerMode": "Backup Timer Is Based On:", - "rollback.midnightconfig.commandAccess": "Rollback Command Access:", + "rollback.midnightconfig.commandAccess": "Rollback-Command Access:", "rollback.midnightconfig.replaceReCreateButton": "Replace Re-Create Button:", "rollback.midnightconfig.promptEnabled": "Suggest Enabling Automated Backups:", "rollback.midnightconfig.enum._TimerMode.DAYLIGHT_CYCLE": "Daylight Cycle", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 72bc54c..e053a9b 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -13,7 +13,7 @@ }, "license": "GPL-3.0", "icon": "assets/rollback/icon.png", - "environment": "*", + "environment": "client", "entrypoints": { "client": [ "ir.mehradn.rollback.Rollback"