### Mod License Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting the license under which the mod is provided. ```properties mod_license=MIT ``` -------------------------------- ### Gradle Daemon Configuration Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of disabling the Gradle daemon for building. ```properties org.gradle.daemon=false ``` -------------------------------- ### Mod Version Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting the version of the mod, displayed in the mod list. ```properties mod_version=1.0 ``` -------------------------------- ### NeoForge Version Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting the target NeoForge version for modding. ```properties neo_version=20.6.62 ``` -------------------------------- ### Minecraft Version Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting the target Minecraft version for modding. ```properties minecraft_version=1.20.6 ``` -------------------------------- ### RP1 sounds.json Example Source: https://docs.neoforged.net/docs/1.21.5/resources/client/sounds Example `sounds.json` content from a resource pack (RP1). ```json { "sound_1": { "sounds": [ "sound_1" ] }, "sound_2": { "replace": true, "sounds": [ "sound_2" ] }, "sound_3": { "sounds": [ "sound_3" ] }, "sound_4": { "replace": true, "sounds": [ "sound_4" ] } } ``` -------------------------------- ### RP2 sounds.json Example Source: https://docs.neoforged.net/docs/1.21.5/resources/client/sounds Example `sounds.json` content from a resource pack (RP2), which is lower in the pack order. ```json { "sound_1": { "sounds": [ "sound_5" ] }, "sound_2": { "sounds": [ "sound_6" ] }, "sound_3": { "replace": true, "sounds": [ "sound_7" ] }, "sound_4": { "replace": true, "sounds": [ "sound_8" ] } } ``` -------------------------------- ### Mod Description Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting a multiline description for the mod, shown in the mod list. ```properties mod_description=Example mod description. ``` -------------------------------- ### Gradle JVM Arguments Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting JVM arguments for Gradle, commonly used to allocate memory. ```properties org.gradle.jvmargs=-Xmx3G ``` -------------------------------- ### Mod Name Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting the human-readable display name for a mod. ```properties mod_name=Example Mod ``` -------------------------------- ### Example TestData JSON Configuration Source: https://docs.neoforged.net/docs/1.21.5/misc/gametest This JSON defines the configuration for a game test, specifying the environment, structure, tick limits, setup ticks, required status, rotation, manual-only flag, max attempts, required successes, and sky access. ```json { // `TestData` // The environment to run the test in // Points to 'data/examplemod/test_environment/example_environment.json' "environment": "examplemod:example_environment", // The structure used for the game test // Points to 'data/examplemod/structure/example_structure.nbt' "structure": "examplemod:example_structure", // The number of ticks that the game test will run until it automatically fails "max_ticks": 400, // The number of ticks that are used to setup everying required for the game test // This is not counted towards the maximum number of ticks the test can take // If not specified, defaults to 0 "setup_ticks": 50, // Whether the test is required to succeed to mark the batch run as successful // If not specified, defaults to true "required": true, // Specifies how the structure and all subsequent helper methods should be rotated for the test // If not specified, nothing is rotated // Can be 'none', 'clockwise_90', '180', 'counterclockwise_90' "rotation": "clockwise_90", // When true, the test can only be ran through the `/test` command // If not specified, defaults to false "manual_only": true, // Specifies the maximum number of times that the test can be reran // If not specified, defaults to 1 "max_attempts": 3, // Specifies the minimum number of successes that must occur for a test to be marked as successful // This must be less than or equal to the maximum number of attempts allowed // If not specified, defaults to 1 "required_successes": 1, // Returns whether the structure boundary should keep the top empty // This is currently only used in block-based test instances // If not specified, defaults to false "sky_access": false // ... } ``` -------------------------------- ### Mod Authors Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting the authors of the mod, displayed in the mod list. ```properties mod_authors=ExampleModder ``` -------------------------------- ### Mod ID Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting the unique identifier for a mod. ```properties mod_id=examplemod ``` -------------------------------- ### NeoForge Version Range Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of defining the acceptable NeoForge version range for a mod. ```properties neo_version_range=[20.6.62,20.7) ``` -------------------------------- ### Gradle Configuration Cache Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of disabling the Gradle configuration cache. ```properties org.gradle.configuration-cache=false ``` -------------------------------- ### Datagen Example for RightClickBlockRecipeBuilder Source: https://docs.neoforged.net/docs/1.21.5/resources/server/recipes/custom Demonstrates how to use the `RightClickBlockRecipeBuilder` during data generation to create a recipe. ```java @Override protected void buildRecipes(RecipeOutput output) { new RightClickBlockRecipeBuilder( new ItemStack(Items.DIAMOND), Blocks.DIRT.defaultBlockState(), Ingredient.of(Items.APPLE) ) .unlockedBy("has_apple", this.has(Items.APPLE)) .save(output); // other recipe builders here } ``` -------------------------------- ### Loader Version Range Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of defining the acceptable mod loader version range for a mod. ```properties loader_version_range=[1,) ``` -------------------------------- ### Minecraft Version Range Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of defining the acceptable Minecraft version range for a mod. ```properties minecraft_version_range=[1.20.6,1.21) ``` -------------------------------- ### Screen Constructor Example Source: https://docs.neoforged.net/docs/1.21.5/gui/screens Example of a basic screen constructor that accepts a Component for its title. This is typically used in subclasses of the base Screen class. ```java public MyScreen(Component title) { super(title); } ``` -------------------------------- ### Blockstate Notation Example Source: https://docs.neoforged.net/docs/1.21.5/blocks/states Demonstrates the standardized text notation for representing a blockstate with properties. ```plaintext minecraft:oak_planks[] ``` -------------------------------- ### Gradle Caching Configuration Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of disabling Gradle task output caching. ```properties org.gradle.caching=false ``` -------------------------------- ### Example: Query IItemHandler Block Capability Source: https://docs.neoforged.net/docs/1.21.5/inventories/capabilities Demonstrates querying an IItemHandler capability for a block from a specific direction. ```java IItemHandler handler = level.getCapability(Capabilities.ItemHandler.BLOCK, pos, Direction.NORTH); if (handler != null) { // Use the handler for some item-related operation. } ``` -------------------------------- ### Merged sounds.json Example Source: https://docs.neoforged.net/docs/1.21.5/resources/client/sounds The resulting in-memory `sounds.json` after merging RP1 and RP2, demonstrating merge logic. ```json { "sound_1": { "sounds": [ "sound_5", "sound_1" ] }, "sound_2": { "sounds": [ "sound_2" ] }, "sound_3": { "sounds": [ "sound_7", "sound_3" ] }, "sound_4": { "sounds": [ "sound_8" ] } } ``` -------------------------------- ### Block Tags Provider Example Source: https://docs.neoforged.net/docs/1.21.5/resources/server/tags Implement a custom BlockTagsProvider to define and generate block tags. This example shows how to add, optionally add, add tags, optionally add tags, replace, remove entries, and manage tag properties. ```java public class MyBlockTagsProvider extends BlockTagsProvider { // Get parameters from one of the `GatherDataEvent`s. public MyBlockTagsProvider(PackOutput output, CompletableFuture lookupProvider) { super(output, lookupProvider, ExampleMod.MOD_ID); } // Add your tag entries here. @Override protected void addTags(HolderLookup.Provider lookupProvider) { // Create a tag builder for our tag. This could also be e.g. a vanilla or NeoForge tag. this.tag(MY_TAG) // Add entries. This is a vararg parameter. // Non-intrinsic providers must provide ResourceKeys here instead of the actual objects. .add(Blocks.DIRT, Blocks.COBBLESTONE) // Add optional entries that will be ignored if absent. This example uses Botania's Pure Daisy. // Unlike #add, this is not a vararg parameter. .addOptional(ResourceLocation.fromNamespaceAndPath("botania", "pure_daisy")) // Add a tag entry. .addTag(BlockTags.PLANKS) // Add multiple tag entries. This is a vararg parameter. // Can cause unchecked warnings that can safely be suppressed. .addTags(BlockTags.LOGS, BlockTags.WOODEN_SLABS) // Add an optional tag entry that will be ignored if absent. .addOptionalTag(ResourceLocation.fromNamespaceAndPath("c", "ingots/tin")) // Add multiple optional tag entries. This is a vararg parameter. // Can cause unchecked warnings that can safely be suppressed. .addOptionalTags(ResourceLocation.fromNamespaceAndPath("c", "nuggets/tin"), ResourceLocation.fromNamespaceAndPath("c", "storage_blocks/tin")) // Set the replace property to true. .replace() // Set the replace property back to false. .replace(false) // Remove entries. This is a vararg parameter. Accepts either resource locations, resource keys, // tag keys, or (intrinsic providers only) direct values. // Can cause unchecked warnings that can safely be suppressed. .remove(ResourceLocation.fromNamespaceAndPath("minecraft", "crimson_slab"), ResourceLocation.fromNamespaceAndPath("minecraft", "warped_slab")); } } ``` -------------------------------- ### Codec Definition for ExampleTriggerInstance Source: https://docs.neoforged.net/docs/1.21.5/resources/server/advancements Provides a concrete example of a Codec for ExampleTriggerInstance using RecordCodecBuilder. This codec handles the serialization of player and item predicates. ```java public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(ExampleTriggerInstance::player), ItemPredicate.CODEC.fieldOf("item").forGetter(ExampleTriggerInstance::item) ).apply(instance, ExampleTriggerInstance::new)); ``` -------------------------------- ### Data File with Values Source: https://docs.neoforged.net/docs/1.21.5/resources/server/datamaps An example JSON data file containing values for 'minecraft:carrot' with multiple keys. ```json { "values": { "minecraft:carrot": { "somekey1": "value1", "somekey2": "value2" } } } ``` -------------------------------- ### Mutable Class Example with hashCode and equals Source: https://docs.neoforged.net/docs/1.21.5/items/datacomponents A class example demonstrating the implementation of `hashCode` and `equals` for a mutable component value. Care must be taken to ensure immutability when used as a component. ```java public class ExampleClass { private final int value1; // Can be mutable, but care needs to be taken when using private boolean value2; public ExampleClass(int value1, boolean value2) { this.value1 = value1; this.value2 = value2; } @Override public int hashCode() { return Objects.hash(this.value1, this.value2); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } else { return obj instanceof ExampleClass ex && this.value1 == ex.value1 && this.value2 == ex.value2; } } } ``` -------------------------------- ### AbstractContainerScreen Constructor Source: https://docs.neoforged.net/docs/1.21.5/gui/screens Example of subclassing AbstractContainerScreen and setting initial label positions. Note that inventoryLabelY depends on imageHeight. ```java public MyContainerScreen(MyMenu menu, Inventory playerInventory, Component title) { super(menu, playerInventory, title); this.titleLabelX = 10; this.inventoryLabelX = 10; /* * If the 'imageHeight' is changed, 'inventoryLabelY' must also be * changed as the value depends on the 'imageHeight' value. */ } ``` -------------------------------- ### Example Saved Data Implementation Source: https://docs.neoforged.net/docs/1.21.5/datastorage/saveddata Demonstrates a basic implementation of the `SavedData` class. Call `setDirty()` when data changes to ensure persistence. ```java // For some saved data implementation public class ExampleSavedData extends SavedData { public void foo() { // Change data in saved data // Call set dirty if data changes this.setDirty(); } } ``` -------------------------------- ### Building Smithing Trim Recipes with Java Source: https://docs.neoforged.net/docs/1.21.5/resources/server/recipes/builtin Example of using SmithingTrimRecipeBuilder in Java for recipe datagen. This method constructs the recipe programmatically. ```java SmithingTrimRecipeBuilder.smithingTrim( // The template ingredient. Ingredient.of(Items.BOLT_ARMOR_TRIM_SMITHING_TEMPLATE), // The base ingredient. this.tag(ItemTags.TRIMMABLE_ARMOR), // The addition ingredient. this.tag(ItemTags.TRIM_MATERIALS), // The trim pattern to apply to the base. this.registries.lookupOrThrow(Registries.TRIM_PATTERN).getOrThrow(TrimPatterns.SPIRE), // The recipe book category. RecipeCategory.MISC ) // The recipe advancement, like with the other recipes above. .unlocks("has_smithing_trim_template", this.has(Items.BOLT_ARMOR_TRIM_SMITHING_TEMPLATE)) // This overload of #save allows us to specify a name. Yes, this name is copied from vanilla. .save(this.output, "bolt_armor_trim_smithing_template_smithing_trim"); ``` -------------------------------- ### Class Naming Scheme Examples Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/structuring Shows common suffixes used for class names to indicate their type, such as Item, Block, or Menu. ```java An `Item` called `PowerRing` -> `PowerRingItem`. A `Block` called `NotDirt` -> `NotDirtBlock`. A menu for an `Oven` -> `OvenMenu`. ``` -------------------------------- ### Custom BlockLootSubProvider Implementation Source: https://docs.neoforged.net/docs/1.21.5/resources/server/loottables Example of extending BlockLootSubProvider to define custom block loot tables. Requires implementing getKnownBlocks and generate methods. ```java public class MyBlockLootSubProvider extends BlockLootSubProvider { public MyBlockLootSubProvider(HolderLookup.Provider lookupProvider) { super(Set.of(), FeatureFlags.DEFAULT_FLAGS, lookupProvider); } @Override protected Iterable getKnownBlocks() { return MyRegistries.BLOCK_REGISTRY.getEntries() .stream() .map(e -> (Block) e.value()) .toList(); } @Override protected void generate() { this.dropSelf(MyBlocks.EXAMPLE_BLOCK.get()); this.add(MyBlocks.EXAMPLE_SILK_TOUCHABLE_BLOCK.get(), this.createSilkTouchOnlyTable(MyBlocks.EXAMPLE_SILK_TOUCHABLE_BLOCK.get())); } } ``` -------------------------------- ### Define and Build ExampleConfig Source: https://docs.neoforged.net/docs/1.21.5/misc/config This snippet shows how to define a static ExampleConfig and its ModConfigSpec, and how to build them using a builder pattern. It's typically used within a static block. ```java //Define a field to keep the config and spec for later public static final ExampleConfig CONFIG; public static final ModConfigSpec CONFIG_SPEC; private ExampleConfig(ModConfigSpec.Builder builder) { // Define properties used by the configuration // ... } //CONFIG and CONFIG_SPEC are both built from the same builder, so we use a static block to seperate the properties static { Pair pair = new ModConfigSpec.Builder().configure(ExampleConfig::new); //Store the resulting values CONFIG = pair.getLeft(); CONFIG_SPEC = pair.getRight(); } ``` -------------------------------- ### Mob Equipment Slot Interaction Source: https://docs.neoforged.net/docs/1.21.5/inventories/container Interacting with a mob's equipment slots, similar to container slots but accessed via EquipmentSlot enums. This example shows how to get, set, and control the drop chance of items in specific equipment slots. ```java // Get the item stack in the HEAD (helmet) slot. ItemStack helmet = mob.getItemBySlot(EquipmentSlot.HEAD); // Put bedrock into the mob's FEET (boots) slot. mob.setItemSlot(EquipmentSlot.FEET, new ItemStack(Items.BEDROCK)); // Enable that bedrock to always drop if the mob is killed. mob.setDropChance(EquipmentSlot.FEET, 1f); ``` -------------------------------- ### Update JSON Format Example Source: https://docs.neoforged.net/docs/1.21.5/misc/updatechecker Defines the structure for the update JSON file, including homepage, version-specific changelogs, and promotional version declarations. ```json { "homepage": "", "": { "": "", "// List all versions of your mod for the given Minecraft version, along with their changelogs" "// ..." }, "promos": { "-latest": "", "// Declare the latest \"bleeding-edge\" version of your mod for the given Minecraft version" "-recommended": "", "// Declare the latest \"stable\" version of your mod for the given Minecraft version" "// ..." } } ``` -------------------------------- ### Creating PlacementInfo from Optional Ingredients Source: https://docs.neoforged.net/docs/1.21.5/resources/server/recipes/custom This example demonstrates how to create a `PlacementInfo` object using `PlacementInfo.createFromOptionals`. This is useful when a recipe might contain empty slots or when ingredient states are not fully determined at recipe creation time. The `placementInfo()` method delegates to this creation logic, handling potential delays in tag and recipe loading. ```java public class RightClickBlockRecipe implements Recipe { // other stuff here private PlacementInfo info; @Override public PlacementInfo placementInfo() { // This delegate is in case the ingredient is not fully populated at this point in time // Tags and recipes are loaded at the same time, which is why this might be the case. if (this.info == null) { // Use optional ingredient as the block state may have an item representation List> ingredients = new ArrayList<>(); Item stateItem = this.inputState.getBlock().asItem(); ingredients.add(stateItem != Items.AIR ? Optional.of(Ingredient.of(stateItem)): Optional.empty()); ingredients.add(Optional.of(this.inputItem)); // Create placement info this.info = PlacementInfo.createFromOptionals(ingredients); } return this.info; } } ``` -------------------------------- ### Example Item Model Provider Source: https://docs.neoforged.net/docs/1.21.5/resources/client/models/datagen Demonstrates how to create a custom `ModelProvider` to register item models. This includes generating flat items and more complex bow-like items with conditional models based on usage. ```java public class ExampleModelProvider extends ModelProvider { public ExampleModelProvider(PackOutput output) { // Replace "examplemod" with your own mod id. super(output, "examplemod"); } @Override protected void registerModels(BlockModelGenerators blockModels, ItemModelGenerators itemModels) { // The most common item // item/generated with the layer0 texture as the item name itemModels.generateFlatItem(MyItemsClass.EXAMPLE_ITEM.get(), ModelTemplates.FLAT_ITEM); // A bow-like item ItemModel.Unbaked bow = ItemModelUtils.plainModel(ModelLocationUtils.getModelLocation(MyItemsClass.EXAMPLE_ITEM.get())); ItemModel.Unbaked pullingBow0 = ItemModelUtils.plainModel(this.createFlatItemModel(MyItemsClass.EXAMPLE_ITEM.get(), "_pulling_0", ModelTemplates.BOW)); ItemModel.Unbaked pullingBow1 = ItemModelUtils.plainModel(this.createFlatItemModel(MyItemsClass.EXAMPLE_ITEM.get(), "_pulling_1", ModelTemplates.BOW)); ItemModel.Unbaked pullingBow2 = ItemModelUtils.plainModel(this.createFlatItemModel(MyItemsClass.EXAMPLE_ITEM.get(), "_pulling_2", ModelTemplates.BOW)); this.itemModelOutput.accept( MyItemsClass.EXAMPLE_ITEM.get(), // Conditional model for item ItemModelUtils.conditional( // Checks if item is being used ItemModelUtils.isUsingItem(), // When true, select model based on use duration ItemModelUtils.rangeSelect( new UseDuration(false), // Scalar to apply to the thresholds 0.05F, pullingBow0, // Threshold when 0.65 ItemModelUtils.override(pullingBow1, 0.65F), // Threshold when 0.9 ItemModelUtils.override(pullingBow2, 0.9F) ), // When false, use the base bow model bow ) ); } } ``` -------------------------------- ### Example ModelProvider Implementation Source: https://docs.neoforged.net/docs/1.21.5/resources/client/models/datagen This is a basic implementation of ModelProvider for generating block models. Replace 'examplemod' with your mod ID. It demonstrates the constructor and the registerModels method. ```java public class ExampleModelProvider extends ModelProvider { public ExampleModelProvider(PackOutput output) { // Replace "examplemod" with your own mod id. super(output, "examplemod"); } @Override protected void registerModels(BlockModelGenerators blockModels, ItemModelGenerators itemModels) { // Placeholders, their usages should be replaced with real values. See above for how to use the model builder, // and below for the helpers the model builder offers. Block block = MyBlocksClass.EXAMPLE_BLOCK.get(); // Create a simple block model with the same texture on each side. // The texture must be located at assets//textures/block/.png, where // and are the block's registry name's namespace and path, respectively. // Used by the majority of (full) blocks, such as planks, cobblestone or bricks. blockModels.createTrivialCube(block); // Overload that accepts a `TexturedModel.Provider` to use. blockModels.createTrivialBlock(block, EXAMPLE_TEMPLATE_PROVIDER); // Block items have a model generated automatically // But let's assume you want to generate a different item, such as a flat item blockModels.registerSimpleFlatItemModel(block); // Adds a log block model. Requires two textures at assets//textures/block/.png and // assets//textures/block/_top.png, referencing the side and top texture, respectively. // Note that the block input here is limited to RotatedPillarBlock, which is the class vanilla logs use. blockModels.woodProvider(block).log(block); // Like WoodProvider#logWithHorizontal. Used by quartz pillars and similar blocks. blockModels.createRotatedPillarWithHorizontalVariant(block, TexturedModel.COLUMN_ALT, TexturedModel.COLUMN_HORIZONTAL_ALT); // Using the `ExtendedModelTemplate` to specify the render type to use. blockModels.createRotatedPillarWithHorizontalVariant(block, TexturedModel.COLUMN_ALT.updateTemplate(template -> template.extend().renderType("minecraft:cutout").build() ), TexturedModel.COLUMN_HORIZONTAL_ALT.updateTemplate(template -> template.extend().renderType(this.mcLocation("cutout_mipped")).build() ) ); // Specifies a horizontally-rotatable block model with a side texture, a front texture, and a top texture. // The bottom will use the side texture as well. If you don't need the front or top texture, // just pass in the side texture twice. Used by e.g. furnaces and similar blocks. blockModels.createHorizontallyRotatedBlock( block, TexturedModel.Provider.ORIENTABLE_ONLY_TOP.updateTexture(mapping -> mapping.put(TextureSlot.SIDE, this.modLocation("block/example_texture_side")) .put(TextureSlot.FRONT, this.modLocation("block/example_texture_front")) .put(TextureSlot.TOP, this.modLocation("block/example_texture_top")) ) ); // Specifies a horizontally-rotatable block model that is attached to a face, e.g. for buttons. // Accounts for placing the block on the ground and on the ceiling, and rotates them accordingly. blockModels.familyWithExistingFullBlock(block).button(block); // Create a model to use for blockstatefiles ResourceLocation modelLoc = TexturedModel.CUBE.create(block, blockModels.modelOutput); // Create a common variant to transform Variant variant = new Variant(modelLoc); // Basic single variant model blockModels.blockStateOutput.accept( MultiVariantGenerator.dispatch( block, new MultiVariant( WeightedList.of( new Weighted<>( // Set model variant // Set rotations around the x and y axes ``` -------------------------------- ### Java quickMoveStack Implementation Example Source: https://docs.neoforged.net/docs/1.21.5/gui/menus This Java code demonstrates the implementation of the quickMoveStack method for handling item stack movements within a GUI menu. It includes logic for moving items between the data inventory, player inventory, and hotbar. ```java // Assume we have a data inventory of size 5 // The inventory has 4 inputs (index 1 - 4) which outputs to a result slot (index 0) // We also have the 27 player inventory slots and the 9 hotbar slots // As such, the actual slots are indexed like so: // - Data Inventory: Result (0), Inputs (1 - 4) // - Player Inventory (5 - 31) // - Player Hotbar (32 - 40) @Override public ItemStack quickMoveStack(Player player, int quickMovedSlotIndex) { // The quick moved slot stack ItemStack quickMovedStack = ItemStack.EMPTY; // The quick moved slot Slot quickMovedSlot = this.slots.get(quickMovedSlotIndex); // If the slot is in the valid range and the slot is not empty if (quickMovedSlot != null && quickMovedSlot.hasItem()) { // Get the raw stack to move ItemStack rawStack = quickMovedSlot.getItem(); // Set the slot stack to a copy of the raw stack quickMovedStack = rawStack.copy(); /* The following quick move logic can be simplified to if in data inventory, try to move to player inventory/hotbar and vice versa for containers that cannot transform data (e.g. chests). */ // If the quick move was performed on the data inventory result slot if (quickMovedSlotIndex == 0) { // Try to move the result slot into the player inventory/hotbar if (!this.moveItemStackTo(rawStack, 5, 41, true)) { // If cannot move, no longer quick move return ItemStack.EMPTY; } // Perform logic on result slot quick move quickMovedSlot.onQuickCraft(rawStack, quickMovedStack); } // Else if the quick move was performed on the player inventory or hotbar slot else if (quickMovedSlotIndex >= 5 && quickMovedSlotIndex < 41) { // Try to move the inventory/hotbar slot into the data inventory input slots if (!this.moveItemStackTo(rawStack, 1, 5, false)) { // If cannot move and in player inventory slot, try to move to hotbar if (quickMovedSlotIndex < 32) { if (!this.moveItemStackTo(rawStack, 32, 41, false)) { // If cannot move, no longer quick move return ItemStack.EMPTY; } } // Else try to move hotbar into player inventory slot else if (!this.moveItemStackTo(rawStack, 5, 32, false)) { // If cannot move, no longer quick move return ItemStack.EMPTY; } } } // Else if the quick move was performed on the data inventory input slots, try to move to player inventory/hotbar else if (!this.moveItemStackTo(rawStack, 5, 41, false)) { // If cannot move, no longer quick move return ItemStack.EMPTY; } if (rawStack.isEmpty()) { // If the raw stack has completely moved out of the slot, set the slot to the empty stack quickMovedSlot.set(ItemStack.EMPTY); } else { // Otherwise, notify the slot that that the stack count has changed quickMovedSlot.setChanged(); } // Execute logic on what to do post move with the remaining stack // This can be removed if there are no `Slot` subtypes that override `onTake` quickMovedSlot.onTake(player, rawStack); } return quickMovedStack; // Return the slot stack } ``` -------------------------------- ### Example Mod Properties Configuration Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Illustrates how to define properties for different mods using TOML syntax. This is useful when a mod file defines multiple mods with distinct metadata. ```toml # Assume we have two mods `mod1` and `mod2` with the following property configuration # [[modproperties.mod1]] # # key="value1" # # [[modproperties.mod2]] # # key="value2" ``` -------------------------------- ### ContainerData Menu Access Example Source: https://docs.neoforged.net/docs/1.21.5/gui/menus Demonstrates the client and server-side constructors for a menu that utilizes ContainerData to synchronize multiple integers. It shows how to initialize ContainerData and add data slots. ```java public MyMenuAccess(int containerId, Inventory playerInventory) { this(containerId, playerInventory, new SimpleContainerData(3)); } public MyMenuAccess(int containerId, Inventory playerInventory, ContainerData dataMultiple) { checkContainerDataCount(dataMultiple, 3); this.addDataSlots(dataMultiple); } ``` -------------------------------- ### Server Initialization for Right Click Recipes Source: https://docs.neoforged.net/docs/1.21.5/resources/server/recipes/custom Handles the registration of the server-side input listener and provides access to the current recipe inputs. This class is responsible for setting up the necessary components for the custom crafting mechanic on the server. ```java public class ServerRightClickBlockRecipes { private static ServerRightClickBlockRecipeInputs inputs; public static RightClickBlockRecipeInputs inputs() { return ServerRightClickBlockRecipes.inputs; } @SubscribeEvent // on the game event bus public static void addListener(AddReloadListenerEvent event) { // Register server reload listener ServerRightClickBlockRecipes.inputs = new ServerRightClickBlockRecipeInputs( event.getServerResources().getRecipeManager() ); event.addListener(ServerRightClickBlockRecipes.inputs); } @SubscribeEvent // on the game event bus public static void datapackSync(OnDatapackSyncEvent event) { // Send to client ``` -------------------------------- ### ExampleHolder Codec and StreamCodec Source: https://docs.neoforged.net/docs/1.21.5/items/datacomponents This example demonstrates how to define a Codec and a StreamCodec for an ExampleHolder class, which includes integer data and a DataComponentPatch. The Codec is used for disk persistence, while the StreamCodec is for network transfer. The constructor applies the patch to an empty DataComponentMap. ```java public class ExampleHolder implements MutableDataComponentHolder { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.INT.fieldOf("data").forGetter(ExampleHolder::getData), DataCopmonentPatch.CODEC.optionalFieldOf("components", DataComponentPatch.EMPTY).forGetter(holder -> holder.components.asPatch()) ).apply(instance, ExampleHolder::new) ); public static final StreamCodec STREAM_CODEC = StreamCodec.composite( ByteBufCodecs.INT, ExampleHolder::getData, DataComponentPatch.STREAM_CODEC, holder -> holder.components.asPatch(), ExampleHolder::new ); // ... public ExampleHolder(int data, DataComponentPatch patch) { this.data = data; this.components = PatchedDataComponentMap.fromPatch( // The prototype map to apply to DataComponentMap.EMPTY, // The associated patches patch ); } // ... } ``` -------------------------------- ### Gradle Parallel Execution Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of disabling parallel execution for Gradle projects. ```properties org.gradle.parallel=false ``` -------------------------------- ### Menu Initialization with Slots and DataSlots Source: https://docs.neoforged.net/docs/1.21.5/gui/menus Illustrates server and client menu constructors that add item handler slots and data slots for synchronization. ```java // Assume we have an inventory from a data object of size 5 // Assume we have a DataSlot constructed on each initialization of the server menu // Client menu constructor public MyMenuAccess(int containerId, Inventory playerInventory) { this(containerId, playerInventory, new ItemStackHandler(5), DataSlot.standalone()); } // Server menu constructor public MyMenuAccess(int containerId, Inventory playerInventory, IItemHandler dataInventory, DataSlot dataSingle) { // Check if the data inventory size is some fixed value // Then, add slots for data inventory this.addSlot(new SlotItemHandler(dataInventory, /*...*/)); // Add slots for player inventory this.addSlot(new Slot(playerInventory, /*...*/)); // Add data slots for handled integers this.addDataSlot(dataSingle); // ... } ``` -------------------------------- ### Example `sounds.json` Structure Source: https://docs.neoforged.net/docs/1.21.5/resources/client/sounds This snippet demonstrates the basic structure of a `sounds.json` file, mapping sound event IDs to sound objects. It shows how to define multiple sounds for an event, with options for random selection, and how to reference sound files. ```json { // Sound definition for the sound event "examplemod:my_sound" "my_sound": { // List of sound objects. If this contains more than one element, an element will be chosen randomly. "sounds": [ // Only name is required, all other properties are optional. { // Location of the sound file, relative to the namespace's sounds folder. // This example references a sound at assets/examplemod/sounds/sound_1.ogg. "name": "examplemod:sound_1", // May be "sound" or "event". "sound" causes the name to refer to a sound file. // "event" causes the name to refer to another sound event. Defaults to "sound". "type": "sound", // The volume this sound will be played at. Must be between 0.0 and 1.0 (default). "volume": 0.8, // The pitch value the sound will be played at. // Must be between 0.0 and 2.0. Defaults to 1.0. "pitch": 1.1, // Weight of this sound when choosing a sound from the sounds list. Defaults to 1. "weight": 3, // If true, the sound will be streamed from the file instead of loaded all at once. // Recommended for sound files that are more than a few seconds long. Defaults to false. "stream": true, // Manual override for the attenuation distance. Defaults to 16. Ignored by fixed range sound events. "attenuation_distance": 8, // If true, the sound will be loaded into memory on pack load, instead of when the sound is played. // Vanilla uses this for underwater ambience sounds. Defaults to false. "preload": true }, // Shortcut for { "name": "examplemod:sound_2" } "examplemod:sound_2" ] }, "my_fixed_sound": { // Optional. If true, replaces sounds from other resource packs instead of adding to them. // See the Merging chapter below for more information. "replace": true, // The translation key of the subtitle displayed when this sound event is triggered. "subtitle": "examplemod.my_fixed_sound", "sounds": [ "examplemod:sound_1", "examplemod:sound_2" ] } } ``` -------------------------------- ### Creating an Advancement Builder Source: https://docs.neoforged.net/docs/1.21.5/resources/server/advancements Demonstrates how to start building an advancement using Advancement.Builder. It shows the initial step of creating a builder instance and enabling telemetry. ```java // All methods follow the builder pattern, meaning that chaining is possible and encouraged. // For better readability of the explanations, chaining will not be done here. // Create an advancement builder using the static #advancement() method. // Using #advancement() automatically enables telemetry events. If you do not want this, // #recipeAdvancement() can be used instead, there are no other functional differences. Advancement.Builder builder = Advancement.Builder.advancement(); ``` -------------------------------- ### Mod Group ID Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of setting the group ID for the mod, typically the top-level package. ```properties mod_group_id=com.example.examplemod ``` -------------------------------- ### Example Environment Definition JSON Source: https://docs.neoforged.net/docs/1.21.5/misc/gametest A JSON file defining a specific instance of the 'example_environment_type'. This configuration is used to set up a test environment with custom parameters. ```json // examplemod:example_environment // In 'data/examplemod/test_environment/example_environment.json' { "type": "examplemod:example_environment_type", "value1": 0, "value2": true } ``` -------------------------------- ### Encoded Recursive Object Example Source: https://docs.neoforged.net/docs/1.21.5/datastorage/codecs An example of how a recursive object is encoded, showing nested 'inner' fields. ```json { "inner": { "inner": {} } } ``` -------------------------------- ### Gradle Debug Mode Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/modfiles Example of disabling Gradle debug mode, which primarily affects log output. ```properties org.gradle.debug=false ``` -------------------------------- ### Unique Package Structure Example Source: https://docs.neoforged.net/docs/1.21.5/gettingstarted/structuring Illustrates how distinct JAR files can contain classes with the same name if they are in different packages. It highlights the potential conflict if packages are identical, leading to only one class being loaded. ```text a.jar - com.example.ExampleClass b.jar - com.example.ExampleClass // This class will not normally be loaded ``` -------------------------------- ### Get Data Component from ItemStack Source: https://docs.neoforged.net/docs/1.21.5/items/datacomponents Retrieves a data component from an ItemStack, delegating to DataComponentMap#get. Returns null if the component is not present. ```java // For some ItemStack stack // Delegates to 'DataComponentMap#get' @Nullable DyeColor color = stack.get(DataComponents.BASE_COLOR); ``` -------------------------------- ### Example Biome Modifier Implementation Source: https://docs.neoforged.net/docs/1.21.5/worldgen/biomemodifier An example of a custom BiomeModifier implementation in Java, demonstrating the modify and codec methods. This is used to define how a biome is altered. ```java public record ExampleBiomeModifier(HolderSet biomes, int value) implements BiomeModifier { @Override public void modify(Holder biome, Phase phase, ModifiableBiomeInfo.BiomeInfo.Builder builder) { if (phase == /* Pick the phase that best matches what your want to modify */) { // Modify the 'builder', checking any information about the biome itself } } @Override public MapCodec codec() { return EXAMPLE_BIOME_MODIFIER.get(); } } // In some registration class private static final DeferredRegister> BIOME_MODIFIERS = DeferredRegister.create(NeoForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, MOD_ID); public static final Supplier> EXAMPLE_BIOME_MODIFIER = BIOME_MODIFIERS.register("example_biome_modifier", () -> RecordCodecBuilder.mapCodec(instance -> instance.group( Biome.LIST_CODEC.fieldOf("biomes").forGetter(ExampleBiomeModifier::biomes), Codec.INT.fieldOf("value").forGetter(ExampleBiomeModifier::value) ).apply(instance, ExampleBiomeModifier::new) )); ``` -------------------------------- ### Creating a KeyMapping with Conflict Context Source: https://docs.neoforged.net/docs/1.21.5/misc/keymappings Create a KeyMapping with a specific conflict context, input type, input code, and category. This example uses the GUI context and a mouse input. ```java new KeyMapping( "key.examplemod.example2", KeyConflictContext.GUI, // Mapping can only be used when a screen is open InputConstants.Type.MOUSE, // Default mapping is on the mouse GLFW.GLFW_MOUSE_BUTTON_LEFT, // Default mouse input is the left mouse button "key.categories.examplemod.examplecategory" // Mapping will be in the new example category ) ``` -------------------------------- ### Dispatch Codec Encoded Examples Source: https://docs.neoforged.net/docs/1.21.5/datastorage/codecs Examples of encoded objects using a dispatch codec, showing differences based on whether the codec is augmented from MapCodec. ```json { "type": "string", // For StringObject "value": "value" // Codec type is not augmented from MapCodec, needs field } // Complex object { "type": "complex", // For ComplexObject // Codec type is augmented from MapCodec, can be inlined "s": "value", "i": 0 } ``` -------------------------------- ### Create or Get SavedData Instance Source: https://docs.neoforged.net/docs/1.21.5/datastorage/saveddata Use computeIfAbsent on DimensionDataStorage to get an existing SavedData instance or create a new one. This method requires a SavedDataType ID. ```java netherDataStorage.computeIfAbsent(ContextExampleSavedData.ID); ``` -------------------------------- ### Configuring Food Properties for an Item Source: https://docs.neoforged.net/docs/1.21.5/items/consumables Example of setting up a food item using FoodProperties.Builder. This configures nutrition, saturation, and whether the food can always be eaten. Use this when creating custom food items. ```java // Assume there is some DeferredRegister.Items ITEMS public static final DeferredItem FOOD = ITEMS.registerSimpleItem( "food", new Item.Properties().food( new FoodProperties.Builder() // Heals 1.5 hearts .nutrition(3) // Carrot is 0.3 // Raw Cod is 0.1 // Cooked Chicken is 0.6 // Cooked Beef is 0.8 // Golden Aple is 1.2 .saturationModifier(0.3f) // When set, the food can alway be eaten even with // a full hunger bar. .alwaysEdible() ) ); ``` -------------------------------- ### Put and Get Nested CompoundTag Source: https://docs.neoforged.net/docs/1.21.5/datastorage/nbt Shows how to embed a CompoundTag within another CompoundTag using put and get methods. getCompoundOrEmpty is used for safe retrieval. ```java tag.put("Tag", new CompoundTag()); // Can use regular `get` as well if you want to handle null case instead tag.getCompoundOrEmpty("Tag"); ``` -------------------------------- ### Menu Access Constructors Source: https://docs.neoforged.net/docs/1.21.5/gui/menus Demonstrates server and client-side constructors for menu access, utilizing ContainerLevelAccess. ```java // Client menu constructor public MyMenuAccess(int containerId, Inventory playerInventory) { this(containerId, playerInventory, ContainerLevelAccess.NULL); } // Server menu constructor public MyMenuAccess(int containerId, Inventory playerInventory, ContainerLevelAccess access) { // ... } // Assume this menu is attached to Supplier MY_BLOCK @Override public boolean stillValid(Player player) { return AbstractContainerMenu.stillValid(this.access, player, MY_BLOCK.get()); } ``` -------------------------------- ### Remove Features Biome Modifier Datagen Example Source: https://docs.neoforged.net/docs/1.21.5/worldgen/biomemodifier Implement the 'remove_features' biome modifier using Java datagen. This example shows how to define a modifier to remove diamond ore from overworld biomes. ```java // Define the ResourceKey for our BiomeModifier. public static final ResourceKey REMOVE_FEATURES_EXAMPLE = ResourceKey.create( NeoForgeRegistries.Keys.BIOME_MODIFIERS, // The registry this key is for ResourceLocation.fromNamespaceAndPath(MOD_ID, "remove_features_example") // The registry name ); // BUILDER is a RegistrySetBuilder passed to DatapackBuiltinEntriesProvider // in a listener for the `GatherDataEvent`s. BUILDER.add(NeoForgeRegistries.Keys.BIOME_MODIFIERS, bootstrap -> { // Lookup any necessary registries. // Static registries only need to be looked up if you need to grab the tag data. HolderGetter biomes = bootstrap.lookup(Registries.BIOME); HolderGetter placedFeatures = bootstrap.lookup(Registries.PLACED_FEATURE); // Register the biome modifiers. bootstrap.register(REMOVE_FEATURES_EXAMPLE, new RemoveFeaturesBiomeModifier( // The biome(s) to remove from biomes.getOrThrow(Tags.Biomes.IS_OVERWORLD), // The feature(s) to remove from the biomes HolderSet.direct(placedFeatures.getOrThrow(OrePlacements.ORE_DIAMOND)), // The generation steps to remove from Set.of( GenerationStep.Decoration.LOCAL_MODIFICATIONS, GenerationStep.Decoration.UNDERGROUND_ORES ) ) ); }); ``` -------------------------------- ### Open Menu with SimpleMenuProvider Source: https://docs.neoforged.net/docs/1.21.5/gui/menus Opens a custom menu for a player on the server using `SimpleMenuProvider`. This is a common way to initiate a menu interaction. ```java // In some implementation with access to the Player on the logical server (e.g. ServerPlayer instance) // Assume we have ServerPlayer serverPlayer serverPlayer.openMenu(new SimpleMenuProvider( (containerId, playerInventory, player) -> new MyMenu(containerId, playerInventory), Component.translatable("menu.title.examplemod.mymenu") )); ```