Compendium, eggs and photos
Filling your familiars' compendium tabs, egg colors, and what a photo stores.
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.
Familiar Eggs
Eggs work for every AbstractSpellCastingPet automatically: lost familiars are recorded, typed eggs exist for each familiar, and hatching goes through your familiar's normal spawn hook (see The spawn hook).
Egg color
Each familiar chooses its egg's color. Override getEggColor():
@Override
public EggColor getEggColor() {
return EggColor.of(0x6FAE3F); // a set color
}
// Or, to preselect a layer in the egg screen:
@Override
public EggColor getEggColor() {
return EggColor.fromLayer(DruidPetEntity.LEAF_LAYER, 0x6FAE3F); // same set color, leaves preselected
}| Method | Meaning |
|---|---|
EggColor.of(rgb) | The familiar's set color. The egg screen opens on Default color |
EggColor.fromLayer(slot, rgb) | Same set color, but the egg screen opens on that layer instead. Players can still pick any layer or the default |
- The default is
EggColor.DEFAULT(0xFDF5E0, a light beige). - Typed eggs always use the set color: a new familiar's layers have their original look.
- Bound eggs use the color chosen in the egg screen. The client only sends the chosen layer slot; the server checks it and works out the color from its own copy of the familiar (
EggColor.layerColor). - The egg texture is greyscale and multiplied by the color, so light, saturated colors look best.
Items and components
| Component | On | Content |
|---|---|---|
familiarslib:familiar_type | Typed eggs | The familiar's entity id (ResourceLocation) |
familiarslib:bound_familiar | Bound eggs | BoundFamiliar: the familiar's id, its owner, its saved data and the egg color |
FamiliarEggItem.typedEgg(entityType) makes a typed egg, for loot or rewards. FamiliarEggColors.defaultColor(type, level) gives a type's set color, and FamiliarEggColors.familiarTypes(level) every familiar type in the game.
Recording lost familiars
FamiliarManager records released and dead familiars on its own, in per-dimension saved data (RecallableFamiliarsData, up to 20 per player). Dead familiars are stored at full health, without their death state. If your mod removes familiars from a roster in its own way and wants them to be recoverable, call FamiliarRecall.recordRelease(player, familiarId, nbt) or FamiliarRecall.recordDeath(familiar, owner) before removing them.
Advancements
Hatching a typed egg fires the familiarslib:shard_use trigger, the same one shards used, so advancements on it keep working.
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.
