From effabf95fdbefa7114d10e966a36770a6c843daf Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Sun, 7 Sep 2025 19:12:25 +1000 Subject: [PATCH] flashback compat --- build.gradle | 2 + .../voxy/client/VoxyClientInstance.java | 31 ++++++++++--- .../voxy/client/compat/FlashbackCompat.java | 42 +++++++++++++++++ .../voxy/client/compat/IFlashbackMeta.java | 8 ++++ .../mixin/flashback/MixinFlashbackMeta.java | 45 +++++++++++++++++++ .../flashback/MixinFlashbackRecorder.java | 29 ++++++++++++ .../world/service/VoxelIngestService.java | 2 + .../cortex/voxy/commonImpl/VoxyInstance.java | 4 ++ src/main/resources/client.voxy.mixins.json | 2 + 9 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 src/main/java/me/cortex/voxy/client/compat/FlashbackCompat.java create mode 100644 src/main/java/me/cortex/voxy/client/compat/IFlashbackMeta.java create mode 100644 src/main/java/me/cortex/voxy/client/mixin/flashback/MixinFlashbackMeta.java create mode 100644 src/main/java/me/cortex/voxy/client/mixin/flashback/MixinFlashbackRecorder.java diff --git a/build.gradle b/build.gradle index 52846060..cc25c192 100644 --- a/build.gradle +++ b/build.gradle @@ -134,6 +134,8 @@ dependencies { //modImplementation('io.github.douira:glsl-transformer:2.0.1') modCompileOnly("maven.modrinth:vivecraft:1.21.1-1.1.14-b2-fabric") + + modCompileOnly("maven.modrinth:flashback:rNCr1Rbs") } diff --git a/src/main/java/me/cortex/voxy/client/VoxyClientInstance.java b/src/main/java/me/cortex/voxy/client/VoxyClientInstance.java index c9256454..52d74226 100644 --- a/src/main/java/me/cortex/voxy/client/VoxyClientInstance.java +++ b/src/main/java/me/cortex/voxy/client/VoxyClientInstance.java @@ -1,5 +1,6 @@ package me.cortex.voxy.client; +import me.cortex.voxy.client.compat.FlashbackCompat; import me.cortex.voxy.client.config.VoxyConfig; import me.cortex.voxy.common.Logger; import me.cortex.voxy.common.config.ConfigBuildCtx; @@ -23,15 +24,17 @@ public class VoxyClientInstance extends VoxyInstance { public static boolean isInGame = false; private final SectionStorageConfig storageConfig; - private final Path basePath = getBasePath(); + private final Path basePath; + private final boolean noIngestOverride; public VoxyClientInstance() { super(VoxyConfig.CONFIG.serviceThreads); - try { - Files.createDirectories(this.basePath); - } catch (Exception e) { - throw new RuntimeException(e); + var path = FlashbackCompat.getReplayStoragePath(); + this.noIngestOverride = path != null; + if (path == null) { + path = getBasePath(); } - this.storageConfig = getCreateStorageConfig(this.basePath); + this.basePath = path; + this.storageConfig = getCreateStorageConfig(path); } @Override @@ -48,7 +51,12 @@ public class VoxyClientInstance extends VoxyInstance { return this.storageConfig.build(ctx); } - private static SectionStorageConfig getCreateStorageConfig(Path path) { + public static SectionStorageConfig getCreateStorageConfig(Path path) { + try { + Files.createDirectories(path); + } catch (Exception e) { + throw new RuntimeException(e); + } var json = path.resolve("config.json"); Config config = null; if (Files.exists(json)) { @@ -81,6 +89,15 @@ public class VoxyClientInstance extends VoxyInstance { return config.sectionStorageConfig; } + public Path getStorageBasePath() { + return this.basePath; + } + + @Override + public boolean isIngestEnabled(WorldIdentifier worldId) { + return !this.noIngestOverride; + } + private static class Config { public int version = 1; public SectionStorageConfig sectionStorageConfig; diff --git a/src/main/java/me/cortex/voxy/client/compat/FlashbackCompat.java b/src/main/java/me/cortex/voxy/client/compat/FlashbackCompat.java new file mode 100644 index 00000000..2c72e3d1 --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/compat/FlashbackCompat.java @@ -0,0 +1,42 @@ +package me.cortex.voxy.client.compat; + +import com.moulberry.flashback.Flashback; +import com.moulberry.flashback.playback.ReplayServer; +import com.moulberry.flashback.record.FlashbackMeta; +import me.cortex.voxy.common.Logger; +import me.cortex.voxy.common.config.section.SectionStorageConfig; +import net.fabricmc.loader.api.FabricLoader; +import org.apache.commons.logging.Log; + +import java.nio.file.Path; + +public class FlashbackCompat { + public static final boolean FLASHBACK_INSTALLED = FabricLoader.getInstance().isModLoaded("flashback"); + + public static Path getReplayStoragePath() { + if (!FLASHBACK_INSTALLED) { + return null; + } + return getReplayStoragePath0(); + } + + private static Path getReplayStoragePath0() { + ReplayServer replayServer = Flashback.getReplayServer(); + if (replayServer != null) { + FlashbackMeta meta = replayServer.getMetadata(); + if (meta != null) { + var path = ((IFlashbackMeta)meta).getVoxyPath(); + if (path != null) { + Logger.info("Flashback replay server exists and meta exists"); + if (path.exists()) { + Logger.info("Flashback voxy path exists in filesystem, using this as lod data source"); + return path.toPath(); + } else { + Logger.warn("Flashback meta had voxy path saved but path doesnt exist"); + } + } + } + } + return null; + } +} diff --git a/src/main/java/me/cortex/voxy/client/compat/IFlashbackMeta.java b/src/main/java/me/cortex/voxy/client/compat/IFlashbackMeta.java new file mode 100644 index 00000000..73e3e4fb --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/compat/IFlashbackMeta.java @@ -0,0 +1,8 @@ +package me.cortex.voxy.client.compat; + +import java.io.File; + +public interface IFlashbackMeta { + void setVoxyPath(File path); + File getVoxyPath(); +} diff --git a/src/main/java/me/cortex/voxy/client/mixin/flashback/MixinFlashbackMeta.java b/src/main/java/me/cortex/voxy/client/mixin/flashback/MixinFlashbackMeta.java new file mode 100644 index 00000000..7e4af4f2 --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/mixin/flashback/MixinFlashbackMeta.java @@ -0,0 +1,45 @@ +package me.cortex.voxy.client.mixin.flashback; + +import com.google.gson.JsonObject; +import com.moulberry.flashback.record.FlashbackMeta; +import me.cortex.voxy.client.compat.IFlashbackMeta; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.io.File; + +@Mixin(value = FlashbackMeta.class, remap = false) +public class MixinFlashbackMeta implements IFlashbackMeta { + @Unique private File voxyPath; + + @Override + public void setVoxyPath(File path) { + this.voxyPath = path; + } + + @Override + public File getVoxyPath() { + return this.voxyPath; + } + + @Inject(method = "toJson", at = @At("RETURN")) + private void voxy$injectSaveVoxyPath(CallbackInfoReturnable cir) { + var val = cir.getReturnValue(); + if (val != null && this.voxyPath != null) { + val.addProperty("voxy_storage_path", this.voxyPath.getAbsoluteFile().getPath()); + } + } + + @Inject(method = "fromJson", at = @At("RETURN")) + private static void voxy$injectGetVoxyPath(JsonObject meta, CallbackInfoReturnable cir) { + var val = cir.getReturnValue(); + if (val != null && meta != null) { + if (meta.has("voxy_storage_path")) { + ((IFlashbackMeta)val).setVoxyPath(new File(meta.get("voxy_storage_path").getAsString())); + } + } + } +} diff --git a/src/main/java/me/cortex/voxy/client/mixin/flashback/MixinFlashbackRecorder.java b/src/main/java/me/cortex/voxy/client/mixin/flashback/MixinFlashbackRecorder.java new file mode 100644 index 00000000..56f98724 --- /dev/null +++ b/src/main/java/me/cortex/voxy/client/mixin/flashback/MixinFlashbackRecorder.java @@ -0,0 +1,29 @@ +package me.cortex.voxy.client.mixin.flashback; + +import com.moulberry.flashback.record.FlashbackMeta; +import com.moulberry.flashback.record.Recorder; +import me.cortex.voxy.client.VoxyClientInstance; +import me.cortex.voxy.client.compat.IFlashbackMeta; +import me.cortex.voxy.commonImpl.VoxyCommon; +import net.minecraft.registry.DynamicRegistryManager; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = Recorder.class, remap = false) +public class MixinFlashbackRecorder { + @Shadow @Final private FlashbackMeta metadata; + + @Inject(method = "", at = @At("TAIL")) + private void voxy$getStoragePath(DynamicRegistryManager registryAccess, CallbackInfo retInf) { + if (VoxyCommon.isAvailable()) { + var instance = VoxyCommon.getInstance(); + if (instance instanceof VoxyClientInstance ci) { + ((IFlashbackMeta)this.metadata).setVoxyPath(ci.getStorageBasePath().toFile()); + } + } + } +} diff --git a/src/main/java/me/cortex/voxy/common/world/service/VoxelIngestService.java b/src/main/java/me/cortex/voxy/common/world/service/VoxelIngestService.java index d21671f8..618e34da 100644 --- a/src/main/java/me/cortex/voxy/common/world/service/VoxelIngestService.java +++ b/src/main/java/me/cortex/voxy/common/world/service/VoxelIngestService.java @@ -177,6 +177,7 @@ public class VoxelIngestService { if (worldId == null) return false; var instance = VoxyCommon.getInstance(); if (instance == null) return false; + if (!instance.isIngestEnabled(worldId)) return false; var engine = instance.getOrCreate(worldId); if (engine == null) return false; instance.getIngestService().enqueueIngest(engine, chunk); @@ -202,6 +203,7 @@ public class VoxelIngestService { public static boolean rawIngest(WorldEngine engine, ChunkSection section, int x, int y, int z, ChunkNibbleArray bl, ChunkNibbleArray sl) { if (!shouldIngestSection(section, x, y, z)) return false; if (engine.instanceIn == null) return false; + if (!engine.instanceIn.isIngestEnabled(null)) return false;//TODO: dont pass in null return engine.instanceIn.getIngestService().rawIngest0(engine, section, x, y, z, bl, sl); } } diff --git a/src/main/java/me/cortex/voxy/commonImpl/VoxyInstance.java b/src/main/java/me/cortex/voxy/commonImpl/VoxyInstance.java index 87223e5c..b8fed1b3 100644 --- a/src/main/java/me/cortex/voxy/commonImpl/VoxyInstance.java +++ b/src/main/java/me/cortex/voxy/commonImpl/VoxyInstance.java @@ -243,4 +243,8 @@ public abstract class VoxyInstance { Logger.info("Instance shutdown"); this.activeWorldLock.unlockWrite(stamp); } + + public boolean isIngestEnabled(WorldIdentifier worldId) { + return true; + } } \ No newline at end of file diff --git a/src/main/resources/client.voxy.mixins.json b/src/main/resources/client.voxy.mixins.json index 796d8818..f9c9fe92 100644 --- a/src/main/resources/client.voxy.mixins.json +++ b/src/main/resources/client.voxy.mixins.json @@ -3,6 +3,8 @@ "package": "me.cortex.voxy.client.mixin", "compatibilityLevel": "JAVA_17", "client": [ + "flashback.MixinFlashbackMeta", + "flashback.MixinFlashbackRecorder", "iris.MixinWorldRenderer", "iris.MixinPackRenderTargetDirectives", "iris.CustomUniformsAccessor",