Tags
Creators
Details
0.21.0
Compatibility
Changes
Ornithe Standard Libraries 0.21.0
OSL 0.21.0 supports Minecraft versions between Alpha 1.0.1_01 and Release 1.14.4.
Core 0.10.0
All of the Core API's registry classes (SimpleIdRegistry, DefaultedIdRegistry, IdBiMap) have been deprecated in favor of the new Registries API introduced in this update. They will be removed in a future update.
Namespaced Identifiers
Namespaced identifiers created through NamespacedIdentifiers factory methods no longer allow uppercase letters ([A-Z]).
NamespacedIdentifiers.from("example", "Thing"); // this will now throw an error
NamespacedIdentifiers.from("example", "thing"); // this is still valid
New prefixed and suffixed methods have been added to create derivative namespaced identifiers with a prefix or suffix.
NamespacedIdentifier id = NamespacedIdentifiers.parse("example:cookie");
NamespacedIdentifier prefixed = id.prefixed("blocks/"); // -> "example:blocks/cookie"
NamespacedIdentifier suffixed = id.suffixed(".json"); // -> "example:cookie.json"
Registries 0.1.0
The Registries API provides an alternative to Vanilla's registry system, with a more modern feature set and available for all Minecraft versions. Not all of Vanilla's registries are registered in the new registry system (only the block and item registries are at this time), but this will change over time as OSL's feature set expands.
This update also provides a Registry Sync API for synchronizing numerical IDs between the server and client and across game sessions, to help avoid network desync and world corruption bugs.
I want to give a shoutout to Cat Core, who helped develop and test this API and the accompanying changes in the Blocks and Items APIs.
Events
The BOOTSTRAP_REGISTRIES event is fired on game start-up, during bootstrapping. All registries should be loaded before this or in a listener to this event. Bootstrapping registries (i.e. populating their contents) may happen before this, but will be forced right after this event anyway.
RegistryEvents.BOOTSTRAP_REGISTRIES.register(() -> {
...
});
Registries
Registries should be created and registered in your mod's entrypoint:
public class ExampleInitializer implements ModInitializer {
@Override
public void init() {
ExampleRegistries.init();
}
}
public final class ExampleRegistries {
public static final ResourceKey<Registry<CookieRecipe>> COOKIE_RECIPE_REGISTRY = RegistryKeys.from(NamespacedIdentifiers.from("example", "cookie_recipe"));
public static final Registry<CookieRecipe> COOKIE_RECIPE = Registries.registerDefaulted(COOKIE_RECIPE_RECIPES, NamespacedIdentifiers.from("example", "chocolate_chip"), CookieRecipes::init);
public static void init() {
}
}
public final class CookieRecipes {
public static final CookieRecipe CHOCOLATE_CHIP = Registry.register(ExampleRegistries.COOKIE_RECIPE, NamespacedIdentifiers.from("example", "chocolate_chip"), new ChocolateChipCookieRecipe());
public static void init() {
}
}
Registry Sync
Numerical IDs may be used for serialization in server-client communication or in world saves. If this is the case, you must register your registry to be synchronized.
public final class ExampleRegistries {
public static final ResourceKey<Registry<CookieRecipe>> COOKIE_RECIPE_REGISTRY = RegistryKeys.from(NamespacedIdentifiers.from("example", "cookie_recipe"));
public static final Registry<CookieRecipe> COOKIE_RECIPE = Registries.registerDefaulted(COOKIE_RECIPE_RECIPES, NamespacedIdentifiers.from("example", "chocolate_chip"), CookieRecipes::init);
public static void init() {
SyncedRegistries.register(COOKIE_RECIPE_REGISTRY);
}
}
It is not recommended that you use the numerical IDs for any other purposes. If it is unavoidable, however, you can register a custom IdMapper or IdFixer to ensure there are no network desync or corruption bugs. This API provides several IdMapper implementations you can use, such BooleanArrayMapper, IntArrayMapper, ListMapper, and Int2ObjectMapMapper. You can of course create a custom implementation as well. See below for some examples from OSL's Blocks and Items APIs.
// the `EndermanEntity.HOLDABLE_BLOCKS` array uses block IDs as indices to the array!
SyncedRegistries.registerMapper(RegistryKeys.BLOCK, NamespacedIdentifiers.from("block/enderman_holdable"), BooleanArrayMapper.of(() -> EndermanEntity.HOLDABLE_BLOCKS, a -> EndermanEntity.HOLDABLE_BLOCKS = a));
// these maps in `ItemModelShaper` use item IDs as keys to the map!
SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model_location"), ItemModelRegistryMapper.of(this.models));
SyncedRegistries.registerMapper(RegistryKeys.ITEM, NamespacedIdentifiers.from("item_model"), ItemModelRegistryMapper.of(this.modelCache));
Blocks 0.2.0
Transitioned to the new Registries API and implemented Registry Sync. This comes with some API changes, the biggest of which is the deprecation of the register(int, NamespacedIdentifier, Block) method in 17w46a and below, in favor of register(NamespacedIdentifier, Block), which automatically assigns a numerical ID to the block.
--BlockRegistry.register(999, NamespacedIdentifiers.from("example", "cookie"), new CookieBlock());
++BlockRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBlock());
In versions between 12w07a and 1.6.4 you can pass a special value into the Block constructor to trigger automatic ID assignment:
BlockRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieBlock(Block.AUTO_ASSIGN_ID));
Items 0.2.0
Transitioned to the new Registries API and implemented Registry Sync. This comes with some API changes, the biggest of which is the deprecation of the register(int, NamespacedIdentifier, Item) method in 17w46a and below, in favor of register(NamespacedIdentifier, Item), which automatically assigns a numerical ID to the item.
--ItemRegistry.register(999, NamespacedIdentifiers.from("example", "cookie"), new CookieItem());
++ItemRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new CookieItem());
In versions between 1.6.4 and below you can pass a special value into the Item constructor to trigger automatic ID assignment:
ItemRegistry.register(NamespacedIdentifiers.from("example", "cookie"), new ItemBlock(Item.AUTO_ASSIGN_ID));
Networking 0.10.0
Connection Events
Connection events have been overhauled to fix some issues and add more features. For all connection events, listeners now receive a context object that holds information about the connection. The context objects give access to the following:
ClientConnectionContext {
Minecraft minecraft();
// singleplayer connections only
String worldName();
// multiplayer connections only
String serverAddress();
int serverPort();
// whether the connection is singleplayer
boolean isServerLocal();
// DISCONNECT events only
TextComponent disconnectReason();
}
ServerConnectionContext {
MinecraftServer server();
ServerPlayerEntity player();
// DISCONNECT events only
TextComponent disconnectReason();
}
Here are some example usages of the new API:
ClientConnectionEvents.LOGIN.register(context -> {
Minecraft minecraft = context.minecraft();
if (context.isServerLocal()) {
String worldName = context.worldName();
} else {
String serverAddress = context.serverAddress();
int serverPort = context.serverPort();
}
});
ServerConnectionEvents.DISCONNECT.register(context -> {
TextComponent disconnectReason = context.disconnectReason();
});
Fixes
- Fixed
DISCONNECTevents not being fired on the side that initiated the disconnect (e.g. when leaving the server the event was not fired client-side, and when kicking a player the event was not fired server-side). - Fixed crash in 1.14 server environments.
- Fixed crash in 12w18a-12w19a due to invalid
mixins.json.
Resource Loader 0.8.0
Resource Locations
The ResourceLocation class now has a factory method for creating a NamespacedIdentifier representing a resource location, that always uses the proper validation for the runtime Minecraft version and supported resource pack format. The validation rules are:
- Resource pack format 1 and 2 (1.10.2 and below): no uppercase letters ([A-Z]) in namespaces, no validation on paths.
- Resource pack format 3 (16w32a-17w47a): no uppercase letters ([A-Z]) in namespaces nor in paths.
- Resource pack format 4 (17w48a and above): only [-._a-z0-9] allowed in namespaces and only [-._/a-z0-9] allowed in paths.
NamespacedIdentifier resourceLocation = ResourceLocation.of("example", "path/to/resource");
// check if the resource location is valid for the runtime Minecraft version and resource pack format
ResourceLocation.isValid(resourceLocation);
ResourceLocation.isValidNamespace("example");
ResourceLocation.isValidPath("path/to/resource");
Resource Packs
The pack icon for resource packs added through custom repository sources now falls back to the default pack icon if none is provided. In prior OSL versions the pack icon would fall back to the missing texture instead, which did not match Vanilla behavior.
Fixes
- (#76) Fixed errors thrown during
RESOURCE_RELOAD_ENDevents being silently caught instead of rethrown. - Fixed crashes due to improper resource location validation.
- Fixed resource metadata sometimes not loading in 1.13 and above.
- Fixed sound freeze issues due to a
ZipFileSystemthread interrupt bug. - Fixed crash in 12w15a-12w17a due to an invalid mixin.
Localization 0.1.1
- Fixes potential NPEs if localization is not set up.
- Fixes formatting errors in some versions (like command feedback in 1.6) by replacing illegal/unsupported formatting codes.
Text Components 0.1 Alpha 4
Vanilla Text components can now be converted to OSL TextComponents through TextComponents.resolve.
TextComponent literalText = TextComponents.resolve(new LiteralText("This is text!"));
TextComponent translatableText = TextComponents.resolve(new TranslatableText("this.is.text"));
Text Components 0.1 Alpha 5
Fixes a start-up crash in 1.6.4 and below due to a missing entrypoint.
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:EHGtwpJv:T21Ph3Pq"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:EHGtwpJv:T21Ph3Pq"
}

