This question already has an answer here:
SendMessage doesn't work for some applications
(1 answer)
Closed last month.
I want to send keyboard input to a game running in the background (game: Knight Online) but the win32api.SendMessage, PostMessage methods are not working. how can I do that
I tried the code in this link
code:
from time import sleep
import win32gui
import win32con
def callback(handle, param):
s = win32gui.GetClassName(handle)
try:
print(f'Sending key to {handle}, {s}')
win32gui.SendMessage(handle, 0x0102, 0x5A, 0)
sleep(.5)
except Exception:
print('Exception sending to {handle}, {s}')
window_id = win32gui.FindWindow(None, "Knight OnLine Client")
win32gui.EnumChildWindows(window_id, callback, 0)
output:
Sending key to 23004754, Edit
Sending key to 1639850, Edit
Sending key to 10421696, Edit
the input does not work in the game
Why it doesn't work
There are many stops along the pipeline from a keypress to an application. And applications can choose where along that pipeline to receive keyboard input.
You're sending 0x0102 which is WM_CHAR. That's about as far to the end of the pipeline as you can go. It's likely the game is tapping the pipe earlier.
When you press a physical key, the keyboard driver places an input event in an input queue.
When the OS pulls that event from the input queue, it places a WM_KEYDOWN message in the message queue for the thread that owns the window with the input focus.
When the application's GUI thread pulls the message from queue, it may choose to route it through an API called TranslateMessage, which watches for low level keyboard messages like WM_KEYDOWN and WM_KEYUP.
TranslateMessage synthesizes WM_CHAR (and/or WM_UNICHAR) and sends them to the window (just before allowing the keyboard message to be processed). These messages tell the program that the user has typed a character (for example, a capital E with an acute accent) which can be done only with a series of keyboard messages.
Meanwhile, part of the system is tracking the state of the entire keyboard at different points in time.
One of those is the asynchronous keyboard state, which watches that input queue so that it knows what's happening on the keyboard right now. Games can query this with GetAsyncKeyState (and maybe with the legacy DirectInput API). A fast video game might rely on this (after checking that they are the "active" window).
There's also a synchronous keyboard state, which is tracked per GUI thread as the threads pull keyboard messages from their queues. Imagine if a thread fell behind and a lot of keyboard messages were still queued up. The synchronous keyboard state (from GetKeyState or GetKeyboardState) would indicate the keyboard state at the time the most recently processed window message was posted, which may be different that the asynchronous state which would already reflect all of the messages still in the queue.
The character input messages, like WM_CHAR, are useful for text editors, word processors, etc. But even they must tap the pipeline earlier for keystrokes like Page Up and Page Down.
Many apps work primarily with the WM_KEYDOWN and WM_KEYUP messages.
Fast video games likely use the asynchronous keyboard state or perhaps the synchronous one. And they may purposely not process any keyboard input when they are in the background.
What you can try
The easiest thing to try is to send (or better, post) WM_KEYDOWN and WM_KEYUP messages instead of WM_CHAR. That won't guarantee success.
Windows has the SendInput API for putting events in the input queue (the way the keyboard driver does). I don't know if there's a Python library that covers that. Even if there is, it's not likely to help, since the system won't send your injected keyboard input events to a background window.
Related
i am working on a game project and i decide to go with twisted for the server part.
its a multiplayer shooting game.
now i want to integrate a main loop into the game (on server side) to process input and physics(for bullets and players).The inputs are recieved from the clients through websockets.
i want the game loop to run game at lets say. 50 fps.
if i follow the method for implementing a game loop mentioned in this atricle. i have this code below
previous = getCurrentTime()
def loop():
double lag = 0.0
while True:
current = getCurrentTime()
elapsed = current - previous
previous = current
lag += elapsed
processInput()
while (lag >= MS_PER_UPDATE):
update()
lag -= MS_PER_UPDATE
send_state_to_connected_clients()
In the article it mentions that:
If you’re making a game that runs in a web browser, you pretty much can’t write your own classic game loop. The browser’s event-based nature precludes it
Now i am having a difficult time understanding it as this applies to Twisted as it's also event based.(i think what it says is the while true statement will block the reactor forever.so what can we do to implement our own loop in twisted given its even based)
in the same article towards the bottom it mentions these points:
Use the platform’s event loop:
1. It’s simple. You don’t have to worry about writing and optimizing the core loop of the game
2. It plays nice with the platform. You don’t have to worry about explicitly giving the host time to process its own events, caching events, or otherwise managing the impedance mismatch between the platform’s input model and yours.
What i am looking for is a general approach towards implementing a game loop in twisted(for a networked multiplayer game).
should i use the inbuilt reactor by using the LoopingCall to call
my Loop? how does then it handles the issues
mentioned in the article.
should i create my own loop somehow? (ex by using threads/processes or some other construct to run the game loop seperate from reactor)
should i create my own reactor implementation somehow?
If I understand the problem accurately, you will have a Python server and players will play a real-time FPS in the browser. You will have to:
display the game in real-time
handle user events in the browser
send browser-event results to the server
parse the results on the server
send server events to the browser
handle server events in the browser
We already know that you are going to use WebSockets.
Display the game in real-time
You will need to display the graphics somewhere, maybe inside a canvas. You will need to implement lots of functions, like update health bar, display changes and so on. These will be triggered when you handle responses from the server.
Handle user events in the browser
If we assume that clicking is shooting, space is activate and so on, you will need some event handlers for those. In the browser you will need a browser-level validation. For instance, if the player intends to shoot, but there is no more ammo, then you do not even have to send a message to the server, maybe display a sound effect of the gun which signifies that shooting was unsuccessful. If, according to the data you have in the browser you have ammo, then the direction you shoot at should be sent to the server.
Send browser-event results to the server
When an event occurs in the browser and is evaluated, then the results in many cases will be sent to the server, which will handle them and eventually send a response to the browser.
Parse the results on the server
The server will have an event loop and will receive WebSocket messages from the browsers of the players. For example if the server receives a shoot event, then it will get the current coordinates of the player and the direction, calculate where the bullet goes and send a message to the players' browser. If someone is hit, then damage is to be calculated and determined whether the player dies, subsequently players will get WebSocket messages from the server and subsequently the sound of the bullet will be displayed along with the bullet's graphical display and potentially some blood, falling players and so on.
Send server events to the browser
The browsers will listen to WebSocket messages from the server and handle those.
Handle server events in the browser
We cannot trust user events, because some cheating could be involved, so when you shoot, the browser will handle the event and the server will receive a message. When the server sends a WebSocket message, the browsers will "believe" that the server sent an accurate response.
Technical needs
You will need a graphics API, user event listeners and WebSocket listeners in the browsers. On the server you will listen to client WebSocket messages.
What I want
Write a script that reads what HID usage ids usb keyboards send without root user right.
The purpose is to map a scancode/HID id and the resulting literal input for writing a keyboard configuration tool; T key press may input a literal Y if the user is using dvorak layout or Z may input a literal ツ.
The code snippet below does a nice job in capturing scancode(usb keyboards send hid usage id, but it still captures scancode), but requires read permission for /dev/input/*, not ideal.
from evdev import *
dev = InputDevice('/dev/input/event5')
print(dev)
for event in dev.read_loop():
if event.type == ecodes.EV_KEY:
print(categorize(event))
Is there anyway to do this without special permissions?
Conclusion:
X input extension 2(XI2) provides access to RawEvents; though I could not find what I need in RawKeyPress event: Capture XI2 RawKeyPress event and interpreting it with python
It's half possible to convert X11 keycodes back to scancodes.
Not detailed but my note on them here: How to translate X11 keycode back to scancode or hid usage id reliably
As to capturing keyboard events upstream of /dev/input/event*, it's not possible without some permissions.
XI2 support in python is poor and playing with it seems to require using C library or writing X client library. The latest version of python3-xlib does support it but at least I cannot find documentations and understanding binary data is not easy.
The key event generation chain:
This blog post had some details about keyboard event generation process: https://seasonofcode.com/posts/internal-input-event-handling-in-the-linux-kernel-and-the-android-userspace.html
----os space-------------
A user press a keyboard key
The keyboard sends an hidbp(a packet of a sort) to the usb controller
USB controller receives the packet and make an irq(Interrupt request)
CPU responds to the irq and invokes irq handler which is set by the keyboard driver.
---somewhat uncertain
irq handler stores the packet or event and queues the processing function call for it in the kernel and exits.
The queued function process the event and reports it to various functions in include/linux/input.h and calls input_sync to write the event to a device file such as /dev/input/event1.
---user space----
Be it xwindow server or android InputDeviceReader reads form /dev/input/event*
If what I've read is right and have read it right, anything upstream of the /dev/input/event* happens in the kernel and the task is handled by the device driver.
Making a very simple tic-tac-toe game in Python using a P2P architecture with sockets. Currently my GUI has button that says 'Create' that will open up and draw a new game board window, create a socket, bind, listen, and accept a connection. The 'Join' button will open and draw a new gameboard and connect to that 'server'.
I'm trying to have it show a message saying 'Waiting for player...' when you create a game, a cancel button to stop and go back to the main menu, and have it disappear on it's own if a connection has been accepted.
I tried using tkMessageBox but the script stops until the user clears the message so there's no way for me to listen/accept until the user presses something.
What other way is there for me to accomplish this?
Thanks!
Sounds like a threading issue.
I'm unfamiliar with TK graphics, but I'd imagine what you need to do is start the window showing the "waiting for player" message. That window then loops waiting for something to happen.
When the message box displays you need to have the "listening" done on another thread, which signals back to the main message box when someone's connected using a semaphore or a queue.
On your main GUI thread you need to make the loop:
check the queue or semaphore for values. If there's a value on there that you expect, close the box. This would need to be non-blocking so that the GUI thread can still check for input from the user.
check for user input. That's probably done using callback functions though.
A have a application with two threads. Its a network controlled game,
1. thread (Server)
Accept socket connections and receive messages
When message is sent, create an event and add it to the queue
Code:
class SingleTCPHandler(SocketServer.StreamRequestHandler):
def handle(self):
try:
while True:
sleep(0.06)
message = self.rfile.readline().strip()
my_event = pygame.event.Event(USEREVENT, {'control':message})
print message
pygame.event.post(my_event)
2. thread (pygame)
In charge of game rendering
Receives messages via event queue which Server populates
Renders the game based on messages every 60ms
This is how the game looks. The control messages are just speeds for the little square.
For the purpose of debug i connect to the server from a virtual machine with:
ncat 192.168.56.1 2000
And then send control messages. In production, these messages will be sent every 50ms by an Android device.
The problem
In my debug environment, i manually type messages with a period of a few seconds. During the time i don't type anything the game gets rendered many times. What happens is that the message (in server code) is constantly rendered with the previously received value.
I send the following:
1:0.5
On the console where the app is started i receive the following due to line print message in Server code:
alan#alan ~/.../py $ python main.py
1:0.5
What the game does is it acts as it is constantly (with the period it renders, and not every few seconds as i type) receiving this value.
SInce that is happenig i would expect that the print message which is in while True also outputs constantly and that the output is:
alan#alan ~/.../py $ python main.py
1:0.5
1:0.5
1:0.5
1:0.5
....
However that is not the case. Please advise (I'm also open for proposals to what to change the subject to if it isn't explanatory enough)
Your while True loop is polling the socket, which is only going to get messages when they are sent; it has no idea or care what the downstream event consumer is doing with those messages, it is just going to dispatch an event for and print the contents of the next record on the socket queue every .6 seconds. If you want the game to print the current command every render loop, you'll have to put the print statement in the render loop itself, not in the socket poller. Also, since you seem to want to have the last command "stick" and not post a new event unless the user actually inputs something, you might want to put an if message: block around the event dispatch code in the socket handler you have here. Right now, you'll send an empty event every .6 seconds if the user hasn't provided you any input since the last time you checked.
I also don't think it's probably advisable to put a sleep, or the loop you have for that matter, in your socket handler. The SocketServer is going to be calling it every time you receive data on the socket, so that loop is effectively being done for you, and all doing it here is going to do is open you up to overflowing the buffer, I think. If you want to control how often you post events to pygame, you probably want to do that by either blocking events of a certain type from being added if there is already 1 queued, or by grabbing all events of a given type from the queue each game loop and then just ignoring all but the first or last one. You could also control it by checking in the handler if it has been some amount of time since the last event was posted, but then you have to make sure the event consumer is capable of handling an event queue with multiple events waiting on it, and does the appropriate queue flushing when needed.
Edit:
Docs:
The difference is that the readline() call in the second handler will call recv() multiple times until it encounters a newline character, while the single recv() call in the first handler will just return what has been sent from the client in one sendall() call.
So yes, reading the whole line is guaranteed. In fact, I don't think the try is necessary either, since this won't even be called unless there is input to handle.
I have a program that captures all key presses using pyHook, then runs a few functions.
I notice that after a while (of random duration), the program was stop receiving key triggers, even though I am pressing keys?
Is pyHook unstable?
I'm not changing what keys are pressed or pressing them prematurely or anything like that.
Here's my code:
import time
import win32api
import win32con
import pythoncom
import pyHook
import os
import ctypes
def Click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
def DeleteRun(event):
if event.Ascii == 96:
BreakHook()
return False
Click(1250, 741)
time.sleep(0.2)
Click(649,261)
time.sleep(0.2)
Click(651, 348)
time.sleep(0.2)
Click(800, 442)
time.sleep(0.2)
Click(865, 612)
time.sleep(0.2)
Click(25, 744)
time.sleep(3)
Click(25, 744)
time.sleep(1.5)
Click(1112,297)
Click(145,392)
return True
def BreakHook():
ctypes.windll.user32.PostQuitMessage(0)
KeyGrabber = pyHook.HookManager()
KeyGrabber.KeyDown = DeleteRun
KeyGrabber.HookKeyboard()
pythoncom.PumpMessages()
Why does is suddenly stop working?
It's very frustrating as the process remains active on my computer, even if I stop the program through the IDE.
Specs:
python 2.7.2
Windows 7 (32)
Similar (dare I say identical?) problems were discussed and resolved here: pyHook + pythoncom stop working after too much keys pressed [Python]
and here: Pyhook stops capturing key events after 6 presses
You may be trying to do to much from withing the event callback.
Any event function callback as configured via HookManager and PumpMessages should return as quickly as possible.
When you press a key, Windows is kind enough to inform you of the event, but there may be other programs who also need the event. You are doing sleep calls within your event, but while you sleep, Windows is waiting for your response on THIS callback.
My guess is that after a certain number of opportunities to return in a timely manner, your event registration is being voided and ignored by Windows.
Move your sleep commands outside of the event, and instead trigger your actually click-sleep sequence outside of the hookmanager callback.
Edit: Links/Reference:
The PyHook API Documentation is one of the best (unfortunately), http://pyhook.sourceforge.net/doc_1.5.0/ If you notice the many things you can do from within the event, it becomes clear why time is of the essence. Windows wants to know how to handle the keypress (for example), and keypresses happen very fast, so it wants to know ASAP.
Its important to understand that PyHook is a very thin layer, and most of the functionality is provided by Windows, so the best documents are from MSDN http://msdn.microsoft.com/en-us/library/ms632589(v=vs.85).aspx. Also might want to take a look up a level at some of the information on 'Messages' (thats where our PumpMessages ultimately derives) The written text is very descriptive, and many of the constants and values are reflected properly through PyHook, although the good code segments are not written in Python.
Here is a pretty direct reference to proper handling of Messages (which is what hookmanager knows how to get, and by which PumpMessages delivers), http://msdn.microsoft.com/en-us/library/ms644927(v=vs.85).aspx
If a top-level window stops responding to messages for more than several seconds, the system considers the window to be not responding.
and
Message Handling
An application must remove and process messages posted to the message queues of its threads
When you call your sleeps, you are hanging in your current message, and neglecting the others that might be stacking up. Even if you grab the message and immediately return, Windows doesn't care what you do with it, as long as you are consuming.