run(String, Event) methods to IScriptUnit interface, with JaninoScript
delegating to callByHookType(). This provides a cleaner abstraction that
supports both ScriptContainer and JaninoScript without type checking.
Affected files:
- IScriptUnit: Added run() methods to interface
- JaninoScript: Implemented run() delegation methods
- DataScript, PlayerDataScript, GlobalNPCDataScript, ForgeDataScript
- EffectScript, LinkedItemScript, RecipeScript
- ScriptCustomItem, TileScripted: Refactored to use polymorphic calls
- Remove interruptThreshold field entirely - interrupts now based on damage source type
- Update canInterrupt() to only allow interrupts from direct physical hits (not magic/fire/explosions)
- Interruption only occurs during WINDUP phase, not ACTIVE
- Reorganize SubGuiAbilityConfig into 4 tabs: General, Type, Target, Effects
- Increase GUI size to 420x216 for better layout
This refactoring allows third-party mods to provide their own custom GUI
for ability type settings by extending SubGuiAbilityConfig.
Changes:
- Refactored SubGuiAbilityConfig as base class with GuiMenuTopButton tabs
- Added virtual methods: initTypeTab(), handleTypeButton(), handleTypeTextField()
- Added createConfigGui() method to Ability base class for GUI instantiation
- Created 15 SubGuiAbility* subclasses in new ability package
- Updated GuiNPCAbilities and GuiNpcManageAbilities to use ability.createConfigGui()
Third-party mods can now:
1. Create a custom Ability subclass
2. Extend SubGuiAbilityConfig with their own GUI
3. Override createConfigGui() to return their custom GUI
When users modified biomes, dimensions, or spawning options through the
sub-GUI dialogs, changes were only stored in client memory and never sent
to the server. This caused spawn configurations to appear correct in the
UI but fail to work after server restarts.
The closeSubGui() method now calls save() when SubGuiNpcBiomes,
SubGuiNpcDimensions, or SubGuiSpawningOptions dialogs close, ensuring
changes are immediately sent to the server via NaturalSpawnSavePacket.
Added @Override annotation for consistency with other GUI classes.
The canQuestBeAccepted() method was missing cases for MCCUSTOM and
RLCUSTOM repeat types, causing quests with custom cooldowns to become
permanently inaccessible after first completion. Added the missing
checks using quest.customCooldown for both MC ticks and real-life
milliseconds.
Two issues were causing the bug:
1. GuiDialogInteract.close() called stopAllSounds() unconditionally,
which stopped Bard music even when the dialog had no sound or
when a different Bard was playing nearby.
2. MusicController.stopMusic() didn't set playDelay, allowing Bards
to immediately restart their music after dialog close.
Changes:
- MusicController.stopMusic() now sets playDelay=20 and clears entity
reference to prevent immediate music restart
- Added MusicController.stopSound(key) to stop specific sounds
- Dialog GUIs now track their dialog sound and only stop that on close,
preserving Bard music and other sounds
The LivingAttackEvent handler was firing too late for NPCs because
EntityNPCInterface.attackEntityFrom() has its own immunity check that
runs BEFORE calling super (which fires LivingAttackEvent).
Now the attack speed bypass is checked directly in the NPC's
attackEntityFrom() method, before the immunity check at line 658.