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

View file

@ -0,0 +1,103 @@
// Package input — humanize.go provides human-like behavior randomization.
package input
import (
"image"
"math/rand"
"sync/atomic"
"time"
)
// HumanProfile defines behavior parameters for human-like input.
type HumanProfile struct {
ReactionMin time.Duration // min reaction delay
ReactionMax time.Duration // max reaction delay
MouseSpeedMin float64 // min pixels per second
MouseSpeedMax float64 // max pixels per second
ClickJitter int // pixel jitter on clicks
HesitationChance float64 // chance of extra pause (0-1)
HesitationMin time.Duration
HesitationMax time.Duration
}
// DefaultProfile returns a realistic human behavior profile.
func DefaultProfile() HumanProfile {
return HumanProfile{
ReactionMin: 150 * time.Millisecond,
ReactionMax: 450 * time.Millisecond,
MouseSpeedMin: 400,
MouseSpeedMax: 1200,
ClickJitter: 3,
HesitationChance: 0.1,
HesitationMin: 300 * time.Millisecond,
HesitationMax: 1200 * time.Millisecond,
}
}
// Humanizer applies human-like randomization to bot actions.
type Humanizer struct {
Profile HumanProfile
actionCount atomic.Int64
}
// NewHumanizer creates a humanizer with the given profile.
func NewHumanizer(profile HumanProfile) *Humanizer {
return &Humanizer{Profile: profile}
}
// ReactionDelay returns a randomized human-like reaction delay.
func (h *Humanizer) ReactionDelay() time.Duration {
minMs := h.Profile.ReactionMin.Milliseconds()
maxMs := h.Profile.ReactionMax.Milliseconds()
base := time.Duration(minMs+rand.Int63n(maxMs-minMs)) * time.Millisecond
// Occasional hesitation
if rand.Float64() < h.Profile.HesitationChance {
hesMinMs := h.Profile.HesitationMin.Milliseconds()
hesMaxMs := h.Profile.HesitationMax.Milliseconds()
base += time.Duration(hesMinMs+rand.Int63n(hesMaxMs-hesMinMs)) * time.Millisecond
}
// Slight fatigue factor
actions := float64(h.actionCount.Load())
fatigue := min(actions/1000.0, 0.3)
base = time.Duration(float64(base) * (1 + fatigue*rand.Float64()))
return base
}
// Wait pauses for a human-like reaction delay.
func (h *Humanizer) Wait() {
time.Sleep(h.ReactionDelay())
h.actionCount.Add(1)
}
// WaitMs pauses for baseMs ± varianceMs with human randomization.
func (h *Humanizer) WaitMs(baseMs, varianceMs int) {
actual := baseMs + rand.Intn(2*varianceMs+1) - varianceMs
if actual < 0 {
actual = 0
}
time.Sleep(time.Duration(actual) * time.Millisecond)
}
// JitterPosition adds random offset to a click position.
func (h *Humanizer) JitterPosition(pos image.Point) image.Point {
j := h.Profile.ClickJitter
return image.Point{
X: pos.X + rand.Intn(2*j+1) - j,
Y: pos.Y + rand.Intn(2*j+1) - j,
}
}
// MouseSpeed returns a randomized mouse movement speed.
func (h *Humanizer) MouseSpeed() float64 {
return h.Profile.MouseSpeedMin + rand.Float64()*(h.Profile.MouseSpeedMax-h.Profile.MouseSpeedMin)
}
func min(a, b float64) float64 {
if a < b {
return a
}
return b
}