Base Entity Registry - liopyu/EntityJS GitHub Wiki

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, targetEntity } = context
        return targetEntity.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, targetEntity } = context
        return targetEntity.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
⚠️ **GitHub.com Fallback** ⚠️