--- a/net/minecraft/world/entity/monster/SpellcasterIllager.java
+++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java
@@ -16,20 +16,25 @@
 import net.minecraft.world.entity.LivingEntity;
 import net.minecraft.world.entity.ai.goal.Goal;
 import net.minecraft.world.level.Level;
+// CraftBukkit start
+import org.bukkit.craftbukkit.event.CraftEventFactory;
+// CraftBukkit end
 
 public abstract class SpellcasterIllager extends AbstractIllager {
+
     private static final EntityDataAccessor<Byte> DATA_SPELL_CASTING_ID = SynchedEntityData.defineId(SpellcasterIllager.class, EntityDataSerializers.BYTE);
     protected int spellCastingTickCount;
-    private SpellcasterIllager.IllagerSpell currentSpell = SpellcasterIllager.IllagerSpell.NONE;
+    private SpellcasterIllager.IllagerSpell currentSpell;
 
     protected SpellcasterIllager(EntityType<? extends SpellcasterIllager> type, Level world) {
         super(type, world);
+        this.currentSpell = SpellcasterIllager.IllagerSpell.NONE;
     }
 
     @Override
     protected void defineSynchedData(SynchedEntityData.Builder builder) {
         super.defineSynchedData(builder);
-        builder.define(DATA_SPELL_CASTING_ID, (byte)0);
+        builder.define(SpellcasterIllager.DATA_SPELL_CASTING_ID, (byte) 0);
     }
 
     @Override
@@ -46,68 +51,49 @@
 
     @Override
     public AbstractIllager.IllagerArmPose getArmPose() {
-        if (this.isCastingSpell()) {
-            return AbstractIllager.IllagerArmPose.SPELLCASTING;
-        } else {
-            return this.isCelebrating() ? AbstractIllager.IllagerArmPose.CELEBRATING : AbstractIllager.IllagerArmPose.CROSSED;
-        }
+        return this.isCastingSpell() ? AbstractIllager.IllagerArmPose.SPELLCASTING : (this.isCelebrating() ? AbstractIllager.IllagerArmPose.CELEBRATING : AbstractIllager.IllagerArmPose.CROSSED);
     }
 
     public boolean isCastingSpell() {
-        return this.level().isClientSide ? this.entityData.get(DATA_SPELL_CASTING_ID) > 0 : this.spellCastingTickCount > 0;
+        return this.level().isClientSide ? (Byte) this.entityData.get(SpellcasterIllager.DATA_SPELL_CASTING_ID) > 0 : this.spellCastingTickCount > 0;
     }
 
     public void setIsCastingSpell(SpellcasterIllager.IllagerSpell spell) {
         this.currentSpell = spell;
-        this.entityData.set(DATA_SPELL_CASTING_ID, (byte)spell.id);
+        this.entityData.set(SpellcasterIllager.DATA_SPELL_CASTING_ID, (byte) spell.id);
     }
 
-    protected SpellcasterIllager.IllagerSpell getCurrentSpell() {
-        return !this.level().isClientSide ? this.currentSpell : SpellcasterIllager.IllagerSpell.byId(this.entityData.get(DATA_SPELL_CASTING_ID));
+    public SpellcasterIllager.IllagerSpell getCurrentSpell() {
+        return !this.level().isClientSide ? this.currentSpell : SpellcasterIllager.IllagerSpell.byId((Byte) this.entityData.get(SpellcasterIllager.DATA_SPELL_CASTING_ID));
     }
 
     @Override
     protected void customServerAiStep() {
         super.customServerAiStep();
         if (this.spellCastingTickCount > 0) {
-            this.spellCastingTickCount--;
+            --this.spellCastingTickCount;
         }
+
     }
 
     @Override
     public void tick() {
         super.tick();
         if (this.level().isClientSide && this.isCastingSpell()) {
-            SpellcasterIllager.IllagerSpell illagerSpell = this.getCurrentSpell();
-            float f = (float)illagerSpell.spellColor[0];
-            float g = (float)illagerSpell.spellColor[1];
-            float h = (float)illagerSpell.spellColor[2];
-            float i = this.yBodyRot * (float) (Math.PI / 180.0) + Mth.cos((float)this.tickCount * 0.6662F) * 0.25F;
-            float j = Mth.cos(i);
-            float k = Mth.sin(i);
-            double d = 0.6 * (double)this.getScale();
-            double e = 1.8 * (double)this.getScale();
-            this.level()
-                .addParticle(
-                    ColorParticleOption.create(ParticleTypes.ENTITY_EFFECT, f, g, h),
-                    this.getX() + (double)j * d,
-                    this.getY() + e,
-                    this.getZ() + (double)k * d,
-                    0.0,
-                    0.0,
-                    0.0
-                );
-            this.level()
-                .addParticle(
-                    ColorParticleOption.create(ParticleTypes.ENTITY_EFFECT, f, g, h),
-                    this.getX() - (double)j * d,
-                    this.getY() + e,
-                    this.getZ() - (double)k * d,
-                    0.0,
-                    0.0,
-                    0.0
-                );
+            SpellcasterIllager.IllagerSpell entityillagerwizard_spell = this.getCurrentSpell();
+            float f = (float) entityillagerwizard_spell.spellColor[0];
+            float f1 = (float) entityillagerwizard_spell.spellColor[1];
+            float f2 = (float) entityillagerwizard_spell.spellColor[2];
+            float f3 = this.yBodyRot * 0.017453292F + Mth.cos((float) this.tickCount * 0.6662F) * 0.25F;
+            float f4 = Mth.cos(f3);
+            float f5 = Mth.sin(f3);
+            double d0 = 0.6D * (double) this.getScale();
+            double d1 = 1.8D * (double) this.getScale();
+
+            this.level().addParticle(ColorParticleOption.create(ParticleTypes.ENTITY_EFFECT, f, f1, f2), this.getX() + (double) f4 * d0, this.getY() + d1, this.getZ() + (double) f5 * d0, 0.0D, 0.0D, 0.0D);
+            this.level().addParticle(ColorParticleOption.create(ParticleTypes.ENTITY_EFFECT, f, f1, f2), this.getX() - (double) f4 * d0, this.getY() + d1, this.getZ() - (double) f5 * d0, 0.0D, 0.0D, 0.0D);
         }
+
     }
 
     protected int getSpellCastingTime() {
@@ -117,79 +103,44 @@
     protected abstract SoundEvent getCastingSoundEvent();
 
     public static enum IllagerSpell {
-        NONE(0, 0.0, 0.0, 0.0),
-        SUMMON_VEX(1, 0.7, 0.7, 0.8),
-        FANGS(2, 0.4, 0.3, 0.35),
-        WOLOLO(3, 0.7, 0.5, 0.2),
-        DISAPPEAR(4, 0.3, 0.3, 0.8),
-        BLINDNESS(5, 0.1, 0.1, 0.2);
 
-        private static final IntFunction<SpellcasterIllager.IllagerSpell> BY_ID = ByIdMap.continuous(
-            spell -> spell.id, values(), ByIdMap.OutOfBoundsStrategy.ZERO
-        );
+        NONE(0, 0.0D, 0.0D, 0.0D), SUMMON_VEX(1, 0.7D, 0.7D, 0.8D), FANGS(2, 0.4D, 0.3D, 0.35D), WOLOLO(3, 0.7D, 0.5D, 0.2D), DISAPPEAR(4, 0.3D, 0.3D, 0.8D), BLINDNESS(5, 0.1D, 0.1D, 0.2D);
+
+        private static final IntFunction<SpellcasterIllager.IllagerSpell> BY_ID = ByIdMap.continuous((entityillagerwizard_spell) -> {
+            return entityillagerwizard_spell.id;
+        }, values(), ByIdMap.OutOfBoundsStrategy.ZERO);
         final int id;
         final double[] spellColor;
 
-        private IllagerSpell(final int id, final double particleVelocityX, final double particleVelocityY, final double particleVelocityZ) {
-            this.id = id;
-            this.spellColor = new double[]{particleVelocityX, particleVelocityY, particleVelocityZ};
+        private IllagerSpell(final int i, final double d0, final double d1, final double d2) {
+            this.id = i;
+            this.spellColor = new double[]{d0, d1, d2};
         }
 
         public static SpellcasterIllager.IllagerSpell byId(int id) {
-            return BY_ID.apply(id);
-        }
-    }
-
-    protected class SpellcasterCastingSpellGoal extends Goal {
-        public SpellcasterCastingSpellGoal() {
-            this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
-        }
-
-        @Override
-        public boolean canUse() {
-            return SpellcasterIllager.this.getSpellCastingTime() > 0;
-        }
-
-        @Override
-        public void start() {
-            super.start();
-            SpellcasterIllager.this.navigation.stop();
-        }
-
-        @Override
-        public void stop() {
-            super.stop();
-            SpellcasterIllager.this.setIsCastingSpell(SpellcasterIllager.IllagerSpell.NONE);
-        }
-
-        @Override
-        public void tick() {
-            if (SpellcasterIllager.this.getTarget() != null) {
-                SpellcasterIllager.this.getLookControl()
-                    .setLookAt(
-                        SpellcasterIllager.this.getTarget(), (float)SpellcasterIllager.this.getMaxHeadYRot(), (float)SpellcasterIllager.this.getMaxHeadXRot()
-                    );
-            }
+            return (SpellcasterIllager.IllagerSpell) SpellcasterIllager.IllagerSpell.BY_ID.apply(id);
         }
     }
 
     protected abstract class SpellcasterUseSpellGoal extends Goal {
+
         protected int attackWarmupDelay;
         protected int nextAttackTickCount;
 
+        protected SpellcasterUseSpellGoal() {}
+
         @Override
         public boolean canUse() {
-            LivingEntity livingEntity = SpellcasterIllager.this.getTarget();
-            return livingEntity != null
-                && livingEntity.isAlive()
-                && !SpellcasterIllager.this.isCastingSpell()
-                && SpellcasterIllager.this.tickCount >= this.nextAttackTickCount;
+            LivingEntity entityliving = SpellcasterIllager.this.getTarget();
+
+            return entityliving != null && entityliving.isAlive() ? (SpellcasterIllager.this.isCastingSpell() ? false : SpellcasterIllager.this.tickCount >= this.nextAttackTickCount) : false;
         }
 
         @Override
         public boolean canContinueToUse() {
-            LivingEntity livingEntity = SpellcasterIllager.this.getTarget();
-            return livingEntity != null && livingEntity.isAlive() && this.attackWarmupDelay > 0;
+            LivingEntity entityliving = SpellcasterIllager.this.getTarget();
+
+            return entityliving != null && entityliving.isAlive() && this.attackWarmupDelay > 0;
         }
 
         @Override
@@ -197,9 +148,10 @@
             this.attackWarmupDelay = this.adjustedTickDelay(this.getCastWarmupTime());
             SpellcasterIllager.this.spellCastingTickCount = this.getCastingTime();
             this.nextAttackTickCount = SpellcasterIllager.this.tickCount + this.getCastingInterval();
-            SoundEvent soundEvent = this.getSpellPrepareSound();
-            if (soundEvent != null) {
-                SpellcasterIllager.this.playSound(soundEvent, 1.0F, 1.0F);
+            SoundEvent soundeffect = this.getSpellPrepareSound();
+
+            if (soundeffect != null) {
+                SpellcasterIllager.this.playSound(soundeffect, 1.0F, 1.0F);
             }
 
             SpellcasterIllager.this.setIsCastingSpell(this.getSpell());
@@ -207,11 +159,17 @@
 
         @Override
         public void tick() {
-            this.attackWarmupDelay--;
+            --this.attackWarmupDelay;
             if (this.attackWarmupDelay == 0) {
+                // CraftBukkit start
+                if (!CraftEventFactory.handleEntitySpellCastEvent(SpellcasterIllager.this, this.getSpell())) {
+                    return;
+                }
+                // CraftBukkit end
                 this.performSpellCasting();
                 SpellcasterIllager.this.playSound(SpellcasterIllager.this.getCastingSoundEvent(), 1.0F, 1.0F);
             }
+
         }
 
         protected abstract void performSpellCasting();
@@ -229,4 +187,36 @@
 
         protected abstract SpellcasterIllager.IllagerSpell getSpell();
     }
+
+    protected class SpellcasterCastingSpellGoal extends Goal {
+
+        public SpellcasterCastingSpellGoal() {
+            this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
+        }
+
+        @Override
+        public boolean canUse() {
+            return SpellcasterIllager.this.getSpellCastingTime() > 0;
+        }
+
+        @Override
+        public void start() {
+            super.start();
+            SpellcasterIllager.this.navigation.stop();
+        }
+
+        @Override
+        public void stop() {
+            super.stop();
+            SpellcasterIllager.this.setIsCastingSpell(SpellcasterIllager.IllagerSpell.NONE);
+        }
+
+        @Override
+        public void tick() {
+            if (SpellcasterIllager.this.getTarget() != null) {
+                SpellcasterIllager.this.getLookControl().setLookAt(SpellcasterIllager.this.getTarget(), (float) SpellcasterIllager.this.getMaxHeadYRot(), (float) SpellcasterIllager.this.getMaxHeadXRot());
+            }
+
+        }
+    }
 }
