← Назад к ресурсам

Where's my Brain (WMB)

Smart mob AI optimization mod

Modrinth management optimization utility

Описание

# WHERE'S MY BRAIN (WMB) A lightweight, loader-agnostic Minecraft 1.20.1 optimization mod focused on smarter mob AI scheduling, distance-aware throttling, and adaptive auto-tuning. Keep gameplay feel near players while cutting wasted CPU on far-away or idle mobs. Works on both Forge and Fabric via Architectury. [![Join our Discord](https://img.shields.io/badge/Join-Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/QM5beZpkYT) --- ## Features - Async Entity Tracking - Off-thread per-player entity visibility/tracking decisions to reduce main thread work. - Global or per-dimension thread pools with adaptive backpressure (queue-aware scheduling). - Respects `asyncTracker.updateInterval`, `cacheDuration`, and `maxTrackingDistance`. - Integrates with AutoTuner to adjust scheduling under load. - Timeouts and graceful fallbacks keep the main thread safe. - Regional/Chunk-based TPS Manager (R‑TPS) - Divides each dimension into square regions (default: `regionalTPS.regionSize = 4` chunks per side) and continuously measures load per region. - Tracks per-region metrics: average AI time (ms), average memory (MB), player presence, redstone updates, BE/scheduled tick counts, and activity recency. - Applies scalable tick multipliers per region using named levels (e.g., `normal=1`, `warning=2`, `critical=4`). - Hysteresis (`regionalTPS.hysteresisPct`, default 0.15) prevents flip‑flops when load hovers near thresholds. - Static overrides let you pin specific regions to a level. - Safety: global TPS is computed over a sliding window and emergency triggers are gated by warm‑up and cooldown to avoid false alarms. - Gating integrates with chunk random/scheduled ticks to cut work in stressed regions while remaining invisible near players. - Distance-based AI Bucketing (DAB) - Dynamically throttles AI ticks based on each mob’s nearest-player distance. - Per-dimension and per-entity overrides. - Hysteresis deadband to prevent thrashing near thresholds. - Sensible exemptions (leashed, named, owned/tamed, persistent, and configurable boss exemptions). - Proximity Snapshot Service - Centralizes nearest-player computations to a periodic snapshot, reducing redundant work. - Mob-side cache reduced to 2 ticks for responsive DAB updates with minimal overhead. - Pathfinding Optimizations - Minimum per-mob path recalculation interval and grouping window. - Optional experimental path sharing. - Caching with TTL to avoid repeated path solves. - Auto-Tuning (PID) - Targets a desired average tick time (ms) and gently adjusts pathfinding recalc interval. - PID controller (kp/ki/kd) with integral clamping and step-limits for smooth convergence. - Transparently falls back to a simple step controller if PID gains are zero. - Optional AI Culling (Conservative) - Skip AI processing for far, idle, and unengaged mobs behind multiple safety gates. - Optional Visibility Culling (Conservative) - Skip AI for mobs far outside any player’s chunk range, with the same safety gates. - Metrics and Command - Lightweight internal counters for `/wmb stats`. - See DAB thresholds, proximity settings, pathfinding parameters, and tuner state. --- ## How It Works - DAB continuously places each mob into a distance bucket (near/mid/far/distant) relative to the nearest player and assigns a tick interval multiplier per bucket. - Async Entity Tracking computes per-player tracked entity sets off-thread and applies updates post-tick; intervals adapt via tuner and backpressure. - The proximity service snapshots player positions every N ticks (configurable) to amortize distance queries. - Pathfinding and AI recalculations are rate-limited with per-mob minimum intervals and optional grouping. - The Auto Tuner reads average tick time over a window and adjusts `pathfinding.minRecalcInterval` to steer the server towards `tuning.targetTickMs`. - Culling and visibility features add optional, conservative gates to skip AI when it’s safe to do so. --- ## Diagrams ### Async Entity Tracking: Flow ``` [Server Tick] ├─ PreTick │ ├─ shouldSchedulePlayer?(interval + tuner + backpressure) │ ├─ Snapshot(Player) │ ├─ CollectEntitySnapshots (AABB around player) │ └─ Submit Task → Executor │ └─ [Off-thread] │ ├─ Filter by distance ≤ maxTrackingDistance (2D) │ ├─ Diff with current tracked set → {toAdd, toRemove} │ └─ Enqueue TrackingResult └─ PostTick ├─ Drain completed results (batched) ├─ Apply adds/removes to tracking sets ├─ Update metrics (durations, queue size, counts) └─ Periodic maintenance (cleanup/disconnects) ``` ### Threading Model: Global vs Per-Dimension Pools ``` Option A: Global Pool [AsyncTracker Executor (N threads)] ↑ tasks from all dimensions Option B: Per-Dimension Pools [Overworld Executor (M)] [Nether Executor (M)] [End Executor (M)] ↑ OW tasks ↑ Nether tasks ↑ End tasks Backpressure: bounded queues + CallerRunsPolicy; scheduling slows when queues grow. ``` ### Auto‑Tuner: Control Loop ``` tickNanos → EMA → window(avg) │ ▼ Controller (PID or Simple) │ ┌───────┴─────────────────────────────┐ │ │ pathfinding.minRecalcInterval += step trackerIntervalAddend = clamp(-step) │ │ cooldown ticks prevent rapid toggling additive scheduling shift for tracker ``` ### DAB Bucketing and Hysteresis ``` distance (blocks) → 0 ── d0 ── d1 ── d2 ──▶ bucket NEAR MID FAR DISTANT multiplier x1 x2 x4 x8 (defaults; configurable) hysteresisBlocks (±h) creates a deadband around d0/d1/d2 to reduce bucket flipping. ``` ### Regional TPS: Decision Pipeline ``` [Server Tick] ├─ PreTick │ ├─ Global TPS sample ← steady after 5+ samples; clamped [0..20]; warm‑up (≥200 ticks) before emergency checks │ └─ Update player→region mapping ├─ PostTick (per region) │ ├─ Accumulate AI nanos, BE & scheduled ticks, redstone updates, memory, players │ ├─ Windowed averages (regionalTPS.windowTicks) │ ├─ Decide target level using thresholds + hysteresis │ ├─ Smoothly adjust region multiplier toward target (±1 per tick) │ └─ Apply gating hooks (e.g., chunk random/scheduled ticks) └─ Global ├─ Emergency trigger if: warm‑up passed ∧ samples≥20 ∧ TPS 0`, `ki = 0`, `kd = 0`. Suggested: `kp = 0.25`. - If you see steady-state error, gently introduce `ki` (e.g., `0.01–0.05`). - If you overshoot or oscillate, add `kd` (e.g., `0.05–0.2`). - Keep `maxStepPerWindow` small (1–2) for smoothness. Clamp integral via `integralMaxAbs`. - Always bound the actuator with `minRecalcMin`/`minRecalcMax`. - Tracker integration: the tuner also adjusts tracker scheduling additively; leave `asyncTracker.updateInterval` moderate and let the tuner smooth load. --- ## Compatibility - Designed to be conservative and safe around gameplay-critical AI. - Bosses, named, leashed, owned/tamed, and persistent mobs are protected by default. - Should be broadly compatible; experimental features (like path sharing) are opt-in. --- ## FAQ - Does DAB change combat behavior near the player? - No. The `near` bucket usually uses a multiplier of `1`, keeping AI behavior responsive up close. - Does async tracking cause entity pop‑in or desync? - No. Tracking sets are computed off‑thread but applied safely on the main thread each tick. Timeouts fall back gracefully. - What if my server has multiple heavy dimensions? - Enable `asyncTracker.perDimensionPools` to isolate tracker load by dimension and size `threadPoolSizePerDim` accordingly. - Will auto-tuning fight my manual settings? - The tuner only adjusts `pathfinding.minRecalcInterval`. Everything else remains exactly as configured. - What if I don’t want any culling? - Both culling systems are disabled by default. They’re strictly opt-in and conservative. - Is this a magic TPS booster? - No. It’s a set of intelligent trade-offs to save CPU in situations where it doesn’t affect gameplay feel. --- ## Changelog ### 1.2 (2025-09-04) - New — Regional/Chunk-based TPS Manager (R‑TPS) - Per‑region load tracking (avg AI ms, memory MB, players, redstone updates, BE/scheduled ticks, activity). - Named scaling levels (e.g., normal=1, warning=2, critical=4) applied as tick multipliers per region. - Hysteresis via `regionalTPS.hysteresisPct` (default 0.15) to stabilize level transitions. - Static region overrides to pin hotspots to specific levels. - Integrates with chunk random/scheduled tick gating; invisible near players. - New — Heatmap UI for Regional TPS - Request with `/wmb heatmap [radius]`; reopen last heatmap with the `H` key. - Mouse wheel zoom; right‑click drag to pan; live window requests while panning/zooming. - Modes: AI ms, Mem MB, Players, Priority; LOD toggle (merged vs per‑region tiles). - Tooltips and a detailed side panel (emergency state, target multiplier, consecutive good/bad ticks, histories). - Global TPS display in the header. - Improvements — Global TPS measurement and safety - Lazy‑init tick timing; compute TPS only after 5+ samples; clamp to [0..20]. - Gate emergency triggers until warm‑up (≥200 ticks) and require ≥20 samples; add cooldown to avoid log spam. - Improvements — Regional decisions and sampling - Applied hysteresis to regional scaling decisions; introduced `levelIndex` to track transitions. - Normalized Y sampling for region gating to `level.getMinBuildHeight() + 1`. - Networking & Client - Updated heatmap/detail serialization to include memory, player counts, priority, global TPS, target multiplier, and histories. - Client can refresh the existing screen (`setHeatmap`) without reopening; remembers last heatmap for the `H` key. - Fixes - Heatmap tooltip compile error fixed by initializing local variables. - Eliminated false global TPS emergencies at startup or sporadic spikes; reduced warning spam. - Config - Config schema bumped to 5; added `regionalTPS.*` keys including `hysteresisPct`. - Defaults and inline comments updated in `wmb.toml`. - Migration Notes - Existing configs auto‑merge new keys and bump `configVersion` safely. Review `regionalTPS.thresholds` and `regionalTPS.scaling.levels` for your pack. --- ## License See `LICENSE.txt` in the repository.