Compatibility
Minecraft: Java Edition
1.21.x
1.20.x
1.2.x
Platforms
Creators
Details
Changelog
Added — Per‑Chunk Entity Limiter (Armor Stands, Boats, etc.)
- New limiter that caps the number of specified non-mob entities per chunk (e.g., armor stands, boats, minecarts, item frames, paintings).
- Actively detects over-cap scenarios even if players move entities into a chunk (e.g., via water streams, pistons)—not just at spawn time.
- Automatically removes the excess entities beyond the configured cap and sends a staff notification with world, chunk coordinates, entity type, and count removed.
- Fully configurable caps per entity type, worlds to include/exclude, check intervals, selection priority for removal, and notification throttling.
- Optional bypass permission for trusted users so their placed entities are not counted or removed.
Configuration
- Configure per-entity caps per chunk, globally or per-world.
- Choose which entities are monitored (e.g., ARMOR_STAND, BOAT, MINECART variants, ITEM_FRAME, PAINTING, TNT_MINECART, etc.).
- Control how “excess” entities are chosen for removal (e.g., oldest first, furthest from center, random) to minimize disruption.
- Set staff notification options (enabled, message format, permissions, cooldown to prevent spam) and console logging.
- Define excluded worlds or regions if needed.
Notifications and Permissions
- Staff alert sent on first detection and then rate-limited: e.g., "[ClearLaggEnhanced] Chunk x=12,z=-34 in world ‘survival’: removed 8 excess ARMOR_STAND (limit=12)."
- Console log entry mirroring the alert (optional).
- Suggested permissions (adjust to your plugin’s scheme):
- clearlagenhanced.limiter.notify — receive staff alerts
- clearlagenhanced.limiter.bypass — player’s entities aren’t counted/removed
Behavior
- Triggers on spawn, chunk load, and periodic sweeps to catch entities moved post-spawn (water, pistons, minecarts, leads, boats, etc.).
- Removal is safe and batched to avoid lag spikes. Limits apply per chunk to prevent dense stacks.
Example — How It Works
- Example configuration (YAML-style, adapt to your config format):
entity-limiter:
enabled: true
check-interval-ticks: 200 # every 10 seconds
notify:
enabled: true
permission: clearlagenhanced.limiter.notify
cooldown-seconds: 60
selection-policy: OLDEST # OLDEST | FURTHEST | RANDOM
limits:
ARMOR_STAND: 12
BOAT: 8
MINECART: 16
worlds:
include: ["survival", "skyblock"]
exclude: []
bypass-permission: clearlagenhanced.limiter.bypass
- In-game scenario:
- A player sets up a water stream that pushes 30 armor stands into a single chunk.
- On the next sweep (or when the chunk loads), the plugin detects 30 ARMOR_STAND in that chunk where the limit is 12.
- The plugin removes 18 excess armor stands using the OLDEST policy.
- Staff online with clearlagenhanced.limiter.notify see: "[ClearLaggEnhanced] Chunk x=120,z=45 (survival): removed 18 excess ARMOR_STAND (limit=12)."
- Console logs the same event (optional), and further alerts for this chunk are suppressed for the configured cooldown period to prevent spam.
Notes
- If you already use other limiters (mobs, spawners, hoppers, redstone), this feature operates independently and complements them.
- Recommended: tune limits conservatively at first; then adjust based on typical player builds.
- Consider granting the bypass permission to trusted builders to avoid accidental cleanup during creative projects.
Added
- Hopper limiter: Cached per-chunk hopper counts to enable soft-cap–based cooldown scaling.
- New concurrent cache:
hopperCountByChunkkeyed as"world:x,z". - Lazy initialization: If a loaded chunk has no cache entry at use time, it’s scanned and cached.
- Event-driven updates:
ChunkLoadEvent: scan and seed cache.ChunkUnloadEvent: remove cache and related per-chunk tick maps to prevent leaks.BlockPlaceEvent(HOPPER): increment chunk count.BlockBreakEvent(HOPPER): decrement chunk count (floors at 0).
- New concurrent cache:
- Debug messaging for throttling per chunk uses the existing key
debug.hopper.throttlingfrommessages.yml(rate limited to once per 100 ticks per chunk).
Changed
- Hopper cooldown computation now properly applies the soft cap:
- Base cooldown:
lag-prevention.hopper-limiter.transfer-cooldownticks (min 1). - If hopper count in the chunk >
max-hoppers-per-chunk, effective cooldown increases by2 * (excess)ticks.
- Base cooldown:
- The count method is now cache-backed:
countHoppersInChunkCached(Chunk)returns the cached number, performs a synchronous scan if necessary for loaded chunks, and returns 0 for unloaded chunks (no forced chunk loads).
Fixed
- Soft-cap effect was previously ineffective because hopper counts always returned 0; now it reflects real counts and increases cooldown in hopper-dense chunks.
Performance/Memory
- Event-driven cache maintenance avoids per-tick scanning.
- Lazy scan only occurs on first access for loaded chunks without a cache entry.
- Cleanup on
ChunkUnloadEventprevents memory leaks by removing:hopperCountByChunk,lastMoveTickByChunk,lastLogTickByChunkentries for the chunk.
Compatibility
- Java 17+, Spigot/Paper 1.17+ APIs.
- No changes to permissions, commands, or message keys.
- Configuration keys reused:
lag-prevention.hopper-limiter.enabledlag-prevention.hopper-limiter.transfer-cooldownlag-prevention.hopper-limiter.max-hoppers-per-chunkdebug
How to test the new hopper limiter behavior
1) Build and install
- Build the plugin (build completed successfully during this session).
- Place the generated JAR into your server’s plugins folder.
- Start the server.
2) Configure
In plugins/ClearLaggEnhanced/config.yml:
- Ensure hopper limiter is enabled:
lag-prevention.hopper-limiter.enabled: true
- Set a visible base cooldown (example):
lag-prevention.hopper-limiter.transfer-cooldown: 8
- Set a testable soft cap (example):
lag-prevention.hopper-limiter.max-hoppers-per-chunk: 5
- Optional: enable debug to see rate-limited throttling notices:
debug: true
Reload:
/lagg reload(or restart the server).
3) Baseline verification (≤ cap)
- In a single chunk, place 5 hoppers (equal to the configured cap).
- Set up a simple hopper-to-chest item transfer.
- Observe transfers occur at the base cooldown (8 ticks in the example).
- With debug on, you should not see persistent throttling logs for this chunk.
4) Soft-cap scaling (> cap)
- Increase hoppers in the same chunk to 8 (3 above cap).
- Expected effective cooldown:
base + (2 * excess)=8 + (2*3) = 14ticks. - Observe that transfers are slower (roughly 75% speed of baseline).
- With debug enabled, you should periodically see:
debug.hopper.throttlingonce per ~100 ticks per chunk (rate-limited).
- Reduce back to 5 hoppers; transfers should return to the base rate on the next allowed move.
5) Event-driven cache updates
- Block place:
- Place a hopper in the test chunk and confirm the slowdown increases immediately (no server reload).
- Block break:
- Break a hopper and confirm slowdown decreases accordingly (no server reload).
- Chunk load:
- Move far enough away (or use a second account) so the test chunk unloads, then return to load it.
- On reload, behavior should match the current in-world number of hoppers (cache is reseeded).
- Chunk unload:
- Move away to unload the chunk; ensure no debug spam continues for that chunk; upon coming back, the count re-initializes and matches reality.
6) Unloaded chunk behavior
- Ensure no chunk forcing:
- When a chunk is unloaded, the system treats the count as 0 (no extra cooldown added due to unknown state).
- This minimizes false throttling for inactive areas.
7) Stress/regression checks
- Place 30+ hoppers in a single chunk and verify transfers are heavily throttled without server lag spikes.
- Verify other systems remain unaffected:
- Entity clear commands still function (
/lagg clear,/lagg next,/lagg tps). - Messages resolve correctly (check
messages.ymlentries still appear).
- Entity clear commands still function (
- TPS stability:
- Monitor
/lagg tpsor your profiler; event-driven design should avoid per-tick overhead.
- Monitor
8) Optional observability
- If you have a diagnostics command or profiler, confirm:
- No growth in per-chunk maps after chunk unloads.
- Hopper counts change as you place/break hoppers.
Quick reference: expected messages and keys
- Debug throttling message key:
debug.hopper.throttlinginmessages.yml- Placeholders:
{x},{z}(chunk coordinates).
- Placeholders:
Rollback plan
- Set
lag-prevention.hopper-limiter.enabled: falseto disable hopper throttling entirely if needed. - Revert to a previous plugin build if you need to remove the feature.




