diff --git a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java index 0956ffa83be..dff83c36350 100644 --- a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java +++ b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java @@ -850,6 +850,10 @@ public static class DeveloperConfigs { @Configurable @Configurable.Comment({ "Dump all registered GT models/blockstates/etc?", "Default: false" }) public boolean dumpAssets = false; + @Configurable + @Configurable.Comment({ "Executes ./gradlew :processResources when F3+T is pressed", + "Only works in a development environment", "Default: false" }) + public boolean autoRebuildResources = false; } public static class RendererConfigs { diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/dev/client/KeyboardHandlerMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/dev/client/KeyboardHandlerMixin.java new file mode 100644 index 00000000000..e06b0e59053 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/dev/client/KeyboardHandlerMixin.java @@ -0,0 +1,25 @@ +package com.gregtechceu.gtceu.core.mixins.dev.client; + +import com.gregtechceu.gtceu.utils.dev.ResourceReloadDetector; + +import net.minecraft.client.KeyboardHandler; +import net.minecraft.client.Minecraft; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.concurrent.CompletableFuture; + +@Mixin(KeyboardHandler.class) +public abstract class KeyboardHandlerMixin { + + @WrapOperation(method = "handleDebugKeys", + at = @At(value = "INVOKE", + target = "Lnet/minecraft/client/Minecraft;reloadResourcePacks()Ljava/util/concurrent/CompletableFuture;")) + private CompletableFuture gtceu$hookResourceReload(Minecraft instance, + Operation> original) { + return ResourceReloadDetector.regenerateResourcesOnReload(() -> original.call(instance)); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java index 610acc56226..327b864f12d 100644 --- a/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/data/lang/LangHandler.java @@ -1233,6 +1233,9 @@ public static void init(RegistrateLangProvider provider) { provider.add("gtceu.key.enable_step_assist", "Enable StepAssist"); provider.add("gtceu.debug.f3_h.enabled", "GregTech has modified the debug info! For Developers: enable the misc:debug config option in the GregTech config file to see more"); + provider.add("gtceu.debug.resource_rebuild.done", "Gradle resource rebuild done in %s"); + provider.add("gtceu.debug.resource_rebuild.start", + "Invoking gradle resource rebuild (./gradlew :processResources)"); provider.add("config.jade.plugin_gtceu.controllable_provider", "[GTCEu] Controllable"); provider.add("config.jade.plugin_gtceu.workable_provider", "[GTCEu] Workable"); provider.add("config.jade.plugin_gtceu.battery_info", "[GTCEu] Battery info"); diff --git a/src/main/java/com/gregtechceu/gtceu/utils/dev/ResourceReloadDetector.java b/src/main/java/com/gregtechceu/gtceu/utils/dev/ResourceReloadDetector.java new file mode 100644 index 00000000000..64baf26b5a7 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/utils/dev/ResourceReloadDetector.java @@ -0,0 +1,68 @@ +package com.gregtechceu.gtceu.utils.dev; + +import com.gregtechceu.gtceu.GTCEu; +import com.gregtechceu.gtceu.config.ConfigHolder; + +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; + +import com.sun.jna.platform.win32.*; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; + +@ApiStatus.Internal +public class ResourceReloadDetector { + + private static final Path gradleDir = findGradleDir(); + + @ApiStatus.Internal + public static CompletableFuture regenerateResourcesOnReload(Supplier> reloadFuture) { + if (!ConfigHolder.INSTANCE.dev.autoRebuildResources || !GTCEu.isDev() || gradleDir == null) { + return reloadFuture.get(); + } + ProcessBuilder builder = switch (Util.getPlatform()) { + case WINDOWS -> new ProcessBuilder("cmd.exe", "/c", "gradlew.bat", ":processResources"); + default -> new ProcessBuilder("./gradlew", ":processResources"); + }; + builder.directory(gradleDir.toFile()); + builder.inheritIO(); + Process process; + try { + process = builder.start(); + } catch (IOException exception) { + GTCEu.LOGGER.error("Cound not run ./gradlew :processResources", exception); + GTCEu.LOGGER.error("Message the GTCEu developers about this!"); + return reloadFuture.get(); + } + Minecraft.getInstance().player.sendSystemMessage(Component.translatable("gtceu.debug.resource_rebuild.start")); + Instant start = Instant.now(); + // wait for the resource reload to finish, then send chat message, then let MC actually reload resources + return process.toHandle().onExit() + .thenRun(() -> Minecraft.getInstance().player + .sendSystemMessage(Component.translatable("gtceu.debug.resource_rebuild.done", + Duration.between(start, Instant.now())))) + .thenCompose($ -> reloadFuture.get()); + } + + private static @Nullable Path findGradleDir() { + Path path = Path.of(".").toAbsolutePath(); + do { + if (Files.isRegularFile(path.resolve("settings.gradle")) || + Files.isRegularFile(path.resolve("settings.gradle.kts"))) { + return path; + } + path = path.getParent(); + } while (path.getParent() != null); + + return null; + } +} diff --git a/src/main/resources/gtceu.mixins.json b/src/main/resources/gtceu.mixins.json index 3ade6f7cca3..0e1923c87a9 100644 --- a/src/main/resources/gtceu.mixins.json +++ b/src/main/resources/gtceu.mixins.json @@ -21,6 +21,7 @@ "client.MultiPlayerGameModeMixin", "client.PlayerInfoAccessor", "client.VariantDeserializerMixin", + "dev.client.KeyboardHandlerMixin", "ftbchunks.FTBChunksClientMixin", "ftbchunks.LargeMapScreenMixin", "ftbchunks.RegionMapPanelMixin",