> ## Documentation Index
> Fetch the complete documentation index at: https://items.lodemc.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Props API

> Find placed props by block, entity or area, change their state, and place, rotate and break them from your plugin.

Everything about [props](https://items.lodemc.net/furniture.md) is in the `org.lodemc.api.prop` package. Plain [flora](https://items.lodemc.net/flora/plants.md) (plants without a crop or sapling section) works exactly like a prop, so it's included too.

## How a placed prop is stored

Each placed prop is **one saved `ItemDisplay` entity**, its *anchor*. The anchor draws the model and keeps all the piece's data, so props survive restarts, chunk unloads and WorldEdit copies. A prop's solid cells are real blocks, and its other hitboxes are packet-only entities that don't exist on the server.

That means:

* Only props in **loaded chunks** can be found.
* Clicking a solid cell gives a normal block event; use `LodeProps.at(block)` to find the piece.
* Don't remove the anchor yourself. Use `PlacedProp.remove()` or `breakNaturally()`, which also clear its cells, lights and seats.

```java theme={null}
import org.lodemc.api.prop.*;

// Every lamp within 10 blocks switches on at night
for (PlacedProp prop : LodeProps.near(player.getLocation(), 10)) {
    if (prop.getId().value().equals("lodestone_lamp")) prop.setState("on");
}
```

## LodeProps

### Finding props

**at(Block block)** `PlacedProp`

The piece filling `block` with one of its solid cells, or standing in it (its origin block). `null` if there's none.

**of(Entity entity)** `PlacedProp`

The piece whose anchor display `entity` is, or `null`.

**byUuid(UUID uuid)** `PlacedProp`

The piece whose anchor has this UUID, if its chunk is loaded. Use it to find a piece again later: save `getUuid()`, not the object.

**near(Location center, double radius)** `List\<PlacedProp\>`

Pieces whose anchor is within `radius` blocks of `center`.

**loaded(World world)** `List\<PlacedProp\>`

Every piece in loaded chunks of `world`, or of every world when you leave `world` out.

**props()** `Collection\<CustomProp\>`

Every prop configured right now.

**prop(Key id)** `CustomProp`

Prop `id`, or `null`. Also takes the id as a `String`.

**propOf(ItemStack stack)** `CustomProp`

The prop a stack places, or `null`.

### Placing props

**place(Key id, Block origin, float yaw, Player player)** `PlacedProp`

Places prop `id` standing on the floor in `origin`. Also takes the id as a `String`.

* `yaw` works like a player's yaw: the prop faces whoever looks at it with that yaw, as if they had placed it. It's snapped to the prop's `rotation:`. It defaults to 0, which is a player looking south, so the prop's front faces north.
* `player` is optional. With a player, protection plugins are asked first through a block place event, and the [`PropPlaceEvent`](https://items.lodemc.net/api/events#propplaceevent) names them.

Returns the new piece, or `null` if it doesn't fit there or was refused.

**problem(Key id, Block origin, float yaw)** `String`

Why prop `id` can't be placed in `origin` turned to `yaw`, such as `There isn't enough room.`, or `null` if it can. It checks the same rules as placing: free cells, the world border, `on:` and `not-on:`, and `max-nearby`.

## PlacedProp

A placed prop. It reads the live piece, so values are always current. It stops being valid once the piece is broken or its chunk unloads; look it up again then. Two `PlacedProp`s for the same piece are equal.

| Method | Returns | What it is |
| - | - | - |
| `getId()` | `Key` | Which prop it is |
| `getProp()` | `CustomProp` | Its config, or `null` if the prop was removed from the configs. The piece stays in the world as it was. |
| `getUuid()` | `UUID` | Its anchor's UUID, which stays the same across restarts |
| `getAnchor()` | `ItemDisplay` | The saved entity that is the piece |
| `getWorld()` | `World` | Its world |
| `getOrigin()` | `Block` | The block it stands in |
| `getLocation()` | `Location` | The middle of its origin block's floor |
| `getYaw()` | `float` | Its turn, like a player's yaw |
| `getPlacement()` | `String` | `floor`, `wall` or `ceiling` |
| `getState()` | `String` | Its current state from `states:`, or `null` for its default look |
| `isOpen()` | `boolean` | Whether its door is open |
| `getLightsOn()` | `boolean` | Whether its lights are on (`light-toggle`) |
| `getCells()` | `List<Block>` | The real blocks its solid cells fill |
| `isValid()` | `boolean` | `false` once it's broken or removed, or its chunk unloaded |
| `dropItem()` | `ItemStack` | The item it drops as itself: the stack it was placed with, dye included |

And to change it:

**setState(String name)** `boolean`

Switches it to one of its `states:`, or to its default look with `null`, with the state's sound, lights and particles. A [`PropStateChangeEvent`](https://items.lodemc.net/api/events#propstatechangeevent) fires first. Returns `false` if the name isn't one of its states or the event was cancelled.

**rotate(float yaw)** `boolean`

Turns it to `yaw`, snapped to its `rotation:`, if it still fits when turned. Returns `true` if it turned.

**breakNaturally(Player player, boolean drops)** `boolean`

Breaks it the way a player does. With a `player`, protection plugins are asked first through a block break event, and the tool rules in `drops:` read the player's hand. A [`PropBreakEvent`](https://items.lodemc.net/api/events#propbreakevent) fires and can change the drops. `drops` (default `true`) controls whether its `drops:` are dropped. Both arguments are optional. Storage contents and a jukebox's disc always spill out. Returns `true` if it broke.

**remove()** `void`

Takes it away with no drops, events or sounds. Storage contents and a jukebox's disc still spill out.

## CustomProp

A prop as it's configured. It's read-only, and a reload makes new objects.

| Method | Returns | What it is |
| - | - | - |
| `getId()` | `Key` | Its id, also its item's id |
| `getItem()` | `CustomItem` | The [item](https://items.lodemc.net/api/items.md) that places it |
| `createItem(int amount)` | `ItemStack` | A stack of that item. `amount` defaults to 1. |
| `getPlacements()` | `Set<String>` | Where it can go: `floor`, `wall`, `ceiling` |
| `getRotation()` | `String` | Its `rotation:`: `4`, `8`, `free` or `none` |
| `snapYaw(float yaw)` | `float` | `yaw` snapped to its rotation, as placing does |
| `getStates()` | `List<String>` | Its `states:` names, in order. A new piece is in none of them. |
| `getSeatCount()`, `getBedCount()` | `int` | How many seats and beds it has |
| `getHasStorage()` | `boolean` | Whether it has `storage:` |
| `isDoor()`, `isJukebox()`, `isConnectable()`, `isDyeable()` | `boolean` | Whether it has `door:`, `jukebox:`, `connect:`, `dyeable:` |
| `getHits()` | `int` | Left clicks it takes to break in survival (`hits:`) |
| `getCells()` | `List<int[]>` | Its solid cells as `[x, y, z]` offsets from its origin, for a piece placed at yaw 0 |

## Events

| Event | Fires when |
| - | - |
| [`PropPlaceEvent`](https://items.lodemc.net/api/events#propplaceevent) | A prop is about to be placed |
| [`PropBreakEvent`](https://items.lodemc.net/api/events#propbreakevent) | A prop is about to break; change its drops |
| [`PropInteractEvent`](https://items.lodemc.net/api/events#propinteractevent) | A player right-clicks a prop |
| [`PropStateChangeEvent`](https://items.lodemc.net/api/events#propstatechangeevent) | A prop switches state |

## Example: props that only work for their owner

```java theme={null}
private final NamespacedKey owner = new NamespacedKey(this, "owner");

@EventHandler
public void onPlace(PropPlaceEvent event) {
    // The anchor doesn't exist yet: remember who placed it once it does
    if (event.getPlayer() == null) return;
    UUID player = event.getPlayer().getUniqueId();
    Bukkit.getScheduler().runTask(this, () -> {
        PlacedProp placed = LodeProps.at(event.getOrigin());
        if (placed != null) placed.getAnchor().getPersistentDataContainer().set(owner, PersistentDataType.STRING, player.toString());
    });
}

@EventHandler
public void onUse(PropInteractEvent event) {
    String placedBy = event.getPlaced().getAnchor().getPersistentDataContainer().get(owner, PersistentDataType.STRING);
    if (placedBy != null && !placedBy.equals(event.getPlayer().getUniqueId().toString())) {
        event.setCancelled(true);
        event.getPlayer().sendMessage("That isn't yours.");
    }
}
```

You can store your own data on the anchor's persistent data container like this. It's saved with the piece and removed with it. Use your own plugin's namespace so you don't overwrite Lode Items' keys.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.