Skip to content

Commit

Permalink
Resolve pcal43#261 autoback (backup after autosaves) is not currently…
Browse files Browse the repository at this point in the history
… supported on Forge

Mixins are used in much the same way they are in the fabric version.
  • Loading branch information
stewi1014 committed Nov 19, 2024
1 parent 98f9e92 commit fcb3633
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import net.minecraft.world.level.storage.LevelResource;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.level.LevelEvent;
import net.neoforged.neoforge.event.server.ServerStartedEvent;
import net.neoforged.neoforge.event.server.ServerStoppingEvent;
import net.neoforged.bus.api.IEventBus;
Expand All @@ -35,13 +36,13 @@
* @author pcal
* @since 0.16.0
*/
class ForgeCommonProvider implements MinecraftProvider {
class ForgeCommonProvider implements MinecraftProvider, MixinGateway {

static final String MOD_ID = "fastback";
private MinecraftServer logicalServer;
private LifecycleListener lifecycleListener = null;
private Runnable autoSaveListener;
private boolean isWorldSaveEnabled;
private boolean isWorldSaveEnabled = true;

ForgeCommonProvider() {
final IEventBus modEventBus = ModLoadingContext.get().getActiveContainer().getEventBus();
Expand Down Expand Up @@ -76,15 +77,6 @@ private void onRegisterCommandEvent(RegisterCommandsEvent event) {
commandDispatcher.register(backupCommand);
}

/**
TODO This one isn't it. We need to hear about it when an autosaves (and only autosaves) are completed.
Might have to delve into Forge mixins to do this.
private void onLevelSaveEvent(LevelEvent.Save event) {
provider.onAutoSaveComplete();
}
**/


// ======================================================================
// Protected

Expand All @@ -105,6 +97,7 @@ void onInitialize() {
syslog().warn("Please note that this is an alpha release. A list of known issues is available here:");
syslog().warn("https://github.com/pcal43/fastback/issues?q=is%3Aissue+is%3Aopen+label%3Aforge");
syslog().warn("------------------------------------------------------------------------------------");
MixinGateway.Singleton.register(this);
}


Expand Down Expand Up @@ -136,25 +129,32 @@ public String getModVersion() {
return "0.15.3+1.20.1-alpha"; //FIXME
}

//FIXME!!
void onAutoSaveComplete() {
syslog().debug("onAutoSaveComplete");
@Override
public void autoSaveCompleted() {
syslog().debug("autoSaveCompleted");
this.autoSaveListener.run();
}

@Override
public Path getWorldDirectory() {
if (this.logicalServer == null) throw new IllegalStateException("minecraftServer is null");
if (logicalServer == null) throw new IllegalStateException("minecraftServer is null");
return logicalServer.getWorldPath(LevelResource.ROOT).toAbsolutePath().normalize();
}

@Override
public void setWorldSaveEnabled(boolean enabled) {
isWorldSaveEnabled = enabled;
if (logicalServer == null) throw new IllegalStateException("minecraftServer is null");
for (ServerLevel world : logicalServer.getAllLevels()) {
world.noSave = !enabled;
}
}

@Override
public boolean isWorldSaveEnabled() {
return isWorldSaveEnabled;
}

@Override
public void saveWorld() {
if (this.logicalServer == null) throw new IllegalStateException();
Expand Down Expand Up @@ -216,5 +216,4 @@ public Collection<Path> getModsBackupPaths() {
**/
return out;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* FastBack - Fast, incremental Minecraft backups powered by Git.
* Copyright (C) 2022 pcal.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/

package net.pcal.fastback.mod.neoforge;

/**
* Singleton 'gateway' that mixin code goes through to call back into the mod.
*
* @author pcal
* @since 0.13.1
*/
public interface MixinGateway {

static MixinGateway get() {
return Singleton.INSTANCE;
}

boolean isWorldSaveEnabled();

void autoSaveCompleted();

class Singleton {
private static MixinGateway INSTANCE = null;

public static void register(MixinGateway gateway) {
Singleton.INSTANCE = gateway;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* FastBack - Fast, incremental Minecraft backups powered by Git.
* Copyright (C) 2022 pcal.net
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; If not, see <http://www.gnu.org/licenses/>.
*/
package net.pcal.fastback.mod.neoforge.mixins;

import net.minecraft.server.MinecraftServer;
import net.pcal.fastback.mod.neoforge.MixinGateway;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

import static net.pcal.fastback.logging.SystemLogger.syslog;

/**
* Allows us to disable vanilla saving during 'git add' to avoid coherency problems in the backup snapshots. Also
* sends notifications when autosaving completes so we can follow them with automated backups.
*
* @author pcal
* @since 0.0.1
*/
@Mixin(MinecraftServer.class)
public class MinecraftServerMixin {

/**
* Intercept the call to saveAll that triggers on autosave, pass it through and then send out notification that
* the autosave is done.
*/
@Redirect(method = "autoSave()V",
at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;saveEverything(ZZZ)Z"))
public boolean fastback_saveAll(MinecraftServer instance, boolean suppressLogs, boolean flush, boolean force) {
boolean result = instance.saveEverything(suppressLogs, flush, force);
MixinGateway.get().autoSaveCompleted();
return result;
}

/**
* Intercept save so we can hard-disable saving during critical parts of the backup.
*/
@Inject(at = @At("HEAD"), method = "saveAllChunks(ZZZ)Z", cancellable = true)
public void fastback_save(boolean suppressLogs, boolean flush, boolean force, CallbackInfoReturnable<Boolean> ci) {
synchronized (this) {
if (MixinGateway.get().isWorldSaveEnabled()) {
syslog().debug("world saves are enabled, doing requested save");
} else {
syslog().warn("Skipping requested save because a backup is in progress.");
ci.setReturnValue(false);
ci.cancel();
}
}
}

/**
* Intercept saveAll so we can hard-disable saving during critical parts of the backup.
*/
@Inject(at = @At("HEAD"), method = "saveEverything(ZZZ)Z", cancellable = true)
public void fastback_saveAll(boolean suppressLogs, boolean flush, boolean force, CallbackInfoReturnable<Boolean> ci) {
synchronized (this) {
if (MixinGateway.get().isWorldSaveEnabled()) {
syslog().debug("world saves are enabled, doing requested saveAll");
//TODO should call save here to ensure all synced?
} else {
syslog().warn("Skipping requested saveAll because a backup is in progress.");
ci.setReturnValue(false);
ci.cancel();
}
}
}
}
3 changes: 3 additions & 0 deletions neoforge/src/main/resources/META-INF/neoforge.mods.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ mandatory = true
versionRange = "1.21.3"
ordering = "NONE"
side = "CLIENT"

[[mixins]]
config="fastback.mixins.json"
12 changes: 12 additions & 0 deletions neoforge/src/main/resources/fastback.mixins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"required": true,
"minVersion": "0.8",
"package": "net.pcal.fastback.mod.neoforge.mixins",
"compatibilityLevel": "JAVA_16",
"mixins": [
"MinecraftServerMixin"
],
"injectors": {
"defaultRequire": 1
}
}

0 comments on commit fcb3633

Please sign in to comment.