Bladeren bron

Close #18 Currently testing item / block addition, keybinds and creative tabs.

shedaniel 4 jaren geleden
bovenliggende
commit
9c6101835d
30 gewijzigde bestanden met toevoegingen van 431 en 41 verwijderingen
  1. 13 4
      build.gradle
  2. 1 2
      common/build.gradle
  3. 19 0
      common/src/main/java/me/shedaniel/architectury/core/AbstractRecipeSerializer.java
  4. 2 1
      common/src/main/java/me/shedaniel/architectury/event/events/client/ClientPlayerEvent.java
  5. 9 0
      common/src/main/java/me/shedaniel/architectury/registry/RegistrySupplier.java
  6. 13 11
      fabric/build.gradle
  7. 1 3
      fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinMinecraft.java
  8. 10 6
      forge/build.gradle
  9. 19 0
      forge/src/main/java/me/shedaniel/architectury/mixin/forge/MixinAbstractRecipeSerializer.java
  10. 19 0
      forge/src/main/java/me/shedaniel/architectury/plugin/forge/ArchitecturyMixinPlugin.java
  11. 1 1
      gradle/wrapper/gradle-wrapper.properties
  12. 0 0
      logs/latest.log
  13. 3 0
      settings.gradle
  14. 12 0
      testmod-common/build.gradle
  15. 42 0
      testmod-common/src/main/java/me/shedaniel/architectury/test/TestMod.java
  16. 1 1
      testmod-common/src/main/java/me/shedaniel/architectury/test/debug/ConsoleMessageSink.java
  17. 10 6
      testmod-common/src/main/java/me/shedaniel/architectury/test/debug/DebugEvents.java
  18. 1 1
      testmod-common/src/main/java/me/shedaniel/architectury/test/debug/MessageSink.java
  19. 8 5
      testmod-common/src/main/java/me/shedaniel/architectury/test/debug/client/ClientOverlayMessageSink.java
  20. 49 0
      testmod-common/src/main/java/me/shedaniel/architectury/test/registry/TestRegistries.java
  21. 43 0
      testmod-common/src/main/java/me/shedaniel/architectury/test/registry/client/TestKeybinds.java
  22. 32 0
      testmod-common/src/main/java/me/shedaniel/architectury/test/tab/TestCreativeTabs.java
  23. 4 0
      testmod-common/src/main/resources/assets/architectury-test/lang/en_us.json
  24. 30 0
      testmod-fabric/build.gradle
  25. 0 0
      testmod-fabric/src/main/resources/fabric.mod.json
  26. 36 0
      testmod-forge/build.gradle
  27. 1 0
      testmod-forge/gradle.properties
  28. 32 0
      testmod-forge/src/main/java/me/shedaniel/architectury/test/TestModForge.java
  29. 14 0
      testmod-forge/src/main/resources/META-INF/mods.toml
  30. 6 0
      testmod-forge/src/main/resources/pack.mcmeta

+ 13 - 4
build.gradle

@@ -1,6 +1,6 @@
 plugins {
-    id "architectury-plugin" version "1.3.47"
-    id "forgified-fabric-loom" version "0.5.30" apply false
+    id "architectury-plugin" version "2.0.57"
+    id "forgified-fabric-loom" version "0.6.47" apply false
     id "org.cadixdev.licenser" version "0.5.0"
     id "com.jfrog.bintray" version "1.8.4"
     id "com.matthewprenger.cursegradle" version "1.4.0" apply false
@@ -15,8 +15,9 @@ architectury {
 subprojects {
     apply plugin: "forgified-fabric-loom"
 
-    dependencies {
-        testCompile sourceSets.main.output
+    loom {
+        silentMojangMappingsLicense()
+        useFabricMixin = true
     }
 }
 
@@ -31,6 +32,14 @@ allprojects {
 
     tasks.withType(JavaCompile) {
         options.encoding = "UTF-8"
+
+        // The Minecraft launcher currently installs Java 8 for users, so your mod probably wants to target Java 8 too
+        // JDK 9 introduced a new way of specifying this that will make sure no newer classes or methods are used.
+        // We'll use that if it's available, but otherwise we'll use the older option.
+        def targetVersion = 8
+        if (JavaVersion.current().isJava9Compatible()) {
+            options.release = targetVersion
+        }
     }
 
     license {

+ 1 - 2
common/build.gradle

@@ -1,10 +1,9 @@
 loom {
     accessWidener = file("src/main/resources/architectury.accessWidener")
-    silentMojangMappingsLicense()
 }
 
 dependencies {
-    minecraft "com.mojang:minecraft:${rootProject.architect.minecraft}"
+    minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
     mappings minecraft.officialMojangMappings()
     // We depend on fabric loader here to use the fabric @Environment annotations
     // Do NOT use other classes from fabric loader

+ 19 - 0
common/src/main/java/me/shedaniel/architectury/core/AbstractRecipeSerializer.java

@@ -1,3 +1,22 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
 package me.shedaniel.architectury.core;
 
 import net.minecraft.world.item.crafting.Recipe;

+ 2 - 1
common/src/main/java/me/shedaniel/architectury/event/events/client/ClientPlayerEvent.java

@@ -24,6 +24,7 @@ import me.shedaniel.architectury.event.EventFactory;
 import net.fabricmc.api.EnvType;
 import net.fabricmc.api.Environment;
 import net.minecraft.client.player.LocalPlayer;
+import org.jetbrains.annotations.Nullable;
 
 @Environment(EnvType.CLIENT)
 public interface ClientPlayerEvent {
@@ -38,7 +39,7 @@ public interface ClientPlayerEvent {
     
     @Environment(EnvType.CLIENT)
     interface ClientPlayerQuit {
-        void quit(LocalPlayer player);
+        void quit(@Nullable LocalPlayer player);
     }
     
     @Environment(EnvType.CLIENT)

+ 9 - 0
common/src/main/java/me/shedaniel/architectury/registry/RegistrySupplier.java

@@ -29,12 +29,21 @@ import java.util.function.Supplier;
 import java.util.stream.Stream;
 
 public interface RegistrySupplier<T> extends Supplier<T> {
+    /**
+     * @return the identifier of the registry
+     */
     @NotNull
     ResourceLocation getRegistryId();
     
+    /**
+     * @return the identifier of the entry
+     */
     @NotNull
     ResourceLocation getId();
     
+    /**
+     * @return whether the entry has been registered
+     */
     boolean isPresent();
     
     @Nullable

+ 13 - 11
fabric/build.gradle

@@ -10,12 +10,16 @@ plugins {
 }
 
 loom {
-    accessWidener(file("src/main/resources/architectury.accessWidener"))
-    silentMojangMappingsLicense()
+    accessWidener = file("src/main/resources/architectury.accessWidener")
 }
 
 configurations {
     shadow
+    dev
+}
+
+artifacts {
+    dev(jar)
 }
 
 architectury {
@@ -23,25 +27,23 @@ architectury {
 }
 
 dependencies {
-    minecraft("com.mojang:minecraft:${rootProject.architect.minecraft}")
-    mappings(minecraft.officialMojangMappings())
-    modCompile("net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}")
-    modCompile("net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}")
-    modCompileOnly("io.github.prospector:modmenu:${rootProject.mod_menu_version}")
+    minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
+    mappings minecraft.officialMojangMappings()
+    modCompile "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
+    modCompile "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
+    modCompileOnly "io.github.prospector:modmenu:${rootProject.mod_menu_version}"
     implementation "net.jodah:typetools:0.6.2"
     shadow "net.jodah:typetools:0.6.2"
 
     compileOnly(project(path: ":common")) {
         transitive = false
     }
-    runtimeOnly(project(path: ":common", configuration: "transformed")) {
+    runtimeOnly(project(path: ":common", configuration: "transformDevelopmentFabric")) {
         transitive = false
     }
-    shadow(project(path: ":common", configuration: "transformed")) {
+    shadow(project(path: ":common", configuration: "transformProductionFabric")) {
         transitive = false
     }
-
-    testCompile project(":common").sourceSets.test.output
 }
 
 processResources {

+ 1 - 3
fabric/src/main/java/me/shedaniel/architectury/mixin/fabric/client/MixinMinecraft.java

@@ -44,9 +44,7 @@ public class MixinMinecraft {
     @Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V",
             at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/chat/NarratorChatListener;clear()V"))
     private void handleLogin(Screen screen, CallbackInfo ci) {
-        if (player != null) {
-            ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player);
-        }
+        ClientPlayerEvent.CLIENT_PLAYER_QUIT.invoker().quit(player);
     }
     
     @Inject(method = "startUseItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z", ordinal = 1),

+ 10 - 6
forge/build.gradle

@@ -4,12 +4,16 @@ plugins {
 }
 
 loom {
-    silentMojangMappingsLicense()
     mixinConfig = "architectury.mixins.json"
 }
 
 configurations {
     shadow
+    dev
+}
+
+artifacts {
+    dev(jar)
 }
 
 architectury {
@@ -17,19 +21,19 @@ architectury {
 }
 
 dependencies {
-    minecraft("com.mojang:minecraft:${rootProject.architect.minecraft}")
-    mappings(minecraft.officialMojangMappings())
-    forge("net.minecraftforge:forge:${rootProject.architect.minecraft}-${rootProject.forge_version}")
+    minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
+    mappings loom.officialMojangMappings()
+    forge "net.minecraftforge:forge:${rootProject.architectury.minecraft}-${rootProject.forge_version}"
     implementation "net.jodah:typetools:0.6.2"
     shadow "net.jodah:typetools:0.6.2"
 
     compileOnly(project(path: ":common")) {
         transitive = false
     }
-    runtimeOnly(project(path: ":common", configuration: "transformForgeFakeMod")) {
+    runtimeOnly(project(path: ":common", configuration: "transformDevelopmentForge")) {
         transitive = false
     }
-    shadow(project(path: ":common", configuration: "transformForge")) {
+    shadow(project(path: ":common", configuration: "transformProductionForge")) {
         transitive = false
     }
 }

+ 19 - 0
forge/src/main/java/me/shedaniel/architectury/mixin/forge/MixinAbstractRecipeSerializer.java

@@ -1,3 +1,22 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
 package me.shedaniel.architectury.mixin.forge;
 
 import me.shedaniel.architectury.core.AbstractRecipeSerializer;

+ 19 - 0
forge/src/main/java/me/shedaniel/architectury/plugin/forge/ArchitecturyMixinPlugin.java

@@ -1,3 +1,22 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
 package me.shedaniel.architectury.plugin.forge;
 
 import org.objectweb.asm.Opcodes;

+ 1 - 1
gradle/wrapper/gradle-wrapper.properties

@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists

+ 0 - 0
logs/latest.log


+ 3 - 0
settings.gradle

@@ -11,5 +11,8 @@ pluginManagement {
 include("common")
 include("fabric")
 include("forge")
+include("testmod-common")
+include("testmod-fabric")
+include("testmod-forge")
 
 rootProject.name = "architectury"

+ 12 - 0
testmod-common/build.gradle

@@ -0,0 +1,12 @@
+dependencies {
+    minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
+    mappings loom.officialMojangMappings()
+    // We depend on fabric loader here to use the fabric @Environment annotations
+    // Do NOT use other classes from fabric loader
+    modCompile "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
+    implementation project(":common")
+}
+
+architectury {
+    common()
+}

+ 42 - 0
testmod-common/src/main/java/me/shedaniel/architectury/test/TestMod.java

@@ -0,0 +1,42 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.test;
+
+import me.shedaniel.architectury.platform.Platform;
+import me.shedaniel.architectury.test.debug.ConsoleMessageSink;
+import me.shedaniel.architectury.test.debug.DebugEvents;
+import me.shedaniel.architectury.test.debug.MessageSink;
+import me.shedaniel.architectury.test.debug.client.ClientOverlayMessageSink;
+import me.shedaniel.architectury.test.registry.TestRegistries;
+import me.shedaniel.architectury.test.registry.client.TestKeybinds;
+import me.shedaniel.architectury.utils.Env;
+import me.shedaniel.architectury.utils.EnvExecutor;
+
+public class TestMod {
+    public static final MessageSink SINK = EnvExecutor.getEnvSpecific(() -> ClientOverlayMessageSink::new, () -> ConsoleMessageSink::new);
+    public static final String MOD_ID = "architectury-test";
+    
+    public static void initialize() {
+        DebugEvents.initialize();
+        TestRegistries.initialize();
+        if (Platform.getEnvironment() == Env.CLIENT)
+            TestKeybinds.initialize();
+    }
+}

+ 1 - 1
common/src/test/java/me/shedaniel/architectury/test/ConsoleMessageSink.java → testmod-common/src/main/java/me/shedaniel/architectury/test/debug/ConsoleMessageSink.java

@@ -17,7 +17,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-package me.shedaniel.architectury.test;
+package me.shedaniel.architectury.test.debug;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;

+ 10 - 6
common/src/test/java/me/shedaniel/architectury/test/TestMod.java → testmod-common/src/main/java/me/shedaniel/architectury/test/debug/DebugEvents.java

@@ -17,7 +17,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-package me.shedaniel.architectury.test;
+package me.shedaniel.architectury.test.debug;
 
 import com.mojang.blaze3d.platform.InputConstants;
 import me.shedaniel.architectury.event.events.*;
@@ -27,7 +27,9 @@ import me.shedaniel.architectury.event.events.client.ClientLifecycleEvent;
 import me.shedaniel.architectury.event.events.client.ClientPlayerEvent;
 import me.shedaniel.architectury.hooks.ExplosionHooks;
 import me.shedaniel.architectury.platform.Platform;
-import me.shedaniel.architectury.test.client.ClientOverlayMessageSink;
+import me.shedaniel.architectury.test.debug.client.ClientOverlayMessageSink;
+import me.shedaniel.architectury.test.debug.ConsoleMessageSink;
+import me.shedaniel.architectury.test.debug.MessageSink;
 import me.shedaniel.architectury.utils.Env;
 import me.shedaniel.architectury.utils.EnvExecutor;
 import net.fabricmc.api.EnvType;
@@ -44,9 +46,9 @@ import net.minecraft.world.level.Level;
 
 import java.util.Optional;
 
-public class TestMod {
-    public static final MessageSink SINK = EnvExecutor.getEnvSpecific(() -> ClientOverlayMessageSink::new, () -> ConsoleMessageSink::new);
-    
+import static me.shedaniel.architectury.test.TestMod.SINK;
+
+public class DebugEvents {
     public static void initialize() {
         debugEvents();
         if (Platform.getEnvironment() == Env.CLIENT)
@@ -203,7 +205,9 @@ public class TestMod {
             SINK.accept(player.getScoreboardName() + " joined (client)");
         });
         ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> {
-            SINK.accept(player.getScoreboardName() + " quit (client)");
+            if (player != null) {
+                SINK.accept(player.getScoreboardName() + " quit (client)");
+            }
         });
         ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.register((oldPlayer, newPlayer) -> {
             SINK.accept(newPlayer.getScoreboardName() + " respawned (client)");

+ 1 - 1
common/src/test/java/me/shedaniel/architectury/test/MessageSink.java → testmod-common/src/main/java/me/shedaniel/architectury/test/debug/MessageSink.java

@@ -17,7 +17,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-package me.shedaniel.architectury.test;
+package me.shedaniel.architectury.test.debug;
 
 public interface MessageSink {
     void accept(String message);

+ 8 - 5
common/src/test/java/me/shedaniel/architectury/test/client/ClientOverlayMessageSink.java → testmod-common/src/main/java/me/shedaniel/architectury/test/debug/client/ClientOverlayMessageSink.java

@@ -17,13 +17,13 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  */
 
-package me.shedaniel.architectury.test.client;
+package me.shedaniel.architectury.test.debug.client;
 
 import com.google.common.collect.Lists;
 import com.mojang.blaze3d.systems.RenderSystem;
 import com.mojang.blaze3d.vertex.PoseStack;
 import me.shedaniel.architectury.event.events.GuiEvent;
-import me.shedaniel.architectury.test.ConsoleMessageSink;
+import me.shedaniel.architectury.test.debug.ConsoleMessageSink;
 import net.fabricmc.api.EnvType;
 import net.fabricmc.api.Environment;
 import net.minecraft.Util;
@@ -57,6 +57,8 @@ public class ClientOverlayMessageSink extends ConsoleMessageSink {
     }
     
     public void render(PoseStack matrices, float delta) {
+        matrices.pushPose();
+        matrices.scale(0.5f, 0.5f, 1f);
         Minecraft minecraft = Minecraft.getInstance();
         long currentMills = Util.getMillis();
         int lineHeight = minecraft.font.lineHeight;
@@ -64,13 +66,13 @@ public class ClientOverlayMessageSink extends ConsoleMessageSink {
         synchronized (messages) {
             Iterator<Message> messageIterator = messages.iterator();
             int y = 1;
-    
+            
             RenderSystem.enableBlend();
-    
+            
             while (messageIterator.hasNext()) {
                 Message message = messageIterator.next();
                 int timeExisted = (int) (currentMills - message.created);
-        
+                
                 if (timeExisted >= 5000) {
                     messageIterator.remove();
                 } else {
@@ -87,6 +89,7 @@ public class ClientOverlayMessageSink extends ConsoleMessageSink {
         
         RenderSystem.disableAlphaTest();
         RenderSystem.disableBlend();
+        matrices.popPose();
     }
     
     private static class Message {

+ 49 - 0
testmod-common/src/main/java/me/shedaniel/architectury/test/registry/TestRegistries.java

@@ -0,0 +1,49 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.test.registry;
+
+import me.shedaniel.architectury.registry.BlockProperties;
+import me.shedaniel.architectury.registry.DeferredRegister;
+import me.shedaniel.architectury.registry.RegistrySupplier;
+import me.shedaniel.architectury.test.TestMod;
+import me.shedaniel.architectury.test.tab.TestCreativeTabs;
+import net.minecraft.core.Registry;
+import net.minecraft.world.item.BlockItem;
+import net.minecraft.world.item.Item;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.Blocks;
+
+public class TestRegistries {
+    public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(TestMod.MOD_ID, Registry.ITEM_REGISTRY);
+    public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(TestMod.MOD_ID, Registry.BLOCK_REGISTRY);
+    
+    public static final RegistrySupplier<Item> TEST_ITEM = ITEMS.register("test_item", () ->
+            new Item(new Item.Properties().tab(TestCreativeTabs.TEST_TAB)));
+    
+    public static final RegistrySupplier<Block> TEST_BLOCK = BLOCKS.register("test_block", () ->
+            new Block(BlockProperties.copy(Blocks.STONE)));
+    public static final RegistrySupplier<Item> TEST_BLOCK_ITEM = ITEMS.register("test_block", () ->
+            new BlockItem(TEST_BLOCK.get(), new Item.Properties().tab(TestCreativeTabs.TEST_TAB)));
+    
+    public static void initialize() {
+        BLOCKS.register();
+        ITEMS.register();
+    }
+}

+ 43 - 0
testmod-common/src/main/java/me/shedaniel/architectury/test/registry/client/TestKeybinds.java

@@ -0,0 +1,43 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.test.registry.client;
+
+import com.mojang.blaze3d.platform.InputConstants;
+import me.shedaniel.architectury.event.events.client.ClientTickEvent;
+import me.shedaniel.architectury.registry.KeyBindings;
+import me.shedaniel.architectury.test.TestMod;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.KeyMapping;
+import net.minecraft.client.resources.language.I18n;
+import org.lwjgl.glfw.GLFW;
+
+public class TestKeybinds {
+    @Environment(EnvType.CLIENT)
+    public static void initialize() {
+        KeyMapping mapping = new KeyMapping("key.architectury-test.test", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_O, "category.architectury-test");
+        KeyBindings.registerKeyBinding(mapping);
+        ClientTickEvent.CLIENT_POST.register(instance -> {
+            while (mapping.consumeClick()) {
+                TestMod.SINK.accept("Key \"%s\" pressed!", I18n.get("key.architectury-test.test"));
+            }
+        });
+    }
+}

+ 32 - 0
testmod-common/src/main/java/me/shedaniel/architectury/test/tab/TestCreativeTabs.java

@@ -0,0 +1,32 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.test.tab;
+
+import me.shedaniel.architectury.registry.CreativeTabs;
+import me.shedaniel.architectury.test.TestMod;
+import me.shedaniel.architectury.test.registry.TestRegistries;
+import net.minecraft.resources.ResourceLocation;
+import net.minecraft.world.item.CreativeModeTab;
+import net.minecraft.world.item.ItemStack;
+
+public class TestCreativeTabs {
+    public static final CreativeModeTab TEST_TAB = CreativeTabs.create(new ResourceLocation(TestMod.MOD_ID, "test_tab"),
+            () -> new ItemStack(TestRegistries.TEST_ITEM.get()));
+}

+ 4 - 0
testmod-common/src/main/resources/assets/architectury-test/lang/en_us.json

@@ -0,0 +1,4 @@
+{
+  "category.architectury-test": "Architectury Test",
+  "key.architectury-test.test": "Test Keybind"
+}

+ 30 - 0
testmod-fabric/build.gradle

@@ -0,0 +1,30 @@
+plugins {
+    id "com.github.johnrengelman.shadow" version "5.0.0"
+    id "com.matthewprenger.cursegradle"
+}
+
+architectury {
+    platformSetupLoomIde()
+}
+
+dependencies {
+    minecraft "com.mojang:minecraft:${rootProject.architectury.minecraft}"
+    mappings loom.officialMojangMappings()
+    modCompile "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
+    modCompile "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
+    modCompileOnly "io.github.prospector:modmenu:${rootProject.mod_menu_version}"
+
+    implementation project(path: ":fabric", configuration: "dev")
+    compileOnly(project(path: ":common")) {
+        transitive = false
+    }
+    runtimeOnly(project(path: ":common", configuration: "transformDevelopmentFabric")) {
+        transitive = false
+    }
+    compileOnly(project(path: ":testmod-common")) {
+        transitive = false
+    }
+    runtimeOnly(project(path: ":testmod-common", configuration: "transformDevelopmentFabric")) {
+        transitive = false
+    }
+}

+ 0 - 0
common/src/test/resources/fabric.mod.json → testmod-fabric/src/main/resources/fabric.mod.json


+ 36 - 0
testmod-forge/build.gradle

@@ -0,0 +1,36 @@
+plugins {
+    id "com.github.johnrengelman.shadow" version "5.0.0"
+    id "com.matthewprenger.cursegradle"
+}
+
+loom {
+    mixinConfig = "architectury.mixins.json"
+    
+    localMods {
+        it.add(project(":forge").sourceSets.main)
+    }
+}
+
+architectury {
+    platformSetupLoomIde()
+}
+
+dependencies {
+    minecraft "com.mojang:minecraft:${gradle.rootProject.architectury.minecraft}"
+    mappings loom.officialMojangMappings()
+    forge "net.minecraftforge:forge:${gradle.rootProject.architectury.minecraft}-${rootProject.forge_version}"
+
+    implementation project(path: ":forge", configuration: "dev")
+    compileOnly(project(path: ":common")) {
+        transitive = false
+    }
+    runtimeOnly(project(path: ":common", configuration: "transformDevelopmentForge")) {
+        transitive = false
+    }
+    compileOnly(project(path: ":testmod-common")) {
+        transitive = false
+    }
+    runtimeOnly(project(path: ":testmod-common", configuration: "transformDevelopmentForge")) {
+        transitive = false
+    }
+}

+ 1 - 0
testmod-forge/gradle.properties

@@ -0,0 +1 @@
+loom.forge=true

+ 32 - 0
testmod-forge/src/main/java/me/shedaniel/architectury/test/TestModForge.java

@@ -0,0 +1,32 @@
+/*
+ * This file is part of architectury.
+ * Copyright (C) 2020, 2021 shedaniel
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package me.shedaniel.architectury.test;
+
+import me.shedaniel.architectury.platform.forge.EventBuses;
+import net.minecraftforge.fml.common.Mod;
+import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
+
+@Mod(TestMod.MOD_ID)
+public class TestModForge {
+    public TestModForge() {
+        EventBuses.registerModEventBus(TestMod.MOD_ID, FMLJavaModLoadingContext.get().getModEventBus());
+        TestMod.initialize();
+    }
+}

+ 14 - 0
testmod-forge/src/main/resources/META-INF/mods.toml

@@ -0,0 +1,14 @@
+modLoader = "javafml"
+loaderVersion = "[33,)"
+issueTrackerURL = "https://github.com/shedaniel/architectury/issues"
+license = "LGPL-3"
+
+[[mods]]
+modId = "architectury-test"
+version = "${version}"
+displayName = "Architectury Test"
+authors = "shedaniel"
+description = '''
+A intermediary api aimed to ease developing multiplatform mods.
+'''
+license = "LGPL-3"

+ 6 - 0
testmod-forge/src/main/resources/pack.mcmeta

@@ -0,0 +1,6 @@
+{
+  "pack": {
+    "description": "Architectury Test",
+    "pack_format": 6
+  }
+}