![[AN]Adaptive Nemesis](/_next/image?url=%2Fapi%2Fproxy-image%3Furl%3Dhttps%253A%252F%252Fcdn.modrinth.com%252Fdata%252FanacxDIl%252Ff63c99aa9be78e31253e68c2c8368f95ea97d58e.gif&w=256&q=75)
[AN]Adaptive Nemesis
The dynamic difficulty balancing module specifically designed for integration packs aims to address the issue of difficulty imbalance in current mainstream integration packs, where the early game is too easy and the late game is too challenging.
Список изменений
⚔️ Adaptive Nemesis v1.0.7 ⚔️
Every time you grow stronger, your Nemesis evolves
📋 TL;DR
| Item | Description |
|---|---|
| Impact Scope | High — Fixes server deadlock/crash issues and refactors Boss attribute amplification |
| Core Changes | Watchdog service, chunk loading deadlock fix, dynamic weapon damage cap, Boss anti-HP-explosion |
🐕 Watchdog Service (New)
File: WatchdogService.java (New)
Monitors server main thread for deadlocks, auto-detects and outputs thread dumps.
| Config | Type | Default | Description |
|---|---|---|---|
enableWatchdog | Boolean | true | Enable watchdog service |
watchdogCheckInterval | Int | 5 | Check interval (seconds) |
watchdogWarnThreshold | Int | 30 | Warning threshold (seconds) |
watchdogCriticalThreshold | Int | 60 | Critical threshold (seconds) |
Two-Level Detection:
- ⚠️ Warning (30s): Logs current entity being processed
- 🚨 Critical (60s): Outputs full thread dump, marks problematic entity
Problem Entity Tracking: Adds frozen entities to problematicEntities set; EnemyScalingHandler skips these to prevent repeated deadlocks.
🔧 Chunk Loading Deadlock Fix
Affected Files:
EnemyScalingHandler.javaEnchantmentScalingHandler.java
Root Cause: AABB + getEntitiesOfClass() in EntityJoinLevelEvent / FinalizeSpawnEvent triggers chunk loading within range, deadlocking with ongoing world generation (especially with Cataclysm and similar structure mods).
Solution:
// ❌ Old code (triggers chunk loading)
AABB searchBox = new AABB(...);
List<<ServerPlayer> nearbyPlayers = serverLevel.getEntitiesOfClass(ServerPlayer.class, searchBox);
// ✅ New code (safe iteration, no chunk loading)
double rangeSq = range * range;
List<<ServerPlayer> nearbyPlayers = new ArrayList<>();
for (ServerPlayer player : serverLevel.getServer().getPlayerList().getPlayers()) {
if (player.level() == serverLevel && player.distanceToSqr(mob) <= rangeSq) {
nearbyPlayers.add(player);
}
}
New Defenses:
SCALE_TIMEOUT_TAG— Auto-marks entity as problematic if scaling exceeds 30 seconds- Try-catch in
onEntityJoinLevel()— Prevents third-party mod exceptions from crashing server - Watchdog integration — Updates status before/after entity processing
⚔️ Dynamic Weapon Damage Cap
Affected Files:
Config.javaEnchantmentScalingHandler.java
New Configs:
| Config | Default | Description |
|---|---|---|
weaponDamageBaseCap | 12.0 | Weapon damage cap at lowest difficulty (6 hearts) |
weaponDamageCapPerDifficulty | 3.0 | Damage cap increase per difficulty multiplier |
weaponDamageMaxCap | 40.0 | Absolute damage cap (20 hearts) |
Formula:
Dynamic Cap = Base + (Difficulty Multiplier - 1.0) × Per-Difficulty Increment
Final Cap = min(Dynamic Cap, Absolute Cap)
Weapon Filtering Logic:
- Iterate weapons from current quality tier downward
- Calculate actual damage via
getWeaponDamage()(includes attribute modifiers) - Only select weapons within damage cap
- If all weapons exceed cap, fallback to wooden sword
Mod Weapon Filtering: Main-hand weapons in tryGetModEquipment() are checked against damage cap; overpowered weapons are filtered with debug logging.
💀 Boss Anti-HP-Explosion
Affected File: BossDamageCapHandler.java
Problem Scenario: EntityJoinLevelEvent may trigger multiple times:
- Player teleports away, chunk unloads, returns and chunk reloads
- Player switches dimensions, entity reloads
- Server restarts, entity loads from disk
Without checks, Boss health multiplies by BOSS_HEALTH_MULTIPLIER on each reload, causing exponential explosion.
Solution:
| New NBT Tag | Purpose |
|---|---|
BOSS_BUFF_APPLIED_TAG | Marks Boss buff as applied, prevents repeated triggers |
BOSS_ORIGINAL_HEALTH_TAG | Stores original base health value |
BOSS_ORIGINAL_DAMAGE_TAG | Stores original base damage value |
Attribute Calculation:
Final Health = Original Health × EnemyScaling Multiplier × Boss Multiplier
Final Damage = Original Damage × EnemyScaling Multiplier × Boss Multiplier
This ensures correct stacking regardless of EnemyScalingHandler and BossDamageCapHandler execution order.
🎯 Other Optimizations
EnchantmentScalingHandler.java:
- Optimized humanoid mob detection using precise entity ID matching instead of string containment
- New supported mob types: Bogged, Piglin, Piglin Brute, etc.
ModEventHandler.java:
- Updates watchdog tick timestamp in
ServerTickEvent.Post - Stops watchdog service in
onServerStopping - Injects watchdog status before/after Boss processing
AdaptiveNemesisMod.java:
- Starts watchdog service after config loading completes
gradle.properties:
- Version bumped from
1.0.6to1.0.7
⚔️ As the Nemesis evolves, so do we ⚔️
