# Entities & Players

> Create and manage entities and players with the Kore OOP module - selectors, execute helpers, batch commands, entity commands, and entity effects.

Updated 2026-10-22. Canonical: https://kore.ayfri.com/docs/oop/entities-and-players

The OOP module models Minecraft entities and players as Kotlin objects with selectors and context-aware
extension functions.

> [!FOOTPRINT]
> Nothing of its own: a handle is a selector, and only the commands you call are written. Score operators against a plain `Int` add the `kore_constants` objective, see [Scoreboards](https://kore.ayfri.com/docs/oop/scoreboards.md).

## Creating entities

```kotlin
val player = player("Steve") {
	gamemode = Gamemode.SURVIVAL
	team = "red"
}

val arenaMobs = entity("ArenaMob", limitToOne = false) {
	tag = "arena"
}

val zombie = entity {
	type = EntityTypes.ZOMBIE
}
```

`player()` creates a `Player` instance (subclass of `Entity`) with `type = minecraft:player`, `limit = 1`,
and the given name. `entity()` creates a generic `Entity` with custom selector arguments, and can also start from a
named entity selector when you already know the exact entity name to target.

Use `player(...)` when you want a selector already scoped to players, and `entity { ... }` when you need a reusable
selector for mobs, armor stands, projectiles, or a more generic execute target. Use `entity("Name", ...)` when you
want the same convenience as `player("Name")` without forcing the selector to `minecraft:player`.

### Creating entities from an EntityType

You can also construct an `Entity` handle directly from an `EntityTypes` value using `toEntity()` or the typed
overload of `entity()`:

```kotlin
// extension on EntityTypeArgument, the selector type is set for you
val creeper = EntityTypes.CREEPER.toEntity()
val skeletons = EntityTypes.SKELETON.toEntity(limitToOne = false) { team = "arena" }

// same result, written like the other entity(...) overloads
val spider = entity(EntityTypes.SPIDER)
val endermen = entity(EntityTypes.ENDERMAN, limitToOne = false) { tag = "target" }
```

Both forms set `selector.type` automatically so you never need to write `type = EntityTypes.X` by hand.
Use `toEntity()` when calling from an `EntityTypeArgument` receiver; use `entity(type, ...)` when you want a form
that reads like the other `entity(...)` overloads.

### Handles for spawned displays, interactions and mannequins

Five `Entity` subclasses target one specific spawned entity by UUID rather than by selector filters:
`BlockDisplayEntity`, `InteractionEntity`, `ItemDisplayEntity`, `TextDisplayEntity`, and `MannequinEntity`. Each pins
`selector.type` and a `UUID` NBT filter, so it always resolves to exactly that entity.

You do not construct them directly in normal use - the [`helpers`](https://kore.ayfri.com/docs/helpers/utilities.md) module returns them
when it spawns something. `DisplayEntityInterpolable.toEntity()` picks the matching display subclass, and
`Mannequin.summon(position)` returns a `MannequinEntity`, and `Interaction.summon(position)` an `InteractionEntity`:

```kotlin
function("spawn_display") {
	val display = blockDisplay {
		blockState(Blocks.DIAMOND_BLOCK)
	}.interpolable(vec3(0, 64, 0))

	display.summon()
	display.toEntity().addTag("arena_decor")

	val statue = mannequin { pose = MannequinPose.STANDING }.summon(vec3(0, 64, 0))
	statue.swing(SwingHand.MAINHAND)
	statue.swing(SwingHand.MAINHAND, SwingAnimationType.STAB, 10.ticks)
}
```

Both spawn calls embed a UUID in the summon NBT, which is what the returned handle filters on - so the handle resolves
to that one instance even if several are spawned. The UUID comes from `DataPack.entityUUID()`, a hash of the pack name,
the entity and its position, so it stays the same across builds and differs between two identical entities. Once you
hold one it behaves like any other `Entity`: every extension on this page applies.

```mcfunction
kill @e[limit=1,nbt={UUID:[I;...]},type=minecraft:block_display]
```

See [Display Entities](https://kore.ayfri.com/docs/helpers/display-entities.md), [Interactions](https://kore.ayfri.com/docs/helpers/interactions.md) and
[Mannequins](https://kore.ayfri.com/docs/helpers/mannequins.md) for building and spawning them.

## Reading and reshaping a handle

An `Entity` is a thin wrapper around `SelectorArguments`, exposed through these members:

| Member                    | Description                                                        |
|---------------------------|--------------------------------------------------------------------|
| `selector`                | The underlying `SelectorArguments`, mutable                        |
| `type`                    | The constrained entity type, or `null`                             |
| `isPlayer`                | Whether the handle currently resolves to `minecraft:player`        |
| `team`                    | Read/write the team filter on the selector                         |
| `limitToOne`              | Whether `asSelector()` defaults to a single-entity selector        |
| `asSelector(limitToOne)`  | Build the `@e[...]` selector, optionally overriding the limit and refining the arguments |

`asSelector()` is the escape hatch: every OOP command ultimately calls it, and you can call it yourself to drop back
into the core command DSL at any point.

```kotlin
function("inspect") {
	val mobs = entity(EntityTypes.ZOMBIE, limitToOne = false) { tag = "arena" }

	kill(mobs.asSelector(limitToOne = false) { tag = "marked" })
}
```

`toEntity<T>()` and `toEntityOrNull<T>()` narrow a generic `Entity` to a subtype such as `Player` - the first throws
when the conversion is impossible, the second returns `null`.

## Targeting `@s`

`Entity` always renders as `@e[...]`, because `asSelector()` builds an `allEntities` selector from the stored
`SelectorArguments`. There is no `Entity` handle that renders as `@s`, and `self()` returns a `SelectorArgument`,
not an `Entity`, so it cannot be passed to `Entity`-only helpers such as `getScoreEntity`, `batch`, or `executeAs`.

When the executing entity is already `@s` - inside an `execute as` block, an [event](https://kore.ayfri.com/docs/oop/events.md) handler, or a
`batch` body - use the core command DSL with `self()` instead of trying to wrap it in an `Entity`:

```kotlin
function("charge_up") {
	val lastCharge = scoreboard.objective(self(), "last_crystal_charge")
	lastCharge += 10
}
```

`scoreboard.objective(selector, objective)` returns a `PlayerObjective` supporting the same operations as
`ScoreboardEntity` (`set`, `add`, `remove`, `reset`, `+=`, `-=`, `min`, `max`, `operation`), so nothing is lost by
dropping the OOP wrapper here. See
[Scoreboards → Raw selectors and `@s`](https://kore.ayfri.com/docs/oop/scoreboards.md#raw-selectors-and-s).

The same applies to every other command: pass `self()` directly to `kill(...)`, `tellraw(...)`, `give(...)` and
friends rather than looking for an `Entity` equivalent.

## Execute helpers

Entity-scoped execute shortcuts emit `/execute as`, `/execute at`, or both:

```kotlin
function("teleport_self") {
	player.executeAs {
		run { it.teleportTo(it) }
	}

	player.executeAt {
		run { it.giveItem(Items.DIAMOND) }
	}

	player.executeAsAt {
		run { it.sendMessage("Hello from my location!") }
	}
}
```

These helpers are especially valuable when you would otherwise repeat the same `execute as`, `execute at`, or
`execute as ... at ...` boilerplate around several commands.

## Batch

`batch()` creates a named sub-function that groups multiple commands under a single entity context:

```kotlin
function("setup") {
	player.batch("init_player") {
		give(self(), Items.DIAMOND)
		effect(self()) { give(Effects.SPEED, duration = 200) }
		tellraw(self(), "Welcome!")
	}
}
```

The block receives a plain `Function` run `as` the entity, so it targets that entity with `self()`: the `Entity`
extensions like `giveItem` need an entity receiver and aren't in scope there.

`batch()` is a good fit for onboarding flows, class kits, respawn setup, or any repeated multi-command routine that
should stay grouped under one entity context.

## Entity Commands

Extension functions on `Entity` for common [Minecraft commands](https://minecraft.wiki/w/Commands):

```kotlin
function("commands_demo") {
	player.kill()
	player.damage(5f)
	player.addTag("vip")
	player.removeTag("vip")
	player.giveXp(10.levels)
	player.setXp(0.points)
	player.setGamemode(Gamemode.CREATIVE)
	player.sendMessage("Hello!")
	player.showTitle(textComponent("Title"), textComponent("Subtitle"))
	player.showActionBar(textComponent("Action bar text"))
	player.playSound(SoundEvents.Entity.ExperienceOrb.PICKUP)
	player.mount(zombie)
	player.dismount()
	player.clearItems()
	player.giveItem(Items.DIAMOND)
	player.replaceItem(WEAPON.MAINHAND, itemStack(Items.NETHERITE_SWORD))
}
```

| Function        | Description                                                               |
|-----------------|---------------------------------------------------------------------------|
| `addTag`        | Add a scoreboard tag                                                      |
| `clearItems`    | Clear inventory (optionally filtered)                                     |
| `damage`        | Deal damage with optional damage type                                     |
| `dismount`      | Dismount from current vehicle                                             |
| `giveItem`      | Give an item stack                                                        |
| `giveXp`        | Add experience (levels or points)                                         |
| `kill`          | Kill the entity                                                           |
| `mount`         | Mount another entity                                                      |
| `playSound`     | Play a sound at the entity                                                |
| `removeTag`     | Remove a scoreboard tag                                                   |
| `replaceItem`   | Replace an item in a specific slot                                        |
| `sendMessage`   | Send a tellraw message                                                    |
| `setGamemode`   | Change the player's gamemode                                              |
| `setXp`         | Set experience to an exact value                                          |
| `showActionBar` | Display text on the action bar                                            |
| `showTitle`     | Display a title and optional subtitle                                     |
| `swing`         | Swing the left or right hand, optionally with an animation and a duration |
| `teleportTo`    | Teleport to coordinates or another entity                                 |

## Scores, teams, and counts

These extensions bridge an `Entity` handle to the other OOP systems:

```kotlin
function("bridge_demo") {
	val kills = player.getScoreEntity("kills")   // -> ScoreboardEntity
	player.setScore("kills", 0)                  // one-shot write, no handle

	player.joinTeam("red")                       // by name, or joinTeam(redTeam)
	player.leaveAnyTeam()

	// counts how many entities match right now, then writes that number to a score or NBT path
	val mobs = entity(EntityTypes.ZOMBIE, limitToOne = false)
	mobs.storeCountIn(kills)
	mobs.storeCountIn(player, "kore.mob_count")
	mobs.storeCountIn(storage("stats", "kore"), "mob_count")
}
```

| Function         | Description                                                                          |
|------------------|--------------------------------------------------------------------------------------|
| `getScoreEntity` | Get a [`ScoreboardEntity`](https://kore.ayfri.com/docs/oop/scoreboards.md) for an objective                   |
| `joinTeam`       | Join a [team](https://kore.ayfri.com/docs/oop/teams.md) by name or `Team` handle                              |
| `leaveAnyTeam`   | Leave the current team                                                               |
| `setScore`       | Set a score without building a handle                                                |
| `storeCountIn`   | Store how many entities match this selector into a score, entity NBT, or storage NBT |

## Distance between two entities

`distanceTo` writes the distance between two entities into a score, multiplied by `scale` (`1000` by default, so
`2500` means 2.5 blocks) and rounded down. It costs three commands: both `Pos` lists go into a storage, then one
[`compute`](https://kore.ayfri.com/docs/commands/commands.md#compute-command) takes the length of their difference, as floats, so it never
overflows.

```kotlin
function("distance_demo") {
	val zombie = entity(EntityTypes.ZOMBIE)
	val distance = fakePlayer("distance").getScoreEntity("game")

	zombie.distanceTo(entity(EntityTypes.VILLAGER), distance)
}
```

```mcfunction
data modify storage my_pack:entity_distance from set from entity @e[limit=1,type=minecraft:zombie] Pos
data modify storage my_pack:entity_distance to set from entity @e[limit=1,type=minecraft:villager] Pos
execute store result score #distance game run compute default float {type:"minecraft:length",inputs:[{type:"minecraft:sub",left:{type:"minecraft:storage",path:"from[0]",storage:"my_pack:entity_distance"},right:{type:"minecraft:storage",path:"to[0]",storage:"my_pack:entity_distance"}},{type:"minecraft:sub",left:{type:"minecraft:storage",path:"from[1]",storage:"my_pack:entity_distance"},right:{type:"minecraft:storage",path:"to[1]",storage:"my_pack:entity_distance"}},{type:"minecraft:sub",left:{type:"minecraft:storage",path:"from[2]",storage:"my_pack:entity_distance"},right:{type:"minecraft:storage",path:"to[2]",storage:"my_pack:entity_distance"}}]} 1000
```

`scale = 1f` gives whole blocks, the `compute` line then ending with `1` instead of `1000`.

Both handles must match one real entity (`limitToOne`, not a fake player), and the positions ignore dimensions. The
coordinates are read as floats, so the result drifts far from the origin: about 1 unit at 10,000 blocks and 8 at
100,000 with the default scale. The storage defaults to `<pack>:entity_distance`, pass `storage` to use another one.

Reading `Pos` on a player serializes the whole player, inventory included. For players, prefer
[`ScoreVector.distanceTo`](https://kore.ayfri.com/docs/helpers/score-vectors.md#length-and-distance) from the `helpers` module, which reads
positions off a marker.

## Entity Effects

Extension functions on `Entity` for giving, clearing, and managing
[mob effects](https://minecraft.wiki/w/Effect):

```kotlin
function("buff_player") {
	player.giveEffect(Effects.SPEED, duration = 200, amplifier = 1)
	player.giveInfiniteEffect(Effects.NIGHT_VISION, hideParticles = true)
	player.clearEffect(Effects.SPEED)
	player.clearAllEffects()
}
```

| Function             | Description                           |
|----------------------|---------------------------------------|
| `giveEffect`         | Give a timed effect with optional amp |
| `giveInfiniteEffect` | Give an infinite-duration effect      |
| `clearEffect`        | Remove a specific effect              |
| `clearAllEffects`    | Remove all effects                    |
| `effects { ... }`    | Builder block for multiple operations |

## Putting it together

```kotlin
dataPack("arena") {
	val player = player("Steve")
	val mobs = entity(EntityTypes.ZOMBIE, limitToOne = false) { tag = "arena" }

	function("round_start") {
		player.joinTeam("red")

		player.batch("round_start_player") {
			give(self(), Items.DIAMOND)
			effect(self()) { give(Effects.SPEED, duration = 200) }
			title(self(), TitleLocation.ACTIONBAR, textComponent("Fight!"))
		}

		mobs.storeCountIn(player.getScoreEntity("mobs_left"))
	}
}
```

One reusable handle per gameplay concept, declared once at datapack level, then used across as many functions as
needed - that is the core value of the OOP entity API.

## See also

- [Items](https://kore.ayfri.com/docs/oop/items.md) - Reuse item stacks with `giveItem`, `replaceItem`, or summon-based reward flows.
- [Events](https://kore.ayfri.com/docs/oop/events.md) - Attach gameplay reactions directly to the entity and player handles you define here.
- [Spawners](https://kore.ayfri.com/docs/oop/spawners.md) - Pair selectors and entity utilities with reusable spawning entry points.
