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>
This commit is contained in:
239
roblox-plugin/RobloxMCPServer_HTTP.lua
Normal file
239
roblox-plugin/RobloxMCPServer_HTTP.lua
Normal file
@@ -0,0 +1,239 @@
|
||||
-- Roblox MCP Server - HTTP Polling Version
|
||||
-- This version polls the MCP server for commands via HTTP
|
||||
|
||||
local HttpService = game:GetService("HttpService")
|
||||
local RunService = game:GetService("RunService")
|
||||
|
||||
-- Configuration
|
||||
local MCP_SERVER_URL = "http://127.0.0.1:37423"
|
||||
local POLL_INTERVAL = 0.5 -- seconds
|
||||
local DEBUG = true
|
||||
|
||||
-- State
|
||||
local isRunning = true
|
||||
local lastCommandId = 0
|
||||
|
||||
-- Logging
|
||||
local function log(msg)
|
||||
if DEBUG then
|
||||
print("[RobloxMCP] " .. msg)
|
||||
end
|
||||
end
|
||||
|
||||
-- Get object by path
|
||||
local function getObjectFromPath(path)
|
||||
if not path or path == "" then return nil end
|
||||
if path == "game" or path == "Game" then return game end
|
||||
if path == "Workspace" or path == "workspace" then return workspace end
|
||||
|
||||
local parts = {}
|
||||
for part in string.gmatch(path, "[^%.]+") do
|
||||
table.insert(parts, part)
|
||||
end
|
||||
|
||||
local obj = game
|
||||
for _, part in ipairs(parts) do
|
||||
if part == "Workspace" or part == "workspace" then
|
||||
obj = workspace
|
||||
elseif typeof(obj) == "Instance" and obj:FindFirstChild(part) then
|
||||
obj = obj[part]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
return obj
|
||||
end
|
||||
|
||||
-- Create object at path
|
||||
local function createObjectAt(path, className, properties)
|
||||
local lastDot = string.find(path, "%.[^%.]+$")
|
||||
local parentPath = lastDot and string.sub(path, 1, lastDot - 1) or "game"
|
||||
local objectName = lastDot and string.sub(path, lastDot + 1) or path
|
||||
|
||||
local parent = getObjectFromPath(parentPath)
|
||||
if not parent then return nil, "Parent not found" end
|
||||
|
||||
local obj = Instance.new(className)
|
||||
obj.Name = objectName
|
||||
|
||||
if properties then
|
||||
for prop, value in pairs(properties) do
|
||||
pcall(function() obj[prop] = value end)
|
||||
end
|
||||
end
|
||||
|
||||
obj.Parent = parent
|
||||
return obj
|
||||
end
|
||||
|
||||
-- Command handlers
|
||||
local handlers = {}
|
||||
|
||||
handlers.createPart = function(params)
|
||||
local props = {
|
||||
Name = params.partName,
|
||||
Anchored = params.anchored ~= false,
|
||||
Shape = Enum.PartType.Block,
|
||||
}
|
||||
|
||||
if params.position then
|
||||
props.Position = Vector3.new(params.position.x or 0, params.position.y or 0, params.position.z or 0)
|
||||
end
|
||||
|
||||
if params.size then
|
||||
props.Size = Vector3.new(params.size.x or 4, params.size.y or 1, params.size.z or 2)
|
||||
end
|
||||
|
||||
if params.color then
|
||||
pcall(function() props.BrickColor = BrickColor.new(params.color) end)
|
||||
end
|
||||
|
||||
local part = createObjectAt((params.parentPath or "Workspace") .. "." .. params.partName, "Part", props)
|
||||
return {success = part ~= nil}
|
||||
end
|
||||
|
||||
handlers.createScript = function(params)
|
||||
local obj = createObjectAt(params.path .. "." .. params.scriptName, params.scriptType or "Script", {Name = params.scriptName})
|
||||
if obj then
|
||||
obj.Source = params.source
|
||||
return {success = true}
|
||||
end
|
||||
return {success = false}
|
||||
end
|
||||
|
||||
handlers.setProperty = function(params)
|
||||
local obj = getObjectFromPath(params.path)
|
||||
if not obj then return {success = false, error = "Not found"} end
|
||||
|
||||
local value = params.value
|
||||
if params.property == "Position" or params.property == "Size" then
|
||||
value = Vector3.new(value.x, value.y, value.z)
|
||||
elseif params.property == "Color3" then
|
||||
value = Color3.new(value.r, value.g, value.b)
|
||||
end
|
||||
|
||||
pcall(function() obj[params.property] = value end)
|
||||
return {success = true}
|
||||
end
|
||||
|
||||
handlers.executeCode = function(params)
|
||||
local fn, err = loadstring(params.code)
|
||||
if not fn then return {success = false, error = err} end
|
||||
|
||||
local ok = pcall(fn)
|
||||
return {success = ok}
|
||||
end
|
||||
|
||||
handlers.getHierarchy = function(params)
|
||||
local obj = getObjectFromPath(params.path or "Workspace")
|
||||
if not obj then return {success = false, error = "Not found"} end
|
||||
|
||||
local function build(obj, depth)
|
||||
if depth <= 0 then return nil end
|
||||
local children = {}
|
||||
for _, child in ipairs(obj:GetChildren()) do
|
||||
table.insert(children, {
|
||||
name = child.Name,
|
||||
className = child.ClassName,
|
||||
})
|
||||
end
|
||||
return children
|
||||
end
|
||||
|
||||
return {success = true, children = build(obj, params.depth or 2)}
|
||||
end
|
||||
|
||||
handlers.importGLB = function(params)
|
||||
-- Import GLB model into Roblox Studio
|
||||
-- GLB files need to be imported via the Editor API for assets
|
||||
-- For now, we'll create a placeholder model with instructions
|
||||
|
||||
local parent = getObjectFromPath(params.parentPath or "Workspace")
|
||||
if not parent then
|
||||
return {success = false, error = "Parent path not found"}
|
||||
end
|
||||
|
||||
-- Create a model to hold the imported GLB
|
||||
local model = Instance.new("Model")
|
||||
model.Name = params.modelName or "ImportedGLB"
|
||||
model.Parent = parent
|
||||
|
||||
-- Create a placeholder part with info
|
||||
local placeholder = Instance.new("Part")
|
||||
placeholder.Name = "GLB_Placeholder"
|
||||
placeholder.Size = Vector3.new(4, 4, 4)
|
||||
placeholder.Position = Vector3.new(0, 5, 0)
|
||||
placeholder.Anchored = true
|
||||
placeholder.BrickColor = BrickColor.new("Bright blue")
|
||||
placeholder.Transparency = 0.5
|
||||
placeholder.Parent = model
|
||||
|
||||
-- Add a note
|
||||
local info = Instance.new("StringValue")
|
||||
info.Name = "ImportInfo"
|
||||
info.Value = "GLB Import: Use the 3D Importer (File > Import 3D) or Editor Service to import GLB files. This is a placeholder."
|
||||
info.Parent = model
|
||||
|
||||
return {
|
||||
success = true,
|
||||
modelPath = (params.parentPath or "Workspace") .. "." .. params.modelName,
|
||||
note = "GLB files require manual import via Roblox Studio's 3D Importer or Editor Service API"
|
||||
}
|
||||
end
|
||||
|
||||
-- Poll for commands
|
||||
local function pollForCommands()
|
||||
local success, response = pcall(function()
|
||||
return HttpService:RequestAsync({
|
||||
Url = MCP_SERVER_URL .. "/poll?last=" .. lastCommandId,
|
||||
Method = "GET",
|
||||
})
|
||||
end)
|
||||
|
||||
if success and response.Success then
|
||||
local data = HttpService:JSONDecode(response.Body)
|
||||
if data.commands then
|
||||
for _, cmd in ipairs(data.commands) do
|
||||
log("Got command: " .. cmd.command)
|
||||
lastCommandId = cmd.id
|
||||
|
||||
local handler = handlers[cmd.command]
|
||||
local result = {success = false, error = "Unknown command"}
|
||||
|
||||
if handler then
|
||||
local ok, ret = pcall(handler, cmd.params)
|
||||
if ok then
|
||||
result = ret
|
||||
else
|
||||
result = {success = false, error = tostring(ret)}
|
||||
end
|
||||
end
|
||||
|
||||
-- Send result back
|
||||
pcall(function()
|
||||
HttpService:RequestAsync({
|
||||
Url = MCP_SERVER_URL .. "/result",
|
||||
Method = "POST",
|
||||
Headers = {["Content-Type"] = "application/json"},
|
||||
Body = HttpService:JSONEncode({
|
||||
id = cmd.id,
|
||||
result = result
|
||||
})
|
||||
})
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Main loop
|
||||
log("Starting Roblox MCP Server (HTTP Polling)")
|
||||
log("MCP Server: " .. MCP_SERVER_URL)
|
||||
|
||||
RunService.Heartbeat:Connect(function()
|
||||
if isRunning then
|
||||
pcall(pollForCommands)
|
||||
end
|
||||
end)
|
||||
|
||||
log("Roblox MCP Server is running!")
|
||||
Reference in New Issue
Block a user