Repository navigation
6.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.
// {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.
// 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) -> { ... });com.luminacity.advancedinteractions.util.ConditionEval:
// "isvip(gold)" in Who sees it / disabled if
ConditionEval.register("isvip", (arg, ctx) -> isVip(ctx.viewer(), arg));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.
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).
// {link.mymachine.energy:LINK}
DataSources.register("mymachine", new DataSource() { ... });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.
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.
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
});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}