diff --git a/dependencies.gradle b/dependencies.gradle index b1a3c3e2..ca6278d1 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -42,7 +42,9 @@ dependencies { // CCL, CT dep for GT (from GTCEu Maven) // Included to allow compiling of certain Draconic Evolution Mixin Classes, and as transitive deps - implementation ("codechicken:codechickenlib:3.2.3.358") // Version 3.2.3.358 + implementation ("codechicken:codechickenlib:3.2.3.358") { + transitive = false + } // Version 3.2.3.358 // GT and GCYM, pretty much the 'core' of this coremod (from GTCEu Maven) // GT Has Mixins! CHECK MIXINS FOR COMPAT AFTER UPDATING! @@ -62,7 +64,17 @@ dependencies { } // Version 1.1.3 // Config Anytime (from Cleanroom Maven) - implementation ('com.cleanroommc:configanytime:3.0') // Version 3.0 + implementation ('com.cleanroommc:configanytime:3.0') { + transitive = false + } // Version 3.0 + + // Had Enough Items + implementation ('mezz:jei:4.26.2') { + transitive = false + } // Version 4.26.2 + + // The One Probe + implementation rfg.deobf('curse.maven:top-245211:2667280') // Version 1.4.28 /* -------------------------------- Compile Time Only Deps -------------------------------- */ diff --git a/gradle.properties b/gradle.properties index 35b532c6..93b20fd8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -84,7 +84,7 @@ includeWellKnownRepositories = true # Adds JEI and TheOneProbe to your development environment. Adds them as 'implementation', meaning they will # be available at compiletime and runtime for your mod (in-game and in-code). # Overrides the above setting to be always true, as these repositories are needed to fetch the mods -includeCommonDevEnvMods = true +includeCommonDevEnvMods = false # If enabled, you may use 'shadowCompile' for dependencies. They will be integrated in your jar. It is your diff --git a/src/main/java/com/nomiceu/nomilabs/NomiLabs.java b/src/main/java/com/nomiceu/nomilabs/NomiLabs.java index 372e06c1..a09b2774 100644 --- a/src/main/java/com/nomiceu/nomilabs/NomiLabs.java +++ b/src/main/java/com/nomiceu/nomilabs/NomiLabs.java @@ -10,6 +10,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import com.nomiceu.nomilabs.command.LabsReloadCommand; import com.nomiceu.nomilabs.config.LabsConfig; import com.nomiceu.nomilabs.event.ClientProxy; import com.nomiceu.nomilabs.event.CommonProxy; @@ -81,6 +82,11 @@ public void loadComplete(FMLLoadCompleteEvent event) { CommonProxy.loadComplete(); } + @EventHandler + public void serverLoad(FMLServerStartingEvent event) { + event.registerServerCommand(new LabsReloadCommand()); + } + @EventHandler public void serverStopped(FMLServerStoppedEvent event) { DataFixerHandler.close(); diff --git a/src/main/java/com/nomiceu/nomilabs/command/LabsReloadCommand.java b/src/main/java/com/nomiceu/nomilabs/command/LabsReloadCommand.java new file mode 100644 index 00000000..b80a5e8b --- /dev/null +++ b/src/main/java/com/nomiceu/nomilabs/command/LabsReloadCommand.java @@ -0,0 +1,84 @@ +package com.nomiceu.nomilabs.command; + +import java.util.List; + +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.text.TextComponentString; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.server.command.CommandTreeBase; + +import org.jetbrains.annotations.NotNull; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.api.GroovyLog; +import com.cleanroommc.groovyscript.sandbox.LoadStage; +import com.google.common.collect.ImmutableList; +import com.nomiceu.nomilabs.network.LabsFastReloadMessage; +import com.nomiceu.nomilabs.network.LabsLangReloadMessage; +import com.nomiceu.nomilabs.network.LabsNetworkHandler; +import com.nomiceu.nomilabs.network.LabsNoJeiReloadMessage; + +/** + * Provides three variations to the GroovyScript reload command: + * + */ +public class LabsReloadCommand extends CommandTreeBase { + + public LabsReloadCommand() { + addSubcommand(new SimpleCommand("lang", + (server, sender, args) -> runReload(sender, server, new LabsLangReloadMessage()))); + + addSubcommand(new SimpleCommand("fast", + (server, sender, args) -> runReload(sender, server, new LabsFastReloadMessage()))); + + addSubcommand(new SimpleCommand("noJei", + (server, sender, args) -> runReload(sender, server, new LabsNoJeiReloadMessage()))); + } + + /** + * Mostly from {@link com.cleanroommc.groovyscript.command.GSCommand#runReload(EntityPlayerMP, MinecraftServer)}, + * but allows for custom packets for client handling. + */ + public static void runReload(ICommandSender sender, MinecraftServer server, IMessage reloadMsg) { + if (!(sender instanceof EntityPlayerMP player)) return; + + if (server.isDedicatedServer()) { + player.sendMessage( + new TextComponentString("Reloading in multiplayer is currently not allowed to avoid desync.")); + return; + } + + GroovyLog.get().info("========== Reloading Groovy scripts =========="); + + // noinspection UnstableApiUsage + long time = GroovyScript.runGroovyScriptsInLoader(LoadStage.POST_INIT); + GroovyScript.postScriptRunResult(player, false, true, false, time); + LabsNetworkHandler.NETWORK_HANDLER.sendTo(reloadMsg, player); + } + + @Override + @NotNull + public String getName() { + return "labsGsReload"; + } + + @Override + @NotNull + public List getAliases() { + return ImmutableList.of("lr", "labsReload"); + } + + @Override + @NotNull + public String getUsage(@NotNull ICommandSender sender) { + return "/lr "; + } +} diff --git a/src/main/java/com/nomiceu/nomilabs/command/SimpleCommand.java b/src/main/java/com/nomiceu/nomilabs/command/SimpleCommand.java new file mode 100644 index 00000000..1807a935 --- /dev/null +++ b/src/main/java/com/nomiceu/nomilabs/command/SimpleCommand.java @@ -0,0 +1,58 @@ +package com.nomiceu.nomilabs.command; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.CommandException; +import net.minecraft.command.ICommandSender; +import net.minecraft.server.MinecraftServer; + +import org.jetbrains.annotations.NotNull; + +public class SimpleCommand extends CommandBase { + + private final String name; + private final String usage; + private final ICommand command; + private final List aliases = new ArrayList<>(); + + public SimpleCommand(String name, String usage, ICommand command, String... aliases) { + this.name = name; + this.usage = usage; + this.command = command; + Collections.addAll(this.aliases, aliases); + } + + public SimpleCommand(String name, ICommand command, String... aliases) { + this(name, "/lr " + name, command, aliases); + } + + @Override + public @NotNull String getName() { + return name; + } + + @Override + public @NotNull String getUsage(@NotNull ICommandSender sender) { + return usage; + } + + @Override + public void execute(@NotNull MinecraftServer server, @NotNull ICommandSender sender, + String @NotNull [] args) throws CommandException { + command.execute(server, sender, args); + } + + @Override + public @NotNull List getAliases() { + return aliases; + } + + @FunctionalInterface + public interface ICommand { + + void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException; + } +} diff --git a/src/main/java/com/nomiceu/nomilabs/integration/jei/SavedJEIValues.java b/src/main/java/com/nomiceu/nomilabs/integration/jei/SavedJEIValues.java new file mode 100644 index 00000000..09679642 --- /dev/null +++ b/src/main/java/com/nomiceu/nomilabs/integration/jei/SavedJEIValues.java @@ -0,0 +1,8 @@ +package com.nomiceu.nomilabs.integration.jei; + +import mezz.jei.ingredients.IngredientFilter; + +public class SavedJEIValues { + + public static IngredientFilter savedFilter; +} diff --git a/src/main/java/com/nomiceu/nomilabs/mixin/jei/JeiStarterMixin.java b/src/main/java/com/nomiceu/nomilabs/mixin/jei/JeiStarterMixin.java index 16bececd..72db47c6 100644 --- a/src/main/java/com/nomiceu/nomilabs/mixin/jei/JeiStarterMixin.java +++ b/src/main/java/com/nomiceu/nomilabs/mixin/jei/JeiStarterMixin.java @@ -2,27 +2,67 @@ import java.util.List; +import net.minecraft.util.NonNullList; + 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.CallbackInfo; import com.cleanroommc.groovyscript.compat.mods.jei.JeiPlugin; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.nomiceu.nomilabs.NomiLabs; import com.nomiceu.nomilabs.groovy.mixinhelper.LabsJEIApplied; +import com.nomiceu.nomilabs.integration.jei.SavedJEIValues; import mezz.jei.api.IJeiRuntime; import mezz.jei.api.IModPlugin; +import mezz.jei.api.ingredients.IIngredientRegistry; +import mezz.jei.gui.ingredients.IIngredientListElement; +import mezz.jei.ingredients.IngredientBlacklistInternal; +import mezz.jei.ingredients.IngredientFilter; +import mezz.jei.ingredients.IngredientListElementFactory; +import mezz.jei.startup.IModIdHelper; import mezz.jei.startup.JeiStarter; import mezz.jei.startup.ModRegistry; /** * Fix GrS JEI Hiding Issues, by re-checking if applied, and if not, applying at end of registers, * instead of before ProgressManager.pop(). This can happen due to HEI's new 'Progress Bar' config. + *

+ * Also allows for 'fast' reloading of JEI, reusing the existing Ingredient Filter, Search Trees and Bookmarks Data. */ @Mixin(value = JeiStarter.class, remap = false) public class JeiStarterMixin { + @SuppressWarnings("rawtypes") + @Redirect(method = "start", + at = @At(value = "INVOKE", + target = "Lmezz/jei/ingredients/IngredientListElementFactory;createBaseList(Lmezz/jei/api/ingredients/IIngredientRegistry;Lmezz/jei/startup/IModIdHelper;)Lnet/minecraft/util/NonNullList;"), + require = 1) + private NonNullList stopRegenerationOfList(IIngredientRegistry ingredientType, + IModIdHelper ingredientRegistry) { + if (SavedJEIValues.savedFilter == null) + return IngredientListElementFactory.createBaseList(ingredientType, ingredientRegistry); + return null; + } + + @SuppressWarnings("rawtypes") + @WrapOperation(method = "start", + at = @At(value = "NEW", + target = "(Lmezz/jei/ingredients/IngredientBlacklistInternal;Lnet/minecraft/util/NonNullList;)Lmezz/jei/ingredients/IngredientFilter;"), + require = 1) + private IngredientFilter reuseIngredientBlacklist(IngredientBlacklistInternal blacklist, + NonNullList ingredients, + Operation original) { + if (SavedJEIValues.savedFilter == null) return original.call(blacklist, ingredients); + + NomiLabs.LOGGER.info("[Fast JEI Reload] Using Saved JEI Ingredient Filter..."); + return SavedJEIValues.savedFilter; + } + @Inject(method = "registerPlugins", at = @At("TAIL")) private static void handleAfterRegister(List plugins, ModRegistry modRegistry, CallbackInfo ci) { if (LabsJEIApplied.afterRegisterApplied) { diff --git a/src/main/java/com/nomiceu/nomilabs/network/LabsFastReloadMessage.java b/src/main/java/com/nomiceu/nomilabs/network/LabsFastReloadMessage.java new file mode 100644 index 00000000..c97bd313 --- /dev/null +++ b/src/main/java/com/nomiceu/nomilabs/network/LabsFastReloadMessage.java @@ -0,0 +1,40 @@ +package com.nomiceu.nomilabs.network; + +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.registry.ReloadableRegistryManager; +import com.nomiceu.nomilabs.integration.jei.SavedJEIValues; + +import io.netty.buffer.ByteBuf; +import mezz.jei.Internal; + +public class LabsFastReloadMessage implements IMessage { + + public LabsFastReloadMessage() {} + + @Override + public void fromBytes(ByteBuf buf) {} + + @Override + public void toBytes(ByteBuf buf) {} + + public static class MessageHandler extends MainThreadMessageHandler { + + @Override + protected IMessage executeClient(LabsFastReloadMessage message, MessageContext ctx) { + // Save existing JEI values + SavedJEIValues.savedFilter = Internal.getIngredientFilter(); + + // noinspection UnstableApiUsage + ReloadableRegistryManager.reloadJei(true); + + SavedJEIValues.savedFilter = null; + + GroovyScript.postScriptRunResult(Minecraft.getMinecraft().player, true, true, true, 0); + return null; + } + } +} diff --git a/src/main/java/com/nomiceu/nomilabs/network/LabsLangReloadMessage.java b/src/main/java/com/nomiceu/nomilabs/network/LabsLangReloadMessage.java new file mode 100644 index 00000000..c408b005 --- /dev/null +++ b/src/main/java/com/nomiceu/nomilabs/network/LabsLangReloadMessage.java @@ -0,0 +1,43 @@ +package com.nomiceu.nomilabs.network; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.text.TextComponentString; +import net.minecraftforge.client.resource.VanillaResourceType; +import net.minecraftforge.fml.client.FMLClientHandler; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import com.cleanroommc.groovyscript.GroovyScript; +import com.cleanroommc.groovyscript.registry.ReloadableRegistryManager; + +import io.netty.buffer.ByteBuf; + +public class LabsLangReloadMessage implements IMessage { + + public LabsLangReloadMessage() {} + + @Override + public void fromBytes(ByteBuf buf) {} + + @Override + public void toBytes(ByteBuf buf) {} + + public static class MessageHandler extends MainThreadMessageHandler { + + @Override + protected IMessage executeClient(LabsLangReloadMessage message, MessageContext ctx) { + // Reload Textures, but ONLY Lang + long time = System.currentTimeMillis(); + FMLClientHandler.instance().refreshResources(VanillaResourceType.LANGUAGES); + time = System.currentTimeMillis() - time; + Minecraft.getMinecraft().player.sendMessage( + new TextComponentString("Reloading Language Resources took " + time + "ms")); + + // noinspection UnstableApiUsage + ReloadableRegistryManager.reloadJei(true); + + GroovyScript.postScriptRunResult(Minecraft.getMinecraft().player, true, true, true, 0); + return null; + } + } +} diff --git a/src/main/java/com/nomiceu/nomilabs/network/LabsNetworkHandler.java b/src/main/java/com/nomiceu/nomilabs/network/LabsNetworkHandler.java index ce667fc8..f623419a 100644 --- a/src/main/java/com/nomiceu/nomilabs/network/LabsNetworkHandler.java +++ b/src/main/java/com/nomiceu/nomilabs/network/LabsNetworkHandler.java @@ -29,6 +29,10 @@ public static void preInit() { registerMessage(4, LabsP2PAddAsInputMessage.MessageHandler.class, LabsP2PAddAsInputMessage.class); registerMessage(5, LabsP2PAddAsOutputMessage.MessageHandler.class, LabsP2PAddAsOutputMessage.class); } + + registerMessage(6, LabsLangReloadMessage.MessageHandler.class, LabsLangReloadMessage.class); + registerMessage(7, LabsFastReloadMessage.MessageHandler.class, LabsFastReloadMessage.class); + registerMessage(8, LabsNoJeiReloadMessage.MessageHandler.class, LabsNoJeiReloadMessage.class); } @SuppressWarnings("SameParameterValue") diff --git a/src/main/java/com/nomiceu/nomilabs/network/LabsNoJeiReloadMessage.java b/src/main/java/com/nomiceu/nomilabs/network/LabsNoJeiReloadMessage.java new file mode 100644 index 00000000..63cb1bb3 --- /dev/null +++ b/src/main/java/com/nomiceu/nomilabs/network/LabsNoJeiReloadMessage.java @@ -0,0 +1,29 @@ +package com.nomiceu.nomilabs.network; + +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +import com.cleanroommc.groovyscript.GroovyScript; + +import io.netty.buffer.ByteBuf; + +public class LabsNoJeiReloadMessage implements IMessage { + + public LabsNoJeiReloadMessage() {} + + @Override + public void fromBytes(ByteBuf buf) {} + + @Override + public void toBytes(ByteBuf buf) {} + + public static class MessageHandler extends MainThreadMessageHandler { + + @Override + protected IMessage executeClient(LabsNoJeiReloadMessage message, MessageContext ctx) { + GroovyScript.postScriptRunResult(Minecraft.getMinecraft().player, true, true, true, 0); + return null; + } + } +} diff --git a/src/main/java/com/nomiceu/nomilabs/network/MainThreadMessageHandler.java b/src/main/java/com/nomiceu/nomilabs/network/MainThreadMessageHandler.java new file mode 100644 index 00000000..60c2ffbf --- /dev/null +++ b/src/main/java/com/nomiceu/nomilabs/network/MainThreadMessageHandler.java @@ -0,0 +1,26 @@ +package com.nomiceu.nomilabs.network; + +import net.minecraft.util.IThreadListener; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public abstract class MainThreadMessageHandler + implements IMessageHandler { + + protected abstract REPLY executeClient(REQ message, MessageContext ctx); + + @Override + public REPLY onMessage(REQ message, MessageContext ctx) { + if (!ctx.side.isClient()) return null; + + IThreadListener threadListener = FMLCommonHandler.instance().getWorldThread(ctx.getClientHandler()); + if (threadListener.isCallingFromMinecraftThread()) { + return executeClient(message, ctx); + } else { + threadListener.addScheduledTask(() -> executeClient(message, ctx)); + } + return null; + } +}