-
Notifications
You must be signed in to change notification settings - Fork 3
Entity Modification Event
liopyu edited this page Aug 14, 2025
·
12 revisions
In this guide, we'll explore how to modify and override methods of Minecraft entities using EntityJS. It's important to understand the limitations and scopes of these modifications, particularly when dealing with entities that have overridden methods in their subclasses. |
Minecraft entities have various methods controlling their behavior, sounds, and interactions. Many of these can be overridden using the `EntityJSEvents.modifyEntity` event, but in some cases, subclass implementations may prevent certain methods from being modified. |
Example: | You can generally modify the `.setHurtSound()` method for most entities, but for entities like zombies, you cannot override the `getHurtSound()` method because it is already overridden in their subclass. |
//Startup Event
EntityJSEvents.modifyEntity(event => {
event.modify("minecraft:zombie", modifyBuilder => {
// Since zombies extend the PathfinderMob class, a ModifyPathfinderMobBuilder will be provided
modifyBuilder.onRemovedFromWorld(entity => {
// Code to execute when the zombie is removed from the world
})
// Example on how to write synced entity data
modifyBuilder.defineSyncedData(entity => {
entity.addSyncedData("string", "NbtTagName", "StartValue")
})
});
});
This example demonstrates how to modify the behavior of a Minecraft zombie using the `EntityJSEvents.modifyEntity` event. In this case, a custom action is triggered when the zombie is removed from the world. |
- You can modify most entity methods using `EntityJSEvents.modifyEntity`, but some methods in subclasses, like `getHurtSound()` in zombies, cannot be overridden. - Focus on modifying methods that are not already overridden in the subclass for entities like zombies. |
Full Code Example 1.19-1.20
EntityJSEvents.modifyEntity(event => {
event.modify("minecraft:zombie", modifyBuilder => {
modifyBuilder
/**
* Entity Overrides for entities that are non-living
*/
.controlledByFirstPassenger(true)
.myRidingOffset(entity => 5)
.canCollideWith(context => true)
.isFreezing(entity => true)
.setBlockJumpFactor(entity => 10)
.isPushable(false)
.positionRider(context => {
const { entity, passenger, moveFunction } = context
})
.canAddPassenger(context => true)
.setSwimSound("minecraft:entity.generic.swim")
.setSwimSplashSound("minecraft:entity.generic.splash")
.blockSpeedFactor(entity => 1)
.isFlapping(entity => false)
.onAddedToWorld(entity => {})
.repositionEntityAfterLoad(true)
.onSprint(entity => {})
.onStopRiding(entity => {})
.rideTick(entity => {})
.canFreeze(entity => true)
.isCurrentlyGlowing(entity => true)
.setMaxFallDistance(entity => 3)
.onClientRemoval(entity => {})
.lavaHurt(entity => {})
.onFlap(entity => {})
.dampensVibrations(entity => {})
.showVehicleHealth(entity => true)
.thunderHit(context => {})
.isInvulnerableTo(context => false)
.canChangeDimensions(entity => false)
.mayInteract(context => false)
.canTrample(context => false)
.onRemovedFromWorld(entity => {})
.onFall(context => {})
.lerpTo(context => {})
.shouldRenderAtSqrDistance(context => true)
.isAttackable(true)
.playerTouch(context => {})
.move(context => {})
.tick(entity => {})
.onInteract(context => {
if (context.player.isShiftKeyDown()) return;
context.player.startRiding(context.entity);
})
/**
* LivingEntity Overrides available for living entities
*/
.setWaterSlowDown(0.6)
.setSoundVolume(0.5)
.shouldDropLoot(entity => false)
.aiStep(entity => {})
.isAffectedByFluids(entity => false)
.isImmobile(entity => false)
.isAlwaysExperienceDropper(true)
.calculateFallDamage(context => 1)
.setDeathSound("minecraft:entity.generic.death")
.doAutoAttackOnTouch(context => {})
.setStandingEyeHeight(context => 1)
.onDecreaseAirSupply(entity => {})
.onBlockedByShield(context => {})
.nextStep(entity => 1)
.onIncreaseAirSupply(entity => {})
.setHurtSound(context => {
const { entity, damageSource } = context;
switch (damageSource.getType()) {
case "fire":
return "minecraft:entity.generic.explode";
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";
}
})
.canAttackType(context => false)
.scale(entity => 1)
.shouldDropExperience(entity => false)
.experienceReward(killedEntity => 10)
.onEquipItem(context => {})
.visibilityPercent(context => 1)
.canAttack(context => false)
.canBeAffected(context => false)
.invertedHealAndHarm(entity => true)
.onEffectAdded(context => {})
.onLivingHeal(context => {})
.onEffectRemoved(context => {})
.onHurt(context => {})
.onDeath(context => {})
.dropCustomDeathLoot(context => {})
.fallSounds("minecraft:entity.generic.small_fall", "minecraft:entity.generic.large_fall")
.eatingSound("minecraft:entity.zombie.ambient")
.onClimbable(entity => false)
.canBreatheUnderwater(true)
.onLivingFall(context => {})
.jumpBoostPower(entity => 1)
.canStandOnFluid(context => true)
.isSensitiveToWater(entity => true)
.onItemPickup(context => {})
.hasLineOfSight(context => false)
.onEnterCombat(entity => {})
.onLeaveCombat(entity => {})
.isAffectedByPotions(entity => false)
.isAttackableFunction(entity => true)
.canTakeItem(context => true)
.isSleeping(entity => false)
.onStartSleeping(context => {})
.onStopSleeping(entity => {})
.eat(context => {})
.shouldRiderFaceForward(context => true)
.canDisableShield(entity => true)
.isPickable(entity => {
return true;
})
.lerpTo(context => {
const { x, y, z, yaw, pitch, posRotationIncrements, teleport, entity } = context;
entity.setPositionAndRotation(x, y, z, yaw, pitch);
})
.isAlliedTo(context => {
const { entity, target } = context;
return target.type == 'minecraft:blaze';
})
.onHurtTarget(context => {
const { entity, targetEntity } = context;
//Execute code when the target is hurt
})
.tickDeath(entity => {})
.travel(context => {
const { entity, vec3 } = context;
// Use the vec3 and entity to determine the travel logic of the entity
})
.mobType('undead')
.positionRider(context => {
const { entity, passenger, moveFunction } = context;
})
/**
* Mob Overrides for entities extending from Mob class
*/
.mobInteract(context => {
if (context.player.isShiftKeyDown()) return;
context.player.startRiding(context.entity);
})
.createNavigation(context => {
const { entity, level } = context;
return EntityJSUtils.createWallClimberNavigation(entity, level);
})
.canBeLeashed(context => true)
.removeWhenFarAway(context => {})
.ambientSoundInterval(100)
.onTargetChanged(context => {})
.ate(entity => {})
.setAmbientSound("minecraft:entity.zombie.ambient")
.canHoldItem(context => true)
.shouldDespawnInPeaceful(true)
.canPickUpLoot(entity => true)
.isPersistenceRequired(true)
.meleeAttackRangeSqr(entity => 2)
.tickLeash(context => {})
/**
* PathfinderMob Overrides for mobs extending the PathfinderMob class
*/
.shouldStayCloseToLeashHolder(entity => true)
.followLeashSpeed(1.5)
.walkTargetValue(context => 10);
})
});
Full Code Example 1.21
EntityJSEvents.modifyEntity(event => {
event.modify("minecraft:zombie", modifyBuilder => {
modifyBuilder
/**
* Entity Overrides for entities that are non-living
*/
.controlledByFirstPassenger(true)
.canCollideWith(context => true)
.isFreezing(entity => true)
.setBlockJumpFactor(entity => 10)
.isPushable(false)
.positionRider(context => {
const { entity, passenger, moveFunction } = context
})
.canAddPassenger(context => true)
.setSwimSound("minecraft:entity.generic.swim")
.setSwimSplashSound("minecraft:entity.generic.splash")
.blockSpeedFactor(entity => 1)
.isFlapping(entity => false)
.onAddedToWorld(entity => { })
.repositionEntityAfterLoad(true)
.onSprint(entity => { })
.onStopRiding(entity => { })
.rideTick(entity => { })
.canFreeze(entity => true)
.isCurrentlyGlowing(entity => true)
.setMaxFallDistance(entity => 3)
.onClientRemoval(entity => { })
.lavaHurt(entity => { })
.onFlap(entity => { })
.dampensVibrations(entity => { })
.showVehicleHealth(entity => true)
.thunderHit(context => { })
.isInvulnerableTo(context => false)
.canChangeDimensions(ctx => false)
.mayInteract(context => false)
.canTrample(context => false)
.onRemovedFromWorld(entity => { })
.onFall(context => { })
.lerpTo(context => { })
.shouldRenderAtSqrDistance(context => true)
.isAttackable(true)
.playerTouch(context => { })
.move(context => { })
.tick(entity => { })
.onInteract(context => {
if (context.player.isShiftKeyDown()) return;
context.player.startRiding(context.entity);
})
/**
* LivingEntity Overrides available for living entities
*/
.setWaterSlowDown(0.6)
.setSoundVolume(0.5)
.shouldDropLoot(entity => false)
.aiStep(entity => { })
.isAffectedByFluids(entity => false)
.isImmobile(entity => false)
.isAlwaysExperienceDropper(true)
.calculateFallDamage(context => 1)
.setDeathSound("minecraft:entity.generic.death")
.doAutoAttackOnTouch(context => { })
.onDecreaseAirSupply(entity => { })
.onBlockedByShield(context => { })
.nextStep(entity => 1)
.onIncreaseAirSupply(entity => { })
.setHurtSound(context => {
const { entity, damageSource } = context;
switch (damageSource.getType()) {
case "fire":
return "minecraft:entity.generic.explode";
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";
}
})
.canAttackType(context => false)
.scale(entity => 1)
.shouldDropExperience(entity => false)
.experienceReward(killedEntity => 10)
.onEquipItem(context => { })
.visibilityPercent(context => 1)
.canAttack(context => false)
.canBeAffected(context => false)
.invertedHealAndHarm(entity => true)
.onEffectAdded(context => { })
.onLivingHeal(context => { })
.onEffectRemoved(context => { })
.onHurt(context => { })
.onDeath(context => { })
.dropCustomDeathLoot(context => { })
.fallSounds("minecraft:entity.generic.small_fall", "minecraft:entity.generic.large_fall")
.eatingSound("minecraft:entity.zombie.ambient")
.onClimbable(entity => false)
.canBreatheUnderwater(true)
.onLivingFall(context => { })
.jumpBoostPower(entity => 1)
.canStandOnFluid(context => true)
.isSensitiveToWater(entity => true)
.onItemPickup(context => { })
.hasLineOfSight(context => false)
.onEnterCombat(entity => { })
.onLeaveCombat(entity => { })
.isAffectedByPotions(entity => false)
.isAttackableFunction(entity => true)
.canTakeItem(context => true)
.isSleeping(entity => false)
.onStartSleeping(context => { })
.onStopSleeping(entity => { })
.eat(context => { })
.shouldRiderFaceForward(context => true)
.canDisableShield(entity => true)
.isPickable(entity => {
return true;
})
.lerpTo(context => {
const { x, y, z, yaw, pitch, posRotationIncrements, teleport, entity } = context;
entity.setPositionAndRotation(x, y, z, yaw, pitch);
})
.isAlliedTo(context => {
const { entity, target } = context;
return target.type == 'minecraft:blaze';
})
.onHurtTarget(context => {
const { entity, targetEntity } = context;
//Execute code when the target is hurt
})
.tickDeath(entity => { })
.travel(context => {
const { entity, vec3 } = context;
// Use the vec3 and entity to determine the travel logic of the entity
})
.positionRider(context => {
const { entity, passenger, moveFunction } = context;
})
/**
* Mob Overrides for entities extending from Mob class
*/
.mobInteract(context => {
if (context.player.isShiftKeyDown()) return;
context.player.startRiding(context.entity);
})
.createNavigation(context => {
const { entity, level } = context;
return EntityJSUtils.createWallClimberNavigation(entity, level);
})
.canBeLeashed(context => true)
.removeWhenFarAway(context => { })
.ambientSoundInterval(100)
.onTargetChanged(context => { })
.ate(entity => { })
.setAmbientSound("minecraft:entity.zombie.ambient")
.canHoldItem(context => true)
.shouldDespawnInPeaceful(true)
.canPickUpLoot(entity => true)
.isPersistenceRequired(true)
.meleeAttackRangeSqr(entity => 2)
/**
* PathfinderMob Overrides for mobs extending the PathfinderMob class
*/
.shouldStayCloseToLeashHolder(entity => true)
.followLeashSpeed(1.5)
.walkTargetValue(context => 10);
})
});
The type of builder provided during entity modification depends on the subtype of the entity being modified. This is determined at runtime by the `modifyEntity` method, which checks the entity's type and provides the appropriate builder. |
ModifyPathfinderMobBuilder | Used for entities that extend PathfinderMob . |
ModifyMobBuilder | Used for entities that extend Mob . |
ModifyLivingEntityBuilder | Used for entities that extend LivingEntity . |
ModifyEntityBuilder | Used for entities that extend Entity . |
Each builder includes methods specific to the features and behaviors of the entity type it supports, ensuring effective and appropriate modifications. |
- `onInteract` - `controlledByFirstPassenger` - `myRidingOffset` - `isPickable` - `canCollideWith` - `isFreezing` - `setBlockJumpFactor` - `isPushable` - `positionRider` - `canAddPassenger` - `setSwimSound` - `setSwimSplashSound` - `blockSpeedFactor` - `isFlapping` - `onAddedToWorld` - `repositionEntityAfterLoad` - `onSprint` - `onStopRiding` - `rideTick` - `canFreeze` - `isCurrentlyGlowing` - `setMaxFallDistance` - `onClientRemoval` - `lavaHurt` - `onFlap` - `dampensVibrations` - `showVehicleHealth` - `thunderHit` - `isInvulnerableTo` - `canChangeDimensions` - `mayInteract` - `canTrample` - `onRemovedFromWorld` - `onFall` - `lerpTo` - `shouldRenderAtSqrDistance` - `isAttackable` - `playerTouch` - `move` - `tick` |
- `setWaterSlowDown` - `setSoundVolume` - `shouldDropLoot` - `aiStep` - `isPushable` - `isAffectedByFluids` - `isImmobile` - `isAlwaysExperienceDropper` - `calculateFallDamage` - `setDeathSound` - `doAutoAttackOnTouch` - `setStandingEyeHeight` - `onDecreaseAirSupply` - `onBlockedByShield` - `repositionEntityAfterLoad` - `nextStep` - `onIncreaseAirSupply` - `setHurtSound` - `canAttackType` - `scale` - `shouldDropExperience` - `experienceReward` - `onEquipItem` - `visibilityPercent` - `canAttack` - `canBeAffected` - `invertedHealAndHarm` - `onEffectAdded` - `onLivingHeal` - `onEffectRemoved` - `onHurt` - `onDeath` - `dropCustomDeathLoot` - `fallSounds` - `eatingSound` - `onClimbable` - `canBreatheUnderwater` - `onLivingFall` - `jumpBoostPower` - `canStandOnFluid` - `isSensitiveToWater` - `onItemPickup` - `hasLineOfSight` - `onEnterCombat` - `onLeaveCombat` - `isAffectedByPotions` - `isAttackableFunction` - `canTakeItem` - `isSleeping` - `onStartSleeping` - `onStopSleeping` - `eat` - `shouldRiderFaceForward` |
- `canDisableShield` - `mobInteract` - `lerpTo` - `isAlliedTo` - `onHurtTarget` - `tickDeath` - `travel` - `mobType` - `positionRider` - `createNavigation` - `canBeLeashed` - `removeWhenFarAway` - `ambientSoundInterval` - `onTargetChanged` - `ate` - `setAmbientSound` - `canHoldItem` - `shouldDespawnInPeaceful` - `canPickUpLoot` - `isPersistenceRequired` - `meleeAttackRangeSqr` - `tickLeash` |
- `shouldStayCloseToLeashHolder` - `followLeashSpeed` - `walkTargetValue` |
- `shouldStayCloseToLeashHolder` - `shouldRiderFaceForward` - `canTrample` |