> ## 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.

# Blocks API

> Recognise custom blocks, read their state, and place them from your plugin.

Custom blocks are real blocks on the server, but Bukkit reports a generic `Material` for all of them: `STONE`, `GLASS` or `TRIPWIRE`. `org.lodemc.api.block.LodeBlocks` tells you which custom block is really there and lets you place them.

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

@EventHandler
public void onClick(PlayerInteractEvent event) {
    if (event.getClickedBlock() == null) return;
    PlacedBlock placed = LodeBlocks.at(event.getClickedBlock());
    if (placed != null && placed.getId().value().equals("ruby_ore")) {
        event.getPlayer().sendMessage("You found ruby ore!");
    }
}
```

This covers every kind of custom block: solid, see-through and walk-through blocks, stairs, slabs, trapdoors, doors, [crops](https://items.lodemc.net/api/crops.md) and saplings. [Props](https://items.lodemc.net/api/props.md) aren't blocks; use `LodeProps` for them.

## LodeBlocks

### Finding blocks

**at(Block block)** `PlacedBlock`

The custom block at `block`, with its state, or `null` for a vanilla block.

**isCustom(Block block)** `boolean`

Whether a custom block is at `block`.

**isBlock(Block block, Key id)** `boolean`

Whether custom block `id` is at `block`.

**blocks()** `Collection\<CustomBlockType\>`

Every custom block configured right now.

**block(Key id)** `CustomBlockType`

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

**blockOf(ItemStack stack)** `CustomBlockType`

The custom block a stack places, or `null`.

### Placing blocks

**place(Block block, Key id, Map\<String, String> properties)** `boolean`

Places custom block `id` at `block`, replacing what's there. `properties` sets its state, using the names from `getPropertyNames()` for cube blocks (`axis=x`, `facing=east`, `stage=2`) or vanilla's names for stairs, slabs, trapdoors and doors (`facing=east`, `half=top`, `open=true`). Leave it out, or leave a property out, to get the default. Also takes the id as a `String`.

* Placed leaves are the kind that never decays, as when a player places them. Add `persistent=false` to place leaves that decay.
* Doors get their top half too.
* Light around a block with `light:` is added.
* **No events fire and nothing is checked**, like `/setblock`.

Returns `false` if there's no such block or the properties don't fit it.

```java theme={null}
LodeBlocks.place(block, "marble_pillar", Map.of("axis", "x"));
LodeBlocks.place(block, "marble_stairs", Map.of("facing", "east", "half", "top"));
```

To place a block as a player would, with protection checks and events, give the player the block's item instead.

## CustomBlockType

A custom block 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 |
| `getKind()` | `Kind` | `SOLID`, `SEE_THROUGH` or `WALK_THROUGH`. Stairs, slabs, trapdoors and doors are `SOLID`. |
| `getShape()` | `Shape` | `CUBE`, `STAIRS`, `SLAB`, `TRAPDOOR` or `DOOR` |
| `getHardness()` | `float` | Its `hardness:`. Stone is 1.5, `0` breaks at once, `-1` never breaks. |
| `getTool()` | `String` | Its `tool:`: `pickaxe`, `axe`, `shovel`, `hoe` or `none` |
| `getLight()` | `int` | Its `light:`, 0 to 15 |
| `getTags()` | `List<Key>` | Block tags it's in (`tags:`) |
| `getStripsInto()` | `Key` | The block an axe strips it into, or `null` |
| `isCrop()` | `boolean` | Whether it's a [crop](https://items.lodemc.net/api/crops.md) |
| `isSapling()` | `boolean` | Whether it's a sapling |
| `getDecays()` | `boolean` | Whether it's leaves that decay without a log nearby |
| `getPropertyNames()` | `List<String>` | The states a cube block can be in, such as `axis=x`, `axis=y`, `axis=z`, or one empty string for a block with one state. Empty for stairs, slabs, trapdoors and doors, which use vanilla's properties. |
| `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. |

The properties a cube block can have:

| Property | Values | Blocks |
| - | - | - |
| `axis` | `x`, `y`, `z` | `rotation: axis` |
| `facing` | `north`, `east`, `south`, `west` (plus `up`, `down` for `rotation: facing`) | `rotation: horizontal` or `facing` |
| `connect` | `0` to `63` | [Connected textures](https://items.lodemc.net/blocks/connected-textures.md): which neighbours it joins |
| `stage` | `0` to the ripe stage | [Crops](https://items.lodemc.net/api/crops.md) |
| `persistent` | `true` | Leaves placed by a player, which never decay |

## PlacedBlock

What `LodeBlocks.at` returns: a custom block in the world at the moment you asked.

| Method | Returns | What it is |
| - | - | - |
| `getBlock()` | `Block` | Where it is |
| `getType()` | `CustomBlockType` | Which block it is |
| `getId()` | `Key` | Its id |
| `getProperties()` | `Map<String, String>` | Its state: `axis`, `facing`, `stage`... for cube blocks, vanilla's properties for stairs, slabs, trapdoors and doors |
| `property(String name)` | `String` | One property, or `null` |

## Events

* [`CustomBlockPlaceEvent`](https://items.lodemc.net/api/events#customblockplaceevent) fires when a player places a custom block.
* [`CustomBlockBreakEvent`](https://items.lodemc.net/api/events#customblockbreakevent) fires when a player breaks one.
* Bukkit's own `BlockPlaceEvent`, `BlockBreakEvent`, `BlockDropItemEvent` and `PlayerInteractEvent` fire as for any block. Check them with `LodeBlocks.at`.


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