Familiars Lib
The shared base for familiar mods: familiar blocks, shrinking, color layers, cosmetics, the compendium, the camera and photos, and the APIs and data formats behind them.
Familiars Lib is the library every familiar mod is built on, including Alshanex's Familiars. It provides:
- Taming and summoning: owning familiars, summoning them, the selection screens, death and revival.
- Shared blocks: the familiar bed, the familiar house and the shrinking station.
- Consumables: items that raise a familiar's stats permanently.
- Color layers: parts of a familiar's texture that can be recolored with dyes, items or the biome it spawns in.
- Cosmetics: hats and weapons players give to their familiars.
- The Identity Vessel: moves a familiar's colors to another familiar of the same type, mixing them into new ones.
- The Familiar Compendium: a book listing every familiar, its abilities and every color it can have.
- The Familiar Camera: takes photos of familiars that remember their exact look and pose.
- The APIs to make your own familiars, houses and beds, and use all of the above.
This page has three parts:
- For players: how taming, summoning, the blocks, colors, cosmetics, the compendium and the camera work in-game.
- For modpack makers: changing recipes, colors, interactions and cosmetics with data files only.
- For mod developers: making your own familiars and using the systems from code.
For players
Taming and summoning
Taming: right-click an untamed familiar with a taming item (Arcane Essence by default). Each try uses one item and has a 40% chance to succeed: hearts mean it worked, smoke means try again. Familiar mods can add other ways to obtain familiars.
Limits:
- You can carry up to 10 familiars by default (servers can change this, see Config). Familiars stored in a familiar house don't count.
- Up to 10 familiars can be summoned at the same time. A newly tamed familiar is already out, so it needs a free spot too.
Keybinds (in the Controls menu, under the familiar categories):
| Key | Default | What it does |
|---|---|---|
| Selection screen | H | Opens the familiar selection screen |
| Summon | X | Summons the selected familiar, or unsummons it if it's out |
| Quick summon 1 to 10 | Unbound | Summons or unsummons your 1st to 10th familiar directly |
Aimed summoning: sneak while pressing the summon key to summon the familiar at the block you're looking at, up to 24 blocks away. The spot must be visible from you, safe to stand on and free of other entities; if there's no valid spot there, the familiar appears next to you as usual. Without sneaking, familiars appear around you, spread out so several summoned familiars don't overlap.
The selection screen shows the familiars you carry. Pick one to make it your selected familiar, or release it into the wild. Released familiars are gone from your list for good.
Familiars can't use portals. When you die, your summoned familiars are unsummoned; summon them again afterwards.
Summoning several familiars
A multi-selection curio (such as Alshanex's Familiars' Pandora's Box) in your familiar trinket slot changes how summoning works:
- The selection key opens a grid of your familiars. Click up to 10 to select them.
- The summon key then summons every selected familiar that isn't out, and unsummons the ones that are.
Taking the curio off clears its selection.
Sitting
Right-click your own familiar with a stick to make it sit: it stays still and won't attack. Right-click it again to make it stand up. Getting hurt also makes it stand up. Modpacks and familiar mods can change which items do this (see Sit items).
Familiars that have a sitting animation play it while sitting, and also while stunned. The others keep their idle animation while sitting, and play their sleep animation while stunned.
Feeding, death and revival
Healing: familiars heal by sleeping in a familiar bed, or when you feed them familiar food (any food put through the shrinking station). Familiar food heals as much as the food would fill your hunger.
Familiars can't hurt you or each other: they're invulnerable to their owner and to the owner's other familiars, and stunned familiars can't be hurt at all.
When a familiar would die:
- If you have the Learn Necromancy advancement and at least 80 mana, the 80 mana is spent and it comes back at half health.
- Otherwise, a totem bound to it in your inventory (such as Alshanex's Familiars' Tiny Totem) is used up and it comes back at half health.
- Otherwise, it dies and is removed from your familiars.
Familiar Bed
Familiar beds are blocks familiars use to sleep and recover health. Familiars that are missing health search for a free bed nearby and sleep in it until they're healed. Each bed holds one familiar. Beds come in all 16 dye colors: right-click a placed bed with a dye to recolor it.
Familiar Storage
The familiar storage (familiar house) stores up to 10 familiars. Familiars inside it are invulnerable, but they also won't attack other mobs, with some exceptions.
It has 2 modes:
- Store mode: move familiars freely between your familiars and the storage.
- Wander mode: stored familiars wander around the house. A slider sets how far they can go, from 3 to 25 blocks (25 by default); those that stray too far are brought back. You can also turn their abilities on or off while they wander.
Wandering familiars go back inside on their own when they drop below 30% health, and sometimes at night or when it rains.
A familiar storage can only be broken by its owner, only in store mode, and only when it's empty.
Important: only 1 familiar storage block can be used in a 16 block radius.
Shrinking Station
The shrinking station (the "Shrinkinator") shrinks items to familiar size:
- Food: any food item becomes familiar food, which can be given to any familiar to heal it.
- Cosmetics: hats and weapons become cosmetics that familiars can wear (see Cosmetics).
- Dyes: any dye becomes a shrunk dye, which colors a familiar's eyes (see Familiar colors).
- Other recipes: familiar mods add their own, such as Alshanex's Familiars' armor plates and tiny shield.
It works with hoppers: insert into it, and pull the results out. JEI shows every shrinking recipe in its own category.
Consumables
Consumables raise a familiar's stats permanently. Right-click your tamed familiar with one to use it. Each stat has a limit, and multi-tier consumables stop working once the familiar reaches that tier's limit, so you need higher tiers to keep going.
| Stat | Tier 1 | Tier 2 | Tier 3 |
|---|---|---|---|
| Armor | +2 (up to 10) | +3 (up to 16) | +4 (up to 20) |
| Max health | +10% (up to 50%) | +25% (up to 100%) | +50% (up to 150%) |
| Spell power | +3% (up to 15%) | +5% (up to 30%) | +15% (up to 45%) |
| Spell resist | +3% (up to 15%) | +5% (up to 30%) | +15% (up to 45%) |
| Enraged | +1 stack (up to 10): +0.5 attack damage per stack | ||
| Blocking | Unlocks blocking attacks (once) |
Health consumables also heal the familiar to full. A consumable's tooltip shows its stat, bonus, limit and tier. Which items are consumables is decided by each familiar mod.
Familiar trinket slot
Familiars Lib adds a familiar trinket curio slot. Familiar mods give each familiar type its own trinket: while you wear a familiar's trinket, that familiar casts its spells at a much higher quality (40% to 60% instead of 10% to 30%).
Familiar colors
Some parts of a familiar can have different colors: clothes, hats, fur, leaves and so on. Each familiar starts with its original colors, unless it spawned with others. Depending on the familiar, colors come from:
- The biome it spawned in, such as a druid born in a cherry grove having pink leaves.
- A random dye color when it spawns naturally.
- Dyes: right-click your own tamed familiar with a dye to recolor its main colored part, such as its clothes.
- Shrunk dyes: dyes put through the shrinking station color a familiar's eyes instead.
- Other items, such as logs and leaves on a druid. Familiar mods and modpacks decide which items do what.
- An Identity Vessel, taking the colors from another of your familiars (see below).
Some familiars have a second part colored with shrunk dyes, such as a companion's eyes or a lantern. Sneak while using the shrunk dye to color that part instead. In the same way, some familiars have a second part colored with normal dyes (such as wings next to the clothes): sneak while using the dye to color it. The Familiar Compendium shows which familiars have these second parts.
Only the owner of a tamed familiar can recolor it, and using a color the familiar already has does nothing (the item isn't used up). A familiar's colors are saved with it and never change on their own.
Identity Vessel
The Identity Vessel moves a familiar's colors (its "identity") to another familiar of the same type.
-
Take an identity: use an empty vessel on one of your familiars. The vessel stores all its colors, and the familiar goes back to its original look.
-
Give it: use the filled vessel on another of your familiars of the same type (a hunter's identity only goes to another hunter). For each stored color:
- a part in its original look takes that color exactly;
- a part that already has a color gets a mix of both colors.
The vessel is then empty and can be used again.
Mixing gives colors that can't be obtained any other way, and you can keep mixing to create new shades. Mixed colors aren't listed in the Familiar Compendium.
- The vessel only works on familiars you've tamed.
- A familiar with no colors has nothing to take.
- A filled vessel shimmers, and its tooltip shows which familiar it came from and the colors it holds.
Familiar mods provide the recipes for the vessel; see your familiar mod's page (in Alshanex's Familiars, it's made and duplicated with rituals).
Cosmetics
Players can give their familiars a hat and a weapon. Cosmetics are purely visual: no stats and no effect on combat.
- Make a cosmetic: put a hat or weapon item in the shrinking station. It comes out shrunk, keeping its enchantments and name. Its tooltip says whether it's a hat, a weapon or both.
- Put it on: right-click your own familiar with the shrunk item. Whatever it had in that slot goes back to your inventory, still shrunk. If an item can be both a hat and a weapon, sneak to put it on as a hat.
- Take it off: sneak + right-click your familiar with an empty main hand. This takes the weapon off first, then the hat on the next click.
Not every familiar can wear a hat or hold a weapon, and each familiar only holds the kind of weapon that suits it. An item a familiar can't use shows a message above your hotbar. By default, the hats are Iron's Spellbooks' Wizard Hat, Tarnished Helmet, Archevoker Helmet and Electromancer Helmet; modpacks can add more (see Cosmetic tags).
Familiar Compendium
The Familiar Compendium is a book listing every familiar in the game, crafted from a Book and a Rabbit's Foot. The left page lists the familiars, with how many of their colors you've unlocked. The right page shows a 3D preview of the selected familiar that follows your mouse, and up to three tabs, chosen with the bookmarks on the book's edge:
- About: how to obtain the familiar, and its description.
- Abilities: its special abilities, and the icons of the spells it casts (hover an icon for the spell's name).
- Colors: every color each of its parts can have, and the hats and weapons it can wear.
In the Colors tab:
- The "O" swatch of each part is the original look, always available.
- Unlocked colors show their color: click them to try them on the preview, and mix colors from different parts freely. "Original" resets the preview.
- Locked colors show "?". Hover any color to see every way to get it, for example the biomes a familiar spawns with it in, or the item to use on it.
A color is unlocked when you tame a familiar that has it, or recolor one of your familiars into it (with a dye, a shrunk dye, an item or an Identity Vessel). Instructions for shrunk dyes say so, for example "Sneak and use Shrunk Red Dye on it". Each part's colors are unlocked separately. Mixed colors aren't part of the compendium.
After the color layers come the Hat and Weapon rows, for familiars that can wear them:
- The "O" cell is no cosmetic.
- Unlocked items show their icon: click them to try them on the preview.
- Locked items show "?"; hover them to see which item to shrink.
A cosmetic is unlocked as soon as you have its shrunk item in your inventory, and it's unlocked for every familiar that can wear it. The counter next to each familiar includes its cosmetics.
Familiar Camera and photos
The Familiar Camera takes photos of familiars, remembering everything about them at that moment: their colors, hat, weapon and pose. It's crafted from a Spyglass, two Arcane Ingots and Arcane Essence.
- Right-click to zoom in, like a spyglass. While zoomed, a viewfinder shows the familiar in focus and how much paper you have left.
- Left-click to take the photo, zoomed or not. The familiar closest to your crosshair is photographed. It must be visible and within 48 blocks, and while zoomed you have to aim more precisely.
- Each photo uses one paper from your inventory (free in creative), and the camera needs a second to get ready again.
- The camera aims at where the familiar is drawn, not just at its body, so you can catch it in the middle of a jump, a spell or any other animation.
Any familiar can be photographed, tamed or not, yours or someone else's.
Photos are named after their familiar (for example Photo of Fluffy). A photo's tooltip shows:
- The familiar's type (if it has a custom name) and its owner.
- Every color layer, with its color or Original.
- Its hat and weapon, if it had any.
- Its pose (Sitting, or the animation it was playing). Hold Shift for the pose details.
- Who took it and on which day.
Held in your hand, a photo shows the printed picture. In item frames it also shows the picture instead of the item: turning the frame rotates it like a map, and in invisible frames the print is bigger. Familiar mods can use photos too; for example, Alshanex's Familiars' Sculpture Station turns them into sculptures.
For modpack makers
Shrinking recipes
| Type | What it does |
|---|---|
familiarslib:shrinking_recipe | A fixed recipe: input → result |
familiarslib:food_shrinking | Turns any food into familiar food |
familiarslib:cosmetic_shrinking | Turns any item in the hat or weapon tags into a cosmetic |
familiarslib:dye_shrinking | Turns any item in familiarslib:shrinkable_dyes into a shrunk dye |
A fixed recipe:
{
"type": "familiarslib:shrinking_recipe",
"input": {
"item": "alshanex_familiars:armor_plate_tier_1"
},
"result": {
"id": "alshanex_familiars:armor_plate_tier_1",
"count": 1,
"components": {
"familiarslib:familiar_consumable": {
"type": "armor",
"tier": 1
}
}
}
}- input: the item that goes in.
- result: the item that comes out. Components are optional; this example shows how to make an item a familiar consumable.
Recipe files go in any recipe folder of a datapack or mod, for example data/mypack/recipe/shrinking/my_recipe.json.
When several recipes match the same item, fixed recipes win, then cosmetics, then dyes, then food.
Before the shrinking station moved to Familiars Lib, the types were alshanex_familiars:shrinking_recipe and alshanex_familiars:food_shrinking. Files using the old types keep working, but update them to the familiarslib: types.
Consumables
Items become familiar consumables through the familiarslib:familiar_consumable component:
"components": {
"familiarslib:familiar_consumable": {
"type": "armor",
"tier": 1
}
}There are 6 types:
| Type | Effect | Tiers |
|---|---|---|
armor | Increases the familiar's armor | 1 to 3 |
health | Increases the familiar's health | 1 to 3 |
spell_power | Increases the familiar's spell power | 1 to 3 |
spell_resist | Increases the familiar's spell resistance | 1 to 3 |
enraged | Adds 1 enraged stack | 1 |
blocking | Unlocks blocking attacks | 1 |
Colors
Color values
Anywhere a color is written in a data file, you can use:
| Format | Example | Notes |
|---|---|---|
| Hex string | "#5A8F3C" or "5A8F3C" | Any RGB color |
| Dye name | "lime", "light_gray" | Minecraft's dye colors. Use Minecraft's names (light_gray, not light_grey) |
| Integer | 5935932 | Same as hex, as a number |
"default" | "default" | Override files only. Puts the part back to its original look |
How the tint works: a recolored part is a grayscale texture multiplied by the color. White parts of the texture become exactly your color, and darker parts become darker shades of it. This keeps the original shading, but a color can only get darker, never brighter, than what you write. Light or saturated colors usually look best.
Layer slots
Each familiar has 5 color slots, numbered 0 to 4. What each slot is depends on the familiar; each familiar mod documents its own. By default:
| Item | Not sneaking | Sneaking |
|---|---|---|
| Dye | Slot 0, on dyeable familiars | The familiar's second dye slot, if it has one; otherwise slot 0 |
| Shrunk dye | The familiar's eye slot | The familiar's second eye slot, if it has one; otherwise the eye slot |
Override rules (below) replace this for the familiars and items they name.
Override files
Override files define "use this item on this familiar to set these colors" rules. They work on any familiar with color layers, with any item.
Files go in data/<namespace>/familiar_color_overrides/<name>.json. Familiars Lib ships an empty base file at data/familiarslib/familiar_color_overrides/overrides.json, which mods and datapacks add to.
{
"replace": false,
"entries": [
{
"familiar": "alshanex_familiars:druid_pet",
"item": "minecraft:cherry_leaves",
"layers": { "1": "#F2A7C8" },
"consume": true,
"sound": "minecraft:block.grass.place"
}
]
}| Field | Required | Description |
|---|---|---|
familiar | Yes | An entity id, an entity tag ("#namespace:tag"), or a list mixing both |
item | Yes | An item id, an item tag ("#namespace:tag"), or a list mixing both |
layers | Yes | Slot ("0" to "4") to color. One or more slots |
consume | No (default true) | Whether one item is used up |
sound | No (default: dye sound) | Sound event id to play |
shrunk | No (default false) | true: the rule only matches shrunk dyes. false: it ignores them |
How rules apply:
- Only the owner of a tamed familiar can use them.
- If the familiar already has those colors, nothing happens, the item isn't used up, and the click goes on to the familiar's normal interaction.
- When several rules match, the last one loaded wins: later entries in a file, files in alphabetical order of their id, and copies of the same file in pack load order.
- Rules come before dyes: a rule for a dye replaces normal dyeing for the familiars it names. Every other familiar keeps dyeing normally.
- Rules naming familiars or items from mods that aren't installed are skipped quietly.
- A slot the familiar doesn't use does nothing, so one rule can safely reset all slots on every familiar.
- Shrunk dyes only match rules with
"shrunk": true, so existing dye rules keep affecting the main color only. For example, to make shrunk light blue dye give an archmage glowing cyan eyes:{ "familiar": "alshanex_familiars:archmage_pet", "item": "minecraft:light_blue_dye", "shrunk": true, "layers": { "1": "#7FE3FF" } }.
Merging and replace: override files merge like tags. When several packs or mods provide the same file id:
"replace": falseadds its entries to the ones loaded before."replace": truediscards everything loaded before for that file id, then adds its own.
To add to the shared rules from a datapack, create data/familiarslib/familiar_color_overrides/overrides.json with "replace": false. To replace every default rule, use "replace": true. Files with different ids never affect each other.
Examples:
{ "familiar": "#alshanex_familiars:familiars", "item": "irons_spellbooks:shriving_stone",
"layers": { "0": "default", "1": "default", "2": "default" }, "consume": false, "sound": "minecraft:block.grindstone.use" }{ "familiar": "alshanex_familiars:archmage_pet", "item": "minecraft:black_dye", "layers": { "0": "#2B1838" } }Since the last match wins, put broad rules (like #minecraft:leaves) before specific ones (like minecraft:cherry_leaves).
Retexturing color layers
Color layers are textures, so a resource pack can change their shape or shading without any code. Each colored part has two textures in the familiar mod's assets/<namespace>/textures/ folder (for Alshanex's Familiars, textures/entity/layers/):
<name>.png: the part in its original colors, drawn when the slot has no color.<name>_bw.png: the same pixels in grayscale, tinted with the slot's color.- Optionally
<name>_glowmask.pngand<name>_bw_glowmask.png, for parts that glow (such as eyes).
Keep the same size and UV layout as the familiar's base texture, and follow the rules in Layer textures. If you change which pixels a layer covers, change the base texture too, or the old pixels show under the layer. The exact file names are listed on each familiar mod's page.
Biome color files
Familiar mods can make familiars take their colors from the biome they spawn in. Each familiar mod decides its folders and color fields (see the mod's own wiki), but every biome color file has the same format:
{
"entries": [
{ "biome": "#c:is_taiga", "hat": "#CC7C66", "dog": "#5A2E1A" },
{ "biome": "minecraft:cherry_grove", "hat": "#B27291", "dog": "#4A2433" }
]
}biome: a biome id, or a biome tag starting with#.- Color fields: each one is optional; a missing field keeps that part's original look.
How a biome is matched:
- An entry with the exact biome id wins over any tag entry.
- Otherwise, the last tag entry containing the biome wins, so order tag entries from broad to specific.
- A biome with no matching entry keeps the original look.
Every file in a folder is loaded and combined, from any namespace. A datapack file with the same path as a built-in one replaces it.
Prefer common #c: tags (#c:is_forest, #c:is_snowy...) so modded biomes get colors automatically. /reload reloads these files, but only affects familiars that spawn afterwards.
Shrunk dyes
The familiarslib:shrinkable_dyes item tag lists what the shrinking station turns into shrunk dyes. It contains #c:dyes by default, so modded dyes work too. Shrunk dyes carry the familiarslib:shrunk_dye component.
Dyes color the eyes automatically. Other items added to the tag (for example glow ink sacs) can be shrunk too, but only do something through override rules with "shrunk": true.
Cosmetic tags
| Tag | Meaning |
|---|---|
familiarslib:familiar_hats | Items that can be shrunk into a hat, worn by every familiar that can wear hats |
familiarslib:familiar_weapons | Items that can be shrunk into a weapon |
<namespace>:familiar_weapons/<familiar> | The weapons one familiar accepts, e.g. alshanex_familiars:familiar_weapons/hunter_pet |
familiarslib:familiar_hats contains Iron's Spellbooks' wizard_hat, tarnished_helmet, archevoker_helmet and electromancer_helmet by default. Other items can be added with "replace": false: helmets, mob and player heads, and blocks like carved pumpkins are all drawn correctly on familiars (see Hats).
familiarslib:familiar_weapons is empty in the lib: each familiar mod adds its familiars' weapon tags to it. If you add items to a familiar's weapon tag, make sure that tag is in familiarslib:familiar_weapons, or the items can't be shrunk.
Sit items
The familiarslib:familiar_sit_items item tag lists the items that make a familiar sit or stand up when its owner right-clicks it. It contains minecraft:stick by default.
To add items, ship data/familiarslib/tags/item/familiar_sit_items.json with "replace": false. Values can be item ids or tags:
{
"replace": false,
"values": [
"minecraft:blaze_rod",
"#c:rods"
]
}To replace the stick entirely, use "replace": true and list only your items.
Avoid items that already do something on familiars, such as foods, consumables, dyes, totems or items in color override rules: those interactions run first, so the item won't toggle sitting (see Interaction order). A familiar mod can also give one familiar its own sit items, which ignore this tag (see Sitting and sleeping).
Familiar Compendium
The compendium is generated automatically from the loaded data: biome color files, override rules and dyes. Modpack changes show up after /reload, including modded biomes in common tags.
Config
The server config has:
| Option | Default | Range | Description |
|---|---|---|---|
maxFamiliars | 10 | 1 to 50 | How many familiars a player can carry. Familiars stored in houses don't count |
The number of familiars summoned at the same time is always capped at 10.
Taming items
The familiarslib:familiar_taming item tag lists the items that tame familiars. Ship data/familiarslib/tags/item/familiar_taming.json with "replace": false to add items, or "replace": true to replace them.
Other tags
| Tag | Type | Meaning |
|---|---|---|
familiarslib:familiar_taming | Item | Items that tame familiars |
familiarslib:familiar_sit_items | Item | Items that make familiars sit (see Sit items) |
familiarslib:crystal_berry | Item | Foods that make familiars drop memory fragments |
familiarslib:fragments | Item | Memory fragments |
familiarslib:illusionist_steals | Item | Items illusionists pick up when nobody's watching |
familiarslib:hunter_cannot_mark | Entity | Entities the hunter's loot sense never marks |
familiarslib:hunter_cannot_attack_in_home | Entity | Entities hunters won't attack while living in a familiar house |
Attributes
| Attribute | Default | Effect |
|---|---|---|
familiarslib:familiar_damage | 100% | Multiplies the damage your familiars deal |
familiarslib:familiar_resist | 100% | Reduces the damage your familiars take (soft-capped, like Iron's Spellbooks resistances) |
Both are player attributes, so gear can raise them for its wearer's familiars.
For mod developers
Getting started
Add the Curse Maven snippet of the Familiars Lib version you want to your dependencies in build.gradle:
implementation "curse.maven:familiarslib-1316458:7415920"Creating your own familiar
You need a few things before coding:
- The familiar's model: a
.geo.jsonfile, exported from your GeckoLib Blockbench project. - The familiar's texture: saved from your Blockbench project.
- Animations, saved as JSON:
- idle: loop animation when idle
- interact: plays when right-clicking the familiar
- long_cast: plays when casting spells with a long cast time
- skill: plays when casting instant or short spells
- walk: loop animation when walking
- spawn: plays when the familiar spawns
- sleep: plays when sleeping in a familiar bed, and when stunned if the familiar has no sit animation
- continuous: loop animation for continuous spells
- sit (optional): loop animation when sitting or stunned. Only used if the familiar enables it (see Sitting and sleeping)
Put them here:
- Model:
resources/assets/<your_mod_id>/geo/ - Texture:
resources/assets/<your_mod_id>/textures/entity/ - Animations: all of them (except the optional ones you don't use), with the exact names above, in one animation file in
resources/assets/<your_mod_id>/animations/
Then create the entity class. Pick the base class that matches how your familiar moves:
| Base class | For |
|---|---|
AbstractTerrestrianSpellCastingPet | Walking familiars. No fall damage, and a random stroll goal that respects sitting and houses |
AbstractFlyingSpellCastingPet | Flying casters, with flying navigation and hovering |
AbstractFlyingMeleeSpellCastingPet | Flying melee fighters with Vex-style movement. Its attack damage grows with its spell power. Pair it with FlyingSkirmisherAttackGoal |
All of them extend AbstractSpellCastingPet, which holds everything else on this page (taming, colors, cosmetics, compendium...). A flying caster example:
public class ExampleFamiliarEntity extends AbstractFlyingSpellCastingPet {
public static final ResourceLocation textureResource = ResourceLocation.fromNamespaceAndPath(YourMainClass.MODID, "textures/entity/familiar_texture.png");
public ExampleFamiliarEntity(EntityType<? extends AbstractFlyingSpellCastingPet> pEntityType, Level pLevel) {
super(pEntityType, pLevel);
}
@Override
protected void registerGoals() {
super.registerGoals();
initializeAttackGoal(2);
//Any other goal specific to this familiar
}
@Override
protected WizardAttackGoal createAttackGoal(float min, float max) {
//The spells the familiar uses. Spell tags are recommended for easier management and flexibility.
List<AbstractSpell> attackSpells = HelperMethods.getSpellsFromTag(YourModTags.EXAMPLE_ATTACK_SPELLS);
List<AbstractSpell> defenseSpells = HelperMethods.getSpellsFromTag(YourModTags.EXAMPLE_DEFENSE_SPELLS);
List<AbstractSpell> movementSpells = HelperMethods.getSpellsFromTag(YourModTags.EXAMPLE_MOVEMENT_SPELLS);
List<AbstractSpell> supportSpells = HelperMethods.getSpellsFromTag(YourModTags.EXAMPLE_SUPPORT_SPELLS);
//Only return one of these goals
//If it's a flying familiar
return new FamiliarGoals.FlyingWizardAttackGoal(this, 1f, 30, 40)
.setPreferredHeight(4.0f)
.setCombatRanges(5.0f, 7.0f, 10.0f)
.setThreatAwarenessRadius(10.0f)
.setSpells(attackSpells, defenseSpells, movementSpells, supportSpells)
.setSingleUseSpell(SpellRegistry.RAY_OF_FROST_SPELL.get(), 160, 300, 3, 5) //Optional signature spell
.setIsFlying()
.setAllowFleeing(true)
.setSpellQuality(min, max);
//If it's a terrestrian familiar
return new WizardAttackGoal(this, 1.25f, 40, 50)
.setSpells(attackSpells, defenseSpells, movementSpells, supportSpells)
.setSingleUseSpell(SpellRegistry.ROOT_SPELL.get(), 340, 400, 8, 10) //Optional signature spell
.setAllowFleeing(true)
.setSpellQuality(min, max);
}
//Be careful: some attributes differ between terrestrian, melee and flying familiars
public static AttributeSupplier.Builder prepareAttributes() {
return LivingEntity.createLivingAttributes()
.add(Attributes.ATTACK_DAMAGE, 3.0)
.add(Attributes.ATTACK_KNOCKBACK, 0.0)
.add(Attributes.MAX_HEALTH, 30.0)
.add(Attributes.FOLLOW_RANGE, 24.0)
.add(Attributes.FLYING_SPEED, .1F)
.add(Attributes.MOVEMENT_SPEED, .2);
}
}The model class:
public class ExampleFamiliarModel extends DefaultedEntityGeoModel<ExampleFamiliarEntity> {
public static final ResourceLocation MODEL = ResourceLocation.fromNamespaceAndPath(YourMainClass.MODID, "geo/familiar_model.geo.json");
public static final ResourceLocation ANIMATIONS = ResourceLocation.fromNamespaceAndPath(YourMainClass.MODID, "animations/familiar_animations.animation.json");
public ExampleFamiliarModel() {
super(ResourceLocation.fromNamespaceAndPath(YourMainClass.MODID, "example_familiar"));
}
protected TransformStack transformStack = new TransformStack();
@Override
public ResourceLocation getModelResource(ExampleFamiliarEntity object) {
return MODEL;
}
@Override
public ResourceLocation getAnimationResource(ExampleFamiliarEntity animatable) {
return ANIMATIONS;
}
@Override
public void setCustomAnimations(ExampleFamiliarEntity entity, long instanceId, AnimationState<ExampleFamiliarEntity> animationState) {
super.setCustomAnimations(entity, instanceId, animationState);
if (Minecraft.getInstance().isPaused() || !entity.shouldBeExtraAnimated())
return;
transformStack.popStack();
}
}The renderer class. It uses culled render types: models with zero-thickness planes (capes, crowns, wings...) flicker with the default no-cull types, because both faces of each plane are drawn in the same place.
public class ExampleFamiliarRenderer extends HumanoidRenderer<ExampleFamiliarEntity> {
public ExampleFamiliarRenderer(EntityRendererProvider.Context renderManager, ExampleFamiliarModel model) {
super(renderManager, model);
//Color layers, hat and weapon layers go here, before the glow layer
addRenderLayer(new AutoGlowingGeoLayer<>(this));
}
@Override
public ResourceLocation getTextureLocation(ExampleFamiliarEntity entity) {
return ExampleFamiliarEntity.textureResource;
}
@Override
public void render(ExampleFamiliarEntity entity, float entityYaw, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight) {
super.render(entity, entityYaw, partialTick, poseStack, bufferSource, packedLight);
SpellRenderingHelper.renderSpellHelper(ClientMagicData.getSyncedSpellData(animatable), animatable, poseStack, bufferSource, partialTick);
}
@Override
public RenderType getRenderType(ExampleFamiliarEntity animatable, ResourceLocation texture, @Nullable MultiBufferSource bufferSource, float partialTick) {
return animatable.isInvisible() ? RenderType.itemEntityTranslucentCull(texture) : RenderType.entityCutout(texture);
}
}Then register the entity like any other modded entity, and your familiar is complete. The Familiar Camera works with it automatically.
Attack goals
createAttackGoal(min, max) returns an Iron's Spellbooks WizardAttackGoal (or a subclass). The lib calls it again with higher spell quality whenever the owner puts on or takes off the familiar's trinket, so always pass min and max to setSpellQuality. FamiliarGoals.FamiliarWizardAttackGoal no longer exists: use WizardAttackGoal directly for walking familiars.
Signature spells: Iron's setSingleUseSpell(spell, minDelay, maxDelay, minLevel, maxLevel) makes the familiar cast a spell outside its tags every so often (delays in ticks). It can be called more than once. Add these spells to getCompendiumSpells() too, so the compendium shows them.
FamiliarGoals provides these goals for familiars that need special movement:
| Goal | For | Extra builder methods |
|---|---|---|
FlyingWizardAttackGoal | Flying casters: orbit the target from above, keep their distance and retreat from nearby threats | setPreferredHeight(height), setCombatRanges(min, optimal, max), setThreatAwarenessRadius(radius) |
FlyingSkirmisherAttackGoal | Flying melee fighters: dash in for melee combos, then pull back | setPreferredDistance, setEngageThreshold, setDisengageDistance, setEngageCooldown, setMaxEngageTicks, setMaxDisengageTicks, setEngageSpeedMultiplier, setDisengageSpeedMultiplier, setMaxCombosPerEngage, setGapCloserSpell(spell, level), setGapCloserDistance, setSpellCastChance, setThreatAwarenessRadius, setCrowdedThreshold |
MeleeSpellCastWarlockAttackGoal | Walking melee fighters that cast a gap-closing spell on far targets | setGapCloserSpell(spell, level), setGapCloserDistance(distance) |
FlyingWizardAttackGoal defaults to a height of 4, ranges of 5 / 10 / 20 blocks and a threat radius of 14. The two melee goals need an entity that implements Iron's IAnimatedAttacker.
Sitting and sleeping
A familiar is in one of these poses:
| Pose | When | Animation | Render offset |
|---|---|---|---|
| Sleeping | Sitting on a familiar bed, or stunned without a sit animation | sleep | getSleepingOffsetY() |
| Sitting | Sitting off a bed, or stunned with a sit animation | sit, or idle without a sit animation | getSittingOffsetY() |
| Normal | Anything else | The usual animations | None |
Being asleep on a bed takes priority over a stun.
Sit animation
The sit animation is off by default, so familiars without one aren't affected. Add a looping sit animation to the familiar's animation file and enable it:
@Override
protected boolean hasSitAnimation() {
return true;
}While the sit animation plays, isAnimating() returns true, so the idle/walk controller stops and the head and legs follow the animation instead of being animated procedurally. To keep the head looking around while sitting, override shouldAlwaysAnimateHead():
@Override
public boolean shouldAlwaysAnimateHead() {
return isInSittingPose();
}Vertical offsets
Move the model up or down while sitting or sleeping, for example to sink it into a bed cushion:
@Override
public float getSittingOffsetY() {
return -0.2F; // blocks, negative = down
}
@Override
public float getSleepingOffsetY() {
return -0.1F;
}- The offsets are in blocks, applied after the renderer's own scaling, so a scaled-down model moves less: tune them in-game.
- Only the model and its layers (colors, hats, weapons) move. The hitbox and shadow stay where the familiar is.
- The offset is applied automatically for every familiar, through GeckoLib's pre-render event. Don't also translate the pose stack for it in your renderer, or it's applied twice.
- The offset snaps on and off, like the sleep animation.
Pose helpers
boolean isInSittingPose(); // sitting off a bed, or stunned with a sit animation
boolean isInSleepingPose(); // on a bed, or stunned without a sit animation
float getPoseOffsetY(); // the offset being applied right nowThe poses are updated once per tick, on both sides.
Custom sit items
By default, a familiar sits or stands up when its owner right-clicks it with an item in familiarslib:familiar_sit_items (see Sit items). Override isSitItem to give a familiar its own:
@Override
protected boolean isSitItem(ItemStack stack) {
return stack.is(MyItems.BONE_FLUTE.get()) || super.isSitItem(stack);
}Leave out super.isSitItem(stack) for the familiar to ignore the shared tag. The tag key is ModTags.FAMILIAR_SIT_ITEMS; to add your items with datagen:
tag(ModTags.FAMILIAR_SIT_ITEMS).add(MyItems.BONE_FLUTE.get());Trinkets, schools and items
Trinket: every familiar declares its trinket. While its owner wears it in any curio slot, the familiar's spell quality switches from getOriginalQualityValues() (0.1 to 0.3) to getTrinketQualityValues() (0.4 to 0.6):
@Override
protected Item getValidTrinket() {
return MyItems.MY_FAMILIAR_TRINKET.get();
}School: getPreferredPowerAttribute() returns the spell power attribute that matches the familiar's school, or null. Familiar mods use it for bonuses that depend on which familiars are out, such as Alshanex's Familiars' Familiologist set.
Base items you can extend:
| Class | What it is |
|---|---|
AbstractFamiliarTotem | A totem bound to one familiar, used up to revive it (stores the familiar in the familiarslib:soul_link component) |
AbstractMultiSelectionCurio | A curio that turns on multi-familiar summoning (see Summoning several familiars) |
AbstractFamiliarSpellbookItem | A spellbook that shares its wearer's magic attributes with their summoned familiars: half of the wearer's bonus above the base value, split evenly between them, for spell power, spell resist, and every school's power and resist (addon schools included). Default stats: +200 max mana, +12% cast time reduction, +8% spell power; override getSpellbookAttributes() to change them |
AbstractRuneItem | A shard that creates a familiar when used |
Reusable goals
FamiliarGoals also has ready-made goals your familiars can add in registerGoals(). They already respect sitting, stuns, houses (canExecuteGoalsInHouse()) and disabled movement. Among them:
| Goal | What it does |
|---|---|
FindAndUsePetBedGoal(pet, radius) | Hurt familiars look for a free familiar bed and sleep in it until healed |
MovementAwareFollowOwnerGoal, TeleportToOwnerGoal | Follow the owner, and teleport to them when too far |
TargetAttackerOfPlayersGoal(pet, owner) | Targets mobs that are targeting the owner |
StealItemsWhenNotWatchedGoal(pet, radius) | Picks up items in familiarslib:illusionist_steals when no player is looking |
ThunderstrikeGoal(pet) | Walks to nearby creepers and charges them |
WitherifyGoal(pet) | Turns nearby skeletons into wither skeletons |
WanderAroundHouseGoal, StayNearHouseGoal, CasualLookAtPlayerGoal, CasualRandomLookGoal | Behavior while wandering around a familiar house |
The base familiar classes already add the goals every familiar needs (following, beds, houses...), so check registerGoals() in AbstractSpellCastingPet before adding one twice. The ability goals (stealing, charging creepers, witherifying) are opt-in.
Creating your own familiar house
Extend AbstractFamiliarStorageBlock for the block:
public class FamiliarHouseExampleBlock extends AbstractFamiliarStorageBlock {
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
public static final MapCodec<FamiliarHouseExampleBlock> CODEC = simpleCodec(FamiliarHouseExampleBlock::new);
public FamiliarHouseExampleBlock(Properties properties) {
super(properties);
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH));
}
@Override
public MapCodec<FamiliarHouseExampleBlock> codec() {
return CODEC;
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new FamiliarHouseExampleBlockEntity(pos, state);
}
//How many familiar houses are allowed per chunk
@Override
protected int getAmountPerChunk() {
return 2;
}
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
return level.isClientSide ? null : createTickerHelper(blockEntityType, BlockEntityRegistry.FAMILIAR_HOUSE_EXAMPLE.get(), AbstractFamiliarStorageBlockEntity::serverTick);
}
//Rest of the implementation...
}The block entity is a normal modded block entity extending AbstractFamiliarStorageBlockEntity.
Creating your own familiar bed
Extend AbstractFamiliarBedBlock for the block and AbstractFamiliarBedBlockEntity for the block entity, and implement them like any other modded block and block entity.
Color layers
On the entity
AbstractSpellCastingPet implements LayerColorHolder:
int getLayerColor(int slot); // 0xRRGGBB, or NO_LAYER_COLOR (-1) for the original look
void setLayerColor(int slot, int rgb); // NO_LAYER_COLOR resets the slot
boolean canBeDyed(); // override: true for dyeable familiars
int getEyeDyeLayerSlot(); // override: the slot shrunk dyes color (the eyes), or -1
int getSneakingEyeDyeLayerSlot(); // override: the slot shrunk dyes color while sneaking, or -1
int getSneakingDyeLayerSlot(); // override: the slot normal dyes color while sneaking, or -1
void initializeLayerColors(LevelReader level, @Nullable MobSpawnType reason); // spawn hook| Constant | Value | Meaning |
|---|---|---|
LayerColorHolder.NO_LAYER_COLOR | -1 | No color: the original layer |
AbstractSpellCastingPet.LAYER_COLOR_SLOTS | 5 | Slots 0 to 4 |
AbstractSpellCastingPet.DYE_LAYER_SLOT | 0 | The slot dyes change |
Colors are synced to clients and saved as "LayerColors" in the familiar's NBT, which the roster, selection screen and familiar houses also store. Give your slots readable names on your entity:
public static final int HAT_LAYER = 0;
public static final int DOG_LAYER = 1;
public static final int CROSSBOW_LAYER = 2;The spawn hook
initializeLayerColors runs once per familiar, on the server:
| How the familiar appears | Called? | reason |
|---|---|---|
Natural spawn, spawner, spawn egg, /summon | Yes, from finalizeSpawn | The MobSpawnType |
Created by code and added with addFreshEntity (shards) | Yes, from onAddedToLevel | null |
| Loaded from a save, resummoned, released from a house | No | n/a |
/summon with a LayerColors tag | No (the given colors are kept) | n/a |
Layer textures
Each colored part needs two textures with the same size and UV layout as the base texture:
| File | Content | Used when |
|---|---|---|
my_layer.png | Only that part, in its original colors; everything else transparent | The slot has no color |
my_layer_bw.png | The same pixels in grayscale | The slot has a color |
- Extract the layers from the base texture so the pixels match exactly, then cut those areas out of the base texture, so the layer is the only surface there.
- Make the grayscale version bright: highlights close to white, since the tint can only darken.
- Don't let two layers of one familiar share pixels: the later layer would draw over the earlier one.
- Fully opaque pixels only: layers use cutout rendering.
- Glowmasks: the base
_glowmaskis drawn after the color layers at full brightness, so remove the layer areas from it. If part of a layer should glow, give the layer its ownmy_layer_glowmask.pngandmy_layer_bw_glowmask.png, and use.glowing().
Rendering
Add one FamiliarColorLayer per slot, before AutoGlowingGeoLayer:
addRenderLayer(new FamiliarColorLayer<>(this, HunterPetEntity.HAT_LAYER,
MyMod.id("textures/entity/layers/hunter_pet_hat_layer.png"),
MyMod.id("textures/entity/layers/hunter_pet_hat_layer_bw.png")));FamiliarColorLayer(renderer, slot, defaultTexture, tintTexture); defaultTexture can be null to draw nothing when the slot has no color. Add .glowing() for an emissive pass using the layers' glowmasks. The layer follows the body's visibility, flashes red when hurt, and uses culled render types to match the renderer above.
Anything else that draws the base texture (decoys, shadows...) needs the layer too, or the cut-out areas show as holes. For entities that aren't familiars, implement LayerColorHolder and return NO_LAYER_COLOR, or copy a familiar's colors into your own synced data.
Dyeable familiars
Override canBeDyed() to return true, and add a FamiliarColorLayer on AbstractSpellCastingPet.DYE_LAYER_SLOT. The lib handles the interaction.
For a random dye color on natural spawns:
@Override
protected void initializeLayerColors(LevelReader level, @Nullable MobSpawnType reason) {
FamiliarColors.rollNaturalDye(this, reason);
}Shard-made familiars (reason == null) keep the original look. FamiliarColors.NATURAL_DEFAULT_LOOK_CHANCE (25%) is the chance of keeping it on a natural spawn.
Eyes (shrunk dyes)
Shrunk dyes color the slot returned by getEyeDyeLayerSlot(). For a familiar with a second part colored the same way (a companion's eyes, a lantern...), getSneakingEyeDyeLayerSlot() returns the slot colored while sneaking; familiars without one color their eyes whether sneaking or not.
public static final int EYES_LAYER = 3;
public static final int DOG_EYES_LAYER = 4;
@Override
public int getEyeDyeLayerSlot() {
return EYES_LAYER;
}
@Override
public int getSneakingEyeDyeLayerSlot() {
return DOG_EYES_LAYER;
}This doesn't depend on canBeDyed(): a familiar can have dyeable eyes without dyeable clothes. Keep slot 0 for the main color, and add a FamiliarColorLayer for each eye slot. If the eyes glow, use .glowing() with the eye layers' glowmasks so dyed eyes glow in their color.
FamiliarDyes has the shrunk dye helpers: isShrunkDye, canBeShrunk and shrink.
Second dye part
For a familiar with two parts colored by normal dyes (clothes and wings, for example), return the second part's slot from getSneakingDyeLayerSlot(). Dyes color it while the owner sneaks, and slot 0 otherwise. Familiars without one color slot 0 whether sneaking or not.
public static final int WINGS_LAYER = 2;
@Override
public boolean canBeDyed() {
return true;
}
@Override
public int getSneakingDyeLayerSlot() {
return WINGS_LAYER;
}Like the eyes, this doesn't depend on canBeDyed(), and the slot needs its own FamiliarColorLayer. Override rules for that dye still win over it.
Biome colors
public static final BiomeLayerColorData DRUID = new BiomeLayerColorData("familiar_colors/druid",
new BiomeLayerColorData.Layer("wood", DruidPetEntity.WOOD_LAYER),
new BiomeLayerColorData.Layer("leaf", DruidPetEntity.LEAF_LAYER));Register it with event.addListener(...) in AddReloadListenerEvent, apply it in the spawn hook with DRUID.applyTo(this, level), and ship a default file in data/<modid>/familiar_colors/druid/. Two loaders can read the same folder: a loader reading the druid's folder with new Layer("wood", HunterPetEntity.CROSSBOW_LAYER) gives the hunter's crossbow the druid's wood colors.
Override rules from your mod
No code needed: add your rules to src/main/resources/data/familiarslib/familiar_color_overrides/overrides.json with "replace": false, or use your own file. To check rules from code, use FamiliarColorOverrides.INSTANCE.find(familiar, stack). Rules only exist on the server.
Changing colors from code
After changing colors or cosmetics of a tamed familiar from code, keep the roster in sync:
familiar.setLayerColor(MyFamiliar.HAT_LAYER, 0xA83232);
FamiliarManager.updateFamiliarData(familiar);
FamiliarSync.snapshot(serverPlayer, familiar.getUUID());Identity Vessel
A filled vessel stores a familiarslib:familiar_identity component (FamiliarIdentity): the familiar's entity id and its 3 layer colors (-1 for a layer in its original look). FamiliarIdentityHandler handles taking and pouring, owner-only.
Mixing works like vanilla dyes on leather armor: the colors are averaged, then the average brightness is restored, so mixes don't get muddy. Mixed colors aren't in the compendium catalog, and FamiliarCompendium.discover only unlocks colors the catalog lists, so they're never tracked.
Cosmetics
On the entity
ItemStack getCosmetic(FamiliarCosmeticSlot slot); // HAT or WEAPON
void setCosmetic(FamiliarCosmeticSlot slot, ItemStack stack);
boolean canWearCosmeticHat(); // override: true if it has a hat slot
boolean canWearCosmeticHat(ItemStack stack); // default: in familiarslib:familiar_hats
boolean canHoldCosmeticWeapon(); // override: true if it has a weapon slot
boolean canHoldCosmeticWeapon(ItemStack stack); // default: in getCosmeticWeaponTag()
TagKey<Item> getCosmeticWeaponTag(); // default: <entity namespace>:familiar_weapons/<entity path>
void dropCosmetics(); // drops both items and empties the slotsUsually you only override the no-argument methods. Ship the familiar's weapon tag, and add it to familiarslib:familiar_weapons in data/familiarslib/tags/item/familiar_weapons.json with "replace": false. Call dropCosmetics() wherever a familiar is gone for good, or its items are lost.
Cosmetics are saved as "CosmeticHat" and "CosmeticWeapon". Shrunk items carry the familiarslib:familiar_cosmetic component; FamiliarCosmetics has helpers like isShrunkCosmetic, shrink, slotForEquip and weaponTagFor.
Hats: FamiliarHatLayer
Hats are drawn on an armor bone, the way GeckoLib draws helmets, so every hat lines up the same:
{ "name": "armorBipedHead", "parent": "body", "pivot": [0, 0.5, 0],
"cubes": [{ "origin": [-5, -0.5, -5], "size": [10, 10, 10], "uv": {} }] }- The pivot is where the head meets the neck; hats sit on it.
- The cube size is the hat size. A vanilla helmet is 10 wide, so hats are scaled by
cube size / 10. Keep the three dimensions equal. - At scale
s, a hat spans frompivot - stopivot + 9·svertically: when shrinking hats, move the pivot up to keep the top in place.
addRenderLayer(new FamiliarHatLayer<>(this)); // the "armorBipedHead" bone
addRenderLayer(new FamiliarHatLayer<>(this, "my_hat_bone")); // or your own boneGeckoLib armor (Iron's Spellbooks hats) and vanilla helmets are drawn as worn helmets, skulls like on a player, and other items the way vanilla draws them on a player's head. GeckoLib helmets may not show when a familiar is drawn in a screen.
Weapons: FamiliarCosmeticLayer
addRenderLayer(new FamiliarCosmeticLayer<>(this)
.weapon(FamiliarCosmeticLayer.Placement.on("bm_weapon")
.rotation(-90, 180, 0)
.scale(0.6F)
.context(ItemDisplayContext.THIRD_PERSON_LEFT_HAND)
.hideBone()));| Method | Meaning |
|---|---|
on(bone) | The bone to attach to |
offset(x, y, z) | Moves the item from the bone's pivot, in model pixels |
rotation(x, y, z) | Rotates the item in degrees, X then Y then Z |
scale(s) | Scales the item |
context(ctx) | The item model view to use (default THIRD_PERSON_RIGHT_HAND) |
hideBone() | Hides the bone and its children while a cosmetic weapon is equipped |
The placement is relative to the bone as it looks in Blockbench, including its animated rotation, so the item follows every animation. The offset needed grows with the scale, so fix the scale first.
The context picks the item model's view: Iron's Spellbooks spellbooks show their open 3D lectern book with ItemDisplayContext.HEAD.
Familiar Compendium
Every AbstractSpellCastingPet in the game is picked up automatically. The book lists familiars with at least one tab, and only shows the tabs a familiar has content for.
About and Abilities tabs
Add these to your familiar class:
@Override
public List<Component> getCompendiumObtaining() { // About tab, next to the preview
return List.of(Component.translatable("compendium.mymod.my_familiar.obtaining"));
}
@Override
public List<Component> getCompendiumDescription() { // About tab, below the preview
return List.of(Component.translatable("compendium.mymod.my_familiar.description"));
}
@Override
public List<CompendiumAbility> getCompendiumAbilities() {
return List.of(
CompendiumAbility.of(
Component.translatable("compendium.mymod.my_familiar.ability.example"),
Component.translatable("compendium.mymod.my_familiar.ability.example.desc")),
CompendiumAbility.of(
Component.translatable("compendium.mymod.my_familiar.ability.other"),
Component.translatable("compendium.mymod.my_familiar.ability.other.desc"),
MyMod.id("textures/gui/abilities/other.png"))); // optional 16x16 icon
}
@Override
public List<AbstractSpell> getCompendiumSpells() {
List<AbstractSpell> spells = new ArrayList<>();
spells.addAll(HelperMethods.getSpellsFromTag(MyTags.MY_FAMILIAR_ATTACK_SPELLS));
spells.addAll(HelperMethods.getSpellsFromTag(MyTags.MY_FAMILIAR_SUPPORT_SPELLS));
return spells;
}- Each
Componentin a list is one paragraph; text wraps to the page. - Abilities are your own entries (not spells). The first one always starts next to the preview; abilities without icons are placed first since they fit there best.
getCompendiumSpellsis called on the server, on a temporary familiar never added to the world, because spell tags only exist there. The book shows the spells as icons, with their names on hover. Duplicates are listed once.- The other methods are called on the client, on the book's preview familiar: only return text and icons.
Colors tab
Register a profile for familiars with color layers, during common setup:
FamiliarCompendium.register(EntityRegistry.HUNTER_PET, CompendiumProfile.builder()
.layer(HunterPetEntity.HAT_LAYER, "compendium.mymod.layer.hat")
.layer(HunterPetEntity.DOG_LAYER, "compendium.mymod.layer.dog")
.layer(HunterPetEntity.CROSSBOW_LAYER, "compendium.mymod.layer.crossbow")
.spawnsFromBiomes(MyColorData.HUNTER, MyColorData.HUNTER_CROSSBOW)
.build());| Builder method | Meaning |
|---|---|
layer(slot, nameKey) | A layer to list, in display order |
dyeable() | Dyes recolor the dye slot (match canBeDyed()) |
spawnsWithRandomDye() | Natural spawns get random dye colors (match rollNaturalDye) |
spawnsFromBiomes(data...) | Spawn colors come from these biome loaders, in this order |
eyeDyeable(slot) | Shrunk dyes color this slot (match getEyeDyeLayerSlot()) |
sneakingEyeDyeable(slot) | Shrunk dyes color this slot while sneaking (match getSneakingEyeDyeLayerSlot()) |
sneakingDyeable(slot) | Normal dyes color this slot while sneaking (match getSneakingDyeLayerSlot()) |
Registering is optional for dyes and eyes: when the catalog is built, each familiar's own canBeDyed(), getEyeDyeLayerSlot(), getSneakingEyeDyeLayerSlot() and getSneakingDyeLayerSlot() are read, and any of those layers the profile doesn't already list are added with generic names (compendium.familiarslib.layer.dye, .eyes, .second_eyes and .second_dye). Register the layers yourself to give them your own names, such as "Dog Eyes" or "Lantern".
Override rules are read automatically. The catalog is rebuilt on the server when the world starts and on /reload, and sent to every player.
Hats and weapons need nothing extra: the catalog lists every item in familiarslib:familiar_hats the familiar accepts with canWearCosmeticHat(stack), and every item in familiarslib:familiar_weapons it accepts with canHoldCosmeticWeapon(stack). Cosmetics are unlocked per item (CompendiumCatalog.cosmeticKey), shared by every familiar; players' inventories are checked every 2 seconds for shrunk cosmetics.
A color is unlocked when its owner tames a familiar with it, or recolors one into it. Unlocks are saved on the player and kept on death.
Preview adjustments
The preview cancels each renderer's getRenderOffset, so most familiars need nothing. For models that still sit oddly in the frame:
public float getCompendiumPreviewOffsetY() { return 0F; } // blocks, positive = up
public float getCompendiumPreviewOffsetX() { return 0F; } // blocks, positive = right
public float getCompendiumPreviewScale() { return 1F; } // 1 = automatic fitThe familiar selection, multi-selection and familiar house screens use the same adjustments through FamiliarPreviewHelper.applyPreviewAdjustments(poseStack, entity). Screens that draw familiars should not disable face culling, or flat planes in the models flicker.
Photos
Photos need no code: every AbstractSpellCastingPet can be photographed. A photo stores a FamiliarPhoto in the familiarslib:familiar_photo component:
| Part | Content |
|---|---|
| Entity type | The familiar's entity id |
Appearance | Its layer colors (-1 for the original look) and its hat and weapon |
FamiliarPose | Head yaw and pitch, whether it was sitting, the animations playing, and every GeckoLib bone's rotation, position and scale |
Info | Its custom name, owner, photographer and day |
The pose is read from the bones as they were last drawn, so photos match what the player saw. When a photo is displayed, a client-only copy of the familiar is built from it and posed bone by bone; bones that no longer exist in the model are skipped. Your mod can read the component to build things from photos, as Alshanex's Familiars' sculptures do.
Interaction order
When a player right-clicks their own familiar, the lib's handlers run before the familiar's mobInteract:
- Identity Vessel: takes or gives an identity; never does anything else.
- Cosmetics: a shrunk cosmetic is put on; sneak + empty main hand takes one off.
- Override rules (server): a matching rule that changes a color applies and stops; one that changes nothing skips the dye step too.
- Dyes: a dye sets the dye slot of dyeable familiars, or the second dye slot while sneaking. A shrunk dye sets the eye slot, or the second eye slot while sneaking.
- Otherwise the familiar's normal interaction runs (feeding, consumables, sit items...).
The Familiar Camera doesn't use right-click on familiars: its photos are taken with left-click and never hurt them.
Color changes and taming unlock compendium colors.
