From 71537de2223cd59fd73316b853cac657f98b3540 Mon Sep 17 00:00:00 2001 From: Tyler Hancock Date: Tue, 5 Oct 2021 20:28:27 -0600 Subject: [PATCH 1/7] Update Forge to 37.0.82 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d7fd8f3..7aed17c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ common_server_run_name=Common Server # Forge -forge_version=37.0.70 +forge_version=37.0.82 //forge_ats_enabled=true # Fabric From e7368f2468cae62e22a1c42caf08529e64c3a142 Mon Sep 17 00:00:00 2001 From: Tyler Hancock Date: Tue, 5 Oct 2021 20:29:16 -0600 Subject: [PATCH 2/7] Move Constants to com.example.examplemod package. --- .../{blamejared/stuff => example/examplemod}/Constants.java | 4 ++-- Forge/src/main/java/com/example/examplemod/ExampleMod.java | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) rename Common/src/main/java/com/{blamejared/stuff => example/examplemod}/Constants.java (89%) diff --git a/Common/src/main/java/com/blamejared/stuff/Constants.java b/Common/src/main/java/com/example/examplemod/Constants.java similarity index 89% rename from Common/src/main/java/com/blamejared/stuff/Constants.java rename to Common/src/main/java/com/example/examplemod/Constants.java index 4090578..8cd59c5 100644 --- a/Common/src/main/java/com/blamejared/stuff/Constants.java +++ b/Common/src/main/java/com/example/examplemod/Constants.java @@ -1,4 +1,4 @@ -package com.blamejared.stuff; +package com.example.examplemod; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -8,4 +8,4 @@ public class Constants { public static final String MOD_ID = "multiloader"; public static final String MOD_NAME = "MultiLoader"; public static final Logger LOG = LogManager.getLogger(MOD_NAME); -} +} \ No newline at end of file diff --git a/Forge/src/main/java/com/example/examplemod/ExampleMod.java b/Forge/src/main/java/com/example/examplemod/ExampleMod.java index 8d3cd7d..000db9b 100644 --- a/Forge/src/main/java/com/example/examplemod/ExampleMod.java +++ b/Forge/src/main/java/com/example/examplemod/ExampleMod.java @@ -2,8 +2,6 @@ package com.example.examplemod; import java.util.stream.Collectors; -import com.blamejared.stuff.Constants; - import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraftforge.common.MinecraftForge; From 210dc0f8bac58d3c369394383e0ecf8091f1c957 Mon Sep 17 00:00:00 2001 From: Tyler Hancock Date: Tue, 5 Oct 2021 21:36:05 -0600 Subject: [PATCH 3/7] Include a README explaining how to use the template. --- README.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d9bcbfc..11af880 100644 --- a/README.md +++ b/README.md @@ -1 +1,25 @@ -ForgeFabricTogether +# MultiLoader Template + +This project provides a Gradle project template that can compile mods for both Forge and Fabric using a common sourceset. This project does not require any third party libraries or dependencies. + +## Getting Started + +## IntelliJ IDEA +This guide will show how to import the MultiLoader Template into IntelliJ IDEA. The setup process is roughly equivalent to setting up Forge and Fabric independently and should be very familiar to anyone who has worked with their MDKs. + +1. Clone or download this repository to your computer. +2. Configure the project by editing the `group`, `mod_name`, `mod_author`, and `mod_id` properties in the `gradle.properties` file. You will also need to change the `rootProject.name` property in `settings.gradle`. +3. Open the template's root folder as a new project in IDEA. This is the folder that contains this README file and the gradlew executable. +4. If your default JVM/JDK is not Java 16 you will encounter an error when opening the project. This error is fixed by going to `File > Settings > Build, Execution, Deployment > Build Tools > Gradle > Gradle JVM`and changing the value to a valid Java 16 JVM. You will also need to set the Project SDK to Java 16. This can be done by going to `File > Project Structure > Project SDK`. Once both have been set open the Gradle tab in IDEA and click the refresh button to reload the project. +5. Open the Gradle tab in IDEA if it has not already been opened. Navigate to `Your Project > Common > Tasks > vanilla gradle > decompile`. Run this task to decompile Minecraft. +6. Open the Gradle tab in IDEA if it has not already been opened. Navigate to `Your Project > Forge > Tasks > forgegradle runs > genIntellijRuns`. Run this task to set up run configurations for Forge. +7. Open your Run/Debug Configurations. Under the Application category there should now be options to run Forge and Fabric projects. Select one of the client options and try to run it. +8. Assuming you were able to run the game in step 7 your workspace should now be set up. + +### Eclipse +While it is possible to use this template in Eclipse it is not recommended. During the development of this template multiple critical bugs and quirks related to Eclipse were found at nearly every level of the required build tools. While we continue to work with these tools to report and resolve issues support for projects like these are not there yet. For now Eclipse is considered unsupported by this project. The development cycle for build tools is notoriously slow so there are no ETAs available. + +## Development Guide +When using this template the majority of your mod is developed in the Common project. The Common project is compiled against the vanilla game and is used to hold code that is shared between the different loader-specific versions of your mod. The Common project has no knwoledge or access to ModLoader specific code, apis, or concepts. Code that requires something from a specific loader must be done through the project that is specific to that loader, such as the Forge or Fabric project. + +Loader specific projects such as the Forge and Fabric project are used to load the Common project into the game. These projects also define code that is specific to that loader. Loader specific projects can access all of the code in the Common project. It is important to remember that the Common project can not access code from loader specific projects. \ No newline at end of file From f445322f61ee5832e0fed65843673f1195742ab0 Mon Sep 17 00:00:00 2001 From: Tyler Hancock Date: Tue, 5 Oct 2021 21:46:10 -0600 Subject: [PATCH 4/7] Move all System.out to Constants.LOG --- .../main/java/com/example/examplemod/CommonClass.java | 7 +++---- .../main/java/com/example/examplemod/ExampleMod.java | 5 ++--- .../com/example/examplemod/mixin/ExampleMixin.java | 10 +++++----- .../main/java/com/example/examplemod/ExampleMod.java | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Common/src/main/java/com/example/examplemod/CommonClass.java b/Common/src/main/java/com/example/examplemod/CommonClass.java index 45ee5cd..eca7b0c 100644 --- a/Common/src/main/java/com/example/examplemod/CommonClass.java +++ b/Common/src/main/java/com/example/examplemod/CommonClass.java @@ -7,8 +7,7 @@ public class CommonClass { public static void init() { - System.out.println("Hello from Common init!"); - System.out.println("Diamond Item >> " + Registry.ITEM.getKey(Items.DIAMOND)); + Constants.LOG.info("Hello from Common init!"); + Constants.LOG.info("Diamond Item >> {}", Registry.ITEM.getKey(Items.DIAMOND)); } - -} +} \ No newline at end of file diff --git a/Fabric/src/main/java/com/example/examplemod/ExampleMod.java b/Fabric/src/main/java/com/example/examplemod/ExampleMod.java index 6a949ef..5d2e28f 100644 --- a/Fabric/src/main/java/com/example/examplemod/ExampleMod.java +++ b/Fabric/src/main/java/com/example/examplemod/ExampleMod.java @@ -9,9 +9,8 @@ public class ExampleMod implements ModInitializer { // This code runs as soon as Minecraft is in a mod-load-ready state. // However, some things (like resources) may still be uninitialized. // Proceed with mild caution. - - System.out.println("Hello Fabric world!"); + + Constants.LOG.info("Hello Fabric world!"); CommonClass.init(); } - } diff --git a/Fabric/src/main/java/com/example/examplemod/mixin/ExampleMixin.java b/Fabric/src/main/java/com/example/examplemod/mixin/ExampleMixin.java index e2b2650..cd8beb0 100644 --- a/Fabric/src/main/java/com/example/examplemod/mixin/ExampleMixin.java +++ b/Fabric/src/main/java/com/example/examplemod/mixin/ExampleMixin.java @@ -1,5 +1,6 @@ package com.example.examplemod.mixin; +import com.example.examplemod.Constants; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.TitleScreen; import org.spongepowered.asm.mixin.Mixin; @@ -13,9 +14,8 @@ public class ExampleMixin { @Inject(at = @At("HEAD"), method = "init()V") private void init(CallbackInfo info) { - System.out.println("This line is printed by an example mod mixin!"); - System.out.println(Minecraft.getInstance().getVersionType()); - System.out.println(this.getClass().getClassLoader()); + Constants.LOG.info("This line is printed by an example mod mixin from Fabric!"); + Constants.LOG.info("MC Version: {}", Minecraft.getInstance().getVersionType()); + Constants.LOG.info("Classloader: {}", this.getClass().getClassLoader()); } - -} +} \ No newline at end of file diff --git a/Forge/src/main/java/com/example/examplemod/ExampleMod.java b/Forge/src/main/java/com/example/examplemod/ExampleMod.java index 000db9b..397cfc4 100644 --- a/Forge/src/main/java/com/example/examplemod/ExampleMod.java +++ b/Forge/src/main/java/com/example/examplemod/ExampleMod.java @@ -66,4 +66,4 @@ public class ExampleMod { } -} +} \ No newline at end of file From 509dda3840e21b247d295ac8609c018720f5e5c2 Mon Sep 17 00:00:00 2001 From: Tyler Hancock Date: Tue, 5 Oct 2021 22:33:10 -0600 Subject: [PATCH 5/7] Cleaned up example code, and added more relevant examples and documentation. --- .../com/example/examplemod/CommonClass.java | 27 +++++++ .../com/example/examplemod/ExampleMod.java | 15 ++-- .../com/example/examplemod/ExampleMod.java | 70 +++++-------------- 3 files changed, 55 insertions(+), 57 deletions(-) diff --git a/Common/src/main/java/com/example/examplemod/CommonClass.java b/Common/src/main/java/com/example/examplemod/CommonClass.java index eca7b0c..f5659ad 100644 --- a/Common/src/main/java/com/example/examplemod/CommonClass.java +++ b/Common/src/main/java/com/example/examplemod/CommonClass.java @@ -1,13 +1,40 @@ package com.example.examplemod; import net.minecraft.core.Registry; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.food.FoodProperties; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.TooltipFlag; + +import java.util.List; public class CommonClass { + // This method serves as an initialization hook for the mod. The vanilla + // game has no mechanism to load tooltip listeners so this must be + // invoked from a mod loader specific project like Forge or Fabric. public static void init() { Constants.LOG.info("Hello from Common init!"); Constants.LOG.info("Diamond Item >> {}", Registry.ITEM.getKey(Items.DIAMOND)); } + + // This method serves as a hook to modify item tooltips. The vanilla game + // has no mechanism to load tooltip listeners so this must be registered + // by a mod loader like Forge or Fabric. + public static void onItemTooltip(ItemStack stack, TooltipFlag context, List tooltip) { + + if (!stack.isEmpty()) { + + final FoodProperties food = stack.getItem().getFoodProperties(); + + if (food != null) { + + tooltip.add(new TextComponent("Nutrition: " + food.getNutrition())); + tooltip.add(new TextComponent("Saturation: " + food.getSaturationModifier())); + } + } + } } \ No newline at end of file diff --git a/Fabric/src/main/java/com/example/examplemod/ExampleMod.java b/Fabric/src/main/java/com/example/examplemod/ExampleMod.java index 5d2e28f..9dddb74 100644 --- a/Fabric/src/main/java/com/example/examplemod/ExampleMod.java +++ b/Fabric/src/main/java/com/example/examplemod/ExampleMod.java @@ -1,16 +1,23 @@ package com.example.examplemod; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; public class ExampleMod implements ModInitializer { @Override public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. - + + // This method is invoked by the Fabric mod loader when it is ready + // to load your mod. You can access Fabric and Common code in this + // project. + + // Use Fabric to bootstrap the Common mod. Constants.LOG.info("Hello Fabric world!"); CommonClass.init(); + + // Some code like events require special initialization from the + // loader specific code. + ItemTooltipCallback.EVENT.register(CommonClass::onItemTooltip); } } diff --git a/Forge/src/main/java/com/example/examplemod/ExampleMod.java b/Forge/src/main/java/com/example/examplemod/ExampleMod.java index 397cfc4..22d578d 100644 --- a/Forge/src/main/java/com/example/examplemod/ExampleMod.java +++ b/Forge/src/main/java/com/example/examplemod/ExampleMod.java @@ -1,69 +1,33 @@ package com.example.examplemod; -import java.util.stream.Collectors; - -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.RegistryEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.InterModComms; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent; -import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.fmlserverevents.FMLServerStartingEvent; @Mod(Constants.MOD_ID) public class ExampleMod { public ExampleMod() { - - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::enqueueIMC); - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::processIMC); - - MinecraftForge.EVENT_BUS.register(this); - } - private void setup(final FMLCommonSetupEvent event) { - - Constants.LOG.info("HELLO FROM PREINIT"); - Constants.LOG.info("DIRT BLOCK >> {}", Blocks.DIRT.getRegistryName()); + // This method is invoked by the Forge mod loader when it is ready + // to load your mod. You can access Forge and Common code in this + // project. + + // Use Forge to bootstrap the Common mod. + Constants.LOG.info("Hello Forge world!"); CommonClass.init(); - } - private void enqueueIMC(final InterModEnqueueEvent event) { - - InterModComms.sendTo("examplemod", "helloworld", () -> { - Constants.LOG.info("Hello world from the MDK"); - return "Hello world"; - }); - } - - private void processIMC(final InterModProcessEvent event) { - - Constants.LOG.info("Got IMC {}", event.getIMCStream() - .map(m -> m.messageSupplier().get()) - .collect(Collectors.toList())); - } - - @SubscribeEvent - public void onServerStarting(FMLServerStartingEvent event) { - - Constants.LOG.info("HELLO from server starting"); - } - - @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) - public static class RegistryEvents { - - @SubscribeEvent - public static void onBlocksRegistry(final RegistryEvent.Register blockRegistryEvent) { - // register a new block here - Constants.LOG.info("HELLO from Register Block"); - } + // Some code like events require special initialization from the + // loader specific code. + MinecraftForge.EVENT_BUS.addListener(this::onItemTooltip); } + // This method exists as a wrapper for the code in the Common project. + // It takes Forge's event object and passes the parameters along to + // the Common listener. + private void onItemTooltip(ItemTooltipEvent event) { + + CommonClass.onItemTooltip(event.getItemStack(), event.getFlags(), event.getToolTip()); + } } \ No newline at end of file From 299a8d52d990ceccdc482623af43dfd508ec3818 Mon Sep 17 00:00:00 2001 From: Tyler Hancock Date: Tue, 5 Oct 2021 23:01:09 -0600 Subject: [PATCH 6/7] Make Forge run names similar to the Common and Fabric ones. --- Forge/build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Forge/build.gradle b/Forge/build.gradle index 93aa82a..f1434ac 100644 --- a/Forge/build.gradle +++ b/Forge/build.gradle @@ -28,6 +28,7 @@ minecraft { client { workingDirectory project.file('run') ideaModule "${rootProject.name}.${project.name}.main" + taskName 'Client' mods { modClientRun { source sourceSets.main @@ -39,6 +40,7 @@ minecraft { server { workingDirectory project.file('run') ideaModule "${rootProject.name}.${project.name}.main" + taskName 'Server' mods { modServerRun { source sourceSets.main @@ -51,6 +53,7 @@ minecraft { workingDirectory project.file('run') ideaModule "${rootProject.name}.${project.name}.main" args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + taskName 'Data' mods { modDataRun { source sourceSets.main From 5cdbd1b0109bc0ab9232e9bef2e8264f7ec661ae Mon Sep 17 00:00:00 2001 From: Tyler Hancock Date: Tue, 5 Oct 2021 23:02:14 -0600 Subject: [PATCH 7/7] Remove JAR manifest entries from Forge project as this is handled in the root build.gradle. --- Forge/build.gradle | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Forge/build.gradle b/Forge/build.gradle index f1434ac..8ab190f 100644 --- a/Forge/build.gradle +++ b/Forge/build.gradle @@ -78,21 +78,6 @@ tasks.withType(JavaCompile) { source(project(":Common").sourceSets.main.allSource) } -jar { - - manifest { - attributes([ - "Specification-Title" : mod_name, - "Specification-Vendor" : mod_author, - "Specification-Version" : "1", - "Implementation-Title" : project.name, - "Implementation-Version" : project.jar.archiveVersion, - "Implementation-Vendor" : mod_author, - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } -} - jar.finalizedBy('reobfJar') publishing {