diff --git a/docs/concepts/events.md b/docs/concepts/events.md index 877dbafa4..64b0b6f21 100644 --- a/docs/concepts/events.md +++ b/docs/concepts/events.md @@ -123,7 +123,7 @@ Results are deprecated and will be replaced by more specific per-event results s ### Priority -Event handlers can optionally get assigned a priority. The `EventPriority` enum contains five values: `HIGHEST`, `HIGH`, `NORMAL` (default), `LOW` and `LOWEST`. Events are executed from highest to lowest priority, with undefined order for two events of the same priority. +Event handlers can optionally get assigned a priority. The `EventPriority` enum contains five values: `HIGHEST`, `HIGH`, `NORMAL` (default), `LOW` and `LOWEST`. Event handlers are executed from highest to lowest priority. If they have the same priority, they fire in registration order on the main bus, which is roughly related to mod load order, and in exact mod load order on the mod bus (see below). Priorities can be defined by setting the `priority` parameter in `IEventBus#addListener` or `@SubscribeEvent`, depending on how you attach event handlers. Note that priorities are ignored for events that are fired in parallel. diff --git a/docs/concepts/registries.md b/docs/concepts/registries.md index c1cc30a08..27c5959f5 100644 --- a/docs/concepts/registries.md +++ b/docs/concepts/registries.md @@ -18,7 +18,7 @@ The main reason all of this works is that `Blocks` is classloaded early enough b ## Methods for Registering -NeoForge offers two ways to register objects: the `DeferredRegister` class, and the `RegisterEvent`. Note that the former is a wrapper around the latter, and is thus recommended in order to prevent mistakes. +NeoForge offers two ways to register objects: the `DeferredRegister` class, and the `RegisterEvent`. Note that the former is a wrapper around the latter, and is recommended in order to prevent mistakes. ### `DeferredRegister` @@ -85,8 +85,9 @@ There are specialized variants of `DeferredRegister`s for blocks and items that public void register(RegisterEvent event) { event.register( // This is the registry key of the registry. - // Get these from Registries for vanilla registries, or from NeoForgeRegistries.Keys for NeoForge registries. - Registries.BLOCKS, + // Get these from BuiltInRegistries for vanilla registries, + // or from NeoForgeRegistries.Keys for NeoForge registries. + BuiltInRegistries.BLOCKS, // Register your objects here. registry -> { registry.register(new ResourceLocation(MODID, "example_block_1"), new Block(...)); @@ -102,12 +103,12 @@ public void register(RegisterEvent event) { Sometimes, you will find yourself in situations where you want to get a registered object by a given id. Or, you want to get the id of a certain registered object. Since registries are basically maps of ids (`ResourceLocation`s) to distinct objects, i.e. a reversible map, both of these operations work: ```java -Registries.BLOCKS.get(new ResourceLocation("minecraft", "dirt")); // returns the dirt block -Registries.BLOCKS.getKey(Blocks.DIRT); // returns the resource location "minecraft:dirt" +BuiltInRegistries.BLOCKS.get(new ResourceLocation("minecraft", "dirt")); // returns the dirt block +BuiltInRegistries.BLOCKS.getKey(Blocks.DIRT); // returns the resource location "minecraft:dirt" // Assume that ExampleBlocksClass.EXAMPLE_BLOCK.get() is a Supplier with the id "yourmodid:example_block" -Registries.BLOCKS.get(new ResourceLocation("yourmodid", "example_block")); // returns the example block -Registries.BLOCKS.getKey(ExampleBlocksClass.EXAMPLE_BLOCK.get()); // returns the resource location "yourmodid:example_block" +BuiltInRegistries.BLOCKS.get(new ResourceLocation("yourmodid", "example_block")); // returns the example block +BuiltInRegistries.BLOCKS.getKey(ExampleBlocksClass.EXAMPLE_BLOCK.get()); // returns the resource location "yourmodid:example_block" ``` If you just want to check for the presence of an object, this is also possible, though only with keys: @@ -131,7 +132,7 @@ for (Map.Entry entry : Registries.BLOCKS.entrySet()) { ``` :::note -Query operations should always use vanilla `Registry`s, not `DeferredRegister`s. This is because `DeferredRegister`s are merely registration utilities and effectively do not exist after registration has finished. +Query operations always use vanilla `Registry`s, not `DeferredRegister`s. This is because `DeferredRegister`s are merely registration utilities. ::: :::danger diff --git a/docs/concepts/sides.md b/docs/concepts/sides.md index f1c612600..48712d430 100644 --- a/docs/concepts/sides.md +++ b/docs/concepts/sides.md @@ -18,7 +18,7 @@ The logical side is mainly focused on the internal program structure of Minecraf The difference between physical and logical sides is best exemplified by two scenarios: -- The player joins a **multiplayer** world. This is fairly straightforward: The player's logical and physical client connects to a logical server somewhere else - the player does not care where; so long as they can connect, that's all the client knows of, and all the client needs to know. +- The player joins a **multiplayer** world. This is fairly straightforward: The player's physical (and logical) client connects to a physical (and logical) server somewhere else - the player does not care where; so long as they can connect, that's all the client knows of, and all the client needs to know. - The player joins a **singleplayer** world. This is where things get interesting. The player's physical client spins up a logical server and then, now in the role of the logical client, connects to that logical server on the same machine. If you are familiar with networking, you can think of it as a connection to `localhost` (only conceptually; there are no actual sockets or similar involved). These two scenarios also show the main problem with this: If a logical server can work with your code, that alone doesn't guarantee that a physical server will be able to work with as well. This is why you should always test with dedicated servers to check for unexpected behavior. `NoClassDefFoundError`s and `ClassNotFoundException`s due to incorrect client and server separation are among the most common errors there are in modding. Another common mistake is working with static fields and accessing them from both logical sides; this is particularly tricky because there's usually no indication that something is wrong. diff --git a/docs/items/index.md b/docs/items/index.md index 1c45deb72..dab3959d0 100644 --- a/docs/items/index.md +++ b/docs/items/index.md @@ -70,10 +70,10 @@ public static final Supplier EXAMPLE_ITEM = ITEMS.registerItem( Internally, this will simply call `ITEMS.register("example_item", () -> new Item(new Item.Properties()))` by applying the properties parameter to the provided item factory (which is commonly the constructor). -If you want to use `Item::new`, you can leave out the factory entirely: +If you want to use `Item::new`, you can leave out the factory entirely and use the `simple` method variant: ```java -public static final Supplier EXAMPLE_ITEM = ITEMS.registerItem( +public static final Supplier EXAMPLE_ITEM = ITEMS.registerSimpleItem( "example_item", new Item.Properties() // The properties to use. ); @@ -81,10 +81,10 @@ public static final Supplier EXAMPLE_ITEM = ITEMS.registerItem( This does the exact same as the previous example, but is slightly shorter. Of course, if you want to use a subclass of `Item` and not `Item` itself, you will have to use the previous method instead. -Both of these methods also have `simple` counterparts that omit the `new Item.Properties()` parameter: +Both of these methods also have overloads that omit the `new Item.Properties()` parameter: ```java -public static final Supplier EXAMPLE_ITEM = ITEMS.registerSimpleItem("example_item", Item::new); +public static final Supplier EXAMPLE_ITEM = ITEMS.registerItem("example_item", Item::new); // Variant that also omits the Item::new parameter public static final Supplier EXAMPLE_ITEM = ITEMS.registerSimpleItem("example_item"); ``` diff --git a/docs/misc/resourcelocation.md b/docs/misc/resourcelocation.md index 9b2d07fb6..f317a7341 100644 --- a/docs/misc/resourcelocation.md +++ b/docs/misc/resourcelocation.md @@ -2,7 +2,7 @@ `ResourceLocation`s are one of the most important things in Minecraft. They are used as keys in [registries][registries], as identifiers for data or resource files, as references to models in code, and in a lot of other places. A `ResourceLocation` consists of two parts: a namespace and a path, separated by a `:`. -The namespace denotes what mod or datapack the location refers to. For example, a mod with the mod id `examplemod` will use the `examplemod` namespace. Minecraft uses the `minecraft` namespace. Extra namespaces can be defined at will simply by creating a corresponding data folder, this is usually done by datapacks to keep their logic separate from the point where they integrate with vanilla. +The namespace denotes what mod, resource pack or datapack the location refers to. For example, a mod with the mod id `examplemod` will use the `examplemod` namespace. Minecraft uses the `minecraft` namespace. Extra namespaces can be defined at will simply by creating a corresponding data folder, this is usually done by datapacks to keep their logic separate from the point where they integrate with vanilla. The path is a reference to whatever object you want, inside your namespace. For example, `minecraft:cow` is a reference to something named `cow` in the `minecraft` namespace - usually this location would be used to get the cow entity from the entity registry. Another example would be `examplemod:example_item`, which would probably be used to get your mod's `example_item` from the item registry. @@ -23,14 +23,14 @@ The namespace and path of a `ResourceLocation` can be retrieved using `ResourceL Some places, for example registries, use `ResourceLocation`s directly. Some other places, however, will resolve the `ResourceLocation` as needed. For example: - `ResourceLocation`s are used as identifiers for GUI background. For example, the furnace GUI uses the resource location `minecraft:textures/gui/container/furnace.png`. This maps to the file `assets/minecraft/textures/gui/container/furnace.png` on disk. Note that the `.png` suffix is required in this resource location. -- `ResourceLocation`s are used as identifiers for block models. For example, the block model of dirt uses the resource location `minecraft:models/block/dirt`. This maps to the file `assets/minecraft/models/block/dirt.json` on disk. Note that the `.json` suffix is NOT required in this resource location. +- `ResourceLocation`s are used as identifiers for block models. For example, the block model of dirt uses the resource location `minecraft:block/dirt`. This maps to the file `assets/minecraft/models/block/dirt.json` on disk. Note that the `.json` suffix is not required here. Note as well that this resource location automatically maps into the `models` subfolder. - `ResourceLocation`s are used as identifiers for recipes. For example, the iron block crafting recipe uses the resource location `minecraft:iron_block`. This maps to the file `data/minecraft/recipes/iron_block.json` on disk. Note that the `.json` suffix is not required here. Note as well that this resource location automatically maps into the `recipes` subfolder. Whether the `ResourceLocation` expects a file suffix, or what exactly the resource location resolves to, depends on the use case. ## `ModelResourceLocation`s -`ModelResourceLocation`s are a special kind of resource location that includes a third part, called the variant. Minecraft uses these mainly to differentiate between different variants of item models, where the different variants are used in different display contexts (for example with tridents, which have different models in first person, third person and inventories). +`ModelResourceLocation`s are a special kind of resource location that includes a third part, called the variant. Minecraft uses these mainly to differentiate between different variants of models, where the different variants are used in different display contexts (for example with tridents, which have different models in first person, third person and inventories). The variant is always `inventory` for items, and the comma-delimited string of property-value pairs for blockstates (for example `facing=north,waterlogged=false`, empty for blocks with no blockstate properties). The variant is appended to the regular resource location, along with a `#`. For example, the full name of the diamond sword's item model is `minecraft:diamond_sword#inventory`. However, in most contexts, the `inventory` variant can be omitted. @@ -42,5 +42,7 @@ The variant is appended to the regular resource location, along with a `#`. For A new `ResourceKey` can be created through the static method `ResourceKey#create(ResourceKey>, ResourceLocation)`. The second parameter here is the registry name, while the first parameter is what is known as a registry key. Registry keys are a special kind of `ResourceKey` whose registry is the root registry (i.e. the registry of all other registries). A registry key can be created via `ResourceKey#createRegistryKey(ResourceLocation)` with the desired registry's id. +`ResourceKey`s are interned at creation. This means that comparing by reference equality (`==`) is possible and encouraged, but their creation is comparatively expensive. + [registries]: ../concepts/registries.md [sides]: ../concepts/sides.md