@Override
 public SpellResult start(CastContext context) {
   if (entity == null && entityType != null) {
     Location location = context.getEyeLocation();
     setEntity(
         context.getController(),
         CompatibilityUtils.spawnEntity(location, entityType, spawnReason));
   }
   if (entity == null) {
     return SpellResult.FAIL;
   }
   return super.start(context);
 }
 @Override
 public SpellResult perform(CastContext context) {
   Entity sourceEntity = context.getEntity();
   Location sourceLocation = context.getEyeLocation().clone();
   Entity targetEntity = context.getTargetEntity();
   Location targetLocation = context.getTargetLocation();
   if (targetLocation != null) {
     targetLocation = targetLocation.clone();
   }
   Vector direction = context.getDirection().normalize();
   if (sourceLocation == null) {
     return SpellResult.LOCATION_REQUIRED;
   }
   if (targetSelf) {
     targetEntity = sourceEntity;
     targetLocation = sourceLocation;
   } else if (targetEntityLocation && targetEntity != null) {
     targetLocation = targetEntity.getLocation();
   }
   if (attachBlock) {
     Block previousBlock = context.getPreviousBlock();
     if (previousBlock != null) {
       Location current = targetLocation;
       targetLocation = previousBlock.getLocation();
       context.getBrush().setTarget(current, targetLocation);
     }
   }
   if (sourceOffset != null) {
     sourceLocation = sourceLocation.add(sourceOffset);
   }
   if (targetOffset != null && targetLocation != null) {
     targetLocation = targetLocation.add(targetOffset);
   }
   if (randomSourceOffset != null) {
     sourceLocation = RandomUtils.randomizeLocation(sourceLocation, randomSourceOffset);
   }
   if (randomTargetOffset != null && targetLocation != null) {
     targetLocation = RandomUtils.randomizeLocation(targetLocation, randomTargetOffset);
   }
   if (targetDirection != null && targetLocation != null) {
     targetLocation.setDirection(targetDirection);
   }
   if (sourceDirection != null) {
     sourceLocation.setDirection(sourceDirection);
     direction = sourceDirection.clone();
   }
   if (targetDirectionOffset != null && targetLocation != null) {
     targetLocation.setDirection(targetLocation.getDirection().add(targetDirectionOffset));
   }
   if (sourceDirectionOffset != null) {
     sourceLocation.setDirection(direction.add(sourceDirectionOffset));
   }
   if (sourceDirectionSpeed != null) {
     sourceLocation = sourceLocation.add(direction.clone().multiply(sourceDirectionSpeed));
   }
   if (targetDirectionSpeed != null && targetLocation != null) {
     targetLocation = targetLocation.add(direction.clone().multiply(targetDirectionSpeed));
   }
   if (sourceAtTarget && targetLocation != null) {
     sourceLocation.setX(targetLocation.getX());
     sourceLocation.setY(targetLocation.getY());
     sourceLocation.setZ(targetLocation.getZ());
     sourceLocation.setWorld(targetLocation.getWorld());
   }
   if (persistTarget) {
     context.setTargetLocation(targetLocation);
   }
   CastContext newContext =
       createContext(context, sourceEntity, sourceLocation, targetEntity, targetLocation);
   return super.perform(newContext);
 }