
NeuroLag
A smart, resource-aware optimization plugin that dynamically adjusts Mob AI based on server TPS and RAM to ensure a lag-free SMP experience
379
4
Список изменений
[1.7.1] — 2026-05-18 — Bug Fix Release
This release corrects five bugs identified in a full source-code audit of 1.7.0. Three of them were silent correctness failures that made advertised features behave differently from their documented intent without producing any visible error.
🔴 Critical Fixes
Fixed — LagEngine — Safe Mode FOLLOW_RANGE silently overwritten every tick
- Root cause: After
SafeModeOptimizer.applySafeMode()setFOLLOW_RANGE = 4.0, the lambda inapplyAiBatched()fell through to an unconditionalattr.setBaseValue(attr.getDefaultValue() * multiplier)at the bottom of the loop. In CRITICAL statemultiplier = 1.0, so the attribute was reset to its default value on every single tick — completely negating the FOLLOW_RANGE reduction that Safe Mode is supposed to maintain. - Fix: Added
continueimmediately aftersafeModeOptimizer.applySafeMode(mob)to skip the unconditionalsetBaseValueline, matching the existing pattern used by the pathfinding-distance branch above it. - Impact: Safe Mode now actually reduces mob target-scanning range during CRITICAL
state as documented. Servers using
safe-mode: truewill see measurably lower entity processing cost during lag spikes.
Fixed — SafeModeOptimizer — NullPointerException crash on certain entity types
- Root cause:
disableExpensiveAI()and the previousrestoreAI()calledmob.getAttribute(FOLLOW_RANGE).setBaseValue(...)without a null-check.getAttribute()returnsnullfor entity types that do not exposeFOLLOW_RANGE(e.g. Slime, Bat, some modded mobs), causing an unhandledNullPointerExceptionthat bubbled up through the scheduler and printed a stack trace every tick. - Fix: Extracted the result of
getAttribute()into a local variable and guarded both call sites withif (attr != null).
Fixed — SafeModeOptimizer — restoreAI() used a hardcoded FOLLOW_RANGE table
- Root cause: The previous implementation maintained an internal
switchtable mappingEntityType → doublefor the restore path. This table was incomplete (missing dozens of types) and ignored any custom attributes set by other plugins or datapacks, silently restoring the wrong range. - Fix: Replaced the hardcoded table with
attr.getDefaultValue(), which reads the actual server-side default and therefore works correctly for all entity types including custom ones.
🟡 Medium Fixes
Fixed — LagEngine — applyDifficultyScaling() had HARD and EASY inverted
- Root cause:
case HARD → tps + 1.0raised the effective TPS, causing optimizations to trigger later on Hard worlds.case EASY → tps - 1.0lowered it, triggering optimizations earlier on Easy worlds. Both are the opposite of what the logic requires: Hard mobs pathfind more aggressively and consume more CPU; optimizations should therefore activate sooner, not later. - Fix: Swapped the offsets —
EASY → tps + 1.0,HARD → tps - 1.0. - Impact: Servers running Hard difficulty worlds will now have mob AI throttled earlier under load, meaningfully reducing the lag window that was previously unaddressed.
Fixed — WebDashboard — Rate-limit map memory leak on long-running servers
- Root cause:
rateLimitCountersandrateLimitWindowsonly cleared onstop(). Each unique IP that ever touched the dashboard created a permanent entry. On servers with public web dashboards, scanner/probe traffic could accumulate thousands of entries over days of uptime without any mechanism to reclaim the memory. - Fix: At the start of each
checkRateLimit()call, entries whose 60-second window has already expired are pruned viaremoveIf, andrateLimitCountersis kept in sync viaretainAll. Cost is amortised O(n) across all incoming requests — negligible compared to the HTTP overhead of each call.
🛠️ Code Quality
Documented — LagEngine — AIThrottler field is intentionally unused
- The 1.7.0 refactor extracted
AIThrottleras a separate class but did not update theapplyAiBatched()call site to delegate to it. The inline throttle logic continued to run usingLagEngine's ownthrottleCounters, leavingAIThrottleras unreachable code with its own duplicate counter map. - This release adds an explicit
NOTEcomment on the field explaining why the field exists, why it is not called, and what is required before delegation can be completed safely. No behaviour change — cleanup is deferred to a dedicated refactor release.
Метаданные
Канал релиза
Release
Номер версии
1.7.1
Загрузчики
BukkitPaperPurpurSpigot
Версии игры
1.21–1.21.11
Загрузок
37
Дата публикации
3 нед. назад
