You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python脚本向Multi Theft Auto发送输入失效问题求助

问题描述

我用Python脚本实现自动化输入,脚本在《Skyrim》《Elden Ring》等Steam游戏、《Bloons Tower Defense》及其他应用中均能正常工作,在Multi Theft Auto(MTA)客户端的服务器浏览器界面也可生效,但连接服务器后完全无输入响应。

已尝试的解决措施:

  • 使用pydirectinput和ctypes库模拟输入
  • 以管理员身份运行VS Code和游戏
  • 查阅相关资料但未找到有效方案

当前实现代码:

import pyautogui
import time
import keyboard
import random
import pydirectinput

import ctypes
import time
import sys

SendInput = ctypes.windll.user32.SendInput
def elevate(console=True):
    arg = 'forced_elevate'
    if sys.argv[-1] != arg and not ctypes.windll.shell32.IsUserAnAdmin():
        script = os.path.abspath(sys.argv[0])
        params = u' '.join([script] + sys.argv[1:] + [arg])
        ret = ctypes.windll.shell32.ShellExecuteW(None, u'runas', unicode(sys.executable), params, None, 5 if console else 0)
        if int(ret) > 32:
            sys.exit(0)
elevate()
# C struct redefinitions 
PUL = ctypes.POINTER(ctypes.c_ulong)
class KeyBdInput(ctypes.Structure):
    _fields_ = [("wVk", ctypes.c_ushort),
                ("wScan", ctypes.c_ushort),
                ("dwFlags", ctypes.c_ulong),
                ("time", ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class HardwareInput(ctypes.Structure):
    _fields_ = [("uMsg", ctypes.c_ulong),
                ("wParamL", ctypes.c_short),
                ("wParamH", ctypes.c_ushort)]

class MouseInput(ctypes.Structure):
    _fields_ = [("dx", ctypes.c_long),
                ("dy", ctypes.c_long),
                ("mouseData", ctypes.c_ulong),
                ("dwFlags", ctypes.c_ulong),
                ("time",ctypes.c_ulong),
                ("dwExtraInfo", PUL)]

class Input_I(ctypes.Union):
    _fields_ = [("ki", KeyBdInput),
                 ("mi", MouseInput),
                 ("hi", HardwareInput)]

class Input(ctypes.Structure):
    _fields_ = [("type", ctypes.c_ulong),
                ("ii", Input_I)]

# Actuals Functions

def PressKey(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput( 0, hexKeyCode, 0x0008, 0, ctypes.pointer(extra) )
    x = Input( ctypes.c_ulong(1), ii_ )
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

def ReleaseKey(hexKeyCode):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput( 0, hexKeyCode, 0x0008 | 0x0002, 0, ctypes.pointer(extra) )
    x = Input( ctypes.c_ulong(1), ii_ )
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

# directx scan codes http://www.gamespp.com/directx/directInputKeyboardScanCodes.html
while (True):
    PressKey(0x11)
    time.sleep(1)
    ReleaseKey(0x11)
    time.sleep(1)

可能的原因及解决方案

1. 输入参数不匹配游戏捕获逻辑

MTA进入服务器后可能切换到Raw Input或自定义输入处理通道,当前代码仅传递扫描码(wScan)且虚拟键码(wVk)设为0,部分游戏会优先校验虚拟键码或要求同时提供两者。修改输入函数:

# 同时传入虚拟键码和扫描码(以W键为例:虚拟键码0x57,扫描码0x11)
def PressKey(vk_code, scan_code):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput(vk_code, scan_code, 0x0008, 0, ctypes.pointer(extra))
    x = Input(ctypes.c_ulong(1), ii_)
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

def ReleaseKey(vk_code, scan_code):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    ii_.ki = KeyBdInput(vk_code, scan_code, 0x0008 | 0x0002, 0, ctypes.pointer(extra))
    x = Input(ctypes.c_ulong(1), ii_)
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

# 调用示例
while True:
    PressKey(0x57, 0x11)
    time.sleep(1)
    ReleaseKey(0x57, 0x11)
    time.sleep(1)

2. 窗口焦点未正确绑定

进入服务器后,脚本可能未将输入定向到MTA游戏窗口。添加窗口激活逻辑:

import pygetwindow as gw

# 根据窗口标题获取MTA窗口(标题需匹配实际游戏窗口)
mta_window = gw.getWindowsWithTitle("Multi Theft Auto")[0]
mta_window.activate()
time.sleep(0.5)  # 等待窗口获取焦点

# 后续执行输入循环
while True:
    PressKey(0x57, 0x11)
    time.sleep(1)
    ReleaseKey(0x57, 0x11)
    time.sleep(1)

3. 服务器反作弊拦截模拟输入

部分MTA服务器可能启用反作弊插件,拦截非物理输入。可尝试:

  • 查看服务器是否有反作弊提示,确认是否允许自动化操作
  • 改用硬件级模拟工具(如Arduino模拟物理键盘),但成本较高

4. 输入计时精度不足

游戏对输入的时间精度要求可能更高,time.sleep()的延迟精度不够,改用系统级高精度睡眠:

import win32api

while True:
    PressKey(0x57, 0x11)
    win32api.Sleep(1000)  # 精度更高的毫秒级睡眠
    ReleaseKey(0x57, 0x11)
    win32api.Sleep(1000)

5. 调整SendInput标志位

尝试添加KEYEVENTF_EXTENDEDKEY标志(0x0004),适配特殊按键的输入逻辑:

def PressKey(vk_code, scan_code):
    extra = ctypes.c_ulong(0)
    ii_ = Input_I()
    # 添加0x0004标志
    ii_.ki = KeyBdInput(vk_code, scan_code, 0x0008 | 0x0004, 0, ctypes.pointer(extra))
    x = Input(ctypes.c_ulong(1), ii_)
    ctypes.windll.user32.SendInput(1, ctypes.pointer(x), ctypes.sizeof(x))

内容的提问来源于stack exchange,提问作者CarruthT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 11:42:48