Skip to content

Commit a95a041

Browse files
authored
Reload JEIless (#351)
* allow reloading without updating jei * add keybind to quick reload * ensure player exists * attempt to run JEIStarter#load, if it exists * allow --entire-jei in command to reload everything * remove copykey fix because its a separate pr * packmode reloads everything * enhance xei reload message
1 parent 55b43ed commit a95a041

File tree

11 files changed

+127
-19
lines changed

11 files changed

+127
-19
lines changed

src/main/java/com/cleanroommc/groovyscript/command/GSCommand.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.io.File;
2727
import java.util.Arrays;
28+
import java.util.Collection;
2829
import java.util.List;
2930
import java.util.Objects;
3031

@@ -33,12 +34,12 @@ public class GSCommand extends CommandTreeBase {
3334
public GSCommand() {
3435
addSubcommand(new SimpleCommand("log", (server, sender, args) -> postLogFiles(sender)));
3536

36-
addSubcommand(new SimpleCommand("reload", (server, sender, args) -> {
37+
addSubcommand(new SimpleCommand("reload", "/gs reload [--clean|--skip-jei|--entire-jei]", (server, sender, args) -> {
3738
if (sender instanceof EntityPlayerMP player) {
3839
if (hasArgument(args, "--clean")) {
3940
GroovyLogImpl.LOG.cleanLog();
4041
}
41-
runReload(player, server);
42+
runReload(player, server, Arrays.asList(args));
4243
}
4344
}));
4445

@@ -128,15 +129,15 @@ public GSCommand() {
128129
}
129130
}
130131

131-
public static void runReload(EntityPlayerMP player, MinecraftServer server) {
132+
public static void runReload(EntityPlayerMP player, MinecraftServer server, Collection<String> args) {
132133
if (server.isDedicatedServer()) {
133134
player.sendMessage(new TextComponentString("Reloading in multiplayer is currently not allowed to avoid desync."));
134135
return;
135136
}
136137
GroovyLog.get().info("========== Reloading Groovy scripts ==========");
137138
long time = GroovyScript.runGroovyScriptsInLoader(LoadStage.POST_INIT);
138139
GroovyScript.postScriptRunResult(player, false, true, false, time);
139-
NetworkHandler.sendToPlayer(new SReloadScripts(null, false, true), player);
140+
NetworkHandler.sendToPlayer(new SReloadScripts(null, false, !args.contains("--skip-jei"), !args.contains("--entire-jei")), player);
140141
}
141142

142143
public static void postLogFiles(ICommandSender sender) {

src/main/java/com/cleanroommc/groovyscript/command/PackmodeCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,6 @@ public void execute(@NotNull MinecraftServer server, @NotNull ICommandSender sen
4242
SReloadScripts.updatePackmode(sender, packmode);
4343
PackmodeSaveData saveData = PackmodeSaveData.get(server);
4444
saveData.setPackmode(Packmode.getPackmode());
45-
NetworkHandler.sendToPlayer(new SReloadScripts(null, true, true), (EntityPlayerMP) sender);
45+
NetworkHandler.sendToPlayer(new SReloadScripts(null, true, true, false), (EntityPlayerMP) sender);
4646
}
4747
}

src/main/java/com/cleanroommc/groovyscript/core/mixin/GuiCreateWorldMixin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ public void actionPerformed2(GuiButton button, CallbackInfo ci) {
5757
if (Packmode.needsPackmode()) {
5858
Packmode.updatePackmode(this.packmodeButton.getPackmode());
5959
GroovyScript.runGroovyScriptsInLoader(LoadStage.POST_INIT);
60-
ReloadableRegistryManager.reloadJei(false);
60+
ReloadableRegistryManager.reloadJei(false, false);
6161
}
6262
}
6363

src/main/java/com/cleanroommc/groovyscript/event/EventHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ public static void playerLogin(PlayerEvent.PlayerLoggedInEvent event) {
9999
PackmodeSaveData saveData = PackmodeSaveData.get(event.player.world);
100100
if (Packmode.hasPackmode() && saveData.isDedicatedServer()) {
101101
// if the world is a dedicated server or a lan server the packmode should be synced with each player
102-
NetworkHandler.sendToPlayer(new SReloadScripts(saveData.getPackmode(), true, true), (EntityPlayerMP) event.player);
102+
NetworkHandler.sendToPlayer(new SReloadScripts(saveData.getPackmode(), true, true, false), (EntityPlayerMP) event.player);
103103
} else if (!Packmode.getPackmode().equals(saveData.getPackmode()) && !saveData.isDedicatedServer()) {
104104
// otherwise we are on a single player world, and we can just set and reload the packmode
105105
SReloadScripts.updatePackmode(event.player, saveData.getPackmode());
106-
NetworkHandler.sendToPlayer(new SReloadScripts(null, true, true), (EntityPlayerMP) event.player);
106+
NetworkHandler.sendToPlayer(new SReloadScripts(null, true, true, false), (EntityPlayerMP) event.player);
107107
}
108108
}
109109
}

src/main/java/com/cleanroommc/groovyscript/helper/StyleConstant.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public class StyleConstant {
6767
* Used for titles to make them emphasised and keep them distinct from the surrounding text
6868
*/
6969
public static Style getTitleStyle() {
70-
return new Style().setColor(TextFormatting.WHITE).setBold(true);
70+
return new Style().setColor(TextFormatting.WHITE).setBold(Boolean.TRUE);
7171
}
7272

7373
/**
@@ -99,4 +99,12 @@ public static Style getWarningStyle() {
9999
public static Style getErrorStyle() {
100100
return new Style().setColor(ERROR);
101101
}
102+
103+
/**
104+
* Used when the text is substituted based on outcome and should be slightly emphasized,
105+
* but doesn't necessarily indicate status.
106+
*/
107+
public static Style getTipStyle() {
108+
return new Style().setItalic(Boolean.TRUE).setColor(TextFormatting.GRAY);
109+
}
102110
}

src/main/java/com/cleanroommc/groovyscript/keybinds/GroovyScriptKeybinds.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public class GroovyScriptKeybinds {
2626

2727
public static void initialize() {
2828
addKey(ReloadKey.createKeybind());
29+
addKey(QuickReloadKey.createKeybind());
2930
addKey(CopyKey.createKeybind());
3031
}
3132

@@ -92,6 +93,10 @@ public abstract static class Key {
9293

9394
private final KeyBinding key;
9495

96+
public Key(String name) {
97+
this(name, KeyConflictContext.UNIVERSAL, KeyModifier.NONE, Keyboard.KEY_NONE);
98+
}
99+
95100
public Key(String name, int keyCode) {
96101
this(name, KeyConflictContext.UNIVERSAL, KeyModifier.NONE, keyCode);
97102
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.cleanroommc.groovyscript.keybinds;
2+
3+
import com.cleanroommc.groovyscript.network.CReload;
4+
import com.cleanroommc.groovyscript.network.NetworkHandler;
5+
import net.minecraft.client.Minecraft;
6+
7+
public class QuickReloadKey extends GroovyScriptKeybinds.Key {
8+
9+
private static final long INTERVAL = 1000L;
10+
private static final int PERMISSION_LEVEL = 4;
11+
12+
private static final Minecraft mc = Minecraft.getMinecraft();
13+
14+
private long timeSinceLastUse;
15+
16+
public QuickReloadKey() {
17+
super("quick_reload");
18+
}
19+
20+
public static QuickReloadKey createKeybind() {
21+
return new QuickReloadKey();
22+
}
23+
24+
@Override
25+
public boolean isValid() {
26+
return mc.currentScreen == null && mc.inGameHasFocus;
27+
}
28+
29+
@Override
30+
public void runOperation() {
31+
long time = Minecraft.getSystemTime();
32+
if (mc.isIntegratedServerRunning() && time - timeSinceLastUse >= INTERVAL && mc.player.getPermissionLevel() >= PERMISSION_LEVEL) {
33+
NetworkHandler.sendToServer(new CReload(false));
34+
timeSinceLastUse = time;
35+
}
36+
}
37+
}
Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
11
package com.cleanroommc.groovyscript.network;
22

33
import com.cleanroommc.groovyscript.command.GSCommand;
4+
import com.google.common.collect.ImmutableList;
45
import net.minecraft.network.NetHandlerPlayServer;
56
import net.minecraft.network.PacketBuffer;
67

78
public class CReload implements IPacket {
89

10+
private boolean reloadJei;
11+
12+
public CReload() {
13+
this(true);
14+
}
15+
16+
public CReload(boolean reloadJei) {
17+
this.reloadJei = reloadJei;
18+
}
19+
920
@Override
10-
public void encode(PacketBuffer buf) {}
21+
public void encode(PacketBuffer buf) {
22+
buf.writeBoolean(this.reloadJei);
23+
}
1124

1225
@Override
13-
public void decode(PacketBuffer buf) {}
26+
public void decode(PacketBuffer buf) {
27+
this.reloadJei = buf.readBoolean();
28+
}
1429

1530
@Override
1631
public IPacket executeServer(NetHandlerPlayServer handler) {
17-
GSCommand.runReload(handler.player, handler.player.getServer());
32+
GSCommand.runReload(handler.player, handler.player.getServer(), ImmutableList.of());
1833
return null;
1934
}
2035
}

src/main/java/com/cleanroommc/groovyscript/network/SReloadScripts.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ public class SReloadScripts implements IPacket {
1616
private String packmode;
1717
private boolean changePackmode;
1818
private boolean reloadJei;
19+
private boolean recipesOnly;
1920

2021
public SReloadScripts() {}
2122

22-
public SReloadScripts(String packmode, boolean changePackmode, boolean reloadJei) {
23+
public SReloadScripts(String packmode, boolean changePackmode, boolean reloadJei, boolean recipesOnly) {
2324
this.packmode = packmode;
2425
this.changePackmode = changePackmode;
2526
this.reloadJei = reloadJei;
27+
this.recipesOnly = recipesOnly;
2628
}
2729

2830
@Override
@@ -35,6 +37,7 @@ public void encode(PacketBuffer buf) {
3537
}
3638
}
3739
buf.writeBoolean(this.reloadJei);
40+
buf.writeBoolean(this.recipesOnly);
3841
}
3942

4043
@Override
@@ -44,6 +47,7 @@ public void decode(PacketBuffer buf) {
4447
this.packmode = buf.readBoolean() ? null : buf.readString(128);
4548
}
4649
this.reloadJei = buf.readBoolean();
50+
this.recipesOnly = buf.readBoolean();
4751
}
4852

4953
@Override
@@ -52,7 +56,7 @@ public IPacket executeClient(NetHandlerPlayClient handler) {
5256
updatePackmode(Minecraft.getMinecraft().player, this.packmode);
5357
}
5458
if (this.reloadJei) {
55-
ReloadableRegistryManager.reloadJei(!this.changePackmode);
59+
ReloadableRegistryManager.reloadJei(!this.changePackmode, this.recipesOnly);
5660
if (this.changePackmode) {
5761
Minecraft.getMinecraft().player.sendMessage(new TextComponentString("Finished updating packmode and JEI. Enjoy :)"));
5862
}

src/main/java/com/cleanroommc/groovyscript/registry/ReloadableRegistryManager.java

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,19 @@
99
import com.cleanroommc.groovyscript.compat.mods.GroovyPropertyContainer;
1010
import com.cleanroommc.groovyscript.compat.mods.ModSupport;
1111
import com.cleanroommc.groovyscript.core.mixin.jei.JeiProxyAccessor;
12+
import com.cleanroommc.groovyscript.helper.StyleConstant;
1213
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
1314
import mezz.jei.Internal;
1415
import mezz.jei.JustEnoughItems;
16+
import mezz.jei.gui.textures.Textures;
1517
import mezz.jei.ingredients.IngredientFilter;
1618
import net.minecraft.client.Minecraft;
1719
import net.minecraft.item.crafting.IRecipe;
1820
import net.minecraft.util.ResourceLocation;
21+
import net.minecraft.util.text.ITextComponent;
1922
import net.minecraft.util.text.TextComponentString;
23+
import net.minecraft.util.text.event.ClickEvent;
24+
import net.minecraft.util.text.event.HoverEvent;
2025
import net.minecraftforge.fml.common.Loader;
2126
import net.minecraftforge.fml.common.registry.ForgeRegistries;
2227
import net.minecraftforge.fml.relauncher.Side;
@@ -137,11 +142,15 @@ public static boolean hasNonDummyRecipe(ResourceLocation rl) {
137142
}
138143

139144
/**
140-
* Reloads JEI completely. Is called after groovy scripts are ran.
145+
* Reloads JEI, called after groovy scripts are ran.
146+
* <p>
147+
* Attempt to use a "load" method added by HEI which offers improved
148+
* performance by allowing just recipes to be reloaded.
149+
* Falls back to restarting JEI entirely if the method fails.
141150
*/
142151
@ApiStatus.Internal
143152
@SideOnly(Side.CLIENT)
144-
public static void reloadJei(boolean msgPlayer) {
153+
public static void reloadJei(boolean msgPlayer, boolean recipesOnly) {
145154
if (ModSupport.JEI.isLoaded()) {
146155
JeiProxyAccessor jeiProxy = (JeiProxyAccessor) JustEnoughItems.getProxy();
147156
long time = System.currentTimeMillis();
@@ -153,11 +162,17 @@ public static void reloadJei(boolean msgPlayer) {
153162
if (plugin instanceof JEISonarPlugin jeiSonarPlugin) jeiSonarPlugin.providers.clear();
154163
});
155164
}
165+
boolean isHei = false;
156166

157-
jeiProxy.getStarter().start(jeiProxy.getPlugins(), jeiProxy.getTextures());
167+
try {
168+
jeiProxy.getStarter().getClass().getDeclaredMethod("load", List.class, Textures.class, boolean.class).invoke(jeiProxy.getStarter(), jeiProxy.getPlugins(), jeiProxy.getTextures(), recipesOnly);
169+
isHei = true;
170+
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ignored) {
171+
jeiProxy.getStarter().start(jeiProxy.getPlugins(), jeiProxy.getTextures());
172+
}
158173
time = System.currentTimeMillis() - time;
159174
if (msgPlayer) {
160-
Minecraft.getMinecraft().player.sendMessage(new TextComponentString("Reloading JEI took " + time + "ms"));
175+
Minecraft.getMinecraft().player.sendMessage(getReloadMessage(isHei, recipesOnly, time));
161176
}
162177

163178
// Fix: HEI Removals Disappearing on Reload
@@ -173,6 +188,28 @@ public static void reloadJei(boolean msgPlayer) {
173188
}
174189
}
175190

191+
private static ITextComponent getReloadMessage(boolean isHei, boolean recipesOnly, long time) {
192+
var name = isHei ? "HEI" : "JEI";
193+
var recipes = new TextComponentString("recipes").setStyle(
194+
StyleConstant.getTipStyle()
195+
.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/gs reload --entire-jei"))
196+
.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString("Only reloaded recipes - click to reload everything in " + name + "."))));
197+
var everythingStyle = StyleConstant.getTipStyle();
198+
if (isHei) {
199+
everythingStyle
200+
.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString("Reloaded everything in " + name + ".")));
201+
} else {
202+
everythingStyle
203+
.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.curseforge.com/minecraft/mc-mods/had-enough-items"))
204+
.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString("Reloaded everything in " + name + ". Click and install HEI to be able to reload only recipes for improved reload speed.")));
205+
}
206+
207+
return new TextComponentString("Reloading ")
208+
.appendSibling(isHei && recipesOnly ? recipes : new TextComponentString("everything").setStyle(everythingStyle))
209+
.appendSibling(new TextComponentString(" in " + name + " took "))
210+
.appendSibling(new TextComponentString(time + "ms").setStyle(StyleConstant.getEmphasisStyle()));
211+
}
212+
176213
protected static void reloadForgeRegistries(IForgeRegistry<?>... registries) {
177214
for (IForgeRegistry<?> registry : registries) {
178215
((IReloadableForgeRegistry<?>) registry).groovyScript$onReload();

0 commit comments

Comments
 (0)