CurseForge · Minecraft mod
Liby
Registration and MultiBlock Library
Quick answer
Which Liby release should I use?
Liby 1.20.1-build-2.0 targets 1.20.1 with Fabric. Installation on the client is optional. Installation on the dedicated server is optional. No extra mods listed for this file.
Where it goes
Is Liby required on the client, server, or both?
Installation on the client is optional. Installation on the dedicated server is optional.
The source marks this as usable on both the client and server.
What else does Liby 1.20.1-build-2.0 need?
1.20.1-build-2.0. Change the file and its required mods may change too.
This file does not list any required mods. Do not add a library just because a different file uses it.
This file does not list any required or optional mods.
Before you install it
Add Liby without breaking your instance.
Built for Liby 1.20.1-build-2.0. Pick another file and the loader, install side or required mods may change.
- 01
Stick to this file
Use 1.20.1-build-2.0. It targets 1.20.1 with Fabric; another release may have different loader, side or dependency requirements.
- 02
Bring the mods it needs
This file does not list any required mods. Do not add a library just because a different file uses it.
- 03
Put it on the correct side
Installation on the client is optional. Installation on the dedicated server is optional.
- 04
Pick the file you checked
Use the “Get this file” button beside 1.20.1-build-2.0. It opens that exact file at the source.
About this project
What does Liby add?
This mod serves as a utility for developers and does not add any content on its own. It is a required dependency for other mods.
How to Add Liby to Your Project
Step 1: Add the CurseMaven Repository To download Liby from CurseMaven, you first need to add the repository to your build.gradle file:
repositories {
maven {
url "https://cursemaven.com"
}
}
Step 2: Add the Liby Dependency
- Find the Correct Maven Snippet:
- Navigate to the Files section and find the version compatible with your Minecraft setup.
- Expand the Curse Maven Snippet for the version you need.
- Copy the provided Maven snippet.
- Add the Dependency:
- After copying the snippet, add it to the dependencies block in your build.gradle. Here’s an example:
dependencies {
// Add the Liby dependency using the Maven snippet
modImplementation "curse.maven:liby-1115157:5783866"
// Liby dependency
implementation "org.reflections:reflections:0.10.2"
}
How to Use Liby
To utilize the Liby library for registering your mod's elements, follow these steps:
Define the Package for Registries: Start by specifying the package where Liby will search for your registries.
package group.your_fabric_mod;
import net.fabricmc.api.ModInitializer;
import nazario.liby.registry.auto.LibyRegistryLoader;
import net.minecraft.util.Identifier;
public class YourFabricMod implements ModInitializer {
public static final String MOD_ID = "your_fabric_mod";
@Override
public void onInitialize() {
LibyRegistryLoader.load("group.your_fabric_mod.registry");
}
public static Identifier id(String name) {
return Identifier.of(MOD_ID, name);
}
}
Set Up Your Registry: Next, create a registry for blocks.
package group.your_fabric_mod.registry;
//This tells Liby to register this class
@LibyAutoRegister
public class BlockRegistry {
public static final LibyBlockRegister REGISTER = new LibyBlockRegister(YourFabricMod.MOD_ID);
public static Block BASIC_BLOCK = REGISTER.registerBlock("basic_block", new Block(AbstractBlock.Settings.create()));
public static Block BLOCK_WITH_ITEM = REGISTER.registerBlock("block_with_item", new Block(AbstractBlock.Settings.create()), new Item.Settings());
public static void register() {
}
}
Registering Items: Register items similarly to blocks.
package group.your_fabric_mod.registry;
@LibyAutoRegister
public class ItemRegistry {
public static final LibyItemRegister REGISTER = new LibyItemRegister(YourFabricMod.MOD_ID);
public static Item BASIC_ITEM = REGISTER.registerItem("basic_item", new Item(new Item.Settings()));
public static void register() {
}
}
Setting Registration Priority: If you want blocks to register before items, adjust the @LibyAutoRegister annotation as follows:
@LibyAutoRegister(priority = 1)
Higher priority values ensure that items are registered after blocks.
Handling Item Groups: Liby has a specific way for managing item groups.
@LibyAutoRegister(priority = 2)
public class ItemGroupRegistry {
public static final LibyItemGroupRegister REGISTER = new LibyItemGroupRegister(ResearchFrontiers.MOD_ID);
public static final LibyItemGroup ITEM_GROUP = new LibyItemGroup("group", Text.translatable("your_fabric_mod.itemGroup"), new ItemStack(ItemRegistry.BASIC_ITEM));
public static void register() {
ITEM_GROUP.addItem(ItemRegistry.BASIC_ITEM, BlockRegistry.BLOCK_WITH_ITEM);
REGISTER.registerItemGroups(ITEM_GROUP);
}
}
Since the item group has an icon, ensure items are registered first by setting the priority of ItemGroupRegistry to 2.
Additional Information on Registration
If you prefer not to name each registration method register, you can specify a custom method name directly in the @LibyAutoRegister annotation. This allows for more descriptive method names that can enhance code readability and organization.
@LibyAutoRegister(priority = 2, register = "registerItemGroup")
public class ItemGroupRegistry {
public static void registerItemGroup() {
// Registration logic for item groups
}
}
If you prefer to keep all your registrations within your registry package, and you also want to handle client-side registration there, you need to include a LibyEntrypoint in the @LibyAutoRegister annotation. (The default Entrypoint is MAIN)
@LibyAutoRegister(priority = 0, entrypoint = LibyEntrypoints.CLIENT)
public class ClientRegistry {
public static void register() {
}
}
Creating Multiblocks with Liby
Liby provides a simple way for creating multiblocks. To get started, you need to define a BlockEntityRegistry.
Step 1: Define the Block Entity Registry
Create a class for your block entities and use the @LibyAutoRegister annotation to register it.
@LibyAutoRegister(priority = 3)
public class BlockEntityRegistry {
public static final LibyBlockEntityRegister REGISTER = new LibyBlockEntityRegister(ResearchFrontiers.MOD_ID);
public static BlockEntityType<WorkbenchBlockEntity> WORKBENCH_BLOCK_ENTITY =
REGISTER.registerType("workbench", BlockEntityType.Builder.create(WorkbenchBlockEntity::new, BlockRegistry.WORKBENCH).build());
public static void register() {
// Additional registration logic can be added here
}
}
Step 2: Create the Workbench Block
Define the WorkbenchBlock class, which extends LibyMultiBlock. Here, you initialize an array of BlockPos to define the positions that make up the multiblock structure. (Due to minecraft limitations on block model sizes 3x3x3, you should consider using GeckoLib for the model)
public class WorkbenchBlock extends LibyMultiBlock {
public WorkbenchBlock(Settings settings) {
super(settings, new BlockPos[]{
new BlockPos(0, 0, 0), // Parent block position
new BlockPos(-1, 0, 0) // Child block position
});
}
@Override
protected MapCodec<? extends BlockWithEntity> getCodec() {
return createCodec(WorkbenchBlock::new);
}
@Override
public @Nullable BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return new WorkbenchBlockEntity(pos, state);
}
}
Step 3: Create the Workbench Block Entity
Next, implement the WorkbenchBlockEntity class, which extends LibyMultiBlockEntity. This class represents the block entity associated with the WorkbenchBlock.
public class WorkbenchBlockEntity extends LibyMultiBlockEntity {
public WorkbenchBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityRegistry.WORKBENCH, pos, state);
}
}
Key Points
- In the
WorkbenchBlockclass, the BlockPos array specifies the positions of the blocks that make up the multiblock structure. The first entry should always represent the parent block. - Multiblock structures are from the start horizontal directional.
Step 4: Player interactions
Now we want the player to be able to right click our Workbench, for that you need to override onMultiBlockUse, inside WorkbenchBlock.
@Override
public ActionResult onMultiBlockUse(World world, BlockState clickedState, BlockState parentState, BlockPos clickedPos, BlockPos parentPos, PlayerEntity player, BlockHitResult hit) {
if(world.isClient) return ActionResult.PASS;
player.sendMessage(Text.literal("Hello from Workbench!"));
return ActionResult.SUCCESS;
}
Notice
When creating multiblock structures larger than the standard 3x3x3 block model limit in vanilla, you may encounter weird lighting issues. These issues arise because the game’s lighting engine thinks your childs blocks are solid, even tho there are invisible and don't render any model at all. To fix these issues we will tell the game that the childs blocks are transparent like glass, this will stop the light engine from drawing shadows on our model texture.
@Override
protected int getOpacity(BlockState state, BlockView world, BlockPos pos) {
return state.get(PARENT)?super.getOpacity(state, world, pos):0;
}
@Override
protected float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) {
return state.get(PARENT)?super.getAmbientOcclusionLightLevel(state, world, pos):1;
}
Networking (Experimental)
If you have a variable that needs to be synced across all players, Liby provides a simple solution for that.
To sync a variable over the network, you need to annotate it with @LibySyncedValue. The class inside the parentheses should correspond to the data type of the variable. (Not all variables are supported—generally, all primitive data types are supported, along with String, BlockPos, Vec3d, Vec3i, Vec2f, and NbtCompound.)
public class SyncedBlock extends Block {
// Annotates the variable to sync its value across the network, specifying Integer as its data type
@LibySyncedValue(Integer.class)
public int clicksValue;
public SyncedBlock(Settings settings) {
super(settings);
}
// Called when the block is right-clicked by a player
@Override
protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, BlockHitResult hit) {
// Sends a message to the player, showing whether the action occurred on the Client or Server, and displays the current clicksValue
player.sendMessage(Text.literal("<" + (world.isClient ? "Client" : "Server") + "> Value: " + clicksValue));
// Increases the clicksValue by 1 on the server side and syncs the new value across all players
if (!world.isClient) {
this.clicksValue += 1; // Increment the value
LibyNetworker.syncBlock(world, pos, this); // Sync the updated value with all players
}
return super.onUse(state, world, pos, player, hit);
}
}
Project description from CurseForge.
Pick your setup
Liby by Minecraft version and loader
Choose the version and loader you play, then open the matching release.
1.20.1
1 loader build1.19.2
1 loader buildCheck the dependencies, then try the file in a copied instance before changing a world you care about.
Recent files
Liby versions and loaders
3.0.0.0-1.20.1
liby-3.0.0.0-1.20.1.jar
18 Oct 2025
1.21.1-build-2.1.1
liby-1.21.1-build-2.1.1.jar
21 Mar 2025
1.21.1-build-2.1
liby-1.21.1-build-2.1.jar
9 Mar 2025
1.20.1-build-2.0
liby-1.20.1-build-2.0.jar
9 Mar 2025
1.21.1-build-2.0
liby-1.21.1-build-2.0.jar
26 Feb 2025
1.19.2-build-2.1
liby-1.19.2-build-2.1.jar
16 Feb 2025
1.19.2-build-2.0
liby-1.19.2-build-2.0.jar
16 Jan 2025
liby-1.20.1-build-1.0.jar
14 Dec 2024
liby-1.19.2-build-1.4.jar
7 Dec 2024
liby-1.19.2-build-1.3.jar
3 Dec 2024
liby-1.21.1-build-1.4.jar
29 Nov 2024
liby-1.21.1-build-1.3.jar
10 Oct 2024
Looking for an older file? The official CurseForge project page is in Resources.

