Repository navigation
feat(middle-click): Add in GUI and in-world middle-click pick to set and reset channels #74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
044b77c
feat(Hologram): Middle-mouse Pick in GUI
AshVz ff90efa
feat(Hologram): Middle-mouse Pick in-world + bogo cancel + server-sid…
AshVz c2c5ae3
fix: commited dead code by accient, removed
AshVz 088f0f4
fix(Hologram): Apply review comments and clear add confirmation
AshVz f671313
Merge branch 'master' into feat/middle-click
Dream-Master 1c66d54
fix(missing file): Forgot to actually commit a file...
AshVz 3243d04
fix(deps): Remove bogo deps
AshVz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
src/main/java/com/gtnewhorizon/structurelib/ChannelPickHandler.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| package com.gtnewhorizon.structurelib; | ||
|
|
||
| import java.util.Collection; | ||
| import java.util.Map; | ||
|
|
||
| import javax.annotation.Nullable; | ||
|
|
||
| import net.minecraft.block.Block; | ||
| import net.minecraft.entity.player.EntityPlayer; | ||
| import net.minecraft.entity.player.EntityPlayerMP; | ||
| import net.minecraft.item.ItemStack; | ||
| import net.minecraft.util.ChatComponentTranslation; | ||
| import net.minecraft.util.MovingObjectPosition; | ||
| import net.minecraft.world.World; | ||
|
|
||
| import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor; | ||
| import com.gtnewhorizon.structurelib.net.SetChannelDataMessage; | ||
|
|
||
| /** | ||
| * Handler for middle-click channel picking. When the player holds a hologram projector on the cursor and middle-clicks | ||
| * a registered indicator item, the corresponding channel is set on the projector. The same applies in world when the | ||
| * projector is held in hand and a registered indicator block is middle-clicked. Shift+middle-click wipes all channels. | ||
| * Was made side neutral to support server-side validation at some point if necessary. | ||
| */ | ||
| public final class ChannelPickHandler { | ||
|
|
||
| private ChannelPickHandler() {} | ||
|
|
||
| /** | ||
| * Handle a middle-click event while holding a hologram projector on the cursor. | ||
| */ | ||
| public static boolean handleMiddleClick(EntityPlayer player, ItemStack holoStack, @Nullable ItemStack targetStack, | ||
| final boolean isSneaking) { | ||
| return handlePick(player, holoStack, targetStack, isSneaking, true); | ||
| } | ||
|
|
||
| public static boolean handleWorldPick(World world, EntityPlayer player, ItemStack holoStack, | ||
| @Nullable MovingObjectPosition hit, final boolean isSneaking) { | ||
| ItemStack targetStack = null; | ||
|
|
||
| if (hit != null) { | ||
| Block block = world.getBlock(hit.blockX, hit.blockY, hit.blockZ); | ||
| if (!block.isAir(world, hit.blockX, hit.blockY, hit.blockZ)) { | ||
| targetStack = block.getPickBlock(hit, world, hit.blockX, hit.blockY, hit.blockZ, player); | ||
| } | ||
| } | ||
|
|
||
| // A null target still goes through so that shift+middle-click wipes even when aiming at nothing | ||
| return handlePick(player, holoStack, targetStack, isSneaking, false); | ||
| } | ||
|
|
||
| private static boolean handlePick(EntityPlayer player, ItemStack holoStack, @Nullable ItemStack targetStack, | ||
| final boolean isSneaking, final boolean onCursor) { | ||
| // Clear channels on shift+middle-click. The "press again to confirm" gesture is gated client-side | ||
| // (see ChannelWipeConfirmation) before this method is ever called. | ||
| if (isSneaking) { | ||
| ChannelDataAccessor.wipeChannelData(holoStack); | ||
| sendChannelData(player, holoStack, onCursor); | ||
| player.addChatMessage(new ChatComponentTranslation("structurelib.pickchannel.cleared")); | ||
| return true; | ||
| } | ||
|
|
||
| if (targetStack == null) return false; // nothing hovered, cancel silently | ||
|
|
||
| Collection<Map.Entry<String, Integer>> channels = ChannelDescription.iterate(targetStack); | ||
| if (channels.isEmpty()) { | ||
| player.addChatMessage(new ChatComponentTranslation("structurelib.pickchannel.nomapping")); | ||
| return false; | ||
| } | ||
|
|
||
| // Assuming there's only 1 channel per item for now (same behavior as drag and drop) | ||
| Map.Entry<String, Integer> first = channels.iterator().next(); | ||
| ChannelDataAccessor.setChannelData(holoStack, first.getKey(), first.getValue()); | ||
| sendChannelData(player, holoStack, onCursor); | ||
| player.addChatMessage( | ||
| new ChatComponentTranslation("structurelib.pickchannel.success", first.getKey(), first.getValue())); | ||
| return true; | ||
| } | ||
|
|
||
| /** | ||
| * Player is the one triggering this update, so should already be in-sync. | ||
| */ | ||
| private static void sendChannelData(EntityPlayer player, ItemStack holoStack, boolean onCursor) { | ||
| if (!(player instanceof EntityPlayerMP)) { | ||
| StructureLib.net.sendToServer(new SetChannelDataMessage(holoStack, onCursor)); | ||
| } | ||
| } | ||
| } | ||
33 changes: 33 additions & 0 deletions
33
src/main/java/com/gtnewhorizon/structurelib/ChannelWipeConfirmation.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.gtnewhorizon.structurelib; | ||
|
|
||
| import net.minecraft.client.Minecraft; | ||
| import net.minecraft.entity.player.EntityPlayer; | ||
| import net.minecraft.util.ChatComponentTranslation; | ||
|
|
||
| /** | ||
| * Client-side-only confirmation gate for "wipe all channels" shift+middle-click gesture. | ||
| */ | ||
| public final class ChannelWipeConfirmation { | ||
|
|
||
| private static final long CONFIRM_WINDOW_MS = 5000; | ||
| private static long armedAtMs = -1; | ||
|
|
||
| private ChannelWipeConfirmation() {} | ||
|
|
||
| /** | ||
| * Call this before invoking {@link ChannelPickHandler} whenever the wipe gesture (shift+middle-click) is detected. | ||
| * | ||
| * @return true if this is a confirming second press within the window and the wipe should proceed now; false if | ||
| * this press only armed the confirmation. | ||
| */ | ||
| public static boolean confirm(EntityPlayer player) { | ||
| long now = Minecraft.getSystemTime(); | ||
| if (now - armedAtMs > CONFIRM_WINDOW_MS) { | ||
| armedAtMs = now; | ||
| player.addChatMessage(new ChatComponentTranslation("structurelib.pickchannel.confirmwipe")); | ||
| return false; | ||
| } | ||
| armedAtMs = -1; | ||
| return true; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
src/main/java/com/gtnewhorizon/structurelib/mixins/early/MixinGuiContainer_PickChannel.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| package com.gtnewhorizon.structurelib.mixins.early; | ||
|
|
||
| import net.minecraft.client.Minecraft; | ||
| import net.minecraft.client.gui.GuiScreen; | ||
| import net.minecraft.client.gui.inventory.GuiContainer; | ||
| import net.minecraft.entity.player.EntityPlayer; | ||
| import net.minecraft.inventory.Slot; | ||
| import net.minecraft.item.ItemStack; | ||
|
|
||
| import org.spongepowered.asm.mixin.Mixin; | ||
| import org.spongepowered.asm.mixin.gen.Invoker; | ||
| import org.spongepowered.asm.mixin.injection.At; | ||
| import org.spongepowered.asm.mixin.injection.Inject; | ||
| import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; | ||
|
|
||
| import com.gtnewhorizon.structurelib.ChannelPickHandler; | ||
| import com.gtnewhorizon.structurelib.ChannelWipeConfirmation; | ||
| import com.gtnewhorizon.structurelib.StructureLib; | ||
| import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger; | ||
|
|
||
| import codechicken.nei.NEIClientConfig; | ||
| import codechicken.nei.guihook.GuiContainerManager; | ||
| import cpw.mods.fml.common.Loader; | ||
|
|
||
| @Mixin(value = GuiContainer.class, priority = 100) | ||
| public abstract class MixinGuiContainer_PickChannel { | ||
|
|
||
| @Inject(method = "mouseClicked(III)V", at = @At("HEAD"), cancellable = true) | ||
| private void slib$onMouseClicked(int mouseX, int mouseY, int mouseButton, CallbackInfo ci) { | ||
| if (mouseButton != 2) return; | ||
|
|
||
| EntityPlayer player = Minecraft.getMinecraft().thePlayer; | ||
| if (player == null) return; | ||
|
|
||
| ItemStack cursorStack = player.inventory.getItemStack(); | ||
| if (cursorStack == null || !(cursorStack.getItem() instanceof ItemConstructableTrigger)) return; | ||
|
|
||
| // Sink middle click as soon as projector is picked up | ||
| ci.cancel(); | ||
|
|
||
| ItemStack hoveredStack = null; | ||
| try { | ||
| Slot slot = slib$invokeGetSlotAtPosition(mouseX, mouseY); | ||
| if (slot != null) { | ||
| hoveredStack = slot.getStack(); | ||
| } | ||
|
|
||
| // try NEI | ||
| if (hoveredStack == null && Loader.isModLoaded("NotEnoughItems") && !NEIClientConfig.isHidden()) { | ||
| hoveredStack = GuiContainerManager.getStackMouseOver((GuiContainer) (Object) this); | ||
| } | ||
| } catch (Exception e) { | ||
| StructureLib.LOGGER.error("Error while resolving hovered slot for channel pick", e); | ||
| } | ||
|
|
||
| boolean isSneaking = GuiScreen.isShiftKeyDown(); | ||
| if (isSneaking && !ChannelWipeConfirmation.confirm(player)) return; | ||
|
|
||
| ChannelPickHandler.handleMiddleClick(player, cursorStack, hoveredStack, isSneaking); | ||
| } | ||
|
|
||
| @Invoker("getSlotAtPosition") | ||
| protected abstract Slot slib$invokeGetSlotAtPosition(int x, int y); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.