Jump to content

Updating Forge MouseEvent and Hooks


ProtoZero

Recommended Posts

I am currently working on a mod that adds Touch Screen support to Minecraft (and any other mod, really). I am developing in 1.6.4 using Forge. Actually, my mod is finished, outside of the fact that it doesn't work because of the useless Forge MouseEvent.

 

The only thing required for my mod to work as intended is for me to be able to read in all MouseEvents and input, interpret it, and pass it along (or not) to Minecraft. I originally planned to register for MouseEvents, make sure no clicks happened on any buttons I care about, etc, and then pass in modified input values with something like:

 

mouseEvent.setX(int x), mouseEvent.setY(int y), etc.

 

However, MouseEvents only have getters, not setters. OK, I thought. I'll just use the getters, interpret it, cancel the mouse event, and make a new one, using values I want! Well, that doesn't work either.

 

Minecraft makes several references to lwjgl.Mouse to get its .x, .y .dX, .dY, etc directly, rather than going through MouseEvent. So, even if I cancel all mouse events, the mouse motion, clicks, drags, still cause player motion!!! You just can't left or right click in game. That's not very useful.

 

I propose an edit to Forge and the Base, in which we overload lwjgl.Mouse, and add getters and setters to it, and replace all lwjgl.Mouse calls in Minecraft and Forge Base Code with this subclassed lwjgl.Mouse. It would fix my problems, and add more control for future modders using MinecraftForge. Since the goal of my project is to add universal touchscreen support to Minecraft and its mods, a base edit is out of the question, and this is the only way. I have the code ready to go, but not the authority to add it to Forge. If there is a better place or way to handle this, I'm open to it as well.

Link to comment
Share on other sites

So, you're wanting us to replace {from a quick search} over 100 instances in the MC code to our wrapper, Not to mention the fact that Mouse is a static class, NOT a Object we can override.

I've seen touch screen done before, pretty sure MC has support for it natvly.

However, what you COULD do, is reflectivly set things, or write a coremod that override the lwjgl classes.

Not to mention the MouseEvent is designed as a PASSIVE event. Just because it has a reference to those values doesn't mean changing those values would actually do anything.

But I fail to see the reason you're needing to do this precisely?

I advise you do a bit of research get your hands into exactly whats going on. Rahter then what you THINK is going on.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

MC has a 'touchscreen mode' but feel free to turn that on and see what it gets you: Only support for clicking menu buttons; you still need mouse and keyboard to play the game.

 

I'm not familiar with coremods, considering this is my first mod. Perhaps since you know so much, you can set me straight, I thought that anything I wrote that didn't use the Forge API was considered a huge foul and would break compatibility. Hence my coming to this forum, suggesting that the MouseEvent actually cancel mouse input to the display, as the MouseEvent.isCancelled(boolean) method seemed to imply. If you have any great sources I would absolutely read them, I'm a very capable developer, and am not afraid to get my hands dirty. Just keep in mind, my goal is to make my mod usable with others, so anything that breaks compatibility is a no go for my project.

Link to comment
Share on other sites

I never advocate breaking compatibility, however, CoreMods are a construct in FML to allow modders to do specialized edits to the internal MC code HOPEFULLY keeping the best compatibility {unless you do something retarded}

However the more I look into it the more I se that core mods arnt needed.

Also, canceling the vent prevents Minecaft from processing it. And just moves on to the next Mouse event.

How is that confusing? Also all of our sources are open so you can easily verify for yourself what it does.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

Well, if you feel core mods aren't necessary, I'd happily take your advice, as I've been reading your source for three days now, and haven't found or thought of a way to avoid MC source edits (which now I understand can be accomplished with core mod, thank you for that clarification). I've read several places where coremods are frowned upon, and it must be what you are insinuating, that it's not necessary.

 

I have registered for MouseEvents, and RenderOverlayEvents, I draw my overlay of controls, and on MouseEvents, I try to detect if my buttons are being clicked or not, among other things. Before all this runs, I set mc.inGameFocus to false to free the mouse to click anywhere but mc.displayWidth /2 and mc.displayHeight/2, but any time a click occurs, the mouse cursor is moved to screen center and nothing registers, as expected. Interestingly enough, if you click and drag quickly, you can change your view substantially from the player perspective. I attribute this to the lwjgl.Mouse calls in the MC code that I have read into substantially.

 

If you feel a core mod is not necessary, what classes should I be looking into using, or reading into? Are there any projects or tutorials I should be looking at to avoid a core mod?

Link to comment
Share on other sites

So, what EXACTLY are you trying to do? Be as thorough as possible, Screen shots, annotations all good.

You should ALWAYS be as through as possible when thinking through ideas. Base edits are a LAST resort, if you're just intercepting some mouse clicks, then it's easy to do.

Remember, how 3D games work.

The mouse is ALWAYS in the center of the screen when looking in the world. If it moves, then the camera adjusts around it to bring it back into the center.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Link to comment
Share on other sites

I can't seem to attach files or embed code using the forum, so here is a dropbox link to my source: https://www.dropbox.com/s/i9qjb7jav64f3dw/touchcraft.zip

 

I am trying to capture the mouse clicks and coordinates to pass into my mod class, which checks if the clicks and coordinates coincide with any on screen inputs that I have drawn. If the answer is true for any of these, they trigger a method that will use a Robot to virtually press the keys or move the mouse. This isn't working, however, and it seems to be because Minecraft is calling up the lwjgl.Mouse for raw input rather than using the MouseEvents that I am cancelling after verifying that they can be used. I wish that I could properly embed code, but I will post some raw code to try and demonstrate the process.

 

/* This is the relevant code in my InputOverlay class, which is called up in my basemod after setting everything up with proxies and whatnot

@ForgeSubscribe(priority = EventPriority.NORMAL)

public void onMouseEvent(MouseEvent event) {

//free the mouse! this is step one

//something is resetting the mouse pos though to window center

mc.setIngameNotInFocus();

 

// Determine where click or touch occurred and if input needs consumed

 

if (isMouseEventConsumed(event)) {

event.setCanceled(true);

} else return;

}

 

@ForgeSubscribe

private boolean isMouseEventConsumed(MouseEvent event) {

boolean result = false;

 

for (int i = 0; i < inputs.size(); i++) {

if (inputs.get(i).consumes(event)) {

result = true;

}

}

return result;

}

 

/* here is my joystick class, a subclass of my input class, to demonstrate how I am handling the event

package touchcraft;

 

import java.awt.event.KeyEvent;

 

import net.minecraftforge.client.event.MouseEvent;

 

public class Joystick extends Input implements Drawable {

 

boolean keyDown[] = new boolean[4];

 

public Joystick(int x, int y, float r) {

super(x, y, r);

for(int i = 0; i < keyDown.length; i++) {

keyDown = false;

}

// TODO Auto-generated constructor stub

}

 

/*

    * The goal is to have an analogue joystick map the wasd keys in MC

    * There are 8 options, each 45 degrees wide radially

    * 8 way dpad

    * w,a,s,d,wa,wd,as,ds

    */

private final double JOYSTICK_ANGLE_SCALAR = 1.5;  // scalar is for dual inputs: 1-2

private final int W = 90, A = 180, S = 270, D = 0; // Angles for keys

private final int keyCode[] = {KeyEvent.VK_W, KeyEvent.VK_A, KeyEvent.VK_S, KeyEvent.VK_D}; //int codes for wasd

 

public void joystickEvent(int x, int y) {

    //calculate the angle for motion vector

        double theta = Math.atan2(y - originY, x - originX);

        theta *= 180 / Math.PI;

 

        if(theta < ( W + (W * JOYSTICK_ANGLE_SCALAR)) && theta > (W - (45 * JOYSTICK_ANGLE_SCALAR)))

        {

            Input.keyDown(keyCode[0]);

            keyDown[0] = true;

        }

        else if(keyDown[0]) Input.keyUp(keyCode[0]);

       

        if (theta < (S + S * JOYSTICK_ANGLE_SCALAR) && theta > (S - 45 * JOYSTICK_ANGLE_SCALAR))

        {

        Input.keyDown(keyCode[1]);

        keyDown[1] = true;

        }

        else if(keyDown[1]) Input.keyUp(keyCode[1]);

       

        if(theta < ( A + (A * JOYSTICK_ANGLE_SCALAR)) && theta > (A - (45 * JOYSTICK_ANGLE_SCALAR)))

        {

        Input.keyDown(keyCode[2]);

        keyDown[2] = true;

        }

        else if(keyDown[2]) Input.keyUp(keyCode[2]);

       

        if(theta < ( D + (D * JOYSTICK_ANGLE_SCALAR)) && theta > (D - (45 * JOYSTICK_ANGLE_SCALAR)))

        {

        Input.keyDown(keyCode[3]);

        keyDown[3] = true;

        }

        else if(keyDown[3]) Input.keyUp(keyCode[3]);

    }

 

public boolean consumes(MouseEvent event) {

if((event.x - originX)*(event.x - originX) + (event.y - originY)*(event.y - originY) < radius * radius && event.buttonstate)

{

joystickEvent(event.x, event.y);

return true;

} else return false;

}

 

public void draw() {

super.draw();

}

}

 

My goal was to cancel the mouse events and create new ones with the 'fake' values that I wanted Minecraft to actually act on. I want to intercept Mouse input to convert it into keyboard and mouse key presses to replace the traditional keyboard and mouse input methods with my on screen ones. If you download the source zip from my dropbox, you can see exactly what I'm talking about. Keep in mind, nothing will work unless you enable Touch Screen mode in your Minecraft settings however.

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.