Apoli (1.17.0)
Curse Maven Snippet
What's new
### Added
- **`apoli:ghost_block`** (block action): Places a temporary block that puts the original back after `duration` ticks, including the original block entity's data. Unlike other temporary-block implementations it cannot be turned into free resources: it cannot be mined in survival or creative, cannot be right-clicked (so a ghost chest or furnace never opens), is skipped by explosions, and cannot be pushed by a piston. It never drops anything, and it is placed and removed without neighbour updates, so it does not trigger redstone, observers or gravity.
Fields: `block`, `nbt`, `duration` (default `20`, also accepted as `tick`), `block_action`, `end_action`.
Re-placing a ghost on top of a live one keeps the *first* original, so a platform that refreshes every few ticks still restores the world correctly. A ghost whose chunk has unloaded is force-loaded briefly so it still gets restored, and every live ghost is restored when the server stops.
- **`apoli:emissive`** (power): The holder renders at full brightness, and with **LambDynamicLights** installed it also casts real light on the blocks around it. Works on any entity that can hold powers.
Fields: `luminance` (0–15, default `15`), `self_lit` (default `true`), `water_sensitive` (default `false`).
The world-lighting half is optional: without LambDynamicLights the holder still glows, the room just stays dark. Nothing to configure either way — the mod is detected at runtime. Multiple active emissive powers do not stack; the highest `luminance` wins.
- **`apoli:player_model_type`** (entity condition): Checks whether a player's skin uses the wide (Steve) or slim (Alex) arms. Field: `model_type` (`wide` / `slim`; `default`, `classic`, `steve` and `alex` are also accepted). Clients report their model on join and whenever it changes; non-players always fail, and a client that has not reported counts as `wide`.
- **`apoli:show_both_arms`** (Power Type): Draws the first-person arm vanilla leaves out. Vanilla only ever draws one bare arm: the main hand's, and only while it is empty.
Fields: `off_hand` (default `true`) draws the off arm when the off hand is empty — the plain "see both hands" behaviour; `main_hand` (default `false`) draws the main arm even while you are holding an item.
It draws your *real* arm, so everything that changes how your arms look elsewhere applies here too: `custom_model_render` skins and texture overlays, `model_color`, `modify_player_model`, `modify_model_parts` transformations and keyframes, disguise skins, and swings from `swing_hand`. Hiding an arm with `modify_model_parts` hides it in first person too.
- **`iterate`** field on **`apoli:action_on_entity_set`**: `members` (default, unchanged behaviour) or `owners`. `owners` walks every entity set that contains *you*, with the set's owner as the actor and you as the target, which is what finally makes "get me out of the set that captured me" expressible. Previously the acting entity had to own the set, so a member that had been added to someone else's set could never act on it or leave it.
- **`accessory_slot`** field on **`apoli:conjure_equipment`**: Conjure straight into a Trinkets / Accessories / Curios slot, using the same slot-filter format as the other accessory types (`"charm"`, `"hand/ring"`, `"hand/ring/1"`, or the object form). `slot` is now optional; at least one of `slot` and `accessory_slot` must be present. When the filter matches several slots the item goes into the first empty one, so it behaves like equipping rather than overwriting. Does nothing when no accessory framework is installed.
- New data types: **Set Iteration** (`members` / `owners`) and **Player Model Type** (`wide` / `slim`).
### Changed
- **`apoli:conjure_equipment` conjured items are now refused instead of deleted.** Trying to put one in a chest, ender chest, crafting grid, shulker box, `apoli:inventory` power container or any other non-player container is now blocked outright, so the item stays where it was. Previously the item was silently destroyed on the way in, and several paths let it through entirely this is the fix for "you can just open a chest and put it inside".
- **`lock: true` conjured items can no longer be unequipped from accessory slots** on any of the three accessory frameworks.
- **`apoli:modify_player_model` now applies in first person.** Previously the model swap only covered third-person rendering, so your first-person arm stayed vanilla.
- **`apoli:disguise` / `apoli:disguise_as` player skins now apply in first person.** The first-person hand path reads the skin directly and never went through the hook the disguise used, so disguised players still saw their own arms.
### Fixed
- **Entity sets no longer leak or go stale.** `EntitySetPower` gained a reverse index (member -> the sets containing it), maintained across add, remove, time-limit expiry, power removal, mob conversion and entity removal. Cleaning up after a removed entity no longer scans every live set, and empty sets are now pruned on the expiry path as well.
### Performance
- `apoli:action_on_entity_set`'s new `owners` mode is an O(1) index lookup, not a scan over every entity set in the world, safe to call from an `action_over_time` with `interval: 1`.
- The ghost-block guards short-circuit to a single field read when no ghost blocks exist, so servers that never use the action pay nothing on block breaks, block use, explosions or piston pushes.
- `apoli:emissive` and `apoli:show_both_arms` both read the power container without allocating on their per-frame paths.
### Notes for data-pack authors
- If you have a power where a set member is supposed to remove itself from a set someone else owns, add `"iterate": "owners"` to the `apoli:action_on_entity_set`, it does nothing without it, and always did nothing before this release.
- `apoli:ghost_block` has no `add_block` field. Use `apoli:offset` to move the placement off the position the action was invoked at.
- Ghost blocks are held in memory, not saved to the world. A hard crash while one is placed leaves it behind, so keep durations short.
- **On-hit powers were investigated and are working correctly.** `apoli:action_on_hit`, `apoli:action_when_hit`, `apoli:action_when_damage_taken` and those aliases nested inside an `apoli:multiple` sub-power were all measured firing on every hit. If a chain built on them looks dead, check the actions inside it first. The entity-set ownership rule above was the real cause in the case that prompted this.
This mod has no additional files

