diff --git a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java index 098933221..436f80ccd 100644 --- a/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java +++ b/src/main/java/com/cleanroommc/groovyscript/GroovyScript.java @@ -15,11 +15,10 @@ import com.cleanroommc.groovyscript.event.EventHandler; import com.cleanroommc.groovyscript.helper.JsonHelper; import com.cleanroommc.groovyscript.helper.StyleConstant; +import com.cleanroommc.groovyscript.keybinds.GroovyScriptKeybinds; import com.cleanroommc.groovyscript.mapper.AbstractObjectMapper; import com.cleanroommc.groovyscript.mapper.ObjectMapperManager; -import com.cleanroommc.groovyscript.network.CReload; import com.cleanroommc.groovyscript.network.NetworkHandler; -import com.cleanroommc.groovyscript.network.NetworkUtils; import com.cleanroommc.groovyscript.registry.ReloadableRegistryManager; import com.cleanroommc.groovyscript.sandbox.*; import com.cleanroommc.groovyscript.sandbox.mapper.GroovyDeobfMapper; @@ -30,19 +29,15 @@ import groovy.lang.GroovySystem; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.settings.KeyBinding; import net.minecraft.command.ICommandSender; import net.minecraft.item.Item; import net.minecraft.util.text.Style; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextFormatting; -import net.minecraftforge.client.settings.KeyConflictContext; -import net.minecraftforge.client.settings.KeyModifier; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fluids.FluidRegistry; -import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Loader; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.ModContainer; @@ -52,14 +47,14 @@ import net.minecraftforge.fml.common.event.FMLServerStartingEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.InputEvent; import net.minecraftforge.fml.relauncher.FMLInjectionData; import net.minecraftforge.fml.relauncher.FMLLaunchHandler; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -import org.lwjgl.input.Keyboard; import java.io.File; import java.io.IOException; @@ -94,9 +89,6 @@ public class GroovyScript { private static ModContainer scriptMod; private static Thread languageServerThread; - private static KeyBinding reloadKey; - private static long timeSinceLastUse; - public static final Random RND = new Random(); @Mod.EventHandler @@ -116,21 +108,28 @@ public void onConstruction(FMLConstructionEvent event) { GroovyScript.sandbox = new GroovyScriptSandbox(); ModSupport.INSTANCE.setup(event.getASMHarvestedData()); - if (NetworkUtils.isDedicatedClient()) { - // this resource pack must be added in construction - ((DefaultResourcePackAccessor) Minecraft.getMinecraft()).get().add(new GroovyResourcePack()); - reloadKey = new KeyBinding("key.groovyscript.reload", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, Keyboard.KEY_R, "key.categories.groovyscript"); - ClientRegistry.registerKeyBinding(reloadKey); - } - FluidRegistry.enableUniversalBucket(); getRunConfig().initPackmode(); } + @Mod.EventHandler + @SideOnly(Side.CLIENT) + public void onClientConstruction(FMLConstructionEvent event) { + MinecraftForge.EVENT_BUS.register(GroovyScriptKeybinds.class); + // this resource pack must be added in construction + ((DefaultResourcePackAccessor) Minecraft.getMinecraft()).get().add(new GroovyResourcePack()); + } + @Mod.EventHandler public void onInit(FMLInitializationEvent event) { if (ModSupport.TINKERS_CONSTRUCT.isLoaded()) TinkersConstruct.init(); - if (event.getSide().isClient() && Boolean.parseBoolean(System.getProperty("groovyscript.run_ls"))) { + } + + @Mod.EventHandler + @SideOnly(Side.CLIENT) + public void onClientInit(FMLInitializationEvent event) { + GroovyScriptKeybinds.initialize(); + if (Boolean.parseBoolean(System.getProperty("groovyscript.run_ls"))) { runLanguageServer(); } } @@ -194,15 +193,6 @@ public void onServerLoad(FMLServerStartingEvent event) { VanillaModule.INSTANCE.command.onStartServer(event.getServer()); } - @SubscribeEvent - public static void onInput(InputEvent.KeyInputEvent event) { - long time = Minecraft.getSystemTime(); - if (Minecraft.getMinecraft().isIntegratedServerRunning() && reloadKey.isPressed() && time - timeSinceLastUse >= 1000 && Minecraft.getMinecraft().player.getPermissionLevel() >= 4) { - NetworkHandler.sendToServer(new CReload()); - timeSinceLastUse = time; - } - } - public static @NotNull String getScriptPath() { return getScriptFile().getPath(); } diff --git a/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserPackage.java b/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserPackage.java index d7832bb6c..4ca760f4d 100644 --- a/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserPackage.java +++ b/src/main/java/com/cleanroommc/groovyscript/api/infocommand/InfoParserPackage.java @@ -1,15 +1,18 @@ package com.cleanroommc.groovyscript.api.infocommand; +import com.cleanroommc.groovyscript.event.GsHandEvent; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; +import net.minecraftforge.common.MinecraftForge; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -103,6 +106,10 @@ public InfoParserPackage( public void setStack(@NotNull ItemStack stack) { this.stack = stack; + if (!stack.isEmpty() && stack.getItem() instanceof ItemBlock itemBlock) { + setBlock(itemBlock.getBlock()); + setBlockState(itemBlock.getBlock().getStateFromMeta(stack.getMetadata())); + } } public boolean isPrettyNbt() { @@ -165,6 +172,8 @@ public void parse() { } public void parse(boolean enabled) { + MinecraftForge.EVENT_BUS.post(new GsHandEvent(this)); + InfoParserRegistry.getInfoParsers().forEach(x -> x.parse(this, enabled)); } } diff --git a/src/main/java/com/cleanroommc/groovyscript/command/BaseInfoCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/BaseInfoCommand.java index 25843eb1f..15723f02b 100644 --- a/src/main/java/com/cleanroommc/groovyscript/command/BaseInfoCommand.java +++ b/src/main/java/com/cleanroommc/groovyscript/command/BaseInfoCommand.java @@ -2,22 +2,14 @@ import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; import com.cleanroommc.groovyscript.api.infocommand.InfoParserRegistry; -import com.cleanroommc.groovyscript.event.GsHandEvent; import com.cleanroommc.groovyscript.helper.StyleConstant; -import com.google.common.base.Predicates; import net.minecraft.command.CommandBase; import net.minecraft.command.ICommandSender; -import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.EntitySelectors; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; -import net.minecraftforge.common.MinecraftForge; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,56 +20,6 @@ public abstract class BaseInfoCommand extends CommandBase { - /** - * gets the block being looked at, stopping on fluid blocks - */ - protected static BlockPos getBlockLookingAt(EntityPlayer player) { - double distance = player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue(); - Vec3d eyes = player.getPositionEyes(0.0F); - Vec3d look = player.getLook(0.0F); - Vec3d end = eyes.add(look.x * distance, look.y * distance, look.z * distance); - - RayTraceResult result = player.getEntityWorld().rayTraceBlocks(eyes, end, true); - if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) { - return result.getBlockPos(); - } - return null; - } - - /** - * gets the closest entity being looked at - */ - protected static Entity getEntityLookingAt(EntityPlayer player) { - Entity entity = null; - double d0 = 0.0D; - - double distance = player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue(); - Vec3d eyes = player.getPositionEyes(0.0F); - Vec3d look = player.getLook(0.0F); - Vec3d end = eyes.add(look.x * distance, look.y * distance, look.z * distance); - - List list = player.world.getEntitiesInAABBexcluding( - player, - player.getEntityBoundingBox() - .expand(look.x * distance, look.y * distance, look.z * distance) - .grow(1.0D, 1.0D, 1.0D), - Predicates.and(EntitySelectors.NOT_SPECTATING, e -> e != null && e.canBeCollidedWith())); - - for (Entity entity1 : list) { - AxisAlignedBB axisalignedbb = entity1.getEntityBoundingBox().grow(0.3); - RayTraceResult raytraceresult = axisalignedbb.calculateIntercept(eyes, end); - - if (raytraceresult != null) { - double d1 = eyes.squareDistanceTo(raytraceresult.hitVec); - if (d1 < d0 || d0 == 0.0D) { - entity = entity1; - d0 = d1; - } - } - } - return entity; - } - @Override public @NotNull String getUsage(@NotNull ICommandSender sender) { return String.format( @@ -141,9 +83,6 @@ public void execute(@NotNull MinecraftServer server, @NotNull ICommandSender sen // add different data to the info parser depending on the command being used gatherInfo(info, player); - GsHandEvent event = new GsHandEvent(info); - MinecraftForge.EVENT_BUS.post(event); - info.parse(enabled); print(player, messages, argList); } diff --git a/src/main/java/com/cleanroommc/groovyscript/command/InfoHandCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/InfoHandCommand.java index e9da3d386..0c82a3204 100644 --- a/src/main/java/com/cleanroommc/groovyscript/command/InfoHandCommand.java +++ b/src/main/java/com/cleanroommc/groovyscript/command/InfoHandCommand.java @@ -2,7 +2,6 @@ import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemBlock; import net.minecraft.util.EnumHand; import org.jetbrains.annotations.NotNull; @@ -22,10 +21,5 @@ protected String targetDescription() { void gatherInfo(InfoParserPackage info, EntityPlayer player) { info.setStack(player.getHeldItem(EnumHand.MAIN_HAND)); if (info.getStack().isEmpty()) info.setStack(player.getHeldItem(EnumHand.OFF_HAND)); - - if (info.getStack().getItem() instanceof ItemBlock itemBlock) { - info.setBlock(itemBlock.getBlock()); - info.setBlockState(itemBlock.getBlock().getStateFromMeta(info.getStack().getMetadata())); - } } } diff --git a/src/main/java/com/cleanroommc/groovyscript/command/InfoInfoCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/InfoInfoCommand.java index c4d910632..2f2d8b7ad 100644 --- a/src/main/java/com/cleanroommc/groovyscript/command/InfoInfoCommand.java +++ b/src/main/java/com/cleanroommc/groovyscript/command/InfoInfoCommand.java @@ -1,8 +1,8 @@ package com.cleanroommc.groovyscript.command; import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.RayTracingHelper; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemBlock; import net.minecraft.util.EnumHand; import org.jetbrains.annotations.NotNull; @@ -26,16 +26,13 @@ void gatherInfo(InfoParserPackage info, EntityPlayer player) { // if there's nothing in the player's hands, get the entity being looked at and then the block position // because entity should be preferred if (info.getStack().isEmpty()) { - info.setEntity(getEntityLookingAt(player)); + info.setEntity(RayTracingHelper.getEntityLookingAt(player)); if (info.getEntity() == null) { - info.copyFromPos(getBlockLookingAt(player)); + info.copyFromPos(RayTracingHelper.getBlockLookingAt(player)); if (info.getPos() == null) { info.setEntity(player); } } - } else if (info.getStack().getItem() instanceof ItemBlock itemBlock) { - info.setBlock(itemBlock.getBlock()); - info.setBlockState(itemBlock.getBlock().getStateFromMeta(info.getStack().getMetadata())); } } } diff --git a/src/main/java/com/cleanroommc/groovyscript/command/InfoLookingCommand.java b/src/main/java/com/cleanroommc/groovyscript/command/InfoLookingCommand.java index 349be774b..5667c3b7f 100644 --- a/src/main/java/com/cleanroommc/groovyscript/command/InfoLookingCommand.java +++ b/src/main/java/com/cleanroommc/groovyscript/command/InfoLookingCommand.java @@ -1,6 +1,7 @@ package com.cleanroommc.groovyscript.command; import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.helper.RayTracingHelper; import net.minecraft.entity.player.EntityPlayer; import org.jetbrains.annotations.NotNull; @@ -19,9 +20,9 @@ protected String targetDescription() { @Override void gatherInfo(InfoParserPackage info, EntityPlayer player) { // get the entity being looked at and then the block position because entity should be preferred - info.setEntity(getEntityLookingAt(player)); + info.setEntity(RayTracingHelper.getEntityLookingAt(player)); if (info.getEntity() == null) { - info.copyFromPos(getBlockLookingAt(player)); + info.copyFromPos(RayTracingHelper.getBlockLookingAt(player)); } } } diff --git a/src/main/java/com/cleanroommc/groovyscript/helper/RayTracingHelper.java b/src/main/java/com/cleanroommc/groovyscript/helper/RayTracingHelper.java new file mode 100644 index 000000000..f6abdee96 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/helper/RayTracingHelper.java @@ -0,0 +1,65 @@ +package com.cleanroommc.groovyscript.helper; + +import com.google.common.base.Predicates; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.EntitySelectors; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; + +import java.util.List; + +public class RayTracingHelper { + + /** + * gets the block being looked at, stopping on fluid blocks + */ + public static BlockPos getBlockLookingAt(EntityPlayer player) { + double distance = player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue(); + Vec3d eyes = player.getPositionEyes(0.0F); + Vec3d look = player.getLook(0.0F); + Vec3d end = eyes.add(look.x * distance, look.y * distance, look.z * distance); + + RayTraceResult result = player.getEntityWorld().rayTraceBlocks(eyes, end, true); + if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) { + return result.getBlockPos(); + } + return null; + } + + /** + * gets the closest entity being looked at + */ + public static Entity getEntityLookingAt(EntityPlayer player) { + Entity entity = null; + double d0 = 0.0D; + + double distance = player.getEntityAttribute(EntityPlayer.REACH_DISTANCE).getAttributeValue(); + Vec3d eyes = player.getPositionEyes(0.0F); + Vec3d look = player.getLook(0.0F); + Vec3d end = eyes.add(look.x * distance, look.y * distance, look.z * distance); + + List list = player.world.getEntitiesInAABBexcluding( + player, + player.getEntityBoundingBox() + .expand(look.x * distance, look.y * distance, look.z * distance) + .grow(1.0D, 1.0D, 1.0D), + Predicates.and(EntitySelectors.NOT_SPECTATING, e -> e != null && e.canBeCollidedWith())); + + for (Entity entity1 : list) { + AxisAlignedBB axisalignedbb = entity1.getEntityBoundingBox().grow(0.3); + RayTraceResult raytraceresult = axisalignedbb.calculateIntercept(eyes, end); + + if (raytraceresult != null) { + double d1 = eyes.squareDistanceTo(raytraceresult.hitVec); + if (d1 < d0 || d0 == 0.0D) { + entity = entity1; + d0 = d1; + } + } + } + return entity; + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/keybinds/CopyKey.java b/src/main/java/com/cleanroommc/groovyscript/keybinds/CopyKey.java new file mode 100644 index 000000000..93a7b4e44 --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/keybinds/CopyKey.java @@ -0,0 +1,99 @@ +package com.cleanroommc.groovyscript.keybinds; + +import com.cleanroommc.groovyscript.api.infocommand.InfoParserPackage; +import com.cleanroommc.groovyscript.compat.mods.ModSupport; +import com.cleanroommc.groovyscript.compat.mods.jei.JeiPlugin; +import com.cleanroommc.groovyscript.helper.RayTracingHelper; +import com.cleanroommc.groovyscript.helper.StyleConstant; +import com.google.common.collect.ImmutableList; +import mezz.jei.api.IRecipesGui; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentString; +import net.minecraftforge.client.settings.KeyModifier; +import org.lwjgl.input.Keyboard; + +import java.util.ArrayList; +import java.util.List; + +public class CopyKey extends GroovyScriptKeybinds.Key { + + private static final Minecraft mc = Minecraft.getMinecraft(); + + public CopyKey() { + super("copy", KeyModifier.CONTROL, Keyboard.KEY_C); + } + + public static CopyKey createKeybind() { + return new CopyKey(); + } + + private static void gatherInfo(InfoParserPackage info, EntityPlayer player) { + if (mc.inGameHasFocus) { + info.setStack(player.getHeldItem(EnumHand.MAIN_HAND)); + if (info.getStack().isEmpty()) info.setStack(player.getHeldItem(EnumHand.OFF_HAND)); + if (info.getStack().isEmpty()) { + info.setEntity(RayTracingHelper.getEntityLookingAt(player)); + if (info.getEntity() == null) { + info.copyFromPos(RayTracingHelper.getBlockLookingAt(player)); + if (info.getPos() == null) { + info.setEntity(player); + } + } + } + } else { + if (mc.currentScreen instanceof GuiContainer container && container.hoveredSlot != null) { + info.setStack(container.hoveredSlot.getStack()); + } + if (info.getStack().isEmpty() && ModSupport.JEI.isLoaded()) info.setStack(getJeiStack()); + } + } + + private static ItemStack getJeiStack() { + var entry = getJeiObject(); + if (entry == null) return ItemStack.EMPTY; + var type = JeiPlugin.itemRegistry.getIngredientType(entry); + return JeiPlugin.itemRegistry.getIngredientHelper(type).getCheatItemStack(entry); + } + + private static Object getJeiObject() { + if (mc.currentScreen instanceof IRecipesGui gui) { + var entry = gui.getIngredientUnderMouse(); + if (entry != null) return entry; + } + var entry = JeiPlugin.jeiRuntime.getBookmarkOverlay().getIngredientUnderMouse(); + if (entry != null) return entry; + return JeiPlugin.jeiRuntime.getIngredientListOverlay().getIngredientUnderMouse(); + } + + private static void print(EntityPlayer player, List messages) { + if (messages.isEmpty()) { + player.sendMessage(new TextComponentString("Couldn't find anything being focused!").setStyle(StyleConstant.getErrorStyle())); + } else { + // have a horizontal bar to improve readability when running multiple consecutive info hand commands + player.sendMessage(new TextComponentString("================================").setStyle(StyleConstant.getEmphasisStyle())); + messages.forEach(player::sendMessage); + } + } + + @Override + public boolean isValid() { + return mc.isIntegratedServerRunning(); + } + + // only runs if isIntegratedServerRunning() is true, so getIntegratedServer() cannot be null + @SuppressWarnings("DataFlowIssue") + @Override + public void runOperation() { + var player = mc.player; + List messages = new ArrayList<>(); + InfoParserPackage info = new InfoParserPackage(mc.getIntegratedServer(), player, ImmutableList.of("all"), messages, false); + gatherInfo(info, player); + info.parse(true); + print(player, messages); + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/keybinds/GroovyScriptKeybinds.java b/src/main/java/com/cleanroommc/groovyscript/keybinds/GroovyScriptKeybinds.java new file mode 100644 index 000000000..4b3cb4e5f --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/keybinds/GroovyScriptKeybinds.java @@ -0,0 +1,155 @@ +package com.cleanroommc.groovyscript.keybinds; + +import com.cleanroommc.groovyscript.GroovyScript; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.client.settings.IKeyConflictContext; +import net.minecraftforge.client.settings.KeyConflictContext; +import net.minecraftforge.client.settings.KeyModifier; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +import java.util.ArrayList; +import java.util.Collection; + +@SideOnly(Side.CLIENT) +public class GroovyScriptKeybinds { + + private static final String CATEGORY = "key.categories.groovyscript"; + private static final Collection KEYS = new ArrayList<>(); + + public static void initialize() { + addKey(ReloadKey.createKeybind()); + addKey(CopyKey.createKeybind()); + } + + private static void addKey(Key key) { + if (key != null) KEYS.add(key); + } + + @SubscribeEvent + public static void onKeyInput(InputEvent.KeyInputEvent event) { + for (Key key : KEYS) { + if (key.isPressed()) key.runOperation(); + } + } + + @SubscribeEvent + public static void onMouseInput(InputEvent.MouseInputEvent event) { + if (!Mouse.getEventButtonState()) return; // only activate on click, not on release or movement + for (Key key : KEYS) { + if (key.isPressed()) key.runOperation(); + } + } + + @SubscribeEvent + public static void onGuiKeyInput(GuiScreenEvent.KeyboardInputEvent.Post event) { + if (!Keyboard.getEventKeyState()) return; // only activate on press, not on release + char typedChar = Keyboard.getEventCharacter(); + int eventKey = Keyboard.getEventKey(); + + for (Key key : KEYS) { + if (key.isPressed(typedChar, eventKey)) { + key.runOperation(); + event.setCanceled(true); + return; + } + } + } + + @SubscribeEvent + public static void onGuiMouseInput(GuiScreenEvent.MouseInputEvent.Post event) { + if (!Mouse.getEventButtonState()) return; // only activate on click, not on release or movement + for (Key key : KEYS) { + if (key.isValid() && GameSettings.isKeyDown(key.getKey()) && key.getKey().getKeyConflictContext().isActive()) { + key.runOperation(); + event.setCanceled(true); + return; + } + } + } + + private static KeyBinding createKeybind(boolean setByDefault, Key key) { + var binding = setByDefault + ? new KeyBinding(key.getDescription(), key.getKeyConflictContext(), key.getKeyModifier(), key.getKeyCode(), CATEGORY) + : new KeyBinding(key.getDescription(), key.getKeyConflictContext(), KeyModifier.NONE, Keyboard.KEY_NONE, CATEGORY); + ClientRegistry.registerKeyBinding(binding); + return binding; + } + + public abstract static class Key { + + private final String name; + private final IKeyConflictContext keyConflictContext; + private final KeyModifier keyModifier; + private final int keyCode; + + private final KeyBinding key; + + public Key(String name, int keyCode) { + this(name, KeyConflictContext.UNIVERSAL, KeyModifier.NONE, keyCode); + } + + public Key(String name, IKeyConflictContext keyConflictContext, int keyCode) { + this(name, keyConflictContext, KeyModifier.NONE, keyCode); + } + + public Key(String name, KeyModifier keyModifier, int keyCode) { + this(name, KeyConflictContext.UNIVERSAL, keyModifier, keyCode); + } + + public Key(String name, IKeyConflictContext keyConflictContext, KeyModifier keyModifier, int keyCode) { + this.name = name; + this.keyConflictContext = keyConflictContext; + this.keyModifier = keyModifier; + this.keyCode = keyCode; + this.key = createKeybind(isSetByDefault(), this); + } + + protected boolean isSetByDefault() { + return GroovyScript.getRunConfig().isDebug(); + } + + public abstract boolean isValid(); + + public abstract void runOperation(); + + public String getName() { + return name; + } + + public IKeyConflictContext getKeyConflictContext() { + return keyConflictContext; + } + + public KeyModifier getKeyModifier() { + return keyModifier; + } + + public int getKeyCode() { + return keyCode; + } + + public KeyBinding getKey() { + return key; + } + + public boolean isPressed() { + return isValid() && key.isPressed() && key.getKeyConflictContext().isActive(); + } + + public boolean isPressed(char typedChar, int keyCode) { + return isValid() && key.isActiveAndMatches(keyCode); + } + + public String getDescription() { + return String.format("keybind.%s.%s", GroovyScript.ID, name); + } + } +} diff --git a/src/main/java/com/cleanroommc/groovyscript/keybinds/ReloadKey.java b/src/main/java/com/cleanroommc/groovyscript/keybinds/ReloadKey.java new file mode 100644 index 000000000..7767386bb --- /dev/null +++ b/src/main/java/com/cleanroommc/groovyscript/keybinds/ReloadKey.java @@ -0,0 +1,40 @@ +package com.cleanroommc.groovyscript.keybinds; + +import com.cleanroommc.groovyscript.network.CReload; +import com.cleanroommc.groovyscript.network.NetworkHandler; +import net.minecraft.client.Minecraft; +import net.minecraftforge.client.settings.KeyConflictContext; +import net.minecraftforge.client.settings.KeyModifier; +import org.lwjgl.input.Keyboard; + +public class ReloadKey extends GroovyScriptKeybinds.Key { + + private static final long INTERVAL = 1000L; + private static final int PERMISSION_LEVEL = 4; + + private static final Minecraft mc = Minecraft.getMinecraft(); + + private long timeSinceLastUse; + + public ReloadKey() { + super("reload", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, Keyboard.KEY_R); + } + + public static ReloadKey createKeybind() { + return new ReloadKey(); + } + + @Override + public boolean isValid() { + return mc.currentScreen == null && mc.inGameHasFocus; + } + + @Override + public void runOperation() { + long time = Minecraft.getSystemTime(); + if (mc.isIntegratedServerRunning() && time - timeSinceLastUse >= INTERVAL && mc.player.getPermissionLevel() >= PERMISSION_LEVEL) { + NetworkHandler.sendToServer(new CReload()); + timeSinceLastUse = time; + } + } +} diff --git a/src/main/resources/assets/groovyscript/lang/en_us.lang b/src/main/resources/assets/groovyscript/lang/en_us.lang index a437eb949..c87c74230 100644 --- a/src/main/resources/assets/groovyscript/lang/en_us.lang +++ b/src/main/resources/assets/groovyscript/lang/en_us.lang @@ -3,7 +3,8 @@ groovyscript.command.copy.copied_start=Copied [ groovyscript.command.copy.copied_end=] to the clipboard key.categories.groovyscript=GroovyScript -key.groovyscript.reload=Reload Scripts +keybind.groovyscript.reload=Reload Scripts +keybind.groovyscript.copy=Copy focused groovyscript.jei.category.groovyscript:fluid_recipe.name=In world fluid recipes groovyscript.jei.category.groovyscript:explosion.name=Explosion recipes