package speedytools.clientside.userinput; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; import net.minecraftforge.client.event.MouseEvent; import org.lwjgl.input.Keyboard; import java.util.LinkedList; import java.util.Queue; /** * User: The Grey Ghost * Date: 16/04/14 * UserInput collects the various input sources and collates them into a suitable form for the tools: * (1) provides a queue of events for mousewheel, mouse buttons up & down * (2) provides information on how long the mouse button has been up or held down * Usage: * (1) Create the UserInput * (2) .activate() it to start collating data * (3) call .handleMouseEvent whenever there is a mouseevent (for the wheel) * (4) call .updateButtonStates() periodically (eg every tick) to update the left and right button states, which * updates the queue and button hold statuses * (5) */ public class UserInput { public UserInput() { active = false; this.reset(); } /** * start collating input. */ public void activate() { if (active) return; active = true; reset(); } /** * stop collating input; */ public void deactivate() { if (!active) return; active = false; reset(); } /** * reset the data - empties the queue, clears the hold times */ public void reset() { inputEvents.clear(); leftButtonIsDown = false; rightButtonIsDown = false; leftButtonLastChangeTimeNS = 0; rightButtonLastChangeTimeNS = 0; } /** * handle the MouseEvent * @param event * @return true if event was handled by UserInput, false if it should be passed to vanilla */ public boolean handleMouseEvent(MouseEvent event) { if (!active) return false; if (event.dwheel == 0) return false; EntityPlayer player = Minecraft.getMinecraft().thePlayer; if (player == null) return false; boolean controlKeyDown = readControlKeyIsDown(); if (!controlKeyDown) return false; // final int MOUSE_DELTA_PER_STEP = 120; // appears to be mouse-dependent. // int stepCount = event.dwheel / MOUSE_DELTA_PER_STEP; // if (stepCount == 0) return false; int stepCount = (event.dwheel > 0) ? 1 : -1; inputEvents.add(new InputEvent(InputEventType.WHEEL_MOVE, event.nanoseconds, controlKeyDown, stepCount, 1)); return true; } /** * update the state of the left and right buttons * @param newLeftButtonIsDown * @param newRightButtonIsDown * @param timeStampNS */ public void updateButtonStates(boolean newLeftButtonIsDown, boolean newRightButtonIsDown, long timeStampNS) { // System.out.println("UserInput.updateButtonStates L = " + newLeftButtonIsDown + "; R = " + newRightButtonIsDown); if (!active) return; controlKeyIsDown = readControlKeyIsDown(); if (leftButtonLastChangeTimeNS == 0) { leftButtonLastChangeTimeNS = timeStampNS; } else if (newLeftButtonIsDown != this.leftButtonIsDown) { inputEvents.add(new InputEvent(newLeftButtonIsDown ? InputEventType.LEFT_CLICK_DOWN : InputEventType.LEFT_CLICK_UP, timeStampNS, controlKeyIsDown, 1, timeStampNS - leftButtonLastChangeTimeNS) ); leftButtonLastChangeTimeNS = timeStampNS; } this.leftButtonIsDown = newLeftButtonIsDown; // System.out.println("UserInput:" + rightButtonLastChangeTimeNS + " : " + newRightButtonIsDown + " : " + this.rightButtonIsDown); if (rightButtonLastChangeTimeNS == 0) { rightButtonLastChangeTimeNS = timeStampNS; } else if (newRightButtonIsDown != this.rightButtonIsDown) { inputEvents.add(new InputEvent(newRightButtonIsDown ? InputEventType.RIGHT_CLICK_DOWN : InputEventType.RIGHT_CLICK_UP, timeStampNS, controlKeyIsDown, 1, timeStampNS - rightButtonLastChangeTimeNS) ); rightButtonLastChangeTimeNS = timeStampNS; } this.rightButtonIsDown = newRightButtonIsDown; } /** returns the next event, without removing it from the queue * @return the next InputEvent, or null if none */ public InputEvent peek() { return inputEvents.peek(); } /** returns the next event, and removes it from the queue * @return the next InputEvent, or null if none */ public InputEvent poll() { return inputEvents.poll(); } /** * how long has the left button been in its current state? * @return hold time in ns. 0 = not valid, +ve = held down, -ve = up eg -1000 is "been up for 1000 ns." */ public long leftButtonHoldTimeNS(long timeNow) { if (leftButtonLastChangeTimeNS == 0) return 0; long holdDuration = timeNow - leftButtonLastChangeTimeNS; assert holdDuration >= 0; return leftButtonIsDown ? holdDuration : -holdDuration; } /** * how long has the left button been in its current state? * @return hold time in ns. +ve = held down, -ve = up eg -1000 is "been up for 1000 ns." */ public long rightButtonHoldTimeNS(long timeNow) { // System.out.println("UserInput.rightButtonHoldTimeNS rBLCTNS= " + rightButtonLastChangeTimeNS + "; rBID= " + rightButtonIsDown); // if (rightButtonLastChangeTimeNS == 0) return 0; long holdDuration = timeNow - rightButtonLastChangeTimeNS; assert holdDuration >= 0; return rightButtonIsDown ? holdDuration : -holdDuration; } public boolean isControlKeyDown() { return controlKeyIsDown; } public enum InputEventType { LEFT_CLICK_DOWN, RIGHT_CLICK_DOWN, LEFT_CLICK_UP, RIGHT_CLICK_UP, WHEEL_MOVE; } public static class InputEvent { public InputEventType eventType; public long eventTimeNS; // nanoseconds timestamp public boolean controlKeyDown; public int count; // might be negative for some eg mousewheel public long eventDuration; // nanoseconds that the previous state lasted for; // eg RIGHT_CLICK_UP with 200 ns means that the right button was held down for 200 ns. // 0 means can't tell / undefined public InputEvent(InputEventType i_inputEventType, long i_eventTimeNS, boolean i_controlKeyDown, int i_count, long i_eventDuration) { eventType = i_inputEventType; eventTimeNS = i_eventTimeNS; controlKeyDown = i_controlKeyDown; count = i_count; eventDuration = i_eventDuration; // System.out.println("InputEvent created: " + eventType.toString() + "; duration= " + eventDuration); // } } private boolean readControlKeyIsDown() { EntityPlayer player = Minecraft.getMinecraft().thePlayer; if (player == null) return false; return Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); } private boolean active; private Queue<InputEvent> inputEvents = new LinkedList<InputEvent>(); private boolean leftButtonIsDown; private boolean rightButtonIsDown; private boolean controlKeyIsDown; private long leftButtonLastChangeTimeNS; // 0 means not valid (no entry received yet) private long rightButtonLastChangeTimeNS; // 0 means not valid (no entry received yet) }