Rewrite to Go: engine, plugin system, D2R plugin, API, loot filter

This commit is contained in:
Hoid 2026-02-14 09:43:39 +00:00
parent e0282a7111
commit 3b363192f2
60 changed files with 1576 additions and 3407 deletions

162
pkg/engine/input/input.go Normal file
View file

@ -0,0 +1,162 @@
// Package input provides human-like mouse and keyboard simulation.
//
// Mouse movement uses Bézier curves with natural acceleration.
// All inputs include randomized timing to mimic human behavior.
// Platform-specific backends: SendInput (Windows), X11/uinput (Linux).
package input
import (
"image"
"math"
"math/rand"
"time"
)
// MouseController handles human-like mouse movement and clicks.
type MouseController struct {
humanizer *Humanizer
}
// NewMouseController creates a mouse controller with the given humanizer.
func NewMouseController(h *Humanizer) *MouseController {
return &MouseController{humanizer: h}
}
// MoveTo moves the mouse to target using a Bézier curve.
func (m *MouseController) MoveTo(target image.Point) {
// Get current position
current := m.GetPosition()
// Generate Bézier control points
points := m.bezierPath(current, target)
// Animate along the path
speed := m.humanizer.MouseSpeed()
totalDist := m.pathLength(points)
steps := int(totalDist / speed * 1000) // ms-based steps
if steps < 5 {
steps = 5
}
for i := 1; i <= steps; i++ {
t := float64(i) / float64(steps)
// Ease in-out for natural acceleration
t = m.easeInOut(t)
p := m.evalBezier(points, t)
m.setPosition(p)
time.Sleep(time.Millisecond)
}
}
// Click performs a mouse click at the current position.
func (m *MouseController) Click() {
m.humanizer.Wait()
// TODO: Platform-specific click (SendInput / X11)
// Randomize hold duration
holdMs := 50 + rand.Intn(80)
time.Sleep(time.Duration(holdMs) * time.Millisecond)
}
// ClickAt moves to position and clicks.
func (m *MouseController) ClickAt(pos image.Point) {
jittered := m.humanizer.JitterPosition(pos)
m.MoveTo(jittered)
m.Click()
}
// RightClick performs a right mouse click.
func (m *MouseController) RightClick() {
m.humanizer.Wait()
holdMs := 50 + rand.Intn(80)
time.Sleep(time.Duration(holdMs) * time.Millisecond)
}
// GetPosition returns current mouse position.
func (m *MouseController) GetPosition() image.Point {
// TODO: Platform-specific implementation
return image.Point{}
}
func (m *MouseController) setPosition(p image.Point) {
// TODO: Platform-specific implementation
}
// bezierPath generates a cubic Bézier curve with randomized control points.
func (m *MouseController) bezierPath(start, end image.Point) [4]image.Point {
dx := float64(end.X - start.X)
dy := float64(end.Y - start.Y)
// Randomize control points for natural curvature
cp1 := image.Point{
X: start.X + int(dx*0.25+rand.Float64()*50-25),
Y: start.Y + int(dy*0.25+rand.Float64()*50-25),
}
cp2 := image.Point{
X: start.X + int(dx*0.75+rand.Float64()*50-25),
Y: start.Y + int(dy*0.75+rand.Float64()*50-25),
}
return [4]image.Point{start, cp1, cp2, end}
}
// evalBezier evaluates a cubic Bézier curve at parameter t.
func (m *MouseController) evalBezier(pts [4]image.Point, t float64) image.Point {
u := 1 - t
return image.Point{
X: int(u*u*u*float64(pts[0].X) + 3*u*u*t*float64(pts[1].X) + 3*u*t*t*float64(pts[2].X) + t*t*t*float64(pts[3].X)),
Y: int(u*u*u*float64(pts[0].Y) + 3*u*u*t*float64(pts[1].Y) + 3*u*t*t*float64(pts[2].Y) + t*t*t*float64(pts[3].Y)),
}
}
// easeInOut applies ease-in-out for natural mouse acceleration.
func (m *MouseController) easeInOut(t float64) float64 {
return t * t * (3 - 2*t)
}
func (m *MouseController) pathLength(pts [4]image.Point) float64 {
length := 0.0
prev := pts[0]
for i := 1; i <= 20; i++ {
t := float64(i) / 20.0
p := m.evalBezier(pts, t)
dx := float64(p.X - prev.X)
dy := float64(p.Y - prev.Y)
length += math.Sqrt(dx*dx + dy*dy)
prev = p
}
return length
}
// KeyboardController handles human-like keyboard input.
type KeyboardController struct {
humanizer *Humanizer
}
// NewKeyboardController creates a keyboard controller.
func NewKeyboardController(h *Humanizer) *KeyboardController {
return &KeyboardController{humanizer: h}
}
// PressKey presses and releases a key with human-like timing.
func (k *KeyboardController) PressKey(key string) {
k.humanizer.Wait()
// TODO: Platform-specific key press
holdMs := 30 + rand.Intn(70)
time.Sleep(time.Duration(holdMs) * time.Millisecond)
}
// TypeText types text with randomized inter-key delays.
func (k *KeyboardController) TypeText(text string) {
for _, ch := range text {
k.PressKey(string(ch))
delay := 30 + rand.Intn(120) // 30-150ms between keys
time.Sleep(time.Duration(delay) * time.Millisecond)
}
}
// HoldKey holds a key down for a duration.
func (k *KeyboardController) HoldKey(key string, durationMs int) {
// TODO: Platform-specific key down/up
variance := rand.Intn(durationMs / 5)
time.Sleep(time.Duration(durationMs+variance) * time.Millisecond)
}