promotional bannermobile promotional banner

Overgrown's Apoli

A data-driven power system that's build for custom abilities, mechanics, and entire origin systems from JSON alone.
Back to Files

Apoli (1.129.0)

File nameapoli-1.129.0.jar
Uploader
OvergrownMCOvergrownMC
Uploaded
Nov 7, 2026
Downloads
10
Size
4.1 MB
Mod Loaders
Fabric
File ID
9498466
Type
R
Release
Supported game versions
  • 1.20.1

Curse Maven Snippet

Fabric

modImplementation "curse.maven:apoli-1631826:9498466"

Learn more about Curse Maven

What's new

1.129.0

Before you update

  • damage_self on the entity and bi-entity apoli:explode works now. It defaults to true, so an explode without the field hurts the entity that sets it off whenever that entity is inside the blast. Add "damage_self": false to keep the old behaviour.
  • Explosions set off by raycasts, projectiles and bi-entity actions are credited to a player more often now, and credited explosions follow the server's PvP and team rules. With pvp=false, a player's explosions don't hurt other players.

Added

Sticky projectiles

apoli:fire_projectile, as a power or as an entity action, takes a sticky object, or true for the defaults. A projectile drawn from texture_location stops in the block it hits and stays there like an arrow, then runs bientity_action_on_expire when its time is up.

Field Type Default Description
duration Integer or expression 1200 Ticks it stays stuck before it expires. 0 keeps it until lifetime or something else ends it.
depth Float or expression 0 How far it sinks past the hit point along its flight path. Negative values hold it off the surface.
block_condition Block condition optional Only blocks that pass this hold it.
bientity_action_on_stick Bi-entity action optional Runs each time it sticks, with the owner as actor and the projectile as target.

Block hit actions still run before it sticks, and lifetime keeps counting while it is stuck. With reflective it bounces first and sticks afterwards, return.after pulls a stuck projectile back out, and a projectile whose block breaks falls and sticks again.

{
  "type": "apoli:fire_projectile",
  "texture_location": "example:textures/entity/sticky_bomb.png",
  "speed": 1,
  "sticky": {
    "duration": 60
  },
  "bientity_action_on_expire": {
    "type": "apoli:explode",
    "power": 3,
    "at_target": true,
    "damage_self": false
  }
}

Fixed

Explosion death messages

Explosions credit whoever caused them. An apoli:explode block action in a raycast, or in a projectile's block_action_on_hit, used to name no killer ("blew up") or blame whoever had last hit the victim. apoli:explode run on a target through apoli:target_action credited the target, and an explode in a projectile's bientity_action_on_hit credited the projectile and printed entity.apoli.custom_projectile. Now a block explosion credits the entity that ran the block action, an entity explosion on a bi-entity target credits that action's actor, and anything a projectile sets off credits its shooter.

damage_self

damage_self: true on the entity and bi-entity apoli:explode never damaged the entity that set the explosion off. It does now, as documented.


1.128.0

Added

apoli:equipped_accessory

An entity condition that passes when the entity wears an accessory matching an item condition, in any slot or in the listed slots. It is registered when Trinkets, Accessories or Curios is installed.

Field Type Default Description
item_condition Item condition optional What a worn accessory must pass. Without it, any equipped accessory counts.
slots Accessory slots [] The slots to look in. Empty means every slot.
{
  "type": "apoli:equipped_accessory",
  "slots": "charm",
  "item_condition": {
    "type": "apoli:ingredient",
    "ingredient": {
      "item": "example:moon_charm"
    }
  }
}

Accessory slots in apoli:equipped_item

apoli:equipped_item takes an accessory_slot field (the same slot format as conjure_equipment), and equipment_slot is optional. At least one of the two is required, and with both the condition passes when either has a matching item. "accessory_slot": "*" checks every accessory slot. The field isn't gated, so a pack using it still loads without an accessory mod.

item_condition on apoli:accessory_equipped_count

Only accessories that pass the condition are counted.

* in accessory slot filters

Any part of an accessory slot filter can be *, which matches everything.

Changed

Invisibility hides everything worn

apoli:invisibility with render_armor: false (the default) hides every layer drawn on the body: vanilla armor, elytra, capes, heads on the helmet slot, Trinkets, Accessories and Curios items, and layers other mods draw, such as backpacks and goggles. Held items still follow render_held_items, and layers from Apoli's own powers still draw.

Load errors point at the problem

Every power, origin, layer, badge, skill tree, keybind, global power set and custom effect that fails to load is logged with its file, pack, JSON path, line and column, plus the line itself with a caret under the broken value. That covers codec errors (unknown types, missing fields, wrong value kinds) as well as syntax errors. Dropped optional fields get a warning pointing at the field, and messages no longer dump whole objects. After loading, one line sums up errors and warnings by kind, and /apoli:dev_mode lists them in chat when it is turned on and after every /reload (hover for details, click to copy the file).

Fixed

Accessories counted twice with the compat layer

With the Accessories compatibility layer next to real Curios (NeoForge) or Trinkets (Fabric), items were read through both, so counts doubled and apoli:action_on_accessory_change fired twice. Apoli reads them once, through Accessories.

Performance

Accessory checks

equipped_accessory, accessory_equipped_count and the accessory_slot of equipped_item scan slots without building lists, and the count stops as soon as the comparison is settled.


1.127.0

Added

/apoli:key hold

/apoli:key hold <targets> <key> holds a key down until /apoli:key release or /apoli:key clear lets go of it, on players and on any other entity. It is for testing powers that run while a key is held, such as a continuous apoli:action_on_key_press or one with entity_action_released.

apoli:key hold @s key.apoli.primary_active
apoli:key release @s key.apoli.primary_active

Fixed

Forced keys on players

A key forced on a player with apoli:force_key_pressed or /apoli:key press counted as a single tap for Apoli's own powers, whatever the duration. It now counts as held on the client for the whole duration, so continuous powers keep firing, the key reaches the server as held, and entity_action_released runs when the hold ends.

A shorter force cut a longer one

Forcing a key that was already forced kept the longer duration on the client but used the newer one on the server, so a short press during a long hold ended the hold early on the server. Both sides keep the longer duration now, so a press can't shorten a hold.

Ghost blocks placed again

Placing apoli:ghost_block where a ghost block already was kept the first placement's timer, so a block that kept being refreshed still disappeared when the first one ran out. The timer restarts from the latest placement, and the original block is still the one from before the first placement.

Performance

Ghost blocks in unloaded chunks

A ghost block that ran out after its chunk unloaded loaded that chunk on the spot, on the server thread, to put the original block back, so walking away from an area full of them caused a lag spike per block. The original now comes back the next time the chunk loads, within a second of it loading, and chunks are only loaded for this when the server stops. apoli:ghost_block also does nothing at a position whose chunk isn't loaded, instead of loading it.


1.126.0

Before you update

  • Resources can hold decimals now. Whole-number resources work and save exactly as before, but a world saved with a decimal value loses the fraction if you go back to an older Apoli.
  • The network format changed, so the client and the server both need 1.126.0. A mismatched pair is turned away at login with a message.
  • consume_sound on apoli:edible_item no longer defaults to entity.generic.eat. Left out, the item uses the eating sound with "eat" and the drinking sound with "drink".

Added

Glowing blocks

New block action apoli:glow highlights the block it runs on, and new power type apoli:block_glow highlights the blocks around its holder for that player only. "outline" mode draws the Glowing effect's colored outline, visible through walls. "glow" mode draws the block itself, block entities included, in front of everything at full brightness, tinted by the color.

Field On Default What it does
red, green, blue (or r, g, b) both 1 The color, from 0 to 1.
mode both "outline" "outline" or "glow".
respect_bounding both true Follow the block's own shape, or draw a full cube.
entity_condition apoli:glow none Only players who pass it see the glow. Checked on the server a few times a second.
duration apoli:glow 20 Ticks. 0 or less lasts until the block changes.
block_condition apoli:block_glow required Which blocks glow. Runs on the player's game.
distance apoli:block_glow 16 Search radius in blocks, at most 64.

A glow ends when its block is mined or replaced. Glows from the action are saved with the world.

{
  "type": "apoli:block_glow",
  "block_condition": { "type": "apoli:block", "block": "minecraft:diamond_ore" },
  "r": 0,
  "g": 1,
  "b": 1,
  "distance": 25
}

Expressions in the random_chance condition

chance on the apoli:random_chance condition (and its apoli:chance alias) takes an expression, read against the entity being checked. The block versions of the condition and the action read the entity behind the block action when there is one.

Changed

Resources with decimals

  • apoli:resource values, min, max, start_value and on_change values take decimals, and so does compare_to on the apoli:resource condition.
  • apoli:modify_resource writes the decimal its modifier works out instead of rounding to a whole number. The legacy change field of apoli:change_resource keeps decimals too, and attribute modifier values are read at full precision.
  • Values keep six decimal places, so adding 0.1 ten times reaches exactly 1 and max_action and on_change fire on time.
  • /apoli:resource set and change take decimals, get has an optional scale after the position (get @s mypack:mana 0 100), and operation keeps fractions. Printed values keep their decimals.
  • Expressions read the exact value. Macro arguments fill in 2.5 for a decimal and 5 for a whole value.
  • The apoli:resource advancement trigger takes decimal bounds.
  • Cooldowns still count whole ticks. A decimal written to one is rounded to the nearest tick.

HUD bars

Bars fill in proportion to decimal values. A bar only looks full at its maximum and only looks empty at its minimum, so 0.001 out of 1 shows a sliver and 0.999 is visibly short of full.

Fixed

edible_item consume_sound

consume_sound only played once after the item was eaten, so the normal eating or drinking sound played the whole time. It now replaces that sound from the first bite.

Tiny decimals in macros

A decimal below 0.001 in a macro argument printed in scientific notation (5.0E-4), which broke the command. It prints as 0.0005 now.


1.125.0

Fabric 1.20.1, Fabric 1.21.1 and NeoForge 1.21.1. Update Origins to 1.50.0 alongside it.

Added

Create integration

With Create installed (NeoForge 1.21.1 and Fabric 1.20.1; Create has no Fabric 1.21.1 build):

  • A diving helmet worn with a backtank that holds air lets an apoli:water_breathing entity with suffocate_outside_water breathe on land, drawing 1 air a second from the backtank, the rate Create uses underwater.
  • Diving boots switch off apoli:modify_swim_speed, including swim speed passed on by apoli:attribute_modify_transfer.
  • New power type apoli:create_goggles shows Create's goggle overlay without the goggles. It has no fields, is always registered, and does nothing without Create.
  • New item tags apoli:create/diving_helmets, apoli:create/backtanks and apoli:create/diving_boots (all entries optional) decide what counts as diving gear.
{
  "type": "apoli:create_goggles",
  "condition": {
    "type": "apoli:sneaking"
  }
}

Fixed

Raycasts that hit a Sable or Create Aeronautics ship

Sable keeps a ship's blocks in a storage area about 20 million blocks out and answers rays there. apoli:raycast used that answer as a world position, so on a ship hit_x, hit_y, hit_z and distance pointed 20 million blocks away, command_at_hit ran out there, and the particle trail and command_along_ray stepped along the whole distance in one tick, which stalls the server. A hit on a ship is now turned back into the point on the hull the ray touched. Teleporting to the hit lands on the deck, command_hit_offset and chain_direction: reflect follow the face as the ship is turned, pierce works through ship blocks, and a ship hides entities behind it. Block actions and block conditions still get the ship's own block. The apoli:raycast entity condition measures its block distance the same way.

Ropes and phasing

A caster with apoli:phasing couldn't attach a rope to a wall or a ship with a raycast endpoint, because the rope's ray asked each block what it blocks for that caster. The ray now checks blocks the same way whoever casts it.

Camera and dev mode on ships

apoli:modify_camera with collision stops at a ship's hull instead of passing into it. Dev mode's outlines of apoli:raycast actions and conditions end where the ray hit a ship instead of trying to draw a line 20 million blocks long.

Type
Name
Game Versions
Mod Loaders
Size
Downloads
Uploaded