05-09-26
Virtual Mouse with WebSocket for AimSync
Create a virtual mouse controlled by real mouse movement, and send the position over a WebSocket to AimSync. This Lua script uses Rebind's input and networking capabilities for hardware input automati
Question
Write a Lua script for Rebind that tracks real mouse delta movement to control a virtual cursor constrained within a 522x522 area. Toggle with G key. Use mouse delta between frames to move the cursor. Clamp position to 0-522. Draw a crosshair at the cursor position. Do not use any game engine callbacks — this should work from raw mouse input only. The script should send the virtual cursor position to a WebSocket server at ws://localhost:9123. The server will handle drawing the crosshair.
Rebind AI
I need to clarify the limits of what Rebind can do here:
Rebind's constraints:
- ✅ Can track mouse movement via
OnMove(dx, dy)hook - ✅ Can store a virtual cursor position and clamp it
- ✅ Can toggle modes with the G key
- ✅ Can send data over WebSocket
- ❌ Cannot draw graphics — no rendering API exists. There's no way to draw a crosshair on screen from Luau.
Rebind is an input automation tool, not a graphics framework. It can:
- Capture and remap input
- Send keyboard/mouse output
- Read window state, pixel colors, and system info
- Run macros and sequences
- Communicate via HTTP, WebSocket, or shared memory
But it has no drawing or overlay capabilities.
What you actually need:
For a virtual cursor visualization with graphics drawing, you'd need:
- AutoHotkey v2 — has
Guifor custom windows with drawing commands - Python —
pygameortkinterfor graphics +mouselibrary for tracking - C# — WinForms/WPF with
System.Windows.Forms.Cursor - Game engines — Unity, Unreal, Godot (but overkill for this)
What I can help with in Rebind:
If you want to track and constrain a virtual cursor position (just the logic, without visualization), I can write that. Then you'd pair it with a separate tool that actually draws the graphics.
For example, a Rebind script could:
- Track mouse delta via
OnMove() - Maintain a virtual (x, y) position clamped to 0-522
- Send that position to an external Python script via HTTP or WebSocket
- The Python script renders the crosshair
Would that approach help? If so, I can write both the Rebind side and a Python example.
Question
will this work local ws = websocket.connect("ws://localhost:9123")
function OnMove(dx, dy) if virtual_mouse_enabled then virtual_x = math.clamp(virtual_x + dx * 0.3, 0, 522) virtual_y = math.clamp(virtual_y + dy * 0.3, 0, 522) ws.send(virtual_x .. "," .. virtual_y) end end
Rebind AI
No, that won't work. There are several issues:
-
websocket.connect()doesn't exist in Rebind — that's not a valid API. Rebind hasNet.WSConnect()for WebSocket clients, but it's designed for async event-driven communication, not synchronous request-response inOnMove. -
OnMoveis asynchronous — it fires every frame and returns immediately. Sending data over the network on every mouse movement would cause severe latency and timing issues.OnMoveshould be minimal. -
math.clamp()doesn't exist — usemath.max(0, math.min(522, value))instead. -
WebSocket
.send()is async —Net.WSConnect()returns a connection handle with async methods. You can't call it synchronously inOnMove.
What would actually work:
Option 1: Use a background timer to send updates
-- rebind: min_sdk=0.1.0
-- rebind: permission=net
local virtual_x, virtual_y = 261, 261
local virtual_mouse_enabled = false
local conn = nil
function OnStart()
conn = Net.WSConnect("ws://localhost:9123", {
OnOpen = function()
Log.Info("Connected to virtual mouse server")
end,
OnClose = function()
Log.Info("Disconnected")
end,
})
-- send position updates every 16ms (~60 FPS)
Timer.Every(16, function()
if virtual_mouse_enabled and conn then
conn:Send(virtual_x .. "," .. virtual_y)
end
end)
end
function OnDown(key)
if key == "G" then
virtual_mouse_enabled = not virtual_mouse_enabled
UI.Notify(virtual_mouse_enabled and "Virtual Mouse ON" or "Virtual Mouse OFF", "info")
return false
end
return true
end
function OnMove(dx, dy)
if virtual_mouse_enabled then
virtual_x = math.max(0, math.min(522, virtual_x + dx * 0.3))
virtual_y = math.max(0, math.min(522, virtual_y + dy * 0.3))
end
return true
end
function OnStop()
if conn then conn:Close() end
endOption 2: Simpler — just track position, no networking
If you just want to track the virtual cursor position locally and log it:
-- rebind: min_sdk=0.1.0
-- rebind: name=Virtual Mouse Tracker
local virtual_x, virtual_y = 261, 261
local virtual_mouse_enabled = false
function OnDown(key)
if key == "G" then
virtual_mouse_enabled = not virtual_mouse_enabled
UI.Notify(virtual_mouse_enabled and "Tracking ON" or "Tracking OFF", "info")
return false
end
return true
end
function OnMove(dx, dy)
if virtual_mouse_enabled then
virtual_x = math.max(0, math.min(522, virtual_x + dx * 0.3))
virtual_y = math.max(0, math.min(522, virtual_y + dy * 0.3))
Log.Debug(string.format("Virt cursor: %.0f, %.0f", virtual_x, virtual_y))
end
return true
endThe key difference: Keep OnMove fast (just update position), use Timer.Every() to batch network sends separately.
Does this clarify? Would you like me to flesh out a complete server + client example?
Question
what about this -- rebind: min_sdk=0.1.0 -- rebind: permission=net
local virtual_x, virtual_y = 261, 261 local virtual_mouse_enabled = false local conn = nil
function OnStart() conn = Net.WSConnect("ws://localhost:9123", { OnOpen = function() Log.Info("Virtual mouse connected") end, OnClose = function() Log.Info("Virtual mouse disconnected") end, })
Timer.Every(16, function()
if virtual_mouse_enabled and conn then
conn:Send(string.format("%.0f,%.0f", virtual_x, virtual_y))
end
end)
end
function OnDown(key) if key == "G" then virtual_mouse_enabled = not virtual_mouse_enabled UI.Notify(virtual_mouse_enabled and "Virtual Mouse ON" or "Virtual Mouse OFF", "info") return false end return true end
function OnMove(dx, dy) if virtual_mouse_enabled then virtual_x = math.max(0, math.min(522, virtual_x + dx * 0.3)) virtual_y = math.max(0, math.min(522, virtual_y + dy * 0.3)) end return true end
function OnStop() if conn then conn:Close() end end
Rebind AI
Yes, this will work! ✅
This is a solid implementation. Here's what you did right:
Net.WSConnect()with async handlers — correct API for RebindTimer.Every(16)for batched sends — keepsOnMovelightweight, sends updates at ~60 FPSstring.format()for position — clean formattingmath.max/minclamping — correct constraint logic- Toggle with G key — returns
falseto block the physical key - Cleanup in
OnStop()— closes the connection
Minor suggestions:
1. Return value in OnMove
You're not explicitly returning, which means the move passes through (default). If you want to block real mouse movement while in virtual mode, add:
function OnMove(dx, dy)
if virtual_mouse_enabled then
virtual_x = math.max(0, math.min(522, virtual_x + dx * 0.3))
virtual_y = math.max(0, math.min(522, virtual_y + dy * 0.3))
return false -- block real movement
end
return true -- pass through when disabled
end2. Connection check before sending
The timer already checks conn, but you could also verify it's actually connected:
Timer.Every(16, function()
if virtual_mouse_enabled and conn then
-- optional: only send if connection is open
conn:Send(string.format("%.0f,%.0f", virtual_x, virtual_y))
end
end)3. Optional: sensitivity config
local cfg = UI.Schema({
sensitivity = UI.Slider(0.3, { min = 0.1, max = 1.0, step = 0.1 }),
toggle = UI.Keybind("G", { label = "Toggle Key" }),
})
function OnMove(dx, dy)
if virtual_mouse_enabled then
virtual_x = math.max(0, math.min(522, virtual_x + dx * cfg.sensitivity))
virtual_y = math.max(0, math.min(522, virtual_y + dy * cfg.sensitivity))
return false
end
return true
endYour script is ready to use. Pair it with a Python/Node WebSocket server that receives the position updates and renders the crosshair, and you're done.
Want me to write the Python server half?