Skip to content

feat: integrate with Divinity plugin stats, healing, CC, and durability - #1775

Open
Travja wants to merge 3 commits into
devfrom
split/1677-divinity-integration
Open

feat: integrate with Divinity plugin stats, healing, CC, and durability#1775
Travja wants to merge 3 commits into
devfrom
split/1677-divinity-integration

Conversation

@Travja

@Travja Travja commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Split out of #1677 (piece 2 of 8 — see that PR for the full breakdown).

What

Adds studio.magemonkey:divinity as a provided dependency and a PluginChecker.isDivinityActive() flag, then wires several mechanics into it when active:

  • DivinityHook: clampStatAmount() caps StatMechanic modifiers to Divinity's configured stat cap; applyStatToMob() / removeStatFromMob() apply temporary Divinity stat effects to non-player entities.
  • StatMechanic: clamps player stat modifiers via Divinity's caps (unless ignore-divinity-cap), and can now apply stat effects to non-player mobs too.
  • HealMechanic: applies Divinity's healing-cast/healing-received multipliers (skippable via new settings).
  • StatusMechanic: applies Divinity's CC-duration multiplier and CC-resistance reduction to status flag durations.
  • DurabilityMechanic: reduces Divinity-tracked item durability alongside vanilla durability.
  • DamageMechanic: sets short-lived caster metadata flags (crit/dodge/block ignore, bleed/vamp disable, skill-crit ignore) around damage application, for Divinity's own damage listener to read.

All Divinity calls are guarded by PluginChecker.isDivinityActive() or wrapped in try/catch, so behavior should be unchanged when Divinity isn't installed.

Why split out separately

This is the largest coherent feature in #1677 and has no dependency on the other split pieces. It's the one most worth extra review scrutiny since it adds an external plugin dependency and several new config options — testable in isolation with/without Divinity present.

Testing

Could not build locally in this environment (private Maven repo repo.travja.dev, including the new divinity dependency, isn't reachable from the sandbox). Needs CI/manual verification, particularly: behavior with Divinity absent (should be a no-op), stat capping math, and the CC duration/resistance formulas.


Generated by Claude Code

Split out of #1677 (piece 2 of 8).

Adds studio.magemonkey:divinity as a provided dependency and a
PluginChecker.isDivinityActive() flag, then wires several mechanics into
it when active:

- DivinityHook: clampStatAmount() caps StatMechanic modifiers to
  Divinity's configured stat cap, applyStatToMob()/removeStatFromMob()
  apply temporary Divinity stat effects to non-player entities.
- StatMechanic: clamps player stat modifiers via Divinity's caps (unless
  ignore-divinity-cap), and applies stat effects to mobs.
- HealMechanic: applies Divinity's healing-cast/healing-received
  multipliers (unless ignored via settings).
- StatusMechanic: applies Divinity's CC-duration multiplier and
  CC-resistance reduction to status flag durations.
- DurabilityMechanic: reduces Divinity-tracked item durability alongside
  vanilla durability.
- DamageMechanic: sets short-lived caster metadata flags (crit/dodge/
  block ignore, bleed/vamp disable, skill-crit ignore) around damage
  application for Divinity's damage listener to read.

All Divinity calls are guarded by PluginChecker.isDivinityActive() or
wrapped in try/catch, so behavior is unchanged when Divinity isn't
installed.
@Travja Travja mentioned this pull request Jul 21, 2026
…/DurabilityMechanic

HealMechanic, StatusMechanic, and DurabilityMechanic called into Divinity's
EntityStats/ItemStats API directly, guarded only by catch(Exception). If
Divinity isn't installed, the first invocation of one of those calls
throws NoClassDefFoundError - a LinkageError, not an Exception - so the
catch block never runs and the mechanic breaks on every server without
Divinity installed (the common case, since Divinity is optional).

StatMechanic already avoided this by checking
PluginChecker.isDivinityActive() before touching any Divinity class.
Apply the same guard to the other three mechanics, and broaden the
catch to Throwable as defense-in-depth for when Divinity is present but
behaves unexpectedly (e.g. an incompatible version).

Adds regression tests exercising each mechanic with Divinity inactive
(the default in this test environment, matching a server without the
plugin installed) to confirm they no longer risk crashing there.

@Travja Travja left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While adding tests for this PR I found and fixed a real crash risk: HealMechanic, StatusMechanic, and DurabilityMechanic called Divinity's EntityStats/ItemStats API directly, guarded only by catch (Exception ignored). If Divinity isn't installed — the common case, since it's an optional integration — the first call into those classes throws NoClassDefFoundError, which is a LinkageError/Error, not an Exception. That means the catch block never runs and the mechanic breaks on every server without Divinity installed.

StatMechanic already avoided this correctly by checking PluginChecker.isDivinityActive() before touching any Divinity class. I applied the same guard to the other three mechanics and broadened the catch to Throwable as defense-in-depth for when Divinity is present but misbehaves (e.g. version mismatch). Added regression tests for each mechanic with Divinity inactive (the default in the test environment) to confirm they no longer risk crashing there.

Pushed as new commits on this branch — nothing else changed.


Generated by Claude Code

ItemLoreStat, DoubleUnaryOperator, and AdjustStatEffect were referenced
by fully-qualified name inline instead of via a normal import. Also
dropped a couple of stale comments claiming these references were
"confined to this method body" for "lazy class-loading" - imports are
compile-time only and don't affect runtime class loading, and the
other Divinity types in this file were already plain class-level
imports, so the claim didn't hold even before this change.

Note: this branch still has the separate, unresolved compile error
where TypedStat.Type.HEALING_CAST/HEALING_RECEIVED/CC_DURATION/
CC_RESISTANCE (referenced from HealMechanic/StatusMechanic) don't
exist in the pinned divinity dependency version - this commit doesn't
touch that.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants