Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: [DFHack] [plugins] Forwarding external keystrokes to DF  (Read 2341 times)

jeancallisti

  • Bay Watcher
    • View Profile
[DFHack] [plugins] Forwarding external keystrokes to DF
« on: November 06, 2013, 09:08:56 am »

Imagine this : you created an external tool to DF (in your very own window, with your very own thread -- but still, using DFHack, and being properly intergrated with it, as a C++ plugin).

You want all keystrokes typed into your window to be forwarded to the DF window. How would you start with that?

Is there any plugin that already does it? I would then just have a look at the code (for example, stonesense, afaik, doesn't do it at all. Anything that happens in the stonesense window stays in the stonesense window).

Logged

Xob Ludosmbax

  • Bay Watcher
    • View Profile
Re: [DFHack] [plugins] Forwarding external keystrokes to DF
« Reply #1 on: November 06, 2013, 11:45:39 am »

For my own simple scripts, windows only, I've been using SendInput(), specifically, I've been using it from Perl with Win32::GuiTest.  I don't think SendMessage() / PostMessage() with WM_KEYDOWN,WM_KEYUP and WM_CHAR get handled by DF, so I'm unsure if there is any other Win32API way to send input without DF being in the foreground. 

Spoiler: Perl code example (click to show/hide)

For a cross platform solution, that allows DF to run in the background, I would look into executing SDL_PushEvent() within the context of Dwarf Fortress.  I haven't done any code injection recently, so I'm not sure what the state of the art is there (and, dfhack does the injection part). 

You can also look at DFterm3 for ideas.

edit:
Oh, and PTW.  I would love to know if there is a better way. 
« Last Edit: November 06, 2013, 11:53:47 am by Xob Ludosmbax »
Logged

jeancallisti

  • Bay Watcher
    • View Profile
Re: [DFHack] [plugins] Forwarding external keystrokes to DF
« Reply #2 on: November 06, 2013, 01:41:49 pm »

For my own simple scripts, windows only, I've been using SendInput(), specifically, I've been using it from Perl with Win32::GuiTest.

For a cross platform solution, that allows DF to run in the background, I would look into executing SDL_PushEvent()

I'd be very surprised if there wasn't a native DFHack solution to send the "key pressed" signal from within a DFHack plugin. But thanks for the SDL lead.
« Last Edit: November 06, 2013, 02:36:00 pm by jeancallisti »
Logged

Warmist

  • Bay Watcher
  • Master of unfinished jobs
    • View Profile
Re: [DFHack] [plugins] Forwarding external keystrokes to DF
« Reply #3 on: November 06, 2013, 05:21:31 pm »

Afaik there is. It's viewscreen feed vmethod. I been using it in lua (with a few layers of indirection and objects in between)

rmblr

  • Bay Watcher
    • View Profile
Re: [DFHack] [plugins] Forwarding external keystrokes to DF
« Reply #4 on: November 06, 2013, 06:22:24 pm »

A lot of times what you want to accomplish can be done with dfhack without forwarding the necessary keys to DF. dfhack will just change the in-memory structures to do w/e you intend.
Logged

Quietust

  • Bay Watcher
  • Does not suffer fools gladly
    • View Profile
    • QMT Productions
Re: [DFHack] [plugins] Forwarding external keystrokes to DF
« Reply #5 on: November 08, 2013, 10:50:09 pm »

Afaik there is. It's viewscreen feed vmethod. I been using it in lua (with a few layers of indirection and objects in between)
In particular, the method is to get the topmost viewscreen and then feed() the relevant keys to it. The catch is that you aren't sending keystrokes - you're actually sending keybinding codes (e.g. "move cursor up", "toggle activity zone as meeting area", "forbid/unforbid item", etc.). The actual keybindings being used within DF are stored in a location I don't recall at the moment, but I'm pretty sure DFHack has access to them.
Logged
P.S. If you don't get this note, let me know and I'll write you another.
It's amazing how dwarves can make a stack of bones completely waterproof and magmaproof.
It's amazing how they can make an entire floodgate out of the bones of 2 cats.

jeancallisti

  • Bay Watcher
    • View Profile
Re: [DFHack] [plugins] Forwarding external keystrokes to DF
« Reply #6 on: November 09, 2013, 09:57:26 am »

get the topmost viewscreen and then feed() the relevant keys to it.
I've been doing that :
Code: [Select]
CoreSuspender s; //not sure if this is needed in that context
auto screen = Core::getInstance().getTopViewscreen();
std::set<df::interface_key>keys;
keys.insert(df::interface_key::A_MOVE_UP);

screen->feed(&keys);

This compiles fine and runs smoothly in the main loop.

But I have some big issues:
1. As you said, one must send keybinding codes. I'd like something more generic, like "up keyboard arrow" or "down keyboard arrow", to make the code work with most viewscreens (including non-standard plugins that cannot be foreseen) without requiring to implement a billion things. By now, the code is very intricate, I fail to find a more global keystroke injection method (in df::ui, maybe?).

2. Even if I went for the actual key binding: I'd need to know the meaning of each key binding (declared in the big-ass list in "interface_key.h"). There is a billion of them, and they're not commented. Some make sense because they are prefixed with an intuitive viewscreen's name (e.g. ORDERS_) but I fail to find, for example, the "pause" keybinding from the main DF window (space bar). OK bad example, that was an easy one. They're the ones prefixed with "D_". But my question still stands: anyone has a tip to be more flexible with that giant list?

3. In some cases I need to indentify the current viewscreen, and here again it's hard to identify them from the class name : e.g. "viewscreen_buildingst.h" is explicit, but I fail to identify the main viewscreen (the one with "building", "units", etc.). All those .h files are generated. Generated from what? And how?

Yes, I know, that's a lot of questions! :D I promise, the pestering will stop soon.
PS: the more I learn, th emore stuff I find to add in the tutorial, that's a great exercise for newbies!
« Last Edit: November 09, 2013, 09:59:15 am by jeancallisti »
Logged

Warmist

  • Bay Watcher
  • Master of unfinished jobs
    • View Profile
Re: [DFHack] [plugins] Forwarding external keystrokes to DF
« Reply #7 on: November 09, 2013, 04:44:14 pm »

1:non-standard plugins should use the df keys IF they make sense (e.g. move_view_left if you are going to move view left). Afaik there is no more global input. Also how will you plan to do anything if somebody changes they keybindings and "a" does not mean the same thing as "a" in your computer?
3: There is "dfhack.gui.getFocusString(viewscreen)" in lua, there might be the same thing in c++ (too lazy to check) which returns e.g. "adventure mode" or "adventure mode/talk" etc... Also the files are generated from structure data xml files (which are included in project under library/xml) you can check them out here: https://github.com/peterix/df-structures/