import math
from typing import Any

from anvil.api.blocks.components import LootTable
from anvil.api.core.components import _BaseAIGoal, _BaseComponent, _BaseEventTrigger
from anvil.api.core.enums import (
    BreedingMutationStrategy,
    ContainerType,
    ControlFlags,
    DamageCause,
    DamageSensor,
    ExplosionParticleEffect,
    FilterSubject,
    LeashSpringType,
    LineOfSightObstructionType,
    LookAtLocation,
    LootedAtSetTarget,
    RideableDismountMode,
    Slots,
    Vibrations,
)
from anvil.api.core.filters import Filter
from anvil.api.core.types import *
from anvil.api.logic.molang import Molang, Query
from anvil.api.vanilla.blocks import MinecraftBlockTypes
from anvil.api.vanilla.effects import MinecraftEffects
from anvil.api.world.trade_tables import TradeTable
from anvil.lib.config import CONFIG
from anvil.lib.format_versions import ENTITY_SERVER_VERSION
from anvil.lib.lib import clamp
from anvil.lib.schemas import MinecraftBlockDescriptor, MinecraftEntityDescriptor, MinecraftItemDescriptor
from anvil.lib.translator import AnvilTranslator

# Components ==========================================================================
# Attributes ==========================================================================


class EntityAddRider(_BaseComponent):
    _identifier = "minecraft:addrider"

    def __init__(
        self,
        entity_type: MinecraftEntityDescriptor | Identifier,
        spawn_event: Event = None,
    ) -> None:
        """Adds a rider to the entity. Requires `minecraft:rideable.`.

        Parameters:
            entity_type (MinecraftEntityDescriptor | Identifier): The type of entity to add as a rider.
            spawn_event (Event, optional): An event to run when the rider is spawned. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_addrider
        """
        super().__init__("addrider")
        # self._require_components(EntityRideable)
        self._add_field("riders", [{"entity_type": entity_type, "spawn_event": spawn_event}])

    def add_rider(
        self,
        entity_type: MinecraftEntityDescriptor | Identifier,
        spawn_event: Event = None,
    ):
        """Adds an additional rider to the entity. Requires `minecraft:rideable.`.

        Parameters:
        `entity_type` : `MinecraftEntityDescriptor` | `Identifier`.
            The type of entity to add as a rider.
        `spawn_event` : `Event`, optional.
            An event to run when the rider is spawned.

        """
        self._component["riders"].append({"entity_type": entity_type, "spawn_event": spawn_event})
        return self


class EntityAdmireItem(_BaseComponent):
    _identifier = "minecraft:admire_item"

    def __init__(self, cooldown_after_being_attacked: Seconds, duration: Seconds = 10) -> None:
        """Causes the mob to ignore attackable targets for a given duration.

        Parameters:
            cooldown_after_being_attacked (Seconds): Duration, in seconds, for which mob won't admire items if it was hurt.
            duration (Seconds, optional): Duration, in seconds, that the mob is pacified. `Default: 10`. Defaults to 10.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_admire_item
        """
        super().__init__("admire_item")
        self._add_field("cooldown_after_being_attacked", cooldown_after_being_attacked)
        if not duration == 10:
            self._add_field("duration", duration)


class EntityCollisionBox(_BaseComponent):
    _identifier = "minecraft:collision_box"

    def __init__(self, height: float, width: float) -> None:
        """Sets the width and height of the Entity's collision box.

        Parameters:
            height (float): Description.
            width (float): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_collision_box
        """
        super().__init__("collision_box")
        self._add_field("height", max(0, height))
        self._add_field("width", max(0, width))


class EntityTypeFamily(_BaseComponent):
    _identifier = "minecraft:type_family"

    def __init__(self, family: list[str]) -> None:
        """Defines the families this entity belongs to.

        Parameters:
            family (list[str]): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_type_family
        """
        super().__init__("type_family")
        self._add_field("family", family)


class EntityInstantDespawn(_BaseComponent):
    _identifier = "minecraft:instant_despawn"

    def __init__(self, remove_child_entities: bool = False) -> None:
        """Despawns the Actor immediately.

        Parameters:
            remove_child_entities (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_instant_despawn
        """
        super().__init__("instant_despawn")
        if remove_child_entities:
            self._add_field("remove_child_entities", True)


class EntityHealth(_BaseComponent):
    _identifier = "minecraft:health"

    def __init__(self, value: int, min: int = None, max: int = None) -> None:
        """Sets the amount of health this mob has.

        Parameters:
            value (int): Description.
            min (int, optional): Description. Defaults to None.
            max (int, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_health
        """
        super().__init__("health")
        self._add_field("value", value)
        if not max is None:
            self._add_field("max", max)
        if not min is None:
            self._add_field("min", min)


class EntityPhysics(_BaseComponent):
    _identifier = "minecraft:physics"

    def __init__(
        self,
        has_collision: bool = True,
        has_gravity: bool = True,
        push_towards_closest_space: bool = False,
    ) -> None:
        """Defines physics properties of an actor, including if it is affected by gravity or if it collides with objects.

        Parameters:
            has_collision (bool, optional): Description. Defaults to True.
            has_gravity (bool, optional): Description. Defaults to True.
            push_towards_closest_space (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_physics
        """
        super().__init__("physics")
        if not has_collision:
            self._add_field("has_collision", has_collision)
        if not has_gravity:
            self._add_field("has_gravity", has_gravity)
        if push_towards_closest_space:
            self._add_field("push_towards_closest_space", push_towards_closest_space)


class EntityKnockbackResistance(_BaseComponent):
    _identifier = "minecraft:knockback_resistance"

    def __init__(self, value: float) -> None:
        """Determines the amount of knockback resistance that the item has.

        Parameters:
            value (float): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_knockback_resistance
        """
        super().__init__("knockback_resistance")
        self._add_field("value", max(0, min(1, value)))


class EntityPushableByBlock(_BaseComponent):
    _identifier = "minecraft:pushable_by_block"

    def __init__(self, value: bool) -> None:
        """Defines what can push an entity between other entities and pistons.

        Parameters:
            value (bool): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_pushable_by_block
        """
        super().__init__("pushable_by_block")
        self._set_value(value)


class EntityPushableByEntity(_BaseComponent):
    _identifier = "minecraft:pushable_by_entity"

    def __init__(self, value: bool) -> None:
        """Defines whether this entity can be pushed by other entities.

        Parameters:
            value (bool): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_pushable_by_entity
        """
        super().__init__("pushable_by_entity")
        self._set_value(value)


class EntityPushThrough(_BaseComponent):
    _identifier = "minecraft:push_through"

    def __init__(self, value: float) -> None:
        """Sets the distance through which the entity can push through.

        Parameters:
            value (float): The distance in blocks that the entity can push through. It can be thought of as a "buffer zone" that the entity creates around itself to navigate through crowded spaces. The default value is 0.0, which means the entity follows the standard collision rules of the game and cannot move through solid entities or blocks. Positive values increase the entity's ability to move through crowds, while negative values are rounded to 0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_push_through
        """
        super().__init__("push_through")
        self._add_field("value", value)


class EntityMovement(_BaseComponent):
    _identifier = "minecraft:movement"

    def __init__(self, value: int, max: int = None) -> None:
        """Defined the movement speed of the entity in block/tick.

        Parameters:
            value (int): Description.
            max (int, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_movement
        """
        super().__init__("movement")
        self._add_field("value", value)
        if not max is None:
            self._add_field("max", max)


class EntityTickWorld(_BaseComponent):
    _identifier = "minecraft:tick_world"

    def __init__(
        self,
        never_despawn: bool = True,
        radius: int = 0,
        distance_to_players: int = 0,
    ) -> None:
        """Defines if the entity ticks the world and the radius around it to tick.

        Parameters:
            never_despawn (bool, optional): Description. Defaults to True.
            radius (int, optional): Description. Defaults to 0.
            distance_to_players (int, optional): Description. Defaults to 0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_tick_world
        """
        super().__init__("tick_world")
        self._add_field("never_despawn", never_despawn)
        if radius != 0:
            self._add_field("radius", clamp(radius, 2, 6))
        if distance_to_players != 0:
            self._add_field("distance_to_players", distance_to_players)


class EntityCustomHitTest(_BaseComponent):
    _identifier = "minecraft:custom_hit_test"

    def __init__(self, height: float, width: float, pivot: list[float, float, float] = [0, 1, 0]) -> None:
        """List of hitboxes for melee and ranged hits against the entity.

        Parameters:
            height (float): Description.
            width (float): Description.
            pivot (list[float, float, float], optional): Description. Defaults to [0, 1, 0].

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_custom_hit_test
        """
        super().__init__("custom_hit_test")
        self._add_field("hitboxes", [{"width": width, "height": height, "pivot": pivot}])

    def add_hitbox(self, height: float, width: float, pivot: list[float, float, float] = [0, 1, 0]):
        self._component["hitboxes"].append({"width": width, "height": height, "pivot": pivot})
        return self


class EntityCanClimb(_BaseComponent):
    _identifier = "minecraft:can_climb"

    def __init__(self) -> None:
        """Allows this entity to climb up ladders.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_can_climb
        """
        super().__init__("can_climb")


class EntityAttack(_BaseComponent):
    _identifier = "minecraft:attack"

    def __init__(self, damage: int, effect_duration: int = None, effect_name: str = None) -> None:
        """Defines an entity's melee attack and any additional effects on it.

        Parameters:
            damage (int): Description.
            effect_duration (int, optional): Description. Defaults to None.
            effect_name (str, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_attack
        """
        super().__init__("attack")
        self._add_field("damage", damage)
        if not effect_duration is None:
            self._add_field("effect_duration", effect_duration)
        if not effect_name is None:
            self._add_field("effect_name", effect_name)


class EntityJumpStatic(_BaseComponent):
    _identifier = "minecraft:jump.static"

    def __init__(self, jump_power: float = 0.42) -> None:
        """Gives the entity the ability to jump.

        Parameters:
            jump_power (float, optional): Description. Defaults to 0.42.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_jump_static
        """
        super().__init__("jump.static")
        self._add_field("jump_power", jump_power)


class EntityJumpDynamic(_BaseComponent):
    _identifier = "minecraft:jump.dynamic"

    def __init__(self) -> None:
        """Defines a dynamic type jump control that will change jump properties based on the speed modifier of the mob. Requires minecraft:movement.skip to be used.

        ## Documentation reference:
            https://learn.microsoft.com/pt-br/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_jump.dynamic
        """
        super().__init__("jump.dynamic")

    def regular_skip_data(self, animation_duration: float, distance_scale: float, height: float, jump_delay: float):
        """Sets the regular skip data for the entity's jump.

        Args:
            animation_duration (float): Duration of the jump animation.
            distance_scale (float): The multiplier applied to horizontal velocity when jumping.
            height (float): The force applied vertically when jumping.
            jump_delay (float): Amount of ticks between sequential jumps.
        """
        self._add_field(
            "regular_skip_data",
            {
                "animation_duration": animation_duration,
                "distance_scale": distance_scale,
                "height": height,
                "jump_delay": jump_delay,
            },
        )
        return self

    def fast_skip_data(self, animation_duration: float, distance_scale: float, height: float, jump_delay: float):
        """Sets the fast skip data for the entity's jump.

        Args:
            animation_duration (float): Duration of the jump animation.
            distance_scale (float): The multiplier applied to horizontal velocity when jumping.
            height (float): The force applied vertically when jumping.
            jump_delay (float): Amount of ticks between sequential jumps.
        """
        self._add_field(
            "fast_skip_data",
            {
                "animation_duration": animation_duration,
                "distance_scale": distance_scale,
                "height": height,
                "jump_delay": jump_delay,
            },
        )
        return self


class EntityHorseJumpStrength(_BaseComponent):
    _identifier = "minecraft:horse.jump_strength"

    def __init__(self, range_min: float, range_max: float) -> None:
        """Allows this mob to jump higher when being ridden by a player.

        Parameters:
            range_min (float): Description.
            range_max (float): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_horse_jump_strength
        """
        super().__init__("horse.jump_strength")
        self._add_field("value", {"range_min": range_min, "range_max": range_max})


class EntitySpellEffects(_BaseComponent):
    _identifier = "minecraft:spell_effects"

    def __init__(self) -> None:
        """Defines what mob effects to add and remove to the entity when adding this component.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_spell_effects
        """
        super().__init__("spell_effects")
        self._add_field("add_effects", [])
        self._add_field("remove_effects", [])

    def add_effects(
        self,
        effect: MinecraftEffects,
        duration: int | Literal["infinite"],
        amplifier: int,
        ambient: bool = True,
        visible: bool = True,
        display_on_screen_animation: bool = True,
    ):
        effect = {
            "effect": effect,
            "duration": duration,
            "amplifier": amplifier,
        }
        if ambient is not True:
            effect.update({"ambient": ambient})
        if visible is not True:
            effect.update({"visible": visible})
        if display_on_screen_animation is not True:
            effect.update({"display_on_screen_animation": display_on_screen_animation})

        self._component["add_effects"].append(effect)
        return self

    def remove_effects(self, *effects: MinecraftEffects):
        self._component["remove_effects"] = [e.value for e in effects]
        return self


class EntityFrictionModifier(_BaseComponent):
    _identifier = "minecraft:friction_modifier"

    def __init__(self, value: int) -> None:
        """Defines how much friction affects this entity.

        Parameters:
            value (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_friction_modifier
        """
        super().__init__("friction_modifier")
        self._add_field("value", value)


class EntityVariant(_BaseComponent):
    _identifier = "minecraft:variant"

    def __init__(self, value: int) -> None:
        """Used to differentiate the component group of a variant of an entity from others. (e.g. ocelot, villager).

        Parameters:
            value (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_variant
        """
        super().__init__("variant")
        self._add_field("value", value)


class EntityMarkVariant(_BaseComponent):
    _identifier = "minecraft:mark_variant"

    def __init__(self, value: int) -> None:
        """Additional variant value. Can be used to further differentiate variants.

        Parameters:
            value (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_mark_variant
        """
        super().__init__("mark_variant")
        self._add_field("value", value)


class EntitySkinID(_BaseComponent):
    _identifier = "minecraft:skin_id"

    def __init__(self, value: int) -> None:
        """Skin ID value. Can be used to differentiate skins, such as base skins for villagers.

        Parameters:
            value (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_skin_id
        """
        super().__init__("skin_id")
        self._add_field("value", value)


class EntityScale(_BaseComponent):
    _identifier = "minecraft:scale"

    def __init__(self, value: int) -> None:
        """Sets the entity's visual size.

        Parameters:
            value (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_scale
        """
        super().__init__("scale")
        self._add_field("value", value)


class EntityScaleByAge(_BaseComponent):
    _identifier = "minecraft:scale_by_age"

    def __init__(self, start_scale: int, end_scale: int) -> None:
        """Defines the entity's size interpolation based on the entity's age.

        Parameters:
            start_scale (int): Description.
            end_scale (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_scale_by_age
        """
        super().__init__("scale_by_age")
        self._add_field("end_scale", end_scale)
        self._add_field("start_scale", start_scale)


class EntityAreaAttack(_BaseComponent):
    _identifier = "minecraft:area_attack"

    def __init__(self, cause: DamageCause, damage_per_tick: int = 2, damage_range: float = 0.2) -> None:
        """Is a component that does damage to entities that get within range.

        Parameters:
            cause (DamageCause): Description.
            damage_per_tick (int, optional): Description. Defaults to 2.
            damage_range (float, optional): Description. Defaults to 0.2.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_area_attack
        """
        super().__init__("area_attack")

        self._add_field("cause", cause.value)

        if not damage_per_tick == 2:
            self._add_field("damage_per_tick", damage_per_tick)
        if not damage_range == 0.2:
            self._add_field("damage_range", damage_range)

    def filter(self, entity_filter: dict):
        self._add_field("entity_filter", entity_filter)
        return self


class EntityIsStackable(_BaseComponent):
    _identifier = "minecraft:is_stackable"

    def __init__(self) -> None:
        """Sets that this entity can be stacked.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_stackable
        """
        super().__init__("is_stackable")


class EntityIsIllagerCaptain(_BaseComponent):
    _identifier = "minecraft:is_illager_captain"

    def __init__(self) -> None:
        """Sets that this entity is an illager captain.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_illager_captain
        """
        super().__init__("is_illager_captain")


class EntityIsBaby(_BaseComponent):
    _identifier = "minecraft:is_baby"

    def __init__(self) -> None:
        """Sets that this entity is a baby.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_baby
        """
        super().__init__("is_baby")


class EntityIsIgnited(_BaseComponent):
    _identifier = "minecraft:is_ignited"

    def __init__(self) -> None:
        """Sets that this entity is currently on fire.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_ignited
        """
        super().__init__("is_ignited")


class EntityIsTamed(_BaseComponent):
    _identifier = "minecraft:is_tamed"

    def __init__(self) -> None:
        """Sets that this entity is currently tamed.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_tamed
        """
        super().__init__("is_tamed")


class EntityIsCharged(_BaseComponent):
    _identifier = "minecraft:is_charged"

    def __init__(self) -> None:
        """Sets that this entity is charged.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_charged
        """
        super().__init__("is_charged")


class EntityIsStunned(_BaseComponent):
    _identifier = "minecraft:is_stunned"

    def __init__(self) -> None:
        """Sets that this entity is currently stunned.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_stunned
        """
        super().__init__("is_stunned")


class EntityIsSaddled(_BaseComponent):
    _identifier = "minecraft:is_saddled"

    def __init__(self) -> None:
        """Sets that this entity is currently saddled.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_saddled
        """
        super().__init__("is_saddled")


class EntityIsSheared(_BaseComponent):
    _identifier = "minecraft:is_sheared"

    def __init__(self) -> None:
        """Sets that this entity is currently sheared.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_sheared
        """
        super().__init__("is_sheared")


class EntityCanFly(_BaseComponent):
    _identifier = "minecraft:can_fly"

    def __init__(self) -> None:
        """Marks the entity as being able to fly, the pathfinder won't be restricted to paths where a solid block is required underneath it.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_can_fly
        """
        super().__init__("can_fly")


class EntityCanPowerJump(_BaseComponent):
    _identifier = "minecraft:can_power_jump"

    def __init__(self) -> None:
        """Allows the entity to power jump like the horse does in vanilla.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_can_power_jump
        """
        super().__init__("can_power_jump")


class EntityIsChested(_BaseComponent):
    _identifier = "minecraft:is_chested"

    def __init__(self) -> None:
        """Sets that this entity is currently carrying a chest.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_chested
        """
        super().__init__("is_chested")


class EntityOutOfControl(_BaseComponent):
    _identifier = "minecraft:out_of_control"

    def __init__(self) -> None:
        """Defines the entity's 'out of control' state.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_out_of_control
        """
        super().__init__("out_of_control")


class EntityDamageSensor(_BaseComponent):
    _identifier = "minecraft:damage_sensor"

    def __init__(self) -> None:
        """Defines what events to call when this entity is damaged by specific entities or items.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_damage_sensor
        """
        super().__init__("damage_sensor")
        self._add_field("triggers", [])

    def add_trigger(
        self,
        cause: DamageCause,
        deals_damage: DamageSensor | bool = DamageSensor.Yes,
        on_damage_event: str = None,
        on_damage_filter: Filter = None,
        damage_multiplier: int = 1,
        damage_modifier: float = 0,
    ):
        if isinstance(deals_damage, bool):
            deals_damage = DamageSensor.Yes if deals_damage else DamageSensor.No

        damage = {"deals_damage": deals_damage, "on_damage": {}}
        if not cause is DamageCause.All:
            damage["cause"] = cause.value
        if not on_damage_event is None:
            damage["on_damage"] = {"event": on_damage_event}
        if not on_damage_filter is None:
            damage["on_damage"]["filters"] = on_damage_filter
        if not damage_multiplier == 1:
            damage["damage_multiplier"] = damage_multiplier
        if not damage_modifier == 0:
            damage["damage_modifier"] = damage_modifier

        self._get_field("triggers", []).append(damage)
        return self


class EntityFollowRange(_BaseComponent):
    _identifier = "minecraft:follow_range"

    def __init__(self, value: int, max_range: int = None) -> None:
        """Defines the range of blocks that a mob will pursue a target.

        Parameters:
            value (int): Description.
            max_range (int, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_follow_range
        """
        super().__init__("follow_range")
        self._add_field("value", value)
        if not max_range is None:
            self._add_field("max", max_range)


class EntityMovementType:
    @staticmethod
    def Basic(max_turn: float = 30):
        movement = _BaseComponent("movement.basic")
        if not max_turn == 30:
            movement._add_field("max_turn", max_turn)
        return movement

    @staticmethod
    def Amphibious(max_turn: float = 30):
        """Allows the mob to swim in water and walk on land."""
        movement = _BaseComponent("movement.amphibious")
        if not max_turn == 30:
            movement._add_field("max_turn", max_turn)
        return movement

    @staticmethod
    def Dolphin() -> None:
        """Allows the mob to swim in water like a dolphin."""
        movement = _BaseComponent("movement.dolphin")
        return movement

    @staticmethod
    def Fly(
        max_turn: float = 30,
        start_speed: float = 0.1,
        speed_when_turning: float = 0.2,
    ) -> None:
        """Causes the mob to fly."""
        movement = _BaseComponent("movement.fly")
        if not max_turn == 30:
            movement._add_field("max_turn", max_turn)
        if not start_speed == 0.1:
            movement._add_field("start_speed", start_speed)
        if not speed_when_turning == 0.2:
            movement._add_field("speed_when_turning", speed_when_turning)
        return movement

    @staticmethod
    def Generic(max_turn: float = 30):
        """Allows a mob to fly, swim, climb, etc."""
        movement = _BaseComponent("movement.generic")
        if not max_turn == 30:
            movement._add_field("max_turn", max_turn)
        return movement

    @staticmethod
    def Glide(
        max_turn: float = 30,
        start_speed: float = 0.1,
        speed_when_turning: float = 0.2,
    ):
        """Is the move control for a flying mob that has a gliding movement."""
        movement = _BaseComponent("movement.glide")
        if not max_turn == 30:
            movement._add_field("max_turn", max_turn)
        if not start_speed == 0.1:
            movement._add_field("start_speed", start_speed)
        if not speed_when_turning == 0.2:
            movement._add_field("speed_when_turning", speed_when_turning)
        return movement

    @staticmethod
    def Jump(max_turn: float = 30, jump_delay: tuple[float, float] = (0, 0)):
        """Causes the mob to jump as it moves with a specified delay between jumps."""
        movement = _BaseComponent("movement.jump")
        if not max_turn == 30:
            movement._add_field("max_turn", max_turn)
        if not jump_delay == (0, 0):
            movement._add_field("jump_delay", jump_delay)
        return movement

    @staticmethod
    def Skip(max_turn: float = 30):
        """Causes the mob to hop as it moves."""
        movement = _BaseComponent("movement.skip")
        if not max_turn == 30:
            movement._add_field("max_turn", max_turn)
        return movement

    @staticmethod
    def Sway(
        max_turn: float = 30,
        sway_amplitude: float = 0.05,
        sway_frequency: float = 0.5,
    ):
        """Causes the mob to sway side to side giving the impression it is swimming."""
        movement = _BaseComponent("movement.sway")
        if not max_turn == 30:
            movement._add_field("max_turn", max_turn)
        if not sway_amplitude == 0.05:
            movement._add_field("sway_amplitude", sway_amplitude)
        if not sway_frequency == 0.5:
            movement._add_field("sway_frequency", sway_frequency)
        return movement

    @staticmethod
    def Hover(max_turn: float = 30):
        """Causes the mob to hover."""
        movement = _BaseComponent("movement.hover")
        if not max_turn == 30:
            movement._add_field("max_turn", max_turn)
        return movement


class EntityNavigationType:
    @staticmethod
    def _basic(
        cls: _BaseComponent,
        avoid_damage_blocks: bool = False,
        avoid_portals: bool = False,
        avoid_sun: bool = False,
        avoid_water: bool = False,
        can_breach: bool = False,
        can_break_doors: bool = False,
        can_jump: bool = True,
        can_float: bool = False,
        can_open_doors: bool = False,
        can_open_iron_doors: bool = False,
        can_pass_doors: bool = True,
        can_path_from_air: bool = False,
        can_path_over_lava: bool = False,
        can_path_over_water: bool = False,
        can_sink: bool = True,
        can_swim: bool = False,
        can_walk: bool = True,
        can_walk_in_lava: bool = False,
        is_amphibious: bool = False,
        blocks_to_avoid: list[Block | Identifier] = [],
    ) -> None:
        if avoid_damage_blocks:
            cls._add_field("avoid_damage_blocks", avoid_damage_blocks)
        if avoid_portals:
            cls._add_field("avoid_portals", avoid_portals)
        if avoid_sun:
            cls._add_field("avoid_sun", avoid_sun)
        if avoid_water:
            cls._add_field("avoid_water", avoid_water)
        if can_breach:
            cls._add_field("can_breach", can_breach)
        if can_break_doors:
            cls._add_field("can_break_doors", can_break_doors)
        if can_float:
            cls._add_field("can_float", can_float)
        if not can_jump:
            cls._add_field("can_jump", can_jump)
        if can_open_doors:
            cls._add_field("can_open_doors", can_open_doors)
        if can_open_iron_doors:
            cls._add_field("can_open_iron_doors", can_open_iron_doors)
        if not can_pass_doors:
            cls._add_field("can_pass_doors", can_pass_doors)
        if can_path_from_air:
            cls._add_field("can_path_from_air", can_path_from_air)
        if can_path_over_lava:
            cls._add_field("can_path_over_lava", can_path_over_lava)
        if can_path_over_water:
            cls._add_field("can_path_over_water", can_path_over_water)
        if not can_sink:
            cls._add_field("can_sink", can_sink)
        if can_swim:
            cls._add_field("can_swim", can_swim)
        if not can_walk:
            cls._add_field("can_walk", can_walk)
        if can_walk_in_lava:
            cls._add_field("can_walk_in_lava", can_walk_in_lava)
        if is_amphibious:
            cls._add_field("is_amphibious", is_amphibious)
        if len(blocks_to_avoid) > 0:
            if not all(isinstance(block, (MinecraftBlockDescriptor, str)) for block in blocks_to_avoid):
                raise TypeError(
                    f"blocks_to_avoid must be a list of MinecraftBlockDescriptor or Identifier instances. Component [{cls._identifier}]."
                )

            cls._add_field(
                "blocks_to_avoid",
                [str(block) for block in blocks_to_avoid],
            )

        return cls

    @staticmethod
    def Climb(
        avoid_damage_blocks: bool = False,
        avoid_portals: bool = False,
        avoid_sun: bool = False,
        avoid_water: bool = False,
        can_breach: bool = False,
        can_break_doors: bool = False,
        can_float: bool = False,
        can_jump: bool = True,
        can_open_doors: bool = False,
        can_open_iron_doors: bool = False,
        can_pass_doors: bool = True,
        can_path_from_air: bool = False,
        can_path_over_lava: bool = False,
        can_path_over_water: bool = False,
        can_sink: bool = True,
        can_swim: bool = False,
        can_walk: bool = True,
        can_walk_in_lava: bool = False,
        is_amphibious: bool = False,
        blocks_to_avoid: list[Block | Identifier] = [],
    ):
        """Allows this entity to generate paths that include vertical walls like the vanilla Spiders do."""
        navigation = _BaseComponent("navigation.climb")
        EntityNavigationType._basic(
            navigation,
            avoid_damage_blocks,
            avoid_portals,
            avoid_sun,
            avoid_water,
            can_breach,
            can_break_doors,
            can_jump,
            can_float,
            can_open_doors,
            can_open_iron_doors,
            can_pass_doors,
            can_path_from_air,
            can_path_over_lava,
            can_path_over_water,
            can_sink,
            can_swim,
            can_walk,
            can_walk_in_lava,
            is_amphibious,
            blocks_to_avoid,
        )
        return navigation

    @staticmethod
    def Float(
        avoid_damage_blocks: bool = False,
        avoid_portals: bool = False,
        avoid_sun: bool = False,
        avoid_water: bool = False,
        can_breach: bool = False,
        can_break_doors: bool = False,
        can_jump: bool = True,
        can_float: bool = False,
        can_open_doors: bool = False,
        can_open_iron_doors: bool = False,
        can_pass_doors: bool = True,
        can_path_from_air: bool = False,
        can_path_over_lava: bool = False,
        can_path_over_water: bool = False,
        can_sink: bool = True,
        can_swim: bool = False,
        can_walk: bool = True,
        can_walk_in_lava: bool = False,
        is_amphibious: bool = False,
        blocks_to_avoid: list[Block | Identifier] = [],
    ):
        """Allows this entity to generate paths by flying around the air like the regular Ghast."""
        navigation = _BaseComponent("navigation.float")
        EntityNavigationType._basic(
            navigation,
            avoid_damage_blocks,
            avoid_portals,
            avoid_sun,
            avoid_water,
            can_breach,
            can_break_doors,
            can_jump,
            can_float,
            can_open_doors,
            can_open_iron_doors,
            can_pass_doors,
            can_path_from_air,
            can_path_over_lava,
            can_path_over_water,
            can_sink,
            can_swim,
            can_walk,
            can_walk_in_lava,
            is_amphibious,
            blocks_to_avoid,
        )
        return navigation

    @staticmethod
    def Fly(
        avoid_damage_blocks: bool = False,
        avoid_portals: bool = False,
        avoid_sun: bool = False,
        avoid_water: bool = False,
        can_breach: bool = False,
        can_break_doors: bool = False,
        can_jump: bool = True,
        can_float: bool = False,
        can_open_doors: bool = False,
        can_open_iron_doors: bool = False,
        can_pass_doors: bool = True,
        can_path_from_air: bool = False,
        can_path_over_lava: bool = False,
        can_path_over_water: bool = False,
        can_sink: bool = True,
        can_swim: bool = False,
        can_walk: bool = True,
        can_walk_in_lava: bool = False,
        is_amphibious: bool = False,
        blocks_to_avoid: list[Block | Identifier] = [],
    ):
        """Allows this entity to generate paths in the air like the vanilla Parrots do."""
        navigation = _BaseComponent("navigation.fly")
        EntityNavigationType._basic(
            navigation,
            avoid_damage_blocks,
            avoid_portals,
            avoid_sun,
            avoid_water,
            can_breach,
            can_break_doors,
            can_jump,
            can_float,
            can_open_doors,
            can_open_iron_doors,
            can_pass_doors,
            can_path_from_air,
            can_path_over_lava,
            can_path_over_water,
            can_sink,
            can_swim,
            can_walk,
            can_walk_in_lava,
            is_amphibious,
            blocks_to_avoid,
        )
        return navigation

    @staticmethod
    def Generic(
        avoid_damage_blocks: bool = False,
        avoid_portals: bool = False,
        avoid_sun: bool = False,
        avoid_water: bool = False,
        can_breach: bool = False,
        can_break_doors: bool = False,
        can_jump: bool = True,
        can_float: bool = False,
        can_open_doors: bool = False,
        can_open_iron_doors: bool = False,
        can_pass_doors: bool = True,
        can_path_from_air: bool = False,
        can_path_over_lava: bool = False,
        can_path_over_water: bool = False,
        can_sink: bool = True,
        can_swim: bool = False,
        can_walk: bool = True,
        can_walk_in_lava: bool = False,
        is_amphibious: bool = False,
        blocks_to_avoid: list[Block | Identifier] = [],
    ):
        """Allows this entity to generate paths by walking, swimming, flying and/or climbing around and jumping up and down a block."""
        navigation = _BaseComponent("navigation.generic")
        EntityNavigationType._basic(
            navigation,
            avoid_damage_blocks,
            avoid_portals,
            avoid_sun,
            avoid_water,
            can_breach,
            can_break_doors,
            can_jump,
            can_float,
            can_open_doors,
            can_open_iron_doors,
            can_pass_doors,
            can_path_from_air,
            can_path_over_lava,
            can_path_over_water,
            can_sink,
            can_swim,
            can_walk,
            can_walk_in_lava,
            is_amphibious,
            blocks_to_avoid,
        )
        return navigation

    @staticmethod
    def Hover(
        avoid_damage_blocks: bool = False,
        avoid_portals: bool = False,
        avoid_sun: bool = False,
        avoid_water: bool = False,
        can_breach: bool = False,
        can_break_doors: bool = False,
        can_jump: bool = True,
        can_float: bool = False,
        can_open_doors: bool = False,
        can_open_iron_doors: bool = False,
        can_pass_doors: bool = True,
        can_path_from_air: bool = False,
        can_path_over_lava: bool = False,
        can_path_over_water: bool = False,
        can_sink: bool = True,
        can_swim: bool = False,
        can_walk: bool = True,
        can_walk_in_lava: bool = False,
        is_amphibious: bool = False,
        blocks_to_avoid: list[Block | Identifier] = [],
    ):
        """Allows this entity to generate paths in the air like the vanilla Bees do. Keeps them from falling out of the skies and doing predictive movement."""
        navigation = _BaseComponent("navigation.hover")
        EntityNavigationType._basic(
            navigation,
            avoid_damage_blocks,
            avoid_portals,
            avoid_sun,
            avoid_water,
            can_breach,
            can_break_doors,
            can_jump,
            can_float,
            can_open_doors,
            can_open_iron_doors,
            can_pass_doors,
            can_path_from_air,
            can_path_over_lava,
            can_path_over_water,
            can_sink,
            can_swim,
            can_walk,
            can_walk_in_lava,
            is_amphibious,
            blocks_to_avoid,
        )
        return navigation

    @staticmethod
    def Swim(
        avoid_damage_blocks: bool = False,
        avoid_portals: bool = False,
        avoid_sun: bool = False,
        avoid_water: bool = False,
        can_breach: bool = False,
        can_break_doors: bool = False,
        can_jump: bool = True,
        can_float: bool = False,
        can_open_doors: bool = False,
        can_open_iron_doors: bool = False,
        can_pass_doors: bool = True,
        can_path_from_air: bool = False,
        can_path_over_lava: bool = False,
        can_path_over_water: bool = False,
        can_sink: bool = True,
        can_swim: bool = False,
        can_walk: bool = True,
        can_walk_in_lava: bool = False,
        is_amphibious: bool = False,
        blocks_to_avoid: list[Block | Identifier] = [],
    ):
        """Allows this entity to generate paths that include water."""
        navigation = _BaseComponent("navigation.swim")
        EntityNavigationType._basic(
            navigation,
            avoid_damage_blocks,
            avoid_portals,
            avoid_sun,
            avoid_water,
            can_breach,
            can_break_doors,
            can_jump,
            can_float,
            can_open_doors,
            can_open_iron_doors,
            can_pass_doors,
            can_path_from_air,
            can_path_over_lava,
            can_path_over_water,
            can_sink,
            can_swim,
            can_walk,
            can_walk_in_lava,
            is_amphibious,
            blocks_to_avoid,
        )
        return navigation

    @staticmethod
    def Walk(
        avoid_damage_blocks: bool = False,
        avoid_portals: bool = False,
        avoid_sun: bool = False,
        avoid_water: bool = False,
        can_breach: bool = False,
        can_break_doors: bool = False,
        can_jump: bool = True,
        can_float: bool = False,
        can_open_doors: bool = False,
        can_open_iron_doors: bool = False,
        can_pass_doors: bool = True,
        can_path_from_air: bool = False,
        can_path_over_lava: bool = False,
        can_path_over_water: bool = False,
        can_sink: bool = True,
        can_swim: bool = False,
        can_walk: bool = True,
        can_walk_in_lava: bool = False,
        is_amphibious: bool = False,
        blocks_to_avoid: list[Block | Identifier] = [],
    ):
        """Allows this entity to generate paths by walking around and jumping up and down a block like regular mobs."""
        navigation = _BaseComponent("navigation.walk")
        EntityNavigationType._basic(
            navigation,
            avoid_damage_blocks,
            avoid_portals,
            avoid_sun,
            avoid_water,
            can_breach,
            can_break_doors,
            can_jump,
            can_float,
            can_open_doors,
            can_open_iron_doors,
            can_pass_doors,
            can_path_from_air,
            can_path_over_lava,
            can_path_over_water,
            can_sink,
            can_swim,
            can_walk,
            can_walk_in_lava,
            is_amphibious,
            blocks_to_avoid,
        )
        return navigation


class EntityEnvironmentSensor(_BaseComponent):
    _identifier = "minecraft:environment_sensor"

    def __init__(self) -> None:
        """Creates a trigger based on environment conditions.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_environment_sensor
        """
        super().__init__("environment_sensor")
        self._add_field("triggers", [])

    def trigger(self, event: Event, filters: Filter):
        self._component["triggers"].append({"filters": filters, "event": event})
        return self


class EntityPreferredPath(_BaseComponent):
    _identifier = "minecraft:preferred_path"

    def __init__(self, default_block_cost: int = 0, jump_cost: int = 0, max_fall_blocks: int = 3) -> None:
        """Specifies costing information for mobs that prefer to walk on preferred paths.

        Parameters:
            default_block_cost (int, optional): Description. Defaults to 0.
            jump_cost (int, optional): Description. Defaults to 0.
            max_fall_blocks (int, optional): Description. Defaults to 3.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_preferred_path
        """
        super().__init__("preferred_path")
        self._add_field("default_block_cost", default_block_cost)
        self._add_field("jump_cost", jump_cost)
        self._add_field("max_fall_blocks", max_fall_blocks)
        self._add_field("preferred_path_blocks", [])

    def add_blocks(self, cost: int, blocks: list[MinecraftBlockDescriptor | Identifier]):
        if not all(isinstance(block, (MinecraftBlockDescriptor, str)) for block in blocks):
            raise TypeError(
                f"blocks must be a list of MinecraftBlockDescriptor or Identifier instances. Component [{self._identifier}]."
            )

        self._component["preferred_path_blocks"].append(
            {
                "cost": cost,
                "blocks": [str(block) for block in blocks],
            }
        )
        return self


class EntityTargetNearbySensor(_BaseComponent):
    _identifier = "minecraft:target_nearby_sensor"

    def __init__(self, inside_range: int = 1, outside_range: int = 5, must_see: bool = False) -> None:
        """Defines the entity's range within which it can see or sense other entities to target them.

        Parameters:
            inside_range (int, optional): Description. Defaults to 1.
            outside_range (int, optional): Description. Defaults to 5.
            must_see (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_target_nearby_sensor
        """
        super().__init__("target_nearby_sensor")
        self._add_field("inside_range", inside_range)
        self._add_field("outside_range", outside_range)
        self._add_field("must_see", must_see)

    def on_inside_range(self, event: Event, target: FilterSubject):
        self._add_field("on_inside_range", {"event": event, "target": target.value})
        return self

    def on_outside_range(self, event: Event, target: FilterSubject):
        self._add_field("on_outside_range", {"event": event, "target": target.value})
        return self

    def on_vision_lost_inside_range(self, event: Event, target: FilterSubject):
        self._add_field("on_vision_lost_inside_range", {"event": event, "target": target.value})
        return self


class EntityRideable(_BaseComponent):
    _identifier = "minecraft:rideable"

    def __init__(
        self,
        interact_text: str = "Mount",
        controlling_seat: int = 0,
        crouching_skip_interact: bool = True,
        pull_in_entities: bool = False,
        rider_can_interact: bool = False,
        dismount_mode: RideableDismountMode = RideableDismountMode.Default,
        on_rider_enter_event: str = None,
        on_rider_exit_event: str = None,
    ) -> None:
        """Determines whether this entity can be ridden. Allows specifying the different seat positions and quantity.

        Parameters:
            interact_text (str, optional): Description. Defaults to 'Mount'.
            controlling_seat (int, optional): Description. Defaults to 0.
            crouching_skip_interact (bool, optional): Description. Defaults to True.
            pull_in_entities (bool, optional): Description. Defaults to False.
            rider_can_interact (bool, optional): Description. Defaults to False.
            dismount_mode (RideableDismountMode, optional): Description. Defaults to RideableDismountMode.Default.
            on_rider_enter_event (str, optional): Description. Defaults to None.
            on_rider_exit_event (str, optional): Description. Defaults to None.

        ## Behaviour Observations:
            Adding a rider makes them occupy the first available seat on the rideable entity.
            Removing a rider at any seat will shift all subsequent riders forward by one seat.
            Unless the rider is a Player in which case they will occupy the very first seat and shift all other riders back by one seat.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_rideable
        """
        super().__init__("rideable")
        self._seat_count = 0

        if not interact_text == "Mount":
            t = interact_text.lower().replace(" ", "_")
            self._add_field("interact_text", f"action.interact.{t}")
            AnvilTranslator().add_localization_entry(f"action.interact.{t}", interact_text)

        self._add_field("controlling_seat", controlling_seat)
        if not crouching_skip_interact:
            self._add_field("crouching_skip_interact", crouching_skip_interact)
        if pull_in_entities:
            self._add_field("pull_in_entities", pull_in_entities)
        if rider_can_interact:
            self._add_field("rider_can_interact", rider_can_interact)
        if not dismount_mode == RideableDismountMode.Default:
            self._add_field("dismount_mode", dismount_mode.value)
        if on_rider_enter_event:
            self._add_field("on_rider_enter_event", on_rider_enter_event)
        if on_rider_exit_event:
            self._add_field("on_rider_exit_event", on_rider_exit_event)

        self._add_field("seats", [])

    def add_seat(
        self,
        position: Vector3D,
        max_rider_count: int,
        min_rider_count: int = 0,
        lock_rider_rotation: int = 181,
        rotate_rider_by: int = 0,
        third_person_camera_radius: float = 1.0,
        camera_relax_distance_smoothing: float = 1.0,
    ):
        self._seat_count += 1
        self._add_field("seat_count", self._seat_count)
        third_person_camera_radius = clamp(third_person_camera_radius, 1, 64)
        camera_relax_distance_smoothing = clamp(camera_relax_distance_smoothing, 1, 32)
        self._get_field("seats", []).append(
            {
                "max_rider_count": max_rider_count,
                "position": position,
                "lock_rider_rotation": (lock_rider_rotation if not lock_rider_rotation == 181 else {}),
                "min_rider_count": min_rider_count if not min_rider_count == 0 else {},
                "rotate_rider_by": rotate_rider_by if not rotate_rider_by == 0 else {},
                "third_person_camera_radius": (
                    third_person_camera_radius if not third_person_camera_radius == 1.0 else {}
                ),
                "camera_relax_distance_smoothing": (
                    camera_relax_distance_smoothing if not camera_relax_distance_smoothing == 1.0 else {}
                ),
            }
        )

        return self

    def family_types(self, families: list[str]):
        self._add_field("family_types", families)
        return self


class EntityProjectile(_BaseComponent):
    _identifier = "minecraft:projectile"

    def __init__(
        self,
        anchor: int = 0,
        angle_offset: float = 0,
        catch_fire: bool = False,
        crit_particle_on_hurt: bool = False,
        destroy_on_hurt: bool = False,
        fire_affected_by_griefing: bool = False,
        gravity: float = 0.05,
        hit_sound: str = "",
        hit_ground_sound: str = "",
        hit_water: bool = False,
        homing: bool = False,
        inertia: float = 0.99,
        is_dangerous: bool = False,
        knockback: bool = True,
        lightning: bool = False,
        liquid_inertia: float = 0.6,
        multiple_targets: bool = True,
        offset: Coordinates = (0, 0.5, 0),
        on_fire_time: float = 5.0,
        particle: str = "iconcrack",
        potion_effect: int = -1,
        power: float = 1.3,
        reflect_on_hurt: bool = False,
        semi_random_diff_damage: bool = False,
        shoot_sound: str = "",
        shoot_target: bool = True,
        should_bounce: bool = False,
        splash_potion: bool = False,
        splash_range: float = 4.0,
        stop_on_hurt: bool = False,
        uncertainty_base: float = 0.0,
        uncertainty_multiplier: float = 0.0,
    ) -> None:
        """Allows the entity to be a thrown entity.

        Parameters:
            anchor (int, optional): . Defaults to 0.
            angle_offset (float, optional): . Defaults to 0.
            catch_fire (bool, optional): . Defaults to False.
            crit_particle_on_hurt (bool, optional): . Defaults to False.
            destroy_on_hurt (bool, optional): . Defaults to False.
            fire_affected_by_griefing (bool, optional): . Defaults to False.
            gravity (float, optional): . Defaults to 0.05.
            hit_sound (str, optional): . Defaults to ''.
            hit_ground_sound (str, optional): . Defaults to ''.
            hit_water (bool, optional): . Defaults to False.
            homing (bool, optional): . Defaults to False.
            inertia (float, optional): . Defaults to 0.99.
            is_dangerous (bool, optional): . Defaults to False.
            knockback (bool, optional): . Defaults to True.
            lightning (bool, optional): . Defaults to False.
            liquid_inertia (float, optional): . Defaults to 0.6.
            multiple_targets (bool, optional): . Defaults to True.
            offset (Coordinates, optional): . Defaults to (0, 0.5, 0).
            on_fire_time (float, optional): . Defaults to 5.0.
            particle (str, optional): . Defaults to 'iconcrack'.
            potion_effect (int, optional): . Defaults to -1.
            power (float, optional): . Defaults to 1.3.
            reflect_on_hurt (bool, optional): . Defaults to False.
            semi_random_diff_damage (bool, optional): . Defaults to False.
            shoot_sound (str, optional): . Defaults to ''.
            shoot_target (bool, optional): . Defaults to True.
            should_bounce (bool, optional): . Defaults to False.
            splash_potion (bool, optional): . Defaults to False.
            splash_range (float, optional): . Defaults to 4.0.
            stop_on_hurt (bool, optional): . Defaults to False.
            uncertainty_base (float, optional): . Defaults to 0.0.
            uncertainty_multiplier (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_projectile
        """
        super().__init__("projectile")
        if anchor != 0:
            self._add_field("anchor", anchor)
        if angle_offset != 0:
            self._add_field("angle_offset", angle_offset)
        if catch_fire:
            self._add_field("catch_fire", catch_fire)
        if crit_particle_on_hurt:
            self._add_field("crit_particle_on_hurt", crit_particle_on_hurt)
        if destroy_on_hurt:
            self._add_field("destroy_on_hurt", destroy_on_hurt)
        if fire_affected_by_griefing:
            self._add_field("fire_affected_by_griefing", fire_affected_by_griefing)
        if gravity != 0.05:
            self._add_field("gravity", gravity)
        if hit_sound != "":
            self._add_field("hit_sound", hit_sound)
        if hit_ground_sound != "":
            self._add_field("hit_ground_sound", hit_ground_sound)
        if hit_water:
            self._add_field("hit_water", hit_water)
        if homing:
            self._add_field("homing", homing)
        if inertia != 0.99:
            self._add_field("inertia", inertia)
        if is_dangerous:
            self._add_field("is_dangerous", is_dangerous)
        if not knockback:
            self._add_field("knockback", knockback)
        if lightning:
            self._add_field("lightning", lightning)
        if liquid_inertia != 0.6:
            self._add_field("liquid_inertia", liquid_inertia)
        if not multiple_targets:
            self._add_field("multiple_targets", multiple_targets)
        if offset != (0, 0.5, 0):
            self._add_field("offset", offset)
        if on_fire_time != 5.0:
            self._add_field("on_fire_time", on_fire_time)
        if particle != "iconcrack":
            self._add_field("particle", particle)
        if potion_effect != -1:
            self._add_field("potion_effect", potion_effect)
        if power != 1.3:
            self._add_field("power", power)
        if reflect_on_hurt:
            self._add_field("reflect_on_hurt", reflect_on_hurt)
        if semi_random_diff_damage:
            self._add_field("semi_random_diff_damage", semi_random_diff_damage)
        if shoot_sound != "":
            self._add_field("shoot_sound", shoot_sound)
        if not shoot_target:
            self._add_field("shoot_target", shoot_target)
        if should_bounce:
            self._add_field("should_bounce", should_bounce)
        if splash_potion:
            self._add_field("splash_potion", splash_potion)
        if splash_range != 4.0:
            self._add_field("splash_range", splash_range)
        if stop_on_hurt:
            self._add_field("stop_on_hurt", stop_on_hurt)
        if uncertainty_base != 0.0:
            self._add_field("uncertainty_base", uncertainty_base)
        if uncertainty_multiplier != 0.0:
            self._add_field("uncertainty_multiplier", uncertainty_multiplier)

        # Initialize on_hit dictionary to avoid checks in methods
        self._add_field("on_hit", {})

    def arrow_effect(self):
        """Enable arrow effect on hit.

        Note:
            Exact behavior unknown according to Bedrock Wiki.

        Returns:
            Self for method chaining.
        """
        self._component["on_hit"]["arrow_effect"] = {}
        return self

    def definition_event(
        self,
        event: Event,
        target: FilterSubject,
        affect_projectile: bool = False,
        affect_shooter: bool = False,
        affect_splash_area: bool = False,
        splash_area: float = 0,
        affect_target: bool = False,
    ):
        """Call an event on hit.

        Args:
            event: Event to trigger.
            target: Target of the event.
            affect_projectile: Event will be triggered for projectile entity. Default is False.
            affect_shooter: Event will be triggered for shooter entity. Default is False.
            affect_splash_area: Event will be triggered for all entities in an area. Default is False.
            splash_area: Area of entities to affect. Default is 0.
            affect_target: Event will be triggered for hit entity. Default is False.

        Returns:
            Self for method chaining.
        """
        self._component["on_hit"]["definition_event"] = {"event_trigger": {"event": event, "target": target.value}}

        if affect_projectile:
            self._component["on_hit"]["definition_event"]["affect_projectile"] = affect_projectile
        if affect_shooter:
            self._component["on_hit"]["definition_event"]["affect_shooter"] = affect_shooter
        if affect_splash_area:
            self._component["on_hit"]["definition_event"]["affect_splash_area"] = affect_splash_area
        if splash_area:
            self._component["on_hit"]["definition_event"]["splash_area"] = splash_area
        if affect_target:
            self._component["on_hit"]["definition_event"]["affect_target"] = affect_target

        return self

    def filter(self, filter: Filter):
        """Set entity filter for the projectile.

        Args:
            filter: The filter to apply.

        Returns:
            Self for method chaining.
        """
        self._add_field("filter", filter)
        return self

    def freeze_on_hit(
        self,
        size: int,
        snap_to_block: bool,
        shape: str = "sphere",
    ):
        """Freeze water on hit.

        Args:
            size: The size of the freeze effect.
            snap_to_block: Whether to snap to block.
            shape: Shape of the freeze effect. Must be "sphere" or "cube". Default is "sphere".

        Returns:
            Self for method chaining.

        Note:
            Requires Education Edition toggle to be enabled.
            According to Bedrock Wiki, exact behavior is unknown.

        Raises:
            RuntimeError: If shape is not "sphere" or "cube".
        """
        self._component["on_hit"]["freeze_on_hit"] = {
            "size": size,
            "snap_to_block": snap_to_block,
        }
        if shape not in ["sphere", "cube"]:
            raise RuntimeError("Unknown shape, must be sphere or cube")
        self._component["on_hit"]["freeze_on_hit"]["shape"] = shape

        return self

    def grant_xp(self, xp: int | tuple[int, int]):
        """Grant experience points on hit.

        Args:
            xp: Experience to grant. If int, grants constant amount. If tuple, grants random amount between min and max.

        Returns:
            Self for method chaining.

        Note:
            Despite the name, this actually spawns a number of experience orbs, being worth the amount stated.

        Raises:
            ValueError: If xp is not an int or tuple of two ints.
        """
        if isinstance(xp, int):
            self._component["on_hit"]["grant_xp"] = {"xp": xp}
        elif isinstance(xp, tuple) and len(xp) == 2:
            if xp[0] == xp[1]:
                self._component["on_hit"]["grant_xp"] = {"xp": xp[0]}
            else:
                self._component["on_hit"]["grant_xp"] = {
                    "minXP": min(xp),
                    "maxXP": max(xp),
                }
        else:
            raise ValueError("xp must be an int or tuple of two ints")

        return self

    def hurt_owner(
        self,
        owner_damage: int = 0,
        knockback: bool = False,
        ignite: bool = False,
    ):
        """Configure projectile to potentially hurt its owner on hit.

        Args:
            owner_damage: Damage dealt to the owner. Default is 0.
            knockback: Whether to apply knockback to owner. Default is False.
            ignite: Whether to ignite the owner. Default is False.

        Returns:
            Self for method chaining.

        Note:
            According to Bedrock Wiki, exact behavior is unknown and this may crash Minecraft with wrong parameters.
        """
        self._component["on_hit"]["hurt_owner"] = {}

        if owner_damage != 0:
            self._component["on_hit"]["hurt_owner"]["owner_damage"] = owner_damage
        if knockback:
            self._component["on_hit"]["hurt_owner"]["knockback"] = knockback
        if ignite:
            self._component["on_hit"]["hurt_owner"]["ignite"] = ignite

        return self

    def impact_damage(
        self,
        filter: str = None,
        catch_fire: bool = False,
        channeling: bool = True,
        damage: int = 1,
        destroy_on_hit: bool = False,
        destroy_on_hit_requires_damage: bool = True,
        knockback: bool = True,
        max_critical_damage: int = 5,
        min_critical_damage: int = 0,
        power_multiplier: float = 2,
        semi_random_diff_damage: bool = False,
        set_last_hurt_requires_damage: bool = False,
        apply_knockback_to_blocking_targets: bool = False,
    ):
        """Deal damage on impact.

        Args:
            filter: Entity identifier to affect. Much more primitive than filters used elsewhere, as it cannot "test" for anything other than an identifier. Default is None.
            catch_fire: Whether targets will be engulfed in flames. Default is False.
            channeling: Whether lightning can be channeled through the weapon. Default is True.
            damage: Damage dealt to entity on hit. Default is 1.
            destroy_on_hit: Whether projectile is removed on hit. Default is False.
            destroy_on_hit_requires_damage: If true, hit must cause damage to destroy the projectile. Default is True.
            knockback: Whether the projectile will knock back the entity it hits. Default is True.
            max_critical_damage: Maximum critical damage. Default is 5.
            min_critical_damage: Minimum critical damage. Default is 0.
            power_multiplier: How much the base damage is multiplied. Default is 2.
            semi_random_diff_damage: If true, damage will be randomized based on damage and speed. Default is False.
            set_last_hurt_requires_damage: If true, hit must cause damage to update the last hurt property. Default is False.
            apply_knockback_to_blocking_targets: If true, knockback will be applied to any blocking targets. Default is False.

        Returns:
            Self for method chaining.
        """
        self._component["on_hit"]["impact_damage"] = {}
        if not filter is None:
            self._component["on_hit"]["impact_damage"]["filter"] = filter
        if catch_fire:
            self._component["on_hit"]["impact_damage"]["catch_fire"] = catch_fire
        if not channeling:
            self._component["on_hit"]["impact_damage"]["channeling"] = channeling
        if damage != 1:
            self._component["on_hit"]["impact_damage"]["damage"] = damage
        if destroy_on_hit:
            self._component["on_hit"]["impact_damage"]["destroy_on_hit"] = destroy_on_hit
        if not destroy_on_hit_requires_damage:
            self._component["on_hit"]["impact_damage"][
                "destroy_on_hit_requires_damage"
            ] = destroy_on_hit_requires_damage
        if not knockback:
            self._component["on_hit"]["impact_damage"]["knockback"] = knockback
        if max_critical_damage != 5:
            self._component["on_hit"]["impact_damage"]["max_critical_damage"] = max_critical_damage
        if min_critical_damage != 0:
            self._component["on_hit"]["impact_damage"]["min_critical_damage"] = min_critical_damage
        if power_multiplier != 2:
            self._component["on_hit"]["impact_damage"]["power_multiplier"] = power_multiplier
        if semi_random_diff_damage:
            self._component["on_hit"]["impact_damage"]["semi_random_diff_damage"] = semi_random_diff_damage
        if set_last_hurt_requires_damage:
            self._component["on_hit"]["impact_damage"]["set_last_hurt_requires_damage"] = set_last_hurt_requires_damage
        if apply_knockback_to_blocking_targets:
            self._component["on_hit"]["impact_damage"][
                "apply_knockback_to_blocking_targets"
            ] = apply_knockback_to_blocking_targets

        return self

    def mob_effect(
        self,
        effect: MinecraftEffects,
        amplifier: int = 1,
        ambient: bool = False,
        visible: bool = False,
        duration: int = 1,
        durationeasy: int = 0,
        durationhard: int = 800,
        durationnormal: int = 200,
    ):
        """Apply a mob effect to the target on hit.

        Args:
            effect: The effect to apply.
            amplifier: Effect amplifier. Default is 1.
            ambient: Whether the effect is ambient. Default is False.
            visible: Whether the effect is visible. Default is False.
            duration: Duration of the effect. Default is 1.
            durationeasy: Duration of the effect on easy difficulty. Default is 0.
            durationhard: Duration of the effect on hard difficulty. Default is 800.
            durationnormal: Duration of the effect on normal difficulty. Default is 200.

        Returns:
            Self for method chaining.
        """
        self._component["on_hit"]["mob_effect"] = {"effect": effect.value}

        if amplifier != 1:
            self._component["on_hit"]["mob_effect"]["amplifier"] = amplifier
        if ambient:
            self._component["on_hit"]["mob_effect"]["ambient"] = ambient
        if visible:
            self._component["on_hit"]["mob_effect"]["visible"] = visible
        if duration != 1:
            self._component["on_hit"]["mob_effect"]["duration"] = duration
        if durationeasy != 0:
            self._component["on_hit"]["mob_effect"]["durationeasy"] = durationeasy
        if durationhard != 800:
            self._component["on_hit"]["mob_effect"]["durationhard"] = durationhard
        if durationnormal != 200:
            self._component["on_hit"]["mob_effect"]["durationnormal"] = durationnormal

        return self

    def on_hit(
        self,
        catch_fire: bool = False,
        douse_fire: bool = False,
        ignite: bool = False,
        teleport_owner: bool = False,
    ):
        """Configure basic on_hit behaviors for the projectile.

        Args:
            catch_fire: Determines if the struck object is set on fire. Default is False.
            douse_fire: If the target is on fire, then douse the fire. Default is False.
            ignite: Determines if a fire may be started on a flammable target. Default is False.
            teleport_owner: Determines if the owner is transported on hit. Default is False.

        Returns:
            Self for method chaining.
        """
        if catch_fire:
            self._component["on_hit"]["catch_fire"] = catch_fire
        if douse_fire:
            self._component["on_hit"]["douse_fire"] = douse_fire
        if ignite:
            self._component["on_hit"]["ignite"] = ignite
        if teleport_owner:
            self._component["on_hit"]["teleport_owner"] = teleport_owner
        return self

    def particle_on_hit(
        self,
        particle_type: str,
        on_other_hit: bool = False,
        on_entity_hit: bool = False,
        num_particles: int = 0,
    ):
        """Spawn particles on hit.

        Args:
            particle_type: Vanilla particle type to use.
            on_other_hit: Whether it should spawn particles on non-entity hit. Default is False.
            on_entity_hit: Whether it should spawn particles on entity hit. Default is False.
            num_particles: Number of particles to spawn. Default is 0.

        Returns:
            Self for method chaining.
        """
        self._component["on_hit"]["particle_on_hit"] = {"particle_type": particle_type}

        if on_other_hit:
            self._component["on_hit"]["particle_on_hit"]["on_other_hit"] = on_other_hit
        if on_entity_hit:
            self._component["on_hit"]["particle_on_hit"]["on_entity_hit"] = on_entity_hit
        if num_particles != 0:
            self._component["on_hit"]["particle_on_hit"]["num_particles"] = num_particles
        return self

    @property
    def remove_on_hit(self):
        """Remove the projectile when it hits something.

        Returns:
            Self for method chaining.
        """
        self._component["on_hit"]["remove_on_hit"] = {"remove": True}
        return self

    def spawn_aoe_cloud(
        self,
        affect_owner: bool = True,
        color: tuple[int, int, int] = (1, 1, 1),
        duration: int = 0,
        particle: str = "",
        potion: int = -1,
        radius: float = 0.0,
        radius_on_use: float = -1.0,
        reapplication_delay: int = 0,
    ):
        """Spawn an area of effect cloud of potion effect on hit.

        Args:
            affect_owner: Whether potion effect affects the shooter. Does not appear to apply to the player. Default is True.
            color: RGB color of the particles. Default is (1, 1, 1).
            duration: Duration of the cloud in seconds. Default is 0.
            particle: Vanilla particle emitter of the cloud. Only accepts Vanilla Particles. 'dragonbreath' enables the usage of Bottles to obtain Dragon's Breath. Default is "".
            potion: Lingering Potion ID. Default is -1.
            radius: Radius of the cloud. Default is 0.0.
            radius_on_use: Radius change on use. Default is -1.0.
            reapplication_delay: Delay in ticks between application of the potion effect. Default is 0.

        Returns:
            Self for method chaining.
        """
        self._component["on_hit"]["spawn_aoe_cloud"] = {}

        if not affect_owner:
            self._component["on_hit"]["spawn_aoe_cloud"]["affect_owner"] = affect_owner
        if color != (1, 1, 1):
            self._component["on_hit"]["spawn_aoe_cloud"]["color"] = color
        if duration != 0:
            self._component["on_hit"]["spawn_aoe_cloud"]["duration"] = duration
        if particle != "":
            self._component["on_hit"]["spawn_aoe_cloud"]["particle"] = particle
        if potion != -1:
            self._component["on_hit"]["spawn_aoe_cloud"]["potion"] = potion
        if radius != 0.0:
            self._component["on_hit"]["spawn_aoe_cloud"]["radius"] = radius
        if radius_on_use != -1.0:
            self._component["on_hit"]["spawn_aoe_cloud"]["radius_on_use"] = radius_on_use
        if reapplication_delay != 0:
            self._component["on_hit"]["spawn_aoe_cloud"]["reapplication_delay"] = reapplication_delay

        return self

    def spawn_chance(
        self,
        spawn_definition: str,
        spawn_baby: bool = False,
        first_spawn_count: int = 0,
        first_spawn_percent_chance: int = 0,
        second_spawn_percent_chance: int = 32,
        second_spawn_count: int = 0,
    ):
        """Spawn an entity on hit with specified chances.

        Args:
            spawn_definition: ID of the entity to spawn.
            spawn_baby: Whether the spawned entity should be a baby. Default is False.
            first_spawn_count: Number of entities to spawn in first spawn. Default is 0.
            first_spawn_percent_chance: Percentage chance for first spawn. Default is 0.
            second_spawn_percent_chance: Percentage chance for second spawn. Default is 32.
            second_spawn_count: Number of entities to spawn in second spawn. Default is 0.

        Returns:
            Self for method chaining.
        """
        self._component["on_hit"]["spawn_chance"] = {"spawn_definition": spawn_definition}

        if spawn_baby:
            self._component["on_hit"]["spawn_chance"]["spawn_baby"] = spawn_baby
        if first_spawn_count:
            self._component["on_hit"]["spawn_chance"]["first_spawn_count"] = first_spawn_count
        if first_spawn_percent_chance:
            self._component["on_hit"]["spawn_chance"]["first_spawn_percent_chance"] = first_spawn_percent_chance
        if second_spawn_percent_chance:
            self._component["on_hit"]["spawn_chance"]["second_spawn_percent_chance"] = second_spawn_percent_chance
        if second_spawn_count:
            self._component["on_hit"]["spawn_chance"]["second_spawn_count"] = second_spawn_count

        return self

    def stick_in_ground(self, shake_time: float):
        """Configure projectile to stick into the ground on hit.

        Args:
            shake_time: Time in seconds the projectile shakes when stuck in ground.

        Returns:
            Self for method chaining.
        """
        self._component["on_hit"]["stick_in_ground"] = {"shake_time": shake_time}
        return self

    @property
    def thrown_potion_effect(self):
        """Enable thrown potion effect.

        Returns:
            Self for method chaining.

        Note:
            According to Bedrock Wiki, exact behavior is unknown and this may crash Minecraft as it's probably only valid for thrown potions.
        """
        self._component["on_hit"]["thrown_potion_effect"] = {}
        return self


class EntityExplode(_BaseComponent):
    _identifier = "minecraft:explode"

    def __init__(
        self,
        breaks_blocks: bool = True,
        causes_fire: bool = False,
        destroy_affected_by_griefing: bool = False,
        fire_affected_by_griefing: bool = False,
        fuse_length: tuple[float, float] = [0.0, 0.0],
        fuse_lit: bool = False,
        max_resistance: int = 3.40282e38,
        power: int = 3,
        damage_scaling: float = 1.0,
        toggles_blocks: bool = False,
        knockback_scaling: float = 1.0,
        particle_effect: ExplosionParticleEffect = ExplosionParticleEffect.Explosion,
        sound_effect: str = "explode",
        negates_fall_damage: bool = False,
        allow_underwater: bool = True,
    ) -> None:
        """Defines how the entity explodes.

        Parameters:
            breaks_blocks (bool, optional): Description. Defaults to True.
            causes_fire (bool, optional): Description. Defaults to False.
            destroy_affected_by_griefing (bool, optional): Description. Defaults to False.
            fire_affected_by_griefing (bool, optional): Description. Defaults to False.
            fuse_length (tuple[float, float], optional): Description. Defaults to [0.0, 0.0].
            fuse_lit (bool, optional): Description. Defaults to False.
            max_resistance (int, optional): Description. Defaults to 3.40282e+38.
            power (int, optional): Description. Defaults to 3.
            damage_scaling (float, optional): Description. Defaults to 1.0.
            toggles_blocks (bool, optional): Description. Defaults to False.
            knockback_scaling (float, optional): Description. Defaults to 1.0.
            particle_effect (ExplosionParticleEffect, optional): Description. Defaults to ExplosionParticleEffect.Explosion.
            sound_effect (str, optional): Description. Defaults to 'explode'.
            negates_fall_damage (bool, optional): Description. Defaults to False.
            allow_underwater (bool, optional): Description. Defaults to True.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_explode
        """
        super().__init__("explode")

        if not breaks_blocks:
            self._add_field("breaks_blocks", breaks_blocks)
        if causes_fire:
            self._add_field("causes_fire", causes_fire)
        if destroy_affected_by_griefing:
            self._add_field("destroy_affected_by_griefing", destroy_affected_by_griefing)
        if fire_affected_by_griefing:
            self._add_field("fire_affected_by_griefing", fire_affected_by_griefing)
        if fuse_length != [0.0, 0.0]:
            self._add_field("fuse_length", fuse_length)
        if fuse_lit:
            self._add_field("fuse_lit", fuse_lit)
        if max_resistance != 3.40282e38:
            self._add_field("max_resistance", max_resistance)
        if power != 3:
            self._add_field("power", power)
        if damage_scaling != 1.0:
            self._add_field("damage_scaling", damage_scaling)
        if toggles_blocks != False:
            self._add_field("toggles_blocks", toggles_blocks)
        if knockback_scaling != 1.0:
            self._add_field("knockback_scaling", knockback_scaling)
        if particle_effect is not ExplosionParticleEffect.Explosion:
            self._add_field("particle_effect", particle_effect)
        if sound_effect != "explode":
            self._add_field("sound_effect", sound_effect)
        if negates_fall_damage != False:
            self._add_field("negates_fall_damage", negates_fall_damage)
        if allow_underwater != True:
            self._add_field("allow_underwater", allow_underwater)


class EntityMobEffect(_BaseComponent):
    _identifier = "minecraft:mob_effect"

    def __init__(
        self,
        mob_effect: MinecraftEffects,
        entity_filter: Filter,
        cooldown_time: int = 0,
        effect_range: float = 0.2,
        effect_time: int = 10,
        ambient: bool = False,
    ) -> None:
        """Applies a mob effect to entities that get within range.

        Parameters:
            mob_effect (MinecraftEffects): Description.
            entity_filter (Filter): Description.
            cooldown_time (int, optional): Description. Defaults to 0.
            effect_range (float, optional): Description. Defaults to 0.2.
            effect_time (int, optional): Description. Defaults to 10.
            ambient (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_mob_effect
        """
        super().__init__("mob_effect")
        self._add_field("mob_effect", mob_effect.value)
        self._add_field("entity_filter", entity_filter)

        if not cooldown_time == 0:
            self._add_field("cooldown_time", cooldown_time)
        if not effect_range == 0.2:
            self._add_field("effect_range", effect_range)
        if not effect_time == 10:
            self._add_field("effect_time", effect_time)
        if ambient:
            self._add_field("ambient", ambient)


class EntitySpawnEntity(_BaseComponent):
    _identifier = "minecraft:spawn_entity"

    def __init__(self) -> None:
        """Adds a timer after which this entity will spawn another entity or item (similar to vanilla's chicken's egg-laying behavior).

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_spawn_entity
        """
        super().__init__("spawn_entity")
        self._add_field("entities", [])

    def _template(
        self,
        identifier: str,
        spawn_type: str = "spawn_entity",
        spawn_event: str = "minecraft:entity_born",
        spawn_method: str = "born",
        spawn_sound: str = "plop",
        filters: Filter = None,
        max_wait_time: int = 600,
        min_wait_time: int = 300,
        num_to_spawn: int = 1,
        should_leash: bool = False,
        single_use: bool = False,
    ):
        self._component["entities"].append(
            {
                spawn_type: identifier,
                "spawn_event": (spawn_event if spawn_event != "minecraft:entity_born" else {}),
                "spawn_method": spawn_method if spawn_method != "born" else {},
                "spawn_sound": spawn_sound if spawn_sound != "plop" else {},
                "filters": filters if not filters is None else {},
                "max_wait_time": max_wait_time if max_wait_time != 600 else {},
                "min_wait_time": min_wait_time if min_wait_time != 300 else {},
                "num_to_spawn": num_to_spawn if num_to_spawn != 1 else {},
                "should_leash": should_leash if should_leash else {},
                "single_use": single_use if single_use else {},
            }
        )
        return self

    def spawn_entity(
        self,
        identifier: str,
        spawn_event: str = "minecraft:entity_born",
        spawn_method: str = "born",
        spawn_sound: str = "plop",
        filters: Filter = None,
        max_wait_time: int = 600,
        min_wait_time: int = 300,
        num_to_spawn: int = 1,
        should_leash: bool = False,
        single_use: bool = False,
    ):
        return self._template(
            identifier,
            "spawn_entity",
            spawn_event,
            spawn_method,
            spawn_sound,
            filters,
            max_wait_time,
            min_wait_time,
            num_to_spawn,
            should_leash,
            single_use,
        )

    def spawn_item(
        self,
        identifier: str,
        spawn_item_event: str = "minecraft:entity_born",
        spawn_method: str = "born",
        spawn_sound: str = "plop",
        filters: Filter = None,
        max_wait_time: int = 600,
        min_wait_time: int = 300,
        num_to_spawn: int = 1,
        should_leash: bool = False,
        single_use: bool = False,
    ):
        return self._template(
            identifier,
            "spawn_item",
            spawn_item_event,
            spawn_method,
            spawn_sound,
            filters,
            max_wait_time,
            min_wait_time,
            num_to_spawn,
            should_leash,
            single_use,
        )


class EntityLoot(_BaseComponent):
    _identifier = "minecraft:loot"

    def __init__(self, loot_table: LootTable | str) -> None:
        """Sets the loot table for what items this entity drops upon death.

        Parameters:
            loot_table (LootTable | str): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_loot
        """
        super().__init__("loot")
        self._add_field(
            "table",
            loot_table.table_path if isinstance(loot_table, LootTable) else loot_table,
        )


class EntityShooter(_BaseComponent):
    _identifier = "minecraft:shooter"

    def __init__(
        self,
        identifier: Identifier,
        magic: bool = False,
        power: float = 0.0,
        aux_value: int = -1,
    ) -> None:
        """Defines the entity's ranged attack behavior. The "minecraft:behavior.ranged_attack" goal uses this component to determine which projectiles to shoot.

        Parameters:
            identifier (Identifier): Description.
            magic (bool, optional): Description. Defaults to False.
            power (float, optional): Description. Defaults to 0.0.
            aux_value (int, optional): Description. Defaults to -1.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_shooter
        """
        super().__init__("shooter")
        self._add_field("def", identifier)
        if magic:
            self._add_field("magic", magic)
        if power != 0:
            self._add_field("power", power)
        if aux_value != -1:
            self._add_field("aux_value", aux_value)


class EntityInsideBlockNotifier(_BaseComponent):
    _identifier = "minecraft:inside_block_notifier"

    def __init__(self) -> None:
        """Verifies whether the entity is inside any of the listed blocks.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_inside_block_notifier
        """
        super().__init__("inside_block_notifier")
        self._add_field("block_list", [])

    def blocks(
        self,
        block_name: MinecraftBlockDescriptor | Identifier,
        entered_block_event: str = None,
        exited_block_event: str = None,
    ):
        if not isinstance(block_name, (MinecraftBlockDescriptor, str)):
            raise TypeError(
                f"block_name must be a MinecraftBlockDescriptor or Identifier instance. Component {self._identifier}[{block_name}]."
            )

        self._component["block_list"].append(
            {
                "block": {
                    "name": (str(block_name)),
                    "states": (
                        block_name.states
                        if isinstance(block_name, MinecraftBlockDescriptor) and block_name.states != ""
                        else {}
                    ),
                }
            }
        )
        if not entered_block_event is None:
            self._component["block_list"][-1]["entered_block_event"] = {
                "event": entered_block_event,
                "target": FilterSubject.Self,
            }
        if not exited_block_event is None:
            self._component["block_list"][-1]["exited_block_event"] = {
                "event": exited_block_event,
                "target": FilterSubject.Self,
            }
        return self


class EntityTransformation(_BaseComponent):
    _identifier = "minecraft:transformation"

    def __init__(
        self,
        into: Identifier,
        transform_event: str = None,
        drop_equipment: bool = False,
        drop_inventory: bool = False,
        keep_level: bool = False,
        keep_owner: bool = False,
        preserve_equipment: bool = False,
    ) -> None:
        """Defines an entity's transformation from the current definition into another.

        Parameters:
            into (Identifier): Description.
            transform_event (str, optional): Description. Defaults to None.
            drop_equipment (bool, optional): Description. Defaults to False.
            drop_inventory (bool, optional): Description. Defaults to False.
            keep_level (bool, optional): Description. Defaults to False.
            keep_owner (bool, optional): Description. Defaults to False.
            preserve_equipment (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_transformation
        """
        super().__init__("transformation")
        self._add_field(
            "into",
            into + f"<{transform_event}>" if not transform_event is None else into,
        )
        self._add_field("add", {"component_groups": []})
        self._add_field("delay", {})
        if drop_equipment:
            self._add_field("drop_equipment", drop_equipment)
        if drop_inventory:
            self._add_field("drop_inventory", drop_inventory)
        if keep_level:
            self._add_field("keep_level", keep_level)
        if keep_owner:
            self._add_field("keep_owner", keep_owner)
        if preserve_equipment:
            self._add_field("preserve_equipment", preserve_equipment)

    def add(self, *component_groups: str):
        self._component["add"]["component_groups"].extend(component_groups)
        return self

    def begin_transform_sound(self, sound: str):
        self._add_field("begin_transform_sound", sound)
        return self

    def transformation_sound(self, sound: str):
        self._add_field("transformation_sound", sound)
        return self

    def delay(
        self,
        block_assist_chance: float = 0.0,
        block_chance: int = 0,
        block_max: int = 0,
        block_radius: int = 0,
        value: int = 0,
        block_type: list[Block | Identifier] = [],
    ):
        if not block_assist_chance == 0.0:
            self._component["delay"]["block_assist_chance"] = block_assist_chance
        if not block_chance == 0:
            self._component["delay"]["block_chance"] = block_chance
        if not block_max == 0:
            self._component["delay"]["block_max"] = block_max
        if not block_radius == 0:
            self._component["delay"]["block_radius"] = block_radius
        if not value == 0:
            self._component["delay"]["value"] = value
        if len(block_type) > 0:
            if not all(isinstance(block, (Block, Identifier)) for block in block_type):
                raise TypeError(
                    f"block_type must be a list of Block or Identifier instances. Component [{self._identifier}]."
                )

            self._component["delay"]["block_type"] = [str(block) for block in block_type]

        return self


class EntityNPC(_BaseComponent):
    _identifier = "minecraft:npc"

    def __init__(self, skin_list: list[int]) -> None:
        """Allows an entity to be an NPC.

        Parameters:
            skin_list (list[int]): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_npc
        """
        super().__init__("npc")
        self._add_field("npc_data", {"skin_list": [{"variant": i} for i in skin_list]})

    def portrait_offsets(self, translate: Coordinates, scale: Coordinates):
        self._component["npc_data"]["portrait_offsets"] = {
            "translate": translate,
            "scale": scale,
        }
        return self

    def picker_offsets(self, translate: Coordinates, scale: Coordinates):
        self._component["npc_data"]["picker_offsets"] = {
            "translate": translate,
            "scale": scale,
        }
        return self


class EntityEquipment(_BaseComponent):
    _identifier = "minecraft:equipment"

    def __init__(self, table: LootTable | str) -> None:
        """Sets the Equipment table to use for this Entity.

        Parameters:
            table (LootTable | str): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_equipment
        """
        super().__init__("equipment")
        self._add_field(
            "table",
            table.table_path if isinstance(table, LootTable) else table,
        )

    def slot_drop_chance(self, slot: str, drop_chance: float = None):
        """Adds a chance to drop an equipped item from a specific slot.

        Parameters:
            slot (str): The equipment slot name.
            drop_chance (float, optional): The chance to drop the equipped item (0.0 to 1.0). If None, it just adds the slot string.

        Returns:
            EntityEquipment: Returns the EntityEquipment component to allow for method chaining.
        """
        if drop_chance is None:
            self._get_field("slot_drop_chance", []).append(slot)
        else:
            self._get_field("slot_drop_chance", []).append({"slot": slot, "drop_chance": clamp(drop_chance, 0, 1)})
        return self


class EntityEquipItem(_BaseComponent):
    _identifier = "minecraft:equip_item"

    def __init__(
        self,
        can_wear_armor: bool = False,
        excluded_items: list[MinecraftItemDescriptor] = [],
    ) -> None:
        """Compels the entity to equip desired equipment.

        Parameters:
            can_wear_armor (bool, optional): Description. Defaults to False.
            excluded_items (list[MinecraftItemDescriptor], optional): Description. Defaults to [].

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_equip_item
        """
        super().__init__("equip_item")
        if can_wear_armor:
            self._add_field("can_wear_armor", can_wear_armor)
        if excluded_items:
            if not all(isinstance(item, MinecraftItemDescriptor) for item in excluded_items):
                raise TypeError(
                    f"excluded_items must be a list of MinecraftItemDescriptor instances. Component [{self._identifier}]."
                )
            self._add_field("excluded_items", excluded_items)


class EntityFireImmune(_BaseComponent):
    _identifier = "minecraft:fire_immune"

    def __init__(self) -> None:
        """Allows an entity to take 0 damage from fire.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_fire_immune
        """
        super().__init__("fire_immune")


class EntitySensor(_BaseComponent):
    _identifier = "minecraft:entity_sensor"

    def __init__(self, relative_range: bool = True, find_players_only: bool = False) -> None:
        super().__init__("entity_sensor")
        self._add_field("subsensors", [])
        if not relative_range:
            self._add_field("relative_range", relative_range)
        if find_players_only:
            self._add_field("find_players_only", find_players_only)

    def add_sensor(
        self,
        event: str,
        event_filters: Filter,
        maximum_count: int = -1,
        minimum_count: int = -1,
        require_all: bool = False,
        range: range = [10, 10],
        cooldown: int = -1,
        y_offset: float = 0.0,
    ):
        """A component that initiates an event when a set of conditions are met by other entities within the defined range.

        Parameters:
            event (str): Event to initiate when the conditions are met.
            event_filter (Filter): The set of conditions that must be satisfied to initiate the event.
            maximum_count (int, optional): The maximum number of entities that must pass the filter conditions for the event to send. Defaults to -1.
            minimum_count (int, optional): The minimum number of entities that must pass the filter conditions for the event to send. Defaults to -1.
            relative_range (bool, optional): If true, the sensor range is additive on top of the entity's size. Defaults to True.
            require_all (bool, optional): If true, requires all nearby entities to pass the filter conditions for the event to send. Defaults to False.
            range (range, optional): The maximum horizontal and vertical distance another entity can be from this and have the filters checked against it. Defaults to (10, 10).
            cooldown (int, optional): How many seconds should elapse before the subsensor can once again sense for entities. The cooldown is applied on top of the base 1 tick (0.05 seconds) delay. Negative values will result in no cooldown being used. Defaults to -1.
            y_offset (float, optional): Vertical offset applied to the entity's position when computing the distance from other entities.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_entity_sensor
        """
        sensor = {}
        sensor["event"] = event
        sensor["event_filters"] = event_filters
        if maximum_count != -1:
            sensor["maximum_count"] = maximum_count
        if minimum_count != -1:
            sensor["minimum_count"] = minimum_count
        if require_all:
            sensor["require_all"] = require_all
        if range != (10, 10):
            sensor["range"] = range if isinstance(range, (tuple, list)) else (range, range)
        if cooldown != -1:
            sensor["cooldown"] = cooldown
        if y_offset != 0.0:
            sensor["y_offset"] = y_offset
        self._component["subsensors"].append(sensor)

        return self


class EntityAmbientSoundInterval(_BaseComponent):
    _identifier = "minecraft:ambient_sound_interval"

    def __init__(self, event_name: str, sound_delay: tuple[float, float] = (8, 16)) -> None:
        """A component that will set the entity's delay between playing its ambient sound.

        Parameters:
            event_name (str): Level sound event to be played as the ambient sound.
            sound_delay (tuple[float, float], optional): Minimum and maximum delay in seconds between playing the ambient sound. Defaults to (8, 16).

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_ambient_sound_interval
        """
        super().__init__("ambient_sound_interval")

        if sound_delay != (8, 16):
            if not isinstance(sound_delay, (tuple, list)):
                raise TypeError(f"sound_delay must be a tuple or list of two floats. Component [{self._identifier}].")
            if len(sound_delay) != 2:
                raise ValueError(f"sound_delay must have exactly two elements. Component [{self._identifier}].")
            if not all(isinstance(delay, (int, float)) for delay in sound_delay):
                raise TypeError(f"Both elements of sound_delay must be numbers. Component [{self._identifier}].")
            if sound_delay[0] < 0 or sound_delay[1] < 0:
                raise ValueError(f"Both elements of sound_delay must be non-negative. Component [{self._identifier}].")
            if sound_delay[0] > sound_delay[1]:
                raise ValueError(
                    f"The first element of sound_delay must be less than or equal to the second element. Component [{self._identifier}]."
                )
            self._add_field("range", sound_delay[0])
            self._add_field("value", sound_delay[1])
            self._add_field("event_names", [])

        self._add_field("event_name", event_name)

    def add_event(self, event_name: str, condition: Molang):
        """Adds an additional sound event to be played when the ambient sound plays, with a Molang condition for it to play.

        Parameters:
            event_name (str): Level sound event to be played as the additional sound.
            condition (Molang): Molang condition that must be satisfied for the additional sound to play when the ambient sound plays.
        """
        self._component["event_names"].append({"event_name": event_name, "condition": condition})
        return self


class EntityUnderwaterMovement(_BaseComponent):
    _identifier = "minecraft:underwater_movement"

    def __init__(self, value: int) -> None:
        """A component that defines the entity's movement speed while underwater in block/tick

        Parameters:
            value (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_underwater_movement
        """
        super().__init__("underwater_movement")
        self._add_field("value", value)


class EntityMovementMeters(_BaseComponent):
    _identifier = "minecraft:movement"

    def __init__(self, value: float, max: float = None) -> None:
        """A component that defines the entity's movement speed in meters per second.

        Parameters:
            value (float): Description.
            max (float, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_movement
        """
        super().__init__("movement")
        self._add_field("value", round(0.152 * math.sqrt(value), 2))
        if not max is None:
            self._add_field("max", round(0.152 * math.sqrt(max), 2))


class EntityInputGroundControlled(_BaseComponent):
    _identifier = "minecraft:input_ground_controlled"

    def __init__(self) -> None:
        """Allows a ridable entity the ability to be controlled using keyboard controls when ridden by a player.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_input_ground_controlled
        """
        super().__init__("input_ground_controlled")


class EntityWaterMovement(_BaseComponent):
    _identifier = "minecraft:water_movement"

    def __init__(self, drag_factor: float = 0.8) -> None:
        """Defines the speed with which an entity can move through water.

        Parameters:
            drag_factor (float, optional): Description. Defaults to 0.8.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_water_movement
        """
        super().__init__("water_movement")
        if not drag_factor == 0.8:
            self._add_field("drag_factor", drag_factor)


class EntityAngry(_BaseComponent):
    _identifier = "minecraft:angry"

    def __init__(
        self,
        angry_sound: str = None,
        broadcast_anger: bool = False,
        broadcast_anger_on_attack: bool = False,
        broadcast_anger_on_being_attacked: bool = False,
        broadcast_filters: Filter = None,
        broadcast_range: int = 20,
        broadcast_targets: list[str] = [],
        duration: Seconds = 25,
        duration_delta: Seconds = 0,
        filters: Filter = None,
        sound_interval: list[Seconds] = [0, 0],
    ) -> None:
        """Defines the entity's 'angry' state using a timer.

        Parameters:
            angry_sound (str, optional): Description. Defaults to None.
            broadcast_anger (bool, optional): Description. Defaults to False.
            broadcast_anger_on_attack (bool, optional): Description. Defaults to False.
            broadcast_anger_on_being_attacked (bool, optional): Description. Defaults to False.
            broadcast_filters (Filter, optional): Description. Defaults to None.
            broadcast_range (int, optional): Description. Defaults to 20.
            broadcast_targets (list[str], optional): Description. Defaults to [].
            duration (Seconds, optional): Description. Defaults to 25.
            duration_delta (Seconds, optional): Description. Defaults to 0.
            filters (Filter, optional): Description. Defaults to None.
            sound_interval (list[Seconds], optional): Description. Defaults to [0, 0].

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_angry
        """
        super().__init__("angry")
        if not angry_sound is None:
            self._add_field("angry_sound", angry_sound)
        if broadcast_anger:
            self._add_field("broadcast_anger", broadcast_anger)
        if broadcast_anger_on_attack:
            self._add_field("broadcast_anger_on_attack", broadcast_anger_on_attack)
        if broadcast_anger_on_being_attacked:
            self._add_field("broadcast_anger_on_being_attacked", broadcast_anger_on_being_attacked)
        if not broadcast_filters is None:
            self._add_field("broadcast_filters", broadcast_filters)
        if broadcast_range != 10:
            self._add_field("broadcast_range", broadcast_range)
        if not broadcast_targets == []:
            self._add_field("broadcast_targets", broadcast_targets)
        if duration != 25:
            self._add_field("duration", duration)
        if duration_delta != 0:
            self._add_field("duration_delta", duration_delta)
        if not filters is None:
            self._add_field("filters", filters)
        if not sound_interval == [0, 0]:
            self._add_field("sound_interval", sound_interval)

    def calm_event(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("calm_event", {"event": event, "target": target.value})
        return self


class EntityFlyingSpeed(_BaseComponent):
    _identifier = "minecraft:flying_speed"

    def __init__(self, value: int) -> None:
        """Sets the speed, in Blocks, at which the entity flies.

        Parameters:
            value (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_flying_speed
        """
        super().__init__("flying_speed")
        self._add_field("value", value)


class EntityInteract(_BaseComponent):
    _identifier = "minecraft:interact"

    def __init__(self) -> None:
        """Defines the interactions that can be used with an entity.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_interact
        """
        super().__init__("interact")
        self._add_field("interactions", [])

    def add_interaction(
        self,
        event: str,
        filter: Filter = None,
        add_items: str = None,
        cooldown: float = 0.0,
        cooldown_after_being_attacked: float = 0.0,
        drop_item_slot: int | Slots = -1,
        equip_item_slot: int | Slots = -1,
        health_amount: int = 0,
        hurt_item: int = 0,
        interact_text: str = None,
        play_sounds: str = None,
        spawn_entities: Identifier = None,
        spawn_items: str = None,
        swing: bool = True,
        transform_to_item: str = None,
        use_item: bool = False,
        vibration: Vibrations = Vibrations.EntityInteract,
        repair_entity_item: tuple[Slots, int] = None,
        # entity_act: str = None,
    ):
        """Adds an interaction to the entity.

        Parameters:
            event (str): Event to trigger when the interaction occurs.
            filter (Filter, optional): Filter to determine which entities can interact with this entity. Defaults to None.
            add_items (str, optional): File path, relative to the behavior Pack's path, to the loot table file. Defaults to None.
            cooldown (float, optional): Time in seconds before this entity can be interacted with again. Defaults to 0.0.
            cooldown_after_being_attacked (float, optional): Time in seconds before this entity can be interacted with after being attacked. Defaults to 0.0.
            drop_item_slot (int | Slots, optional): Slot from which the item will be dropped when interacting with this entity. Defaults to -1.
            equip_item_slot (int | Slots, optional): Slot from which the item will be equipped when interacting with this entity. Defaults to -1.
            health_amount (int, optional): The amount of health this entity will recover or hurt when interacting with this item. Negative values will harm the entity. Defaults to 0.
            hurt_item (int, optional): The amount of damage the item will take when used to interact with this entity. A value of 0 means the item won't lose durability. Defaults to 0.
            interact_text (str, optional): Text to show while playing with touch-screen controls when the player is able to interact in this way with this entity. Defaults to None.
            play_sounds (str, optional): One or more sound identifiers to play when the interaction occurs. Defaults to None.
            spawn_entities (str, optional): Entity to spawn when the interaction occurs. Defaults to None.
            spawn_items (str, optional): Loot table with items to drop on the ground upon successful interaction. Defaults to None.
            swing (bool, optional): If true, the player will do the 'swing' animation when interacting with this entity. Defaults to False.
            transform_to_item (str, optional): The item used will transform to this item upon successful interaction. Format: itemName:auxValue. Defaults to None.
            use_item (bool, optional): If true, the interaction will use an item. Defaults to False.
            vibration (str, optional): Vibration to emit when the interaction occurs. Admitted values are entity_interact (used by default), shear, and none (no vibration emitted). Defaults to None.
            repair_entity_item (tuple[Slots, int], optional): Slot and amount to repair the item used to interact with this entity. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_interact?view=minecraft-bedrock-stable#parameter
        """

        interaction = {
            "on_interact": {
                "filters": filter if not filter is None else {},
                "event": event,
            }
        }
        if not add_items is None:
            interaction["add_items"] = {"table": add_items}
        if not cooldown == 0.0:
            interaction["cooldown"] = cooldown
        if not cooldown_after_being_attacked == 0.0:
            interaction["cooldown_after_being_attacked"] = cooldown_after_being_attacked
        if not drop_item_slot == -1:
            interaction["drop_item_slot"] = drop_item_slot
        if not equip_item_slot == -1:
            interaction["equip_item_slot"] = equip_item_slot
        if not health_amount == 0:
            interaction["health_amount"] = health_amount
        if not hurt_item == 0:
            interaction["hurt_item"] = hurt_item
        if not interact_text is None:
            interaction["interact_text"] = interact_text
        if not play_sounds is None:
            interaction["play_sounds"] = play_sounds
        if not spawn_entities is None:
            interaction["spawn_entities"] = spawn_entities
        if not spawn_items is None:
            interaction["spawn_items"] = {"table": spawn_items}
        if not swing:
            interaction["swing"] = swing
        if not transform_to_item is None:
            interaction["transform_to_item"] = transform_to_item
        if use_item:
            interaction["use_item"] = use_item
        if not vibration is Vibrations.EntityInteract:
            interaction["vibration"] = vibration.value
        if not repair_entity_item is None:
            interaction["repair_entity_item"] = {
                "slot": repair_entity_item[0],
                "repair_amount": repair_entity_item[1],
            }

        self._component["interactions"].append(interaction)
        return self

    def particle_on_start(
        self,
        particle_type: str,
        particle_offset_towards_interactor: bool = False,
        particle_y_offset: float = 0.0,
    ):
        """Adds a particle effect when the interaction starts.

        Parameters:
            particle_type (str): Name of the particle system to run.
            particle_offset_towards_interactor (bool, optional): Whether or not the particle will appear closer to who performed the interaction. Defaults to False.
            particle_y_offset (float, optional): Vertical offset of the particle system. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_interact?view=minecraft-bedrock-stable#particle_on_start
        """

        # add this to the last interaction, if none exists, raise an error
        if not self._component["interactions"]:
            raise ValueError("No interaction found to add the particle to.")
        else:
            self._component["interactions"][-1]["particle_on_start"] = {
                "particle_type": particle_type,
                "particle_offset_towards_interactor": particle_offset_towards_interactor,
                "particle_y_offset": particle_y_offset,
            }


class EntityAngerLevel(_BaseComponent):
    _identifier = "minecraft:anger_level"

    def __init__(
        self,
        anger_decrement_interval: Seconds = 1.0,
        angry_boost: int = 20,
        angry_threshold: int = 80,
        default_annoyingness: int = 0,
        default_projectile_annoyingness: int = 0,
        max_anger: int = 100,
        nuisance_filter: Filter = None,
        on_increase_sounds: list[dict[str, str]] = [],
        remove_targets_below_angry_threshold: bool = True,
    ) -> None:
        """Compels the entity to track anger towards a set of nuisances.

        Parameters:
            anger_decrement_interval (Seconds, optional): Description. Defaults to 1.0.
            angry_boost (int, optional): Description. Defaults to 20.
            angry_threshold (int, optional): Description. Defaults to 80.
            default_annoyingness (int, optional): Description. Defaults to 0.
            default_projectile_annoyingness (int, optional): Description. Defaults to 0.
            max_anger (int, optional): Description. Defaults to 100.
            nuisance_filter (Filter, optional): Description. Defaults to None.
            on_increase_sounds (list[dict[str, str]], optional): Description. Defaults to [].
            remove_targets_below_angry_threshold (bool, optional): Description. Defaults to True.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_anger_level
        """
        super().__init__("anger_level")

        if anger_decrement_interval != 1.0:
            self._add_field("anger_decrement_interval", anger_decrement_interval)
        if angry_boost != 20:
            self._add_field("angry_boost", angry_boost)
        if angry_threshold != 80:
            self._add_field("angry_threshold", angry_threshold)
        if default_annoyingness != 0:
            self._add_field("default_annoyingness", default_annoyingness)
        if default_projectile_annoyingness != 0:
            self._add_field("default_projectile_annoyingness", default_projectile_annoyingness)
        if max_anger != 100:
            self._add_field("max_anger", max_anger)
        if not nuisance_filter is None:
            self._add_field("nuisance_filter", nuisance_filter)
        if not on_increase_sounds == []:
            self._add_field("on_increase_sounds", on_increase_sounds)
        if not remove_targets_below_angry_threshold:
            self._add_field(
                "remove_targets_below_angry_threshold",
                remove_targets_below_angry_threshold,
            )


class EntityCanJoinRaid(_BaseComponent):
    _identifier = "minecraft:can_join_raid"

    def __init__(self) -> None:
        """Determines that a given entity can join an existing raid.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_can_join_raid
        """
        super().__init__("can_join_raid")


class EntityTameable(_BaseComponent):
    _identifier = "minecraft:tameable"

    def __init__(
        self,
        probability: float = 1.0,
    ) -> None:
        """Defines the rules for an entity to be tamed by the player.

        Parameters:
            probability (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_tameable
        """
        super().__init__("tameable")

        if probability != 1.0:
            self._add_field("probability", probability)

        self._add_field("tame_items", [])

    def add_tame_item(
        self,
        item: MinecraftItemDescriptor | Identifier,
        result_item: MinecraftItemDescriptor | Identifier = None,
    ):
        """Adds an item to the list of items that can be used to tame the entity.

        Parameters:
            item (str): The item to add to the list of items that can be used to tame the entity.
            result_item (str, optional): The item that the tame item will transform into upon successful taming. Defaults to None.

            Returns:
                Tameable: Returns the Tameable component to allow for method chaining.
        """
        if result_item is None:
            self._component["tame_items"].append(item)
        else:
            self._component["tame_items"].append(
                {
                    "item": item,
                    "result_item": result_item,
                }
            )
        return self

    def tame_event(self, event: str, target: FilterSubject = FilterSubject.Self):
        """Sets the event to initiate when the entity becomes tamed.

        Parameters:
            event (str): Event to initiate when the entity becomes tamed.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

            Returns:
                Tameable: Returns the Tameable component to allow for method chaining.
        """
        self._add_field("tame_event", {"event": event, "target": target})
        return self


class EntityAgeable(_BaseComponent):
    _identifier = "minecraft:ageable"

    def __init__(
        self,
        duration: Seconds = 1200.0,
        interact_filters: Filter = None,
        result_item: str = None,
    ) -> None:
        """Adds a timer for the entity to grow up. The timer can be accelerated by giving the entity items it likes as defined by feed_items.

        Parameters:
            duration (Seconds, optional): Description. Defaults to 1200.0.
            interact_filters (Filter, optional): Description. Defaults to None.
            result_item (str, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_ageable
        """
        super().__init__("ageable")
        self._component["feed_items"] = []

        if duration != 1200.0:
            self._add_field("duration", duration)
        if not interact_filters is None:
            self._add_field("interact_filters", interact_filters)
        if not result_item is None:
            self._add_field("result_item", result_item)

    def drop_item(self, *items: str):
        """Adds an item to the list of items the entity drops when it grows up.

        Parameters:
            item (str): The item to add to the list of items the entity drops when it grows up.

            Returns:
                Ageable: Returns the Ageable component to allow for method chaining.
        """
        self._add_field("drop_items", items)
        return self

    def feed_items(self, items: list[str]):
        """Adds an item to the list of items the entity can be fed.

        Parameters:
            item (str): The item to add to the list of items the entity can be fed.

            Returns:
                Ageable: Returns the Ageable component to allow for method chaining.
        """
        self._component["feed_items"].extend([str(i) for i in items])
        return self

    def feed_item_growth(self, item: str, growth: float):
        """Adds an item to the list of items the entity can be fed.

        Parameters:
            item (str): The item to add to the list of items the entity can be fed.
            growth (float): The amount of growth to add to the entity when fed this item.

            Returns:
                Ageable: Returns the Ageable component to allow for method chaining.
        """
        self._component["feed_items"].append({"item": str(item), "growth": clamp(growth, 0, 1)})
        return self

    def grow_up(self, event: str, target: FilterSubject = FilterSubject.Self):
        """Sets the event to initiate when the entity grows up.

        Parameters:
            event (str): Event to initiate when the entity grows up.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

            Returns:
                Ageable: Returns the Ageable component to allow for method chaining.
        """
        self._add_field("grow_up", {"event": event, "target": target})
        return self

    def pause_growth_items(self, items: list[MinecraftItemDescriptor | Identifier]):
        """Pauses the growth of the entity when given specific items.

        Parameters:
            items (list[MinecraftItemDescriptor | Identifier]): The items that will pause the entity's growth.

            Returns:
                Ageable: Returns the Ageable component to allow for method chaining.
        """
        self._add_field("pause_growth_items", [str(i) for i in items])
        return self

    def reset_growth_items(self, items: list[MinecraftItemDescriptor | Identifier]):
        """Resets the growth of the entity when given specific items.

        Parameters:
            items (list[MinecraftItemDescriptor | Identifier]): The items that will reset the entity's growth.

        Returns:
            Ageable: Returns the Ageable component to allow for method chaining.
        """
        self._add_field("reset_growth_items", [str(i) for i in items])


class EntityInventory(_BaseComponent):
    _identifier = "minecraft:inventory"

    def __init__(
        self,
        additional_slots_per_strength: int = 0,
        can_be_siphoned_from: bool = False,
        container_type: ContainerType = ContainerType.Inventory,
        inventory_size: int = 5,
        private: bool = False,
        restrict_to_owner: bool = False,
    ) -> None:
        """Defines how an entity's inventory is managed.

        Parameters:
            additional_slots_per_strength (int, optional): Description. Defaults to 0.
            can_be_siphoned_from (bool, optional): Description. Defaults to False.
            container_type (ContainerType, optional): Description. Defaults to ContainerType.Inventory.
            inventory_size (int, optional): Description. Defaults to 5.
            private (bool, optional): Description. Defaults to False.
            restrict_to_owner (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_inventory
        """
        super().__init__("inventory")

        self._add_field("container_type", container_type)
        if additional_slots_per_strength != 0:
            self._add_field("additional_slots_per_strength", additional_slots_per_strength)
        if can_be_siphoned_from:
            self._add_field("can_be_siphoned_from", can_be_siphoned_from)
        if inventory_size != 5:
            self._add_field("inventory_size", inventory_size)
        if private:
            self._add_field("private", private)
        if restrict_to_owner:
            self._add_field("restrict_to_owner", restrict_to_owner)


class EntityDashAction(_BaseComponent):
    _identifier = "minecraft:dash_action"

    def __init__(
        self,
        direction: Literal["entity", "passenger"] = "entity",
        cooldown_time: Seconds = 1.0,
        horizontal_momentum: float = 1.0,
        vertical_momentum: float = 1.0,
        can_dash_underwater: bool = False,
    ) -> None:
        """Determines a rideable entity's ability to dash.

        Parameters:
            direction (Literal['entity', 'passenger'], optional): Description. Defaults to 'entity'.
            cooldown_time (Seconds, optional): Description. Defaults to 1.0.
            horizontal_momentum (float, optional): Description. Defaults to 1.0.
            vertical_momentum (float, optional): Description. Defaults to 1.0.
            can_dash_underwater (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_dash_action
        """
        super().__init__("dash_action")

        if direction != "entity":
            self._add_field("direction", direction)
        if cooldown_time != 1.0:
            self._add_field("cooldown_time", cooldown_time)
        if horizontal_momentum != 1.0:
            self._add_field("horizontal_momentum", horizontal_momentum)
        if vertical_momentum != 1.0:
            self._add_field("vertical_momentum", vertical_momentum)
        if can_dash_underwater:
            self._add_field("can_dash_underwater", can_dash_underwater)


class EntityBreathable(_BaseComponent):
    _identifier = "minecraft:breathable"

    def __init__(
        self,
        breathes_air: bool = True,
        breathes_lava: bool = True,
        breathes_solids: bool = False,
        breathes_water: bool = False,
        generates_bubbles: bool = True,
        inhale_time: Seconds = 0.0,
        suffocate_time: Seconds = -20,
        total_supply: Seconds = 15,
        can_dehydrate: bool = False,
        breathe_blocks: list[MinecraftBlockDescriptor] = [],
        non_breathe_blocks: list[MinecraftBlockDescriptor] = [],
    ) -> None:
        """Defines which blocks an entity can breathe in and defines the ability to suffocate in those blocks.

        Parameters:
            breathes_air (bool, optional): Description. Defaults to True.
            breathes_lava (bool, optional): Description. Defaults to True.
            breathes_solids (bool, optional): Description. Defaults to False.
            breathes_water (bool, optional): Description. Defaults to False.
            generates_bubbles (bool, optional): Description. Defaults to True.
            inhale_time (Seconds, optional): Description. Defaults to 0.0.
            suffocate_time (Seconds, optional): Description. Defaults to -20.
            total_supply (Seconds, optional): Description. Defaults to 15.
            can_dehydrate (bool, optional): Description. Defaults to False.
            breathe_blocks (list[MinecraftBlockDescriptor], optional): Description. Defaults to [].
            non_breathe_blocks (list[MinecraftBlockDescriptor], optional): Description. Defaults to [].

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_breathable
        """
        super().__init__("breathable")

        if not breathes_air:
            self._add_field("breathes_air", breathes_air)
        if not breathes_lava:
            self._add_field("breathes_lava", breathes_lava)
        if breathes_solids:
            self._add_field("breathes_solids", breathes_solids)
        if breathes_water:
            self._add_field("breathes_water", breathes_water)
        if not generates_bubbles:
            self._add_field("generates_bubbles", generates_bubbles)
        if inhale_time != 0.0:
            self._add_field("inhale_time", inhale_time)
        if suffocate_time != -20:
            self._add_field("suffocate_time", suffocate_time)
        if total_supply != 15:
            self._add_field("total_supply", total_supply)
        if not breathe_blocks == []:
            self._add_field("breathe_blocks", breathe_blocks)
        if not non_breathe_blocks == []:
            self._add_field("non_breathe_blocks", non_breathe_blocks)
        if can_dehydrate:
            self._add_field("can_dehydrate", can_dehydrate)


class EntityVariableMaxAutoStep(_BaseComponent):
    _identifier = "minecraft:variable_max_auto_step"

    def __init__(
        self,
        base_value: float = 0.5625,
        controlled_value: float = 0.5625,
        jump_prevented_value: float = 0.5625,
    ) -> None:
        """Allows entities have a maximum auto step height that is different depending on whether they are on a block that prevents jumping.

        Parameters:
            base_value (float, optional): Description. Defaults to 0.5625.
            controlled_value (float, optional): Description. Defaults to 0.5625.
            jump_prevented_value (float, optional): Description. Defaults to 0.5625.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_variable_max_auto_step
        """
        super().__init__("variable_max_auto_step")

        if base_value != 0.5625:
            self._add_field("base_value", base_value)
        if controlled_value != 0.5625:
            self._add_field("controlled_value", controlled_value)
        if jump_prevented_value != 0.5625:
            self._add_field("jump_prevented_value", jump_prevented_value)


class EntityBuoyant(_BaseComponent):
    _identifier = "minecraft:buoyant"

    def __init__(
        self,
        liquid_blocks: list[MinecraftBlockDescriptor],
        apply_gravity: bool = True,
        base_buoyancy: float = 1.0,
        big_wave_probability: float = 0.03,
        big_wave_speed: float = 10.0,
        drag_down_on_buoyancy_removed: float = 0.0,
        movement_type: Literal["waves", "bobbing", "none"] = "waves",
        can_auto_step_from_liquid: bool = False,
    ) -> None:
        """Allows an entity to float on the specified liquid blocks.

        Parameters:
            liquid_blocks (list[MinecraftBlockDescriptor]): Description.
            apply_gravity (bool, optional): Description. Defaults to True.
            base_buoyancy (float, optional): Description. Defaults to 1.0.
            big_wave_probability (float, optional): Description. Defaults to 0.03.
            big_wave_speed (float, optional): Description. Defaults to 10.0.
            drag_down_on_buoyancy_removed (float, optional): Description. Defaults to 0.0.
            movement_type (Literal["waves", "bobbing", "none"], optional): Description. Defaults to "waves".
            can_auto_step_from_liquid (bool, optional): Defines whether the entity can move out of a liquid block to a neighboring solid block if pushed against it. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_buoyant
        """
        super().__init__("buoyant")

        self._add_field("liquid_blocks", list(map(str, liquid_blocks)))
        if not apply_gravity:
            self._add_field("apply_gravity", apply_gravity)
        if base_buoyancy != 1.0:
            self._add_field("base_buoyancy", clamp(base_buoyancy, 0, 1))
        if drag_down_on_buoyancy_removed != 0.0:
            self._add_field("drag_down_on_buoyancy_removed", drag_down_on_buoyancy_removed)
        if movement_type != "waves":
            self._add_field("movement_type", movement_type)

        if movement_type == "waves":
            if big_wave_probability != 0.03:
                self._add_field("big_wave_probability", big_wave_probability)
            if big_wave_speed != 10.0:
                self._add_field("big_wave_speed", big_wave_speed)


class EntityLavaMovement(_BaseComponent):
    _identifier = "minecraft:lava_movement"

    def __init__(self, value: float) -> None:
        """Defines the speed with which an entity can move through lava.

        Parameters:
            value (float): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_lava_movement
        """
        super().__init__("lava_movement")
        self._add_field("value", value)


class EntityExperienceReward(_BaseComponent):
    _identifier = "minecraft:experience_reward"

    def __init__(
        self,
        on_bred: int | float | Molang = 0,
        on_death: int | float | Molang = 0,
    ) -> None:
        """Defines the amount of experience rewarded when the entity dies or is successfully bred.

        Parameters:
            on_bred (int | float | Molang, optional): Description. Defaults to 0.
            on_death (int | float | Molang, optional): Description. Defaults to 0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_experience_reward
        """
        super().__init__("experience_reward")
        if on_bred != 0:
            self._add_field("on_bred", on_bred)
        if on_death != 0:
            self._add_field("on_death", on_death)


class EntityEquippable(_BaseComponent):
    _identifier = "minecraft:equippable"

    def __init__(self) -> None:
        """Defines an entity's behavior for having items equipped to it.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_equippable
        """
        super().__init__("equippable")
        self._component["slots"] = []

    def slot(
        self,
        slot: int,
        item: MinecraftItemDescriptor | Identifier,
        accepted_items: list[MinecraftItemDescriptor | Identifier],
        interact_text: str = None,
        on_equip: str = None,
        on_unequip: str = None,
    ):
        """Adds a slot to the entity's equippable slots.

        Parameters:
            slot (int): The slot number of this slot.
            item (str): Identifier of the item that can be equipped for the slot.
            accepted_items (list[str]): The list of items that can fill this slot.
            interact_text (str, optional): Text to be displayed while playing with touch-screen controls when the entity can be equipped with this item. Defaults to None.
            on_equip (str, optional): Event to trigger when the entity is equipped with the item. Defaults to None.
            on_unequip (str, optional): Event to trigger when the item is removed from the entity. Defaults to None.

        Returns:
            Equippable: Returns the Equippable component to allow for method chaining.
        """
        slot_data = {
            "slot": slot,
            "item": str(item),
            "accepted_items": list(map(str, accepted_items)),
        }
        if not interact_text is None:
            t = interact_text.lower().replace(" ", "_")
            slot_data["interact_text"] = f"action.interact.{t}"
            AnvilTranslator().add_localization_entry(f"action.interact.{t}", interact_text)
        if not on_equip is None:
            slot_data["on_equip"] = {"event": on_equip}
        if not on_unequip is None:
            slot_data["on_unequip"] = {"event": on_unequip}

        self._component["slots"].append(slot_data)
        return self


class EntityColor(_BaseComponent):
    _identifier = "minecraft:color"

    def __init__(self, value: int) -> None:
        """Defines the entity's main color.

        Parameters:
            value (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_color
        """
        super().__init__("color")
        self._add_field("value", value)


class EntityColor2(_BaseComponent):
    _identifier = "minecraft:color2"

    def __init__(self, value: int) -> None:
        """Defines the entity's second texture color.

        Parameters:
            value (int): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_color2
        """
        super().__init__("color2")
        self._add_field("value", value)


class EntityBurnsInDaylight(_BaseComponent):
    _identifier = "minecraft:burns_in_daylight"

    def __init__(self, protection_slot: Slots = None) -> None:
        """Compels an entity to burn when it's daylight.

        Parameters:
            protection_slot (Slots, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_burns_in_daylight
        """
        super().__init__("burns_in_daylight")

        if not protection_slot is None:
            if not isinstance(protection_slot, Slots):
                raise TypeError("protection_slot must be an instance of Slots Enum")
            if protection_slot in [
                Slots.Body,
                Slots.Chest,
                Slots.Feet,
                Slots.Head,
                Slots.Legs,
                Slots.Offhand,
            ]:
                raise ValueError("protection_slot must be one of the armor or offhand slots.")

            self._add_field("protection_slot", protection_slot)


class EntityBoss(_BaseComponent):
    _identifier = "minecraft:boss"

    def __init__(
        self,
        name: str,
        hud_range: int = 55,
        should_darken_sky: bool = False,
    ) -> None:
        """Defines the current state of the boss for updating the boss HUD.

        Parameters:
            name (str): Description.
            hud_range (int, optional): Description. Defaults to 55.
            should_darken_sky (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_boss
        """
        super().__init__("boss")

        self._add_field("name", name)
        if hud_range != 55:
            self._add_field("hud_range", hud_range)
        if should_darken_sky:
            self._add_field("should_darken_sky", should_darken_sky)


class EntitySittable(_BaseComponent):
    _identifier = "minecraft:sittable"

    def __init__(
        self,
        sit_event: str = None,
        stand_event: str = None,
    ) -> None:
        """Defines the entity's 'sit' state.

        Parameters:
            sit_event (str, optional): Description. Defaults to None.
            stand_event (str, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_sittable
        """
        super().__init__("sittable")

        if not sit_event is None:
            self._add_field("sit_event", {"event": sit_event})
        if not stand_event is None:
            self._add_field("stand_event", {"event": stand_event})


class EntityFlyingSpeedMeters(_BaseComponent):
    _identifier = "minecraft:flying_speed"

    def __init__(self, value: float, max: float = None) -> None:
        """A component that defines the entity's flying movement speed in meters per second.

        Parameters:
            value (float): Description.
            max (float, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_flying_speed
        """
        super().__init__("flying_speed")
        self._add_field("value", round(0.152 * math.sqrt(value), 2))
        if not max is None:
            self._add_field("max", round(0.152 * math.sqrt(max), 2))


class EntityConditionalBandwidthOptimization(_BaseComponent):
    _identifier = "minecraft:conditional_bandwidth_optimization"

    def __init__(
        self,
        max_dropped_ticks: int = 0,
        max_optimized_distance: int = 0,
        use_motion_prediction_hints: bool = False,
    ) -> None:
        """Defines the Conditional Spatial Update Bandwidth Optimizations of the entity.

        Parameters:
            max_dropped_ticks (int, optional): Description. Defaults to 0.
            max_optimized_distance (int, optional): Description. Defaults to 0.
            use_motion_prediction_hints (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_conditional_bandwidth_optimization
        """
        super().__init__("conditional_bandwidth_optimization")
        a = {}
        if max_dropped_ticks != 0:
            a["max_dropped_ticks"] = max_dropped_ticks
        if max_optimized_distance != 0:
            a["max_optimized_distance"] = max_optimized_distance
        if use_motion_prediction_hints:
            a["use_motion_prediction_hints"] = use_motion_prediction_hints

        self._add_field(
            "default_values",
            a,
        )

    def conditional_values(
        self,
        filters: Filter = None,
        max_dropped_ticks: int = 0,
        max_optimized_distance: int = 0,
        use_motion_prediction_hints: bool = False,
    ):
        a = {
            "conditional_values": [filters] if not filters is None else [],
        }
        if max_dropped_ticks != 0:
            a["max_dropped_ticks"] = max_dropped_ticks
        if max_optimized_distance != 0:
            a["max_optimized_distance"] = max_optimized_distance
        if use_motion_prediction_hints:
            a["use_motion_prediction_hints"] = use_motion_prediction_hints

        self._add_field(
            "conditional_values",
            a,
        )
        return self


class EntityItemHopper(_BaseComponent):
    _identifier = "minecraft:item_hopper"

    def __init__(
        self,
    ) -> None:
        """Allows an entity to function like a hopper block.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_item_hopper
        """
        super().__init__("item_hopper")


class EntityBodyRotationBlocked(_BaseComponent):
    _identifier = "minecraft:body_rotation_blocked"

    def __init__(
        self,
    ) -> None:
        """When set, the entity will no longer visually rotate their body to match their facing direction.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_body_rotation_blocked
        """
        super().__init__("body_rotation_blocked")


class EntityDamageAbsorption(_BaseComponent):
    _identifier = "minecraft:damage_absorption"

    def __init__(self, absorbable_causes: list[DamageCause] = DamageCause.Nothing) -> None:
        """Allows an item to absorb damage that would otherwise be dealt to its wearer. The item must be equipped in an armor slot for this to happen. The absorbed damage reduces the item's durability, with any excess damage being ignored. The item must also have a minecraft:durability component.

        Parameters:
            absorbable_causes (list[DamageCause], optional): Description. Defaults to DamageCause.Nothing.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_damage_absorption
        """
        super().__init__("damage_absorption")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.20")

        if absorbable_causes != DamageCause.Nothing:
            self._set_value("absorbable_causes", absorbable_causes)


class EntityDimensionBound(_BaseComponent):
    _identifier = "minecraft:dimension_bound"

    def __init__(
        self,
    ) -> None:
        """Prevents the entity from changing dimension through portals.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_dimension_bound
        """
        super().__init__("dimension_bound")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.40")


class EntityTransient(_BaseComponent):
    _identifier = "minecraft:transient"

    def __init__(
        self,
    ) -> None:
        """An entity with this component will NEVER persist, and will forever disappear when unloaded.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_transient
        """
        super().__init__("transient")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.40")


class EntityCannotBeAttacked(_BaseComponent):
    _identifier = "minecraft:cannot_be_attacked"

    def __init__(
        self,
    ) -> None:
        """An entity with this component will NEVER be attacked by other entities.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_cannot_be_attacked
        """
        super().__init__("cannot_be_attacked")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.51")


class EntityIgnoreCannotBeAttacked(_BaseComponent):
    _identifier = "minecraft:ignore_cannot_be_attacked"

    def __init__(self, filters: Filter = None) -> None:
        """When set, blocks entities from attacking the owner entity unless they have the minecraft:ignore_cannot_be_attacked component.

        Parameters:
            filters (Filter, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_ignore_cannot_be_attacked
        """
        super().__init__("ignore_cannot_be_attacked")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.51")

        if not filters is None:
            self._add_field("filters", filters)


class EntityLookedAt(_BaseComponent):
    _identifier = "minecraft:looked_at"

    def __init__(
        self,
        field_of_view: float = 26,
        filters: Filter = None,
        find_players_only: bool = False,
        line_of_sight_obstruction_type: LineOfSightObstructionType = LineOfSightObstructionType.Collision,
        look_at_locations: list[LookAtLocation] = None,
        looked_at_cooldown: tuple[Seconds, Seconds] = (0, 0),
        looked_at_event: str = None,
        not_looked_at_event: str = None,
        scale_fov_by_distance: bool = True,
        search_radius: float = 10,
        set_target: LootedAtSetTarget = LootedAtSetTarget.OnceAndStopScanning,
    ) -> None:
        """Defines the behavior when another entity looks at the owner entity.

        Parameters:
            field_of_view (float, optional): Description. Defaults to 26.
            filters (Filter, optional): Description. Defaults to None.
            find_players_only (bool, optional): Description. Defaults to False.
            line_of_sight_obstruction_type (LineOfSightObstructionType, optional): Description. Defaults to LineOfSightObstructionType.Collision.
            look_at_locations (list[LookAtLocation], optional): Description. Defaults to None.
            looked_at_cooldown (tuple[Seconds, Seconds], optional): Description. Defaults to (0, 0).
            looked_at_event (str, optional): Description. Defaults to None.
            not_looked_at_event (str, optional): Description. Defaults to None.
            scale_fov_by_distance (bool, optional): Description. Defaults to True.
            search_radius (float, optional): Description. Defaults to 10.
            set_target (LootedAtSetTarget, optional): Description. Defaults to LootedAtSetTarget.OnceAndStopScanning.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_looked_at
        """
        super().__init__("looked_at")

        if field_of_view != 26:
            self._add_field("field_of_view", field_of_view)
        if filters is not None:
            self._add_field("filters", filters)
        if find_players_only:
            self._add_field("find_players_only", find_players_only)
        if line_of_sight_obstruction_type != LineOfSightObstructionType.Collision:
            self._add_field("line_of_sight_obstruction_type", line_of_sight_obstruction_type)
        if look_at_locations is not None:
            self._add_field("look_at_locations", look_at_locations)
        if looked_at_cooldown != (0, 0):
            self._add_field("looked_at_cooldown", looked_at_cooldown)
        if looked_at_event is not None:
            self._add_field("looked_at_event", looked_at_event)
        if not_looked_at_event is not None:
            self._add_field("not_looked_at_event", not_looked_at_event)
        if not scale_fov_by_distance:
            self._add_field("scale_fov_by_distance", scale_fov_by_distance)
        if search_radius != 10:
            self._add_field("search_radius", search_radius)
        if set_target != LootedAtSetTarget.OnceAndStopScanning:
            self._add_field("set_target", set_target)


class EntityMovementSoundDistanceOffset(_BaseComponent):
    _identifier = "minecraft:movement_sound_distance_offset"

    def __init__(self, value: float) -> None:
        """Sets the offset used to determine the next step distance for playing a movement sound.

        Parameters:
            value (float): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_movement_sound_distance_offset
        """
        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.60")
        super().__init__("movement_sound_distance_offset")
        self._add_field("value", value)


class EntityRendersWhenInvisible(_BaseComponent):
    _identifier = "minecraft:renders_when_invisible"

    def __init__(self) -> None:
        """When set, the entity will render even when invisible. Appropriate rendering behavior can then be specified in the corresponding "minecraft:client_entity".

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_renders_when_invisible
        """
        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.60")
        super().__init__("renders_when_invisible")


class EntityBreedable(_BaseComponent):
    _identifier = "minecraft:breedable"

    def __init__(
        self,
        allow_sitting: bool = False,
        breed_cooldown: Seconds = 60,
        breed_items: list[str] = None,
        causes_pregnancy: bool = False,
        extra_baby_chance: float = 0,
        love_filters: Filter = None,
        require_full_health: bool = False,
        require_tame: bool = True,
        result_item: str = None,
    ) -> None:
        """Allows an entity to get into the 'love' state used for breeding.

        Parameters:
            allow_sitting (bool, optional): Description. Defaults to False.
            breed_cooldown (Seconds, optional): Description. Defaults to 60.
            breed_items (list[str], optional): Description. Defaults to None.
            causes_pregnancy (bool, optional): Description. Defaults to False.
            extra_baby_chance (float, optional): Description. Defaults to 0.
            love_filters (Filter, optional): Description. Defaults to None.
            require_full_health (bool, optional): Description. Defaults to False.
            require_tame (bool, optional): Description. Defaults to True.
            result_item (str, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_breedable
        """
        super().__init__("breedable")

        if allow_sitting:
            self._add_field("allow_sitting", allow_sitting)
        if breed_cooldown != 60:
            self._add_field("breed_cooldown", breed_cooldown)
        if breed_items is not None:
            self._add_field("breed_items", breed_items)
        if causes_pregnancy:
            self._add_field("causes_pregnancy", causes_pregnancy)
        if extra_baby_chance != 0:
            self._add_field("extra_baby_chance", extra_baby_chance)
        if love_filters is not None:
            self._add_field("love_filters", love_filters)
        if require_full_health:
            self._add_field("require_full_health", require_full_health)
        if require_tame is not True:
            self._add_field("require_tame", require_tame)
        if result_item is not None:
            self._add_field("result_item", result_item)

    def environment_requirements(self, block_types: list[str], count: int, radius: float) -> dict:
        """Defines the nearby block requirements for breeding.

        Parameters:
            block_types (list[str]): The block types required nearby for breeding.
            count (int): The number of required block types nearby for breeding.
            radius (float): The radius in blocks to search for the required blocks.

        Returns:
            dict: A dictionary containing the environment requirements information.
        """
        self._add_field(
            "environment_requirements",
            {
                "block_types": block_types,
                "count": count,
                "radius": clamp(radius, 0, 16),
            },
        )
        return self

    def breeds_with(self, mate_type: str) -> dict:
        """Defines the breeding partner for the entity.

        Parameters:
            mate_type (str): The entity type of the breeding partner.
            baby_type (str): The entity type of the offspring.
            breed_event (str): The event to trigger when breeding occurs.

        Returns:
            dict: A dictionary containing the breeding information.
        """

        self._add_field(
            "breeds_with",
            {mate_type: {}},
        )
        return self


class EntityOffspring(_BaseComponent):
    _identifier = "minecraft:offspring"

    def __init__(
        self,
        blend_attributes: bool = True,
        inherit_tamed: bool = True,
        mutation_strategy: BreedingMutationStrategy = BreedingMutationStrategy.None_,
        offspring_pairs: list[
            tuple[MinecraftEntityDescriptor | Identifier, MinecraftEntityDescriptor | Identifier]
        ] = None,
        combine_parent_colors: bool = None,
        parent_centric_attribute_blending: list[_BaseComponent] = None,
        property_inheritance: list[str] = None,
        random_extra_variant_mutation_interval: tuple[int, int] = (0, 0),
        random_variant_mutation_interval: tuple[int, int] = (0, 0),
    ):
        """Defines the way an entity can create a born offspring.

        Parameters:
            blend_attributes (bool, optional): Description. Defaults to True.
            inherit_tamed (bool, optional): Description. Defaults to True.
            mutation_strategy (BreedingMutationStrategy, optional): Description. Defaults to BreedingMutationStrategy.None_.
            offspring_pairs (list[tuple[MinecraftEntityDescriptor | Identifier, MinecraftEntityDescriptor | Identifier]], optional): Description. Defaults to None.
            combine_parent_colors (bool, optional): Description. Defaults to None.
            parent_centric_attribute_blending (list[_BaseComponent], optional): Description. Defaults to None.
            property_inheritance (list[str], optional): Description. Defaults to None.
            random_extra_variant_mutation_interval (tuple[int, int], optional): Description. Defaults to (0, 0).
            random_variant_mutation_interval (tuple[int, int], optional): Description. Defaults to (0, 0).

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_offspring
        """

        super().__init__("offspring")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.26.0")
        if blend_attributes is not True:
            self._add_field("blend_attributes", blend_attributes)
        if inherit_tamed is not True:
            self._add_field("inherit_tamed", inherit_tamed)
        if offspring_pairs is not None:
            self._add_field(
                "offspring_pairs",
                {str(parent): str(offspring) for parent, offspring in offspring_pairs},
            )
        if parent_centric_attribute_blending is not None:
            self._add_field(
                "parent_centric_attribute_blending",
                [c.identifier for c in parent_centric_attribute_blending],
            )
        if property_inheritance is not None:
            self._add_field(
                "property_inheritance",
                [f"{CONFIG.NAMESPACE}:{property}" for property in property_inheritance],
            )
        if random_extra_variant_mutation_interval != (0, 0):
            self._add_field(
                "random_extra_variant_mutation_interval",
                random_extra_variant_mutation_interval,
            )
        if random_variant_mutation_interval != (0, 0):
            self._add_field("random_variant_mutation_interval", random_variant_mutation_interval)
        if mutation_strategy != BreedingMutationStrategy.None_:
            self._add_field("mutation_strategy", mutation_strategy.value)
        if combine_parent_colors is not None:
            self._add_field("combine_parent_colors", combine_parent_colors)

    def deny_parents_variant(self, chance: float, min_variant: str, max_variant: str) -> dict:
        """Defines the chance of denying the parents' variant.

        Parameters:
            chance (float): The percentage chance of denying the parents' variant.
            min_variant (str): The inclusive minimum of the variant range.
            max_variant (str): The inclusive maximum of the variant range.

        Returns:
            dict: A dictionary containing the deny parents variant information.
        """
        self._add_field(
            "deny_parents_variant",
            {
                "chance": chance,
                "min_variant": min_variant,
                "max_variant": max_variant,
            },
        )
        return self

    def mutation_factor(self, color: float, extra_variant: float, variant: float) -> dict:
        """Defines the mutation factor for the entity.

        Parameters:
            color (float): The percentage chance of denying the parents' variant.
            extra_variant (float): The percentage chance of a mutation on the entity's extra variant type.
            variant (float): The percentage chance of a mutation on the entity's variant type.

        Returns:
            dict: A dictionary containing the mutation factor information.
        """
        self._add_field(
            "mutation_factor",
            {
                "color": clamp(color, 0, 1),
                "extra_variant": clamp(extra_variant, 0, 1),
                "variant": clamp(variant, 0, 1),
            },
        )
        return self


class EntityIsCollidable(_BaseComponent):
    _identifier = "minecraft:is_collidable"

    def __init__(self) -> None:
        """Allows other mobs to have vertical and horizontal collisions with this mob.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_collidable
        """
        super().__init__("is_collidable")


class EntityRotationAxisAligned(_BaseComponent):
    _identifier = "minecraft:rotation_axis_aligned"

    def __init__(self) -> None:
        """Causes the entity's body to automatically rotate to align with the nearest cardinal direction based on its current facing direction.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_rotation_axis_aligned
        """
        super().__init__("rotation_axis_aligned")


class EntityFreeCameraControlled(_BaseComponent):
    _identifier = "minecraft:free_camera_controlled"

    def __init__(
        self,
        backwards_movement_modifier: float = 0.5,
        strafe_speed_modifier: float = 0.4,
    ) -> None:
        """Allows a rideable entity to be controlled in the air using WASD and mouse controls.

        Parameters:
            backwards_movement_modifier (float, optional): Description. Defaults to 0.5.
            strafe_speed_modifier (float, optional): Description. Defaults to 0.4.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_free_camera_controlled
        """
        super().__init__("free_camera_controlled")
        if backwards_movement_modifier != 0.5:
            self._add_field("backwards_movement_modifier", backwards_movement_modifier)
        if strafe_speed_modifier != 0.4:
            self._add_field("strafe_speed_modifier", strafe_speed_modifier)


class EntityLeashable(_BaseComponent):
    _identifier = "minecraft:leashable"

    def __init__(
        self,
        can_be_cut: bool = True,
        can_be_stolen: bool = True,
        hard_distance: int = 6,
        max_distance: int = None,
        soft_distance: int = 4,
        on_unleash_interact_only: bool = False,
    ) -> None:
        """Defines how this mob can be leashed to other items.

        Parameters:
            can_be_cut (bool, optional): Description. Defaults to True.
            can_be_stolen (bool, optional): Description. Defaults to True.
            hard_distance (int, optional): Description. Defaults to 6.
            max_distance (int, optional): Description. Defaults to None.
            soft_distance (int, optional): Description. Defaults to 4.
            on_unleash_interact_only (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_leashable
        """
        super().__init__("leashable")

        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.70")

        if not can_be_cut:
            self._add_field("can_be_cut", can_be_cut)
        if not can_be_stolen:
            self._add_field("can_be_stolen", can_be_stolen)
        if hard_distance != 6:
            self._add_field("hard_distance", hard_distance)
        if max_distance is not None:
            self._add_field("max_distance", max_distance)
        if soft_distance != 4:
            self._add_field("soft_distance", soft_distance)
        if on_unleash_interact_only:
            self._add_field("on_unleash_interact_only", on_unleash_interact_only)

    def on_leash(self, event: str, target: FilterSubject = FilterSubject.Self) -> dict:
        self._add_field("on_leash", {"event": event, "target": target})
        return self

    def on_unleash(
        self,
        event: str,
        interact_only: bool = False,
        target: FilterSubject = FilterSubject.Self,
    ) -> dict:
        """Defines the event to trigger when the entity is unleashed.

        Parameters:
            event (str): The event to trigger when the entity is unleashed.
            interact_only (bool, optional): If true, the event will only trigger when the player directly interacts with the entity. Defaults to False.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        Returns:
            dict: A dictionary containing the unleash information.
        """

        self._add_field("on_unleash", {"event": event, "target": target})
        if interact_only:
            self._add_field("on_unleash_interact_only", interact_only)
        return self

    def preset(
        self,
        filter: Filter = None,
        hard_distance: int = 7,
        max_distance: int = 12,
        rotation_adjustment: float = 0,
        soft_distance: float = 4,
        spring_type: LeashSpringType = LeashSpringType.Dampened,
    ) -> dict:
        """Defines a preset for the leashable component.

        Parameters:
            filter (Filter, optional): Conditions that must be met for this preset to be applied. Defaults to None.
            hard_distance (int, optional): Distance (in blocks) over which the entity starts being pulled toward the leash holder with a spring-like force. Defaults to 7.
            max_distance (int, optional): Distance in blocks at which the leash breaks. Defaults to 12.
            rotation_adjustment (float, optional): Adjusts the rotation at which the entity reaches equilibrium. Defaults to 0.
            soft_distance (float, optional): Distance (in blocks) over which the entity begins pathfinding toward the leash holder. Defaults to 4.
            spring_type (LeashSpringType, optional): Defines the type of spring-like force that pulls the entity towards its leash holder. Defaults to LeashSpringType.Dampened.

        Returns:
            dict: A dictionary containing the preset information.
        """
        a = {}
        if not filter is None:
            a["filter"] = filter
        if hard_distance != 7:
            a["hard_distance"] = hard_distance
        if max_distance != 12:
            a["max_distance"] = max_distance
        if rotation_adjustment != 0:
            a["rotation_adjustment"] = rotation_adjustment
        if soft_distance != 4:
            a["soft_distance"] = soft_distance
        if spring_type != LeashSpringType.Dampened:
            a["spring_type"] = spring_type.value

        self._add_field("presets", [a])
        return self


class EntityBodyRotationAlwaysFollowsHead(_BaseComponent):
    _identifier = "minecraft:body_rotation_always_follows_head"

    def __init__(self) -> None:
        """Causes the entity's body to always be automatically rotated to align with the entity's head. Does not override the "minecraft:body_rotation_blocked" component.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_body_rotation_always_follows_head
        """
        super().__init__("body_rotation_always_follows_head")


class EntityTimer(_BaseComponent):
    _identifier = "minecraft:timer"

    def __init__(
        self,
        event: Event,
        target: FilterSubject = FilterSubject.Self,
        looping: bool = True,
        randomInterval: bool = True,
        time: tuple[float, float] | float = 0,
    ) -> None:
        """Adds a timer after which an event will fire.

        Parameters:
            event (Event): Description.
            target (FilterSubject, optional): Description. Defaults to FilterSubject.Self.
            looping (bool, optional): Description. Defaults to True.
            randomInterval (bool, optional): Description. Defaults to True.
            time (tuple[float, float] | float, optional): Description. Defaults to 0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_timer
        """
        super().__init__("timer")

        self._add_field("time_down_event", {"event": event, "target": target.value})

        if not looping:
            self._add_field("looping", looping)
        if not randomInterval:
            self._add_field("randomInterval", randomInterval)
        if not time == (0, 0):
            self._add_field("time", time)


class EntityPersistent(_BaseComponent):
    _identifier = "minecraft:persistent"

    def __init__(self) -> None:
        """Defines whether an entity should be persistent in the game world.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_persistent
        """
        super().__init__("persistent")


class EntityVerticalMovementAction(_BaseComponent):
    _identifier = "minecraft:vertical_movement_action"

    def __init__(self, vertical_velocity: float = 0.5) -> None:
        """When configured as a rideable entity, moves the entity up/down when the player uses the jump action.

        Parameters:
            vertical_velocity (float, optional): Description. Defaults to 0.5.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_vertical_movement_action
        """
        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.111")
        super().__init__("vertical_movement_action")
        if vertical_velocity != 0.5:
            self._add_field("vertical_velocity", vertical_velocity)


class EntityOnDeath(_BaseEventTrigger):
    _identifier = "minecraft:on_death"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """Add a trigger to run when the entity dies.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_death
        """
        super().__init__(event, filters, target)


class EntityOnFriendlyAnger(_BaseEventTrigger):
    _identifier = "minecraft:on_friendly_anger"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """Adds a trigger that will run when a nearby entity of the same type as this entity becomes Angry.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_friendly_anger
        """
        super().__init__(event, filters, target)


class EntityOnHurt(_BaseEventTrigger):
    _identifier = "minecraft:on_hurt"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """Add a trigger to run when the entity is hurt.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_hurt
        """
        super().__init__(event, filters, target)


class EntityOnHurtByPlayer(_BaseEventTrigger):
    _identifier = "minecraft:on_hurt_by_player"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """Adds a trigger to call when this entity is attacked by the player.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_hurt_by_player
        """
        super().__init__(event, filters, target)


class EntityOnIgnite(_BaseEventTrigger):
    _identifier = "minecraft:on_ignite"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """Adds a trigger to call when this entity is set on fire.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_ignite
        """
        super().__init__(event, filters, target)


class EntityOnStartLanding(_BaseEventTrigger):
    _identifier = "minecraft:on_start_landing"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """Only usable by the Ender Dragon. Adds a trigger to call when this entity lands.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_start_landing
        """
        super().__init__(event, filters, target)


class EntityOnStartTakeoff(_BaseEventTrigger):
    _identifier = "minecraft:on_start_takeoff"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """Only usable by the Ender Dragon. Adds a trigger to call when this entity starts flying.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_start_takeoff
        """
        super().__init__(event, filters, target)


class EntityOnTargetAcquired(_BaseEventTrigger):
    _identifier = "minecraft:on_target_acquired"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """Adds a trigger to call when this entity finds a target.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_target_acquired
        """
        super().__init__(event, filters, target)


class EntityOnTargetEscaped(_BaseEventTrigger):
    _identifier = "minecraft:on_target_escaped"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """Adds a trigger to call when this entity loses the target it currently has.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_target_escaped
        """
        super().__init__(event, filters, target)


class EntityOnWakeWithOwner(_BaseEventTrigger):
    _identifier = "minecraft:on_wake_with_owner"

    def __init__(
        self,
        event: Event,
        filters: Filter = None,
        target: FilterSubject = FilterSubject.Self,
    ):
        """A trigger when a mob's tamed onwer wakes up.

        Parameters:
            event (Event): The event to run when the conditions for this trigger are met.
            filters (Filter, optional): The list of conditions for this trigger to execute. Defaults to None.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        ## Documentation reference:
            https://learn.microsoft.com/en-us/minecraft/creator/reference/content/entityreference/examples/entitytriggers/minecrafttrigger_on_wake_with_owner
        """
        super().__init__(event, filters, target)


class EntityNameable(_BaseComponent):
    _identifier = "minecraft:nameable"

    def __init__(self, allow_name_tag_renaming: bool = True, always_show: bool = False) -> None:
        """Allows the entity to have a custom name.

        Parameters:
            allow_name_tag_renaming (bool, optional): Description. Defaults to True.
            always_show (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_nameable
        """
        super().__init__("nameable")

        if always_show:
            self._add_field("always_show", always_show)
        if not allow_name_tag_renaming:
            self._add_field("allow_name_tag_renaming", allow_name_tag_renaming)

        self._add_field("name_actions", [])

    def default_trigger(self, event: str, target: FilterSubject = FilterSubject.Self):
        """Sets the default trigger event for the nameable component.

        Parameters:
            event (str): The event to trigger when the entity is named.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.
        """
        self._add_field("default_trigger", {"event": event, "target": target})
        return self

    def name_action(self, name, event: str, target: FilterSubject = FilterSubject.Self):
        """Adds a name action to the nameable component.

        Parameters:
            name (str): The name that triggers the event.
            event (str): The event to trigger when the entity is named.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.
        """
        self._component["name_actions"].append({"name_filter": name, "on_named": {"event": event, "target": target}})
        return self


class EntityRotationLockedToVehicle(_BaseComponent):
    _identifier = "minecraft:rotation_locked_to_vehicle"

    def __init__(self) -> None:
        """Locks the body rotation of this entity to the vehicle it is riding.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_rotation_locked_to_vehicle
        """
        super().__init__("rotation_locked_to_vehicle")


class EntityHealable(_BaseComponent):
    _identifier = "minecraft:healable"

    def __init__(self, filters: Filter = None, force_use: bool = False) -> None:
        """Allows the entity to be healed by players using healing items.

        Parameters:
            filters (Filter, optional): Description. Defaults to None.
            force_use (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_healable
        """
        super().__init__("healable")
        if not filters is None:
            self._add_field("filters", filters)
        if force_use:
            self._add_field("force_use", force_use)
        self._add_field("items", [])

    def add_heal_item(
        self,
        item: MinecraftItemDescriptor | Identifier,
        heal_amount: float,
        result_item: MinecraftItemDescriptor | Identifier = None,
    ) -> dict:
        """Adds a healing item to the healable component.

        Parameters:
            item (str): The item that can heal the entity.
            heal_amount (float): The amount of health the item restores.

        Returns:
            dict: A dictionary containing the healing item information.
        """
        self._component["items"].append({"item": item, "heal_amount": heal_amount, "result_item": result_item})
        return self


class EntityExhaustionValues(_BaseComponent):
    _identifier = "minecraft:exhaustion_values"

    def __init__(
        self,
        attack: float = 0.1,
        damage: float = 0.1,
        heal: float = 6,
        jump: float = 0.05,
        lunge: float = 4,
        mine: float = 0.005,
        sprint: float = 0.01,
        sprint_jump: float = 0.2,
        swim: float = 0.01,
        walk: float = 0.0,
    ) -> None:
        """Defines how much exhaustion this entity generates for various actions.

        Parameters:
            attack (float, optional): Description. Defaults to 0.1.
            damage (float, optional): Description. Defaults to 0.1.
            heal (float, optional): Description. Defaults to 6.
            jump (float, optional): Description. Defaults to 0.05.
            lunge (float, optional): Description. Defaults to 4.
            mine (float, optional): Description. Defaults to 0.005.
            sprint (float, optional): Description. Defaults to 0.01.
            sprint_jump (float, optional): Description. Defaults to 0.2.
            swim (float, optional): Description. Defaults to 0.01.
            walk (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_exhaustion_values
        """
        super().__init__("exhaustion_values")

        if not attack == 0.1:
            self._add_field("attack", attack)
        if not damage == 0.1:
            self._add_field("damage", damage)
        if not heal == 6:
            self._add_field("heal", heal)
        if not jump == 0.05:
            self._add_field("jump", jump)
        if not lunge == 4:
            self._add_field("lunge", lunge)
        if not mine == 0.005:
            self._add_field("mine", mine)
        if not sprint == 0.01:
            self._add_field("sprint", sprint)
        if not sprint_jump == 0.2:
            self._add_field("sprint_jump", sprint_jump)
        if not swim == 0.01:
            self._add_field("swim", swim)
        if not walk == 0.0:
            self._add_field("walk", walk)


class EntityIsHiddenWhenInvisible(_BaseComponent):
    _identifier = "minecraft:is_hidden_when_invisible"

    def __init__(self) -> None:
        """Causes the entity to be completely hidden when it has the invisibility effect.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_is_hidden_when_invisible
        """
        super().__init__("is_hidden_when_invisible")


class EntityHurtOnCondition(_BaseComponent):
    _identifier = "minecraft:hurt_on_condition"

    def __init__(
        self,
        cause: DamageCause = None,
        filters: Filter = None,
        damage_per_tick: int = 1,
    ) -> None:
        """Causes the entity to take damage when certain conditions are met.

        Parameters:
            cause (DamageCause, optional): Description. Defaults to None.
            filters (Filter, optional): Description. Defaults to None.
            damage_per_tick (int, optional): Description. Defaults to 1.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_hurt_on_condition
        """
        super().__init__("hurt_on_condition")
        self._add_field("damage_conditions", [])
        self.add_condition(cause, filters, damage_per_tick)

    def add_condition(
        self,
        cause: DamageCause = None,
        filters: Filter = None,
        damage_per_tick: int = 1,
    ):
        self._component["damage_conditions"].append(
            {
                "cause": cause,
                "filters": filters,
                "damage_per_tick": damage_per_tick,
            }
        )
        return self


class EntityHide(_BaseComponent):
    _identifier = "minecraft:hide"

    def __init__(self) -> None:
        """Moves to and hides at their owned POI or the closest nearby.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_hide
        """
        super().__init__("hide")


class EntityAnnotationOpenDoor(_BaseComponent):
    _identifier = "minecraft:annotation.open_door"

    def __init__(self) -> None:
        """Allows the entity to open doors.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_annotation_open_door
        """
        super().__init__("minecraft:annotation.open_door")


class EntityDweller(_BaseComponent):
    _identifier = "minecraft:dweller"

    def __init__(
        self,
        can_find_poi: bool = False,
        can_migrate: bool = False,
        dweller_role: Literal["inhabitant", "defender", "hostile", "passive"] = None,
        dwelling_bounds_tolerance: float = 0.0,
        dwelling_type: Literal["village"] = None,
        first_founding_reward: int = 0,
        preferred_profession: str = None,
        update_interval_base: float = 0.0,
        update_interval_variant: float = 0.0,
    ) -> None:
        """Compels an entity to join and migrate between villages and other dwellings.

        Parameters:
            can_find_poi (bool, optional): Description. Defaults to False.
            can_migrate (bool, optional): Description. Defaults to False.
            dweller_role (Literal['inhabitant', 'defender', 'hostile', 'passive'], optional): Description. Defaults to None.
            dwelling_bounds_tolerance (float, optional): Description. Defaults to 0.0.
            dwelling_type (Literal['village'], optional): Description. Defaults to None.
            first_founding_reward (int, optional): Description. Defaults to 0.
            preferred_profession (str, optional): Description. Defaults to None.
            update_interval_base (float, optional): Description. Defaults to 0.0.
            update_interval_variant (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_dweller
        """
        super().__init__("dweller")

        if can_find_poi:
            self._add_field("can_find_poi", can_find_poi)
        if can_migrate:
            self._add_field("can_migrate", can_migrate)
        if dweller_role is not None:
            self._add_field("dweller_role", dweller_role)
        if dwelling_bounds_tolerance != 0.0:
            self._add_field("dwelling_bounds_tolerance", dwelling_bounds_tolerance)
        if dwelling_type is not None:
            self._add_field("dwelling_type", dwelling_type)
        if first_founding_reward != 0:
            self._add_field("first_founding_reward", first_founding_reward)
        if preferred_profession is not None:
            self._add_field("preferred_profession", preferred_profession)
        if update_interval_base != 0.0:
            self._add_field("update_interval_base", update_interval_base)
        if update_interval_variant != 0.0:
            self._add_field("update_interval_variant", update_interval_variant)


class EntityEconomyTradeTable(_BaseComponent):
    _identifier = "minecraft:economy_trade_table"

    def __init__(
        self,
        table: TradeTable | str,
        convert_trades_economy: bool = False,
        cured_discount: list[int] = None,
        display_name: str = None,
        hero_demand_discount: int = -4,
        max_cured_discount: list[int] = None,
        max_nearby_cured_discount: int = -200,
        nearby_cured_discount: int = -20,
        new_screen: bool = False,
        persist_trades: bool = False,
        show_trade_screen: bool = True,
        use_legacy_price_formula: bool = False,
    ) -> None:
        """Defines this entity's ability to trade with players.

        Parameters:
            table (TradeTable | str): Description.
            convert_trades_economy (bool, optional): Description. Defaults to False.
            cured_discount (list[int], optional): Description. Defaults to None.
            display_name (str, optional): Description. Defaults to None.
            hero_demand_discount (int, optional): Description. Defaults to -4.
            max_cured_discount (list[int], optional): Description. Defaults to None.
            max_nearby_cured_discount (int, optional): Description. Defaults to -200.
            nearby_cured_discount (int, optional): Description. Defaults to -20.
            new_screen (bool, optional): Description. Defaults to False.
            persist_trades (bool, optional): Description. Defaults to False.
            show_trade_screen (bool, optional): Description. Defaults to True.
            use_legacy_price_formula (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_economy_trade_table
        """
        super().__init__("economy_trade_table")
        self._add_field("table", table.table_path if isinstance(table, TradeTable) else table)

        if convert_trades_economy:
            self._add_field("convert_trades_economy", convert_trades_economy)
        if cured_discount is not None:
            self._add_field("cured_discount", cured_discount)
        if display_name is not None:
            lower_case = display_name.lower().replace(" ", "_")
            key = f"tradetable.{CONFIG.NAMESPACE}.{CONFIG.PROJECT_NAME}.{lower_case}.name"
            AnvilTranslator().add_localization_entry(key, display_name)
            self._add_field("display_name", key)
        if hero_demand_discount != -4:
            self._add_field("hero_demand_discount", hero_demand_discount)
        if max_cured_discount is not None:
            self._add_field("max_cured_discount", max_cured_discount)
        if max_nearby_cured_discount != -200:
            self._add_field("max_nearby_cured_discount", max_nearby_cured_discount)
        if nearby_cured_discount != -20:
            self._add_field("nearby_cured_discount", nearby_cured_discount)
        if new_screen:
            self._add_field("new_screen", new_screen)
        if persist_trades:
            self._add_field("persist_trades", persist_trades)
        if not show_trade_screen:
            self._add_field("show_trade_screen", show_trade_screen)
        if use_legacy_price_formula:
            self._add_field("use_legacy_price_formula", use_legacy_price_formula)


class EntityScheduler(_BaseComponent):
    _identifier = "minecraft:scheduler"

    def __init__(
        self,
        max_delay_secs: float = 0.0,
        min_delay_secs: float = 0.0,
    ) -> None:
        """Fires off scheduled mob events at time of day events.

        Parameters:
            max_delay_secs (float, optional): Description. Defaults to 0.0.
            min_delay_secs (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_scheduler
        """
        super().__init__("scheduler")

        if max_delay_secs != 0.0:
            self._add_field("max_delay_secs", max_delay_secs)
        if min_delay_secs != 0.0:
            self._add_field("min_delay_secs", min_delay_secs)
        self._add_field("scheduled_events", [])

    def add_scheduled_event(self, event: str, filters: Filter = None):
        """Adds a scheduled event to the scheduler.

        Parameters:
            event (str): The event to fire.
            filters (Filter, optional): The filters to check before firing the event. Defaults to None.

        Returns:
            EntityScheduler: The current instance of the class.
        """
        self._get_field("scheduled_events", []).append({"event": event, "filters": filters})
        return self


class EntityTradeResupply(_BaseComponent):
    _identifier = "minecraft:trade_resupply"

    def __init__(self) -> None:
        """Allows the entity to resupply its trades.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_trade_resupply
        """
        super().__init__("trade_resupply")


class EntityShareables(_BaseComponent):
    _identifier = "minecraft:shareables"

    def __init__(
        self,
        all_items: bool = False,
        all_items_max_amount: int = -1,
        all_items_surplus_amount: int = -1,
        all_items_want_amount: int = -1,
        singular_pickup: bool = False,
    ) -> None:
        """Defines a list of items the mob wants to share or pick up. Items can be configured with optional parameters to control pickup, sharing, and inventory behavior.

        Parameters:
            all_items (bool, optional): Description. Defaults to False.
            all_items_max_amount (int, optional): Description. Defaults to -1.
            all_items_surplus_amount (int, optional): Description. Defaults to -1.
            all_items_want_amount (int, optional): Description. Defaults to -1.
            singular_pickup (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_shareables
        """
        super().__init__("shareables")

        if all_items:
            self._add_field("all_items", all_items)
        if all_items_max_amount != -1:
            self._add_field("all_items_max_amount", all_items_max_amount)
        if all_items_surplus_amount != -1:
            self._add_field("all_items_surplus_amount", all_items_surplus_amount)
        if all_items_want_amount != -1:
            self._add_field("all_items_want_amount", all_items_want_amount)
        if singular_pickup:
            self._add_field("singular_pickup", singular_pickup)

        self._add_field("items", [])

    def item(
        self,
        item: MinecraftItemDescriptor | Identifier,
        admire: bool = False,
        barter: bool = False,
        consume_item: bool = False,
        craft_into: MinecraftItemDescriptor | Identifier = None,
        max_amount: int = -1,
        pickup_limit: int = -1,
        pickup_only: bool = False,
        priority: int = 0,
        stored_in_inventory: bool = False,
        surplus_amount: int = -1,
        want_amount: int = -1,
    ):
        """Adds an item to the shareables list.

        Parameters:
            item (str): The identifier of the item.
            admire (bool, optional): Mob will admire the item after picking up by looking at it. Defaults to False.
            barter (bool, optional): Mob will barter for the item after picking it up. Defaults to False.
            consume_item (bool, optional): Determines whether the mob will consume the item or not. Defaults to False.
            craft_into (str, optional): Item to craft this item into. Defaults to None.
            max_amount (int, optional): Maximum number of this item the mob will hold. Defaults to -1.
            pickup_limit (int, optional): Maximum number items the mob will pick up during a single goal tick. Defaults to -1.
            pickup_only (bool, optional): Determines whether the mob can only pickup the item and not drop it. Defaults to False.
            priority (int, optional): Prioritizes which items the entity prefers. 0 is the highest priority. Defaults to 0.
            stored_in_inventory (bool, optional): Determines whether the mob will try to put the item in its inventory if it has the inventory component and if it can't be equipped. Defaults to False.
            surplus_amount (int, optional): Number of this item considered extra that the entity wants to share. Defaults to -1.
            want_amount (int, optional): Number of this item this entity wants to share. Defaults to -1.
        """
        item_data = {
            "item": str(item),
            "priority": priority,
        }
        if admire:
            item_data["admire"] = admire
        if barter:
            item_data["barter"] = barter
        if consume_item:
            item_data["consume_item"] = consume_item
        if craft_into is not None:
            item_data["craft_into"] = str(craft_into)
        if max_amount != -1:
            item_data["max_amount"] = max_amount
        if pickup_limit != -1:
            item_data["pickup_limit"] = pickup_limit
        if pickup_only:
            item_data["pickup_only"] = pickup_only
        if stored_in_inventory:
            item_data["stored_in_inventory"] = stored_in_inventory
        if surplus_amount != -1:
            item_data["surplus_amount"] = surplus_amount
        if want_amount != -1:
            item_data["want_amount"] = want_amount

        self._component["items"].append(item_data)
        return self


class EntityArmorEquipmentSlotMapping(_BaseComponent):
    _identifier = "minecraft:entity_armor_equipment_slot_mapping"

    def __init__(self, armor_slot: Slots) -> None:
        """Sets the equipment slot to map to the entity's armor slot.

        Parameters:
            armor_slot (Slots): Description.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_entity_armor_equipment_slot_mapping
        """
        super().__init__("entity_armor_equipment_slot_mapping")
        if not armor_slot in [Slots.Chest, Slots.Body]:
            raise ValueError(f"Invalid armor_slot '{armor_slot}'. Must be one of: '{Slots.Chest}', '{Slots.Body}'")
        self._add_field("armor_slot", armor_slot)


class EntityDespawn(_BaseComponent):
    _identifier = "minecraft:despawn"

    def __init__(
        self,
        despawn_from_chance: bool = True,
        despawn_from_distance: tuple[int, int] = None,
        despawn_from_inactivity: bool = True,
        despawn_from_simulation_edge: bool = True,
        filters: Filter = None,
        min_range_inactivity_timer: int = 30,
        min_range_random_chance: int = 800,
        remove_child_entities: bool = False,
    ) -> None:
        """Despawns the Actor when the despawn rules or optional filters evaluate to true.

        Parameters:
            despawn_from_chance (bool, optional): Determines if "min_range_random_chance" is used in the standard despawn rules. Defaults to True.
            despawn_from_distance (tuple[int, int], optional): Specifies if the 'min_distance' and 'max_distance' are used in the standard despawn rules. Defaults to None.
            despawn_from_inactivity (bool, optional): Determines if the "min_range_inactivity_timer" is used in the standard despawn rules. Defaults to True.
            despawn_from_simulation_edge (bool, optional): Determines if the mob is instantly despawned at the edge of simulation distance in the standard despawn rules. Defaults to True.
            filters (Filter, optional): The list of conditions that must be satisfied before the Actor is despawned. If a filter is defined then standard despawn rules are ignored. Defaults to None.
            min_range_inactivity_timer (int, optional): The amount of time in seconds that the mob must be inactive. Defaults to 30.
            min_range_random_chance (int, optional): A random chance between 1 and the given value. Defaults to 800.
            remove_child_entities (bool, optional): If true, all entities linked to this entity in a child relationship will also be despawned. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_despawn
        """
        super().__init__("despawn")

        if not despawn_from_chance:
            self._add_field("despawn_from_chance", despawn_from_chance)
        if despawn_from_distance is not None:
            if (
                not isinstance(despawn_from_distance, (tuple, list))
                or not len(despawn_from_distance) == 2
                or not all(isinstance(i, int) for i in despawn_from_distance)
            ):
                raise ValueError("despawn_from_distance must be a tuple of 2 integers")

            if despawn_from_distance[0] < 0 or despawn_from_distance[1] < 0:
                raise ValueError("despawn_from_distance values must be non-negative")
            if despawn_from_distance[0] > despawn_from_distance[1]:
                raise ValueError("despawn_from_distance minimum must be less than or equal to maximum")

            self._add_field(
                "despawn_from_distance",
                {"min_distance": despawn_from_distance[0], "max_distance": despawn_from_distance[1]},
            )
        if not despawn_from_inactivity:
            self._add_field("despawn_from_inactivity", despawn_from_inactivity)
        if not despawn_from_simulation_edge:
            self._add_field("despawn_from_simulation_edge", despawn_from_simulation_edge)
        if filters is not None:
            self._add_field("filters", filters)
        if min_range_inactivity_timer != 30:
            self._add_field("min_range_inactivity_timer", min_range_inactivity_timer)
        if min_range_random_chance != 800:
            self._add_field("min_range_random_chance", min_range_random_chance)
        if remove_child_entities:
            self._add_field("remove_child_entities", remove_child_entities)

    def despawn_from_distance(self, range: tuple[int, int] = (32, 128)):
        """Sets the despawn distance properties.

        Parameters:
            range (tuple[int, int], optional): A tuple containing the minimum and maximum distance for despawning. Defaults to (32, 128).

        Returns:
            EntityDespawn: Returns the EntityDespawn component to allow for method chaining.
        """
        if not isinstance(range, tuple) or not len(range) == 2 or not all(isinstance(i, int) for i in range):
            raise ValueError("range must be a tuple of 2 integers")
        if range[0] < 0 or range[1] < 0:
            raise ValueError("range values must be non-negative")
        if range[0] > range[1]:
            raise ValueError("range minimum must be less than or equal to maximum")
        if range != (32, 128):
            min_distance, max_distance = range
            self._add_field("despawn_from_distance", {"min_distance": min_distance, "max_distance": max_distance})
        return self


class EntityGameEventMovementTracking(_BaseComponent):
    _identifier = "minecraft:game_event_movement_tracking"

    def __init__(
        self,
        emit_flap: bool = False,
        emit_move: bool = True,
        emit_swim: bool = True,
    ) -> None:
        """Allows an entity to emit entityMove, swim and flap game events, depending on the block the entity is moving through. It is added by default to every mob.

        Parameters:
            emit_flap (bool, optional): If true, the flap game event will be emitted when the entity moves through air. Defaults to False.
            emit_move (bool, optional): If true, the entityMove game event will be emitted when the entity moves on ground or through a solid. Defaults to True.
            emit_swim (bool, optional): If true, the swim game event will be emitted when the entity moves through a liquid. Defaults to True.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitycomponents/minecraftcomponent_game_event_movement_tracking
        """
        super().__init__("game_event_movement_tracking")

        if emit_flap:
            self._add_field("emit_flap", emit_flap)
        if not emit_move:
            self._add_field("emit_move", emit_move)
        if not emit_swim:
            self._add_field("emit_swim", emit_swim)


# AI Goals ==========================================================================


class EntityAINearestAttackableTarget(_BaseAIGoal):
    _identifier = "minecraft:behavior.nearest_attackable_target"

    def __init__(
        self,
        attack_interval: tuple[float, float] | float = 0,
        attack_interval_min: int = 0,
        attack_owner: bool = False,
        must_reach: bool = False,
        must_see: bool = False,
        must_see_forget_duration: float = 3.0,
        persist_time: float = 0.0,
        # reevaluate_description: bool = False,
        reselect_targets: bool = False,
        scan_interval: int = 10,
        set_persistent: bool = False,
        target_invisible_multiplier: float = 0.7,
        target_search_height: float = -0.1,
        target_sneak_visibility_multiplier: float = 0.8,
        within_radius: float = 0.0,
        target_acquisition_probability: float = 1.0,
    ) -> None:
        """Allows an entity to attack the closest target within a given subset of specific target types.

        Parameters:
            attack_interval (tuple[float, float] | float, optional): Description. Defaults to 0.
            attack_interval_min (int, optional): Description. Defaults to 0.
            attack_owner (bool, optional): Description. Defaults to False.
            must_reach (bool, optional): Description. Defaults to False.
            must_see (bool, optional): Description. Defaults to False.
            must_see_forget_duration (float, optional): Description. Defaults to 3.0.
            persist_time (float, optional): Description. Defaults to 0.0.
            reselect_targets (bool, optional): Description. Defaults to False.
            scan_interval (int, optional): Description. Defaults to 10.
            set_persistent (bool, optional): Description. Defaults to False.
            target_invisible_multiplier (float, optional): Description. Defaults to 0.7.
            target_search_height (float, optional): Description. Defaults to -0.1.
            target_sneak_visibility_multiplier (float, optional): Description. Defaults to 0.8.
            within_radius (float, optional): Description. Defaults to 0.0.
            target_acquisition_probability (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_nearest_attackable_target
        """
        super().__init__("behavior.nearest_attackable_target")
        self._add_field("entity_types", [])

        if not attack_interval == 0:
            if (
                not isinstance(attack_interval, tuple)
                or not len(attack_interval) == 2
                or not all(isinstance(i, (int, float)) for i in attack_interval)
            ):
                raise ValueError("attack_interval must be a tuple of 2 numbers (int or float)")

            self._add_field(
                "attack_interval",
                {
                    "min": attack_interval[0],
                    "max": attack_interval[1],
                },
            )

        if not attack_interval_min == 0:
            self._add_field("attack_interval_min", attack_interval_min)
        if attack_owner:
            self._add_field("attack_owner", attack_owner)
        if must_reach:
            self._add_field("must_reach", must_reach)
        if must_see:
            self._add_field("must_see", must_see)
        if not must_see_forget_duration == 3.0:
            self._add_field("must_see_forget_duration", must_see_forget_duration)
        if not persist_time == 0.0:
            self._add_field("persist_time", persist_time)
        # if reevaluate_description: self._add_field("reevaluate_description", reevaluate_description)
        if reselect_targets:
            self._add_field("reselect_targets", reselect_targets)
        if not scan_interval == 10:
            self._add_field("scan_interval", scan_interval)
        if set_persistent:
            self._add_field("set_persistent", set_persistent)
        if not target_invisible_multiplier == 0.7:
            self._add_field("target_invisible_multiplier", target_invisible_multiplier)
        if not target_search_height == -0.1:
            self._add_field("target_search_height", target_search_height)
        if not target_sneak_visibility_multiplier == 0.8:
            self._add_field("target_sneak_visibility_multiplier", target_sneak_visibility_multiplier)
        if not within_radius == 0.0:
            self._add_field("within_radius", within_radius)
        if not target_acquisition_probability == 1.0:
            self._add_field("target_acquisition_probability", target_acquisition_probability)

    def add_target(
        self,
        filters: Filter,
        cooldown: int = 0,
        max_dist: int = 32,
        must_see: bool = False,
        must_see_forget_duration: float = 3.0,
        sprint_speed_multiplier: float = 1.0,
        walk_speed_multiplier: float = 1.0,
    ):
        # empty dicts will be removed at compilation
        self._component["entity_types"].append(
            {
                "filters": filters,
                "cooldown": cooldown if cooldown > 0 else {},
                "max_dist": max_dist if max_dist != 32 else {},
                "must_see": must_see if must_see else {},
                "must_see_forget_duration": (must_see_forget_duration if must_see_forget_duration != 3.0 else {}),
                "sprint_speed_multiplier": (sprint_speed_multiplier if sprint_speed_multiplier != 1.0 else {}),
                "walk_speed_multiplier": (walk_speed_multiplier if walk_speed_multiplier != 1.0 else {}),
            }
        )
        return self


class EntityAINearestPrioritizedAttackableTarget(_BaseAIGoal):
    _identifier = "minecraft:behavior.nearest_prioritized_attackable_target"

    def __init__(
        self,
        attack_interval: int = 0,
        attack_interval_min: int = 0,
        attack_owner: bool = False,
        must_reach: bool = False,
        must_see: bool = False,
        must_see_forget_duration: float = 3.0,
        persist_time: float = 0.0,
        reevaluate_description: bool = False,
        reselect_targets: bool = False,
        scan_interval: int = 10,
        set_persistent: bool = False,
        target_invisible_multiplier: float = 0.7,
        target_search_height: float = -0.1,
        target_sneak_visibility_multiplier: float = 0.8,
        within_radius: float = 0.0,
    ) -> None:
        """Allows an entity to attack the closest target within a given subset of specific target types.

        Parameters:
            attack_interval (int, optional): Description. Defaults to 0.
            attack_interval_min (int, optional): Description. Defaults to 0.
            attack_owner (bool, optional): Description. Defaults to False.
            must_reach (bool, optional): Description. Defaults to False.
            must_see (bool, optional): Description. Defaults to False.
            must_see_forget_duration (float, optional): Description. Defaults to 3.0.
            persist_time (float, optional): Description. Defaults to 0.0.
            reevaluate_description (bool, optional): Description. Defaults to False.
            reselect_targets (bool, optional): Description. Defaults to False.
            scan_interval (int, optional): Description. Defaults to 10.
            set_persistent (bool, optional): Description. Defaults to False.
            target_invisible_multiplier (float, optional): Description. Defaults to 0.7.
            target_search_height (float, optional): Description. Defaults to -0.1.
            target_sneak_visibility_multiplier (float, optional): Description. Defaults to 0.8.
            within_radius (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_nearest_prioritized_attackable_target
        """
        super().__init__("behavior.nearest_prioritized_attackable_target")
        self._add_field("entity_types", [])

        if not attack_interval == 0:
            self._add_field("attack_interval", attack_interval)
        if not attack_interval_min == 0:
            self._add_field("attack_interval_min", attack_interval_min)
        if attack_owner:
            self._add_field("attack_owner", attack_owner)
        if must_reach:
            self._add_field("must_reach", must_reach)
        if must_see:
            self._add_field("must_see", must_see)
        if not must_see_forget_duration == 3.0:
            self._add_field("must_see_forget_duration", must_see_forget_duration)
        if not persist_time == 0.0:
            self._add_field("persist_time", persist_time)
        if reevaluate_description:
            self._add_field("reevaluate_description", reevaluate_description)
        if reselect_targets:
            self._add_field("reselect_targets", reselect_targets)
        if not scan_interval == 10:
            self._add_field("scan_interval", scan_interval)
        if set_persistent:
            self._add_field("set_persistent", set_persistent)
        if not target_invisible_multiplier == 0.7:
            self._add_field("target_invisible_multiplier", target_invisible_multiplier)
        if not target_search_height == -0.1:
            self._add_field("target_search_height", target_search_height)
        if not target_sneak_visibility_multiplier == 0.8:
            self._add_field("target_sneak_visibility_multiplier", target_sneak_visibility_multiplier)
        if not within_radius == 0.0:
            self._add_field("within_radius", within_radius)

    def add_target(
        self,
        filters: Filter,
        cooldown: int = 0,
        max_dist: int = 32,
        must_see: bool = False,
        must_see_forget_duration: float = 3.0,
        sprint_speed_multiplier: float = 1.0,
        walk_speed_multiplier: float = 1.0,
    ):
        # empty dicts will be removed at compilation
        self._component["entity_types"].append(
            {
                "filters": filters,
                "cooldown": cooldown if cooldown > 0 else {},
                "max_dist": max_dist if max_dist != 32 else {},
                "must_see": must_see if must_see else {},
                "must_see_forget_duration": (must_see_forget_duration if must_see_forget_duration != 3.0 else {}),
                "sprint_speed_multiplier": (sprint_speed_multiplier if sprint_speed_multiplier != 1.0 else {}),
                "walk_speed_multiplier": (walk_speed_multiplier if walk_speed_multiplier != 1.0 else {}),
            }
        )
        return self


class EntityAIKnockbackRoar(_BaseAIGoal):
    _identifier = "minecraft:behavior.knockback_roar"

    def __init__(
        self,
        attack_time: float = 0.5,
        cooldown_time: float = 0.1,
        damage_filters: Filter = None,
        duration: float = 1,
        knockback_damage: int = 6,
        knockback_filters: Filter = None,
        knockback_height_cap: float = 0.4,
        knockback_horizontal_strength: int = 4,
        knockback_range: int = 4,
        knockback_vertical_strength: int = 4,
    ) -> None:
        """Compels an entity to emit a roar effect that knocks back other entities in a set radius from where the roar was emitted.

        Parameters:
            attack_time (float, optional): Description. Defaults to 0.5.
            cooldown_time (float, optional): Description. Defaults to 0.1.
            damage_filters (Filter, optional): Description. Defaults to None.
            duration (float, optional): Description. Defaults to 1.
            knockback_damage (int, optional): Description. Defaults to 6.
            knockback_filters (Filter, optional): Description. Defaults to None.
            knockback_height_cap (float, optional): Description. Defaults to 0.4.
            knockback_horizontal_strength (int, optional): Description. Defaults to 4.
            knockback_range (int, optional): Description. Defaults to 4.
            knockback_vertical_strength (int, optional): Description. Defaults to 4.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_knockback_roar
        """
        super().__init__("behavior.knockback_roar")

        if not attack_time == 0.5:
            self._add_field("attack_time", attack_time)
        if not cooldown_time == 0.1:
            self._add_field("cooldown_time", cooldown_time)
        if not damage_filters is None:
            self._add_field("damage_filters", damage_filters)
        if not duration == 1:
            self._add_field("duration", duration)
        if not knockback_damage == 6:
            self._add_field("knockback_damage", knockback_damage)
        if not knockback_filters is None:
            self._add_field("knockback_filters", knockback_filters)
        if not knockback_height_cap == 0.4:
            self._add_field("knockback_height_cap", knockback_height_cap)
        if not knockback_horizontal_strength == 4:
            self._add_field("knockback_horizontal_strength", knockback_horizontal_strength)
        if not knockback_range == 4:
            self._add_field("knockback_range", knockback_range)
        if not knockback_vertical_strength == 4:
            self._add_field("knockback_vertical_strength", knockback_vertical_strength)

    def on_roar_end(self, on_roar_end: str):
        self._add_field("on_roar_end", {"event": on_roar_end})
        return self


class EntityAIFloat(_BaseAIGoal):
    _identifier = "minecraft:behavior.float"

    def __init__(
        self,
        sink_with_passengers: bool = False,
        chance_per_tick_to_float: float = 0.0,
        time_under_water_to_dismount_passengers: Seconds = 0.0,
    ) -> None:
        """Allows an entity to float on water. Passengers will be kicked out the moment the mob's head goes underwater, which may not happen for tall mobs.

        Parameters:
            sink_with_passengers (bool, optional): Description. Defaults to False.
            chance_per_tick_to_float (float, optional): Description. Defaults to 0.0.
            time_under_water_to_dismount_passengers (Seconds, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_float
        """
        super().__init__("behavior.float")
        if sink_with_passengers:
            self._add_field("sink_with_passengers", sink_with_passengers)
        if chance_per_tick_to_float != 0.0:
            self._add_field("chance_per_tick_to_float", chance_per_tick_to_float)
        if time_under_water_to_dismount_passengers != 0.0:
            self._add_field(
                "time_under_water_to_dismount_passengers",
                time_under_water_to_dismount_passengers,
            )


class EntityAIRandomStroll(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_stroll"

    def __init__(
        self,
        interval: int = 120,
        speed_multiplier: float = 1.0,
        xz_dist: int = 10,
        y_dist: int = 7,
    ) -> None:
        """Compels an entity to choose a random direction to walk towards.

        Parameters:
            interval (int, optional): Description. Defaults to 120.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            xz_dist (int, optional): Description. Defaults to 10.
            y_dist (int, optional): Description. Defaults to 7.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_stroll
        """
        super().__init__("behavior.random_stroll")
        if interval != 120:
            self._add_field("interval", interval)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if xz_dist != 10:
            self._add_field("xz_dist", max(1, xz_dist))
        if y_dist != 7:
            self._add_field("y_dist", max(1, y_dist))


class EntityAILookAtPlayer(_BaseAIGoal):
    _identifier = "minecraft:behavior.look_at_player"

    def __init__(
        self,
        angle_of_view_horizontal: int = 360,
        angle_of_view_vertical: int = 360,
        look_distance: float = 8.0,
        look_time: tuple[int, int] = (2, 4),
        probability: float = 0.02,
        target_distance: float = 0.6,
    ) -> None:
        """Compels an entity to look at the player by rotating the head bone pose within a set limit.

        Parameters:
            angle_of_view_horizontal (int, optional): Description. Defaults to 360.
            angle_of_view_vertical (int, optional): Description. Defaults to 360.
            look_distance (float, optional): Description. Defaults to 8.0.
            look_time (tuple[int, int], optional): Description. Defaults to (2, 4).
            probability (float, optional): Description. Defaults to 0.02.
            target_distance (float, optional): Description. Defaults to 0.6.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_look_at_player
        """
        super().__init__("behavior.look_at_player")
        if angle_of_view_horizontal != 360:
            self._add_field("angle_of_view_horizontal", angle_of_view_horizontal)
        if angle_of_view_vertical != 360:
            self._add_field("angle_of_view_vertical", angle_of_view_vertical)
        if look_distance != 8.0:
            self._add_field("look_distance", look_distance)
        if look_time != (2, 4):
            if (
                not isinstance(look_time, tuple)
                or not len(look_time) == 2
                or not all(isinstance(i, (int, float)) for i in look_time)
            ):
                raise ValueError("look_time must be a tuple of 2 numbers (int or float)")
            self._add_field("look_time", {"min": look_time[0], "max": look_time[1]})

        if probability != 0.02:
            self._add_field("probability", probability)
        if target_distance != 0.6:
            self._add_field("target_distance", target_distance)


class EntityAIRandomLookAround(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_look_around"

    def __init__(
        self,
        angle_of_view_horizontal: int = 360,
        angle_of_view_vertical: int = 360,
        look_distance: float = 8.0,
        look_time: tuple[int, int] = (2, 4),
        probability: float = 0.02,
        target_distance: float = 0.6,
    ) -> None:
        """Compels an entity to choose a random direction to look in for a random duration within a range.

        Parameters:
            angle_of_view_horizontal (int, optional): Description. Defaults to 360.
            angle_of_view_vertical (int, optional): Description. Defaults to 360.
            look_distance (float, optional): Description. Defaults to 8.0.
            look_time (tuple[int, int], optional): Description. Defaults to (2, 4).
            probability (float, optional): Description. Defaults to 0.02.
            target_distance (float, optional): Description. Defaults to 0.6.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_look_around
        """
        super().__init__("behavior.random_look_around")
        if angle_of_view_horizontal != 360:
            self._add_field("angle_of_view_horizontal", angle_of_view_horizontal)
        if angle_of_view_vertical != 360:
            self._add_field("angle_of_view_vertical", angle_of_view_vertical)
        if look_distance != 8.0:
            self._add_field("look_distance", look_distance)
        if look_time != (2, 4):
            self._add_field("look_time", look_time)
        if probability != 0.02:
            self._add_field("probability", probability)
        if target_distance != 0.6:
            self._add_field("target_distance", target_distance)


class EntityAIHurtByTarget(_BaseAIGoal):
    _identifier = "minecraft:behavior.hurt_by_target"

    def __init__(
        self,
        alert_same_type: bool = False,
        entity_types: Filter = None,
        max_dist: int = 16,
        must_see: bool = False,
        must_see_forget_duration: float = 3.0,
        reevaluate_description: bool = False,
        sprint_speed_multiplier: float = 1.0,
        walk_speed_multiplier: float = 1.0,
        hurt_owner: bool = False,
    ) -> None:
        """Compels an entity to react when hit by set target.

        Parameters:
            alert_same_type (bool, optional): Description. Defaults to False.
            entity_types (Filter, optional): Description. Defaults to None.
            max_dist (int, optional): Description. Defaults to 16.
            must_see (bool, optional): Description. Defaults to False.
            must_see_forget_duration (float, optional): Description. Defaults to 3.0.
            reevaluate_description (bool, optional): Description. Defaults to False.
            sprint_speed_multiplier (float, optional): Description. Defaults to 1.0.
            walk_speed_multiplier (float, optional): Description. Defaults to 1.0.
            hurt_owner (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_hurt_by_target
        """
        super().__init__("behavior.hurt_by_target")

        if alert_same_type:
            self._add_field("alert_same_type", alert_same_type)
        if entity_types != None:
            self._add_field("entity_types", {"filters": entity_types})
        if max_dist != 16:
            self._add_field("max_dist", max_dist)
        if must_see:
            self._add_field("must_see", must_see)
        if must_see_forget_duration != 3.0:
            self._add_field("must_see_forget_duration", must_see_forget_duration)
        if reevaluate_description:
            self._add_field("reevaluate_description", reevaluate_description)
        if sprint_speed_multiplier != 1.0:
            self._add_field("sprint_speed_multiplier", sprint_speed_multiplier)
        if walk_speed_multiplier != 1.0:
            self._add_field("walk_speed_multiplier", walk_speed_multiplier)
        if hurt_owner:
            self._add_field("hurt_owner", hurt_owner)


class EntityAIMeleeAttack(_BaseAIGoal):
    _identifier = "minecraft:behavior.melee_attack"

    def __init__(
        self,
        attack_once: bool = False,
        cooldown_time: int = 1,
        inner_boundary_time_increase: float = 0.25,
        max_path_time: float = 0.55,
        melee_fov: int = 90,
        min_path_time: float = 0.2,
        outer_boundary_time_increase: float = 0.5,
        path_fail_time_increase: float = 0.75,
        path_inner_boundary: int = 16,
        path_outer_boundary: int = 32,
        random_stop_interval: int = 0,
        reach_multiplier: int = 2,
        require_complete_path: bool = False,
        # set_persistent: bool = False,
        speed_multiplier: float = 1,
        track_target: bool = False,
        x_max_rotation: int = 30,
        y_max_head_rotation: int = 30,
        can_spread_on_fire: bool = False,
    ) -> None:
        """Compels entities to make close combat melee attacks.

        Parameters:
            attack_once (bool, optional): Description. Defaults to False.
            cooldown_time (int, optional): Description. Defaults to 1.
            inner_boundary_time_increase (float, optional): Description. Defaults to 0.25.
            max_path_time (float, optional): Description. Defaults to 0.55.
            melee_fov (int, optional): Description. Defaults to 90.
            min_path_time (float, optional): Description. Defaults to 0.2.
            outer_boundary_time_increase (float, optional): Description. Defaults to 0.5.
            path_fail_time_increase (float, optional): Description. Defaults to 0.75.
            path_inner_boundary (int, optional): Description. Defaults to 16.
            path_outer_boundary (int, optional): Description. Defaults to 32.
            random_stop_interval (int, optional): Description. Defaults to 0.
            reach_multiplier (int, optional): Description. Defaults to 2.
            require_complete_path (bool, optional): Description. Defaults to False.
            speed_multiplier (float, optional): Description. Defaults to 1.
            track_target (bool, optional): Description. Defaults to False.
            x_max_rotation (int, optional): Description. Defaults to 30.
            y_max_head_rotation (int, optional): Description. Defaults to 30.
            can_spread_on_fire (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_melee_attack
        """
        super().__init__("behavior.melee_attack")
        if attack_once:
            self._add_field("attack_once", attack_once)
        if cooldown_time != 1:
            self._add_field("cooldown_time", cooldown_time)
        if inner_boundary_time_increase != 0.75:
            self._add_field("inner_boundary_time_increase", inner_boundary_time_increase)
        if max_path_time != 0.75:
            self._add_field("max_path_time", max_path_time)
        if melee_fov != 90:
            self._add_field("melee_fov", melee_fov)
        if min_path_time != 0.2:
            self._add_field("min_path_time", min_path_time)
        if outer_boundary_time_increase != 0.5:
            self._add_field("outer_boundary_time_increase", outer_boundary_time_increase)
        if path_fail_time_increase != 0.75:
            self._add_field("path_fail_time_increase", path_fail_time_increase)
        if path_inner_boundary != 16:
            self._add_field("path_inner_boundary", path_inner_boundary)
        if path_outer_boundary != 32:
            self._add_field("path_outer_boundary", path_outer_boundary)
        if random_stop_interval != 0:
            self._add_field("random_stop_interval", random_stop_interval)
        if reach_multiplier != 2:
            self._add_field("reach_multiplier", reach_multiplier)
        if require_complete_path:
            self._add_field("require_complete_path", require_complete_path)
        # if set_persistent:
        #    self._add_field("set_persistent", set_persistent)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)
        if track_target:
            self._add_field("track_target", track_target)
        if x_max_rotation != 30:
            self._add_field("x_max_rotation", x_max_rotation)
        if y_max_head_rotation != 30:
            self._add_field("y_max_head_rotation", y_max_head_rotation)
        if can_spread_on_fire:
            self._add_field("can_spread_on_fire", can_spread_on_fire)

    def attack_types(self, attack_types: str):
        self._add_field("attack_types", attack_types)
        return self

    def on_attack(self, on_attack: Event):
        self._add_field("on_attack", on_attack)
        return self

    def on_kill(
        self,
        on_kill: str,
        subject: FilterSubject = FilterSubject.Self,
        filter: Filter = None,
    ):
        self._add_field(
            "on_kill",
            {
                "event": on_kill,
                "filters": filter if not filter is None else {},
                "target": subject,
            },
        )


class EntityAIRangedAttack(_BaseAIGoal):
    _identifier = "minecraft:behavior.ranged_attack"

    def __init__(
        self,
        attack_interval: int = 0,
        attack_interval_max: int = 0,
        attack_interval_min: int = 0,
        attack_radius: int = 0,
        attack_radius_min: int = 0,
        burst_interval: int = 0,
        burst_shots: int = 1,
        charge_charged_trigger: int = 0,
        charge_shoot_trigger: int = 0,
        ranged_fov: int = 90,
        set_persistent: bool = False,
        speed_multiplier: int = 1,
        swing: bool = False,
        target_in_sight_time: int = 1,
        x_max_rotation: int = 30,
        y_max_head_rotation: int = 30,
    ) -> None:
        """Allows an entity to attack by using ranged shots. charge_shoot_trigger must be greater than 0 to enable charged up burst-shot attacks. Requires minecraft:shooter to define projectile behavior.

        Parameters:
            attack_interval (int, optional): Description. Defaults to 0.
            attack_interval_max (int, optional): Description. Defaults to 0.
            attack_interval_min (int, optional): Description. Defaults to 0.
            attack_radius (int, optional): Description. Defaults to 0.
            attack_radius_min (int, optional): Description. Defaults to 0.
            burst_interval (int, optional): Description. Defaults to 0.
            burst_shots (int, optional): Description. Defaults to 1.
            charge_charged_trigger (int, optional): Description. Defaults to 0.
            charge_shoot_trigger (int, optional): Description. Defaults to 0.
            ranged_fov (int, optional): Description. Defaults to 90.
            set_persistent (bool, optional): Description. Defaults to False.
            speed_multiplier (int, optional): Description. Defaults to 1.
            swing (bool, optional): Description. Defaults to False.
            target_in_sight_time (int, optional): Description. Defaults to 1.
            x_max_rotation (int, optional): Description. Defaults to 30.
            y_max_head_rotation (int, optional): Description. Defaults to 30.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_ranged_attack
        """
        super().__init__("behavior.ranged_attack")

        if attack_interval != 0:
            self._add_field("attack_interval", attack_interval)
        if attack_interval_max != 0:
            self._add_field("attack_interval_max", attack_interval_max)
        if attack_interval_min != 0:
            self._add_field("attack_interval_min", attack_interval_min)
        if attack_radius != 0:
            self._add_field("attack_radius", attack_radius)
        if attack_radius_min != 0:
            self._add_field("attack_radius_min", attack_radius_min)
        if burst_interval != 0:
            self._add_field("burst_interval", burst_interval)
        if burst_shots != 1:
            self._add_field("burst_shots", burst_shots)
        if charge_charged_trigger != 0:
            self._add_field("charge_charged_trigger", charge_charged_trigger)
        if charge_shoot_trigger != 0:
            self._add_field("charge_shoot_trigger", charge_shoot_trigger)
        if ranged_fov != 90:
            self._add_field("ranged_fov", ranged_fov)
        if set_persistent:
            self._add_field("set_persistent", set_persistent)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)
        if swing:
            self._add_field("swing", swing)
        if target_in_sight_time != 1:
            self._add_field("target_in_sight_time", target_in_sight_time)
        if x_max_rotation != 30:
            self._add_field("x_max_rotation", x_max_rotation)
        if y_max_head_rotation != 30:
            self._add_field("y_max_head_rotation", y_max_head_rotation)


class EntityAISummonEntity(_BaseAIGoal):
    _identifier = "minecraft:behavior.summon_entity"

    def __init__(self) -> None:
        """compels an entity to attack other entities by summoning new entities.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_summon_entity
        """
        super().__init__("behavior.summon_entity")
        self._add_field("summon_choices", [])

    def summon_choice(
        self,
        cast_duration: int,
        cooldown_time: int = 0,
        do_casting: bool = True,
        filters: Filter = None,
        max_activation_range: float = 32.0,
        min_activation_range: float = 1,
        particle_color: int = 0,
        start_sound_event: str = None,
        weight: int = 1,
    ):
        self._component["summon_choices"].append(
            {
                "cast_duration": cast_duration,
                "cooldown_time": cooldown_time if cooldown_time != 0 else {},
                "do_casting": do_casting if not do_casting else {},
                "filters": filters if not filters is None != 0 else {},
                "max_activation_range": (max_activation_range if max_activation_range != 32 else {}),
                "min_activation_range": (min_activation_range if min_activation_range != 1 else {}),
                "particle_color": particle_color if particle_color != 0 else {},
                "start_sound_event": (start_sound_event if not start_sound_event is None else {}),
                "weight": weight,
                "sequence": [],
            }
        )
        return self

    def sequence(
        self,
        entity_type: Identifier,
        base_delay: float = 0.0,
        delay_per_summon: float = 0.0,
        entity_lifespan: int = -1,
        num_entities_spawned: int = 1,
        shape: str = "line",
        size: int = 1,
        sound_event: str = None,
        summon_cap: int = 0,
        summon_cap_radius: float = 0.0,
        target: FilterSubject = FilterSubject.Self,
        summon_event: str = "minecraft:entity_spawned",
    ):
        self._component["summon_choices"][-1]["sequence"].append(
            {
                "entity_type": entity_type,
                "base_delay": base_delay,
                "delay_per_summon": delay_per_summon,
                "entity_lifespan": entity_lifespan,
                "num_entities_spawned": num_entities_spawned,
                "shape": shape,
                "size": size,
                "sound_event": sound_event if not sound_event is None else {},
                "summon_cap": summon_cap if summon_cap != 0 else {},
                "summon_cap_radius": (summon_cap_radius if summon_cap_radius != 0 else {}),
                "target": target,
                "summon_event": (summon_event if summon_event != "minecraft:entity_spawned" else {}),
            }
        )
        return self


class EntityAIDelayedAttack(_BaseAIGoal):
    _identifier = "minecraft:behavior.delayed_attack"

    def __init__(
        self,
        attack_duration: float = 0.75,
        attack_once: bool = False,
        cooldown_time: int = 1,
        hit_delay_pct: float = 0.5,
        inner_boundary_time_increase: float = 0.25,
        max_path_time: float = 0.55,
        melee_fov: int = 90,
        min_path_time: float = 0.2,
        outer_boundary_time_increase: float = 0.5,
        path_fail_time_increase: float = 0.75,
        path_inner_boundary: int = 16,
        path_outer_boundary: int = 32,
        random_stop_interval: int = 0,
        reach_multiplier: int = 2,
        require_complete_path: bool = False,
        # set_persistent: bool = False,
        speed_multiplier: float = 1,
        track_target: bool = False,
        x_max_rotation: int = 30,
        y_max_head_rotation: int = 30,
        can_spread_on_fire: bool = False,
    ) -> None:
        """Compels an entity to attack while also delaying the damage dealt until a specific time in the attack animation.

        Parameters:
            attack_duration (float, optional): Description. Defaults to 0.75.
            attack_once (bool, optional): Description. Defaults to False.
            cooldown_time (int, optional): Description. Defaults to 1.
            hit_delay_pct (float, optional): Description. Defaults to 0.5.
            inner_boundary_time_increase (float, optional): Description. Defaults to 0.25.
            max_path_time (float, optional): Description. Defaults to 0.55.
            melee_fov (int, optional): Description. Defaults to 90.
            min_path_time (float, optional): Description. Defaults to 0.2.
            outer_boundary_time_increase (float, optional): Description. Defaults to 0.5.
            path_fail_time_increase (float, optional): Description. Defaults to 0.75.
            path_inner_boundary (int, optional): Description. Defaults to 16.
            path_outer_boundary (int, optional): Description. Defaults to 32.
            random_stop_interval (int, optional): Description. Defaults to 0.
            reach_multiplier (int, optional): Description. Defaults to 2.
            require_complete_path (bool, optional): Description. Defaults to False.
            speed_multiplier (float, optional): Description. Defaults to 1.
            track_target (bool, optional): Description. Defaults to False.
            x_max_rotation (int, optional): Description. Defaults to 30.
            y_max_head_rotation (int, optional): Description. Defaults to 30.
            can_spread_on_fire (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_delayed_attack
        """

        super().__init__("behavior.delayed_attack")
        if attack_duration != 0.75:
            self._add_field("attack_duration", attack_duration)
        if attack_once:
            self._add_field("attack_once", attack_once)
        if cooldown_time != 1:
            self._add_field("cooldown_time", cooldown_time)
        if hit_delay_pct != 0.5:
            self._add_field("hit_delay_pct", clamp(hit_delay_pct, 0, 1))
        if inner_boundary_time_increase != 0.25:
            self._add_field("inner_boundary_time_increase", inner_boundary_time_increase)
        if max_path_time != 0.55:
            self._add_field("max_path_time", max_path_time)
        if melee_fov != 90:
            self._add_field("melee_fov", melee_fov)
        if min_path_time != 0.2:
            self._add_field("min_path_time", min_path_time)
        if outer_boundary_time_increase != 0.5:
            self._add_field("outer_boundary_time_increase", outer_boundary_time_increase)
        if path_fail_time_increase != 0.75:
            self._add_field("path_fail_time_increase", path_fail_time_increase)
        if path_inner_boundary != 16:
            self._add_field("path_inner_boundary", path_inner_boundary)
        if path_outer_boundary != 32:
            self._add_field("path_outer_boundary", path_outer_boundary)
        if random_stop_interval != 0:
            self._add_field("random_stop_interval", random_stop_interval)
        if reach_multiplier != 2:
            self._add_field("reach_multiplier", reach_multiplier)
        if require_complete_path:
            self._add_field("require_complete_path", require_complete_path)
        # if set_persistent:
        #    self._add_field("set_persistent", set_persistent)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)
        if track_target:
            self._add_field("track_target", track_target)
        if x_max_rotation != 30:
            self._add_field("x_max_rotation", x_max_rotation)
        if y_max_head_rotation != 30:
            self._add_field("y_max_head_rotation", y_max_head_rotation)
        if can_spread_on_fire:
            self._add_field("can_spread_on_fire", can_spread_on_fire)

    def attack_types(self, attack_types: str):
        self._add_field("attack_types", attack_types)
        return self

    def on_attack(
        self,
        on_attack: str,
        target: FilterSubject = FilterSubject.Self,
        filter: Filter = None,
    ):
        self._add_field(
            "on_attack",
            {
                "event": on_attack,
                "filters": filter if not filter is None else {},
                "target": target,
            },
        )
        return self


class EntityAIMoveToBlock(_BaseAIGoal):
    _identifier = "minecraft:behavior.move_to_block"

    def __init__(
        self,
        target_blocks: list[Block | str],
        goal_radius: float = 0.5,
        search_height: int = 1,
        search_range: int = 0,
        speed_multiplier: float = 1.0,
        start_chance: float = 1.0,
        stay_duration: float = 0.0,
        target_offset: tuple[float, float, float] = (0, 0, 0),
        target_selection_method: str = "nearest",
        tick_interval: int = 20,
    ) -> None:
        """Compels a mob to move towards a block.

        Parameters:
            target_blocks (list[Block | str]): Description.
            goal_radius (float, optional): Description. Defaults to 0.5.
            search_height (int, optional): Description. Defaults to 1.
            search_range (int, optional): Description. Defaults to 0.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            start_chance (float, optional): Description. Defaults to 1.0.
            stay_duration (float, optional): Description. Defaults to 0.0.
            target_offset (tuple[float, float, float], optional): Description. Defaults to (0, 0, 0).
            target_selection_method (str, optional): Description. Defaults to 'nearest'.
            tick_interval (int, optional): Description. Defaults to 20.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_move_to_block
        """
        super().__init__("behavior.move_to_block")

        from anvil.lib.schemas import MinecraftBlockDescriptor

        if not all(isinstance(block, (MinecraftBlockDescriptor, str)) for block in target_blocks):
            raise TypeError(
                f"All target_blocks must be either MinecraftBlockDescriptor instances or strings representing block identifiers. Component [{self._identifier}]"
            )

        self._add_field(
            "target_blocks",
            [str(block) for block in target_blocks],
        )

        if goal_radius != 0.5:
            self._add_field("goal_radius", goal_radius)
        if search_height != 1:
            self._add_field("search_height", search_height)
        if search_range != 0:
            self._add_field("search_range", search_range)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if start_chance != 1.0:
            self._add_field("start_chance", start_chance)
        if stay_duration != 0.0:
            self._add_field("stay_duration", stay_duration)
        if target_offset != (0, 0, 0):
            self._add_field("target_offset", target_offset)
        if target_selection_method != "nearest":
            self._add_field("target_selection_method", target_selection_method)
        if tick_interval != 20:
            self._add_field("tick_interval", tick_interval)

    def on_reach(self, event: Event, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_reach", {"event": event, "target": target.value})
        return self

    def on_stay_completed(self, event: Event, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_stay_completed", {"event": event, "target": target.value})
        return self


class EntityAIEquipItem(_BaseAIGoal):
    _identifier = "minecraft:behavior.equip_item"

    def __init__(self) -> None:
        """Compels an entity to equip an item.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_equip_item
        """
        super().__init__("behavior.equip_item")


class EntityAISendEvent(_BaseAIGoal):
    _identifier = "minecraft:behavior.send_event"

    def __init__(self) -> None:
        """Compels an entity to send an event to another entity.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_send_event
        """
        super().__init__("behavior.send_event")
        self._add_field("event_choices", [])

    def choice(
        self,
        cast_duration: Seconds,
        cooldown_time: Seconds,
        # look_at_target: bool = True,
        min_activation_range: float = 0.0,
        max_activation_range: float = 16.0,
        particle_color: str = None,
        weight: int = 1,
        filters: Filter = None,
        start_sound_event: str = None,
    ):
        choice = {
            "cast_duration": cast_duration,
            "cooldown_time": cooldown_time,
            "min_activation_range": min_activation_range,
            "max_activation_range": max_activation_range,
            "weight": weight,
            "sequence": [],
        }
        # if not look_at_target:
        #    choice["look_at_target"] = look_at_target
        if not particle_color is None:
            choice["particle_color"] = particle_color
        if not filters is None:
            choice["filters"] = filters
        if not start_sound_event is None:
            choice["start_sound_event"] = start_sound_event

        self._component["event_choices"].append(choice)

        return self

    def sequence(self, base_delay: Seconds, event: str, sound_event: str = None):
        seq = {
            "base_delay": base_delay,
            "event": event,
        }
        if not sound_event is None:
            seq["sound_event"] = sound_event

        self._component["event_choices"][-1]["sequence"].append(seq)
        return self


class EntityAIMoveTowardsTarget(_BaseAIGoal):
    _identifier = "minecraft:behavior.move_towards_target"

    def __init__(self, within_radius: float = 0.0, speed_multiplier: float = 1.0) -> None:
        """Compels an entity to move towards a target.

        Parameters:
            within_radius (float, optional): Description. Defaults to 0.0.
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_move_towards_target
        """
        super().__init__("behavior.move_towards_target")

        if within_radius != 0.0:
            self._add_field("within_radius", within_radius)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIRandomSitting(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_sitting"

    def __init__(
        self,
        cooldown_time: float = 0,
        min_sit_time: float = 10,
        start_chance: float = 0.1,
        stop_chance: float = 0.3,
    ) -> None:
        """Compels an entity to stop and sit for a random duration of time.

        Parameters:
            cooldown_time (float, optional): Description. Defaults to 0.
            min_sit_time (float, optional): Description. Defaults to 10.
            start_chance (float, optional): Description. Defaults to 0.1.
            stop_chance (float, optional): Description. Defaults to 0.3.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_sitting
        """
        super().__init__("behavior.random_sitting")

        if cooldown_time != 0:
            self._add_field("cooldown_time", cooldown_time)
        if min_sit_time != 10:
            self._add_field("min_sit_time", min_sit_time)
        if start_chance != 0.1:
            self._add_field("start_chance", clamp(start_chance, 0, 1))
        if stop_chance != 0.3:
            self._add_field("stop_chance", clamp(stop_chance, 0, 1))


class EntityAIStayWhileSitting(_BaseAIGoal):
    _identifier = "minecraft:behavior.stay_while_sitting"

    def __init__(self) -> None:
        """Compels an entity to stay in place while sitting.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_stay_while_sitting
        """
        super().__init__("behavior.stay_while_sitting")


class EntityAIRandomSwim(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_swim"

    def __init__(
        self,
        avoid_surface: bool = True,
        interval: int = 120,
        speed_multiplier: float = 1,
        xz_dist: int = 10,
        y_dist: int = 7,
    ) -> None:
        """Compels an entity to swim in a random point in water.

        Parameters:
            avoid_surface (bool, optional): Description. Defaults to True.
            interval (int, optional): Description. Defaults to 120.
            speed_multiplier (float, optional): Description. Defaults to 1.
            xz_dist (int, optional): Description. Defaults to 10.
            y_dist (int, optional): Description. Defaults to 7.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_swim
        """

        super().__init__("behavior.random_swim")

        if not avoid_surface:
            self._add_field("avoid_surface", avoid_surface)
        if interval != 120:
            self._add_field("interval", interval)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)
        if xz_dist != 10:
            self._add_field("xz_dist", max(1, xz_dist))
        if y_dist != 7:
            self._add_field("y_dist", max(1, y_dist))


class EntityAIRandomBreach(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_breach"

    def __init__(
        self,
        cooldown_time: float = 0,
        interval: int = 120,
        speed_multiplier: float = 1,
        xz_dist: int = 10,
        y_dist: int = 7,
    ) -> None:
        """Compels an entity to swim in a random point in water.

        Parameters:
            cooldown_time (float, optional): Description. Defaults to 0.
            interval (int, optional): Description. Defaults to 120.
            speed_multiplier (float, optional): Description. Defaults to 1.
            xz_dist (int, optional): Description. Defaults to 10.
            y_dist (int, optional): Description. Defaults to 7.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_breach
        """

        super().__init__("behavior.random_breach")

        if not cooldown_time:
            self._add_field("avoid_surface", cooldown_time)
        if interval != 120:
            self._add_field("interval", interval)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)
        if xz_dist != 10:
            self._add_field("xz_dist", max(1, xz_dist))
        if y_dist != 7:
            self._add_field("y_dist", max(1, y_dist))


class EntityAIMoveToWater(_BaseAIGoal):
    _identifier = "minecraft:behavior.move_to_water"

    def __init__(
        self,
        goal_radius: float = 0.5,
        search_count: int = 10,
        search_height: int = 1,
        search_range: int = 0,
        speed_multiplier: float = 1,
    ) -> None:
        """Compels an entity to move to water when on land.

        Parameters:
            goal_radius (float, optional): Description. Defaults to 0.5.
            search_count (int, optional): Description. Defaults to 10.
            search_height (int, optional): Description. Defaults to 1.
            search_range (int, optional): Description. Defaults to 0.
            speed_multiplier (float, optional): Description. Defaults to 1.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_move_to_water
        """
        super().__init__("behavior.move_to_water")

        if goal_radius != 0.5:
            self._add_field("goal_radius", goal_radius)
        if search_count != 10:
            self._add_field("search_count", search_count)
        if search_height != 1:
            self._add_field("search_height", search_height)
        if search_range != 0:
            self._add_field("search_range", search_range)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIMoveToLand(_BaseAIGoal):
    _identifier = "minecraft:behavior.move_to_land"

    def __init__(
        self,
        goal_radius: float = 0.5,
        search_count: int = 10,
        search_height: int = 1,
        search_range: int = 0,
        speed_multiplier: float = 1,
    ) -> None:
        """Compels an entity to move to land when on land.

        Parameters:
            goal_radius (float, optional): Description. Defaults to 0.5.
            search_count (int, optional): Description. Defaults to 10.
            search_height (int, optional): Description. Defaults to 1.
            search_range (int, optional): Description. Defaults to 0.
            speed_multiplier (float, optional): Description. Defaults to 1.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_move_to_land
        """
        super().__init__("behavior.move_to_land")

        if goal_radius != 0.5:
            self._add_field("goal_radius", goal_radius)
        if search_count != 10:
            self._add_field("search_count", search_count)
        if search_height != 1:
            self._add_field("search_height", search_height)
        if search_range != 0:
            self._add_field("search_range", search_range)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIMoveToLava(_BaseAIGoal):
    _identifier = "minecraft:behavior.move_to_lava"

    def __init__(
        self,
        goal_radius: float = 0.5,
        search_count: int = 10,
        search_height: int = 1,
        search_range: int = 0,
        speed_multiplier: float = 1,
    ) -> None:
        """Compels an entity to move to lava when on lava.

        Parameters:
            goal_radius (float, optional): Description. Defaults to 0.5.
            search_count (int, optional): Description. Defaults to 10.
            search_height (int, optional): Description. Defaults to 1.
            search_range (int, optional): Description. Defaults to 0.
            speed_multiplier (float, optional): Description. Defaults to 1.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_move_to_lava
        """
        super().__init__("behavior.move_to_lava")

        if goal_radius != 0.5:
            self._add_field("goal_radius", goal_radius)
        if search_count != 10:
            self._add_field("search_count", search_count)
        if search_height != 1:
            self._add_field("search_height", search_height)
        if search_range != 0:
            self._add_field("search_range", search_range)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAILookAtTarget(_BaseAIGoal):
    _identifier = "minecraft:behavior.look_at_target"

    def __init__(
        self,
        angle_of_view_horizontal: int = 360,
        angle_of_view_vertical: int = 360,
        look_distance: float = 8.0,
        look_time: tuple[int, int] = (2, 4),
        probability: float = 0.02,
        target_distance: float = 0.6,
    ) -> None:
        """Compels an entity to look at the target by rotating the head bone pose within a set limit.

        Parameters:
            angle_of_view_horizontal (int, optional): Description. Defaults to 360.
            angle_of_view_vertical (int, optional): Description. Defaults to 360.
            look_distance (float, optional): Description. Defaults to 8.0.
            look_time (tuple[int, int], optional): Description. Defaults to (2, 4).
            probability (float, optional): Description. Defaults to 0.02.
            target_distance (float, optional): Description. Defaults to 0.6.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_look_at_target
        """
        super().__init__("behavior.look_at_target")
        if angle_of_view_horizontal != 360:
            self._add_field("angle_of_view_horizontal", angle_of_view_horizontal)
        if angle_of_view_vertical != 360:
            self._add_field("angle_of_view_vertical", angle_of_view_vertical)
        if look_distance != 8.0:
            self._add_field("look_distance", look_distance)
        if look_time != (2, 4):
            if (
                not isinstance(look_time, tuple)
                or not len(look_time) == 2
                or not all(isinstance(i, (int, float)) for i in look_time)
            ):
                raise ValueError("look_time must be a tuple of 2 numbers (int or float)")
            self._add_field("look_time", {"min": look_time[0], "max": look_time[1]})
        if probability != 0.02:
            self._add_field("probability", probability)
        if target_distance != 0.6:
            self._add_field("target_distance", target_distance)


class EntityAIFollowParent(_BaseAIGoal):
    _identifier = "minecraft:behavior.follow_parent"

    def __init__(
        self,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Compels an entity that has been tagged as a baby to follow their parent around.

        Parameters:
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_follow_parent
        """
        super().__init__("behavior.follow_parent")
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIPlayerRideTamed(_BaseAIGoal):
    _identifier = "minecraft:behavior.player_ride_tamed"

    def __init__(self) -> None:
        """Allows an entity to be rideable after being tamed by a player.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_player_ride_tamed
        """
        super().__init__("behavior.player_ride_tamed")


class EntityAIFollowOwner(_BaseAIGoal):
    _identifier = "minecraft:behavior.follow_owner"

    def __init__(
        self,
        can_teleport: bool = True,
        ignore_vibration: bool = True,
        max_distance: float = 60.0,
        speed_multiplier: float = 1.0,
        start_distance: float = 10.0,
        stop_distance: float = 2.0,
        post_teleport_distance: int = 1,
    ) -> None:
        """Compels an entity to follow a player marked as an owner.

        Parameters:
            can_teleport (bool, optional): Description. Defaults to True.
            ignore_vibration (bool, optional): Description. Defaults to True.
            max_distance (float, optional): Description. Defaults to 60.0.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            start_distance (float, optional): Description. Defaults to 10.0.
            stop_distance (float, optional): Description. Defaults to 2.0.
            post_teleport_distance (int, optional): Description. Defaults to 1.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_follow_owner
        """
        super().__init__("behavior.follow_owner")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.21.20")

        if not can_teleport:
            self._add_field("can_teleport", can_teleport)
        if not ignore_vibration:
            self._add_field("ignore_vibration", ignore_vibration)
        if max_distance != 60.0:
            self._add_field("max_distance", max_distance)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if start_distance != 10.0:
            self._add_field("start_distance", start_distance)
        if stop_distance != 2.0:
            self._add_field("stop_distance", stop_distance)
        if post_teleport_distance > 1:
            self._add_field("post_teleport_distance", post_teleport_distance)


class EntityAIPanic(_BaseAIGoal):
    _identifier = "minecraft:behavior.panic"

    def __init__(
        self,
        damage_sources: DamageCause = DamageCause.All,
        force: bool = False,
        ignore_mob_damage: bool = False,
        panic_sound: str = None,
        prefer_water: bool = False,
        sound_interval: float = 0,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Compels an entity to react when it receives damage.

        Parameters:
            damage_sources (DamageCause, optional): Description. Defaults to DamageCause.All.
            force (bool, optional): Description. Defaults to False.
            ignore_mob_damage (bool, optional): Description. Defaults to False.
            panic_sound (str, optional): Description. Defaults to None.
            prefer_water (bool, optional): Description. Defaults to False.
            sound_interval (float, optional): Description. Defaults to 0.
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_panic
        """
        super().__init__("behavior.panic")
        if not damage_sources == DamageCause.All:
            self._add_field("damage_sources", damage_sources)
        if force:
            self._add_field("force", force)
        if ignore_mob_damage:
            self._add_field("ignore_mob_damage", ignore_mob_damage)
        if not panic_sound is None:
            self._add_field("panic_sound", panic_sound)
        if prefer_water:
            self._add_field("prefer_water", prefer_water)
        if sound_interval != 0:
            self._add_field("sound_interval", sound_interval)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIChargeAttack(_BaseAIGoal):
    _identifier = "minecraft:behavior.charge_attack"

    def __init__(
        self,
        max_distance: int = 3,
        min_distance: int = 2,
        success_rate: float = 0.1428,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Compels an entity to damage a target by using a running attack.

        Parameters:
            max_distance (int, optional): Description. Defaults to 3.
            min_distance (int, optional): Description. Defaults to 2.
            success_rate (float, optional): Description. Defaults to 0.1428.
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_charge_attack
        """
        super().__init__("behavior.charge_attack")
        if max_distance != 3:
            self._add_field("max_distance", max_distance)
        if min_distance != 2:
            self._add_field("min_distance", min_distance)
        if success_rate != 0.1428:
            self._add_field("success_rate", success_rate)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIRamAttack(_BaseAIGoal):
    _identifier = "minecraft:behavior.ram_attack"

    def __init__(
        self,
        baby_knockback_modifier: float = 0.333333,
        cooldown_range: list[int, int] = [10, 20],
        knockback_force: float = 5,
        knockback_height: float = 0.1,
        min_ram_distance: float = 0.0,
        pre_ram_sound: str = None,
        ram_distance: float = 0.0,
        ram_impact_sound: str = None,
        ram_speed: float = 2.0,
        run_speed: float = 1.0,
    ) -> None:
        """Compels an entity to search for a random target and, if a direct path exists between the entity and the target, it will perform a charge. If the attack hits, the target will be knocked back based on the entity's speed.

        Parameters:
            baby_knockback_modifier (float, optional): Description. Defaults to 0.333333.
            cooldown_range (list[int, int], optional): Description. Defaults to [10, 20].
            knockback_force (float, optional): Description. Defaults to 5.
            knockback_height (float, optional): Description. Defaults to 0.1.
            min_ram_distance (float, optional): Description. Defaults to 0.0.
            pre_ram_sound (str, optional): Description. Defaults to None.
            ram_distance (float, optional): Description. Defaults to 0.0.
            ram_impact_sound (str, optional): Description. Defaults to None.
            ram_speed (float, optional): Description. Defaults to 2.0.
            run_speed (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_ram_attack
        """
        super().__init__("behavior.ram_attack")
        if baby_knockback_modifier != 0.333333:
            self._add_field("baby_knockback_modifier", baby_knockback_modifier)
        if cooldown_range != [10, 20]:
            self._add_field("cooldown_range", {"min": cooldown_range[0], "max": cooldown_range[1]})
        if knockback_force != 5:
            self._add_field("knockback_force", knockback_force)
        if knockback_height != 0.1:
            self._add_field("knockback_height", knockback_height)
        if min_ram_distance != 0.0:
            self._add_field("min_ram_distance", min_ram_distance)
        if not pre_ram_sound is None:
            self._add_field("pre_ram_sound", pre_ram_sound)
        if ram_distance != 0.0:
            self._add_field("ram_distance", ram_distance)
        if not ram_impact_sound is None:
            self._add_field("ram_impact_sound", ram_impact_sound)
        if ram_speed != 2.0:
            self._add_field("ram_speed", ram_speed)
        if run_speed != 1.0:
            self._add_field("run_speed", run_speed)

    def on_start(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_start", {"event": event, "target": target.value})
        return self


class EntityAIAvoidMobType(_BaseAIGoal):
    _identifier = "minecraft:behavior.avoid_mob_type"

    def __init__(
        self,
        avoid_mob_sound: str = None,
        avoid_target_xz: int = 16,
        avoid_target_y: int = 7,
        ignore_visibility: bool = False,
        probability_per_strength: float = 1.0,
        remove_target: bool = False,
        sound_interval: list[float] = [3.0, 8.0],
        check_if_outnumbered: bool = False,
        cooldown: float = 0.0,
    ) -> None:
        """Compels an entity to run away from other entities that meet the criteria specified.

        Parameters:
            avoid_mob_sound (str, optional): Description. Defaults to None.
            avoid_target_xz (int, optional): Description. Defaults to 16.
            avoid_target_y (int, optional): Description. Defaults to 7.
            ignore_visibility (bool, optional): Description. Defaults to False.
            probability_per_strength (float, optional): Description. Defaults to 1.0.
            remove_target (bool, optional): Description. Defaults to False.
            sound_interval (list[float], optional): Description. Defaults to [3.0, 8.0].
            check_if_outnumbered (bool, optional): Description. Defaults to False.
            cooldown (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_avoid_mob_type
        """
        super().__init__("behavior.avoid_mob_type")
        if not avoid_mob_sound is None:
            self._add_field("avoid_mob_sound", avoid_mob_sound)
        if avoid_target_xz != 16:
            self._add_field("avoid_target_xz", avoid_target_xz)
        if avoid_target_y != 7:
            self._add_field("avoid_target_y", avoid_target_y)
        if ignore_visibility:
            self._add_field("ignore_visibility", ignore_visibility)
        if probability_per_strength != 1.0:
            self._add_field("probability_per_strength", probability_per_strength)
        if remove_target:
            self._add_field("remove_target", remove_target)
        if sound_interval != [3.0, 8.0]:
            if not isinstance(sound_interval, list):
                raise TypeError("sound_interval must be a list of two numbers")
            if len(sound_interval) != 2:
                raise ValueError("sound_interval must contain exactly two numbers")
            self._add_field(
                "sound_interval",
                {
                    "range_min": min(sound_interval),
                    "range_max": max(sound_interval),
                },
            )
        if check_if_outnumbered:
            self._add_field("check_if_outnumbered", check_if_outnumbered)
        if cooldown != 0.0:
            self._add_field("cooldown", cooldown)

    def add_type(
        self,
        filter: Filter,
        max_dist: float = 3.0,
        max_flee: float = 10.0,
        sprint_distance: float = 7.0,
        sprint_speed_multiplier: float = 1.0,
        walk_speed_multiplier: float = 1.0,
    ):
        """Adds a new entity type to the list of conditions another entity must meet to be a valid target to avoid.

        Parameters:
            filter (Filter): Filter to determine which entities to avoid.
            max_dist (float, optional): Maximum distance to look for an avoid target for the entity. Defaults to 3.0.
            max_flee (float, optional): How many blocks away from its avoid target the entity must be for it to stop fleeing from the avoid target. Defaults to 10.0.
            sprint_distance (float, optional): How many blocks within range of its avoid target the entity must be for it to begin sprinting away from the avoid target. Defaults to 7.0.
            sprint_speed_multiplier (float, optional): Multiplier for sprint speed. 1.0 means keep the regular speed, while higher numbers make the sprint speed faster. Defaults to 1.0.
            walk_speed_multiplier (float, optional): Multiplier for walking speed. 1.0 means keep the regular speed, while higher numbers make the walking speed faster. Defaults to 1.0.
        """

        a = {"filters": filter}
        if max_dist != 3.0:
            a["max_dist"] = max_dist
        if max_flee != 10.0:
            a["max_flee"] = max_flee
        if sprint_distance != 7.0:
            a["sprint_distance"] = sprint_distance
        if sprint_speed_multiplier != 1.0:
            a["sprint_speed_multiplier"] = sprint_speed_multiplier
        if walk_speed_multiplier != 1.0:
            a["walk_speed_multiplier"] = walk_speed_multiplier
        self._get_field("entity_types", []).append(a)
        return self

    def on_escape_event(self, event: str, target: FilterSubject = FilterSubject.Self):
        """Event that is triggered when escaping from a mob.

        Parameters:
            event (str): Event to trigger.
            target (FilterSubject, optional): Target of the event. Defaults to FilterSubject.Self.
        """
        # append to the escape event list so multiple handlers can be added
        self._get_field("on_escape_event", []).append({"event": event, "target": target.value})
        return self


class EntityAILeapAtTarget(_BaseAIGoal):
    _identifier = "minecraft:behavior.leap_at_target"

    def __init__(
        self,
        must_be_on_ground: bool = True,
        set_persistent: bool = False,
        target_dist: float = 0.3,
        yd: float = 0.0,
    ) -> None:
        """Compels an entity to jump towards a target.

        Parameters:
            must_be_on_ground (bool, optional): Description. Defaults to True.
            set_persistent (bool, optional): Description. Defaults to False.
            target_dist (float, optional): Description. Defaults to 0.3.
            yd (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_leap_at_target
        """

        super().__init__("behavior.leap_at_target")
        if not must_be_on_ground:
            self._add_field("must_be_on_ground", must_be_on_ground)
        if set_persistent:
            self._add_field("set_persistent", set_persistent)
        if target_dist != 0.3:
            self._add_field("target_dist", target_dist)
        if yd != 0.0:
            self._add_field("yd", yd)


class EntityAIOcelotAttack(_BaseAIGoal):
    _identifier = "minecraft:behavior.ocelotattack"

    def __init__(
        self,
        cooldown_time: int = 1,
        max_distance: int = 15,
        max_sneak_range: int = 15,
        max_sprint_range: int = 4,
        reach_multiplier: int = 2,
        sneak_speed_multiplier: float = 0.6,
        sprint_speed_multiplier: float = 1.33,
        walk_speed_multiplier: float = 0.8,
        x_max_rotation: int = 30,
        y_max_head_rotation: int = 30,
    ) -> None:
        """Allows an entity to attack by sneaking and pouncing.

        Parameters:
            cooldown_time (int, optional): Description. Defaults to 1.
            max_distance (int, optional): Description. Defaults to 15.
            max_sneak_range (int, optional): Description. Defaults to 15.
            max_sprint_range (int, optional): Description. Defaults to 4.
            reach_multiplier (int, optional): Description. Defaults to 2.
            sneak_speed_multiplier (float, optional): Description. Defaults to 0.6.
            sprint_speed_multiplier (float, optional): Description. Defaults to 1.33.
            walk_speed_multiplier (float, optional): Description. Defaults to 0.8.
            x_max_rotation (int, optional): Description. Defaults to 30.
            y_max_head_rotation (int, optional): Description. Defaults to 30.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_ocelotattack
        """
        super().__init__("behavior.ocelotattack")
        if cooldown_time != 5:
            self._add_field("cooldown_time", cooldown_time)
        if x_max_rotation != 30.0:
            self._add_field("x_max_rotation", x_max_rotation)
        if y_max_head_rotation != 30.0:
            self._add_field("y_max_head_rotation", y_max_head_rotation)
        if max_distance != 20:
            self._add_field("max_distance", max_distance)
        if max_sneak_range != 15.0:
            self._add_field("max_sneak_range", max_sneak_range)
        if max_sprint_range != 4.0:
            self._add_field("max_sprint_range", max_sprint_range)
        if reach_multiplier != 2.0:
            self._add_field("reach_multiplier", reach_multiplier)
        if sneak_speed_multiplier != 0.6:
            self._add_field("sneak_speed_multiplier", sneak_speed_multiplier)
        if sprint_speed_multiplier != 1.33:
            self._add_field("sprint_speed_multiplier", sprint_speed_multiplier)
        if walk_speed_multiplier != 0.8:
            self._add_field("walk_speed_multiplier", walk_speed_multiplier)


class EntityAIOwnerHurtByTarget(_BaseAIGoal):
    _identifier = "minecraft:behavior.owner_hurt_by_target"

    def __init__(
        self,
        entity_types: Filter = None,
        cooldown: Seconds = 0,
        filters: Filter = None,
        max_dist: int = 16,
        must_see: bool = False,
        must_see_forget_duration: float = 3.0,
        reevaluate_description: bool = False,
        sprint_speed_multiplier: float = 1.0,
        walk_speed_multiplier: float = 1.0,
    ) -> None:
        """Compels an entity to react when the owner is hit by a target.

        Parameters:
            entity_types (Filter, optional): Description. Defaults to None.
            cooldown (Seconds, optional): Description. Defaults to 0.
            filters (Filter, optional): Description. Defaults to None.
            max_dist (int, optional): Description. Defaults to 16.
            must_see (bool, optional): Description. Defaults to False.
            must_see_forget_duration (float, optional): Description. Defaults to 3.0.
            reevaluate_description (bool, optional): Description. Defaults to False.
            sprint_speed_multiplier (float, optional): Description. Defaults to 1.0.
            walk_speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_owner_hurt_by_target
        """
        super().__init__("behavior.owner_hurt_by_target")

        if entity_types != None:
            self._add_field("entity_types", {"filters": entity_types})
        if cooldown != 0:
            self._add_field("cooldown", cooldown)
        if filters != None:
            self._add_field("filters", filters)
        if max_dist != 16:
            self._add_field("max_dist", max_dist)
        if must_see:
            self._add_field("must_see", must_see)
        if must_see_forget_duration != 3.0:
            self._add_field("must_see_forget_duration", must_see_forget_duration)
        if reevaluate_description:
            self._add_field("reevaluate_description", reevaluate_description)
        if sprint_speed_multiplier != 1.0:
            self._add_field("sprint_speed_multiplier", sprint_speed_multiplier)
        if walk_speed_multiplier != 1.0:
            self._add_field("walk_speed_multiplier", walk_speed_multiplier)


class EntityAIOwnerHurtTarget(_BaseAIGoal):
    _identifier = "minecraft:behavior.owner_hurt_target"

    def __init__(
        self,
        entity_types: Filter = None,
        cooldown: Seconds = 0,
        filters: Filter = None,
        max_dist: int = 16,
        must_see: bool = False,
        must_see_forget_duration: float = 3.0,
        reevaluate_description: bool = False,
        sprint_speed_multiplier: float = 1.0,
        walk_speed_multiplier: float = 1.0,
    ) -> None:
        """Compels an entity to react when the owner hits a target.

        Parameters:
            entity_types (Filter, optional): Description. Defaults to None.
            cooldown (Seconds, optional): Description. Defaults to 0.
            filters (Filter, optional): Description. Defaults to None.
            max_dist (int, optional): Description. Defaults to 16.
            must_see (bool, optional): Description. Defaults to False.
            must_see_forget_duration (float, optional): Description. Defaults to 3.0.
            reevaluate_description (bool, optional): Description. Defaults to False.
            sprint_speed_multiplier (float, optional): Description. Defaults to 1.0.
            walk_speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_owner_hurt_target
        """
        super().__init__("behavior.owner_hurt_target")

        if entity_types != None:
            self._add_field("entity_types", {"filters": entity_types})
        if cooldown != 0:
            self._add_field("cooldown", cooldown)
        if filters != None:
            self._add_field("filters", filters)
        if max_dist != 16:
            self._add_field("max_dist", max_dist)
        if must_see:
            self._add_field("must_see", must_see)
        if must_see_forget_duration != 3.0:
            self._add_field("must_see_forget_duration", must_see_forget_duration)
        if reevaluate_description:
            self._add_field("reevaluate_description", reevaluate_description)
        if sprint_speed_multiplier != 1.0:
            self._add_field("sprint_speed_multiplier", sprint_speed_multiplier)
        if walk_speed_multiplier != 1.0:
            self._add_field("walk_speed_multiplier", walk_speed_multiplier)


class EntityAIRandomSearchAndDig(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_search_and_dig"

    def __init__(
        self,
        cooldown_range: tuple[Seconds, Seconds] = (0, 0),
        digging_duration_range: tuple[Seconds, Seconds] = (0, 0),
        find_valid_position_retries: int = 0,
        goal_radius: float = 1.5,
        item_table: str = None,
        search_range_xz: float = 0,
        search_range_y: float = 0,
        spawn_item_after_seconds: Seconds = 0,
        spawn_item_pos_offset: float = 0,
        speed_multiplier: float = 0,
        target_blocks: list[str] = [],
        target_dig_position_offset: float = 2.25,
    ) -> None:
        """Compels an entity to locate a random target block that it can find a path towards. Once found, the entity will move towards the target block and dig up an item.

        Parameters:
            cooldown_range (tuple[Seconds, Seconds], optional): Description. Defaults to (0, 0).
            digging_duration_range (tuple[Seconds, Seconds], optional): Description. Defaults to (0, 0).
            find_valid_position_retries (int, optional): Description. Defaults to 0.
            goal_radius (float, optional): Description. Defaults to 1.5.
            item_table (str, optional): Description. Defaults to None.
            search_range_xz (float, optional): Description. Defaults to 0.
            search_range_y (float, optional): Description. Defaults to 0.
            spawn_item_after_seconds (Seconds, optional): Description. Defaults to 0.
            spawn_item_pos_offset (float, optional): Description. Defaults to 0.
            speed_multiplier (float, optional): Description. Defaults to 0.
            target_blocks (list[str], optional): Description. Defaults to [].
            target_dig_position_offset (float, optional): Description. Defaults to 2.25.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_search_and_dig
        """
        super().__init__("behavior.random_search_and_dig")

        if cooldown_range != (0, 0):
            self._add_field("cooldown_range", cooldown_range)
        if digging_duration_range != (0, 0):
            self._add_field("digging_duration_range", digging_duration_range)
        if find_valid_position_retries != 0:
            self._add_field("find_valid_position_retries", find_valid_position_retries)
        if goal_radius != 1.5:
            self._add_field("goal_radius", goal_radius)
        if not item_table is None:
            self._add_field("item_table", item_table)
        if search_range_xz != 0:
            self._add_field("search_range_xz", search_range_xz)
        if search_range_y != 0:
            self._add_field("search_range_y", search_range_y)
        if spawn_item_after_seconds != 0:
            self._add_field("spawn_item_after_seconds", spawn_item_after_seconds)
        if spawn_item_pos_offset != 0:
            self._add_field("spawn_item_pos_offset", spawn_item_pos_offset)
        if speed_multiplier != 0:
            self._add_field("speed_multiplier", speed_multiplier)
        if not target_blocks == []:
            self._add_field("target_blocks", target_blocks)
        if target_dig_position_offset != 2.25:
            self._add_field("target_dig_position_offset", target_dig_position_offset)

    def on_digging_start(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_digging_start", {"event": event, "target": target.value})
        return self

    def on_fail_during_digging(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_fail_during_digging", {"event": event, "target": target.value})
        return self

    def on_fail_during_searching(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_fail_during_searching", {"event": event, "target": target.value})
        return self

    def on_item_found(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_item_found", {"event": event, "target": target.value})
        return self

    def on_searching_start(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_searching_start", {"event": event, "target": target.value})
        return self

    def on_success(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_success", {"event": event, "target": target.value})
        return self


class EntityAIStompAttack(_BaseAIGoal):
    _identifier = "minecraft:behavior.stomp_attack"

    def __init__(
        self,
        attack_once: bool = False,
        attack_types: list[str] = [],
        cooldown_time: Seconds = 1,
        inner_boundary_time_increase: Seconds = 0.25,
        max_path_time: Seconds = 0.55,
        melee_fov: int = 90,
        min_path_time: Seconds = 0.2,
        no_damage_range_multiplier: float = 2,
        outer_boundary_time_increase: Seconds = 0.5,
        path_fail_time_increase: Seconds = 0.75,
        path_inner_boundary: float = 16,
        path_outer_boundary: float = 32,
        random_stop_interval: int = 0,
        reach_multiplier: float = 2,
        require_complete_path: bool = False,
        set_persistent: bool = False,
        speed_multiplier: float = 1,
        stomp_range_multiplier: float = 2,
        track_target: bool = False,
        x_max_rotation: int = 30,
        y_max_head_rotation: int = 30,
    ) -> None:
        """Compels an entity to attack a target by stomping on them.

        Parameters:
            attack_once (bool, optional): Description. Defaults to False.
            attack_types (list[str], optional): Description. Defaults to [].
            cooldown_time (Seconds, optional): Description. Defaults to 1.
            inner_boundary_time_increase (Seconds, optional): Description. Defaults to 0.25.
            max_path_time (Seconds, optional): Description. Defaults to 0.55.
            melee_fov (int, optional): Description. Defaults to 90.
            min_path_time (Seconds, optional): Description. Defaults to 0.2.
            no_damage_range_multiplier (float, optional): Description. Defaults to 2.
            outer_boundary_time_increase (Seconds, optional): Description. Defaults to 0.5.
            path_fail_time_increase (Seconds, optional): Description. Defaults to 0.75.
            path_inner_boundary (float, optional): Description. Defaults to 16.
            path_outer_boundary (float, optional): Description. Defaults to 32.
            random_stop_interval (int, optional): Description. Defaults to 0.
            reach_multiplier (float, optional): Description. Defaults to 2.
            require_complete_path (bool, optional): Description. Defaults to False.
            set_persistent (bool, optional): Description. Defaults to False.
            speed_multiplier (float, optional): Description. Defaults to 1.
            stomp_range_multiplier (float, optional): Description. Defaults to 2.
            track_target (bool, optional): Description. Defaults to False.
            x_max_rotation (int, optional): Description. Defaults to 30.
            y_max_head_rotation (int, optional): Description. Defaults to 30.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_stomp_attack
        """
        super().__init__("behavior.stomp_attack")

        if attack_once:
            self._add_field("attack_once", attack_once)
        if not attack_types == []:
            self._add_field("attack_types", attack_types)
        if cooldown_time != 1:
            self._add_field("cooldown_time", cooldown_time)
        if inner_boundary_time_increase != 0.25:
            self._add_field("inner_boundary_time_increase", inner_boundary_time_increase)
        if max_path_time != 0.55:
            self._add_field("max_path_time", max_path_time)
        if melee_fov != 90:
            self._add_field("melee_fov", melee_fov)
        if min_path_time != 0.2:
            self._add_field("min_path_time", min_path_time)
        if no_damage_range_multiplier != 2:
            self._add_field("no_damage_range_multiplier", no_damage_range_multiplier)
        if outer_boundary_time_increase != 0.5:
            self._add_field("outer_boundary_time_increase", outer_boundary_time_increase)
        if path_fail_time_increase != 0.75:
            self._add_field("path_fail_time_increase", path_fail_time_increase)
        if path_inner_boundary != 16:
            self._add_field("path_inner_boundary", path_inner_boundary)
        if path_outer_boundary != 32:
            self._add_field("path_outer_boundary", path_outer_boundary)
        if random_stop_interval != 0:
            self._add_field("random_stop_interval", random_stop_interval)
        if reach_multiplier != 2:
            self._add_field("reach_multiplier", reach_multiplier)
        if require_complete_path:
            self._add_field("require_complete_path", require_complete_path)
        if set_persistent:
            self._add_field("set_persistent", set_persistent)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)
        if stomp_range_multiplier != 2:
            self._add_field("stomp_range_multiplier", stomp_range_multiplier)
        if track_target:
            self._add_field("track_target", track_target)
        if x_max_rotation != 30:
            self._add_field("x_max_rotation", x_max_rotation)
        if y_max_head_rotation != 30:
            self._add_field("y_max_head_rotation", y_max_head_rotation)

    def on_attack(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_attack", {"event": event, "target": target.value})
        return self


class EntityAIFollowMob(_BaseAIGoal):
    _identifier = "minecraft:behavior.follow_mob"

    def __init__(
        self,
        search_range: int = 0,
        speed_multiplier: float = 1.0,
        stop_distance: int = 2,
        filters: Filter = None,
        preferred_actor_type: str = None,
        use_home_position_restriction: bool = False,
    ) -> None:
        """Compels an entity to follow and gather around other mobs of the same type.

        Parameters:
            search_range (int, optional): Description. Defaults to 0.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            stop_distance (int, optional): Description. Defaults to 2.
            filters (Filter, optional): Description. Defaults to None.
            preferred_actor_type (str, optional): Description. Defaults to None.
            use_home_position_restriction (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_follow_mob
        """
        super().__init__("behavior.follow_mob")
        if search_range != 0:
            self._add_field("search_range", search_range)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if stop_distance != 2:
            self._add_field("stop_distance", stop_distance)
        if filters != None:
            self._add_field("filters", filters)
        if preferred_actor_type != None:
            self._add_field("preferred_actor_type", preferred_actor_type)
        if use_home_position_restriction:
            self._add_field("use_home_position_restriction", use_home_position_restriction)


class EntityAIRandomSwim(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_swim"

    def __init__(
        self,
        avoid_surface: bool = True,
        interval: int = 120,
        speed_multiplier: float = 1.0,
        xz_dist: int = 10,
        y_dist: int = 7,
    ) -> None:
        """Compels an entity to swim in a random point in water.

        Parameters:
            avoid_surface (bool, optional): Description. Defaults to True.
            interval (int, optional): Description. Defaults to 120.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            xz_dist (int, optional): Description. Defaults to 10.
            y_dist (int, optional): Description. Defaults to 7.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_swim
        """
        super().__init__("behavior.random_swim")

        if not avoid_surface:
            self._add_field("avoid_surface", avoid_surface)
        if interval != 120:
            self._add_field("interval", interval)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if xz_dist != 10:
            self._add_field("xz_dist", xz_dist)
        if y_dist != 7:
            self._add_field("y_dist", y_dist)


class EntityAIRandomBreach(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_breach"

    def __init__(
        self,
        interval: int = 120,
        speed_multiplier: float = 1.0,
        xz_dist: int = 10,
        y_dist: int = 7,
        cooldown_time: Seconds = 10,
    ) -> None:
        """Compels an entity to breach the surface of the water at a random interval.

        Parameters:
            interval (int, optional): Description. Defaults to 120.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            xz_dist (int, optional): Description. Defaults to 10.
            y_dist (int, optional): Description. Defaults to 7.
            cooldown_time (Seconds, optional): Description. Defaults to 10.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_breach
        """
        super().__init__("behavior.random_breach")

        if interval != 120:
            self._add_field("interval", interval)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if xz_dist != 10:
            self._add_field("xz_dist", xz_dist)
        if y_dist != 7:
            self._add_field("y_dist", y_dist)
        if cooldown_time != 10:
            self._add_field("cooldown_time", cooldown_time)


class EntityAIRandomHover(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_hover"

    def __init__(
        self,
        hover_height: tuple[float, float] = (0.0, 0.0),
        interval: int = 120,
        speed_multiplier: float = 1.0,
        xz_dist: int = 10,
        y_dist: int = 7,
        y_offset: float = 0.0,
    ) -> None:
        """Compels an entity to hover around randomly, close to the surface.

        Parameters:
            hover_height (tuple[float, float], optional): Description. Defaults to (0.0, 0.0).
            interval (int, optional): Description. Defaults to 120.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            xz_dist (int, optional): Description. Defaults to 10.
            y_dist (int, optional): Description. Defaults to 7.
            y_offset (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_hover
        """
        super().__init__("behavior.random_hover")

        if hover_height != (0.0, 0.0):
            self._add_field("hover_height", hover_height)
        if interval != 120:
            self._add_field("interval", interval)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if xz_dist != 10:
            self._add_field("xz_dist", xz_dist)
        if y_dist != 7:
            self._add_field("y_dist", y_dist)
        if y_offset != 0.0:
            self._add_field("y_offset", y_offset)


class EntityAIRoar(_BaseAIGoal):
    _identifier = "minecraft:behavior.roar"

    def __init__(
        self,
        duration: Seconds = 0.0,
    ) -> None:
        """Compels the entity to roar at another entity based on data in minecraft:anger_level. When the anger threshold specified in minecraft:anger_level has been reached, this entity will roar for the specified amount of time, look at the other entity, apply anger boost towards it, and finally target it.

        Parameters:
            duration (Seconds, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_roar
        """
        super().__init__("behavior.roar")

        if duration != 0.0:
            self._add_field("duration", duration)


class EntityAIFloatWander(_BaseAIGoal):
    _identifier = "minecraft:behavior.float_wander"

    def __init__(
        self,
        additional_collision_buffer: bool = False,
        allow_navigating_through_liquids: bool = False,
        float_duration: tuple[Seconds, Seconds] = (0.0, 0.0),
        float_wander_has_move_control: bool = True,
        must_reach: bool = False,
        navigate_around_surface: bool = False,
        random_reselect: bool = False,
        surface_xz_dist: int = 0,
        surface_y_dist: int = 0,
        use_home_position_restriction: bool = True,
        xz_dist: int = 10,
        y_dist: int = 7,
        y_offset: float = 0.0,
    ) -> None:
        """Allows the mob to float around like the Ghast.

        Parameters:
            additional_collision_buffer (bool, optional): Description. Defaults to False.
            allow_navigating_through_liquids (bool, optional): Description. Defaults to False.
            float_duration (tuple[Seconds, Seconds], optional): Description. Defaults to (0.0, 0.0).
            float_wander_has_move_control (bool, optional): Description. Defaults to True.
            must_reach (bool, optional): Description. Defaults to False.
            navigate_around_surface (bool, optional): Description. Defaults to False.
            random_reselect (bool, optional): Description. Defaults to False.
            surface_xz_dist (int, optional): Description. Defaults to 0.
            surface_y_dist (int, optional): Description. Defaults to 0.
            use_home_position_restriction (bool, optional): Description. Defaults to True.
            xz_dist (int, optional): Description. Defaults to 10.
            y_dist (int, optional): Description. Defaults to 7.
            y_offset (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_float_wander
        """
        super().__init__("behavior.float_wander")

        if additional_collision_buffer:
            self._add_field("additional_collision_buffer", additional_collision_buffer)
        if allow_navigating_through_liquids:
            self._add_field("allow_navigating_through_liquids", allow_navigating_through_liquids)
        if float_duration != (0.0, 0.0):
            self._add_field("float_duration", float_duration)
        if not float_wander_has_move_control:
            self._add_field("float_wander_has_move_control", float_wander_has_move_control)
        if must_reach:
            self._add_field("must_reach", must_reach)
        if navigate_around_surface:
            self._add_field("navigate_around_surface", navigate_around_surface)
        if random_reselect:
            self._add_field("random_reselect", random_reselect)
        if surface_xz_dist != 0:
            self._add_field("surface_xz_dist", surface_xz_dist)
        if surface_y_dist != 0:
            self._add_field("surface_y_dist", surface_y_dist)
        if not use_home_position_restriction:
            self._add_field("use_home_position_restriction", use_home_position_restriction)
        if xz_dist != 10:
            self._add_field("xz_dist", xz_dist)
        if y_dist != 7:
            self._add_field("y_dist", y_dist)
        if y_offset != 0.0:
            self._add_field("y_offset", y_offset)


class EntityAILayDown(_BaseAIGoal):
    _identifier = "minecraft:behavior.lay_down"

    def __init__(
        self,
        interval: int = 120,
        random_stop_interval: int = 120,
    ) -> None:
        """Compels an entity randomly lay down for a period of time.

        Parameters:
            interval (int, optional): Description. Defaults to 120.
            random_stop_interval (int, optional): Description. Defaults to 120.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_lay_down
        """
        super().__init__("behavior.lay_down")

        if interval != 120:
            self._add_field("interval", interval)
        if random_stop_interval != 120:
            self._add_field("random_stop_interval", random_stop_interval)


class EntityAIMeleeBoxAttack(_BaseAIGoal):
    _identifier = "minecraft:behavior.melee_box_attack"

    def __init__(
        self,
        attack_once: bool = False,
        attack_types: list[str] = [],
        can_spread_on_fire: bool = False,
        cooldown_time: Seconds = 1,
        horizontal_reach: float = 0.8,
        inner_boundary_time_increase: Seconds = 0.25,
        max_path_time: Seconds = 0.55,
        melee_fov: int = 90,
        min_path_time: Seconds = 0.2,
        outer_boundary_time_increase: Seconds = 0.5,
        path_fail_time_increase: Seconds = 0.75,
        path_inner_boundary: float = 16,
        path_outer_boundary: float = 32,
        random_stop_interval: int = 0,
        box_increase: float = 2,
        require_complete_path: bool = False,
        set_persistent: bool = False,
        speed_multiplier: float = 1,
        track_target: bool = False,
        x_max_rotation: int = 30,
        y_max_head_rotation: int = 30,
    ) -> None:
        """Compels an entity to attack a target by stomping on them.

        Parameters:
            attack_once (bool, optional): Description. Defaults to False.
            attack_types (list[str], optional): Description. Defaults to [].
            can_spread_on_fire (bool, optional): Description. Defaults to False.
            cooldown_time (Seconds, optional): Description. Defaults to 1.
            horizontal_reach (float, optional): Description. Defaults to 0.8.
            inner_boundary_time_increase (Seconds, optional): Description. Defaults to 0.25.
            max_path_time (Seconds, optional): Description. Defaults to 0.55.
            melee_fov (int, optional): Description. Defaults to 90.
            min_path_time (Seconds, optional): Description. Defaults to 0.2.
            outer_boundary_time_increase (Seconds, optional): Description. Defaults to 0.5.
            path_fail_time_increase (Seconds, optional): Description. Defaults to 0.75.
            path_inner_boundary (float, optional): Description. Defaults to 16.
            path_outer_boundary (float, optional): Description. Defaults to 32.
            random_stop_interval (int, optional): Description. Defaults to 0.
            box_increase (float, optional): Description. Defaults to 2.
            require_complete_path (bool, optional): Description. Defaults to False.
            set_persistent (bool, optional): Description. Defaults to False.
            speed_multiplier (float, optional): Description. Defaults to 1.
            track_target (bool, optional): Description. Defaults to False.
            x_max_rotation (int, optional): Description. Defaults to 30.
            y_max_head_rotation (int, optional): Description. Defaults to 30.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_melee_box_attack
        """
        super().__init__("behavior.melee_box_attack")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.20.50")

        if attack_once:
            self._add_field("attack_once", attack_once)
        if not attack_types == []:
            self._add_field("attack_types", attack_types)
        if can_spread_on_fire:
            self._add_field("can_spread_on_fire", can_spread_on_fire)
        if cooldown_time != 1:
            self._add_field("cooldown_time", cooldown_time)
        if horizontal_reach != 0.8:
            self._add_field("horizontal_reach", horizontal_reach)
        if inner_boundary_time_increase != 0.25:
            self._add_field("inner_boundary_time_increase", inner_boundary_time_increase)
        if max_path_time != 0.55:
            self._add_field("max_path_time", max_path_time)
        if melee_fov != 90:
            self._add_field("melee_fov", melee_fov)
        if min_path_time != 0.2:
            self._add_field("min_path_time", min_path_time)
        if outer_boundary_time_increase != 0.5:
            self._add_field("outer_boundary_time_increase", outer_boundary_time_increase)
        if path_fail_time_increase != 0.75:
            self._add_field("path_fail_time_increase", path_fail_time_increase)
        if path_inner_boundary != 16:
            self._add_field("path_inner_boundary", path_inner_boundary)
        if path_outer_boundary != 32:
            self._add_field("path_outer_boundary", path_outer_boundary)
        if random_stop_interval != 0:
            self._add_field("random_stop_interval", random_stop_interval)
        if box_increase != 2:
            self._add_field("box_increase", box_increase)
        if require_complete_path:
            self._add_field("require_complete_path", require_complete_path)
        if set_persistent:
            self._add_field("set_persistent", set_persistent)
        if speed_multiplier != 1:
            self._add_field("speed_multiplier", speed_multiplier)
        if track_target:
            self._add_field("track_target", track_target)
        if x_max_rotation != 30:
            self._add_field("x_max_rotation", x_max_rotation)
        if y_max_head_rotation != 30:
            self._add_field("y_max_head_rotation", y_max_head_rotation)

    def on_attack(self, event: str, target: FilterSubject = FilterSubject.Self):
        self._add_field("on_attack", {"event": event, "target": target.value})
        return self


class EntityAITimerFlag1(_BaseAIGoal):
    _identifier = "minecraft:behavior.timer_flag_1"

    def __init__(
        self,
        cooldown_range: tuple[Seconds, Seconds] = (10.0, 10.0),
        duration_range: tuple[Seconds, Seconds] = (2.0, 2.0),
        *control_flags: ControlFlags,
    ) -> None:
        """Fires an event when this behavior starts, then waits for a duration before stopping. When stopping to due the timeout or due to being interrupted by another behavior, the goal fires another event. query.timer_flag_1 will return 1.0 on both the client and server when this behavior is running, and 0.0 otherwise.

        Parameters:
            cooldown_range (tuple[Seconds, Seconds], optional): Description. Defaults to (10.0, 10.0).
            duration_range (tuple[Seconds, Seconds], optional): Description. Defaults to (2.0, 2.0).

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_timer_flag_1
        """
        super().__init__("behavior.timer_flag_1")

        if cooldown_range != (10.0, 10.0):
            if (
                not isinstance(cooldown_range, tuple)
                or not len(cooldown_range) == 2
                or not all(isinstance(i, (int, float)) for i in cooldown_range)
            ):
                raise ValueError("cooldown_range must be a tuple of 2 numbers (int or float)")
            self._add_field("cooldown_range", {"min": cooldown_range[0], "max": cooldown_range[1]})
        if duration_range != (2.0, 2.0):
            if (
                not isinstance(duration_range, tuple)
                or not len(duration_range) == 2
                or not all(isinstance(i, (int, float)) for i in duration_range)
            ):
                raise ValueError("duration_range must be a tuple of 2 numbers (int or float)")
            self._add_field("duration_range", {"min": duration_range[0], "max": duration_range[1]})
        if not control_flags == []:
            self._add_field("control_flags", control_flags)

    def on_end(self, on_end: str, subject: FilterSubject = FilterSubject.Self):
        self._add_field("on_end", {"event": on_end, "target": subject})
        return self

    def on_start(self, on_start: str, subject: FilterSubject = FilterSubject.Self):
        self._add_field("on_start", {"event": on_start, "target": subject})
        return self


class EntityAITimerFlag2(_BaseAIGoal):
    _identifier = "minecraft:behavior.timer_flag_2"

    def __init__(
        self,
        cooldown_range: tuple[Seconds, Seconds] = (10.0, 10.0),
        duration_range: tuple[Seconds, Seconds] = (2.0, 2.0),
        *control_flags: ControlFlags,
    ) -> None:
        """Fires an event when this behavior starts, then waits for a duration before stopping. When stopping to due the timeout or due to being interrupted by another behavior, the goal fires another event. query.timer_flag_2 will return 1.0 on both the client and server when this behavior is running, and 0.0 otherwise.

        Parameters:
            cooldown_range (tuple[Seconds, Seconds], optional): Description. Defaults to (10.0, 10.0).
            duration_range (tuple[Seconds, Seconds], optional): Description. Defaults to (2.0, 2.0).

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_timer_flag_2
        """
        super().__init__("behavior.timer_flag_2")

        if cooldown_range != (10.0, 10.0):
            if (
                not isinstance(cooldown_range, tuple)
                or not len(cooldown_range) == 2
                or not all(isinstance(i, (int, float)) for i in cooldown_range)
            ):
                raise ValueError("cooldown_range must be a tuple of 2 numbers (int or float)")
            self._add_field("cooldown_range", {"min": cooldown_range[0], "max": cooldown_range[1]})
        if duration_range != (2.0, 2.0):
            if (
                not isinstance(duration_range, tuple)
                or not len(duration_range) == 2
                or not all(isinstance(i, (int, float)) for i in duration_range)
            ):
                raise ValueError("duration_range must be a tuple of 2 numbers (int or float)")
            self._add_field("duration_range", {"min": duration_range[0], "max": duration_range[1]})
        if not control_flags == []:
            self._add_field("control_flags", control_flags)

    def on_end(self, on_end: str, subject: FilterSubject = FilterSubject.Self):
        self._add_field("on_end", {"event": on_end, "target": subject})
        return self

    def on_start(self, on_start: str, subject: FilterSubject = FilterSubject.Self):
        self._add_field("on_start", {"event": on_start, "target": subject})
        return self


class EntityAITimerFlag3(_BaseAIGoal):
    _identifier = "minecraft:behavior.timer_flag_3"

    def __init__(
        self,
        cooldown_range: tuple[Seconds, Seconds] = (10.0, 10.0),
        duration_range: tuple[Seconds, Seconds] = (2.0, 2.0),
        *control_flags: ControlFlags,
    ) -> None:
        """Fires an event when this behavior starts, then waits for a duration before stopping. When stopping to due the timeout or due to being interrupted by another behavior, the goal fires another event. query.timer_flag_3 will return 1.0 on both the client and server when this behavior is running, and 0.0 otherwise.

        Parameters:
            cooldown_range (tuple[Seconds, Seconds], optional): Description. Defaults to (10.0, 10.0).
            duration_range (tuple[Seconds, Seconds], optional): Description. Defaults to (2.0, 2.0).

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_timer_flag_3
        """
        super().__init__("behavior.timer_flag_3")

        if cooldown_range != (10.0, 10.0):
            if (
                not isinstance(cooldown_range, tuple)
                or not len(cooldown_range) == 2
                or not all(isinstance(i, (int, float)) for i in cooldown_range)
            ):
                raise ValueError("cooldown_range must be a tuple of 2 numbers (int or float)")
            self._add_field("cooldown_range", {"min": cooldown_range[0], "max": cooldown_range[1]})
        if duration_range != (2.0, 2.0):
            if (
                not isinstance(duration_range, tuple)
                or not len(duration_range) == 2
                or not all(isinstance(i, (int, float)) for i in duration_range)
            ):
                raise ValueError("duration_range must be a tuple of 2 numbers (int or float)")
            self._add_field("duration_range", {"min": duration_range[0], "max": duration_range[1]})
        if not control_flags == []:
            self._add_field("control_flags", control_flags)

    def on_end(self, on_end: str, subject: FilterSubject = FilterSubject.Self):
        self._add_field("on_end", {"event": on_end, "target": subject})
        return self

    def on_start(self, on_start: str, subject: FilterSubject = FilterSubject.Self):
        self._add_field("on_start", {"event": on_start, "target": subject})
        return self


class EntityAIRunAroundLikeCrazy(_BaseAIGoal):
    _identifier = "minecraft:behavior.run_around_like_crazy"

    def __init__(
        self,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Compels an entity to run around without a set goal.

        Parameters:
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_run_around_like_crazy
        """
        super().__init__("behavior.run_around_like_crazy")

        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAISlimeKeepOnJumping(_BaseAIGoal):
    _identifier = "minecraft:behavior.slime_keep_on_jumping"

    def __init__(
        self,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Compels an entity to continuously jump around like a slime.

        Parameters:
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_slime_keep_on_jumping
        """
        super().__init__("behavior.slime_keep_on_jumping")

        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIRiseToLiquidLevel(_BaseAIGoal):
    _identifier = "minecraft:behavior.rise_to_liquid_level"

    def __init__(
        self,
        liquid_y_offset: float = 0.0,
        rise_delta: float = 0.0,
        sink_delta: float = 0.0,
    ) -> None:
        """Compels an entity to rise to the top of a liquid block if they are located in one or have spawned under a liquid block.

        Parameters:
            liquid_y_offset (float, optional): Target distance down from the liquid surface. i.e. Positive values move the target Y down. Defaults to 0.0.
            rise_delta (float, optional): Movement up in Y per tick when below the liquid surface. Defaults to 0.0.
            sink_delta (float, optional): Movement down in Y per tick when above the liquid surface. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_rise_to_liquid_level
        """
        super().__init__("behavior.rise_to_liquid_level")

        if liquid_y_offset != 0.0:
            self._add_field("liquid_y_offset", liquid_y_offset)
        if rise_delta != 0.0:
            self._add_field("rise_delta", rise_delta)
        if sink_delta != 0.0:
            self._add_field("sink_delta", sink_delta)


class EntityAITakeBlock(_BaseAIGoal):
    _identifier = "minecraft:behavior.take_block"

    def __init__(
        self,
        affected_by_griefing_rule: bool = False,
        blocks: list[MinecraftBlockDescriptor] = [],
        can_take: Filter = None,
        chance: float = 0.0,
        requires_line_of_sight: bool = False,
        xz_range: Vector2D = (0, 0),
        y_range: Vector2D = (0, 0),
    ):
        """Compels an entity to take blocks from the world, such as Endermen taking blocks.

        Parameters:
            affected_by_griefing_rule (bool, optional): Description. Defaults to False.
            blocks (list[MinecraftBlockDescriptor], optional): Description. Defaults to [].
            can_take (Filter, optional): Description. Defaults to None.
            chance (float, optional): Description. Defaults to 0.0.
            requires_line_of_sight (bool, optional): Description. Defaults to False.
            xz_range (Vector2D, optional): Description. Defaults to (0, 0).
            y_range (Vector2D, optional): Description. Defaults to (0, 0).

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_take_block
        """
        super().__init__("behavior.take_block")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.20.100")

        if affected_by_griefing_rule:
            self._add_field("affected_by_griefing_rule", affected_by_griefing_rule)
        if blocks:
            self._add_field("blocks", blocks)
        if can_take is not None:
            self._add_field("can_take", can_take)
        if chance != 0.0:
            self._add_field("chance", chance)
        if requires_line_of_sight:
            self._add_field("requires_line_of_sight", requires_line_of_sight)
        if xz_range != (0, 0):
            self._add_field("xz_range", xz_range)
        if y_range != (0, 0):
            self._add_field("y_range", y_range)

    def on_take(self, event: str, target: FilterSubject = FilterSubject.Self):
        """Sets the event to be triggered when the entity successfully takes a block.

        Parameters:
            event (str): The name of the event to trigger.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        Returns:
            self: Returns the current instance for method chaining.
        """
        self._add_field("on_take", {"event": event, "target": target.value})
        return self


class EntityAIPlaceBlock(_BaseAIGoal):
    _identifier = "minecraft:behavior.place_block"

    def __init__(
        self,
        affected_by_griefing_rule: bool = False,
        can_place: Filter = None,
        chance: float = 0.0,
        placeable_carried_blocks: list[MinecraftBlockDescriptor] = [],
        xz_range: Vector2D = (0, 0),
        y_range: Vector2D = (0, 0),
    ) -> None:
        """Compels an entity to place blocks in the world, such as Copper Golems placing statues.

        Parameters:
            affected_by_griefing_rule (bool, optional): Description. Defaults to False.
            can_place (Filter, optional): Description. Defaults to None.
            chance (float, optional): Description. Defaults to 0.0.
            placeable_carried_blocks (list[MinecraftBlockDescriptor], optional): Description. Defaults to [].
            xz_range (Vector2D, optional): Description. Defaults to (0, 0).
            y_range (Vector2D, optional): Description. Defaults to (0, 0).

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_place_block
        """
        super().__init__("behavior.place_block")
        self._enforce_version(ENTITY_SERVER_VERSION, "1.20.100")

        if affected_by_griefing_rule:
            self._add_field("affected_by_griefing_rule", affected_by_griefing_rule)
        if can_place is not None:
            self._add_field("can_place", can_place)
        if chance:
            self._add_field("chance", chance)
        if placeable_carried_blocks:
            self._add_field("placeable_carried_blocks", placeable_carried_blocks)
        if xz_range != (0, 0):
            self._add_field("xz_range", xz_range)
        if y_range != (0, 0):
            self._add_field("y_range", y_range)
        self._add_field("randomly_placeable_blocks", [])

    def on_place(self, event: str, target: FilterSubject = FilterSubject.Self):
        """Sets the event to be triggered when the entity successfully places a block.

        Parameters:
            event (str): The name of the event to trigger.
            target (FilterSubject, optional): The target of the event. Defaults to FilterSubject.Self.

        Returns:
            self: Returns the current instance for method chaining.
        """
        self._add_field("on_place", {"event": event, "target": target.value})
        return self

    def randomly_placeable_block(
        self,
        block: MinecraftBlockDescriptor,
        filter: Filter,
        states: dict[str, Any] = None,
    ):
        """Sets the block that the entity can randomly place.

        Parameters:
            block (MinecraftBlockDescriptor): The block descriptor for which the block should be randomly placed.
            filter (Filter): The filter that determines when the block can be placed.
            states (dict[str, Any], optional): The states of the block to be placed.

        Returns:
            self: Returns the current instance for method chaining.
        """
        self._get_field("randomly_placeable_blocks").append(
            {
                "block": {"name": block.name, "states": states if states else {}},
                "filter": filter,
            }
        )
        return self


class EntityAIMoveToRandomBlock(_BaseAIGoal):
    _identifier = "minecraft:behavior.move_to_random_block"

    def __init__(
        self,
        block_distance: float = 16,
        speed_multiplier: float = 1.0,
        within_radius: float = 0.0,
    ) -> None:
        """Compels a mob to move towards a randomly chosen block.

        Parameters:
            block_distance (float, optional): Description. Defaults to 16.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            within_radius (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_move_to_random_block
        """
        super().__init__("behavior.move_to_random_block")

        if block_distance != 16:
            self._add_field("block_distance", block_distance)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if within_radius != 0.0:
            self._add_field("within_radius", within_radius)


class EntityAIDig(_BaseAIGoal):
    _identifier = "minecraft:behavior.dig"

    def __init__(
        self,
        duration: Seconds = 0,
        idle_time: Seconds = 0,
        allow_dig_when_named: bool = False,
        digs_in_daylight: bool = False,
        suspicion_is_disturbance: bool = False,
        vibration_is_disturbance: bool = False,
    ) -> None:
        """Allows this entity to dig into the ground before despawning.

        Parameters:
            duration (Seconds, optional): Description. Defaults to 0.
            idle_time (Seconds, optional): Description. Defaults to 0.
            allow_dig_when_named (bool, optional): Description. Defaults to False.
            digs_in_daylight (bool, optional): Description. Defaults to False.
            suspicion_is_disturbance (bool, optional): Description. Defaults to False.
            vibration_is_disturbance (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_dig
        """
        super().__init__("behavior.dig")

        if duration != 0:
            self._add_field("duration", duration)
        if idle_time != 0:
            self._add_field("idle_time", idle_time)
        if allow_dig_when_named:
            self._add_field("allow_dig_when_named", allow_dig_when_named)
        if digs_in_daylight:
            self._add_field("digs_in_daylight", digs_in_daylight)
        if suspicion_is_disturbance:
            self._add_field("suspicion_is_disturbance", suspicion_is_disturbance)
        if vibration_is_disturbance:
            self._add_field("vibration_is_disturbance", vibration_is_disturbance)

    def on_start(self, event: str, target: FilterSubject = FilterSubject.Self):
        """Sets an event to run when the dig goal starts.

        Parameters:
            event (str): The event name to trigger.
            target (FilterSubject, optional): The event target. Defaults to FilterSubject.Self.

        Returns:
            self: for chaining.
        """
        self._add_field("on_start", {"event": event, "target": target.value})
        return self


class EntityAIDrinkMilk(_BaseAIGoal):
    _identifier = "minecraft:behavior.drink_milk"

    def __init__(
        self,
        cooldown_seconds: Seconds = 5,
        filters: Filter = None,
    ) -> None:
        """Allows the mob to drink milk based on specified environment conditions.

        Parameters:
            cooldown_seconds (Seconds, optional): Description. Defaults to 5.
            filters (Filter, optional): Description. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_drink_milk
        """
        super().__init__("behavior.drink_milk")

        if cooldown_seconds != 5:
            self._add_field("cooldown_seconds", cooldown_seconds)
        if filters is not None:
            self._add_field("filters", filters)


class EntityAIAvoidBlock(_BaseAIGoal):
    _identifier = "minecraft:behavior.avoid_block"

    def __init__(
        self,
        tick_interval: int = 1,
        search_range: int = 0,
        search_height: int = 0,
        walk_speed_modifier: float = 1.0,
        sprint_speed_modifier: float = 1.0,
        avoid_block_sound: str = None,
        sound_interval: list[float] = None,
        target_selection_method: Literal["nearest"] = "nearest",
        target_blocks: list[MinecraftBlockDescriptor] = [],
    ) -> None:
        """Allows this entity to avoid certain blocks.

        Parameters:
            tick_interval (int, optional): Description. Defaults to 1.
            search_range (int, optional): Description. Defaults to 0.
            search_height (int, optional): Description. Defaults to 0.
            walk_speed_modifier (float, optional): Description. Defaults to 1.0.
            sprint_speed_modifier (float, optional): Description. Defaults to 1.0.
            avoid_block_sound (str, optional): Description. Defaults to None.
            sound_interval (list[float], optional): Description. Defaults to None.
            target_selection_method (Literal['nearest'], optional): Description. Defaults to 'nearest'.
            target_blocks (list[MinecraftBlockDescriptor], optional): Description. Defaults to [].

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_avoid_block
        """
        super().__init__("behavior.avoid_block")

        if tick_interval != 1:
            self._add_field("tick_interval", tick_interval)
        if search_range != 0:
            self._add_field("search_range", search_range)
        if search_height != 0:
            self._add_field("search_height", search_height)
        if walk_speed_modifier != 1.0:
            self._add_field("walk_speed_modifier", walk_speed_modifier)
        if sprint_speed_modifier != 1.0:
            self._add_field("sprint_speed_modifier", sprint_speed_modifier)
        if avoid_block_sound is not None:
            self._add_field("avoid_block_sound", avoid_block_sound)
        if sound_interval is not None:
            if not isinstance(sound_interval, list):
                raise TypeError("sound_interval must be a list of two floats")
            if len(sound_interval) != 2:
                raise ValueError("sound_interval must be a list of two floats")
            self._add_field(
                "sound_interval",
                {"range_min": min(sound_interval), "range_max": max(sound_interval)},
            )
        if target_selection_method != "nearest":
            self._add_field("target_selection_method", target_selection_method)
        if not target_blocks == []:
            self._add_field("target_blocks", target_blocks)

        self._add_field("on_escape", [])

    def on_escape(self, event: str, target: FilterSubject = FilterSubject.Self):
        """Add an escape event to be triggered when the mob escapes the avoided block.

        Parameters:
            event (str): The event name to trigger.
            target (FilterSubject, optional): The event target. Defaults to FilterSubject.Self.

        Returns:
            self: for chaining.
        """
        self._get_field("on_escape").append({"event": event, "target": target.value})
        return self


class EntityAIUseKineticWeapon(_BaseAIGoal):
    _identifier = "minecraft:behavior.use_kinetic_weapon"

    def __init__(
        self,
        approach_distance: float = None,
        reposition_distance: float = None,
        reposition_speed_multiplier: float = None,
        cooldown_distance: float = None,
        cooldown_speed_multiplier: float = None,
        weapon_reach_multiplier: float = None,
        weapon_min_speed_multiplier: float = None,
        min_path_time: float = None,
        max_path_time: float = None,
        path_fail_time_increase: float = None,
        inner_boundary_time_increase: float = None,
        outer_boundary_time_increase: float = None,
        path_inner_boundary: float = None,
        path_outer_boundary: float = None,
        speed_multiplier: float = None,
        require_complete_path: bool = None,
        track_target: bool = None,
        cooldown_time: float = None,
        melee_fov: float = None,
        x_max_rotation: float = None,
        y_max_head_rotation: float = None,
        random_stop_interval: int = None,
        attack_once: bool = None,
        hijack_mount_navigation: bool = None,
    ) -> None:
        """Allows a mob to make use of items with a "minecraft:kinetic_weapon" item component.

        Parameters:
            approach_distance (float, optional): The distance to the target within which the mob begins using its kinetic weapon. Defaults to None.
            reposition_distance (float, optional): The distance the mob retreats to once the target is closer than the midpoint of the item's "minecraft:kinetic_weapon" component's minimum and maximum "reach". Defaults to None.
            reposition_speed_multiplier (float, optional): Multiplier applied to the mob's movement speed while repositioning. Defaults to None.
            cooldown_distance (float, optional): The distance the mob retreats to after all of the item's "minecraft:kinetic_weapon" component's "max_duration" values have elapsed. Defaults to None.
            cooldown_speed_multiplier (float, optional): Multiplier applied to the mob's movement speed while on cooldown. Defaults to None.
            weapon_reach_multiplier (float, optional): Multiplier applied to the item's "minecraft:kinetic_weapon" component's "reach". Defaults to None.
            weapon_min_speed_multiplier (float, optional): Multiplier applied to each "min_speed" and "min_relative_speed" condition in the item's "minecraft:kinetic_weapon" component. Defaults to None.
            min_path_time (float, optional): Minimum base time, in seconds, before recalculating a new attack path to the target (before increases are applied). Defaults to None.
            max_path_time (float, optional): Maximum base time, in seconds, before recalculating a new attack path to the target (before increases are applied). Defaults to None.
            path_fail_time_increase (float, optional): Time, in seconds, added to the attack path recalculation interval when the mob cannot move along the current path. Defaults to None.
            inner_boundary_time_increase (float, optional): Time, in seconds, added to the attack path recalculation interval when the target is beyond "path_inner_boundary". Defaults to None.
            outer_boundary_time_increase (float, optional): Time, in seconds, added to the attack path recalculation interval when the target is beyond "path_outer_boundary". Defaults to None.
            path_inner_boundary (float, optional): Distance at which to increase attack path recalculation by "inner_boundary_time_increase". Defaults to None.
            path_outer_boundary (float, optional): Distance at which to increase attack path recalculation by "outer_boundary_time_increase". Defaults to None.
            speed_multiplier (float, optional): Multiplier applied to the mob's movement speed when moving toward its target. Defaults to None.
            require_complete_path (bool, optional): Specifies whether a full navigation path from the mob to the target is required. Defaults to None.
            track_target (bool, optional): Allows the mob to track its target even if it lacks a hard-coded sensing component. Defaults to None.
            cooldown_time (float, optional): Cooldown time, in seconds, between consecutive attacks. Defaults to None.
            melee_fov (float, optional): Field of view, in degrees, used by the hard-coded sensing component to detect a valid attack target. Defaults to None.
            x_max_rotation (float, optional): Maximum rotation, in degrees, on the X-axis while the mob is trying to look at its target. Defaults to None.
            y_max_head_rotation (float, optional): Maximum rotation, in degrees, on the Y-axis while the mob is trying to look at its target. Defaults to None.
            random_stop_interval (int, optional): Defines a 1-in-N chance for the mob to stop its current attack, where N equals "random_stop_interval". Defaults to None.
            attack_once (bool, optional): Allows the mob to perform this melee attack behavior only once during its lifetime. Defaults to None.
            hijack_mount_navigation (bool, optional): Allows a mob to override its mount's navigation behavior with the one defined by this goal. ## Documentation reference:. Defaults to None.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_use_kinetic_weapon
        """
        super().__init__("behavior.use_kinetic_weapon")
        if approach_distance is not None:
            self._add_field("approach_distance", approach_distance)
        if reposition_distance is not None:
            self._add_field("reposition_distance", reposition_distance)
        if reposition_speed_multiplier is not None:
            self._add_field("reposition_speed_multiplier", reposition_speed_multiplier)
        if cooldown_distance is not None:
            self._add_field("cooldown_distance", cooldown_distance)
        if cooldown_speed_multiplier is not None:
            self._add_field("cooldown_speed_multiplier", cooldown_speed_multiplier)
        if weapon_reach_multiplier is not None:
            self._add_field("weapon_reach_multiplier", weapon_reach_multiplier)
        if weapon_min_speed_multiplier is not None:
            self._add_field("weapon_min_speed_multiplier", weapon_min_speed_multiplier)
        if min_path_time is not None:
            self._add_field("min_path_time", min_path_time)
        if max_path_time is not None:
            self._add_field("max_path_time", max_path_time)
        if path_fail_time_increase is not None:
            self._add_field("path_fail_time_increase", path_fail_time_increase)
        if inner_boundary_time_increase is not None:
            self._add_field("inner_boundary_time_increase", inner_boundary_time_increase)
        if outer_boundary_time_increase is not None:
            self._add_field("outer_boundary_time_increase", outer_boundary_time_increase)
        if path_inner_boundary is not None:
            self._add_field("path_inner_boundary", path_inner_boundary)
        if path_outer_boundary is not None:
            self._add_field("path_outer_boundary", path_outer_boundary)
        if speed_multiplier is not None:
            self._add_field("speed_multiplier", speed_multiplier)
        if require_complete_path is not None:
            self._add_field("require_complete_path", require_complete_path)
        if track_target is not None:
            self._add_field("track_target", track_target)
        if cooldown_time is not None:
            self._add_field("cooldown_time", cooldown_time)
        if melee_fov is not None:
            self._add_field("melee_fov", melee_fov)
        if x_max_rotation is not None:
            self._add_field("x_max_rotation", x_max_rotation)
        if y_max_head_rotation is not None:
            self._add_field("y_max_head_rotation", y_max_head_rotation)
        if random_stop_interval is not None:
            self._add_field("random_stop_interval", random_stop_interval)
        if attack_once is not None:
            self._add_field("attack_once", attack_once)


class EntityAIHide(_BaseAIGoal):
    _identifier = "minecraft:behavior.hide"

    def __init__(
        self,
        duration: Seconds = 1.0,
        poi_type: str = None,
        speed_multiplier: float = 1.0,
        timeout_cooldown: float = 8.0,
    ) -> None:
        """Allows a mob with the hide component to attempt to move to - and hide at - an owned or nearby POI.

        Parameters:
            duration (Seconds, optional): Description. Defaults to 1.0.
            poi_type (str, optional): Description. Defaults to None.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            timeout_cooldown (float, optional): Description. Defaults to 8.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_hide
        """
        super().__init__("behavior.hide")
        if duration != 1.0:
            self._add_field("duration", duration)
        if poi_type is not None:
            self._add_field("poi_type", poi_type)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if timeout_cooldown != 8.0:
            self._add_field("timeout_cooldown", timeout_cooldown)


class EntityAITradeWithPlayer(_BaseAIGoal):
    _identifier = "minecraft:behavior.trade_with_player"

    def __init__(
        self,
        filters: Filter = None,
        max_distance_from_player: float = 8.0,
    ) -> None:
        """Allows the player to trade with this mob. When the goal starts, it will stop the mob's navigation.

        Parameters:
            filters (Filter, optional): Description. Defaults to None.
            max_distance_from_player (float, optional): Description. Defaults to 8.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_trade_with_player
        """
        super().__init__("behavior.trade_with_player")

        if filters is not None:
            self._add_field("filters", filters)
        if max_distance_from_player != 8.0:
            self._add_field("max_distance_from_player", max_distance_from_player)


class EntityAIPickupItems(_BaseAIGoal):
    _identifier = "minecraft:behavior.pickup_items"

    def __init__(
        self,
        can_pickup_any_item: bool = False,
        can_pickup_to_hand_or_equipment: bool = True,
        cooldown_after_being_attacked: float = 0.0,
        excluded_items: list[str] = [],
        goal_radius: float = 0.5,
        max_dist: float = 0.0,
        pickup_based_on_chance: bool = False,
        pickup_same_items_as_in_hand: bool = False,
        search_height: float = 0.0,
        speed_multiplier: float = 1.0,
        track_target: bool = False,
    ) -> None:
        """Allows the mob to pick up items on the ground.

        Parameters:
            can_pickup_any_item (bool, optional): Description. Defaults to False.
            can_pickup_to_hand_or_equipment (bool, optional): Description. Defaults to True.
            cooldown_after_being_attacked (float, optional): Description. Defaults to 0.0.
            excluded_items (list[str], optional): Description. Defaults to [].
            goal_radius (float, optional): Description. Defaults to 0.5.
            max_dist (float, optional): Description. Defaults to 0.0.
            pickup_based_on_chance (bool, optional): Description. Defaults to False.
            pickup_same_items_as_in_hand (bool, optional): Description. Defaults to False.
            search_height (float, optional): Description. Defaults to 0.0.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            track_target (bool, optional): Description. Defaults to False.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_pickup_items
        """
        super().__init__("behavior.pickup_items")

        if can_pickup_any_item:
            self._add_field("can_pickup_any_item", can_pickup_any_item)
        if not can_pickup_to_hand_or_equipment:
            self._add_field("can_pickup_to_hand_or_equipment", can_pickup_to_hand_or_equipment)
        if cooldown_after_being_attacked != 0.0:
            self._add_field("cooldown_after_being_attacked", cooldown_after_being_attacked)
        if excluded_items:
            self._add_field("excluded_items", excluded_items)
        if goal_radius != 0.5:
            self._add_field("goal_radius", goal_radius)
        if max_dist != 0.0:
            self._add_field("max_dist", max_dist)
        if pickup_based_on_chance:
            self._add_field("pickup_based_on_chance", pickup_based_on_chance)
        if pickup_same_items_as_in_hand:
            self._add_field("pickup_same_items_as_in_hand", pickup_same_items_as_in_hand)
        if search_height != 0.0:
            self._add_field("search_height", search_height)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if track_target:
            self._add_field("track_target", track_target)


class EntityAIMoveIndoors(_BaseAIGoal):
    _identifier = "minecraft:behavior.move_indoors"

    def __init__(
        self,
        speed_multiplier: float = 0.8,
        timeout_cooldown: float = 8.0,
    ) -> None:
        """Allows this entity to move indoors.

        Parameters:
            speed_multiplier (float, optional): Description. Defaults to 0.8.
            timeout_cooldown (float, optional): Description. Defaults to 8.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_move_indoors
        """
        super().__init__("behavior.move_indoors")

        if speed_multiplier != 0.8:
            self._add_field("speed_multiplier", speed_multiplier)
        if timeout_cooldown != 8.0:
            self._add_field("timeout_cooldown", timeout_cooldown)


class EntityAILookAtTradingPlayer(_BaseAIGoal):
    _identifier = "minecraft:behavior.look_at_trading_player"

    def __init__(
        self,
        angle_of_view_horizontal: int = 360,
        angle_of_view_vertical: int = 360,
        look_distance: float = 8.0,
        look_time: tuple[int, int] = None,
        probability: float = 0.02,
    ) -> None:
        """Compels an entity to look at the player that is currently trading with the entity.

        Parameters:
            angle_of_view_horizontal (int, optional): Description. Defaults to 360.
            angle_of_view_vertical (int, optional): Description. Defaults to 360.
            look_distance (float, optional): Description. Defaults to 8.0.
            look_time (tuple[int, int], optional): Description. Defaults to None.
            probability (float, optional): Description. Defaults to 0.02.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_look_at_trading_player
        """
        super().__init__("behavior.look_at_trading_player")

        if angle_of_view_horizontal != 360:
            self._add_field("angle_of_view_horizontal", angle_of_view_horizontal)
        if angle_of_view_vertical != 360:
            self._add_field("angle_of_view_vertical", angle_of_view_vertical)
        if look_distance != 8.0:
            self._add_field("look_distance", look_distance)
        if look_time is not None:
            if (
                not isinstance(look_time, tuple)
                or len(look_time) != 2
                or not all(isinstance(t, (int, float)) for t in look_time)
            ):
                raise ValueError("look_time must be a tuple of two numbers (int or float)")
            self._add_field("look_time", {"min": look_time[0], "max": look_time[1]})

        if probability != 0.02:
            self._add_field("probability", probability)


class EntityAIShareItems(_BaseAIGoal):
    _identifier = "minecraft:behavior.share_items"

    def __init__(
        self,
        entity_types: Filter = None,
        goal_radius: float = 0.5,
        max_dist: float = 0.0,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Allows the mob to give items it has to others.

        Parameters:
            entity_types (Filter, optional): Description. Defaults to None.
            goal_radius (float, optional): Description. Defaults to 0.5.
            max_dist (float, optional): Description. Defaults to 0.0.
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_share_items
        """
        super().__init__("behavior.share_items")

        if entity_types is not None:
            self._add_field("entity_types", [{"filters": entity_types}])
        if goal_radius != 0.5:
            self._add_field("goal_radius", goal_radius)
        if max_dist != 0.0:
            self._add_field("max_dist", max_dist)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIMoveTowardsDwellingRestriction(_BaseAIGoal):
    _identifier = "minecraft:behavior.move_towards_dwelling_restriction"

    def __init__(
        self,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Allows entities with the "minecraft:dweller" component to move toward their Village area that the entity should be restricted to.

        Parameters:
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_move_towards_dwelling_restriction
        """
        super().__init__("behavior.move_towards_dwelling_restriction")
        # self._require_components(EntityDweller)

        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAITradeInterest(_BaseAIGoal):
    _identifier = "minecraft:behavior.trade_interest"

    def __init__(
        self,
        carried_item_switch_time: float = 2.0,
        cooldown: float = 2.0,
        interest_time: float = 45.0,
        remove_item_time: float = 1.0,
        within_radius: float = 0.0,
    ) -> None:
        """Allows the mob to look at a player that is holding a tradable item.

        Parameters:
            carried_item_switch_time (float, optional): Description. Defaults to 2.0.
            cooldown (float, optional): Description. Defaults to 2.0.
            interest_time (float, optional): Description. Defaults to 45.0.
            remove_item_time (float, optional): Description. Defaults to 1.0.
            within_radius (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_trade_interest
        """
        super().__init__("behavior.trade_interest")

        if carried_item_switch_time != 2.0:
            self._add_field("carried_item_switch_time", carried_item_switch_time)
        if cooldown != 2.0:
            self._add_field("cooldown", cooldown)
        if interest_time != 45.0:
            self._add_field("interest_time", interest_time)
        if remove_item_time != 1.0:
            self._add_field("remove_item_time", remove_item_time)
        if within_radius != 0.0:
            self._add_field("within_radius", within_radius)


class EntityAIMakeLove(_BaseAIGoal):
    _identifier = "minecraft:behavior.make_love"

    def __init__(self) -> None:
        """Allows the villager to look for a mate to spawn other villagers with.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_make_love
        """
        super().__init__("behavior.make_love")


class EntityAIReceiveLove(_BaseAIGoal):
    _identifier = "minecraft:behavior.receive_love"

    def __init__(self) -> None:
        """Allows the villager to receive love from another villager.

        Parameters:

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_receive_love
        """
        super().__init__("behavior.receive_love")


class EntityAIWork(_BaseAIGoal):
    _identifier = "minecraft:behavior.work"

    def __init__(
        self,
        active_time: int = 0,
        can_work_in_rain: bool = False,
        goal_cooldown: int = 0,
        on_arrival: str = None,
        sound_delay_max: int = 0,
        sound_delay_min: int = 0,
        speed_multiplier: float = 0.5,
        work_in_rain_tolerance: int = -1,
    ) -> None:
        """Allows the NPC to use the POI.

        Parameters:
            active_time (int, optional): Description. Defaults to 0.
            can_work_in_rain (bool, optional): Description. Defaults to False.
            goal_cooldown (int, optional): Description. Defaults to 0.
            on_arrival (str, optional): Description. Defaults to None.
            sound_delay_max (int, optional): Description. Defaults to 0.
            sound_delay_min (int, optional): Description. Defaults to 0.
            speed_multiplier (float, optional): Description. Defaults to 0.5.
            work_in_rain_tolerance (int, optional): Description. Defaults to -1.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_work
        """
        super().__init__("behavior.work")

        if active_time != 0:
            self._add_field("active_time", active_time)
        if can_work_in_rain:
            self._add_field("can_work_in_rain", can_work_in_rain)
        if goal_cooldown != 0:
            self._add_field("goal_cooldown", goal_cooldown)
        if on_arrival is not None:
            self._add_field("on_arrival", {"event": on_arrival, "target": "self"})
        if sound_delay_max != 0:
            self._add_field("sound_delay_max", sound_delay_max)
        if sound_delay_min != 0:
            self._add_field("sound_delay_min", sound_delay_min)
        if speed_multiplier != 0.5:
            self._add_field("speed_multiplier", speed_multiplier)
        if work_in_rain_tolerance != -1:
            self._add_field("work_in_rain_tolerance", work_in_rain_tolerance)


class EntityAIWorkComposter(_BaseAIGoal):
    _identifier = "minecraft:behavior.work_composter"

    def __init__(
        self,
        active_time: int = 0,
        block_interaction_max: int = 1,
        can_empty_composter: bool = True,
        can_fill_composter: bool = True,
        can_work_in_rain: bool = False,
        goal_cooldown: int = 0,
        items_per_use_max: int = 20,
        min_item_count: int = 10,
        on_arrival: str = None,
        speed_multiplier: float = 0.5,
        use_block_max: int = 200,
        use_block_min: int = 100,
        work_in_rain_tolerance: int = -1,
    ) -> None:
        """Allows the NPC to use the composter POI to convert excess seeds into bone meal.

        Parameters:
            active_time (int, optional): Description. Defaults to 0.
            block_interaction_max (int, optional): Description. Defaults to 1.
            can_empty_composter (bool, optional): Description. Defaults to True.
            can_fill_composter (bool, optional): Description. Defaults to True.
            can_work_in_rain (bool, optional): Description. Defaults to False.
            goal_cooldown (int, optional): Description. Defaults to 0.
            items_per_use_max (int, optional): Description. Defaults to 20.
            min_item_count (int, optional): Description. Defaults to 10.
            on_arrival (str, optional): Description. Defaults to None.
            speed_multiplier (float, optional): Description. Defaults to 0.5.
            use_block_max (int, optional): Description. Defaults to 200.
            use_block_min (int, optional): Description. Defaults to 100.
            work_in_rain_tolerance (int, optional): Description. Defaults to -1.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_work_composter
        """
        super().__init__("behavior.work_composter")

        if active_time != 0:
            self._add_field("active_time", active_time)
        if block_interaction_max != 1:
            self._add_field("block_interaction_max", block_interaction_max)
        if not can_empty_composter:
            self._add_field("can_empty_composter", can_empty_composter)
        if not can_fill_composter:
            self._add_field("can_fill_composter", can_fill_composter)
        if can_work_in_rain:
            self._add_field("can_work_in_rain", can_work_in_rain)
        if goal_cooldown != 0:
            self._add_field("goal_cooldown", goal_cooldown)
        if items_per_use_max != 20:
            self._add_field("items_per_use_max", items_per_use_max)
        if min_item_count != 10:
            self._add_field("min_item_count", min_item_count)
        if on_arrival is not None:
            self._add_field("on_arrival", {"event": on_arrival, "target": "self"})
        if speed_multiplier != 0.5:
            self._add_field("speed_multiplier", speed_multiplier)
        if use_block_max != 200:
            self._add_field("use_block_max", use_block_max)
        if use_block_min != 100:
            self._add_field("use_block_min", use_block_min)
        if work_in_rain_tolerance != -1:
            self._add_field("work_in_rain_tolerance", work_in_rain_tolerance)


class EntityAIHarvestFarmBlock(_BaseAIGoal):
    _identifier = "minecraft:behavior.harvest_farm_block"

    def __init__(
        self,
        goal_radius: float = 1.5,
        max_seconds_before_search: float = 1.0,
        search_cooldown_max_seconds: float = 8.0,
        search_count: int = 0,
        search_height: int = 1,
        search_range: int = 16,
        seconds_until_new_task: float = 0.5,
        speed_multiplier: float = 0.5,
    ) -> None:
        """Allows the entity to search within an area for farmland with air above it. If found, the entity will replace the air block by planting a seed item from its inventory on the farmland block. This goal will not execute if the entity does not have an item in its inventory.

        Parameters:
            goal_radius (float, optional): Description. Defaults to 1.5.
            max_seconds_before_search (float, optional): Description. Defaults to 1.0.
            search_cooldown_max_seconds (float, optional): Description. Defaults to 8.0.
            search_count (int, optional): Description. Defaults to 0.
            search_height (int, optional): Description. Defaults to 1.
            search_range (int, optional): Description. Defaults to 16.
            seconds_until_new_task (float, optional): Description. Defaults to 0.5.
            speed_multiplier (float, optional): Description. Defaults to 0.5.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_harvest_farm_block
        """
        super().__init__("behavior.harvest_farm_block")
        self._require_components(EntityInventory)

        if goal_radius != 1.5:
            self._add_field("goal_radius", goal_radius)
        if max_seconds_before_search != 1.0:
            self._add_field("max_seconds_before_search", max_seconds_before_search)
        if search_cooldown_max_seconds != 8.0:
            self._add_field("search_cooldown_max_seconds", search_cooldown_max_seconds)
        if search_count != 0:
            self._add_field("search_count", search_count)
        if search_height != 1:
            self._add_field("search_height", search_height)
        if search_range != 16:
            self._add_field("search_range", search_range)
        if seconds_until_new_task != 0.5:
            self._add_field("seconds_until_new_task", seconds_until_new_task)
        if speed_multiplier != 0.5:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIFertilizeFarmBlock(_BaseAIGoal):
    _identifier = "minecraft:behavior.fertilize_farm_block"

    def __init__(
        self,
        goal_radius: float = 1.5,
        max_fertilizer_usage: int = 1,
        search_cooldown_max_seconds: float = 8.0,
        search_count: int = 9,
        search_height: int = 1,
        search_range: int = 1,
        speed_multiplier: float = 0.5,
    ) -> None:
        """Allows the mob to search within an area for a growable crop block. If found, the mob will use any available fertilizer in their inventory on the crop. This goal will not execute if the mob does not have a fertilizer item in its inventory.

        Parameters:
            goal_radius (float, optional): Description. Defaults to 1.5.
            max_fertilizer_usage (int, optional): Description. Defaults to 1.
            search_cooldown_max_seconds (float, optional): Description. Defaults to 8.0.
            search_count (int, optional): Description. Defaults to 9.
            search_height (int, optional): Description. Defaults to 1.
            search_range (int, optional): Description. Defaults to 1.
            speed_multiplier (float, optional): Description. Defaults to 0.5.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_fertilize_farm_block
        """
        super().__init__("behavior.fertilize_farm_block")

        if goal_radius != 1.5:
            self._add_field("goal_radius", goal_radius)
        if max_fertilizer_usage != 1:
            self._add_field("max_fertilizer_usage", max_fertilizer_usage)
        if search_cooldown_max_seconds != 8.0:
            self._add_field("search_cooldown_max_seconds", search_cooldown_max_seconds)
        if search_count != 9:
            self._add_field("search_count", search_count)
        if search_height != 1:
            self._add_field("search_height", search_height)
        if search_range != 1:
            self._add_field("search_range", search_range)
        if speed_multiplier != 0.5:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIPlay(_BaseAIGoal):
    _identifier = "minecraft:behavior.play"

    def __init__(
        self,
        chance_to_start: float = 0.0,
        follow_distance: int = 2,
        friend_search_area: Coordinates = (6, 3, 6),
        friend_types: Filter = None,
        max_play_duration_seconds: float = 50.0,
        random_pos_search_height: int = 3,
        random_pos_search_range: int = 16,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Allows the mob to play with other mobs by chasing each other and moving around randomly.

        Parameters:
            chance_to_start (float, optional): Description. Defaults to 0.0.
            follow_distance (int, optional): Description. Defaults to 2.
            friend_search_area (Coordinates, optional): Description. Defaults to (6, 3, 6).
            friend_types (Filter, optional): Description. Defaults to None.
            max_play_duration_seconds (float, optional): Description. Defaults to 50.0.
            random_pos_search_height (int, optional): Description. Defaults to 3.
            random_pos_search_range (int, optional): Description. Defaults to 16.
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_play
        """
        super().__init__("behavior.play")

        if chance_to_start != 0.0:
            self._add_field("chance_to_start", chance_to_start)
        if follow_distance != 2:
            self._add_field("follow_distance", follow_distance)
        if friend_search_area != (6, 3, 6):
            self._add_field("friend_search_area", friend_search_area)
        if friend_types is not None:
            self._add_field("friend_types", friend_types)
        if max_play_duration_seconds != 50.0:
            self._add_field("max_play_duration_seconds", max_play_duration_seconds)
        if random_pos_search_height != 3:
            self._add_field("random_pos_search_height", random_pos_search_height)
        if random_pos_search_range != 16:
            self._add_field("random_pos_search_range", random_pos_search_range)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIMingle(_BaseAIGoal):
    _identifier = "minecraft:behavior.mingle"

    def __init__(
        self,
        cooldown_time: float = 0.0,
        duration: float = 1.0,
        mingle_distance: float = 2.0,
        mingle_partner_type: list[str] = [],
        speed_multiplier: float = 1.0,
    ) -> None:
        """Allows an entity to go to the village bell and mingle with other entities.

        Parameters:
            cooldown_time (float, optional): Description. Defaults to 0.0.
            duration (float, optional): Description. Defaults to 1.0.
            mingle_distance (float, optional): Description. Defaults to 2.0.
            mingle_partner_type (list[str], optional): Description. Defaults to [].
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_mingle
        """
        super().__init__("behavior.mingle")

        if cooldown_time != 0.0:
            self._add_field("cooldown_time", cooldown_time)
        if duration != 1.0:
            self._add_field("duration", duration)
        if mingle_distance != 2.0:
            self._add_field("mingle_distance", mingle_distance)
        if mingle_partner_type:
            self._add_field("mingle_partner_type", mingle_partner_type)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAISleep(_BaseAIGoal):
    _identifier = "minecraft:behavior.sleep"

    def __init__(
        self,
        can_sleep_while_riding: bool = False,
        cooldown_time: float = 0.0,
        goal_radius: float = None,
        sleep_collider_height: float = 1.0,
        sleep_collider_width: float = 1.0,
        sleep_y_offset: float = 1.0,
        speed_multiplier: float = 1.0,
        timeout_cooldown: float = 8.0,
    ) -> None:
        """Allows mobs that own a bed to in a village to move to and sleep in it.

        Parameters:
            can_sleep_while_riding (bool, optional): Description. Defaults to False.
            cooldown_time (float, optional): Description. Defaults to 0.0.
            goal_radius (float, optional): Description. Defaults to None.
            sleep_collider_height (float, optional): Description. Defaults to 1.0.
            sleep_collider_width (float, optional): Description. Defaults to 1.0.
            sleep_y_offset (float, optional): Description. Defaults to 1.0.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            timeout_cooldown (float, optional): Description. Defaults to 8.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_sleep
        """
        super().__init__("behavior.sleep")

        if can_sleep_while_riding:
            self._add_field("can_sleep_while_riding", can_sleep_while_riding)
        if cooldown_time != 0.0:
            self._add_field("cooldown_time", cooldown_time)
        if goal_radius is not None:
            self._add_field("goal_radius", goal_radius)
        if sleep_collider_height != 1.0:
            self._add_field("sleep_collider_height", sleep_collider_height)
        if sleep_collider_width != 1.0:
            self._add_field("sleep_collider_width", sleep_collider_width)
        if sleep_y_offset != 1.0:
            self._add_field("sleep_y_offset", sleep_y_offset)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if timeout_cooldown != 8.0:
            self._add_field("timeout_cooldown", timeout_cooldown)


class EntityAIExploreOutskirts(_BaseAIGoal):
    _identifier = "minecraft:behavior.explore_outskirts"

    def __init__(
        self,
        dist_from_boundary: Coordinates = (5, 0, 5),
        explore_dist: float = 5.0,
        max_travel_time: float = 60.0,
        max_wait_time: float = 0.0,
        min_dist_from_target: float = 2.2,
        min_perimeter: float = 1.0,
        min_wait_time: float = 3.0,
        next_xz: int = 5,
        next_y: int = 3,
        speed_multiplier: float = 1.0,
        timer_ratio: float = 2.0,
    ) -> None:
        """Allows the entity to first travel to a random point on the outskirts of the village, and then explore random points within a small distance.

        Parameters:
            dist_from_boundary (Coordinates, optional): Description. Defaults to (5, 0, 5).
            explore_dist (float, optional): Description. Defaults to 5.0.
            max_travel_time (float, optional): Description. Defaults to 60.0.
            max_wait_time (float, optional): Description. Defaults to 0.0.
            min_dist_from_target (float, optional): Description. Defaults to 2.2.
            min_perimeter (float, optional): Description. Defaults to 1.0.
            min_wait_time (float, optional): Description. Defaults to 3.0.
            next_xz (int, optional): Description. Defaults to 5.
            next_y (int, optional): Description. Defaults to 3.
            speed_multiplier (float, optional): Description. Defaults to 1.0.
            timer_ratio (float, optional): Description. Defaults to 2.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_explore_outskirts
        """
        super().__init__("behavior.explore_outskirts")
        # self._require_components(EntityDweller)

        if dist_from_boundary != (5, 0, 5):
            self._add_field("dist_from_boundary", dist_from_boundary)
        if explore_dist != 5.0:
            self._add_field("explore_dist", explore_dist)
        if max_travel_time != 60.0:
            self._add_field("max_travel_time", max_travel_time)
        if max_wait_time != 0.0:
            self._add_field("max_wait_time", max_wait_time)
        if min_dist_from_target != 2.2:
            self._add_field("min_dist_from_target", min_dist_from_target)
        if min_perimeter != 1.0:
            self._add_field("min_perimeter", min_perimeter)
        if min_wait_time != 3.0:
            self._add_field("min_wait_time", min_wait_time)
        if next_xz != 5:
            self._add_field("next_xz", next_xz)
        if next_y != 3:
            self._add_field("next_y", next_y)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if timer_ratio != 2.0:
            self._add_field("timer_ratio", timer_ratio)


class EntityAIBreed(_BaseAIGoal):
    _identifier = "minecraft:behavior.breed"

    def __init__(self, speed_multiplier: float = 1.0) -> None:
        """Allows this mob to breed with other mobs.

        Parameters:
            speed_multiplier (float, optional): Description. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_breed
        """
        super().__init__("behavior.breed")
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIInspectBookshelf(_BaseAIGoal):
    _identifier = "minecraft:behavior.inspect_bookshelf"

    def __init__(
        self,
        goal_radius: float = 0.5,
        search_count: int = 10,
        search_height: int = 1,
        search_range: int = 0,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Allows the mob to inspect bookshelves.

        Parameters:
            goal_radius (float, optional): Distance in blocks within the mob considers it has reached the goal. Defaults to 0.5.
            search_count (int, optional): The number of blocks each tick that the mob will check. Defaults to 10.
            search_height (int, optional): The height that the mob will search for bookshelves. Defaults to 1.
            search_range (int, optional): Distance in blocks the mob will look for books to inspect. Defaults to 0.
            speed_multiplier (float, optional): Movement speed multiplier of the mob. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_inspect_bookshelf
        """
        super().__init__("behavior.inspect_bookshelf")

        if goal_radius != 0.5:
            self._add_field("goal_radius", goal_radius)
        if search_count != 10:
            self._add_field("search_count", search_count)
        if search_height != 1:
            self._add_field("search_height", search_height)
        if search_range != 0:
            self._add_field("search_range", search_range)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAIRandomFly(_BaseAIGoal):
    _identifier = "minecraft:behavior.random_fly"

    def __init__(
        self,
        avoid_damage_blocks: bool = False,
        can_land_on_trees: bool = True,
        speed_multiplier: float = 1.0,
        xz_dist: int = 10,
        y_dist: int = 7,
        y_offset: float = 0.0,
    ) -> None:
        """Allows a mob to randomly fly around.

        Parameters:
            avoid_damage_blocks (bool, optional): Description. Defaults to False.
            can_land_on_trees (bool, optional): If true, the mob can stop flying and land on a tree instead of the ground. Defaults to True.
            speed_multiplier (float, optional): Movement speed multiplier of the mob when using this AI Goal. Defaults to 1.0.
            xz_dist (int, optional): Distance in blocks on ground that the mob will look for a new spot to move to. Must be at least 1. Defaults to 10.
            y_dist (int, optional): Distance in blocks that the mob will look up or down for a new spot to move to. Must be at least 1. Defaults to 7.
            y_offset (float, optional): Description. Defaults to 0.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_random_fly
        """
        super().__init__("behavior.random_fly")

        if avoid_damage_blocks:
            self._add_field("avoid_damage_blocks", avoid_damage_blocks)
        if not can_land_on_trees:
            self._add_field("can_land_on_trees", can_land_on_trees)
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)
        if xz_dist != 10:
            self._add_field("xz_dist", max(1, xz_dist))
        if y_dist != 7:
            self._add_field("y_dist", max(1, y_dist))
        if y_offset != 0.0:
            self._add_field("y_offset", y_offset)


class EntityAICircleAroundAnchor(_BaseAIGoal):
    _identifier = "minecraft:behavior.circle_around_anchor"

    def __init__(
        self,
        angle_change: float = 15.0,
        goal_radius: float = 0.5,
        height_above_target_range: tuple[int, int] = None,
        height_adjustment_chance: float = 0.002857,
        height_offset_range: tuple[int, int] = None,
        radius_adjustment_chance: float = 0.004,
        radius_change: float = 1.0,
        radius_range: tuple[int, int] = None,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Causes an entity to circle around an anchor point placed near a point or target.

        Parameters:
            angle_change (float, optional): Number of degrees to change the entity's facing by when selecting the next anchor point. Defaults to 15.0.
            goal_radius (float, optional): Maximum distance from the anchor-point in which the entity considers itself to have reached the anchor point. Defaults to 0.5.
            height_above_target_range (tuple[int, int], optional): The number of blocks above the target that the next anchor point can be set. Only used when tracking a target. Defaults to None.
            height_adjustment_chance (float, optional): Percent chance to increase or decrease the current height around the anchor point. Defaults to 0.002857.
            height_offset_range (tuple[int, int], optional): Vertical distance from the anchor point the entity must stay within upon height adjustment. Defaults to None.
            radius_adjustment_chance (float, optional): Percent chance to increase the current movement radius around the anchor point. Defaults to 0.004.
            radius_change (float, optional): Number of blocks to increase the movement radius by upon successful radius adjustment. Defaults to 1.0.
            radius_range (tuple[int, int], optional): Horizontal distance from the anchor point the entity must stay within upon radius adjustment. Defaults to None.
            speed_multiplier (float, optional): Multiplier for the speed at which the entity travels to its next desired position. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_circle_around_anchor
        """
        super().__init__("behavior.circle_around_anchor")

        if angle_change != 15.0:
            self._add_field("angle_change", angle_change)
        if goal_radius != 0.5:
            self._add_field("goal_radius", goal_radius)
        if height_above_target_range is not None:
            self._add_field(
                "height_above_target_range",
                {"min": height_above_target_range[0], "max": height_above_target_range[1]},
            )
        if height_adjustment_chance != 0.002857:
            self._add_field("height_adjustment_chance", height_adjustment_chance)
        if height_offset_range is not None:
            self._add_field("height_offset_range", {"min": height_offset_range[0], "max": height_offset_range[1]})
        if radius_adjustment_chance != 0.004:
            self._add_field("radius_adjustment_chance", radius_adjustment_chance)
        if radius_change != 1.0:
            self._add_field("radius_change", radius_change)
        if radius_range is not None:
            self._add_field("radius_range", {"min": radius_range[0], "max": radius_range[1]})
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAISwoopAttack(_BaseAIGoal):
    _identifier = "minecraft:behavior.swoop_attack"

    def __init__(
        self,
        damage_reach: float = 0.2,
        delay_range: tuple[Seconds, Seconds] = None,
        speed_multiplier: float = 1.0,
    ) -> None:
        """Allows an entity to attack using swoop attack behavior; Ideal for use with flying mobs. The behavior ends if the entity has a horizontal collision or gets hit.

        Parameters:
            damage_reach (float, optional): Added to the base size of the entity, to determine the target's maximum allowable distance, when trying to deal attack damage. Defaults to 0.2.
            delay_range (tuple[Seconds, Seconds], optional): Minimum and maximum cooldown time-range (in seconds) between each attempted swoop attack. Defaults to None.
            speed_multiplier (float, optional): During swoop attack behavior, this determines the multiplier the entity's speed is modified by when moving toward the target. Defaults to 1.0.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_swoop_attack
        """
        super().__init__("behavior.swoop_attack")

        if damage_reach != 0.2:
            self._add_field("damage_reach", damage_reach)
        if delay_range is not None:
            if (
                not isinstance(delay_range, (tuple, list))
                or len(delay_range) != 2
                or not all(isinstance(i, (int, float)) for i in delay_range)
            ):
                raise ValueError("delay_range must be a tuple of 2 numbers (int or float)")
            self._add_field("delay_range", {"min": delay_range[0], "max": delay_range[1]})
        if speed_multiplier != 1.0:
            self._add_field("speed_multiplier", speed_multiplier)


class EntityAISwimUpForBreath(_BaseAIGoal):
    _identifier = "minecraft:behavior.swim_up_for_breath"

    def __init__(
        self,
        material_type: Literal["water", "lava", "any"] = "water",
        search_height: int = 16,
        search_radius: int = 4,
        speed_mod: float = 1.4,
    ) -> None:
        """Allows the mob to try to move to air once it is close to running out of its total breathable supply. Requires "minecraft:breathable".

        Parameters:
            material_type (str, optional): The material the mob is traveling in. Options are: "water", "lava", or "any". Defaults to "water".
            search_height (int, optional): The height (in blocks) above the mob's current position that it will search for a valid air block to move to. If a valid block cannot be found, the mob will move to the position this many blocks above it. Defaults to 16.
            search_radius (int, optional): The radius (in blocks) around the mob's current position that it will search for a valid air block to move to. Defaults to 4.
            speed_mod (float, optional): Movement speed multiplier of the mob when using this Goal. Defaults to 1.4.

        ## Documentation reference:
            https://learn.microsoft.com/en-gb/minecraft/creator/reference/content/entityreference/examples/entitygoals/minecraftbehavior_swim_up_for_breath
        """
        super().__init__("behavior.swim_up_for_breath")
        self._require_components(EntityBreathable)

        if material_type != "water":
            self._add_field("material_type", material_type)
        if search_height != 16:
            self._add_field("search_height", search_height)
        if search_radius != 4:
            self._add_field("search_radius", search_radius)
        if speed_mod != 1.4:
            self._add_field("speed_mod", speed_mod)
