LoadoutTcApi is a small, optional, client-side API. It lets another
mod change the HUD look, add its own slots, animate a slot, show ability timers or place a
second overlay next to the HUD. The HUD works with none of these calls.
API 4 Fabric 1.21.1 Client side 90 methods
| Entry point | com.toancao.loadouttc.api.LoadoutTcApi |
|---|---|
| Types | SlotView, SourceView, SlotSource, ApiSlot, SlotEffect, EffectContext, EffectFrame |
| Side | Client only; never call from a dedicated server |
| Version | LoadoutTcApi.version() and apiVersion() |
All methods are static members of LoadoutTcApi unless a row
names another type. Setters save config/loadouttc.json immediately, so do
not call them every frame.
The API is organised in layers. Most integrations need one or two of them:
| Layer | Use it to |
|---|---|
| Slot sources | Contribute slots from your own inventory; they appear as a tab and draw like any other slot. |
| Queries | Read every slot, its item, durability, cooldown and ability state. |
| Selection and order | Show, hide, filter and sort slots; open the slot menu. |
| Effects | Play a built-in animation, register a custom one or pin a featured slot. |
| Feedback layers | Style the durability, cooldown and ability feedback. |
| Panels | Split slots across independent HUD panels and read their screen bounds. |
| Look and layout | Pick the style, size, accent, arrangement and open the editor. |
| Task | Call |
|---|---|
| Change the whole look | setStyle("hex"), setSize("2x") |
| Highlight a slot for 3 s | playEffect(key, "pulse", 3000) |
| Show a skill timer | showAbility(key, 4500) |
| Add your own slots | Implement SlotSource, then declare the entrypoint |
| Move slots to another panel | splitToCluster("Rings", keys) |
| Keep another overlay clear of the HUD | hudBounds() |
The API lives inside the mod jar; there is no separate library. Add the jar as a compile-only dependency:
dependencies {
compileOnly files("libs/loadouttc-1.0.1+1.21.1.jar")
// Fabric Loom projects can use modCompileOnly instead
}
Imports used in this reference:
import com.toancao.loadouttc.api.ApiSlot;
import com.toancao.loadouttc.api.EffectContext;
import com.toancao.loadouttc.api.EffectFrame;
import com.toancao.loadouttc.api.LoadoutTcApi;
import com.toancao.loadouttc.api.SlotEffect;
import com.toancao.loadouttc.api.SlotSource;
Guard new methods by contract version. It only goes up when a method changes meaning or is removed:
if (LoadoutTcApi.apiVersion() >= 4) {
// SlotSource / ApiSlot, the extra SlotView fields and sourceViews() exist
for (LoadoutTcApi.SourceView tab : LoadoutTcApi.sourceViews()) {
LOG.info("{}: {}", tab.id(), tab.label());
}
}
| Method | Returns | Details |
|---|---|---|
apiVersion() | int | API contract version, currently 4. Cheap; safe in an entrypoint. |
version() | String | Fabric version string such as 1.0.1+1.21.1; "unknown" only if the mod container is missing. |
Optional dependency. If Loadout TC may be absent, check
FabricLoader.getInstance().isModLoaded("loadouttc") and keep every API call
behind that check, preferably in its own class so the API types are never loaded without
the mod.
Every slot has a stable key. The group segment is omitted when the group and the slot type share a name:
source/slot/index when group and slot share a name
source/group/slot/index otherwise
| Key | Source / group / slot / index |
|---|---|
accessories/ring/0 | accessories / ring / ring / 0 |
trinkets/chest/necklace/0 | trinkets / chest / necklace / 0 |
curios/ring/1 | curios / ring / ring / 1 |
vanilla/armor/helmet/0 | vanilla / armor / helmet / 0 |
vanilla/offhand/0 | vanilla / offhand / offhand / 0 |
vanilla/hotbar/3 | vanilla / hotbar / hotbar / 3 |
vanilla/inventory/14 | vanilla / inventory / inventory / 14 |
mymod/charm/0 | your source / charm / charm / 0 |
Indices start at 0. Keys never change while the game runs, so they are safe to
persist, but a removed source makes its keys disappear.
| Method | Returns | Details |
|---|---|---|
slotKeys() | List<String> | Keys the HUD is drawing right now, in display order. Filtered and sorted. |
slots() | List<LoadoutTcApi.SlotView> | Every known slot, including hidden and empty ones. |
visibleSlots() | List<LoadoutTcApi.SlotView> | Exactly the drawn slots, following each panel's own sort order and slot cap. |
slotBounds(String slotKey) | int[] | x, y, w, h in GUI pixels, or all zeroes when the slot is not drawn. |
LoadoutTcApi.SlotView is an immutable snapshot of one slot, including its live
state at the moment of the call.
| Field | Meaning |
|---|---|
key | Stable slot key, see Slot keys. |
source / group | Provider id (for example accessories) and its sub-group (ring). |
label | Heading shown for the group, for example Ring. |
index | Position inside that slot type. |
itemId | Registry id such as minecraft:diamond_sword; empty for an empty slot. |
empty | true when the slot has no stack. |
visible | Whether the panel that owns the slot is drawing it, using that panel's filter, sort and cap. |
stack / count | The live ItemStack and its stack size (0 when empty). |
damage / maxDamage | Durability values; both 0 for items that cannot take damage. |
cooldownRemaining | Vanilla cooldown fraction: 0 ready, 1 just started. |
abilityRemaining | Ability timer fraction, 0..1. |
abilitySeconds | Remaining seconds of the timer started with showAbility; 0 when idle. |
Helpers: damageable() is maxDamage > 0, and
onCooldown() is cooldownRemaining > 0.
LoadoutTcApi.SourceView is a record of id and label,
returned in the order the slot menu shows its tabs. Use it to build a matching tab bar.
A source contributes slots to the HUD. It gets a tab in the slot menu, and its keys use your
id as the prefix. Implement SlotSource with only API types; no internal class
is needed.
public final class MySource implements SlotSource {
public String id() { return "mymod"; }
public String label() { return "My Mod"; }
public boolean available() { return true; }
public void collect(Minecraft minecraft, Player player, boolean includeEmpty,
List<ApiSlot> out) {
ItemStack stack = myEquippedStack(player);
if (!stack.isEmpty() || includeEmpty) {
out.add(new ApiSlot(id(), "charm", "Charm", "charm", 0, stack));
}
}
}
LoadoutTcApi.registerSource(new MySource());
| Member | Contract |
|---|---|
id() | Unique, lowercase. Becomes the key prefix (mymod/...) and the tab id. |
label() | Tab caption; defaults to id(). |
available() | Return false while the other mod is absent; the tab is hidden and collect is not called. |
collect(Minecraft, Player, boolean includeEmpty, List<ApiSlot> out) | Fill out in display order. Emit empty stacks only when includeEmpty is true. |
| Field | Meaning |
|---|---|
source | Must equal id(). |
group / groupLabel | Sub-group inside the tab (for example ring) and the heading printed for it. |
slot | Slot type; repeat the group name when they are the same. |
index | Position inside that slot type, starting at 0. |
stack | ItemStack.EMPTY for an empty slot; null becomes empty. |
key(), empty() and itemId() are derived for you;
key() follows the format in Slot keys.
Declare the loadouttc:slot_source entrypoint in your own
fabric.mod.json and the HUD picks the source up at launch:
{
"entrypoints": {
"loadouttc:slot_source": ["com.example.mymod.MySlots"]
}
}
The class needs a no-arg constructor and implements SlotSource. List one class
per source. Registering the same id at runtime replaces the entrypoint version, so a mod
can also call registerSource(...) later, for example after its own config
loads. A throwing available() or collect() disables only that
source and is logged; the rest of the HUD keeps working.
| Method | Returns | Details |
|---|---|---|
registerSource(SlotSource source) | boolean | Adds or replaces a source; its tab appears immediately. false for a null or blank id. |
registerSource(AccessorySource source) | boolean | Legacy overload. It exposes internal types that may change; prefer SlotSource. |
unregisterSource(String id) | boolean | Removes a source; false when the id was not registered. |
sources() | List<String> | Installed source ids, vanilla first. |
hasSource(String id) | boolean | Whether a source is installed/registered right now; this is not the enable switch. |
sourceViews() | List<LoadoutTcApi.SourceView> | Id and display label of every source, in slot-menu tab order. |
setSourceEnabled(String sourceId, boolean enabled) | void | Hides or shows a whole source in every panel without uninstalling it. |
isSourceEnabled(String sourceId) | boolean | The saved enable switch for that source. |
setVanillaGroup(String group, boolean enabled) | void | Accepts armor, offhand, hotbar or inventory; other names are ignored. |
These setters apply to every panel. Once a config has more than one panel, each panel keeps its own selection; the getters below return the shared defaults that new panels start from. Ticking a slot in the menu also claims it for the panel being edited.
| Method | Returns | Details |
|---|---|---|
setEmptySlots(boolean enabled) | void | Draw empty slots as ghost frames. |
setSlotVisible(String slotKey, boolean visible) | void | Tick or untick one slot using the active filter mode. |
isSlotVisible(String slotKey) | boolean | Shared default selection for that key. |
showOnlySlots(Collection<String> keys) | void | Switches to selected mode and keeps only these keys. |
showAllSlots() | void | Resets to all mode. |
setSlotFilter(String mode) | void | all or selected. Selecting selected snapshots the slots visible at that moment; other values are ignored. |
slotFilter() | String | Current shared visibility model. |
setSortMode(String mode) | void | default, name, type, source or custom. custom seeds the manual order from provider order. |
sortMode() | String | Current shared sort mode. |
setSlotOrder(List<String> keys) | void | Replaces the manual order and switches to custom. Keys missing from the list are appended, so they never disappear. |
moveSlot(String slotKey, int delta) | void | Moves one slot in the manual order; -1 up, 1 down. Switches to custom when it actually moves. |
openSlots() | void | Opens the slot menu when a player is in game and no other screen is open. |
A panel is one independent HUD: its own slots, position and optionally its own look. A config always has at least one, and the rest panel catches every slot no other panel claims, so one panel behaves like the classic single HUD.
String panel = LoadoutTcApi.splitToCluster("Rings", List.of("accessories/ring/0"));
LoadoutTcApi.assignSlotToCluster("accessories/ring/1", panel);
int[] rect = LoadoutTcApi.clusterBounds(panel); // x, y, w, h on screen
int[] all = LoadoutTcApi.hudBounds(); // union of every panel
| Method | Returns | Details |
|---|---|---|
clusters() | List<String> | Ids of every panel, in draw order. |
clusterOf(String slotKey) | String | Panel currently drawing that slot, or an empty string. |
clusterSlots(String clusterId) | List<String> | Slots explicitly owned by a panel; empty means it is the catch-all panel. |
createCluster(String name) | String | Creates an empty panel and returns its id. |
splitToCluster(String name, Collection<String> slotKeys) | String | Creates a panel and moves those slots into it, in one call. |
assignSlotToCluster(String slotKey, String clusterId) | void | Moves one slot. A blank or unknown id leaves it to the catch-all panel. |
removeCluster(String clusterId) | boolean | Deletes the panel and switches its slots off, so deleting never hands them to another panel. The last panel cannot be removed. false when nothing changed. |
mergeClusters(String sourceId, String destId, boolean takeSourceLook) | boolean | Moves all slots of sourceId into destId and removes the source; optionally the source look becomes the destination look. false for equal or unknown ids. |
renameCluster(String clusterId, String name) | boolean | Sets the panel label, truncated to 20 characters. false for an unknown id or blank name. |
setClusterEnabled(String clusterId, boolean enabled) | void | Hides or shows one panel; its settings are kept. |
clusterBounds(String clusterId) | int[] | x, y, w, h of one panel, or all zeroes when it is not drawn. |
hudBounds() | int[] | Union of every panel, so another overlay can avoid the HUD. |
An effect is a per-frame transform of one slot icon. Built-ins cover the common cases; a mod can register its own.
| Id | Effect |
|---|---|
spin | 2D wheel rotation, 360 deg/s (best for flat icons). |
spin_3d | 3D coin rotation, 300 deg/s. |
spin_fast | 2D rotation, 720 deg/s. |
spin_3d_fast | 3D rotation, 720 deg/s. |
bob | Gentle vertical float. |
pulse | Scale and accent glow pulse. |
shake | Small jitter. |
flash | Glow blink. |
rainbow | Hue-cycling glow. |
hover | Small lift and glow; used automatically on hover. |
none | No-op. |
LoadoutTcApi.playEffect("accessories/ring/0", "spin", 3000); // 3 seconds
LoadoutTcApi.playEffect("accessories/ring/0", "pulse", 0, 0xFFFF6B6B); // until cleared, red
LoadoutTcApi.clearEffect("accessories/ring/0");
LoadoutTcApi.clearAllEffects();
durationMillis <= 0 means "until cleared". color is ARGB;
0 uses the HUD accent. Both playEffect overloads return
false for a blank slot key or an unknown effect id.
| Method | Returns | Details |
|---|---|---|
playEffect(String slotKey, String effectId, long durationMillis, int color) | boolean | Plays one effect on one slot with an ARGB override. |
playEffect(String slotKey, String effectId, long durationMillis) | boolean | Same, using the HUD accent. |
clearEffect(String slotKey) | void | Stops the timed effect on that slot; per-slot settings stay. |
clearAllEffects() | void | Stops every timed effect. |
triggerFeaturedEffect(long durationMillis) | boolean | Plays the pinned effect on the featured slot for that long. |
triggerFeaturedEffect() | boolean | Same with a 2000 ms duration. |
setFeaturedSlot(String slotKey) | void | Pins the featured slot; an empty string clears it. Persisted as featuredSlot. |
featuredSlot() | String | Current pinned key, or an empty string. |
setFeaturedEffect(String effectId) | void | Changes the pinned effect. Unknown ids are ignored. |
registerEffect(String id, SlotEffect effect) | boolean | Registers or replaces a custom effect. false for a blank id or null effect. |
unregisterEffect(String id) | boolean | Removes a custom effect; false when it was not registered. |
effects() | Set<String> | Every available effect id, including built-ins. |
setSlotEffect(String slotKey, String effectId) | void | Permanent per-slot effect. Unknown ids are ignored; "none" disables it. Glow effects use the slot's light channel. |
clearSlotOverrides(String slotKey) | void | Drops every per-slot override: effect, cooldown style and durability style. |
LoadoutTcApi.registerEffect("sparkle", context -> {
float wave = 0.5f + 0.5f * (float) Math.sin(context.seconds() * 9.0f);
return new EffectFrame(
0.0f, // offsetX
0.0f, // offsetY
1.0f + wave * 0.06f, // scale
0.0f, // spinDegrees
false, // threeD
0xFFFFD166, // glowColor (ARGB)
wave * 0.6f // glowStrength 0..1
);
});
SlotEffect is a functional interface:
EffectFrame apply(EffectContext context). It runs on the client render thread
once per frame, so keep it cheap.
| Field | Meaning |
|---|---|
slotKey() | Key of the slot being drawn. |
stack() | Its ItemStack. |
seconds() | Seconds since the effect started (or since launch for featured/hover). |
progress() | 0..1 for timed effects, 1 for permanent effects. |
featured() | Whether this is the pinned/featured slot. |
hovered() | Whether the mouse is over it in the editor. |
accentColor() | Active accent, or the colour passed to playEffect. |
| Field | Range | Meaning |
|---|---|---|
offsetX / offsetY | GUI pixels | Translates the icon. |
scale | > 0 | Uniform scale; values <= 0 become 1. |
spinDegrees | degrees | Rotation, around the vertical axis when threeD is true. |
threeD | boolean | 3D coin spin instead of flat 2D spin. |
glowColor | ARGB | 0 means no glow. |
glowStrength | 0..1 | Clamped on construction. |
Shortcuts: EffectFrame.NONE, EffectFrame.spin(degrees),
EffectFrame.offset(x, y), EffectFrame.scale(s) and
EffectFrame.glow(color, strength).
Durability, cooldown and ability each own an options object: colour, thickness, opacity, text format and motion. These setters change the global layer options; per-slot styles are set separately at the end of the table. Values are clamped to the stated range.
| Method | Returns | Details |
|---|---|---|
setCooldownThickness(int pixels) | void | Cooldown stroke or bar height, 1..4. |
setCooldownOpacity(int percent) | void | Cooldown layer opacity, 30..100. |
setCooldownText(String kind) | void | seconds, int or percent; other values are ignored. |
setCooldownPulse(boolean enabled) | void | Blink when the cooldown is nearly done. |
setCooldownReverse(boolean enabled) | void | Draw the arc, bar or frame from the opposite end. |
setCooldownTrack(boolean enabled) | void | Faint background track behind the fill. |
setAbilityThickness(int pixels) | void | Ability stroke or bar height, 1..4. |
setAbilityOpacity(int percent) | void | Ability layer opacity, 30..100. |
setAbilityText(String kind) | void | seconds, int or percent; other values are ignored. |
setAbilityPulse(boolean enabled) | void | Blink when the timer is nearly done. |
setAbilityReverse(boolean enabled) | void | Draw the timer from the opposite end. |
setAbilityTrack(boolean enabled) | void | Faint background track behind the timer. |
setDurabilityThickness(int pixels) | void | Durability bar, pips or ring stroke, 1..4. |
setDurabilityOpacity(int percent) | void | Durability layer opacity, 30..100. |
setDurabilityTrack(boolean enabled) | void | Background track behind the durability fill. |
setSlotCooldownStyle(String slotKey, String styleId) | void | Cooldown style for one slot: arc, text, bar, frame or off. Unknown ids fall back to arc. |
setSlotDurabilityStyle(String slotKey, String styleId) | void | Durability style for one slot: bar, segments, pips, text, ring, battery or off. Unknown ids fall back to bar. |
Global shapes are picked with setCooldownStyle and
setDurabilityStyle; per-slot effects with
setSlotEffect.
Vanilla exposes item cooldowns only. For skills, channels or buffs, push a timer yourself; the HUD draws a countdown in the configured style.
// 4.5 s cast on the ring slot; colour 0 uses the configured accent
LoadoutTcApi.showAbility("accessories/ring/0", 4500L);
LoadoutTcApi.showAbility("accessories/necklace/0", 4500L, 0xFF7C9EFF);
LoadoutTcApi.hideAbility("accessories/ring/0");
LoadoutTcApi.clearAbilities();
| Method | Returns | Details |
|---|---|---|
showAbility(String slotKey, long durationMillis) | void | Starts or restarts a timer using the accent colour. |
showAbility(String slotKey, long durationMillis, int argb) | void | Same with an explicit ARGB colour; 0 falls back to the accent. |
hideAbility(String slotKey) | void | Stops the timer on one slot. |
clearAbilities() | void | Stops every ability timer at once. |
setAbilityStyle(String styleId) | void | Chooses the drawing style; unknown ids fall back to ring. |
| Style | Look |
|---|---|
ring | Arc just outside the icon. |
bar | 2 px strip on the slot's top edge. |
text | Remaining seconds over the icon. |
frame | Progress traced along the slot frame; follows hex, rounded or square shapes. |
off | Hidden. |
Styles, size, accent and arrangement are global config values. Every setter here saves
config/loadouttc.json immediately.
| Method | Returns | Details |
|---|---|---|
styles() | List<String> | Every style id (31). The first ten are the editor gallery. |
setStyle(String styleId) | void | Switches the whole HUD style. Unknown ids fall back to vanilla. |
setSize(String size) | void | auto, small, medium, large, xlarge, huge, giant or custom; other values are ignored. |
setCustomScale(float scale) | void | Switches to custom and clamps to 0.5..3.0. |
setDurabilityStyle(String styleId) | void | Global durability shape; off also disables the layer. Unknown ids fall back to bar. |
setCooldownStyle(String styleId) | void | Global cooldown shape; off also disables the layer. Unknown ids fall back to arc. |
cooldownStyles() | List<String> | Every id setCooldownStyle accepts. |
setLayoutMode(String mode) | void | vertical, horizontal, grid or circle; other values are ignored. |
layoutMode() | String | Current resolved arrangement. |
setColumns(int columns) | void | Grid columns, clamped to 1..8. |
setCircleRadius(int radius) | void | Ring radius in GUI pixels, clamped to 16..200. |
setAccent(int argb) | void | Sets the accent; the alpha channel is ignored and only RGB is stored. |
setEnabled(boolean enabled) | void | Hides or shows the whole HUD; all settings are kept. |
openEditor() | void | Opens the editor when a player is in game and no other screen is open. |
reload() | void | Re-reads loadouttc.json, for example after another mod edited it. |
auto is one HUD unit per GUI unit, so a slot matches a vanilla hotbar slot at
every GUI scale. Larger presets exist because the vanilla size can read small on a big
screen.
| Id | Scale |
|---|---|
auto | 1.00x of the GUI scale |
small | 0.80x |
medium | 1.00x |
large | 1.25x |
xlarge | 1.50x |
huge | 2.00x |
giant | 3.00x |
custom | 0.50 - 3.00x |
styles() returns all 31 ids. Ten are shown in the editor gallery; the rest still
load from an existing config:
vanilla, steel, hex, liquid_glass, bare, fantasy_rpg, carbon, parchment, arcane, outline,
notion, glassmorphism, neumorphism, bento, dynamic_island, dock, material_expressive, terminal,
pixel_vanilla, minimal, chips, sticker, clay, neon, brutalist, editorial, frost, arcade,
grouped, compact, scifi_tactical
The first line is the gallery set, in menu order. bare, minimal,
chips, sticker and outline draw no outer panel.