Skip to content

6.For Mod Developers

ClassicBiz edited this page Oct 20, 2026 · 1 revision

For mod developers

AdvancedInteractions has an API for adding placeholders, actions, conditions, shops, economies and block data. Everything is server side. The main package is com.luminacity.advancedinteractions.api.

No hard dependency needed: you can call it through reflection, Forge IMC, or a KubeJS script, so your mod still loads without AdvancedInteractions.

Placeholders

// {mymod.balance} for the viewer
Placeholders.registerKey("mymod", "balance", "Player balance",
        (args, ctx) -> String.valueOf(getBalance(ctx.viewer())));

// A whole namespace: {mymod.<anything>}
Placeholders.register("mymod", (key, args, ctx) -> resolve(key, args, ctx));

// Describe your keys for /aholo placeholders and the editor's picker
Placeholders.document("mymod", Map.of("balance", "Player balance"));

ctx.viewer() is the player looking, ctx.level() the world, ctx.holo() the hologram. Values are worked out on the server and sent to the viewer.

Forge IMC (no compile dependency, send during InterModEnqueueEvent):

InterModComms.sendTo("advancedinteractions", "register_placeholder", () -> Map.of(
    "namespace", "mymod",
    "key", "balance",                 // optional: omit to handle the whole namespace
    "description", "Player balance",  // optional
    "resolver", (Function<Map<String, Object>, String>) ctx -> ...));

The resolver's map has key, args, viewer, level, holoId, holoAlias and meta.

Actions

// Button action "mymod:heal"
ActionRegistry.register("mymod:heal", (player, view, params) -> player.heal(20));

// Every action starting with "mymod:"
Actions.registerPrefix("mymod", (id, params, ctx) -> { ... });

Conditions

com.luminacity.advancedinteractions.util.ConditionEval:

// "isvip(gold)" in Who sees it / disabled if
ConditionEval.register("isvip", (arg, ctx) -> isVip(ctx.viewer(), arg));

Shops

Shops.register("mystore", new ShopHandler() {
    public TradeResult trade(TradeRequest r) { ... return TradeResult.ok("Bought!"); }
    public int maxQuantity(TradeRequest r) { return -1; } // -1 = unknown
});
Shops.document("mystore", "What it trades and what the trade action needs");

Holograms then use advholo:trade?shop=mystore&side=buy&qty={input.qty}&.... Your handler gets every action parameter (r.param(...)), plus the hologram's linked block (r.linkDim(), r.linkPos()). It runs on the server thread.

Economy

Connect your economy so money shops and money costs use it:

Economy.register(new Economy.Provider() {
    public double balance(ServerPlayer p) { ... }
    public boolean withdraw(ServerPlayer p, double amount) { ... } // false = can't afford, nothing changed
    public boolean deposit(ServerPlayer p, double amount) { ... }
    public String format(double amount) { return "$" + amount; }  // optional
});

For economies that answer later (e.g. a bank over the network), use Economy.registerAsync(...) instead; shops hold the goods until the answer arrives.

Forge IMC: InterModComms.sendTo("advancedinteractions", "register_economy", () -> Map.of("balance", ..., "withdraw", ..., "deposit", ..., "format", ...)) with Function / BiFunction values.

Once connected, {econ.player.balance} and {econ.format:N} show your money (unless you register your own econ placeholders).

Block data for linked blocks

// {link.mymachine.energy:LINK}
DataSources.register("mymachine", new DataSource() { ... });

Events

Listen for clicks (cancel to stop the action, or change it) and for advholo:event actions:

HologramEvents.onClick(e -> { if (blocked(e.getPlayer())) { e.setCanceled(true); e.setMessage("Not now"); } });
HologramEvents.onAction(e -> { if (e.getName().equals("opened_shop")) { ... } });

Forge / NeoForge: these are also posted on the Forge event bus as ForgeHologramEvents.Click and ForgeHologramEvents.Action (1.20.1). In the 1.19.2 version, listen for HologramClickEvent / HologramActionEvent on the Forge event bus.

Give a player a hologram

HologramFactory.createFromTemplate(...) / createFromJson(...) make a hologram owned by a player, e.g. a shop's storefront above its chest. It follows the player rules, doesn't count toward their limit, and they can't remove its links.

Land and claims

Ownership.register(new Ownership.Provider() {
    public Boolean mayPlace(ServerPlayer p, ServerLevel level, BlockPos pos) { ... }      // null = no opinion
    public Boolean mayEditOthers(ServerPlayer p, ServerLevel level, BlockPos pos) { ... } // e.g. co-owners
});

KubeJS

No Java needed:

// kubejs/server_scripts/holograms.js
const AI = Java.loadClass('com.luminacity.advancedinteractions.api.AdvInteractionsJS')

AI.placeholder('myserver', 'motd', 'Message of the day', (args, player, holo) => 'Welcome!')
AI.action('myserver:heal', (player, params, holo) => { player.heal(20) })
AI.condition('isnight', (arg, player, holo) => player.level.isNight())
AI.setState(player, 'coins', '10')   // shared with {state.coins}

Clone this wiki locally