Bug Closed · Resolved

5 runtime exceptions (3 NPE)

#10139 opened by chikage_ 1 hour ago

chikage_reported this bug

Write with Claude this goat

1. ParticleLineEffect throws when the target is in another world

[22:07:14] [lumine-scheduler-302/ERROR]: [MythicMobs] [SCHEDULER] Exception thrown whilst executing task
[22:07:14] [lumine-scheduler-302/WARN]: java.lang.IllegalArgumentException: Cannot measure distance between two different worlds.
[22:07:14] [lumine-scheduler-302/WARN]:         at MythicMobs.jar//io.lumine.mythic.api.adapters.AbstractLocation.distanceSquared(AbstractLocation.java:434)
[22:07:14] [lumine-scheduler-302/WARN]:         at MythicMobs.jar//io.lumine.mythic.api.adapters.AbstractLocation.distance(AbstractLocation.java:422)
[22:07:14] [lumine-scheduler-302/WARN]:         at MythicMobs.jar//io.lumine.mythic.core.skills.mechanics.ParticleLineEffect.playParticleLineEffect(ParticleLineEffect.java:100)
[22:07:14] [lumine-scheduler-302/WARN]:         at MythicMobs.jar//io.lumine.mythic.core.skills.mechanics.ParticleLineEffect.castAtEntity(ParticleLineEffect.java:66)
[22:07:14] [lumine-scheduler-302/WARN]:         at MythicMobs.jar//io.lumine.mythic.core.skills.SkillMechanic.lambda$executeTargetedEntitySkill$20(SkillMechanic.java:875)

Problem: the mechanic measures the distance between the start and target locations without checking that both are in the same world, so distanceSquared throws and the task aborts. It runs on lumine-scheduler, so a target or caster can change world between targeting and execution.

Solution: check that both locations are in the same world before measuring the distance, and skip the effect when they are not.


2. LungeMechanic has the same missing world check

[17:36:14] [Server thread/WARN]: java.lang.IllegalArgumentException: Cannot measure distance between two different worlds.
[17:36:14] [Server thread/WARN]:        at MythicMobs.jar//io.lumine.mythic.api.adapters.AbstractLocation.distance2DSquared(AbstractLocation.java:494)
[17:36:14] [Server thread/WARN]:        at MythicMobs.jar//io.lumine.mythic.core.skills.mechanics.LungeMechanic.doNewVelocity(LungeMechanic.java:70)
[17:36:14] [Server thread/WARN]:        at MythicMobs.jar//io.lumine.mythic.core.skills.mechanics.LungeMechanic.castAtLocation(LungeMechanic.java:51)
[17:36:14] [Server thread/WARN]:        at MythicMobs.jar//io.lumine.mythic.core.skills.SkillMechanic.lambda$executeTargetedLocationSkill$21(SkillMechanic.java:886)

Problem: doNewVelocity measures the 2D distance between the caster and the target with no world check. doOldVelocity follows the same pattern.

Solution: reject a target in another world before either velocity calculation runs, and treat it as an invalid target.


3. targetWithin and targetNotWithin race on getTarget()

The target is cleared while the condition is being evaluated. Three variants appear in the logs.

Variant A: TargetWithinCondition

[16:17:26] [lumine-scheduler-11575/WARN]: [MythicMobs] ✗ Configuration Error in Condition targetWithin
[16:17:26] [lumine-scheduler-11575/WARN]: [MythicMobs] --| Error Message: An internal error occurred
[16:17:26] [lumine-scheduler-11575/WARN]: [MythicMobs] --| Condition Line: targetwithin{d=4} castinstead dyerftumbrute_em_rageproximitycheckb
[16:17:26] [lumine-scheduler-11575/WARN]: java.lang.NullPointerException: Cannot invoke "org.bukkit.entity.LivingEntity.getL value of "org.bukkit.entity.Mob.getTarget()" is null
[16:17:26] [lumine-scheduler-11575/WARN]:       at MythicMobs.jar//io.lumine.mythic.core.skills.conditions.all.TargetWithinCondition.check(TargetWithinCondition.java:65)
[16:17:26] [lumine-scheduler-11575/WARN]:       at MythicMobs.jar//io.lumine.mythic.core.skills.SkillCondition.evaluateCaster(SkillCondition.java:351)

Variant B: TargetNotWithinCondition

[05:00:41] [lumine-scheduler-974/WARN]: [MythicMobs] ✗ Configuration Error in Condition targetnotwithin
[05:00:41] [lumine-scheduler-974/WARN]: [MythicMobs] --| Error Message: An internal error occurred
[05:00:41] [lumine-scheduler-974/WARN]: [MythicMobs] --| Condition Line: targetnotwithin{d=9} true
[05:00:41] [lumine-scheduler-974/WARN]: java.lang.NullPointerException: Cannot invoke "org.bukkit.entity.LivingEntity.getWore of "org.bukkit.entity.Mob.getTarget()" is null
[05:00:41] [lumine-scheduler-974/WARN]:         at MythicMobs.jar//io.lumine.mythic.core.skills.conditions.all.TargetNotWithinCondition.check(TargetNotWithinCondition.java:66)

Variant C: inside CraftMob.getTarget()

[23:52:22] [lumine-scheduler-8099/WARN]: [MythicMobs] ✗ Configuration Error in Condition targetnotwithin
[23:52:22] [lumine-scheduler-8099/WARN]: [MythicMobs] --| Error Message: An internal error occurred
[23:52:22] [lumine-scheduler-8099/WARN]: [MythicMobs] --| Condition Line: targetnotwithin{d=9} castinstead fknighta_parryproximitycheckb
[23:52:22] [lumine-scheduler-8099/WARN]: java.lang.NullPointerException: Cannot invoke "net.minecraft.world.entity.LivingEntity.getBukkitEntity()" because the return value of "net.minecraft.world.entity.Mob.getTarget()" is null
[23:52:22] [lumine-scheduler-8099/WARN]:        at org.bukkit.craftbukkit.entity.CraftMob.getTarget(CraftMob.java:38)
[23:52:22] [lumine-scheduler-8099/WARN]:        at org.bukkit.craftbukkit.entity.CraftMob.getTarget(CraftMob.java:14)
[23:52:22] [lumine-scheduler-8099/WARN]:        at MythicMobs.jar//io.lumine.mythic.core.skills.conditions.all.TargetNotWithinCondition.check(TargetNotWithinCondition.java:67)

Problem: both conditions read the mob's target several times, and they run off the main thread when evaluated from an aura tick. The main thread can clear the target between two reads. Variant C shows the same race inside CraftMob.getTarget(), so reading the target only once in MythicMobs would not be enough on its own. The log also reports a valid config line as a Configuration Error, whic

Solution: evaluate these conditions on the main thread and read the target only once per check. If they have to stay async, they must also handle a failure inside CraftMob.getTarget() and treat it as "no target". Runtime failures like this one should not be reported as configuration errors.


4. LumineAsyncTask.stop() can run before future is assigned

[15:38:39] [lumine-scheduler-3967/ERROR]: [MythicMobs] [SCHEDULER] Exception thrown whilst executing task
[15:38:39] [lumine-scheduler-3967/WARN]: java.lang.NullPointerException: Cannot invoke "java.util.concurrent.ScheduledFuture.cancel(boolean)" because "this.future" is null
[15:38:39] [lumine-scheduler-3967/WARN]:        at MythicMobs.jar//io.lumine.mythic.bukkit.utils.Schedulers$LumineAsyncTask.stop(Schedulers.java:564)
[15:38:39] [lumine-scheduler-3967/WARN]:        at MythicMobs.jar//io.lumine.mythic.core.skills.auras.Aura$AuraTracker.lambda$armExpiration$37(Aura.java:809)
[15:38:39] [lumine-scheduler-3967/WARN]:        at MythicMobs.jar//io.lumine.mythic.bukkit.utils.Schedulers$LumineAsyncTask.run(Schedulers.java:548)
[15:38:39] [lumine-scheduler-3967/WARN]:        at MythicMobs.jar//io.lumine.mythic.bukkit.utils.tasks.LumineExecutors$SchedulerWrappedRunnable.run(LumineExecutors.java:70)
[15:38:39] [lumine-scheduler-3967/WARN]:        at MythicMobs.jar//io.lumine.mythic.bukkit.utils.tasks.LumineAsyncExecutor$FixedRateWorker.lambda$run$0(LumineAsyncExecutor.java:186)

Problem: the constructor schedules the task first and stores the returned future afterwards. A worker can run the task before that assignment finishes. If the task stops itself on that first run, as armExpiration does here, stop() tries to cancel a future that is still null.

Solution: make stop() safe when the future is not set yet, and have the constructor cancel the future straight away if a stop was already requested.


5. ParticleOrbitalEffect$Animator can run before task is assigned

[09:14:55] [lumine-scheduler-1494/ERROR]: [MythicMobs] [SCHEDULER] Exception thrown whilst executing task
[09:14:55] [lumine-scheduler-1494/WARN]: java.lang.NullPointerException: Cannot invoke "io.lumine.mythic.bukkit.utils.tasks.Task.terminate()" because "this.task" is null
[09:14:55] [lumine-scheduler-1494/WARN]:        at MythicMobs.jar//io.lumine.mythic.core.skills.mechanics.ParticleOrbitalEfftalEffect.java:134)
[09:14:55] [lumine-scheduler-1494/WARN]:        at MythicMobs.jar//io.lumine.mythic.bukkit.utils.Delegates$RunnableToConsumer.accept(Delegates.java:93)
[09:14:55] [lumine-scheduler-1494/WARN]:        at MythicMobs.jar//io.lumine.mythic.bukkit.utils.Schedulers$LumineAsyncTask.
[09:14:55] [lumine-scheduler-1494/WARN]:        at MythicMobs.jar//io.lumine.mythic.bukkit.utils.tasks.LumineExecutors$SchedulerWrappedRunnable.run(LumineExecutors.java:70)
[09:14:55] [lumine-scheduler-1494/WARN]:        at MythicMobs.jar//io.lumine.mythic.bukkit.utils.tasks.LumineAsyncExecutor$FixedRateWorker.lambda$run$0(LumineAsyncExecutor.java:186)

Problem: the animator schedules itself in its constructor with a delay of 0 and stores the task afterwards. The first run can start before the field is assigned. If the caster is already dead on that run, the animator tries to terminate a task that is still null.

Solution: have the animator stop through the task handle the scheduler gives it on each run, rather than through a field set after scheduling. The scheduler already has a repeating overload that provides this handle.

Sign in to join the discussion.