Skip to content

Base Entity Registry

liopyu edited this page Jan 28, 2026 · 30 revisions

Entity Registration Overview πŸ› οΈ

Entity registration allows you to dynamically define and customize entities using several types of builders. Each builder type provides specific functionalities to help you shape unique entity behaviors.


Builder Types πŸ—οΈ

πŸ”΅ LivingEntity Builder Create living entities with basic attributes and behaviors.
🚢 PathfinderMob Builder Create mobs with pathfinding capabilities for navigation.
🍼 AgeableMob Builder Create ageable mobs like animals, capable of growing and breeding.
πŸ• TamableMob Builder Create tamable animals or neutral mobs with taming capabilities.
🏹 Arrow Builder Customize arrows with unique effects and behaviors.
πŸš€ Projectile Builder Define custom projectiles with specific behaviors.
🐟 Water Entity Builder Create aquatic animals with water-based behaviors.
🧱 Non-Living Entity Builder Create basic non-living entities with customizable properties.

More builders coming soon...


Builder Script Example πŸ’»

// Entity Registration Example (models/textures included for 'kubejs:wyrm', 'kubejs:sasuke', 'kubejs:arrow', 'kubejs:projectile')
StartupEvents.registry('entity_type', event => {
    event.create('bat', 'entityjs:living') // LivingEntity Builder
    event.create('sasuke', 'entityjs:mob') // PathfinderMob Builder 
    event.create('wyrm', 'entityjs:animal') // AgeableMob Builder
    event.create('dragon', 'entityjs:tamable') // TamableMob Builder
    event.create('arrow', "entityjs:arrow") // Arrow Builder 
    event.create('projectile', "entityjs:projectile") // Projectile builder 
    event.create('serpent', "entityjs:watercreature") // Water Animal Builder
    event.create('dummy', "entityjs:nonliving") // Non-Living Entity Builder
    event.create('projectile', "entityjs:geckolib_projectile") // Projectile builder with Geckolib modelling
})

The examples below contain most of the methods available.

Full TamableMob Entity Example

Full Animal Entity Example Usage 1.19.2
StartupEvents.registry('entity_type', event => {
    let builder = event.create('wyrm', 'entityjs:tamable')
    /**
     * One-Off values set at the startup of the game.
     */
    builder.immuneTo("minecraft:stone", "minecraft:dirt")
    builder.canSpawnFarFromPlayer(true)
    builder.clientTrackingRange(20)
    builder.mobCategory('monster')
    builder.setRenderType("solid")
    builder.sized(1, 1)
    builder.modelSize(2, 3)
    builder.updateInterval(3)
    builder.defaultDeathPose(true)
    builder.repositionEntityAfterLoad(true)
    builder.isPersistenceRequired(true)
    builder.isAlwaysExperienceDropper(true)
    builder.setDeathSound("minecraft:entity.generic.death")
    builder.canJump(true)
    builder.ambientSoundInterval(100)
    builder.isPushable(true)
    builder.canBreatheUnderwater(true)
    builder.eatingSound("minecraft:entity.zombie.ambient")
    builder.fallSounds("minecraft:entity.generic.small_fall", "minecraft:entity.generic.large_fall")
    builder.fireImmune(false)
    builder.followLeashSpeed(1.5)
    builder.setAmbientSound("minecraft:entity.zombie.ambient")
    builder.mainArm("left")
    builder.mobType('undead')
    builder.saves(true)
    builder.setSoundVolume(0.5)
    builder.setSummonable(true)
    builder.setSwimSound("minecraft:entity.generic.swim")
    builder.setSwimSplashSound("minecraft:entity.generic.splash")
    builder.setWaterSlowDown(0.6)
    builder.shouldDespawnInPeaceful(true)
    builder.mountJumpingEnabled(true)
    builder.tamableFood([
        'minecraft:diamond',
        Ingredient.of("minecraft:bedrock")
    ])
    builder.isFood([
        'minecraft:diamond',
        Ingredient.of("minecraft:apple")
    ])
    builder.isFood([
        'minecraft:diamond',
        Ingredient.of("minecraft:apple")
    ])
    // .noEggItem() // Disables automatic egg item creation
    //Customize egg item
    builder.eggItem(item => {
        item.backgroundColor(0);
        item.highlightColor(0);
    })
    builder.canFireProjectileWeapon([
        'minecraft:bow',
        'minecraft:crossbow'
    ])
    builder.newGeoLayer(builder => {
        // New render layers like what the exploding Creeper or the Wither has
        /*builder.textureResource(entity => {
            return "kubejs:textures/entity/sasuke.png"
        })*/
    })
    /**
     * These methods below require a set return value, if the value does not match the required result
     * it will automatically default to the super method in the entity builder and output an error in logs>kubejs>startup.log.
     *
     * Remember all callback functions are also able to be live-edited with global events!
     *
     * Example:
     * global.interact = context => {
     *  if (context.player.isShiftKeyDown()) return
     *      context.player.startRiding(context.entity);
     * }
     *
     * .onInteract(context => global.interact(context)) // Reload this with /kubejs reload startup_scripts
     */

    builder.addAnimationController('exampleController', 1, event => {
        if (event.entity.hurtTime > 0) {
            event.thenPlayAndHold('spawn');
        } else {
            event.thenLoop('idle');
        }
        return true;
    })
    builder.setBreedOffspring(context => {
        const { entity, mate, level } = context
        // Use the context to return a ResourceLocation of an entity to spawn when the entity mates
        return 'minecraft:cow' //Some Resourcelocation representing the entity to spawn.
    })
    builder.addPartEntity("head", 1, 1, builder => {
        // Adds an additional hitbox to the entity with builder support
        builder
            .isPickable(true)
            .onPartHurt(context => {
                const { entity, part, source, amount } = context
                // Custom logic for determining how the parts of the entity should relay damage
                // To the entity. For example, relay double the damage to the entity when this hitbox is hit
                entity.attack(source, amount * 2)
                console.log("source: " + source + " amount: " + amount + " part name: " + part.name)
            })
    })
    builder.aiStep(entity => {
        // Custom logic to be executed during the living entity's AI step
        // Access information about the entity
        // Tick the previously registered part entity/hitbox to be 1 square y-offset to the entity
        entity.tickPart("head", 0, 1, 0)
    })
    builder.setLookControl(entity => {
        return EntityJSUtils.createLookControl(entity, lookControlBuilder => { })
    })
    builder.setMoveControl(entity => {
        return EntityJSUtils.createMoveControl(entity, moveControlBuilder => { })
    })
    builder.setJumpControl(entity => {
        return EntityJSUtils.createJumpControl(entity, jumpControlBuilder => { })
    })
    builder.createNavigation(context => {
        const { entity, level } = context
        // Use the new EntityJSUtils binding to create different path navigations
        // Returning WallClimberNavigation here will allow the entity to path-find up walls like spiders
        return EntityJSUtils.createWallClimberNavigation(entity, level) // Return some path navigation
    })
    builder.render(context => {
        // Define core logic to render the entity (recommended to use .scaleModelForRender instead)
        if (context.entity.isBaby()) {
            return context.poseStack.scale(0.5, 0.5, 0.5); // Scale down if the entity is a baby
        }
        return context.poseStack; // Otherwise, keep the default pose stack
    })
    builder.scaleModelForRender(context => {
        // Define logic to render the entity without changing core logic such as hitbox rendering
        const { entity, widthScale, heightScale, poseStack, model, isReRender, partialTick, packedLight, packedOverlay } = context
        if (entity.hurtTime > 0) {
            poseStack.scale(0.5, 0.5, 0.5)
        }
    })
    builder.jumpBoostPower(entity => {
        //Sets the jump boost power for the entity when they have the jump boost effect applied
        //Mimic vanilla logic with resistance instead of jump boost
        return entity.hasEffect("minecraft:resistance") ? (0.1 * (entity.getEffect("minecraft:resistance").getAmplifier() + 1)) : 0.0;
    })
    builder.setBlockJumpFactor(entity => {
        // Sets block jump factor returning a float value
        if (entity.age > 2000) {
            return 1.3; // Increase jump factor when the entity is old enough
        }
        return 1; // Default jump factor
    })
    builder.setMaxFallDistance(entity => {
        // Define custom logic to determine the maximum fall distance before taking damage
        // Use information about the LivingEntity provided by the context
        if (entity.isOnFire()) {
            return 1; // Reduced fall distance when entity is on fire
        }
        return 3; // Default fall distance
    })
    builder.myRidingOffset(entity => {
        // Use the provided context about the entity to determine the riding offset of the passengers
        if (!entity.isBaby()) {
            return 7; // Increased riding offset when the entity is not a baby
        }
        return 5; // Default riding offset
    })
    builder.animationResource(entity => {
        // Return different animation resources based on the entity's state
        // Use information about the LivingEntity provided by the context.
        if (entity.hurtTime > 0) {
            return // Return some animation path when entity is hurt
        } else {
            return "kubejs:animations/entity/wyrm.animation.json"; // Return Wyrm animation otherwise
        }
    })
    builder.blockSpeedFactor(entity => {
        // Define logic to calculate and return the block speed factor for the entity
        // Use information about the LivingEntity provided by the context.
        const age = entity.age;
        const maxAge = 5000; // Assuming the maximum age is 5000

        // Custom logic to calculate block speed factor based on entity's age
        const factor = age < maxAge ? 1.0 : 0.5; // Reduce speed factor for older entities
        return factor;
    })
    builder.calculateFallDamage(context => {
        // Define logic to calculate and return the fall damage for the entity
        // Use information about the CalculateFallDamageContext provided by the context.
        const fallHeight = context.fallHeight;
        const damageMultiplier = context.damageMultiplier;
        const entity = context.entity;

        // Custom logic to calculate fall damage based on fall height and multiplier
        const calculatedDamage = Math.floor(fallHeight * damageMultiplier);
        return calculatedDamage;
    })
    builder.canAddPassenger(context => {
        // Define custom logic to determine if a passenger can be added to the entity
        // Use information about the PassengerEntityContext provided by the context.
        // For example, check if the entity is not already carrying too many passengers.
        const maxPassengers = 4; // Assuming a maximum of 4 passengers
        return context.entity.getPassengers().size() < maxPassengers;
    })
    builder.isAlliedTo(context => {
        const { entity, target } = context
        return target.type == 'minecraft:blaze'
    })
    builder.canAttack(context => {
        // Define conditions to check if the entity can attack the targetEntity
        // Use information about the LivingEntity provided by the context.
        // For example, check if the targetEntity is not the same as the entity itself.
        return context.target.type !== context.entity.type;
    })
    builder.canAttackType(context => {
        // Define conditions to check if the entity can attack the specified entity type
        // Use information about the EntityTypeEntityContext provided by the context.
        // For example, check if the entity type of the target matches a specific type.
        const targetType = context.targetType.category.friendly;
        // Assuming we want the entity to attack only friendly mobs
        return targetType;
    })
    builder.canBeAffected(context => {
        // Define conditions to check if the entity can be affected by the effect
        // Use information about the OnEffectContext provided by the context.
        // For example, check if the entity is not already affected by a specific effect.
        const effect = context.effect;
        // Assuming we want the entity to be affected only if it doesn't have the same effect already
        return !context.entity.hasEffect(effect.getEffect());
    })
    builder.canChangeDimensions(entity => {
        // Define the conditions for the entity to be able to change dimensions
        // Use information about the LivingEntity provided by the context.
        // For example, allow dimension change only for entities with a specific tag.
        return entity.tags.contains("dimension_changer");
    })
    builder.canDisableShield(entity => {
        // Define the conditions to check if the entity can disable its shield
        // Use information about the LivingEntity provided by the context.
        return entity.mainHandItem.id == 'minecraft:diamond_sword'; // Disable shield if the entity is wielding a diamond sword.
    })
    builder.canFireProjectileWeaponPredicate(context => {
        // Custom logic to determine whether the entity can fire a projectile weapon
        // Access information about the entity and the projectile weapon using the provided context.
        return context.projectileWeapon.id == 'minecraft:bow';
    })
    builder.canFreeze(entity => {
        // Define conditions for the entity to be able to freeze
        // For example, allow freezing only if the entity is in water.
        return entity.inWater;
    })
    builder.canHoldItem(context => {
        // Custom logic to determine whether the entity can hold an item based on the provided context.
        // For example, allow holding an item only if the entity is not a baby.
        return !context.entity.isBaby();
    })
    builder.canBreed(entity => {
        // Custom logic to determine if the entity can breed
        // Use information about the LivingEntity provided by the context.
        // For example, check if the entity has reached maturity.
        const baby = entity.isBaby();
        // Assuming we want the entity to be able to breed only if it's an adult
        return baby;
    })
    builder.canMate(context => {
        // Custom logic to determine if the entity can mate
        // For example, allow mating only if both animals are in the same biome.
        let blockpos1 = context.animal.block.pos
        let blockpos2 = context.otherAnimal.block.pos
        return context.animal.level.getBiome(blockpos1) === context.otherAnimal.level.getBiome(blockpos2);
    })
    builder.canPickUpLoot(entity => {
        // Custom logic to determine whether the entity can pick up loot based on the provided mob.
        // Allow loot pickup during nighttime.

        return !entity.level.isDay(); // Only allow loot pickup during nighttime
    })
    builder.canStandOnFluid(context => {
        // Define conditions for the entity to be able to stand on a fluid
        // Use information about the EntityFluidStateContext provided by the context.
        // Allow standing on water.
        let fluid = Fluid.of("minecraft:water").fluid.fluidType
        return context.fluidState.fluidType == fluid
    })
    builder.canTakeItem(context => {
        // Define conditions for the entity to be able to take an item
        // Use information about the EntityItemLevelContext provided by the context.
        // Allow taking items only if the living entity is not null and the item stack is not empty.
        return context.entity !== null && !context.itemStack.isEmpty();
    })
    builder.dampensVibrations(entity => {
        // Determine whether the living entity dampens vibrations
        // Return true if the entity dampens vibrations, false otherwise
        // For example, return true if the entity has no gravity.
        return entity.isNoGravity();
    })
    builder.experienceReward(killedEntity => {
        // Define logic to calculate and return the experience reward for the killedEntity
        // Use information about the LivingEntity provided by the context.
        // For example, return 5 times the armor cover percentage of the entity.
        const armorCoverPercentage = killedEntity.armorCoverPercentage + 1;
        return armorCoverPercentage * 5;
    })
    builder.hasLineOfSight(context => {
        // Check if the target entity is within the same level
        if (context.targetEntity.level !== context.entity.level) {
            return false;
        }
        // Get the positions of the entities
        const entityPos = new Vec3(context.entity.getX(), context.entity.getEyeY(), context.entity.getZ());
        const targetPos = new Vec3(context.targetEntity.getX(), context.targetEntity.getEyeY(), context.targetEntity.getZ());
        // Calculate the distance between the two entities
        const distance = entityPos.distanceTo(targetPos);
        // Check if the target entity is within a reasonable range
        if (distance > 128.0) {
            return false;
        }
        // Allow the entity to "see through" blocks by not implimenting ClipContext as done in LivingEntity Class.
        return true;
    })
    builder.setHurtSound(context => {
        // Custom logic to determine the hurt sound for the entity
        // You can use information from the HurtContext to customize the sound based on the context
        const { entity, damageSource } = context;
        // Determine the hurt sound based on the type of damage source
        switch (damageSource.getType()) {
            case "fire":
                return "minecraft:entity.generic.burn";
            case "fall":
                return "minecraft:entity.generic.hurt";
            case "drown":
                return "minecraft:entity.generic.hurt";
            case "explosion":
                return "minecraft:entity.generic.explode";
            default:
                return "minecraft:entity.generic.explode";
        }
    })
    builder.invertedHealAndHarm(entity => {
        //Used by undead mobs to invert potion effects such as Instant Health & Instant Damage
        const blockAboveHasSky = entity.block.down.canSeeSky;
        return blockAboveHasSky; // Return true if the block below has sky visibility
    })
    builder.isAffectedByFluids(entity => {
        // Define logic to determine whether the entity is affected by fluids
        // For example, check if the entity is swimming or flying
        return entity.isSwimming() || entity.isFallFlying();
    })
    builder.isAffectedByPotions(entity => {
        // Define conditions to check if the entity is affected by potions
        // For example, check if the entity has any active potion effects
        return entity.getActiveEffects().size() > 0;
    })
    builder.isAttackable(entity => {
        // Define conditions to check if the entity is attackable
        // For example, check if the entity is not invulnerable
        return !entity.isInvulnerable();
    })
    builder.isCurrentlyGlowing(entity => {
        // Define the conditions to check if the entity is currently glowing
        // For example, check if the entity has a regeneration or glowing effect applied
        return entity.hasEffect("minecraft:regeneration") || entity.hasEffect("minecraft:glowing");
    })
    builder.isFlapping(entity => {
        // Mimics the Ender Dragon's Flapping Behavior
        // Define logic to determine whether the entity is currently flapping
        const flapTime = entity.flapTime; // Current flap time
        const oFlapTime = entity.oFlapTime; // Previous flap time

        // Calculate cosine values for the current and previous flap times
        const f = Math.cos(flapTime * 6.2831855);
        const f1 = Math.cos(oFlapTime * 6.2831855);

        // Check if the entity is flapping based on cosine values
        return f1 <= -0.3 && f >= -0.3;
    })
    builder.tamableFoodPredicate(context => {
        const { entity, item } = context
        return item.id == 'minecraft:carrot' // Return true if the player's current itemstack will tame the mob.
    })
    builder.isFoodPredicate(context => {
        // Custom logic to determine if the entity item stack is considered as food.
        // Access information about the item stack using the provided context.
        const itemStack = context.item; // Get the item stack from the context

        // Example condition: Check if the item stack is edible
        return itemStack.isEdible();
    })
    builder.isFreezing(entity => {
        // Define the conditions for the entity to start freezing
        // Use information about the LivingEntity provided by the context.
        // Start freezing the entity if they're in the taiga biome and can freeze.
        return entity.level.getBiome(entity.block.pos) == 'minecraft:taiga' && entity.canFreeze();
    })
    builder.isImmobile(entity => {
        // Define logic to determine whether the entity is immobile
        // Use information about the LivingEntity provided by the context.
        return entity.isSleeping(); // Example: Entity is immobile if sleeping
    })
    builder.isInvulnerableTo(context => {
        // Define conditions for the entity to be invulnerable to the specific type of damage
        // Use information about the DamageContext provided by the context.

        // Example condition: Entity is invulnerable to magic damage
        return context.damageSource.isMagic();
    })
    builder.isSensitiveToWater(entity => {
        // Define conditions to check if the entity is in a "Cold Ocean" biome and sensitive to water
        // Use information about the LivingEntity provided by the context.

        // Example condition: Check if the biome ID corresponds to a "Cold Ocean" biome
        return entity.level.getBiome(entity.block.pos).is('minecraft:cold_ocean')
    })
    builder.isSleeping(entity => {
        // Check if the entity has a sleeping position
        // Use information about the LivingEntity provided by the context.
        //Mimics how vanilla does the isSleeping() method.
        return entity.getSleepingPos().isPresent();
    })
    builder.mayInteract(context => {
        // Define conditions for the entity to be allowed to interact with the world
        // Use information about the MayInteractContext provided by the context.
        return context.entity.getTags().contains('canInteractWithWorld')
    })
    builder.meleeAttackRangeSqr(entity => {
        // Define custom logic to calculate the squared melee attack range based on the provided entity.
        // For example, you can calculate based on the size or type of the entity.
        const size = entity.boundingBox.size;
        const range = size * size; // Adjust this calculation based on your requirements
        return range;
    })
    builder.nextStep(entity => {
        // Define custom logic to calculate the next step distance based on the provided entity.
        const movementSpeed = entity.getTotalMovementSpeed(); // Get the entity's movement speed
        //If the entity is not an animal return default vanilla behavior
        if (!entity.animal) return entity.moveDist + 1;
        const behaviorFactor = entity.isAggressive() ? 1.5 : 1; // Adjust the step distance based on behavior
        // Calculate the next step distance based on movement speed, size, and behavior
        const nextStepDistance = movementSpeed * behaviorFactor;
        return nextStepDistance;
    })
    builder.onClimbable(entity => {
        const blockBelow = entity.block.down; // Get the block below the entity
        // Check if the block below the entity is climbable (e.g., a ladder, vine, or scaffold)
        const isClimbableBlock = blockBelow.hasTag('minecraft:my_climbeable_block_tag');

        // Check if the entity is currently moving upwards (which might indicate climbing)
        const isMovingUpwards = entity.motionY > 0;

        // Return true if the entity is on a climbable surface and moving upwards
        return isClimbableBlock && isMovingUpwards;
    })
    builder.removeWhenFarAway(context => {
        // Get information from the context
        const { distanceToClosestPlayer } = context;
        // Return true if the entity is far away from the closest player and should be removed
        //Fine tune removal logic
        return distanceToClosestPlayer > 64;
    })
    builder.scale(entity => {
        // Define logic to calculate the custom scale for the entity
        // For example, you can scale the entity based on its size or other properties
        return entity.isBaby() ? 0.5 : 1;
    })
    builder.setStandingEyeHeight(context => {
        // Define logic to calculate and return the standing eye height for the entity
        // Use information about the EntityPoseDimensionsContext provided by the context
        const entity = context.entity; // Get the entity from the context
        const pose = context.pose; // Get the entity pose from the context

        // Define default standing eye height
        let standingEyeHeight = 1.8; // Default human-like standing eye height

        // Adjust standing eye height based on entity pose if needed
        if (pose === 'crouching') {
            standingEyeHeight = 1.5; // Adjust standing eye height for crouching pose
        }

        // Return the calculated standing eye height
        return standingEyeHeight;
    })
    builder.shouldDropExperience(entity => {
        // Define conditions to check if the entity should drop experience upon death
        // Use information about the LivingEntity provided by the context.
        return entity.block.down.id == 'minecraft:grass_block'// Only drop experience if the entity dies on grass
    })
    builder.shouldDropLoot(entity => {
        // Define logic to determine whether the entity should drop loot
        // Use information about the LivingEntity provided by the context.
        return !entity.isBaby(); //Only drop loot if they're an adult
    })
    builder.showVehicleHealth(entity => {
        // Determine whether to show the vehicle health for the living entity
        // Return true to show the vehicle health, false otherwise
        return !entity.isFallFlying(); //Only show vehicle's health to the player if the vehicle is fall flying
    })
    builder.visibilityPercent(context => {
        // Define logic to calculate and return the visibility percentage for the targetEntity
        // Use information about the Entity provided by the context.
        // Our mob is less 'seen' by other mobs in the plains biome by 20%.
        return context.lookingEntity.age > 0 ? 0.8 : 1
    })
    builder.walkTargetValue(context => {
        const { levelReader, pos } = context; // Destructure context for easier access

        // Get the block state below the given position
        const blockBelow = levelReader.getBlockState(pos.below());

        // Adjust walk target value based on the block below, is usually Grass Block in Vanilla
        return blockBelow.is(Blocks.AZALEA_LEAVES) ? 10 : levelReader.getPathfindingCostFromLightLevels(pos);
    })
    builder.canCollideWith(context => {
        return true //Some Boolean value determining whether the entity may collid with another
    })

    /**
     * All methods below return void meaning they don't require a set return value to function.
     * These mostly are similar to KubeJS' normal events where you may do things on certain events your entities call!
     */

    builder.tickLeash(context => {
        const { player, entity } = context
        if (player != undefined && player.isDiscrete()) {
            // Give the player a diamond
            player.give(Item.of('minecraft:diamond'));
            // Print a message indicating the diamond was given
            console.log(`Gave ${player.getName()} a diamond for sneaking while leashing ${entity.type}.`);
        }
    })
    builder.tick(entity => {
        if (entity.age % 100 != 0) return
        console.log('ticked every 100 ticks')
    })
    builder.lavaHurt(entity => {
        // Heal the entity by 20 health points
        entity.heal(20);
    })
    builder.doAutoAttackOnTouch(context => {
        // Attack the target entity with a damage value of 1
        context.target.attack(1);
    })
    builder.ate(entity => {
        // Log a message when the entity eats something
        console.log(`${entity.type} just ate!`)
    })
    builder.dropCustomDeathLoot(context => {
        // Drop custom loot (iron ingot) when the entity dies with a looting multiplier of 2
        if (context.lootingMultiplier == 2) context.entity.block.popItemFromFace('minecraft:iron_ingot', 'up')
    })
    builder.eat(context => {
        // Heal the entity when it eats something
        context.entity.heal(20)
    })
    builder.lerpTo(context => {
        const { x, y, z, yaw, pitch, entity, delta } = context;
        // Set the entity's position directly to the target position if the entity is freezing
        if (entity.isFreezing()) entity.setPosition(x, y, z);
    })
    builder.onAddedToWorld(entity => {
        // Teleport the entity slightly above its current position when added to the world
        entity.teleportTo(entity.level.dimension, entity.x, entity.y + 1, entity.z, 1, 1)
    })
    builder.onBlockedByShield(context => {
        const { entity, target } = context
        // Log a message when the target is blocked by a shield
        console.log(`${target} Get blocked!`)
    })
    builder.onClientRemoval(entity => {
        // Log a message when the entity is removed on the client side
        console.log(`${entity} was removed on the client`)
    })
    builder.onDeath(context => {
        // Place a diamond ore block below the entity when it dies
        context.entity.block.down.set('minecraft:diamond_ore')
    })
    builder.onDecreaseAirSupply(entity => {
        // Log the entity's remaining air supply when it decreases
        console.log(entity.airSupply)
    })
    builder.onEffectAdded(context => {
        // Log the description ID of an added effect
        console.log(context.effect.descriptionId)
    })
    builder.onEffectRemoved(context => {
        // Log the description ID of a removed effect
        console.log(context.effect.descriptionId)
    })
    builder.onEnterCombat(entity => {
        // Log a message when the entity enters combat
        console.log(`${entity} just entered combat`)
    })
    builder.onEquipItem(context => {
        // Log the ID of the item being equipped by the entity
        if (context.entity.age % 100 != 0) return
        console.log(context.currentStack.id)
    })
    builder.onFlap(entity => {
        // Place a gold ore block below the entity when it flaps
        entity.block.down.set('minecraft:gold_ore')
    })
    builder.onHurt(context => {
        // Log the amount of damage received by the entity
        console.log(context.damageAmount)
    })
    builder.onIncreaseAirSupply(entity => {
        // Log a message when the entity's air supply increases
        console.log(`${entity} increasing air`)
    })
    builder.onItemPickup(context => {
        // Log the ID of the item picked up by the entity
        console.log(context.itemEntity.id)
    })
    builder.onLeaveCombat(entity => {
        // Log a message when the entity leaves combat
        console.log(`${entity} just left combat!`)
    })
    builder.onLivingFall(context => {
        // Log a message when the entity falls
        console.log(`${context.entity} just fell ${context.distance} blocks!`)
    })
    builder.onLivingHeal(context => {
        // Log a message when the entity heals
        console.log(`${context.entity} just gained ${context.healAmount} health!`)
    })
    builder.onLivingJump(entity => {
        // Log a message when the entity jumps
        console.log(`${entity} just jumped!`)
    })
    builder.onRemovedFromWorld(entity => {
        // Log a message when the entity is removed from the world
        console.log(`${entity} was just removed from the world!`)
    })
    builder.onSpawnChildFromBreeding(context => {
        // Log a message when the entity breeds with another entity
        console.log(`${context.entity} mated with ${context.mate}! *blush*`)
    })
    builder.onSprint(entity => {
        // Log a message when the entity starts sprinting
        console.log(`${entity} is sprinting!`)
    })
    builder.onStartSleeping(context => {
        // Log a message when the entity starts sleeping at a specific position
        console.log(`Sleeping at ${context.blockPos}`)
    })
    builder.onStopRiding(entity => {
        // Drop a diamond above the entity when it stops riding
        if (!entity.isPassenger()) return
        entity.block.popItemFromFace('minecraft:diamond', 'up')
    })
    builder.onStopSleeping(entity => {
        // Log a message when the entity stops sleeping
        console.log(`Stopped sleeping at ${entity.pos}`)
    })
    builder.onTargetChanged(context => {
        //Only firing every 100 ticks to reduce log spam.
        if (context.entity.age % 100 != 0) return
        // Log a message when the entity's target changes
        if (context.target == null) return
        console.log(`${context.target} is being targeted!`)
    })
    builder.playerTouch(context => {
        // Attack the player when touched by the entity
        context.player.attack(1)
    })
    builder.rideTick(entity => {
        // Log a message every 100 ticks if the entity is a vehicle
        if (entity.age % 100 != 0) return
        console.log(entity.isVehicle())
    })
    builder.thunderHit(context => {
        // Heal the entity when struck by lightning
        context.entity.heal(15)
    })
    builder.onTamed(ctx => {
        let entity = ctx.entity
        let player = ctx.player
        // Do stuff when the entity is tamed.
    })
    builder.tameOverride(context => {
        const { entity, player } = context
        // Mimic the vanilla way of setting the uuid when the entity is tamed.
        entity.setOwnerUUID(player.getUuid());
    })
    //Default vanilla implimentation of tickDeath removes the entity from the world after 20 ticks
    /*.tickDeath(entity => {
        // Override the tickDeath method in the entity
    })*/
    builder.onInteract(context => global.interact(context))
})

/**
 *
 * @param {Internal.ContextUtils$MobInteractContext} context
 * @returns
 */
global.interact = context => {
    if (context.player.isShiftKeyDown()) return
    context.player.startRiding(context.entity);
}
Full Animal Entity Example Usage 1.20.1
StartupEvents.registry('entity_type', event => {
    let builder = event.create('wyrm', 'entityjs:tamable')
    /**
     * One-Off values set at the startup of the game.
     */
    builder.immuneTo("minecraft:stone", "minecraft:dirt")
    builder.canSpawnFarFromPlayer(true)
    builder.clientTrackingRange(20)
    builder.mobCategory('monster')
    builder.setRenderType("solid")
    builder.sized(1, 1)
    builder.modelSize(2, 3)
    builder.updateInterval(3)
    builder.defaultDeathPose(true)
    builder.repositionEntityAfterLoad(true)
    builder.isPersistenceRequired(true)
    builder.isAlwaysExperienceDropper(true)
    builder.setDeathSound("minecraft:entity.generic.death")
    builder.canJump(true)
    builder.ambientSoundInterval(100)
    builder.isPushable(true)
    builder.canBreatheUnderwater(true)
    builder.eatingSound("minecraft:entity.zombie.ambient")
    builder.fallSounds("minecraft:entity.generic.small_fall", "minecraft:entity.generic.large_fall")
    builder.fireImmune(false)
    builder.followLeashSpeed(1.5)
    builder.setAmbientSound("minecraft:entity.zombie.ambient")
    builder.mainArm("left")
    builder.mobType('undead')
    builder.saves(true)
    builder.setSoundVolume(0.5)
    builder.setSummonable(true)
    builder.setSwimSound("minecraft:entity.generic.swim")
    builder.setSwimSplashSound("minecraft:entity.generic.splash")
    builder.setWaterSlowDown(0.6)
    builder.shouldDespawnInPeaceful(true)
    builder.mountJumpingEnabled(true)
    builder.tamableFood([
        'minecraft:diamond',
        Ingredient.of("minecraft:bedrock")
    ])
    builder.isFood([
        'minecraft:diamond',
        Ingredient.of("minecraft:apple")
    ])
    // .noEggItem() // Disables automatic egg item creation
    //Customize egg item
    builder.eggItem(item => {
        item.backgroundColor(0);
        item.highlightColor(0);
    })
    builder.canFireProjectileWeapon([
        'minecraft:bow',
        'minecraft:crossbow'
    ])
    builder.newGeoLayer(builder => {
        // New render layers like what the exploding Creeper or the Wither has
        /*builder.textureResource(entity => {
            return "kubejs:textures/entity/sasuke.png"
        })*/
    })
    /**
     * These methods below require a set return value, if the value does not match the required result
     * it will automatically default to the super method in the entity builder and output an error in logs>kubejs>startup.log.
     *
     * Remember all callback functions are also able to be live-edited with global events!
     *
     * Example:
     * global.interact = context => {
     *  if (context.player.isShiftKeyDown()) return
     *      context.player.startRiding(context.entity);
     * }
     *
     * .onInteract(context => global.interact(context)) // Reload this with /kubejs reload startup_scripts
     */

    builder.addAnimationController('exampleController', 1, event => {
        if (event.entity.hurtTime > 0) {
            event.thenPlayAndHold('spawn');
        } else {
            event.thenLoop('idle');
        }
        return true;
    })
    builder.setBreedOffspring(context => {
        const { entity, mate, level } = context
        // Use the context to return a ResourceLocation of an entity to spawn when the entity mates
        return 'minecraft:cow' //Some Resourcelocation representing the entity to spawn.
    })
    builder.addPartEntity("head", 1, 1, builder => {
        // Adds an additional hitbox to the entity with builder support
        builder
            .isPickable(true)
            .onPartHurt(context => {
                const { entity, part, source, amount } = context
                // Custom logic for determining how the parts of the entity should relay damage
                // To the entity. For example, relay double the damage to the entity when this hitbox is hit
                entity.attack(source, amount * 2)
                console.log("source: " + source + " amount: " + amount + " part name: " + part.name)
            })
    })
    builder.aiStep(entity => {
        // Custom logic to be executed during the living entity's AI step
        // Access information about the entity
        // Tick the previously registered part entity/hitbox to be 1 square y-offset to the entity
        entity.tickPart("head", 0, 1, 0)
    })
    builder.setLookControl(entity => {
        return EntityJSUtils.createLookControl(entity, lookControlBuilder => { })
    })
    builder.setMoveControl(entity => {
        return EntityJSUtils.createMoveControl(entity, moveControlBuilder => { })
    })
    builder.setJumpControl(entity => {
        return EntityJSUtils.createJumpControl(entity, jumpControlBuilder => { })
    })
    builder.createNavigation(context => {
        const { entity, level } = context
        // Use the new EntityJSUtils binding to create different path navigations
        // Returning WallClimberNavigation here will allow the entity to path-find up walls like spiders
        return EntityJSUtils.createWallClimberNavigation(entity, level) // Return some path navigation
    })
    builder.render(context => {
        // Define core logic to render the entity (recommended to use .scaleModelForRender instead)
        if (context.entity.isBaby()) {
            return context.poseStack.scale(0.5, 0.5, 0.5); // Scale down if the entity is a baby
        }
        return context.poseStack; // Otherwise, keep the default pose stack
    })
    builder.scaleModelForRender(context => {
        // Define logic to render the entity without changing core logic such as hitbox rendering
        const { entity, widthScale, heightScale, poseStack, model, isReRender, partialTick, packedLight, packedOverlay } = context
        if (entity.hurtTime > 0) {
            poseStack.scale(0.5, 0.5, 0.5)
        }
    })
    builder.jumpBoostPower(entity => {
        //Sets the jump boost power for the entity when they have the jump boost effect applied
        //Mimic vanilla logic with resistance instead of jump boost
        return entity.hasEffect("minecraft:resistance") ? (0.1 * (entity.getEffect("minecraft:resistance").getAmplifier() + 1)) : 0.0;
    })
    builder.setBlockJumpFactor(entity => {
        // Sets block jump factor returning a float value
        if (entity.age > 2000) {
            return 1.3; // Increase jump factor when the entity is old enough
        }
        return 1; // Default jump factor
    })
    builder.setMaxFallDistance(entity => {
        // Define custom logic to determine the maximum fall distance before taking damage
        // Use information about the LivingEntity provided by the context
        if (entity.isOnFire()) {
            return 1; // Reduced fall distance when entity is on fire
        }
        return 3; // Default fall distance
    })
    builder.myRidingOffset(entity => {
        // Use the provided context about the entity to determine the riding offset of the passengers
        if (!entity.isBaby()) {
            return 7; // Increased riding offset when the entity is not a baby
        }
        return 5; // Default riding offset
    })
    builder.animationResource(entity => {
        // Return different animation resources based on the entity's state
        // Use information about the LivingEntity provided by the context.
        if (entity.hurtTime > 0) {
            return // Return some animation path when entity is hurt
        } else {
            return "kubejs:animations/entity/wyrm.animation.json"; // Return Wyrm animation otherwise
        }
    })
    builder.blockSpeedFactor(entity => {
        // Define logic to calculate and return the block speed factor for the entity
        // Use information about the LivingEntity provided by the context.
        const age = entity.age;
        const maxAge = 5000; // Assuming the maximum age is 5000

        // Custom logic to calculate block speed factor based on entity's age
        const factor = age < maxAge ? 1.0 : 0.5; // Reduce speed factor for older entities
        return factor;
    })
    builder.calculateFallDamage(context => {
        // Define logic to calculate and return the fall damage for the entity
        // Use information about the CalculateFallDamageContext provided by the context.
        const fallHeight = context.fallHeight;
        const damageMultiplier = context.damageMultiplier;
        const entity = context.entity;

        // Custom logic to calculate fall damage based on fall height and multiplier
        const calculatedDamage = Math.floor(fallHeight * damageMultiplier);
        return calculatedDamage;
    })
    builder.canAddPassenger(context => {
        // Define custom logic to determine if a passenger can be added to the entity
        // Use information about the PassengerEntityContext provided by the context.
        // For example, check if the entity is not already carrying too many passengers.
        const maxPassengers = 4; // Assuming a maximum of 4 passengers
        return context.entity.getPassengers().size() < maxPassengers;
    })
    builder.isAlliedTo(context => {
        const { entity, target } = context
        return target.type == 'minecraft:blaze'
    })
    builder.canAttack(context => {
        // Define conditions to check if the entity can attack the targetEntity
        // Use information about the LivingEntity provided by the context.
        // For example, check if the targetEntity is not the same as the entity itself.
        return context.target.type !== context.entity.type;
    })
    builder.canAttackType(context => {
        // Define conditions to check if the entity can attack the specified entity type
        // Use information about the EntityTypeEntityContext provided by the context.
        // For example, check if the entity type of the target matches a specific type.
        const targetType = context.targetType.category.friendly;
        // Assuming we want the entity to attack only friendly mobs
        return targetType;
    })
    builder.canBeAffected(context => {
        // Define conditions to check if the entity can be affected by the effect
        // Use information about the OnEffectContext provided by the context.
        // For example, check if the entity is not already affected by a specific effect.
        const effect = context.effect;
        // Assuming we want the entity to be affected only if it doesn't have the same effect already
        return !context.entity.hasEffect(effect.getEffect());
    })
    builder.canChangeDimensions(entity => {
        // Define the conditions for the entity to be able to change dimensions
        // Use information about the LivingEntity provided by the context.
        // For example, allow dimension change only for entities with a specific tag.
        return entity.tags.contains("dimension_changer");
    })
    builder.canDisableShield(entity => {
        // Define the conditions to check if the entity can disable its shield
        // Use information about the LivingEntity provided by the context.
        return entity.mainHandItem.id == 'minecraft:diamond_sword'; // Disable shield if the entity is wielding a diamond sword.
    })
    builder.canFireProjectileWeaponPredicate(context => {
        // Custom logic to determine whether the entity can fire a projectile weapon
        // Access information about the entity and the projectile weapon using the provided context.
        return context.projectileWeapon.id == 'minecraft:bow';
    })
    builder.canFreeze(entity => {
        // Define conditions for the entity to be able to freeze
        // For example, allow freezing only if the entity is in water.
        return entity.inWater;
    })
    builder.canHoldItem(context => {
        // Custom logic to determine whether the entity can hold an item based on the provided context.
        // For example, allow holding an item only if the entity is not a baby.
        return !context.entity.isBaby();
    })
    builder.canBreed(entity => {
        // Custom logic to determine if the entity can breed
        // Use information about the LivingEntity provided by the context.
        // For example, check if the entity has reached maturity.
        const baby = entity.isBaby();
        // Assuming we want the entity to be able to breed only if it's an adult
        return baby;
    })
    builder.canMate(context => {
        // Custom logic to determine if the entity can mate
        // For example, allow mating only if both animals are in the same biome.
        let blockpos1 = context.animal.block.pos
        let blockpos2 = context.otherAnimal.block.pos
        return context.animal.getLevel().getBiome(blockpos1) === context.otherAnimal.getLevel().getBiome(blockpos2);
    })
    builder.canPickUpLoot(entity => {
        // Custom logic to determine whether the entity can pick up loot based on the provided mob.
        // Allow loot pickup during nighttime.

        return !entity.getLevel().isDay(); // Only allow loot pickup during nighttime
    })
    builder.canStandOnFluid(context => {
        // Define conditions for the entity to be able to stand on a fluid
        // Use information about the EntityFluidStateContext provided by the context.
        // Allow standing on water.
        let fluid = Fluid.of("minecraft:water").fluid.fluidType
        return context.fluidState.fluidType == fluid
    })
    builder.canTakeItem(context => {
        // Define conditions for the entity to be able to take an item
        // Use information about the EntityItemLevelContext provided by the context.
        // Allow taking items only if the living entity is not null and the item stack is not empty.
        return context.entity !== null && !context.itemStack.isEmpty();
    })
    builder.dampensVibrations(entity => {
        // Determine whether the living entity dampens vibrations
        // Return true if the entity dampens vibrations, false otherwise
        // For example, return true if the entity has no gravity.
        return entity.isNoGravity();
    })
    builder.experienceReward(killedEntity => {
        // Define logic to calculate and return the experience reward for the killedEntity
        // Use information about the LivingEntity provided by the context.
        // For example, return 5 times the armor cover percentage of the entity.
        const armorCoverPercentage = killedEntity.armorCoverPercentage + 1;
        return armorCoverPercentage * 5;
    })
    builder.hasLineOfSight(context => {
        // Check if the target entity is within the same level
        if (context.targetEntity.getLevel() !== context.entity.getLevel()) {
            return false;
        }
        // Get the positions of the entities
        // In 1.20.1+ this is Vec3d instead of Vec3
        const entityPos = new Vec3d(context.entity.getX(), context.entity.getEyeY(), context.entity.getZ());
        const targetPos = new Vec3d(context.targetEntity.getX(), context.targetEntity.getEyeY(), context.targetEntity.getZ());
        // Calculate the distance between the two entities
        const distance = entityPos.distanceTo(targetPos);
        // Check if the target entity is within a reasonable range
        if (distance > 128.0) {
            return false;
        }
        // Allow the entity to "see through" blocks by not implimenting ClipContext as done in LivingEntity Class.
        return true;
    })
    builder.setHurtSound(context => {
        // Custom logic to determine the hurt sound for the entity
        // You can use information from the HurtContext to customize the sound based on the context
        const { entity, damageSource } = context;
        // Determine the hurt sound based on the type of damage source
        switch (damageSource.getType()) {
            case "fire":
                return "minecraft:entity.generic.burn";
            case "fall":
                return "minecraft:entity.generic.hurt";
            case "drown":
                return "minecraft:entity.generic.hurt";
            case "explosion":
                return "minecraft:entity.generic.explode";
            default:
                return "minecraft:entity.generic.explode";
        }
    })
    builder.invertedHealAndHarm(entity => {
        //Used by undead mobs to invert potion effects such as Instant Health & Instant Damage
        const blockAboveHasSky = entity.block.down.canSeeSky;
        return blockAboveHasSky; // Return true if the block below has sky visibility
    })
    builder.isAffectedByFluids(entity => {
        // Define logic to determine whether the entity is affected by fluids
        // For example, check if the entity is swimming or flying
        return entity.isSwimming() || entity.isFallFlying();
    })
    builder.isAffectedByPotions(entity => {
        // Define conditions to check if the entity is affected by potions
        // For example, check if the entity has any active potion effects
        return entity.getActiveEffects().size() > 0;
    })
    builder.isAttackable(entity => {
        // Define conditions to check if the entity is attackable
        // For example, check if the entity is not invulnerable
        return !entity.isInvulnerable();
    })
    builder.isCurrentlyGlowing(entity => {
        // Define the conditions to check if the entity is currently glowing
        // For example, check if the entity has a regeneration or glowing effect applied
        return entity.hasEffect("minecraft:regeneration") || entity.hasEffect("minecraft:glowing");
    })
    builder.isFlapping(entity => {
        // Mimics the Ender Dragon's Flapping Behavior
        // Define logic to determine whether the entity is currently flapping
        const flapTime = entity.flapTime; // Current flap time
        const oFlapTime = entity.oFlapTime; // Previous flap time

        // Calculate cosine values for the current and previous flap times
        const f = Math.cos(flapTime * 6.2831855);
        const f1 = Math.cos(oFlapTime * 6.2831855);

        // Check if the entity is flapping based on cosine values
        return f1 <= -0.3 && f >= -0.3;
    })
    builder.tamableFoodPredicate(context => {
        const { entity, item } = context
        return item.id == 'minecraft:carrot' // Return true if the player's current itemstack will tame the mob.
    })
    builder.isFoodPredicate(context => {
        // Custom logic to determine if the entity item stack is considered as food.
        // Access information about the item stack using the provided context.
        const itemStack = context.item; // Get the item stack from the context

        // Example condition: Check if the item stack is edible
        return itemStack.isEdible();
    })
    builder.isFreezing(entity => {
        // Define the conditions for the entity to start freezing
        // Use information about the LivingEntity provided by the context.
        // Start freezing the entity if they're in the taiga biome and can freeze.
        return entity.getLevel().getBiome(entity.block.pos) == 'minecraft:taiga' && entity.canFreeze();
    })
    builder.isImmobile(entity => {
        // Define logic to determine whether the entity is immobile
        // Use information about the LivingEntity provided by the context.
        return entity.isSleeping(); // Example: Entity is immobile if sleeping
    })
    builder.isInvulnerableTo(context => {
        // Define conditions for the entity to be invulnerable to the specific type of damage
        // Use information about the DamageContext provided by the context.

        // Example condition: Entity is invulnerable to magic damage
        return context.damageSource.getType() == 'magic';
    })
    builder.isSensitiveToWater(entity => {
        // Define conditions to check if the entity is in a "Cold Ocean" biome and sensitive to water
        // Use information about the LivingEntity provided by the context.

        // Example condition: Check if the biome ID corresponds to a "Cold Ocean" biome
        return entity.getLevel().getBiome(entity.block.pos).is('minecraft:cold_ocean')
    })
    builder.isSleeping(entity => {
        // Check if the entity has a sleeping position
        // Use information about the LivingEntity provided by the context.
        //Mimics how vanilla does the isSleeping() method.
        return entity.getSleepingPos().isPresent();
    })
    builder.mayInteract(context => {
        // Define conditions for the entity to be allowed to interact with the world
        // Use information about the MayInteractContext provided by the context.
        return context.entity.getTags().contains('canInteractWithWorld')
    })
    builder.meleeAttackRangeSqr(entity => {
        // Define custom logic to calculate the squared melee attack range based on the provided entity.
        // For example, you can calculate based on the size or type of the entity.
        const size = entity.boundingBox.size;
        const range = size * size; // Adjust this calculation based on your requirements
        return range;
    })
    builder.nextStep(entity => {
        // Define custom logic to calculate the next step distance based on the provided entity.
        const movementSpeed = entity.getTotalMovementSpeed(); // Get the entity's movement speed
        //If the entity is not an animal return default vanilla behavior
        if (!entity.animal) return entity.moveDist + 1;
        const behaviorFactor = entity.isAggressive() ? 1.5 : 1; // Adjust the step distance based on behavior
        // Calculate the next step distance based on movement speed, size, and behavior
        const nextStepDistance = movementSpeed * behaviorFactor;
        return nextStepDistance;
    })
    builder.onClimbable(entity => {
        const blockBelow = entity.block.down; // Get the block below the entity
        // Check if the block below the entity is climbable (e.g., a ladder, vine, or scaffold)
        const isClimbableBlock = blockBelow.hasTag('minecraft:my_climbeable_block_tag');

        // Check if the entity is currently moving upwards (which might indicate climbing)
        const isMovingUpwards = entity.motionY > 0;

        // Return true if the entity is on a climbable surface and moving upwards
        return isClimbableBlock && isMovingUpwards;
    })
    builder.removeWhenFarAway(context => {
        // Get information from the context
        const { distanceToClosestPlayer } = context;
        // Return true if the entity is far away from the closest player and should be removed
        //Fine tune removal logic
        return distanceToClosestPlayer > 64;
    })
    builder.scale(entity => {
        // Define logic to calculate the custom scale for the entity
        // For example, you can scale the entity based on its size or other properties
        return entity.isBaby() ? 0.5 : 1;
    })
    builder.setStandingEyeHeight(context => {
        // Define logic to calculate and return the standing eye height for the entity
        // Use information about the EntityPoseDimensionsContext provided by the context
        const entity = context.entity; // Get the entity from the context
        const pose = context.pose; // Get the entity pose from the context

        // Define default standing eye height
        let standingEyeHeight = 1.8; // Default human-like standing eye height

        // Adjust standing eye height based on entity pose if needed
        if (pose === 'crouching') {
            standingEyeHeight = 1.5; // Adjust standing eye height for crouching pose
        }

        // Return the calculated standing eye height
        return standingEyeHeight;
    })
    builder.shouldDropExperience(entity => {
        // Define conditions to check if the entity should drop experience upon death
        // Use information about the LivingEntity provided by the context.
        return entity.block.down.id == 'minecraft:grass_block'// Only drop experience if the entity dies on grass
    })
    builder.shouldDropLoot(entity => {
        // Define logic to determine whether the entity should drop loot
        // Use information about the LivingEntity provided by the context.
        return !entity.isBaby(); //Only drop loot if they're an adult
    })
    builder.showVehicleHealth(entity => {
        // Determine whether to show the vehicle health for the living entity
        // Return true to show the vehicle health, false otherwise
        return !entity.isFallFlying(); //Only show vehicle's health to the player if the vehicle is fall flying
    })
    builder.visibilityPercent(context => {
        // Define logic to calculate and return the visibility percentage for the targetEntity
        // Use information about the Entity provided by the context.
        // Our mob is less 'seen' by other mobs in the plains biome by 20%.
        return context.lookingEntity.age > 0 ? 0.8 : 1
    })
    builder.walkTargetValue(context => {
        const { levelReader, pos } = context; // Destructure context for easier access

        // Get the block state below the given position
        const blockBelow = levelReader.getBlockState(pos.below());

        // Adjust walk target value based on the block below, is usually Grass Block in Vanilla
        return blockBelow.is(Blocks.AZALEA_LEAVES) ? 10 : levelReader.getPathfindingCostFromLightLevels(pos);
    })
    builder.canCollideWith(context => {
        return true //Some Boolean value determining whether the entity may collid with another
    })

    /**
     * All methods below return void meaning they don't require a set return value to function.
     * These mostly are similar to KubeJS' normal events where you may do things on certain events your entities call!
     */

    builder.tickLeash(context => {
        const { player, entity } = context
        if (player != undefined && player.isDiscrete()) {
            // Give the player a diamond
            player.give(Item.of('minecraft:diamond'));
            // Print a message indicating the diamond was given
            console.log(`Gave ${player.getName()} a diamond for sneaking while leashing ${entity.type}.`);
        }
    })
    builder.tick(entity => {
        if (entity.age % 100 != 0) return
        console.log('ticked every 100 ticks')
    })
    builder.lavaHurt(entity => {
        // Heal the entity by 20 health points
        entity.heal(20);
    })
    builder.doAutoAttackOnTouch(context => {
        // Attack the target entity with a damage value of 1
        context.target.attack(1);
    })
    builder.ate(entity => {
        // Log a message when the entity eats something
        console.log(`${entity.type} just ate!`)
    })
    builder.dropCustomDeathLoot(context => {
        // Drop custom loot (iron ingot) when the entity dies with a looting multiplier of 2
        if (context.lootingMultiplier == 2) context.entity.block.popItemFromFace('minecraft:iron_ingot', 'up')
    })
    builder.eat(context => {
        // Heal the entity when it eats something
        context.entity.heal(20)
    })
    builder.lerpTo(context => {
        const { x, y, z, yaw, pitch, entity, delta } = context;
        // Set the entity's position directly to the target position if the entity is freezing
        if (entity.isFreezing()) entity.setPosition(x, y, z);
    })
    builder.onAddedToWorld(entity => {
        // Teleport the entity slightly above its current position when added to the world
        let namespace = entity.getLevel().dimension.namespace
        let path = entity.getLevel().dimension.path
        entity.teleportTo(`${namespace}:${path}`, entity.x, entity.y + 1, entity.z, 1, 1)
    })
    builder.onBlockedByShield(context => {
        const { entity, target } = context
        // Log a message when the target is blocked by a shield
        console.log(`${target} Get blocked!`)
    })
    builder.onClientRemoval(entity => {
        // Log a message when the entity is removed on the client side
        console.log(`${entity} was removed on the client`)
    })
    builder.onDeath(context => {
        // Place a diamond ore block below the entity when it dies
        context.entity.block.down.set('minecraft:diamond_ore')
    })
    builder.onDecreaseAirSupply(entity => {
        if (entity.age % 20 != 0) return
        // Log the entity's remaining air supply when it decreases
        console.log(entity.airSupply)
    })
    builder.onEffectAdded(context => {
        // Log the description ID of an added effect
        console.log(context.effect.descriptionId)
    })
    builder.onEffectRemoved(context => {
        // Log the description ID of a removed effect
        console.log(context.effect.descriptionId)
    })
    builder.onEnterCombat(entity => {
        // Log a message when the entity enters combat
        console.log(`${entity} just entered combat`)
    })
    builder.onEquipItem(context => {
        // Log the ID of the item being equipped by the entity
        if (context.entity.age % 100 != 0) return
        console.log(context.currentStack.id)
    })
    builder.onFlap(entity => {
        // Place a gold ore block below the entity when it flaps
        entity.block.down.set('minecraft:gold_ore')
    })
    builder.onHurt(context => {
        // Log the amount of damage received by the entity
        console.log(context.damageAmount)
    })
    builder.onIncreaseAirSupply(entity => {
        if (entity.age % 20 != 0) return
        // Log a message when the entity's air supply increases
        console.log(`${entity} increasing air`)
    })
    builder.onItemPickup(context => {
        // Log the ID of the item picked up by the entity
        console.log(context.itemEntity.id)
    })
    builder.onLeaveCombat(entity => {
        // Log a message when the entity leaves combat
        console.log(`${entity} just left combat!`)
    })
    builder.onLivingFall(context => {
        // Log a message when the entity falls
        console.log(`${context.entity} just fell ${context.distance} blocks!`)
    })
    builder.onLivingHeal(context => {
        // Log a message when the entity heals
        console.log(`${context.entity} just gained ${context.healAmount} health!`)
    })
    builder.onLivingJump(entity => {
        // Log a message when the entity jumps
        console.log(`${entity} just jumped!`)
    })
    builder.onRemovedFromWorld(entity => {
        // Log a message when the entity is removed from the world
        console.log(`${entity} was just removed from the world!`)
    })
    builder.onSpawnChildFromBreeding(context => {
        // Log a message when the entity breeds with another entity
        console.log(`${context.entity} mated with ${context.mate}! *blush*`)
    })
    builder.onSprint(entity => {
        // Log a message when the entity starts sprinting
        console.log(`${entity} is sprinting!`)
    })
    builder.onStartSleeping(context => {
        // Log a message when the entity starts sleeping at a specific position
        console.log(`Sleeping at ${context.blockPos}`)
    })
    builder.onStopRiding(entity => {
        // Drop a diamond above the entity when it stops riding
        if (!entity.isPassenger()) return
        entity.block.popItemFromFace('minecraft:diamond', 'up')
    })
    builder.onStopSleeping(entity => {
        // Log a message when the entity stops sleeping
        console.log(`Stopped sleeping at ${entity.pos}`)
    })
    builder.onTargetChanged(context => {
        //Only firing every 100 ticks to reduce log spam.
        if (context.entity.age % 100 != 0) return
        // Log a message when the entity's target changes
        if (context.target == null) return
        console.log(`${context.target} is being targeted!`)
    })
    builder.playerTouch(context => {
        // Attack the player when touched by the entity
        context.player.attack(1)
    })
    builder.rideTick(entity => {
        // Log a message every 100 ticks if the entity is a vehicle
        if (entity.age % 100 != 0) return
        console.log(entity.isVehicle())
    })
    builder.thunderHit(context => {
        // Heal the entity when struck by lightning
        context.entity.heal(15)
    })
    builder.onTamed(ctx => {
        let entity = ctx.entity
        let player = ctx.player
        // Do stuff when the entity is tamed.
    })
    builder.tameOverride(context => {
        const { entity, player } = context
        // Mimic the vanilla way of setting the uuid when the entity is tamed.
        entity.setOwnerUUID(player.getUuid());
    })
    //Default vanilla implimentation of tickDeath removes the entity from the world after 20 ticks
    /*.tickDeath(entity => {
        // Override the tickDeath method in the entity
    })*/
    builder.onInteract(context => global.interact(context))
})

/**
 *
 * @param {Internal.ContextUtils$MobInteractContext} context
 * @returns
 */
global.interact = context => {
    if (context.player.isShiftKeyDown()) return
    context.player.startRiding(context.entity);
}
Full Animal Entity Example Usage 1.21
StartupEvents.registry('entity_type', event => {
    let builder = event.create('sasuke', "entityjs:tamable")
    /**
     * One-Off values set at the startup of the game.
     */
    builder.immuneTo("minecraft:stone", "minecraft:dirt")
    builder.canSpawnFarFromPlayer(true)
    builder.clientTrackingRange(20)
    builder.mobCategory('monster')
    builder.setRenderType("solid")
    builder.sized(1, 1)
    builder.modelSize(2, 3)
    builder.updateInterval(3)
    builder.defaultDeathPose(true)
    builder.repositionEntityAfterLoad(true)
    builder.isPersistenceRequired(true)
    builder.isAlwaysExperienceDropper(true)
    builder.setDeathSound("minecraft:entity.generic.death")
    builder.canJump(true)
    builder.ambientSoundInterval(100)
    builder.isPushable(true)
    builder.canBreatheUnderwater(true)
    builder.eatingSound("minecraft:entity.zombie.ambient")
    builder.fallSounds("minecraft:entity.generic.small_fall", "minecraft:entity.generic.large_fall")
    builder.fireImmune(false)
    builder.followLeashSpeed(1.5)
    builder.setAmbientSound("minecraft:entity.zombie.ambient")
    builder.mainArm("left")
    builder.saves(true)
    builder.setSoundVolume(0.5)
    builder.setSummonable(true)
    builder.setSwimSound("minecraft:entity.generic.swim")
    builder.setSwimSplashSound("minecraft:entity.generic.splash")
    builder.setWaterSlowDown(0.6)
    builder.shouldDespawnInPeaceful(true)
    builder.mountJumpingEnabled(true)
    builder.tamableFood([
        'minecraft:diamond',
        Ingredient.of("minecraft:bedrock")
    ])
    builder.isFood([
        'minecraft:diamond',
        Ingredient.of("minecraft:apple")
    ])
    // .noEggItem() // Disables automatic egg item creation
    //Customize egg item
    builder.eggItem(item => {
        item.backgroundColor(0);
        item.highlightColor(0);
    })
    builder.canFireProjectileWeapon([
        'minecraft:bow',
        'minecraft:crossbow'
    ])
    builder.newGeoLayer(builder => {
        // New render layers like what the exploding Creeper or the Wither has
        /*builder.textureResource(entity => {
            return "kubejs:textures/entity/sasuke.png"
        })*/
    })
    /**
     * These methods below require a set return value, if the value does not match the required result
     * it will automatically default to the super method in the entity builder and output an error in logs>kubejs>startup.log.
     *
     * Remember all callback functions are also able to be live-edited with global events!
     *
     * Example:
     * global.interact = context => {
     *  if (context.player.isShiftKeyDown()) return
     *      context.player.startRiding(context.entity);
     * }
     *
     * .onInteract(context => global.interact(context)) // Reload this with /kubejs reload startup_scripts
     */

    builder.addAnimationController('exampleController', 1, event => {
        if (event.entity.hurtTime > 0) {
            event.thenPlayAndHold('spawn');
        } else {
            event.thenLoop('idle');
        }
        return true;
    })
    builder.setBreedOffspring(context => {
        const { entity, mate, level } = context
        // Use the context to return a ResourceLocation of an entity to spawn when the entity mates
        return 'minecraft:cow' //Some Resourcelocation representing the entity to spawn.
    })
    builder.addPartEntity("head", 1, 1, builder => {
        // Adds an additional hitbox to the entity with builder support
        builder
            .isPickable(true)
            .onPartHurt(context => {
                const { entity, part, source, amount } = context
                // Custom logic for determining how the parts of the entity should relay damage
                // To the entity. For example, relay double the damage to the entity when this hitbox is hit
                entity.attack(source, amount * 2)
                console.log("source: " + source + " amount: " + amount + " part name: " + part.name)
            })
    })
    builder.aiStep(entity => {
        // Custom logic to be executed during the living entity's AI step
        // Access information about the entity
        // Tick the previously registered part entity/hitbox to be 1 square y-offset to the entity
        entity.tickPart("head", 0, 1, 0)
    })
    builder.setLookControl(entity => {
        return EntityJSUtils.createLookControl(entity, lookControlBuilder => { })
    })
    builder.setMoveControl(entity => {
        return EntityJSUtils.createMoveControl(entity, moveControlBuilder => { })
    })
    builder.setJumpControl(entity => {
        return EntityJSUtils.createJumpControl(entity, jumpControlBuilder => { })
    })
    builder.createNavigation(context => {
        const { entity, level } = context
        // Use the new EntityJSUtils binding to create different path navigations
        // Returning WallClimberNavigation here will allow the entity to path-find up walls like spiders
        return EntityJSUtils.createWallClimberNavigation(entity, level) // Return some path navigation
    })
    builder.render(context => {
        // Define core logic to render the entity (recommended to use .scaleModelForRender instead)
        if (context.entity.isBaby()) {
            return context.poseStack.scale(0.5, 0.5, 0.5); // Scale down if the entity is a baby
        }
        return context.poseStack; // Otherwise, keep the default pose stack
    })
    builder.scaleModelForRender(context => {
        // Define logic to render the entity without changing core logic such as hitbox rendering
        const { entity, widthScale, heightScale, poseStack, model, isReRender, partialTick, packedLight, packedOverlay } = context
        if (entity.hurtTime > 0) {
            poseStack.scale(0.5, 0.5, 0.5)
        }
    })
    builder.getAttackBoundingBox(entity => {
        // Custom logic to calculate the squared melee attack range based on the provided mob.
        return entity;
    })
    builder.jumpBoostPower(entity => {
        //Sets the jump boost power for the entity when they have the jump boost effect applied
        //Mimic vanilla logic with resistance instead of jump boost
        return entity.hasEffect("minecraft:resistance") ? (0.1 * (entity.getEffect("minecraft:resistance").getAmplifier() + 1)) : 0.0;
    })
    builder.setBlockJumpFactor(entity => {
        // Sets block jump factor returning a float value
        if (entity.age > 2000) {
            return 1.3; // Increase jump factor when the entity is old enough
        }
        return 1; // Default jump factor
    })
    builder.setMaxFallDistance(entity => {
        // Define custom logic to determine the maximum fall distance before taking damage
        // Use information about the LivingEntity provided by the context
        if (entity.isOnFire()) {
            return 1; // Reduced fall distance when entity is on fire
        }
        return 3; // Default fall distance
    })
    builder.animationResource(entity => {
        // Return different animation resources based on the entity's state
        // Use information about the LivingEntity provided by the context.
        if (entity.hurtTime > 0) {
            return // Return some animation path when entity is hurt
        } else {
            return "kubejs:animations/entity/wyrm.animation.json"; // Return Wyrm animation otherwise
        }
    })
    builder.blockSpeedFactor(entity => {
        // Define logic to calculate and return the block speed factor for the entity
        // Use information about the LivingEntity provided by the context.
        const age = entity.age;
        const maxAge = 5000; // Assuming the maximum age is 5000

        // Custom logic to calculate block speed factor based on entity's age
        const factor = age < maxAge ? 1.0 : 0.5; // Reduce speed factor for older entities
        return factor;
    })
    builder.calculateFallDamage(context => {
        // Define logic to calculate and return the fall damage for the entity
        // Use information about the CalculateFallDamageContext provided by the context.
        const fallHeight = context.fallHeight;
        const damageMultiplier = context.damageMultiplier;
        const entity = context.entity;

        // Custom logic to calculate fall damage based on fall height and multiplier
        const calculatedDamage = Math.floor(fallHeight * damageMultiplier);
        return calculatedDamage;
    })
    builder.canAddPassenger(context => {
        // Define custom logic to determine if a passenger can be added to the entity
        // Use information about the PassengerEntityContext provided by the context.
        // For example, check if the entity is not already carrying too many passengers.
        const maxPassengers = 4; // Assuming a maximum of 4 passengers
        return context.entity.getPassengers().size() < maxPassengers;
    })
    builder.isAlliedTo(context => {
        const { entity, target } = context
        return target.type == 'minecraft:blaze'
    })
    builder.canAttack(context => {
        // Define conditions to check if the entity can attack the targetEntity
        // Use information about the LivingEntity provided by the context.
        // For example, check if the targetEntity is not the same as the entity itself.
        return context.target.type !== context.entity.type;
    })
    builder.canAttackType(context => {
        // Define conditions to check if the entity can attack the specified entity type
        // Use information about the EntityTypeEntityContext provided by the context.
        // For example, check if the entity type of the target matches a specific type.
        const targetType = context.targetType.category.friendly;
        // Assuming we want the entity to attack only friendly mobs
        return targetType;
    })
    builder.canBeAffected(context => {
        // Define conditions to check if the entity can be affected by the effect
        // Use information about the OnEffectContext provided by the context.
        // For example, check if the entity is not already affected by a specific effect.
        const effect = context.effect;
        // Assuming we want the entity to be affected only if it doesn't have the same effect already
        return !context.entity.hasEffect(effect.getEffect());
    })
    builder.canChangeDimensions(entity => {
        // Define the conditions for the entity to be able to change dimensions
        // Use information about the LivingEntity provided by the context.
        // For example, allow dimension change only for entities with a specific tag.
        return entity.tags.contains("dimension_changer");
    })
    builder.canDisableShield(entity => {
        // Define the conditions to check if the entity can disable its shield
        // Use information about the LivingEntity provided by the context.
        return entity.mainHandItem.id == 'minecraft:diamond_sword'; // Disable shield if the entity is wielding a diamond sword.
    })
    builder.canFireProjectileWeaponPredicate(context => {
        // Custom logic to determine whether the entity can fire a projectile weapon
        // Access information about the entity and the projectile weapon using the provided context.
        return context.projectileWeapon.id == 'minecraft:bow';
    })
    builder.canFreeze(entity => {
        // Define conditions for the entity to be able to freeze
        // For example, allow freezing only if the entity is in water.
        return entity.inWater;
    })
    builder.canHoldItem(context => {
        // Custom logic to determine whether the entity can hold an item based on the provided context.
        // For example, allow holding an item only if the entity is not a baby.
        return !context.entity.isBaby();
    })
    builder.canBreed(entity => {
        // Custom logic to determine if the entity can breed
        // Use information about the LivingEntity provided by the context.
        // For example, check if the entity has reached maturity.
        const baby = entity.isBaby();
        // Assuming we want the entity to be able to breed only if it's an adult
        return baby;
    })
    builder.canMate(context => {
        // Custom logic to determine if the entity can mate
        // For example, allow mating only if both animals are in the same biome.
        let blockpos1 = context.animal.block.pos
        let blockpos2 = context.otherAnimal.block.pos
        return context.animal.getLevel().getBiome(blockpos1) === context.otherAnimal.getLevel().getBiome(blockpos2);
    })
    builder.canPickUpLoot(entity => {
        // Custom logic to determine whether the entity can pick up loot based on the provided mob.
        // Allow loot pickup during nighttime.

        return !entity.getLevel().isDay(); // Only allow loot pickup during nighttime
    })
    builder.canStandOnFluid(context => {
        // Define conditions for the entity to be able to stand on a fluid
        // Use information about the EntityFluidStateContext provided by the context.
        // Allow standing on water.
        let fluid = Fluid.of("minecraft:water").fluid.fluidType
        return context.fluidState.fluidType == fluid
    })
    builder.canTakeItem(context => {
        // Define conditions for the entity to be able to take an item
        // Use information about the EntityItemLevelContext provided by the context.
        // Allow taking items only if the living entity is not null and the item stack is not empty.
        return context.entity !== null && !context.itemStack.isEmpty();
    })
    builder.dampensVibrations(entity => {
        // Determine whether the living entity dampens vibrations
        // Return true if the entity dampens vibrations, false otherwise
        // For example, return true if the entity has no gravity.
        return entity.isNoGravity();
    })
    builder.experienceReward(killedEntity => {
        // Define logic to calculate and return the experience reward for the killedEntity
        // Use information about the LivingEntity provided by the context.
        // For example, return 5 times the armor cover percentage of the entity.
        const armorCoverPercentage = killedEntity.armorCoverPercentage + 1;
        return armorCoverPercentage * 5;
    })
    builder.hasLineOfSight(context => {
        // Check if the target entity is within the same level
        if (context.targetEntity.getLevel() !== context.entity.getLevel()) {
            return false;
        }
        // Get the positions of the entities
        // In 1.20.1+ this is Vec3d instead of Vec3
        const entityPos = new Vec3d(context.entity.getX(), context.entity.getEyeY(), context.entity.getZ());
        const targetPos = new Vec3d(context.targetEntity.getX(), context.targetEntity.getEyeY(), context.targetEntity.getZ());
        // Calculate the distance between the two entities
        const distance = entityPos.distanceTo(targetPos);
        // Check if the target entity is within a reasonable range
        if (distance > 128.0) {
            return false;
        }
        // Allow the entity to "see through" blocks by not implimenting ClipContext as done in LivingEntity Class.
        return true;
    })
    builder.setHurtSound(context => {
        // Custom logic to determine the hurt sound for the entity
        // You can use information from the HurtContext to customize the sound based on the context
        const { entity, damageSource } = context;
        // Determine the hurt sound based on the type of damage source
        switch (damageSource.getType()) {
            case "fire":
                return "minecraft:entity.generic.burn";
            case "fall":
                return "minecraft:entity.generic.hurt";
            case "drown":
                return "minecraft:entity.generic.hurt";
            case "explosion":
                return "minecraft:entity.generic.explode";
            default:
                return "minecraft:entity.generic.explode";
        }
    })
    builder.invertedHealAndHarm(entity => {
        //Used by undead mobs to invert potion effects such as Instant Health & Instant Damage
        const blockAboveHasSky = entity.block.down.canSeeSky;
        return blockAboveHasSky; // Return true if the block below has sky visibility
    })
    builder.isAffectedByFluids(entity => {
        // Define logic to determine whether the entity is affected by fluids
        // For example, check if the entity is swimming or flying
        return entity.isSwimming() || entity.isFallFlying();
    })
    builder.isAffectedByPotions(entity => {
        // Define conditions to check if the entity is affected by potions
        // For example, check if the entity has any active potion effects
        return entity.getActiveEffects().size() > 0;
    })
    builder.isAttackable(entity => {
        // Define conditions to check if the entity is attackable
        // For example, check if the entity is not invulnerable
        return !entity.isInvulnerable();
    })
    builder.isCurrentlyGlowing(entity => {
        // Define the conditions to check if the entity is currently glowing
        // For example, check if the entity has a regeneration or glowing effect applied
        return entity.hasEffect("minecraft:regeneration") || entity.hasEffect("minecraft:glowing");
    })
    builder.isFlapping(entity => {
        // Mimics the Ender Dragon's Flapping Behavior
        // Define logic to determine whether the entity is currently flapping
        const flapTime = entity.flapTime; // Current flap time
        const oFlapTime = entity.oFlapTime; // Previous flap time

        // Calculate cosine values for the current and previous flap times
        const f = Math.cos(flapTime * 6.2831855);
        const f1 = Math.cos(oFlapTime * 6.2831855);

        // Check if the entity is flapping based on cosine values
        return f1 <= -0.3 && f >= -0.3;
    })
    builder.tamableFoodPredicate(context => {
        const { entity, item } = context
        return item.id == 'minecraft:carrot' // Return true if the player's current itemstack will tame the mob.
    })
    builder.isFoodPredicate(context => {
        // Custom logic to determine if the entity item stack is considered as food.
        // Access information about the item stack using the provided context.
        const itemStack = context.item; // Get the item stack from the context

        // Example condition: Check if the item stack is edible
        return itemStack.isEdible();
    })
    builder.isFreezing(entity => {
        // Define the conditions for the entity to start freezing
        // Use information about the LivingEntity provided by the context.
        // Start freezing the entity if they're in the taiga biome and can freeze.
        return entity.getLevel().getBiome(entity.block.pos) == 'minecraft:taiga' && entity.canFreeze();
    })
    builder.isImmobile(entity => {
        // Define logic to determine whether the entity is immobile
        // Use information about the LivingEntity provided by the context.
        return entity.isSleeping(); // Example: Entity is immobile if sleeping
    })
    builder.isInvulnerableTo(context => {
        // Define conditions for the entity to be invulnerable to the specific type of damage
        // Use information about the DamageContext provided by the context.

        // Example condition: Entity is invulnerable to magic damage
        return context.damageSource.getType() == 'magic';
    })
    builder.isSensitiveToWater(entity => {
        // Define conditions to check if the entity is in a "Cold Ocean" biome and sensitive to water
        // Use information about the LivingEntity provided by the context.

        // Example condition: Check if the biome ID corresponds to a "Cold Ocean" biome
        return entity.getLevel().getBiome(entity.block.pos).is('minecraft:cold_ocean')
    })
    builder.isSleeping(entity => {
        // Check if the entity has a sleeping position
        // Use information about the LivingEntity provided by the context.
        //Mimics how vanilla does the isSleeping() method.
        return entity.getSleepingPos().isPresent();
    })
    builder.mayInteract(context => {
        // Define conditions for the entity to be allowed to interact with the world
        // Use information about the MayInteractContext provided by the context.
        return context.entity.getTags().contains('canInteractWithWorld')
    })
    builder.nextStep(entity => {
        // Define custom logic to calculate the next step distance based on the provided entity.
        const movementSpeed = entity.getTotalMovementSpeed(); // Get the entity's movement speed
        //If the entity is not an animal return default vanilla behavior
        if (!entity.animal) return entity.moveDist + 1;
        const behaviorFactor = entity.isAggressive() ? 1.5 : 1; // Adjust the step distance based on behavior
        // Calculate the next step distance based on movement speed, size, and behavior
        const nextStepDistance = movementSpeed * behaviorFactor;
        return nextStepDistance;
    })
    builder.onClimbable(entity => {
        const blockBelow = entity.block.down; // Get the block below the entity
        // Check if the block below the entity is climbable (e.g., a ladder, vine, or scaffold)
        const isClimbableBlock = blockBelow.hasTag('minecraft:my_climbeable_block_tag');

        // Check if the entity is currently moving upwards (which might indicate climbing)
        const isMovingUpwards = entity.motionY > 0;

        // Return true if the entity is on a climbable surface and moving upwards
        return isClimbableBlock && isMovingUpwards;
    })
    builder.removeWhenFarAway(context => {
        // Get information from the context
        const { distanceToClosestPlayer } = context;
        // Return true if the entity is far away from the closest player and should be removed
        //Fine tune removal logic
        return distanceToClosestPlayer > 64;
    })
    builder.scale(entity => {
        // Define logic to calculate the custom scale for the entity
        // For example, you can scale the entity based on its size or other properties
        return entity.isBaby() ? 0.5 : 1;
    })
    builder.shouldDropExperience(entity => {
        // Define conditions to check if the entity should drop experience upon death
        // Use information about the LivingEntity provided by the context.
        return entity.block.down.id == 'minecraft:grass_block'// Only drop experience if the entity dies on grass
    })
    builder.shouldDropLoot(entity => {
        // Define logic to determine whether the entity should drop loot
        // Use information about the LivingEntity provided by the context.
        return !entity.isBaby(); //Only drop loot if they're an adult
    })
    builder.showVehicleHealth(entity => {
        // Determine whether to show the vehicle health for the living entity
        // Return true to show the vehicle health, false otherwise
        return !entity.isFallFlying(); //Only show vehicle's health to the player if the vehicle is fall flying
    })
    builder.visibilityPercent(context => {
        // Define logic to calculate and return the visibility percentage for the targetEntity
        // Use information about the Entity provided by the context.
        // Our mob is less 'seen' by other mobs in the plains biome by 20%.
        return context.lookingEntity.age > 0 ? 0.8 : 1
    })
    builder.walkTargetValue(context => {
        const { levelReader, pos } = context; // Destructure context for easier access

        // Get the block state below the given position
        const blockBelow = levelReader.getBlockState(pos.below());

        // Adjust walk target value based on the block below, is usually Grass Block in Vanilla
        return blockBelow.is(Blocks.AZALEA_LEAVES) ? 10 : levelReader.getPathfindingCostFromLightLevels(pos);
    })
    builder.canCollideWith(context => {
        return true //Some Boolean value determining whether the entity may collid with another
    })

    /**
     * All methods below return void meaning they don't require a set return value to function.
     * These mostly are similar to KubeJS' normal events where you may do things on certain events your entities call!
     */
    builder.tick(entity => {
        if (entity.age % 100 != 0) return
    })
    builder.lavaHurt(entity => {
        // Heal the entity by 20 health points
        entity.heal(20);
    })
    builder.doAutoAttackOnTouch(context => {
        // Attack the target entity with a damage value of 1
        context.target.attack(1);
    })
    builder.ate(entity => {
        // Log a message when the entity eats something
        console.log(`${entity.type} just ate!`)
    })
    builder.dropCustomDeathLoot(context => {
        const { damageSource, serverLevel, hitByPlayer, entity } = context
        if (hitByPlayer) context.entity.block.popItemFromFace('minecraft:iron_ingot', 'up')
    })
    builder.eat(context => {
        // Heal the entity when it eats something
        context.entity.heal(20)
    })
    builder.lerpTo(context => {
        const { x, y, z, yaw, pitch, entity, delta } = context;
        // Set the entity's position directly to the target position if the entity is freezing
        if (entity.isFreezing()) entity.setPosition(x, y, z);
    })
    builder.onAddedToWorld(entity => {
        // Teleport the entity slightly above its current position when added to the world
        let namespace = entity.getLevel().dimension.namespace
        let path = entity.getLevel().dimension.path
        entity.teleportTo(`${namespace}:${path}`, entity.x, entity.y + 1, entity.z, 1, 1)
    })
    builder.onBlockedByShield(context => {
        const { entity, target } = context
        // Log a message when the target is blocked by a shield
        console.log(`${target} Get blocked!`)
    })
    builder.onClientRemoval(entity => {
        // Log a message when the entity is removed on the client side
        console.log(`${entity} was removed on the client`)
    })
    builder.onDeath(context => {
        // Place a diamond ore block below the entity when it dies
        context.entity.block.down.set('minecraft:diamond_ore')
    })
    builder.onDecreaseAirSupply(entity => {
        if (entity.age % 20 != 0) return
        // Log the entity's remaining air supply when it decreases
    })
    builder.onEffectAdded(context => {
        // Log the description ID of an added effect
        console.log(context.effect.descriptionId)
    })
    builder.onEffectRemoved(context => {
        // Log the description ID of a removed effect
        console.log(context.effect.descriptionId)
    })
    builder.onEnterCombat(entity => {
        // Log a message when the entity enters combat
        console.log(`${entity} just entered combat`)
    })
    builder.onEquipItem(context => {
        // Log the ID of the item being equipped by the entity
        if (context.entity.age % 100 != 0) return
        console.log(context.currentStack.id)
    })
    builder.onFlap(entity => {
        // Place a gold ore block below the entity when it flaps
        entity.block.down.set('minecraft:gold_ore')
    })
    builder.onHurt(context => {
        // Log the amount of damage received by the entity
        console.log(context.damageAmount)
    })
    builder.onIncreaseAirSupply(entity => {
    })
    builder.onItemPickup(context => {
        // Log the ID of the item picked up by the entity
        console.log(context.itemEntity.id)
    })
    builder.onLeaveCombat(entity => {
        // Log a message when the entity leaves combat
        console.log(`${entity} just left combat!`)
    })
    builder.onLivingFall(context => {
        // Log a message when the entity falls
        console.log(`${context.entity} just fell ${context.distance} blocks!`)
    })
    builder.onLivingHeal(context => {
        // Log a message when the entity heals
        console.log(`${context.entity} just gained ${context.healAmount} health!`)
    })
    builder.onLivingJump(entity => {
        // Log a message when the entity jumps
        console.log(`${entity} just jumped!`)
    })
    builder.onRemovedFromWorld(entity => {
        // Log a message when the entity is removed from the world
        console.log(`${entity} was just removed from the world!`)
    })
    builder.onSpawnChildFromBreeding(context => {
        // Log a message when the entity breeds with another entity
        console.log(`${context.entity} mated with ${context.mate}! *blush*`)
    })
    builder.onSprint(entity => {
        // Log a message when the entity starts sprinting
        console.log(`${entity} is sprinting!`)
    })
    builder.onStartSleeping(context => {
        // Log a message when the entity starts sleeping at a specific position
        console.log(`Sleeping at ${context.blockPos}`)
    })
    builder.onStopRiding(entity => {
        // Drop a diamond above the entity when it stops riding
        if (!entity.isPassenger()) return
        entity.block.popItemFromFace('minecraft:diamond', 'up')
    })
    builder.onRemovePassenger(entity => {
        // Drop a diamond above the entity when the passenger dismounts it
        entity.block.popItemFromFace('minecraft:diamond', 'up')
    })
    builder.onStopSleeping(entity => {
        // Log a message when the entity stops sleeping
        console.log(`Stopped sleeping at ${entity.pos}`)
    })
    builder.onTargetChanged(context => {
        //Only firing every 100 ticks to reduce log spam.
        if (context.entity.age % 100 != 0) return
        // Log a message when the entity's target changes
        if (context.target == null) return
        console.log(`${context.target} is being targeted!`)
    })
    builder.playerTouch(context => {
        // Attack the player when touched by the entity
        context.player.attack(1)
    })
    builder.rideTick(entity => {
        // Log a message every 100 ticks if the entity is a vehicle
        if (entity.age % 100 != 0) return
        console.log(entity.isVehicle())
    })
    builder.thunderHit(context => {
        // Heal the entity when struck by lightning
        context.entity.heal(15)
    })
    builder.onTamed(ctx => {
        let entity = ctx.entity
        let player = ctx.player
        // Do stuff when the entity is tamed.
    })
    builder.tameOverride(context => {
        const { entity, player } = context
        // Mimic the vanilla way of setting the uuid when the entity is tamed.
        entity.setOwnerUUID(player.getUuid());
    })
    //Default vanilla implimentation of tickDeath removes the entity from the world after 20 ticks
    /*.tickDeath(entity => {
        // Override the tickDeath method in the entity
    })*/
    builder.onInteract(context => global.interact(context))
})

/**
 *
 * @param {Internal.ContextUtils$MobInteractContext} context
 * @returns
 */
global.interact = context => {
    if (context.player.isShiftKeyDown()) return
    context.player.startRiding(context.entity);
}

Exclusive Methods πŸ”’

Note: Some methods are exclusive to certain builders and are not shared across all of them. Below is a list of methods that are exclusive to different types of builders.


Methods Exclusive to Forge πŸ› οΈ

  • shouldStayCloseToLeashHolder
  • shouldRiderFaceForward
  • canTrample
  • biomeSpawn
  • spawnPlacement

Methods Exclusive to the Animal Builder 🐾

  • .setBreedOffspring
  • .isFood
  • .isFoodPredicate
  • .canBreed
  • .canMate
  • .spawnChildFromBreeding

Methods Exclusive to the Animal/Mob Builder (Not in LivingEntity Builder) πŸ•β€πŸ¦Ί

  • .removeWhenFarAway
  • .followLeashSpeed
  • .ambientSoundInterval
  • .myRidingOffset
  • .canJump
  • .walkTargetValue
  • .tickLeash
  • .shouldStayCloseToLeashHolder
  • .onTargetChanged
  • .canFireProjectileWeaponPredicate
  • .canFireProjectileWeapon
  • .ate
  • .setAmbientSound
  • .canHoldItem
  • .shouldDespawnInPeaceful
  • .isPersistenceRequired
  • .meleeAttackRangeSqr

Methods Exclusive to the TamableMob Builder πŸ•

  • .tamableFood
  • .tamableFoodPredicate

Clone this wiki locally