Unstable Releases
A guide on how to use/download unstable releases of SI: Essentials
Introduction
Maven repository
The maven repository stays the same as for stable releases.
You can use unstable releases to test new features early and find bugs for us that you can report on our Support page.
Current latest unstable release
Version: 2.4.0-b2
Changelog
## For Developers
- Added Cnfg Enum support
- [NeoForge] RegistryUtils are finally coming to NeoForge!
- [Fabric] Using RegistryUtils to register blocks and items now returns a Supplier instead of the object itself. To access the object, call `get()` on the returned Supplier. This was changed for parity with NeoForge.
- More methods have been added to the RegistryUtils class to make registering easier.
- Improved Cnfg value validation
- Incorrect types of cnfg values will now get parsed to the correct type if possible (Numbers -> Strings, Double -> Float, Float -> Integer (decimal point is dropped))
- Fixed an issue where accessing Cnfg values not registered in any schema would silently return nothing. In this case, the default value is now returned.
- Fixed an issue where NeoForge 1.21.10+ worlds couldn't be loaded in a development environment.Adding the dependency
Fabric
Fabric API
The Fabric version of SI: Essentials requires Fabric API! Building your Mod requires Fabric Loom 1.16-SNAPSHOT or higher.
Gradle dependency
// Groovy
implementation "dev.soncresityindustries:sies:2.4.0-b2-26.1.2-fabric"
implementation "net.fabricmc.fabric-api:fabric-api:0.151.0+26.1.2"
// Kotlin
implementation("dev.soncresityindustries:sies:2.4.0-b2-26.1.2-fabric")
implementation("net.fabricmc.fabric-api:fabric-api:0.151.0+26.1.2")fabric.mods.json
"depends": {
"fabricloader": ">=0.19",
"minecraft": "26.1.2",
"fabric-api": ">=0.151.0+26.1.2",
"sies": ">=2.4.0-b2"
}NeoForge
Gradle dependency
// Groovy
implementation "dev.soncresityindustries:sies:2.4.0-b2-26.1.2-neoforge"
// Kotlin
implementation("dev.soncresityindustries:sies:2.4.0-b2-26.1.2-neoforge")neoforge.mods.toml
[[dependencies.your_mod_id]]
modId="sies"
type="required"
versionRange="[2.4.0-b2,)"
ordering="AFTER"
side="BOTH"Feature list
Migration notice
When the full 2.4.0 release is released, everything in this section will be moved/migrated into all respective wiki pages.
In this section features that were added during unstable releases will be listed and explained.
Global Screen titles (UI Module)
2.4.0-b1 adds support for global screen titles in the UI configuration in addition to the previous per-screen titles.
Meaning that once you turn them on, the global screen title will be prepended to every per-screen title allowing for configurations like those:
change_screen_titles = true
# Whether a global screen title should be set. If true, values from screen_titles will append to the global title.
# Requires 'change_screen_titles' to be true.
global_screen_titles = true
# The global screen title. Requires 'global_screen_titles' to be true.
# You can use the placeholders listed here: https://wiki.soncresity.industries/sies/placeholders
global_title = "Minecraft %game_version% %loader%"
# A map of custom screen titles.
# You can use the placeholders listed here: https://wiki.soncresity.industries/sies/placeholders
# Key: Screen package.Class
# Value: Screen title to show
screen_titles = {
"dev.soncresityindustries.es.ui.MainMenuScreen": " - Main Menu",
"net.minecraft.client.gui.screens.TitleScreen": " - Main Menu",
"ingame": " - Playing"
}Example:
![]()
Finally, as you can see in the cnfg snippet, we've added an "ingame" identifier option as it was previously impossible to track the screen when playing as the screen in that case was null
Known issues
- On some versions in a non-dev environment, custom screen titles don't work at all. This is due to minecrafts’ obfuscation and will be fixed in a future beta.
Cnfg Enum support
2.4.0-b2 adds support for Cnfg Enum values. You can define and use them like this:
import dev.soncresityindustries.es.api.v0.config.cnfg.CnfgBuilder;
import dev.soncresityindustries.es.api.v0.config.cnfg.CnfgKey;
import dev.soncresityindustries.es.api.v0.config.cnfg.CnfgManager;
public class Cnfg {
public static dev.soncresityindustries.es.api.v0.config.cnfg.Cnfg MYMOD_COMMON_CNFG = null;
public enum ENUMCLASS {
VALUE1,
VALUE2,
VALUE3
}
public static final CnfgKey<ENUMCLASS> ENUM_CNFG_KEY =
CnfgKey.ofEnum("enum", ENUMCLASS.class, ENUMCLASS.VALUE1);
private static CnfgBuilder createSchema() {
return new CnfgBuilder()
/* Method reference:
* public <E extends Enum<E>> CnfgBuilder defineEnum(String key, Class<E> enumClass, E defaultValue, boolean showDefault, boolean showAvailable) {}
* showDefault defaults to false
* showAvailable defaults to true
*
* Other possible methods:
* public <E extends Enum<E>> CnfgBuilder defineEnum(CnfgKey<E> key) {}
* public <E extends Enum<E>> CnfgBuilder defineEnum(CnfgKey<E> key, boolean showDefault) {}
* public <E extends Enum<E>> CnfgBuilder defineEnum(CnfgKey<E> key, boolean showDefault, boolean showAvailable) {}
* public <E extends Enum<E>> CnfgBuilder defineEnum(String key, Class<E> enumClass, E defaultValue) {}
* public <E extends Enum<E>> CnfgBuilder defineEnum(String key, Class<E> enumClass, E defaultValue, boolean showDefault) {}
* public <E extends Enum<E>> CnfgBuilder defineEnum(String key, Class<E> enumClass, E defaultValue, boolean showDefault, boolean showAvailable) {}
*
* As you can see above, if you supply a CnfgKey, the other values like the enum class and default value are parsed from the CnfgKey automatically.
*/
.defineEnum(ENUM_CNFG_KEY.key(), ENUM_CNFG_KEY.type(), ENUM_CNFG_KEY.defaultValue(), true, true)
// `.defineEnum(ENUM_CNFG_KEY, true)` would also work and do the same thing as above
.withComment(ENUM_CNFG_KEY.key(), "This is a test enum.");
}
protected static void init() {
MYMOD_COMMON_CNFG = CnfgManager.loadCommonCnfg(
"mymod_common",
"mymod/general.cnfg",
createSchema()
);
if (MYMOD_COMMON_CNFG == null) {
throw new RuntimeException("Failed to load common config!");
}
}
}Cnfg improvements and fixes
In 2.4.0-b2, we've improved the Cnfg value validation by checking the type that is assigned to a CnfgKey. This means that if you define a CnfgKey of a specific type (e.g. String) the parser will always try to parse a string. If parsing fails, the default value will be returned.
This also fixes a bug where numerical values could be parsed as an incorrect numerical type (e.g. float instead of double). Now, if, for example, a decimal value is set in an integer field, the parser will drop the decimal points and correct the value in the cnfg.
Registry Utils
In 2.4.0-b2, the RegistryUtils class has been heavily reworked to add support for NeoForge and more flexibility.
For version parity we've also introduced a new fire_and_explosion_resistant DamageType tag to be able to make an item fire- and explosion-resistant, just like in 1.21.1.
Currently, the RegistryUtils class only allows you to register Items, Blocks and BlockItems; however, we plan to add more options in the future.
Warning
NeoForge requires additional setup for the RegistryUtils to work. If you'd like to skip directly to that part, click here.
Method overview
Notice
Keep in mind that those methods work in the same way on both Fabric and NeoForge!
Items
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, boolean fireResistant) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, boolean fireResistant, boolean explosionResistant) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, @NotNull Function<Item.Properties, Item> itemFactory) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, @NotNull Function<Item.Properties, Item> itemFactory, boolean fireResistant) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, @NotNull Function<Item.Properties, Item> itemFactory, boolean fireResistant, boolean explosionResistant) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, Item.@NotNull Properties settings) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, Item.@NotNull Properties settings, boolean fireResistant) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, Item.@NotNull Properties settings, boolean fireResistant, boolean explosionResistant) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, @NotNull Function<Item.Properties, Item> itemFactory, Item.@NotNull Properties settings) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, @NotNull Function<Item.Properties, Item> itemFactory, Item.@NotNull Properties settings, boolean fireResistant) {}
public static Supplier<Item> registerItem(@NotNull String modID, @NotNull String itemID, @NotNull Function<Item.Properties, Item> itemFactory, Item.@NotNull Properties settings, boolean fireResistant, boolean explosionResistant) {}Blocks
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, boolean registerBlockItem) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory, boolean registerBlockItem) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, BlockBehaviour.@NotNull Properties blockSettings) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, BlockBehaviour.@NotNull Properties blockSettings, boolean registerBlockItem) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory, BlockBehaviour.@NotNull Properties blockSettings) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory, BlockBehaviour.@NotNull Properties blockSettings, boolean registerBlockItem) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory, BlockBehaviour.@NotNull Properties blockSettings, Item.@NotNull Properties blockItemSettings) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory, BlockBehaviour.@NotNull Properties blockSettings, boolean registerBlockItem, Item.@NotNull Properties blockItemSettings) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory, BlockBehaviour.@NotNull Properties blockSettings, Item.@NotNull Properties blockItemSettings, boolean blockItemFireResistant) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory, BlockBehaviour.@NotNull Properties blockSettings, boolean registerBlockItem, Item.@NotNull Properties blockItemSettings, boolean blockItemFireResistant) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory, BlockBehaviour.@NotNull Properties blockSettings, Item.@NotNull Properties blockItemSettings, boolean blockItemFireResistant, boolean blockItemExplosionResistant) {}
public static Supplier<Block> registerBlock(@NotNull String modID, @NotNull String itemID, @NotNull Function<BlockBehaviour.Properties, Block> blockFactory, BlockBehaviour.@NotNull Properties blockSettings, boolean registerBlockItem, Item.@NotNull Properties blockItemSettings, boolean blockItemFireResistant, boolean blockItemExplosionResistant) {}BlockItems
public static Supplier<BlockItem> registerBlockItem(@NotNull String modID, @NotNull String itemID, @NotNull Supplier<Block> block) {}
public static Supplier<BlockItem> registerBlockItem(@NotNull String modID, @NotNull String itemID, @NotNull Supplier<Block> block, boolean fireResistant) {}
public static Supplier<BlockItem> registerBlockItem(@NotNull String modID, @NotNull String itemID, @NotNull Supplier<Block> block, boolean fireResistant, boolean explosionResistant) {}
public static Supplier<BlockItem> registerBlockItem(@NotNull String modID, @NotNull String itemID, @NotNull Supplier<Block> block, Item.@NotNull Properties settings, boolean fireResistant) {}
public static Supplier<BlockItem> registerBlockItem(@NotNull String modID, @NotNull String itemID, @NotNull Supplier<Block> block, Item.@NotNull Properties settings, boolean fireResistant, boolean explosionResistant) {}Examples
Register a simple item without any additional functionality:
public static final Supplier<Item> ITEM = registerItem(MyMod.MODID, "item");Register a simple item without any additional functionality except it being resistant to fire and explosion damage:
public static final Supplier<Item> ITEM = registerItem(MyMod.MODID, "item", true, true);Register a custom item with custom item properties:
public static final Supplier<Item> ITEM = registerItem(MyMod.MODID, "item", MyItemClass::new, new Item.Properties());Register a custom item with custom item properties while making it resistant to fire and explosion damage:
Warning
When defining at least one of the two fireResistant and explosionResistant booleans as true, your implementation of Item.Properties().delayedComponent(DataComponents.DAMAGE_RESISTANT, ...) or Item.Properties().component(DataComponents.DAMAGE_RESISTANT, ...) will be overridden!
This only applies if you're registering a DataComponents.DAMAGE_RESISTANT component. All other components will be registered normally!
public static final Supplier<Item> ITEM = registerItem(MyMod.MODID, "item", MyItemClass::new, new Item.Properties(), true, true);Register a simple block (with a BlockItem) without any additional functionality:
public static final Supplier<Block> BLOCK = registerBlock(MyMod.MODID, "block");Register a simple block without a BlockItem or any additional functionality:
public static final Supplier<Block> BLOCK = registerBlock(MyMod.MODID, "block", false);Register a custom block with custom block properties and custom BlockItem properties while making the Blockitem resistant to fire and explosion damage::
public static final Supplier<Block> BLOCK = registerBlock(MyMod.MODID, "block", MyBlockClass::new, new Block.Properties(), true, true);Item and Main Class setup
For both Fabric and NeoForge, you need a method that loads the class into memory. We use a method called init() with no additional functionality. (public static void init() {})
While you can simply call this init method in the onInitialize method when using Fabric, you need to call it in the Main Class constructor and call two other helper methods when using NeoForge:
@Mod(MyMod.MODID)
public class MyMod {
public static final String MODID = "modid";
public MyMod(IEventBus modEventBus, ModContainer modContainer) {
// Set up the DeferredRegister.
RegistryUtils.init(MODID);
// Load all Classes that use the RegistryUtils class.
MyModItems.init();
// Other classes that use RegistryUtils need to be loaded before the call to RegistryUtils.register(modEventBus)!
// Register all items, etc. using the modEventBus.
RegistryUtils.register(modEventBus);
}
}