在游戏顶部绘制覆盖图的库
game-overlay-sdk的Python项目详细描述
游戏覆盖sdk
在游戏窗口顶部写入文本消息的库。
支持的图形api:
- DirectX 11
- DirectX 12
- 瓦肯
支持的体系结构:
- x86
- x64
用法
要为全屏游戏绘制覆盖图,在初始化图形api之前,您必须钩住游戏进程,因此有两个选项可以实现它:
- 创建挂起的进程,安装挂钩并恢复线程
- 如果创建了目标进程,请为createprocess事件注册回调-挂起所有线程,安装挂钩并恢复所有线程(我使用WMI来实现它)
这两个选项都已实现,因此有:
run_process (exe_path, exe_args = "", steam_app_id = None)
start_monitor (process_name)
重要提示:对于启动监视器,您需要提供与taskmanager中完全相同的可执行文件名,并自行运行目标进程,而对于运行进程,您需要提供可执行文件的完整路径,sdk将为您运行它
在游戏进程中加载dll后,您就可以调用
send_message (message)
发送消息并将其呈现在游戏进程窗口的顶部 对于进程间的通信,我使用Memory Mapped Files,所以send_message方法只是将数据发送到这个内存映射文件,然后注入游戏进程的dll读取它。
重要提示:当游戏显示新帧时,将立即显示消息,但我不能确保显示所有消息,例如,如果您发送消息的速度快于游戏绘制帧,则只显示最新消息,同时,游戏进程每200毫秒读取一次数据(但我在python代码中使用queue缓冲消息,因此实际速率可能更高)
还有几种方法可以控制cpp代码的日志级别:
set_log_level (level) # level here is not related to python's log levels!
enable_monitor_logger ()
disble_monitor_logger ():
enable_dev_logger ()
我建议默认使用enable_monitor_logger
最后应该调用的方法:
release_resources ()
我还添加了python日志处理程序,以便在游戏窗口顶部编写日志消息
overlay_log_handler = game_overlay_sdk.injector.OvelrayLogHandler ()
蒸汽游戏使用
默认情况下,steam forks游戏进程有两个进程,不可能区分它们,并且它会中断dll注入,因为run_processdll将加载到错误的进程,因此不会绘制覆盖,而对于start_monitor它几乎是随机的,如果选择了错误的进程,它可能会挂起,或者工作正常
幸运的是,有一种方法可以强制steam只创建一个进程,我们只需要在game文件夹中创建文件steam app id.txt,而且每个游戏应该只创建一次,这就是为什么在run-process方法中有steam app\u id参数的原因。您可以获取应用程序idhere
示例
看上去怎么样? 如何实现它?代码:
import argparse
import time
import game_overlay_sdk
import game_overlay_sdk.injector
import threading
import logging
logging.basicConfig (filename = 'test.log', level = logging.WARNING)
logger = logging.getLogger (__name__)
logger.setLevel (logging.INFO)
overlay_log_handler = game_overlay_sdk.injector.OvelrayLogHandler ()
formatter = logging.Formatter ('%(levelname)s:%(message)s')
overlay_log_handler.setFormatter (formatter)
logger.addHandler (overlay_log_handler)
class MessageThread (threading.Thread):
def __init__ (self):
super (MessageThread, self).__init__ ()
self.need_quit = False
def run (self):
i = 0
while not self.need_quit:
logger.info ('Hi from python OverlayLogHandler %d' % i)
i = i + 1
time.sleep (1)
def main ():
parser = argparse.ArgumentParser ()
parser.add_argument ('--exe_path', type = str, help = 'exe path', required = True)
parser.add_argument ('--exe_args', type = str, help = 'exe args', default = '')
parser.add_argument ('--steam_app_id', type = int, help = 'for steam games please provide app_id', required = False)
args = parser.parse_args ()
game_overlay_sdk.injector.enable_monitor_logger ()
game_overlay_sdk.injector.run_process (args.exe_path, args.exe_args, args.steam_app_id)
# start sending messages to overlay
thread = MessageThread ()
thread.start ()
input ("Press Enter to stop...")
thread.need_quit = True
thread.join ()
game_overlay_sdk.injector.release_resources ()
if __name__ == "__main__":
main ()
命令行(我使用古墓丽影的试用演示,对于另一个需要更改蒸汽应用程序ID的蒸汽游戏):
python examples\overlay_log_handler.py --exe_path "D:\Steam\steamapps\common\Shadow of the Tomb Raider Trial\SOTTR.exe" --steam_app_id 974630
使用start_monitor而不是run_process的示例:
代码:
import argparse
import time
import game_overlay_sdk
import game_overlay_sdk.injector
import threading
import logging
class MessageThread (threading.Thread):
def __init__ (self):
super (MessageThread, self).__init__ ()
self.need_quit = False
def run (self):
i = 0
while not self.need_quit:
try:
game_overlay_sdk.injector.send_message ('Hi from python %d' % i)
i = i + 1
time.sleep (1)
except game_overlay_sdk.injector.InjectionError as err:
if err.exit_code == game_overlay_sdk.injector.CustomExitCodes.TARGET_PROCESS_IS_NOT_CREATED_ERROR.value:
logging.warning ('target process is not created')
time.sleep (5)
elif err.exit_code == game_overlay_sdk.injector.CustomExitCodes.TARGET_PROCESS_WAS_TERMINATED_ERROR.value:
logging.warning ('target process was stopped')
# in monitor mode we can run process several times so dont need to stop this thread here
i = 0
time.sleep (5)
else:
raise err
def main ():
logging.basicConfig (level = logging.DEBUG)
parser = argparse.ArgumentParser ()
parser.add_argument ('--name', type = str, help = 'process name', required = True)
args = parser.parse_args ()
game_overlay_sdk.injector.enable_monitor_logger ()
game_overlay_sdk.injector.start_monitor (args.name)
# start sending messages to overlay
thread = MessageThread ()
thread.start ()
input ("Press Enter to stop...")
thread.need_quit = True
thread.join ()
game_overlay_sdk.injector.release_resources ()
if __name__ == "__main__":
main ()
命令行:
python examples\monitor.py --name SOTTR.exe
重要提示:使用start_monitor可以按顺序运行目标进程多次这里唯一的要求是:不要同时运行多个进程