-
-
Notifications
You must be signed in to change notification settings - Fork 0
Common API
Cobweb simplifies the process of registering custom game objects by allowing you to register them directly in the common module, eliminating the need to register them separately in each of your mod loader submodules.
This system is designed to resemble the one provided by NeoForge. To use it, instantiate a register for each type of game object you want to register. This register will be unique to your mod. Then, use this register to add each of your custom game objects of that type. Unlike NeoForge, you don't need to register the register itself to the event bus, Cobweb handles it automatically when you instantiate your register!
Registration example
public final class ItemRegistry {
// Cobweb provides a utility to get a register for items and a few others.
private static final CobwebRegister<Item> ITEMS = CobwebRegistry.ofItems(Constants.MOD_ID);
// Use the Item register above to register any item you need, in this example a new SwordItem.
public static final CobwebEntry<SwordItem> CUSTOM_SWORD = ITEMS.register("custom_sword", () -> new SwordItem(Tiers.DIAMOND, 5, 0, new Item.Properties()));
public static void register() {
// Need to call this method in your CommonModLoader class to load this class.
}
}
public final class EnchantmentRegistry {
// Get a register without a specific utility method.
private static final CobwebRegister<Enchantment> ENCHANTMENTS = CobwebRegistry.of(Registries.ENCHANTMENT, Constants.MOD_ID);
// Use the Enchantment register above to register any enchantment you need, in this example a new ProtectionEnchantment.
public static final CobwebEntry<Enchantment> CUSTOM_ENCHANTMENT = ENCHANTMENTS.register("custom_enchantment", () -> new ProtectionEnchantment(Enchantment.Rarity.VERY_RARE, ProtectionEnchantment.Type.ALL, EquipmentSlot.OFFHAND));
public static void register() {
// Need to call this method in your CommonModLoader class to load this class.
}
}
public final class CommonModLoader {
public static void init() {
ItemRegistry.register();
EnchantmentRegistry.register();
}
}
Since Minecraft 1.21.3, Item
s and Block
s are required to set their ID within their Properties
.
For this reason, new and more specialized CobwebRegister
subclasses have been added, to accomodate for this change.
Don't worry, everything is fully backwards compatible! However, if you do still use the previous way to register Item
s and Block
s, you'll have to set manually the required ID property yourself. For this reason, it's suggested to use the aforementioned new CobwebRegister.Items
and CobwebRegister.Blocks
instead of CobwebRegister<Item>
and CobwebRegister<Block>
.
Registration example for Items
public final class ItemRegistry {
// Get the specialized Item register.
private static final CobwebRegister.Items ITEMS = CobwebRegistry.ofItems(Constants.MOD_ID);
// Use the Item register above to register any item you need, in this example a new SwordItem.
public static final CobwebEntry<SwordItem> CUSTOM_SWORD = ITEMS.registerItem("custom_sword", properties -> new SwordItem(ToolMaterial.DIAMOND, 3.0F, -2.4F, properties)));
// It's VERY IMPORTANT that you pass in the properties provided into your item constructor.
// Of course, if your item constructor just takes a single Properties parameter and there are no other properties to set, you can directly use CustomItem::new
// If you want to override the ID, you can still use the old ITEMS.register method.
// Since 1.21.3 you can also use the Item register to easily register any BlockItem, in this example one for your custom block.
public static final CobwebEntry<BlockItem> CUSTOM_BLOCK_ITEM = ITEMS.registerBlockItem("custom_block", BlockRegistry.CUSTOM_BLOCK);
// If you need to set extra properties, there is also an overload that takes as a third parameter some Properties.
// If you also need to register a BlockItem subclass instance, you can by using the method ITEMS.registerBlockItemLike, but then you'll also have to provide your constructor.
public static void register() {
// Need to call this method in your CommonModLoader class to load this class.
}
}
Registration example for Blocks
public final class BlockRegistry {
// Get the specialized Block register.
private static final CobwebRegister.Blocks BLOCKS = CobwebRegistry.ofBlocks(Constants.MOD_ID);
// Use the Block register above to register any block you need, in this example a new custom block.
public static final CobwebEntry<CustomBlock> CUSTOM_BLOCK = BLOCKS.registerBlock("custom_block", properties -> new CustomBlock(properties));
// It's VERY IMPORTANT that you pass in the properties provided into your block constructor.
// Of course, if your block constructor just takes a single Properties parameter and there are no other properties to set, you can directly use CustomBlock::new
// If you want to override the ID, you can still use the old BLOCKS.register method.
public static void register() {
// Need to call this method in your CommonModLoader class to load this class.
}
}
For any other game object, the registration stays unchanged from previous versions.
If you create your mod with our Mod Generator, a configuration example using Cobweb system will already be included!
Cobweb provides three different classes depending on the side you wish to register your configuration on: CommonConfig
, ClientConfig
, and ServerConfig
. However, it's highly suggested that you only use the CommonConfig
.
A simple configuration class looks like this:
Simple configuration class
import it.crystalnest.cobweb.api.config.CommonConfig;
import net.neoforged.neoforge.common.ModConfigSpec;
// Use the import below instead of the one right above for 1.20.1 and lower.
// import net.minecraftforge.common.ForgeConfigSpec;
public final class ModConfig extends CommonConfig {
/**
* Register your configuration within Cobweb system.
*/
public static final ModConfig CONFIG = register(Constants.MOD_ID, ModConfig::new);
/**
* Config example value.
* Make it private but not final.
*/
private ModConfigSpec.BooleanValue example;
private ModConfig(ModConfigSpec.Builder builder) {
super(builder);
}
/**
* This is the way to read any configuration value you declared within your config.
*
* @return the value of {@link #example} as read from the configuration file.
*/
public static Boolean getExample() {
return CONFIG.example.get();
}
/**
* Define all your configuration items here.
* Make sure you define all of your configuration items declared above, otherwise you will get a NPE!
*/
@Override
protected void define(ModConfigSpec.Builder builder) {
example = builder.comment(" Config example value").define("example", true);
}
}
And then it needs to be registered within the game:
Configuration registration
public final class CommonModLoader {
private CommonModLoader() {}
/**
* Register your configuration here.
*/
public static void init() {
ModConfig.CONFIG.register();
}
}
That's it! You now have a working configuration for your end users to tweak!
To learn how to define your configuration values, refer to the NeoForge configuration documentation, as this system is built upon it.
What are static and dynamic resource packs?
Resource packs are either texture packs or data packs.
Static and Dynamic refer to the way they are defined, either via files (can't change at runtime, static) or via code (can change at runtime, dynamic).
Here is a table for an easy comparison between different types of resource packs:
Mod resource pack | Static resource pack | Dynamic resource pack | External resource pack | |
---|---|---|---|---|
Shipped with your mod | Yes | Yes | Yes | No |
Toggleable by the user | No | Customizable (default Yes) |
Customizable (default No) |
Yes |
Definition |
resources directory |
resources directory and single line code registration |
Code | External |
Can change at runtime | No | No | Yes | No |
"Mod resource packs" here refers to what you generally put under the resources
directory of your mod.
Since v1.3.0 and Minecraft 1.21, there is a dedicated API to add static resource packs within your mod.
To use it, simply do the following steps:
- As you would for an external resource pack, create all the files and put them under a single directory.
Make sure the name of this directory conforms to MinecraftResourceLocation
standards. - In your
pack.mcmeta
, make sure to define the"description"
field as a translatable text.
The translation key can be whatever you want, but it's recommended to usedatapack.mod_id.custom_data_pack.description
ortexturepack.mod_id.custom_texture_pack.description
, depending on your resource pack type. - Put your resource pack under either
resources/datapack/
orresources/texturepack/
, depending on your resource pack type. - Register your resource pack as follows:
import it.crystalnest.cobweb.api.pack.fixed.StaticDataPack; import it.crystalnest.cobweb.api.pack.fixed.StaticTexturePack; import net.minecraft.server.packs.repository.PackSource; import net.minecraft.server.packs.repository.Pack; public final class CommonModLoader { private CommonModLoader() {} public static void init() { // Register your static data pack. new StaticDataPack( ResourceLocation.fromNamespaceAndPath(Constants.MOD_ID, "custom_data_pack"), // Use your mod ID and the correct directory name. PackSource.FEATURE, // Resource pack source type, defaults to BUILT_IN if omitted. Pack.Position.TOP, // Resource pack default position, either TOP (highest priority) or BOTTOM (lowest priority). false // Whether the resource pack is always active (can't be toggled on or off). Defaults to false (toggleable) if omitted. ).register(); // Register your static texture pack. new StaticTexturePack( ResourceLocation.fromNamespaceAndPath(Constants.MOD_ID, "custom_texture_pack"), // Use your mod ID and the correct directory name. PackSource.FEATURE, // Resource pack source type, defaults to BUILT_IN if omitted. Pack.Position.TOP, // Resource pack default position, either TOP (highest priority) or BOTTOM (lowest priority). false // Whether the resource pack is always active (can't be toggled on or off). Defaults to false (toggleable) if omitted. ).register(); } }
- Add the localization for your resource pack name and description:
{ "datapack.mod_id.custom_data_pack": "Custom data pack", "datapack.mod_id.custom_data_pack.description": "Custom data pack description", "texturepack.mod_id.custom_texture_pack": "Custom texture pack", "texturepack.mod_id.custom_texture_pack.description": "Custom texture pack description" }
That's it! Now, if you open the data pack or texture pack selection menu, you'll see your resource pack there as if it was an external one!
The API for dynamic resource packs is currently unstable and subject to breaking changes.
The feature offered is currently incomplete, allowing to define dynamic data packs that contain tags only.
More will come in the future, including support for dynamic resource packs, and many more features, but there is no ETA at the moment.
The Tool Tiers API is available only for Minecraft < 1.21
, since Minecraft removed the concept of levels from tool tiers afterwards.
Forge and NeoForge offer a tool tier API, but it lacks some utility methods. Fabric, on the other hand, doesn't have an API at all.
To address these gaps, Cobweb introduces the TierUtils
utility class, which provides the lacking utility methods and allows handling tool tiers within the common module.
-
NO_TIER
SpecialTier
to represent no tier. -
NO_TIER_REFERENCE
Special string reference forNO_TIER
. -
getAllTiers()
Returns aCollection<Tier>
of all the tiers in the game. -
getTier(ResourceLocation)
/getTier(String)
Returns the tool tier from the given reference.
Returnsnull
if not tier could be found.
The string must be parsable into a validResourceLocation
. -
compare(Item, Item)
/compare(TieredItem, TieredItem)
/compare(Tier, Tier)
/compare(ResourceLocation, ResourceLocation)
/compare(String, String)
Compares the two tiers, abiding to the usual compare semantics:0
if the tiers are equal,< 0
if the first tier is lower than the second one,> 0
vice versa. -
isIn(Collection<Tier>, Tier)
/isIn(Collection<Tier>, ResourceLocation)
/isIn(Collection<Tier>, String)
Checks whether the given tier is in the given tier list. -
getLevel(Item)
/getLevel(TieredItem)
/getLevel(Tier)
/getLevel(ResourceLocation)
/getLevel(String)
Returns the numeric level of the given tool tier.
The level can be the special value-1
if the reference is forNO_TIER
or if theItem
is not an instance ofTieredItem
. -
matches(Tier, String)
Checks whether the given reference represents the given tier.
For both blocks and items, Cobweb provides a shorthand to retrieve their in-game IDs (e.g. Blocks.DIRT
-> minecraft:dirt
).
Blocks:
-
BlockUtils#getKey(Block)
Returns the in-game ID of the given block as aResourceLocation
. -
BlockUtils#getStringKey(Block)
Returns the in-game ID of the given block as a string.
Items:
-
ItemUtils#getKey(Item)
Returns the in-game ID of the given item as aResourceLocation
. -
ItemUtils#getStringKey(Item)
Returns the in-game ID of the given item as a string.
To prevent code duplication across various projects, Cobweb also provides enums for the Environment and the Platform.
If you have any suggestions or questions about this wiki, please open an issue following the Documentation enhancement template.