[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.

File Details

adaptive_nemesis-1.0.7.jar

  • R
  • Jun 13, 2026
  • 414.63 KB
  • 27
  • 1.21.1
  • NeoForge

File Name

adaptive_nemesis-1.0.7.jar

Supported Versions

  • 1.21.1

Curse Maven Snippet

NeoForge

implementation "curse.maven:an-adaptive-nemesis-1530829:8240663"
Curse Maven does not yet support mods that have disabled 3rd party sharing

Learn more about Curse Maven



⚔️ 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.java
  • EnchantmentScalingHandler.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.java
  • EnchantmentScalingHandler.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:

  1. Iterate weapons from current quality tier downward
  2. Calculate actual damage via getWeaponDamage() (includes attribute modifiers)
  3. Only select weapons within damage cap
  4. 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.6 to 1.0.7

⚔️ As the Nemesis evolves, so do we ⚔️

GitHub