Skip to content

Information for Mod Developers

Tschipp edited this page Aug 2, 2026 · 1 revision

This page collects everything a mod developer needs to integrate with Carry On: excluding your own blocks and entities from being picked up, the events Carry On fires so protection mods can veto a pickup or placement, and the legacy IMC API.


Adding Carry On to your workspace

repositories {
    maven {
        url "https://maven.blamejared.com/"
    }
}

dependencies {
    deobfCompile "tschipp.carryon:carryon-LOADER-MCVERSION:MODVERSION"
}

Replace LOADER, MCVERSION and MODVERSION with the appropriate values, for example tschipp.carryon:carryon-forge-1.19.2:2.0.0.5.

You only need this dependency if you want to listen to Carry On's own events. Blacklisting via tags requires no dependency at all.


Blacklisting your own Blocks and Entities

The recommended way to exclude your content is tags. Ship the files below in your own mod's data folder. They merge with the tags of Carry On and every other mod, they work on all loaders, and they are silently ignored when Carry On is not installed — so no dependency and no compat code is needed.

Tag Registry File in your mod Effect
carryon:block_blacklist Block data/carryon/tags/blocks/block_blacklist.json Block can never be picked up
carryon:entity_blacklist Entity Type data/carryon/tags/entity_types/entity_blacklist.json Entity can never be picked up
carryon:stacking_blacklist Entity Type data/carryon/tags/entity_types/stacking_blacklist.json Nothing can be stacked on top of this entity
carryon:block_whitelist Block data/carryon/tags/blocks/block_whitelist.json Block can be picked up in whitelist mode
carryon:entity_whitelist Entity Type data/carryon/tags/entity_types/entity_whitelist.json Entity can be picked up in whitelist mode
carryon:stacking_whitelist Entity Type data/carryon/tags/entity_types/stacking_whitelist.json Entity can be stacked on in whitelist mode

Example — data/carryon/tags/blocks/block_blacklist.json:

{
  "replace": false,
  "values": [
    "yourmod:fragile_machine",
    "yourmod:multiblock_controller"
  ]
}

Always use "replace": false, otherwise you wipe every other mod's entries.

Whitelist mode

Blacklist and whitelist are never active at the same time. The config options useWhitelistBlocks, useWhitelistEntities and useWhitelistStacking switch each category over: when a whitelist is enabled, the corresponding blacklist is not consulted at all, and only tagged/listed content can be picked up.

Most packs use blacklist mode, but if your blocks should also work in a whitelist-mode pack, add them to the whitelist tag as well.

Interaction with the user config

Tag contents are merged with the user's config lists (blacklist.forbiddenTiles, blacklist.forbiddenEntities, blacklist.forbiddenStacking and the whitelist.* counterparts). See Black- and Whitelist Config for the config format, which additionally supports * wildcards and #namespace:tag entries.

Both lists are rebuilt whenever tags are (re)loaded — on world load and on /reload.

Things that bypass the blacklist

  • Baby mobs. A blacklisted AgeableMob can still be picked up while it is a baby, as long as the allowBabies config option is enabled. Give your entity a pickup-blocking script if this matters for you.
  • Scripts. A Carry On script with overrideChecks skips most guards. The block blacklist is still enforced, but the entity blacklist is not.

Blocks that can never be picked up anyway

Even without a blacklist entry, Carry On refuses to pick up:

  • Blocks using the vanilla DoorBlock.HALF property type (double blocks)
  • Blocks whose block entity NBT has a non-empty Lock tag
  • Unbreakable blocks (destroy speed -1) in Survival, unless pickupUnbreakableBlocks is enabled
  • Blocks without a block entity, unless pickupAllBlocks is enabled

For entities: tamed animals belonging to another player, entities with active invulnerability frames, hostile mobs in Survival while pickupHostileMobs is off, and entities exceeding maxEntityHeight / maxEntityWidth in Survival.

Requesting a blacklist entry in Carry On itself

If your mod is already released and you cannot ship a tag, open a Blacklist Request issue and the entry can be added to Carry On's own tag file.


Events

All Carry On events fire server-side only and before the world is modified. Cancelling one aborts the pickup or placement; Carry On then falls through to the normal interaction.

Carry On's own event: EntityPickupEvent

tschipp.carryon.events.EntityPickupEvent — fired right before a player picks up an entity. Available on NeoForge and Forge; there is no Fabric equivalent.

NeoForge — a cancellable Event with the public fields player and target, posted on NeoForge.EVENT_BUS:

@SubscribeEvent
public static void onCarryPickup(EntityPickupEvent event) {
    if (event.target instanceof YourEntity)
        event.setCanceled(true);
}

Forge — a RecordEvent with its own bus, player() and target() accessors, listener returns true to cancel:

EntityPickupEvent.BUS.addListener(event -> {
    return event.target() instanceof YourEntity;
});

There is no equivalent block pickup event of Carry On's own — block pickup is vetoed through the loader's block break event, see below.

Loader events that Carry On posts

So that protection, claim and anti-grief mods keep working without knowing anything about Carry On, every pickup and placement is announced through the loader's regular events. If you already listen to these, you are covered.

Action NeoForge Forge Fabric
Block pickup BreakBlockEvent BlockEvent.BreakEvent PlayerBlockBreakEvents.BEFORE
Block placement BlockEvent.EntityPlaceEvent BlockEvent.EntityPlaceEvent Architectury BlockEvent.PLACE
Entity pickup EntityPickupEvent EntityPickupEvent
Entity placement MobSpawnEvent.PositionCheck FinalizeSpawn

Notes:

  • Cancelling the break/place event denies the pickup or placement. For MobSpawnEvent.PositionCheck on NeoForge, return the result FAIL.
  • Entity placement events are only posted for entities that are a Mob.
  • On Fabric, the block placement event is only posted when Architectury is installed, since Fabric itself has no block place event.
  • Entity stacking (putting a carried mob on top of another mob) posts no event.
  • Placement of a carried block also happens on player death and on disconnect. Those paths do not post a place event.

Reading what a player is carrying

CarryOnData carry = CarryOnDataManager.getCarryData(player);

if (carry.isCarrying(CarryType.BLOCK))
    BlockState state = carry.getBlock();

if (carry.isCarrying(CarryType.ENTITY))
    Entity entity = carry.getEntity(level);

CarryType is one of BLOCK, ENTITY or PLAYER. The data is synced to clients, so it can be read on both sides. Write to it only on the server, and call CarryOnDataManager.setCarryData(player, carry) afterwards to sync the change.


IMC (legacy)

Carry On still processes IMC messages during InterModProcessEvent on Forge and NeoForge.

Use tags instead. The black- and whitelists are rebuilt when tags load, which happens after mod loading — so entries added through IMC are dropped again before the world is playable. IMC is kept for compatibility with old mods only.

Method Argument Meaning
blacklistBlock block name Add a block to the blacklist
whitelistBlock block name Add a block to the whitelist
blacklistEntity entity name Add an entity to the blacklist
whitelistEntity entity name Add an entity to the whitelist
blacklistStacking entity name Nothing can be stacked on top of this entity
whitelistStacking entity name Entity can be stacked on in whitelist mode
addModelOverride Model Override string No longer implemented

1.13 and newer:

InterModComms.sendTo("carryon", "blacklistBlock", () -> "minecraft:stone");
InterModComms.sendTo("carryon", "whitelistEntity", () -> "minecraft:zombie");

1.12:

FMLInterModComms.sendMessage("carryon", "blacklistBlock", "minecraft:stone");
FMLInterModComms.sendMessage("carryon", "whitelistEntity", "minecraft:zombie");
FMLInterModComms.sendMessage("carryon", "addModelOverride", "minecraft:hopper->(block)minecraft:hopper");

Datapack features

These are aimed at pack makers, but they are just as usable from a mod's built-in datapack: