# Forge Datastorage Capabilities

> Forge Capabilities 能力系统：ICapabilityProvider#getCapability 获取、CapabilityManager#get CapabilityToken、LazyOptional 可选值、Forge-provided capabilities（IItemHandler/IFluidHandler/IEnergyStorage）、Capability 暴露（#getCapability 重写、LazyOptional.of、Capability#orEmpty）、AttachCapabilitiesEvent 事件（Entity/BlockEntity/ItemStack/Level/LevelChunk 5种泛型类型、#addCapability、ICapabilitySerializable 持久化）、RegisterCapabilitiesEvent 注册、@AutoRegisterCapability 注解、LevelChunk/BlockEntity 持久化（标记脏位、setChanged）、客户端同步（网络包发送）、PlayerEvent$Clone 玩家死亡数据持久化、Direction 面向特定实例、Capability#isRegistered 注册检查。

- Skill: `zmjjkk123-hub/forge-datastorage-capabilities` (Agent Skill)
- Install (CLI): `npx skillmds@latest add zmjjkk123-hub/forge-datastorage-capabilities`
- Raw SKILL.md: https://api.skillmd.com/api/skills/zmjjkk123-hub/forge-datastorage-capabilities/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: ZMJJKK123-hub (https://skillmd.com/u/zmjjkk123-hub)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/zmjjkk123-hub/forge-datastorage-capabilities

---


# The Capability System

Capabilities expose features dynamically via interfaces, avoiding direct implementation of many interfaces. Forge adds capability support to BlockEntities, Entities, ItemStacks, Levels, and LevelChunks.

## Forge-provided capabilities

- `IItemHandler`: inventory slots (block entities, entities, item stacks); replaces the old `Container`/`WorldlyContainer`.
- `IFluidHandler`: fluid inventories.
- `IEnergyStorage`: energy containers (based on RedstoneFlux).

## Using an existing capability

Query via `ICapabilityProvider#getCapability(Capability<T>, Direction)`. Get the capability instance via `CapabilityManager#get(new CapabilityToken<>(){})` (e.g. `ForgeCapabilities#ITEM_HANDLER`). A non-null instance may still be unregistered — check `Capability#isRegistered`. The `Direction` requests a face-specific instance; `null` = side-agnostic. Returns a `LazyOptional` (empty when unavailable).

## Exposing a capability

Create an instance per object; override `#getCapability`, compare `cap == ForgeCapabilities.ITEM_HANDLER`, return `LazyOptional.of(supplier).cast()`, fall back to `super`. Use `Capability#orEmpty` for a single capability. Invalidate at lifecycle end: `LazyOptional#invalidate` (in `#invalidateCaps` for owned providers; via `AttachCapabilitiesEvent#addListener` otherwise).

Items: attach providers via `Item#initCapabilities` (stored on the ItemStack).

Use direct `cap ==` checks, not maps — capability tests run every tick.

## Attaching capabilities

`AttachCapabilitiesEvent` has 5 generic types: `Entity`, `BlockEntity`, `ItemStack`, `Level`, `LevelChunk` (no subtypes — check `instanceof` yourself). Use `#addCapability` with an `ICapabilityProvider` (or `ICapabilitySerializable<T>` for persistence with save/load).

## Creating your own capability

- `RegisterCapabilitiesEvent#register(IExampleCapability.class)` (mod event bus), or
- annotate the interface with `@AutoRegisterCapability`.

## Persisting LevelChunk/BlockEntity capabilities

These are only written when marked dirty — mark the owner dirty on state changes (e.g. `ItemStackHandler#onContentsChanged` → `setChanged()`).

## Synchronizing with clients

Capability data is not sent by default; sync via packets on: entity spawn/block place, data changes, and new viewers.

## Persisting across player deaths

Data does not persist by default — copy it in `PlayerEvent$Clone`, using `#isWasDeath` to avoid duplicating values when returning from the End.

