Files
ClaudeCode-Roblox-Studio-MCP/examples/inject-all-parts.py
Admin a66533206f Add FPS game example, auto-connect plugin, and Python injection tools
- Updated RobloxMCPPlugin with HTTP polling (auto-enables HttpService)
- Added 20-weapon FPS game example (CoD-style)
- Added Python studio-inject.py for command bar injection via Win32 API
- Added auto-connect setup scripts (VBS + PowerShell)
- Updated MCP server with all FPS game tools

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

177 lines
5.1 KiB
Python

"""
Inject all 5 FPS game parts into Roblox Studio command bar sequentially.
"""
import ctypes
import ctypes.wintypes
import subprocess
import time
import sys
import os
user32 = ctypes.windll.user32
def find_studio():
target = [None]
def cb(hwnd, _):
length = user32.GetWindowTextLengthW(hwnd)
if length > 0:
buf = ctypes.create_unicode_buffer(length + 1)
user32.GetWindowTextW(hwnd, buf, length + 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 set_foreground(hwnd):
SW_RESTORE = 9
user32.ShowWindow(hwnd, SW_RESTORE)
time.sleep(0.3)
fg = user32.GetForegroundWindow()
if fg != hwnd:
tid_fg = user32.GetWindowThreadProcessId(fg, None)
tid_target = user32.GetWindowThreadProcessId(hwnd, None)
user32.AttachThreadInput(tid_fg, tid_target, True)
user32.SetForegroundWindow(hwnd)
user32.AttachThreadInput(tid_fg, tid_target, False)
time.sleep(0.3)
def set_clipboard(text):
# Use PowerShell for reliable clipboard
# Write to temp file first to avoid escaping issues
tmp = os.path.join(os.environ["TEMP"], "roblox_clipboard.lua")
with open(tmp, "w", encoding="utf-8") as f:
f.write(text)
result = subprocess.run(
["powershell", "-Command",
f"Get-Content '{tmp}' -Raw | Set-Clipboard"],
capture_output=True, text=True, timeout=10
)
return result.returncode == 0
def press_key(vk):
user32.keybd_event(vk, 0, 0, 0)
time.sleep(0.03)
user32.keybd_event(vk, 0, 2, 0)
time.sleep(0.05)
def ctrl_v():
user32.keybd_event(0x11, 0, 0, 0) # Ctrl down
time.sleep(0.02)
user32.keybd_event(0x56, 0, 0, 0) # V down
time.sleep(0.03)
user32.keybd_event(0x56, 0, 2, 0) # V up
time.sleep(0.02)
user32.keybd_event(0x11, 0, 2, 0) # Ctrl up
time.sleep(0.1)
def click_at(x, y):
screen_w = user32.GetSystemMetrics(0)
screen_h = user32.GetSystemMetrics(1)
nx = int(x * 65535 / screen_w)
ny = int(y * 65535 / screen_h)
user32.mouse_event(0x8001, nx, ny, 0, 0) # Move
time.sleep(0.02)
user32.mouse_event(0x8002, nx, ny, 0, 0) # Down
time.sleep(0.03)
user32.mouse_event(0x8004, nx, ny, 0, 0) # Up
time.sleep(0.05)
def inject_script(lua_code, part_num, total):
print(f"\n [{part_num}/{total}] Injecting {len(lua_code)} bytes...")
if not set_clipboard(lua_code):
print(f" ERROR: Clipboard failed for part {part_num}")
return False
time.sleep(0.3)
# Press Escape to clear any selection
press_key(0x1B)
time.sleep(0.2)
# Click in command bar area
hwnd = find_studio()
if not hwnd:
print(" ERROR: Studio window lost!")
return False
rect = ctypes.wintypes.RECT()
user32.GetWindowRect(hwnd, ctypes.byref(rect))
w = rect.right - rect.left
h = rect.bottom - rect.top
cmd_x = rect.left + w // 2
cmd_y = rect.bottom - 50
click_at(cmd_x, cmd_y)
time.sleep(0.3)
# Select all + delete existing text
user32.keybd_event(0x11, 0, 0, 0) # Ctrl
press_key(0x41) # A
user32.keybd_event(0x11, 0, 2, 0) # Ctrl up
time.sleep(0.1)
press_key(0x2E) # Delete
time.sleep(0.1)
# Paste
ctrl_v()
time.sleep(0.5)
# Execute
press_key(0x0D) # Enter
time.sleep(1.5) # Wait for execution
print(f" [{part_num}/{total}] Done.")
return True
def main():
parts = [
r"C:\Users\Admin\ClaudeCode-Roblox-Studio-MCP\examples\fps-game\part1_map.lua",
r"C:\Users\Admin\ClaudeCode-Roblox-Studio-MCP\examples\fps-game\part2_weapons.lua",
r"C:\Users\Admin\ClaudeCode-Roblox-Studio-MCP\examples\fps-game\part3_ai.lua",
r"C:\Users\Admin\ClaudeCode-Roblox-Studio-MCP\examples\fps-game\part4_hud.lua",
r"C:\Users\Admin\ClaudeCode-Roblox-Studio-MCP\examples\fps-game\part5_client.lua",
]
total = len(parts)
print("=" * 50)
print(" MINI CALL OF DUTY - Injecting into Roblox Studio")
print("=" * 50)
# Find and focus Studio
hwnd = find_studio()
if not hwnd:
print("ERROR: Roblox Studio not found!")
sys.exit(1)
print(f"\n Studio found: HWND={hwnd}")
set_foreground(hwnd)
time.sleep(1)
for i, path in enumerate(parts, 1):
if not os.path.exists(path):
print(f"\n WARNING: {path} not found. Skipping.")
continue
with open(path, "r", encoding="utf-8") as f:
lua_code = f.read()
if not inject_script(lua_code, i, total):
print(f"\n FATAL: Part {i} failed. Stopping.")
sys.exit(1)
# Re-focus between injections
set_foreground(hwnd)
time.sleep(1)
print("\n" + "=" * 50)
print(" ALL PARTS INJECTED SUCCESSFULLY!")
print(" Press PLAY in Roblox Studio to start the game.")
print("=" * 50)
if __name__ == "__main__":
main()