diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b01da52..542101f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,14 +12,12 @@ jobs: matrix: # Use these Java versions java: [ - 21, # Current Java LTS + 25, # Current Java LTS ] - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - name: checkout repository uses: actions/checkout@v4 - - name: validate gradle wrapper - uses: gradle/wrapper-validation-action@v2 - name: setup jdk ${{ matrix.java }} uses: actions/setup-java@v4 with: @@ -30,8 +28,8 @@ jobs: - name: build run: ./gradlew build - name: capture build artifacts - if: ${{ matrix.java == '21' }} # Only upload artifacts built from latest java - uses: actions/upload-artifact@v4 + if: ${{ matrix.java == '25' }} # Only upload artifacts built from latest java + uses: actions/upload-artifact@v7 with: name: Artifacts path: build/libs/ \ No newline at end of file diff --git a/build.gradle b/build.gradle index b584d10..041d705 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version "${loom_version}" + id 'net.fabricmc.fabric-loom' version "${loom_version}" id 'maven-publish' id "io.github.p03w.machete" version "2.0.1" } @@ -20,17 +20,18 @@ repositories { dependencies { // To change the versions see the gradle.properties file minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + implementation "net.fabricmc:fabric-loader:${project.loader_version}" // Fabric API - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" + implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" // ModMenu - modImplementation "com.terraformersmc:modmenu:${project.modmenu_version}" + implementation("com.terraformersmc:modmenu:${project.modmenu_version}"){ + exclude(group: "eu.pb4") + } // Cloth Config - modImplementation("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}") { + implementation("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_config_version}") { exclude(group: "net.fabricmc.fabric-api") } } @@ -44,14 +45,14 @@ processResources { } tasks.withType(JavaCompile).configureEach { - it.options.release = 21 + it.options.release = 25 } java { withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } jar { diff --git a/gradle.properties b/gradle.properties index 198da96..447de71 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,18 +7,17 @@ org.gradle.configuration-cache=false # Fabric Properties # check these on https://fabricmc.net/develop -minecraft_version=1.21.11 -yarn_mappings=1.21.11+build.3 -loader_version=0.18.3 -loom_version=1.14-SNAPSHOT +minecraft_version=26.1 +loader_version=0.18.5 +loom_version=1.15-SNAPSHOT # Mod Properties mod_version=3.1.3 -target_version=1.21.11 +target_version=26.1 maven_group=me.contaria archives_base_name=fastquit # Dependencies -fabric_api_version=0.140.0+1.21.11 -modmenu_version=17.0.0-alpha.1 -cloth_config_version=21.11.151 +fabric_api_version=0.144.1+26.1 +modmenu_version=18.0.0-alpha.7 +cloth_config_version=26.1.154 diff --git a/src/main/java/me/contaria/fastquit/CatalogueIntegration.java b/src/main/java/me/contaria/fastquit/CatalogueIntegration.java index 49cbf91..8419550 100644 --- a/src/main/java/me/contaria/fastquit/CatalogueIntegration.java +++ b/src/main/java/me/contaria/fastquit/CatalogueIntegration.java @@ -1,7 +1,7 @@ package me.contaria.fastquit; import net.fabricmc.loader.api.ModContainer; -import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screens.Screen; /** * Provides support for configuring options through Catalogue. diff --git a/src/main/java/me/contaria/fastquit/FastQuit.java b/src/main/java/me/contaria/fastquit/FastQuit.java index 797fa06..5908b52 100644 --- a/src/main/java/me/contaria/fastquit/FastQuit.java +++ b/src/main/java/me/contaria/fastquit/FastQuit.java @@ -1,6 +1,6 @@ package me.contaria.fastquit; -import me.contaria.fastquit.mixin.MinecraftClientAccessor; +import me.contaria.fastquit.mixin.MinecraftAccessor; import me.contaria.fastquit.mixin.MinecraftServerAccessor; import me.contaria.fastquit.mixin.LevelStorageSessionAccessor; import com.mojang.logging.LogUtils; @@ -9,11 +9,11 @@ import net.fabricmc.api.ClientModInitializer; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.metadata.ModMetadata; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.server.integrated.IntegratedServer; -import net.minecraft.text.Text; -import net.minecraft.world.level.storage.LevelStorage; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.server.IntegratedServer; +import net.minecraft.network.chat.Component; +import net.minecraft.world.level.storage.LevelStorageSource; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -36,9 +36,9 @@ public final class FastQuit implements ClientModInitializer { public static final Map savingWorlds = Collections.synchronizedMap(new HashMap<>()); /** - * Stores {@link LevelStorage.Session}'s used by FastQuit as to only close them if no other process is currently using them. + * Stores {@link LevelStorageSource.LevelStorageAccess}'s used by FastQuit as to only close them if no other process is currently using them. */ - public static final List occupiedSessions = Collections.synchronizedList(new ArrayList<>()); + public static final List occupiedSessions = Collections.synchronizedList(new ArrayList<>()); @Override public void onInitializeClient() { @@ -79,9 +79,9 @@ public static void exit() { error("Something went horribly wrong when exiting FastQuit!", throwable); savingWorlds.forEach((server, info) -> { try { - server.getThread().join(); + server.getRunningThread().join(); } catch (Throwable throwable2) { - error("Failed to wait for \"" + server.getSaveProperties().getLevelName() + "\"", throwable2); + error("Failed to wait for \"" + server.getWorldData().getLevelName() + "\"", throwable2); } }); } @@ -119,10 +119,10 @@ public static void wait(Collection servers, @Nullable Callback return; } - MinecraftClient client = MinecraftClient.getInstance(); + Minecraft client = Minecraft.getInstance(); - if (!client.isOnThread()) { - if (servers.stream().anyMatch(server -> Thread.currentThread() == server.getThread())) { + if (!client.isSameThread()) { + if (servers.stream().anyMatch(server -> Thread.currentThread() == server.getRunningThread())) { throw new IllegalStateException("Tried to call FastQuit.wait(...) from one of the servers it's supposed to wait for."); } @@ -130,32 +130,32 @@ public static void wait(Collection servers, @Nullable Callback return; } - Screen oldScreen = client.currentScreen; + Screen oldScreen = client.screen; - Text stillSaving = TextHelper.translatable("fastquit.screen.waiting", String.join("\" & \"", servers.stream().map(server -> server.getSaveProperties().getLevelName()).toList())); + Component stillSaving = TextHelper.translatable("fastquit.screen.waiting", String.join("\" & \"", servers.stream().map(server -> server.getWorldData().getLevelName()).toList())); log(stillSaving.getString()); - servers.forEach(server -> server.getThread().setPriority(Thread.NORM_PRIORITY)); + servers.forEach(server -> server.getRunningThread().setPriority(Thread.NORM_PRIORITY)); try { client.setScreen(new WaitingScreen(stillSaving, cancellable)); - while (servers.stream().anyMatch(server -> !server.isStopping())) { + while (servers.stream().anyMatch(server -> !server.isShutdown())) { if (cancellable != null && cancellable.isCancelled()) { if (CONFIG.backgroundPriority != 0) { - servers.forEach(server -> server.getThread().setPriority(CONFIG.backgroundPriority)); + servers.forEach(server -> server.getRunningThread().setPriority(CONFIG.backgroundPriority)); } log("Cancelled waiting for currently saving worlds."); break; } - ((MinecraftClientAccessor) client).fastquit$render(false); + ((MinecraftAccessor) client).fastquit$runTick(false); } } finally { // compatibility with "WorldGen" mod if (oldScreen != null && oldScreen.getClass().getName().equals("caeruleusTait.WorldGen.gui.screens.WGConfigScreen")) { - client.currentScreen = oldScreen; + client.screen = oldScreen; } else { - client.setScreenAndRender(oldScreen); + client.setScreenAndShow(oldScreen); } } } @@ -165,25 +165,25 @@ public static void wait(Collection servers, @Nullable Callback */ public static Optional getSavingWorld(Path path) { // noinspection resource - return savingWorlds.keySet().stream().filter(server -> ((LevelStorageSessionAccessor) ((MinecraftServerAccessor) server).fastquit$getSession()).fastquit$getDirectory().path().equals(path)).findFirst(); + return savingWorlds.keySet().stream().filter(server -> ((LevelStorageSessionAccessor) ((MinecraftServerAccessor) server).fastquit$getStorageSource()).fastquit$getLevelDirectory().path().equals(path)).findFirst(); } /** - * @return optionally returns the currently saving {@link IntegratedServer} matching the given {@link LevelStorage.Session} + * @return optionally returns the currently saving {@link IntegratedServer} matching the given {@link LevelStorageSource.LevelStorageAccess} */ - public static Optional getSavingWorld(LevelStorage.Session session) { + public static Optional getSavingWorld(LevelStorageSource.LevelStorageAccess session) { // noinspection resource - return savingWorlds.keySet().stream().filter(server -> ((MinecraftServerAccessor) server).fastquit$getSession() == session).findFirst(); + return savingWorlds.keySet().stream().filter(server -> ((MinecraftServerAccessor) server).fastquit$getStorageSource() == session).findFirst(); } /** - * @apiNote Remember to {@link LevelStorage.Session#close() close} the session after using it! - * @return optionally returns the {@link LevelStorage.Session} of the currently saving {@link IntegratedServer} matching the given {@link Path} + * @apiNote Remember to {@link LevelStorageSource.LevelStorageAccess#close() close} the session after using it! + * @return optionally returns the {@link LevelStorageSource.LevelStorageAccess} of the currently saving {@link IntegratedServer} matching the given {@link Path} */ - public static Optional getSession(Path path) { + public static Optional getSession(Path path) { return getSavingWorld(path).flatMap(server -> { - LevelStorage.Session session; - synchronized (session = ((MinecraftServerAccessor) server).fastquit$getSession()) { + LevelStorageSource.LevelStorageAccess session; + synchronized (session = ((MinecraftServerAccessor) server).fastquit$getStorageSource()) { // noinspection resource if (((LevelStorageSessionAccessor) session).fastquit$getLock().isValid()) { occupiedSessions.add(session); diff --git a/src/main/java/me/contaria/fastquit/FastQuitConfig.java b/src/main/java/me/contaria/fastquit/FastQuitConfig.java index 0bf18f9..e365a8d 100644 --- a/src/main/java/me/contaria/fastquit/FastQuitConfig.java +++ b/src/main/java/me/contaria/fastquit/FastQuitConfig.java @@ -11,9 +11,9 @@ import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.metadata.ModMetadata; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.server.integrated.IntegratedServer; -import net.minecraft.util.Formatting; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.server.IntegratedServer; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -160,7 +160,7 @@ public Screen createConfigScreen(Screen parent) { } else { modCompatCategory.addEntry(entryBuilder.startEnumSelector(TextHelper.translatable("text.autoconfig.fastquit.option.allowMultipleServers"), ModCompat.class, ModCompat.DISABLED) .setTooltip(TextHelper.translatable("text.autoconfig.fastquit.option.allowMultipleServers.@Tooltip").append("\n\n").append(TextHelper.translatable("fastquit.config.compat.allowMultipleServers.disabledForCompat", String.join(", ", MODS_THAT_CONFLICT_WITH_MULTIPLE_SERVERS)))) - .setEnumNameProvider(disabled -> TextHelper.translatable("manageServer.resourcePack.disabled").styled(style -> style.withColor(Formatting.RED))) + .setEnumNameProvider(disabled -> TextHelper.translatable("manageServer.resourcePack.disabled").withStyle(style -> style.withColor(ChatFormatting.RED))) .build() ); } diff --git a/src/main/java/me/contaria/fastquit/TextHelper.java b/src/main/java/me/contaria/fastquit/TextHelper.java index 351aa93..26bae66 100644 --- a/src/main/java/me/contaria/fastquit/TextHelper.java +++ b/src/main/java/me/contaria/fastquit/TextHelper.java @@ -1,22 +1,22 @@ package me.contaria.fastquit; -import net.minecraft.screen.ScreenTexts; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; /** * Utility class for ease of porting to older Minecraft versions. */ public final class TextHelper { - public static final Text OFF = ScreenTexts.OFF; - public static final Text BACK = ScreenTexts.BACK; + public static final Component OFF = CommonComponents.OPTION_OFF; + public static final Component BACK = CommonComponents.GUI_BACK; - public static MutableText translatable(String key, Object... args) { - return Text.translatable(key, args); + public static MutableComponent translatable(String key, Object... args) { + return Component.translatable(key, args); } - public static MutableText literal(String string) { - return Text.literal(string); + public static MutableComponent literal(String string) { + return Component.literal(string); } } \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/WaitingScreen.java b/src/main/java/me/contaria/fastquit/WaitingScreen.java index 5d18039..6c96a38 100644 --- a/src/main/java/me/contaria/fastquit/WaitingScreen.java +++ b/src/main/java/me/contaria/fastquit/WaitingScreen.java @@ -1,16 +1,16 @@ package me.contaria.fastquit; -import net.minecraft.client.gui.screen.MessageScreen; -import net.minecraft.client.gui.widget.ButtonWidget; -import net.minecraft.text.Text; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.GenericMessageScreen; +import net.minecraft.network.chat.Component; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -public class WaitingScreen extends MessageScreen { +public class WaitingScreen extends GenericMessageScreen { private final CallbackInfo callbackInfo; - public WaitingScreen(Text text, @Nullable CallbackInfo callbackInfo) { + public WaitingScreen(Component text, @Nullable CallbackInfo callbackInfo) { super(text); if (callbackInfo != null && !callbackInfo.isCancellable()) { FastQuit.warn("Provided CallbackInfo for \"" + callbackInfo.getId() + "\" is not cancellable!"); @@ -23,7 +23,7 @@ public WaitingScreen(Text text, @Nullable CallbackInfo callbackInfo) { public void init() { super.init(); if (this.callbackInfo != null) { - this.addDrawableChild(ButtonWidget.builder(TextHelper.BACK, button -> this.close()).dimensions(this.width - 100 - 5, this.height - 20 - 5, 100, 20).build()); + this.addRenderableWidget(Button.builder(TextHelper.BACK, button -> this.onClose()).bounds(this.width - 100 - 5, this.height - 20 - 5, 100, 20).build()); } } @@ -33,8 +33,8 @@ public boolean shouldCloseOnEsc() { } @Override - public void close() { - super.close(); + public void onClose() { + super.onClose(); if (this.callbackInfo != null) { this.callbackInfo.cancel(); } diff --git a/src/main/java/me/contaria/fastquit/mixin/EditWorldScreenMixin.java b/src/main/java/me/contaria/fastquit/mixin/EditWorldScreenMixin.java index 536bf0b..15ed6d9 100644 --- a/src/main/java/me/contaria/fastquit/mixin/EditWorldScreenMixin.java +++ b/src/main/java/me/contaria/fastquit/mixin/EditWorldScreenMixin.java @@ -1,8 +1,8 @@ package me.contaria.fastquit.mixin; import me.contaria.fastquit.FastQuit; -import net.minecraft.client.gui.screen.world.EditWorldScreen; -import net.minecraft.world.level.storage.LevelStorage; +import net.minecraft.client.gui.screens.worldselection.EditWorldScreen; +import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -15,14 +15,14 @@ public abstract class EditWorldScreenMixin { @Shadow @Final - private LevelStorage.Session storageSession; + private LevelStorageSource.LevelStorageAccess levelAccess; // method_54595 - Optimize World // method_54596 - Make Backup @Inject( method = { - "method_54595", - "method_54596" + "lambda$new$12", + "lambda$new$7" }, at = @At("HEAD"), require = 2, @@ -30,6 +30,6 @@ public abstract class EditWorldScreenMixin { cancellable = true ) private void waitForSaveOnBackupOrOptimizeWorld_cancellable(CallbackInfo ci) { - FastQuit.getSavingWorld(this.storageSession).ifPresent(server -> FastQuit.wait(server, ci)); + FastQuit.getSavingWorld(this.levelAccess).ifPresent(server -> FastQuit.wait(server, ci)); } } \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/LevelInfoAccessor.java b/src/main/java/me/contaria/fastquit/mixin/LevelInfoAccessor.java deleted file mode 100644 index 2a5357f..0000000 --- a/src/main/java/me/contaria/fastquit/mixin/LevelInfoAccessor.java +++ /dev/null @@ -1,13 +0,0 @@ -package me.contaria.fastquit.mixin; - -import net.minecraft.world.level.LevelInfo; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(LevelInfo.class) -public interface LevelInfoAccessor { - @Mutable - @Accessor("name") - void fastquit$setName(String name); -} \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/LevelPropertiesAccessor.java b/src/main/java/me/contaria/fastquit/mixin/LevelPropertiesAccessor.java deleted file mode 100644 index 83af3ca..0000000 --- a/src/main/java/me/contaria/fastquit/mixin/LevelPropertiesAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package me.contaria.fastquit.mixin; - -import net.minecraft.world.level.LevelInfo; -import net.minecraft.world.level.LevelProperties; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(LevelProperties.class) -public interface LevelPropertiesAccessor { - @Accessor("levelInfo") - LevelInfo fastquit$getLevelInfo(); -} \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/LevelSettingsAccessor.java b/src/main/java/me/contaria/fastquit/mixin/LevelSettingsAccessor.java new file mode 100644 index 0000000..01a363a --- /dev/null +++ b/src/main/java/me/contaria/fastquit/mixin/LevelSettingsAccessor.java @@ -0,0 +1,13 @@ +package me.contaria.fastquit.mixin; + +import net.minecraft.world.level.LevelSettings; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(LevelSettings.class) +public interface LevelSettingsAccessor { + @Mutable + @Accessor("levelName") + void fastquit$setLevelName(String name); +} \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/LevelStorageSessionMixin.java b/src/main/java/me/contaria/fastquit/mixin/LevelStorageAccessMixin.java similarity index 55% rename from src/main/java/me/contaria/fastquit/mixin/LevelStorageSessionMixin.java rename to src/main/java/me/contaria/fastquit/mixin/LevelStorageAccessMixin.java index e0aa980..e3f0c98 100644 --- a/src/main/java/me/contaria/fastquit/mixin/LevelStorageSessionMixin.java +++ b/src/main/java/me/contaria/fastquit/mixin/LevelStorageAccessMixin.java @@ -4,14 +4,14 @@ import me.contaria.fastquit.plugin.Synchronized; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; import com.mojang.serialization.Dynamic; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.registry.DynamicRegistryManager; -import net.minecraft.server.integrated.IntegratedServer; -import net.minecraft.world.PlayerSaveHandler; -import net.minecraft.world.SaveProperties; -import net.minecraft.world.level.storage.LevelStorage; +import net.minecraft.client.server.IntegratedServer; +import net.minecraft.core.RegistryAccess; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.util.DirectoryLock; +import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelSummary; -import net.minecraft.world.level.storage.SessionLock; +import net.minecraft.world.level.storage.PlayerDataStorage; +import net.minecraft.world.level.storage.WorldData; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -24,50 +24,51 @@ import java.io.IOException; import java.util.Optional; +import java.util.UUID; import java.util.function.Consumer; -@Mixin(LevelStorage.Session.class) -public abstract class LevelStorageSessionMixin { +@Mixin(LevelStorageSource.LevelStorageAccess.class) +public abstract class LevelStorageAccessMixin { @Shadow @Final - private String directoryName; + private String levelId; @Synchronized @Shadow - public abstract PlayerSaveHandler createSaveHandler(); + public abstract PlayerDataStorage createPlayerStorage(); @Synchronized @Shadow - public abstract @Nullable LevelSummary getLevelSummary(Dynamic dynamic); + public abstract @Nullable LevelSummary fixAndGetSummaryFromTag(Dynamic dynamic); @Synchronized @Shadow - protected abstract @Nullable Dynamic readLevelProperties(boolean old); + public abstract @Nullable Dynamic getUnfixedDataTag(boolean old); @Synchronized @Shadow - public abstract void backupLevelDataFile(DynamicRegistryManager registryManager, SaveProperties saveProperties, @Nullable NbtCompound nbt); + public abstract void saveDataTag(WorldData saveProperties, @Nullable UUID nbt); @Synchronized @Shadow - protected abstract void save(NbtCompound compound) throws IOException; + protected abstract void saveLevelData(CompoundTag compound) throws IOException; @Synchronized @Shadow - public abstract long createBackup() throws IOException; + public abstract long makeWorldBackup() throws IOException; @Synchronized @Shadow - public abstract void deleteSessionLock() throws IOException; + public abstract void deleteLevel() throws IOException; @Synchronized @Shadow - protected abstract void save(Consumer nbtProcessor) throws IOException; + protected abstract void modifyLevelDataWithoutDatafix(Consumer nbtProcessor) throws IOException; @Synchronized @Shadow - public abstract boolean tryRestoreBackup(); + public abstract boolean restoreLevelDataFromOld(); @Synchronized @Shadow @@ -75,7 +76,7 @@ public abstract class LevelStorageSessionMixin { // this now acts as a fallback in case the method gets called from somewhere else than EditWorldScreen @Inject( - method = "createBackup", + method = "makeWorldBackup", at = @At("HEAD") ) private void fastquit$waitForSaveOnBackup(CallbackInfoReturnable cir) { @@ -83,15 +84,15 @@ public abstract class LevelStorageSessionMixin { } @Inject( - method = "save(Ljava/lang/String;)V", + method = "renameLevel(Ljava/lang/String;)V", at = @At("TAIL") ) private void fastquit$editSavingWorldName(String name, CallbackInfo ci) { - this.getSavingWorld().ifPresent(server -> ((LevelInfoAccessor) (Object) ((LevelPropertiesAccessor) server.getSaveProperties()).fastquit$getLevelInfo()).fastquit$setName(name)); + this.getSavingWorld().ifPresent(server -> ((LevelSettingsAccessor) (Object) ((PrimaryLevelDataAccessor) server.getWorldData()).fastquit$getSettings()).fastquit$setLevelName(name)); } @Inject( - method = "deleteSessionLock", + method = "deleteLevel", at = @At("TAIL") ) private void fastquit$deleteSavingWorld(CallbackInfo ci) { @@ -102,22 +103,22 @@ public abstract class LevelStorageSessionMixin { method = "close", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/storage/SessionLock;close()V" + target = "Lnet/minecraft/util/DirectoryLock;close()V" ) ) - private boolean fastquit$checkSessionClose(SessionLock lock) { - return !FastQuit.occupiedSessions.remove((LevelStorage.Session) (Object) this); + private boolean fastquit$checkSessionClose(DirectoryLock lock) { + return !FastQuit.occupiedSessions.remove((LevelStorageSource.LevelStorageAccess) (Object) this); } @Inject( - method = "checkValid", + method = "checkLock", at = @At("HEAD") ) private void fastquit$warnIfUnSynchronizedSessionAccess(CallbackInfo ci) { if (!Thread.holdsLock(this)) { this.getSavingWorld().ifPresent(server -> { - FastQuit.warn("Un-synchronized access to \"" + this.directoryName + "\" session!"); - if (!server.isOnThread()) { + FastQuit.warn("Un-synchronized access to \"" + this.levelId + "\" session!"); + if (!server.isSameThread()) { FastQuit.wait(server); } }); @@ -126,6 +127,6 @@ public abstract class LevelStorageSessionMixin { @Unique private Optional getSavingWorld() { - return FastQuit.getSavingWorld((LevelStorage.Session) (Object) this); + return FastQuit.getSavingWorld((LevelStorageSource.LevelStorageAccess) (Object) this); } } \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/LevelStorageSessionAccessor.java b/src/main/java/me/contaria/fastquit/mixin/LevelStorageSessionAccessor.java index 39d98c6..d7b7c44 100644 --- a/src/main/java/me/contaria/fastquit/mixin/LevelStorageSessionAccessor.java +++ b/src/main/java/me/contaria/fastquit/mixin/LevelStorageSessionAccessor.java @@ -1,15 +1,15 @@ package me.contaria.fastquit.mixin; -import net.minecraft.world.level.storage.LevelStorage; -import net.minecraft.world.level.storage.SessionLock; +import net.minecraft.util.DirectoryLock; +import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; -@Mixin(LevelStorage.Session.class) +@Mixin(LevelStorageSource.LevelStorageAccess.class) public interface LevelStorageSessionAccessor { @Accessor("lock") - SessionLock fastquit$getLock(); + DirectoryLock fastquit$getLock(); - @Accessor("directory") - LevelStorage.LevelSave fastquit$getDirectory(); + @Accessor("levelDirectory") + LevelStorageSource.LevelDirectory fastquit$getLevelDirectory(); } \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/LevelStorageMixin.java b/src/main/java/me/contaria/fastquit/mixin/LevelStorageSourceMixin.java similarity index 73% rename from src/main/java/me/contaria/fastquit/mixin/LevelStorageMixin.java rename to src/main/java/me/contaria/fastquit/mixin/LevelStorageSourceMixin.java index 8dfe3a7..0dbfc8f 100644 --- a/src/main/java/me/contaria/fastquit/mixin/LevelStorageMixin.java +++ b/src/main/java/me/contaria/fastquit/mixin/LevelStorageSourceMixin.java @@ -1,7 +1,7 @@ package me.contaria.fastquit.mixin; import me.contaria.fastquit.FastQuit; -import net.minecraft.world.level.storage.LevelStorage; +import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelSummary; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -12,22 +12,22 @@ import java.nio.file.Path; -@Mixin(LevelStorage.class) -public abstract class LevelStorageMixin { +@Mixin(LevelStorageSource.class) +public abstract class LevelStorageSourceMixin { @Shadow @Final - private Path savesDirectory; + private Path baseDir; @Inject( - method = "createSession", + method = "validateAndCreateAccess", at = @At("HEAD") ) - private void fastquit$waitForSaveOnSessionCreation(String levelName, CallbackInfoReturnable cir) { + private void fastquit$waitForSaveOnSessionCreation(String levelName, CallbackInfoReturnable cir) { if (!FastQuit.CONFIG.allowMultipleServers()) { FastQuit.wait(FastQuit.savingWorlds.keySet()); } - FastQuit.getSavingWorld(this.savesDirectory.resolve(levelName)).ifPresent(FastQuit::wait); + FastQuit.getSavingWorld(this.baseDir.resolve(levelName)).ifPresent(FastQuit::wait); if (!FastQuit.savingWorlds.isEmpty()) { FastQuit.warn(String.join(" ", "FastQuit is allowing a world to load while another is currently being saved, which may cause problems with mod compatibility.", @@ -38,7 +38,7 @@ public abstract class LevelStorageMixin { // method_43418 - lambda in loadSummaries @Inject( - method = "method_43418", + method = "lambda$loadLevelSummaries$0", at = @At( value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V" @@ -46,10 +46,10 @@ public abstract class LevelStorageMixin { cancellable = true, remap = false ) - private void fastquit$addCurrentlySavingLevelsToWorldList(LevelStorage.LevelSave levelSave, CallbackInfoReturnable cir) { + private void fastquit$addCurrentlySavingLevelsToWorldList(LevelStorageSource.LevelDirectory levelSave, CallbackInfoReturnable cir) { FastQuit.getSession(levelSave.path()).ifPresent(session -> { try (session) { - cir.setReturnValue(session.getLevelSummary(session.readLevelProperties())); + cir.setReturnValue(session.fixAndGetSummaryFromTag(session.getUnfixedDataTagWithFallback())); } catch (Exception e) { FastQuit.error("Failed to load level summary from saving server!", e); } diff --git a/src/main/java/me/contaria/fastquit/mixin/MinecraftAccessor.java b/src/main/java/me/contaria/fastquit/mixin/MinecraftAccessor.java new file mode 100644 index 0000000..58f7cb2 --- /dev/null +++ b/src/main/java/me/contaria/fastquit/mixin/MinecraftAccessor.java @@ -0,0 +1,11 @@ +package me.contaria.fastquit.mixin; + +import net.minecraft.client.Minecraft; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(Minecraft.class) +public interface MinecraftAccessor { + @Invoker("runTick") + void fastquit$runTick(boolean tick); +} diff --git a/src/main/java/me/contaria/fastquit/mixin/MinecraftClientAccessor.java b/src/main/java/me/contaria/fastquit/mixin/MinecraftClientAccessor.java deleted file mode 100644 index d544955..0000000 --- a/src/main/java/me/contaria/fastquit/mixin/MinecraftClientAccessor.java +++ /dev/null @@ -1,11 +0,0 @@ -package me.contaria.fastquit.mixin; - -import net.minecraft.client.MinecraftClient; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(MinecraftClient.class) -public interface MinecraftClientAccessor { - @Invoker("render") - void fastquit$render(boolean tick); -} diff --git a/src/main/java/me/contaria/fastquit/mixin/MinecraftClientMixin.java b/src/main/java/me/contaria/fastquit/mixin/MinecraftMixin.java similarity index 57% rename from src/main/java/me/contaria/fastquit/mixin/MinecraftClientMixin.java rename to src/main/java/me/contaria/fastquit/mixin/MinecraftMixin.java index 56baa7b..a0f6e89 100644 --- a/src/main/java/me/contaria/fastquit/mixin/MinecraftClientMixin.java +++ b/src/main/java/me/contaria/fastquit/mixin/MinecraftMixin.java @@ -4,9 +4,9 @@ import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import me.contaria.fastquit.FastQuit; import me.contaria.fastquit.WorldInfo; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.server.integrated.IntegratedServer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.server.IntegratedServer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -14,38 +14,38 @@ import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(MinecraftClient.class) -public abstract class MinecraftClientMixin { +@Mixin(Minecraft.class) +public abstract class MinecraftMixin { @Shadow - private boolean integratedServerRunning; + private boolean isLocalServer; @Redirect( - method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;ZZ)V", + method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;ZZ)V", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/integrated/IntegratedServer;isStopping()Z" + target = "Lnet/minecraft/client/server/IntegratedServer;isShutdown()Z" ) ) private boolean fastquit(IntegratedServer server) { FastQuit.savingWorlds.put(server, new WorldInfo()); if (FastQuit.CONFIG.backgroundPriority != 0) { - server.getThread().setPriority(FastQuit.CONFIG.backgroundPriority); + server.getRunningThread().setPriority(FastQuit.CONFIG.backgroundPriority); } - FastQuit.log("Disconnected \"" + server.getSaveProperties().getLevelName() + "\" from the client."); + FastQuit.log("Disconnected \"" + server.getWorldData().getLevelName() + "\" from the client."); return true; } @WrapOperation( - method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;ZZ)V", + method = "disconnect(Lnet/minecraft/client/gui/screens/Screen;ZZ)V", at = @At( value = "INVOKE", - target = "Lnet/minecraft/client/MinecraftClient;setScreenAndRender(Lnet/minecraft/client/gui/screen/Screen;)V" + target = "Lnet/minecraft/client/Minecraft;setScreenAndShow(Lnet/minecraft/client/gui/screens/Screen;)V" ) ) - private void fastquit$doNotOpenSaveScreen(MinecraftClient client, Screen screen, Operation original) { - if (FastQuit.CONFIG.renderSavingScreen && this.integratedServerRunning) { + private void fastquit$doNotOpenSaveScreen(Minecraft client, Screen screen, Operation original) { + if (FastQuit.CONFIG.renderSavingScreen && this.isLocalServer) { original.call(client, screen); } else { client.setScreen(screen); @@ -53,10 +53,10 @@ private boolean fastquit(IntegratedServer server) { } @Inject( - method = "stop", + method = "destroy", at = @At( value = "INVOKE", - target = "Lnet/minecraft/client/MinecraftClient;disconnectWithProgressScreen()V", + target = "Lnet/minecraft/client/Minecraft;disconnectWithProgressScreen()V", shift = At.Shift.AFTER ) ) @@ -65,7 +65,7 @@ private boolean fastquit(IntegratedServer server) { } @Inject( - method = "printCrashReport(Lnet/minecraft/client/MinecraftClient;Ljava/io/File;Lnet/minecraft/util/crash/CrashReport;)V", + method = "crash(Lnet/minecraft/client/Minecraft;Ljava/io/File;Lnet/minecraft/CrashReport;)V", at = @At("HEAD") ) private static void fastquit$waitForSaveOnCrash(CallbackInfo ci) { diff --git a/src/main/java/me/contaria/fastquit/mixin/MinecraftServerAccessor.java b/src/main/java/me/contaria/fastquit/mixin/MinecraftServerAccessor.java index 73fd03a..9e33dd6 100644 --- a/src/main/java/me/contaria/fastquit/mixin/MinecraftServerAccessor.java +++ b/src/main/java/me/contaria/fastquit/mixin/MinecraftServerAccessor.java @@ -1,12 +1,12 @@ package me.contaria.fastquit.mixin; import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.storage.LevelStorage; +import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(MinecraftServer.class) public interface MinecraftServerAccessor { - @Accessor("session") - LevelStorage.Session fastquit$getSession(); + @Accessor("storageSource") + LevelStorageSource.LevelStorageAccess fastquit$getStorageSource(); } \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/MinecraftServerMixin.java b/src/main/java/me/contaria/fastquit/mixin/MinecraftServerMixin.java index 94325de..691f62b 100644 --- a/src/main/java/me/contaria/fastquit/mixin/MinecraftServerMixin.java +++ b/src/main/java/me/contaria/fastquit/mixin/MinecraftServerMixin.java @@ -5,12 +5,12 @@ import me.contaria.fastquit.TextHelper; import me.contaria.fastquit.WorldInfo; import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.toast.SystemToast; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.toasts.SystemToast; +import net.minecraft.client.server.IntegratedServer; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.PlayerManager; -import net.minecraft.server.integrated.IntegratedServer; -import net.minecraft.text.MutableText; +import net.minecraft.server.players.PlayerList; import org.slf4j.Logger; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -29,7 +29,7 @@ public abstract class MinecraftServerMixin { private static Logger LOGGER; @Inject( - method = "exit", + method = "onServerExit", at = @At("RETURN") ) private void fastquit$finishSaving(CallbackInfo ci) { @@ -38,29 +38,29 @@ public abstract class MinecraftServerMixin { WorldInfo info = FastQuit.savingWorlds.remove(server); if (info == null) { - FastQuit.warn("\"" + server.getSaveProperties().getLevelName() + "\" was not registered in currently saving worlds!"); + FastQuit.warn("\"" + server.getWorldData().getLevelName() + "\" was not registered in currently saving worlds!"); return; } - MutableText description = TextHelper.translatable("fastquit.toast." + (info.deleted ? "deleted" : "description"), server.getSaveProperties().getLevelName()); + MutableComponent description = TextHelper.translatable("fastquit.toast." + (info.deleted ? "deleted" : "description"), server.getWorldData().getLevelName()); if (FastQuit.CONFIG.showSavingTime != FastQuitConfig.ShowSavingTime.FALSE && !info.deleted) { description.append(" (" + info.getTimeSaving() + ")"); } if (FastQuit.CONFIG.showToasts) { - MinecraftClient.getInstance().submit(() -> MinecraftClient.getInstance().getToastManager().add(new SystemToast(SystemToast.Type.WORLD_BACKUP, TextHelper.translatable("fastquit.toast.title"), description))); + Minecraft.getInstance().submit(() -> Minecraft.getInstance().getToastManager().addToast(new SystemToast(SystemToast.SystemToastId.WORLD_BACKUP, TextHelper.translatable("fastquit.toast.title"), description))); } FastQuit.log(description.getString()); } } @WrapWithCondition( - method = "shutdown", + method = "stopServer", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/PlayerManager;saveAllPlayerData()V" + target = "Lnet/minecraft/server/players/PlayerList;saveAll()V" ) ) - private boolean fastquit$cancelPlayerSavingIfDeleted(PlayerManager playerManager) { + private boolean fastquit$cancelPlayerSavingIfDeleted(PlayerList playerManager) { if (this.isDeleted()) { LOGGER.info("Cancelled saving players because level was deleted"); return false; @@ -69,7 +69,7 @@ public abstract class MinecraftServerMixin { } @Inject( - method = "save", + method = "saveAllChunks", at = { @At( value = "INVOKE", @@ -77,7 +77,7 @@ public abstract class MinecraftServerMixin { ), @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/storage/LevelStorage$Session;backupLevelDataFile(Lnet/minecraft/registry/DynamicRegistryManager;Lnet/minecraft/world/SaveProperties;Lnet/minecraft/nbt/NbtCompound;)V" + target = "Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;saveDataTag(Lnet/minecraft/world/level/storage/WorldData;Ljava/util/UUID;)V" ) }, cancellable = true diff --git a/src/main/java/me/contaria/fastquit/mixin/OptimizeWorldScreenMixin.java b/src/main/java/me/contaria/fastquit/mixin/OptimizeWorldScreenMixin.java index efddf31..c31f5af 100644 --- a/src/main/java/me/contaria/fastquit/mixin/OptimizeWorldScreenMixin.java +++ b/src/main/java/me/contaria/fastquit/mixin/OptimizeWorldScreenMixin.java @@ -1,11 +1,11 @@ package me.contaria.fastquit.mixin; import me.contaria.fastquit.FastQuit; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.worldselection.OptimizeWorldScreen; +import net.minecraft.world.level.storage.LevelStorageSource; import com.mojang.datafixers.DataFixer; import it.unimi.dsi.fastutil.booleans.BooleanConsumer; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.world.OptimizeWorldScreen; -import net.minecraft.world.level.storage.LevelStorage; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -19,7 +19,7 @@ public abstract class OptimizeWorldScreenMixin { method = "create", at = @At("HEAD") ) - private static void fastquit$waitForSaveOnOptimizeWorld(MinecraftClient client, BooleanConsumer callback, DataFixer dataFixer, LevelStorage.Session session, boolean eraseCache, CallbackInfoReturnable cir) { + private static void fastquit$waitForSaveOnOptimizeWorld(Minecraft client, BooleanConsumer callback, DataFixer dataFixer, LevelStorageSource.LevelStorageAccess session, boolean eraseCache, CallbackInfoReturnable cir) { FastQuit.getSavingWorld(session).ifPresent(FastQuit::wait); } } \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/PrimaryLevelDataAccessor.java b/src/main/java/me/contaria/fastquit/mixin/PrimaryLevelDataAccessor.java new file mode 100644 index 0000000..93bc60e --- /dev/null +++ b/src/main/java/me/contaria/fastquit/mixin/PrimaryLevelDataAccessor.java @@ -0,0 +1,12 @@ +package me.contaria.fastquit.mixin; + +import net.minecraft.world.level.LevelSettings; +import net.minecraft.world.level.storage.PrimaryLevelData; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(PrimaryLevelData.class) +public interface PrimaryLevelDataAccessor { + @Accessor("settings") + LevelSettings fastquit$getSettings(); +} \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/UploadCompressorMixin.java b/src/main/java/me/contaria/fastquit/mixin/RealmsUploadWorldPackerMixin.java similarity index 63% rename from src/main/java/me/contaria/fastquit/mixin/UploadCompressorMixin.java rename to src/main/java/me/contaria/fastquit/mixin/RealmsUploadWorldPackerMixin.java index 29ac49f..18d7527 100644 --- a/src/main/java/me/contaria/fastquit/mixin/UploadCompressorMixin.java +++ b/src/main/java/me/contaria/fastquit/mixin/RealmsUploadWorldPackerMixin.java @@ -1,27 +1,26 @@ package me.contaria.fastquit.mixin; import me.contaria.fastquit.FastQuit; -import net.minecraft.client.realms.util.UploadCompressor; 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.CallbackInfoReturnable; - +import com.mojang.realmsclient.client.worldupload.RealmsUploadWorldPacker; import java.io.File; import java.nio.file.Path; -@Mixin(UploadCompressor.class) -public abstract class UploadCompressorMixin { +@Mixin(RealmsUploadWorldPacker.class) +public abstract class RealmsUploadWorldPackerMixin { - @Shadow @Final private Path directory; + @Shadow @Final private Path directoryToPack; @Inject( - method = "run", + method = "tarGzipArchive", at = @At("HEAD") ) private void fastquit$waitForSaveOnRealmsUpload(CallbackInfoReturnable cir) { - FastQuit.getSavingWorld(directory).ifPresent(FastQuit::wait); + FastQuit.getSavingWorld(directoryToPack).ifPresent(FastQuit::wait); } } \ No newline at end of file diff --git a/src/main/java/me/contaria/fastquit/mixin/WorldListWidgetWorldEntryMixin.java b/src/main/java/me/contaria/fastquit/mixin/WorldListWidgetWorldEntryMixin.java index 979f56f..b3379e5 100644 --- a/src/main/java/me/contaria/fastquit/mixin/WorldListWidgetWorldEntryMixin.java +++ b/src/main/java/me/contaria/fastquit/mixin/WorldListWidgetWorldEntryMixin.java @@ -5,11 +5,11 @@ import me.contaria.fastquit.WorldInfo; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.world.WorldListWidget; -import net.minecraft.world.level.storage.LevelStorage; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphicsExtractor; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.worldselection.WorldSelectionList; +import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelSummary; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -18,74 +18,74 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(WorldListWidget.WorldEntry.class) -public abstract class WorldListWidgetWorldEntryMixin extends WorldListWidget.Entry { +@Mixin(WorldSelectionList.WorldListEntry.class) +public abstract class WorldListWidgetWorldEntryMixin extends WorldSelectionList.Entry { @Shadow @Final private Screen screen; @Shadow @Final - private MinecraftClient client; + private Minecraft minecraft; @Shadow @Final - LevelSummary level; + LevelSummary summary; @WrapOperation( method = { - "edit", - "recreate" + "editWorld", + "recreateWorld" }, at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/storage/LevelStorage;createSession(Ljava/lang/String;)Lnet/minecraft/world/level/storage/LevelStorage$Session;" + target = "Lnet/minecraft/world/level/storage/LevelStorageSource;validateAndCreateAccess(Ljava/lang/String;)Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;" ), require = 2 ) - private LevelStorage.Session fastquit$editSavingWorld(LevelStorage storage, String directoryName, Operation original) { - return FastQuit.getSession(storage.getSavesDirectory().resolve(directoryName)).orElseGet(() -> original.call(storage, directoryName)); + private LevelStorageSource.LevelStorageAccess fastquit$editSavingWorld(LevelStorageSource storage, String directoryName, Operation original) { + return FastQuit.getSession(storage.getBaseDir().resolve(directoryName)).orElseGet(() -> original.call(storage, directoryName)); } @WrapOperation( - method = "delete", + method = "doDeleteWorld", at = @At( value = "INVOKE", - target = "Lnet/minecraft/world/level/storage/LevelStorage;createSessionWithoutSymlinkCheck(Ljava/lang/String;)Lnet/minecraft/world/level/storage/LevelStorage$Session;" + target = "Lnet/minecraft/world/level/storage/LevelStorageSource;createAccess(Ljava/lang/String;)Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;" ) ) - private LevelStorage.Session fastquit$deleteSavingWorld(LevelStorage storage, String directoryName, Operation original) { - return FastQuit.getSession(storage.getSavesDirectory().resolve(directoryName)).orElseGet(() -> original.call(storage, directoryName)); + private LevelStorageSource.LevelStorageAccess fastquit$deleteSavingWorld(LevelStorageSource storage, String directoryName, Operation original) { + return FastQuit.getSession(storage.getBaseDir().resolve(directoryName)).orElseGet(() -> original.call(storage, directoryName)); } // While this should not be needed anymore, I'll leave it in just in case something goes wrong. @Inject( - method = "edit", + method = "editWorld", at = @At( value = "INVOKE", - target = "Lnet/minecraft/client/toast/SystemToast;addWorldAccessFailureToast(Lnet/minecraft/client/MinecraftClient;Ljava/lang/String;)V" + target = "Lnet/minecraft/client/gui/components/toasts/SystemToast;onWorldAccessFailure(Lnet/minecraft/client/Minecraft;Ljava/lang/String;)V" ) ) private void fastquit$openWorldListWhenFailed(CallbackInfo ci) { - this.client.setScreen(this.screen); + this.minecraft.setScreen(this.screen); } @Inject( - method = "render", + method = "extractContent", at = @At( value = "INVOKE", - target = "Lnet/minecraft/client/gui/widget/TextWidget;render(Lnet/minecraft/client/gui/DrawContext;IIF)V", + target = "Lnet/minecraft/client/gui/components/StringWidget;extractRenderState(Lnet/minecraft/client/gui/GuiGraphicsExtractor;IIF)V", ordinal = 0, shift = At.Shift.AFTER ) ) - private void fastquit$renderSavingTimeOnWorldList(DrawContext context, int mouseX, int mouseY, boolean hovered, float deltaTicks, CallbackInfo ci) { + private void fastquit$renderSavingTimeOnWorldList(GuiGraphicsExtractor context, int mouseX, int mouseY, boolean hovered, float deltaTicks, CallbackInfo ci) { if (FastQuit.CONFIG.showSavingTime != FastQuitConfig.ShowSavingTime.TRUE || FastQuit.HAS_WORLDPLAYTIME) { return; } - FastQuit.getSavingWorld(this.client.getLevelStorage().getSavesDirectory().resolve(this.level.getName())).ifPresent(server -> { + FastQuit.getSavingWorld(this.minecraft.getLevelSource().getBaseDir().resolve(this.summary.getLevelId())).ifPresent(server -> { WorldInfo info = FastQuit.savingWorlds.get(server); if (info != null) { String time = info.getTimeSaving() + " ⌛"; - context.drawText(this.client.textRenderer, time, this.getX() + this.getWidth() - this.client.textRenderer.getWidth(time) - 4, this.getY() + 1, -6939106, false); + context.text(this.minecraft.font, time, this.getX() + this.getWidth() - this.minecraft.font.width(time) - 4, this.getY() + 1, -6939106, false); } }); } diff --git a/src/main/java/me/contaria/fastquit/mixin/IntegratedServerLoaderMixin.java b/src/main/java/me/contaria/fastquit/mixin/WorldOpenFlowsMixin.java similarity index 59% rename from src/main/java/me/contaria/fastquit/mixin/IntegratedServerLoaderMixin.java rename to src/main/java/me/contaria/fastquit/mixin/WorldOpenFlowsMixin.java index 3841fd1..2ea2e58 100644 --- a/src/main/java/me/contaria/fastquit/mixin/IntegratedServerLoaderMixin.java +++ b/src/main/java/me/contaria/fastquit/mixin/WorldOpenFlowsMixin.java @@ -1,8 +1,8 @@ package me.contaria.fastquit.mixin; import me.contaria.fastquit.FastQuit; -import net.minecraft.server.integrated.IntegratedServerLoader; -import net.minecraft.world.level.storage.LevelStorage; +import net.minecraft.client.gui.screens.worldselection.WorldOpenFlows; +import net.minecraft.world.level.storage.LevelStorageSource; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -10,20 +10,20 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -@Mixin(IntegratedServerLoader.class) -public abstract class IntegratedServerLoaderMixin { +@Mixin(WorldOpenFlows.class) +public abstract class WorldOpenFlowsMixin { @Shadow @Final - private LevelStorage storage; + private LevelStorageSource levelSource; @Inject( - method = "start(Ljava/lang/String;Ljava/lang/Runnable;)V", + method = "openWorld(Ljava/lang/String;Ljava/lang/Runnable;)V", at = @At("HEAD"), cancellable = true ) private void fastquit$waitForSaveOnWorldLoad_cancellable(String levelName, Runnable onCancel, CallbackInfo ci) { - FastQuit.getSavingWorld(this.storage.getSavesDirectory().resolve(levelName)).ifPresent(server -> FastQuit.wait(server, ci)); + FastQuit.getSavingWorld(this.levelSource.getBaseDir().resolve(levelName)).ifPresent(server -> FastQuit.wait(server, ci)); if (ci.isCancelled()) { onCancel.run(); } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 07b969f..f810155 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -28,10 +28,10 @@ ], "depends": { "fabricloader": ">=0.16.9", - "minecraft": ">=1.21.11", + "minecraft": ">=26.1", "fabric-resource-loader-v0": "*", "cloth-config": "*", - "java": ">=21" + "java": ">=25" }, "suggests": { "modmenu": "*" diff --git a/src/main/resources/fastquit.mixins.json b/src/main/resources/fastquit.mixins.json index 199c323..17eae35 100644 --- a/src/main/resources/fastquit.mixins.json +++ b/src/main/resources/fastquit.mixins.json @@ -5,19 +5,19 @@ "compatibilityLevel": "JAVA_17", "client": [ "EditWorldScreenMixin", - "IntegratedServerLoaderMixin", - "LevelInfoAccessor", - "LevelPropertiesAccessor", - "LevelStorageMixin", + "LevelSettingsAccessor", + "LevelStorageAccessMixin", "LevelStorageSessionAccessor", - "LevelStorageSessionMixin", - "MinecraftClientAccessor", - "MinecraftClientMixin", + "LevelStorageSourceMixin", + "MinecraftAccessor", + "MinecraftMixin", "MinecraftServerAccessor", "MinecraftServerMixin", "OptimizeWorldScreenMixin", - "UploadCompressorMixin", - "WorldListWidgetWorldEntryMixin" + "PrimaryLevelDataAccessor", + "RealmsUploadWorldPackerMixin", + "WorldListWidgetWorldEntryMixin", + "WorldOpenFlowsMixin" ], "injectors": { "defaultRequire": 1