Files
ClaudeCode-Roblox-Studio-MCP/inject_bg2.py
Gemini AI 2065361e57 Add GTA city builder + background injection API for Roblox Studio
- inject_gta_city.py: Full GTA-style city with 20 buildings, roads, cars,
  street lights, traffic lights, trees, 15 human enemies with varied
  skin/clothing, and 10 COD weapons with visible gun models
- inject_bg.py: Background injection using SendMessage/PostMessage Win32 API
- inject_bg2.py: PostMessage approach targeting main window for WPF apps
- inject_cod_final.py: Working COD game injection (7-step sequential)
- cod_inject.py: Combined COD game builder with proper Studio launch
- roblox-fps-p1-p6: Split Lua scripts for multi-part injection

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 21:39:39 +04:00

104 lines
3.9 KiB
Python

"""
Background injection v2 - PostMessage to main window.
Roblox Studio uses WPF (no standard child controls).
We send keystrokes via PostMessage to the main window handle.
This works even when Studio is minimized or behind other windows.
"""
import ctypes, ctypes.wintypes, subprocess, time, sys, os
user32 = ctypes.windll.user32
WM_KEYDOWN = 0x0100
WM_KEYUP = 0x0101
WM_CHAR = 0x0102
WM_PASTE = 0x0302
def find_studio():
target = [None]
def cb(hwnd, _):
l = user32.GetWindowTextLengthW(hwnd)
if l > 0:
buf = ctypes.create_unicode_buffer(l + 1)
user32.GetWindowTextW(hwnd, buf, l + 1)
if "Roblox Studio" in buf.value:
target[0] = hwnd
return False
return True
WNDENUMPROC = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.wintypes.HWND, ctypes.wintypes.LPARAM)
user32.EnumWindows(WNDENUMPROC(cb), 0)
return target[0]
def post_key(hwnd, vk, shift=False, ctrl=False):
"""Send a key press/release via PostMessage to background window."""
if ctrl:
user32.PostMessageW(hwnd, WM_KEYDOWN, 0x11, 0)
if shift:
user32.PostMessageW(hwnd, WM_KEYDOWN, 0x10, 0)
# Key down
scan = ctypes.windll.user32.MapVirtualKeyW(vk, 0)
lparam_down = (scan << 16) | 1
user32.PostMessageW(hwnd, WM_KEYDOWN, vk, lparam_down)
time.sleep(0.01)
# Key up
lparam_up = (scan << 16) | 1 | (1 << 30) | (1 << 31)
user32.PostMessageW(hwnd, WM_KEYUP, vk, lparam_up)
time.sleep(0.01)
if ctrl:
user32.PostMessageW(hwnd, WM_KEYUP, 0x11, 0)
if shift:
user32.PostMessageW(hwnd, WM_KEYUP, 0x10, 0)
def paste_and_run(hwnd, code):
"""Copy code to clipboard, then send Ctrl+A, Ctrl+V, Enter via PostMessage."""
tmp = os.path.join(os.environ["TEMP"], "rbx.lua")
with open(tmp, "w", encoding="utf-8") as f:
f.write(code)
subprocess.run(["powershell", "-Command", f"Get-Content '{tmp}' -Raw | Set-Clipboard"],
capture_output=True, timeout=10)
time.sleep(0.3)
# Select all: Ctrl+A
user32.PostMessageW(hwnd, WM_KEYDOWN, 0x11, 0) # Ctrl down
time.sleep(0.02)
scan_a = user32.MapVirtualKeyW(0x41, 0)
user32.PostMessageW(hwnd, WM_KEYDOWN, 0x41, (scan_a << 16) | 1)
time.sleep(0.02)
user32.PostMessageW(hwnd, WM_KEYUP, 0x41, (scan_a << 16) | 1 | (1 << 30) | (1 << 31))
time.sleep(0.02)
user32.PostMessageW(hwnd, WM_KEYUP, 0x11, 0) # Ctrl up
time.sleep(0.1)
# Paste: Ctrl+V
user32.PostMessageW(hwnd, WM_KEYDOWN, 0x11, 0)
time.sleep(0.02)
scan_v = user32.MapVirtualKeyW(0x56, 0)
user32.PostMessageW(hwnd, WM_KEYDOWN, 0x56, (scan_v << 16) | 1)
time.sleep(0.02)
user32.PostMessageW(hwnd, WM_KEYUP, 0x56, (scan_v << 16) | 1 | (1 << 30) | (1 << 31))
time.sleep(0.02)
user32.PostMessageW(hwnd, WM_KEYUP, 0x11, 0)
time.sleep(0.8)
# Enter to execute
scan_enter = user32.MapVirtualKeyW(0x0D, 0)
user32.PostMessageW(hwnd, WM_KEYDOWN, 0x0D, (scan_enter << 16) | 1)
time.sleep(0.02)
user32.PostMessageW(hwnd, WM_KEYUP, 0x0D, (scan_enter << 16) | 1 | (1 << 30) | (1 << 31))
time.sleep(2)
# ═══════════════════════════════════════
hwnd = find_studio()
if not hwnd:
print("ERROR: Roblox Studio not found!")
sys.exit(1)
print(f"Studio: {hwnd}")
state = "minimized" if user32.IsIconic(hwnd) else ("background" if user32.GetForegroundWindow() != hwnd else "foreground")
print(f"Window state: {state}")
# Test with simple code
print("\nTest: sending print('BG_TEST_OK') via PostMessage...")
paste_and_run(hwnd, """print("BG_TEST_OK - BACKGROUND INJECTION WORKS!")""")
print("Sent! Check Studio Output window (F9) for the message.")
print("\nNOTE: If nothing appeared, the command bar needs focus first.")
print("Alternative: bring Studio to front briefly, inject, then let it go to background.")