From f8cf2bb4361832b435d7202b1a13cd8d9a404fa6 Mon Sep 17 00:00:00 2001
From: i509VCB <git@i509.me>
Date: Tue, 19 Jan 2021 12:48:09 -0600
Subject: [PATCH] Add custom value denoting module lifecycles.  (#1253)

* Add custom value denoting module lifecycles.

* Make the module validation work.

My hand has been forced - we must use buildSrc since JsonSlurper is not available in main buildscript.

* Apply task to each project and dont cross projects

* A horrible hack

* Wait what

* It works now.

* Not needed

* Drop unneeded maven repo, cache map lookup

(cherry picked from commit daa38b3d8212614c0ab4f4436695acff567d3fb9)
---
 build.gradle                                  |   4 +
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   3 +
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   3 +
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   3 +
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 .../src/main/resources/fabric.mod.json        |   5 +-
 gradle/module-validation.gradle               |  61 ++++++
 gradle/wrapper/gradle-wrapper.jar             | Bin 58694 -> 59203 bytes
 gradle/wrapper/gradle-wrapper.properties      |   2 +-
 gradlew                                       |   2 +
 gradlew.bat                                   | 192 ++++++++----------
 47 files changed, 318 insertions(+), 142 deletions(-)
 create mode 100644 gradle/module-validation.gradle

diff --git a/build.gradle b/build.gradle
index 0787bf22f..2564cb39f 100644
--- a/build.gradle
+++ b/build.gradle
@@ -180,6 +180,10 @@ allprojects {
 	}
 }
 
+// Apply auxiliary buildscripts to submodules
+// This must be done after all plugins are applied to subprojects
+apply from: "gradle/module-validation.gradle"
+
 javadoc {
 	options {
 		source = "8"
diff --git a/fabric-api-base/src/main/resources/fabric.mod.json b/fabric-api-base/src/main/resources/fabric.mod.json
index 4ce576766..7fda5d59f 100644
--- a/fabric-api-base/src/main/resources/fabric.mod.json
+++ b/fabric-api-base/src/main/resources/fabric.mod.json
@@ -18,5 +18,8 @@
   "depends": {
     "fabricloader": ">=0.4.0"
   },
-  "description": "Contains the essentials for Fabric API modules."
+  "description": "Contains the essentials for Fabric API modules.",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-biome-api-v1/src/main/resources/fabric.mod.json b/fabric-biome-api-v1/src/main/resources/fabric.mod.json
index 7f9984e6b..21c70d68f 100644
--- a/fabric-biome-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-biome-api-v1/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "mixins": [
     "fabric-biome-api-v1.mixins.json"
   ],
-  "accessWidener" : "fabric-biome-api-v1.accesswidener"
+  "accessWidener" : "fabric-biome-api-v1.accesswidener",
+  "custom": {
+    "fabric-api:module-lifecycle": "experimental"
+  }
 }
diff --git a/fabric-blockrenderlayer-v1/src/main/resources/fabric.mod.json b/fabric-blockrenderlayer-v1/src/main/resources/fabric.mod.json
index 036a3c431..12ec985b7 100644
--- a/fabric-blockrenderlayer-v1/src/main/resources/fabric.mod.json
+++ b/fabric-blockrenderlayer-v1/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "description": "Registration utility for block and fluid render layers.",
   "mixins": [
     "fabric-blockrenderlayer-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-command-api-v1/src/main/resources/fabric.mod.json b/fabric-command-api-v1/src/main/resources/fabric.mod.json
index 64a43e5b7..1d996428f 100644
--- a/fabric-command-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-command-api-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Adds command-related hooks.",
   "mixins": [
     "fabric-command-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-commands-v0/src/main/resources/fabric.mod.json b/fabric-commands-v0/src/main/resources/fabric.mod.json
index 8048ade7c..7f401a491 100644
--- a/fabric-commands-v0/src/main/resources/fabric.mod.json
+++ b/fabric-commands-v0/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   },
   "description": "Deprecated. Please migrate to v1",
   "mixins": [
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-containers-v0/src/main/resources/fabric.mod.json b/fabric-containers-v0/src/main/resources/fabric.mod.json
index 765b3500e..76281ce45 100644
--- a/fabric-containers-v0/src/main/resources/fabric.mod.json
+++ b/fabric-containers-v0/src/main/resources/fabric.mod.json
@@ -29,5 +29,8 @@
     "client": [
       "net.fabricmc.fabric.impl.client.container.ScreenProviderRegistryImpl::init"
     ]
+  },
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
   }
 }
diff --git a/fabric-content-registries-v0/src/main/resources/fabric.mod.json b/fabric-content-registries-v0/src/main/resources/fabric.mod.json
index b7486229b..d25c1c7d9 100644
--- a/fabric-content-registries-v0/src/main/resources/fabric.mod.json
+++ b/fabric-content-registries-v0/src/main/resources/fabric.mod.json
@@ -24,5 +24,8 @@
   "description": "Adds registries for vanilla mechanics that are missing them.",
   "mixins": [
     "fabric-content-registries-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-crash-report-info-v1/src/main/resources/fabric.mod.json b/fabric-crash-report-info-v1/src/main/resources/fabric.mod.json
index 53df27ffb..2d6add287 100644
--- a/fabric-crash-report-info-v1/src/main/resources/fabric.mod.json
+++ b/fabric-crash-report-info-v1/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Adds Fabric-related debug info to crash reports.",
   "mixins": [
     "fabric-crash-report-info-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-dimensions-v1/src/main/resources/fabric.mod.json b/fabric-dimensions-v1/src/main/resources/fabric.mod.json
index 2a8c87e39..6a6606b1f 100644
--- a/fabric-dimensions-v1/src/main/resources/fabric.mod.json
+++ b/fabric-dimensions-v1/src/main/resources/fabric.mod.json
@@ -12,5 +12,8 @@
   },
   "mixins": [
     "fabric-dimensions-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "experimental"
+  }
 }
diff --git a/fabric-entity-events-v1/src/main/resources/fabric.mod.json b/fabric-entity-events-v1/src/main/resources/fabric.mod.json
index 5df554aab..ea5ce0a4a 100644
--- a/fabric-entity-events-v1/src/main/resources/fabric.mod.json
+++ b/fabric-entity-events-v1/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Events to hook into entities.",
   "mixins": [
     "fabric-entity-events-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-events-interaction-v0/src/main/resources/fabric.mod.json b/fabric-events-interaction-v0/src/main/resources/fabric.mod.json
index 94a7c7f11..85cc9baae 100644
--- a/fabric-events-interaction-v0/src/main/resources/fabric.mod.json
+++ b/fabric-events-interaction-v0/src/main/resources/fabric.mod.json
@@ -31,5 +31,8 @@
   "description": "Events for player interaction with blocks and entities.",
   "mixins": [
     "fabric-events-interaction-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-events-lifecycle-v0/src/main/resources/fabric.mod.json b/fabric-events-lifecycle-v0/src/main/resources/fabric.mod.json
index 7eb6a935f..5630ecba6 100644
--- a/fabric-events-lifecycle-v0/src/main/resources/fabric.mod.json
+++ b/fabric-events-lifecycle-v0/src/main/resources/fabric.mod.json
@@ -29,5 +29,8 @@
     "fabric-item-api-v1": "*",
     "fabric-lifecycle-events-v1": "*"
   },
-  "description": "Legacy events for the game's lifecycle, superseded by fabric-lifecycle-events-v1 and fabric-item-api-v1."
+  "description": "Legacy events for the game's lifecycle, superseded by fabric-lifecycle-events-v1 and fabric-item-api-v1.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-game-rule-api-v1/src/main/resources/fabric.mod.json b/fabric-game-rule-api-v1/src/main/resources/fabric.mod.json
index 3d7f814be..a1e909b53 100644
--- a/fabric-game-rule-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-game-rule-api-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "mixins": [
     "fabric-game-rule-api-v1.mixins.json"
   ],
-  "accessWidener" : "fabric-game-rule-api-v1.accesswidener"
+  "accessWidener" : "fabric-game-rule-api-v1.accesswidener",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-item-api-v1/src/main/resources/fabric.mod.json b/fabric-item-api-v1/src/main/resources/fabric.mod.json
index 111fe5731..6a2e17f7c 100644
--- a/fabric-item-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-item-api-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
     "fabricloader": ">=0.4.0",
     "fabric-api-base": "*"
   },
-  "description": "Hooks for items"
+  "description": "Hooks for items",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-item-groups-v0/src/main/resources/fabric.mod.json b/fabric-item-groups-v0/src/main/resources/fabric.mod.json
index 74ce83e75..9e60fb649 100644
--- a/fabric-item-groups-v0/src/main/resources/fabric.mod.json
+++ b/fabric-item-groups-v0/src/main/resources/fabric.mod.json
@@ -24,5 +24,8 @@
   "description": "An API for adding custom item groups.",
   "mixins": [
     "fabric-item-groups-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-key-binding-api-v1/src/main/resources/fabric.mod.json b/fabric-key-binding-api-v1/src/main/resources/fabric.mod.json
index c7fe5b4ff..db552fc70 100644
--- a/fabric-key-binding-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-key-binding-api-v1/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Key Binding registry API.",
   "mixins": [
     "fabric-key-binding-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-keybindings-v0/src/main/resources/fabric.mod.json b/fabric-keybindings-v0/src/main/resources/fabric.mod.json
index a6c01bfaf..c35c67374 100644
--- a/fabric-keybindings-v0/src/main/resources/fabric.mod.json
+++ b/fabric-keybindings-v0/src/main/resources/fabric.mod.json
@@ -19,5 +19,8 @@
     "fabricloader": ">=0.4.0",
     "fabric-key-binding-api-v1": "*"
   },
-  "description": "Keybinding registry API."
+  "description": "Keybinding registry API.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-lifecycle-events-v1/src/main/resources/fabric.mod.json b/fabric-lifecycle-events-v1/src/main/resources/fabric.mod.json
index 724aa33a8..05ce7a7f7 100644
--- a/fabric-lifecycle-events-v1/src/main/resources/fabric.mod.json
+++ b/fabric-lifecycle-events-v1/src/main/resources/fabric.mod.json
@@ -30,5 +30,8 @@
     "fabricloader": ">=0.4.0",
     "fabric-api-base": "*"
   },
-  "description": "Events for the game's lifecycle."
+  "description": "Events for the game's lifecycle.",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-loot-tables-v1/src/main/resources/fabric.mod.json b/fabric-loot-tables-v1/src/main/resources/fabric.mod.json
index 597b845d2..ecd00ec3c 100644
--- a/fabric-loot-tables-v1/src/main/resources/fabric.mod.json
+++ b/fabric-loot-tables-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks for manipulating loot tables.",
   "mixins": [
     "fabric-loot-tables-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-mining-levels-v0/src/main/resources/fabric.mod.json b/fabric-mining-levels-v0/src/main/resources/fabric.mod.json
index bbf95ced2..c7bfd8097 100644
--- a/fabric-mining-levels-v0/src/main/resources/fabric.mod.json
+++ b/fabric-mining-levels-v0/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
     "fabric-tag-extensions-v0": "*",
     "fabric-tool-attribute-api-v1": "*"
   },
-  "description": "Block mining level tags for tools. Deprecated and replaced by fabric-tool-attribute-v1."
+  "description": "Block mining level tags for tools. Deprecated and replaced by fabric-tool-attribute-v1.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-models-v0/src/main/resources/fabric.mod.json b/fabric-models-v0/src/main/resources/fabric.mod.json
index c66ff4e10..93a4b284b 100644
--- a/fabric-models-v0/src/main/resources/fabric.mod.json
+++ b/fabric-models-v0/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks for models and model loading.",
   "mixins": [
     "fabric-models-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-networking-api-v1/src/main/resources/fabric.mod.json b/fabric-networking-api-v1/src/main/resources/fabric.mod.json
index 0e2b09bc5..4264185e7 100644
--- a/fabric-networking-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-networking-api-v1/src/main/resources/fabric.mod.json
@@ -30,5 +30,8 @@
   "description": "Low-level, vanilla protocol oriented networking hooks.",
   "mixins": [
     "fabric-networking-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-networking-blockentity-v0/src/main/resources/fabric.mod.json b/fabric-networking-blockentity-v0/src/main/resources/fabric.mod.json
index 3a3a27891..e41cbd094 100644
--- a/fabric-networking-blockentity-v0/src/main/resources/fabric.mod.json
+++ b/fabric-networking-blockentity-v0/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Networking hooks for block entities.",
   "mixins": [
     "fabric-networking-blockentity-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-networking-v0/src/main/resources/fabric.mod.json b/fabric-networking-v0/src/main/resources/fabric.mod.json
index b5c186463..081e30da0 100644
--- a/fabric-networking-v0/src/main/resources/fabric.mod.json
+++ b/fabric-networking-v0/src/main/resources/fabric.mod.json
@@ -28,5 +28,8 @@
     "fabric-api-base": "*",
     "fabric-networking-api-v1": "*"
   },
-  "description": "Legacy Networking packet hooks and registries, superseded by fabric-networking-api-v1."
+  "description": "Legacy Networking packet hooks and registries, superseded by fabric-networking-api-v1.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json b/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json
index 744ae1bc6..6f07272be 100644
--- a/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-object-builder-api-v1/src/main/resources/fabric.mod.json
@@ -24,5 +24,8 @@
   "mixins": [
     "fabric-object-builder-v1.mixins.json"
   ],
-  "accessWidener" : "fabric-object-builder-api-v1.accesswidener"
+  "accessWidener" : "fabric-object-builder-api-v1.accesswidener",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-object-builders-v0/src/main/resources/fabric.mod.json b/fabric-object-builders-v0/src/main/resources/fabric.mod.json
index e4da46d34..f3a301595 100644
--- a/fabric-object-builders-v0/src/main/resources/fabric.mod.json
+++ b/fabric-object-builders-v0/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "description": "Legacy builders for objects vanilla has locked down, superseded by fabric-object-builder-api-v1.",
   "mixins": [
     "fabric-object-builders-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-particles-v1/src/main/resources/fabric.mod.json b/fabric-particles-v1/src/main/resources/fabric.mod.json
index 62ac00ca2..b6fcf47e4 100644
--- a/fabric-particles-v1/src/main/resources/fabric.mod.json
+++ b/fabric-particles-v1/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Hooks for registering custom particles.",
   "mixins": [
     "fabric-particles-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-registry-sync-v0/src/main/resources/fabric.mod.json b/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
index c4917633e..c57dea4b7 100644
--- a/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
+++ b/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
@@ -31,5 +31,8 @@
     "client": [
       "net.fabricmc.fabric.impl.registry.sync.FabricRegistryClientInit"
     ]
+  },
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
   }
 }
diff --git a/fabric-renderer-api-v1/src/main/resources/fabric.mod.json b/fabric-renderer-api-v1/src/main/resources/fabric.mod.json
index 501a70e68..61e4f8592 100644
--- a/fabric-renderer-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-renderer-api-v1/src/main/resources/fabric.mod.json
@@ -24,5 +24,8 @@
   "mixins": [
     "fabric-renderer-api-v1.mixins.json",
     "fabric-renderer-api-v1.debughud.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-renderer-indigo/src/main/resources/fabric.mod.json b/fabric-renderer-indigo/src/main/resources/fabric.mod.json
index cc58f9fb1..f8a08d113 100755
--- a/fabric-renderer-indigo/src/main/resources/fabric.mod.json
+++ b/fabric-renderer-indigo/src/main/resources/fabric.mod.json
@@ -29,5 +29,8 @@
     "client": [
       "net.fabricmc.fabric.impl.client.indigo.Indigo"
     ]
+  },
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
   }
 }
diff --git a/fabric-renderer-registries-v1/src/main/resources/fabric.mod.json b/fabric-renderer-registries-v1/src/main/resources/fabric.mod.json
index 16a0173c1..2ed23dcb8 100644
--- a/fabric-renderer-registries-v1/src/main/resources/fabric.mod.json
+++ b/fabric-renderer-registries-v1/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "description": "Registries for entity and block renderers.",
   "mixins": [
     "fabric-renderer-registries-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-rendering-data-attachment-v1/src/main/resources/fabric.mod.json b/fabric-rendering-data-attachment-v1/src/main/resources/fabric.mod.json
index ccc4e8e39..362f2c0b5 100644
--- a/fabric-rendering-data-attachment-v1/src/main/resources/fabric.mod.json
+++ b/fabric-rendering-data-attachment-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Thread-safe hooks for block entity data use during terrain rendering.",
   "mixins": [
     "fabric-rendering-data-attachment-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-rendering-fluids-v1/src/main/resources/fabric.mod.json b/fabric-rendering-fluids-v1/src/main/resources/fabric.mod.json
index 5708d98a6..e0705bbcb 100644
--- a/fabric-rendering-fluids-v1/src/main/resources/fabric.mod.json
+++ b/fabric-rendering-fluids-v1/src/main/resources/fabric.mod.json
@@ -25,5 +25,8 @@
   "description": "Hooks for registering fluid renders.",
   "mixins": [
     "fabric-rendering-fluids-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-rendering-v0/src/main/resources/fabric.mod.json b/fabric-rendering-v0/src/main/resources/fabric.mod.json
index 0290e6039..3a9d8eef4 100644
--- a/fabric-rendering-v0/src/main/resources/fabric.mod.json
+++ b/fabric-rendering-v0/src/main/resources/fabric.mod.json
@@ -26,5 +26,8 @@
     "fabric-api-base": "*",
     "fabric-rendering-v1": "*"
   },
-  "description": "Hooks and registries for rendering-related things."
+  "description": "Hooks and registries for rendering-related things.",
+  "custom": {
+    "fabric-api:module-lifecycle": "deprecated"
+  }
 }
diff --git a/fabric-rendering-v1/src/main/resources/fabric.mod.json b/fabric-rendering-v1/src/main/resources/fabric.mod.json
index 5b21b99b5..a17c8cd5c 100644
--- a/fabric-rendering-v1/src/main/resources/fabric.mod.json
+++ b/fabric-rendering-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks and registries for rendering-related things.",
   "mixins": [
     "fabric-rendering-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json
index 291900737..60c01dfbe 100644
--- a/fabric-resource-loader-v0/src/main/resources/fabric.mod.json
+++ b/fabric-resource-loader-v0/src/main/resources/fabric.mod.json
@@ -21,5 +21,8 @@
   "description": "Asset and data resource loading.",
   "mixins": [
     "fabric-resource-loader-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json b/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json
index 6539d01a1..434523493 100644
--- a/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-screen-handler-api-v1/src/main/resources/fabric.mod.json
@@ -27,5 +27,8 @@
   "mixins": [
     "fabric-screen-handler-api-v1.mixins.json"
   ],
-  "accessWidener": "fabric-screen-handler-api-v1.accesswidener"
+  "accessWidener": "fabric-screen-handler-api-v1.accesswidener",
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-structure-api-v1/src/main/resources/fabric.mod.json b/fabric-structure-api-v1/src/main/resources/fabric.mod.json
index 7e597d4d9..255dc0742 100644
--- a/fabric-structure-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-structure-api-v1/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks for registering custom structures.",
   "mixins": [
     "fabric-structure-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-tag-extensions-v0/src/main/resources/fabric.mod.json b/fabric-tag-extensions-v0/src/main/resources/fabric.mod.json
index 125cb5310..fae990293 100644
--- a/fabric-tag-extensions-v0/src/main/resources/fabric.mod.json
+++ b/fabric-tag-extensions-v0/src/main/resources/fabric.mod.json
@@ -23,5 +23,8 @@
   "description": "Hooks for tags.",
   "mixins": [
     "fabric-tag-extensions-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-textures-v0/src/main/resources/fabric.mod.json b/fabric-textures-v0/src/main/resources/fabric.mod.json
index 1d3156ebf..9c22c5c3c 100644
--- a/fabric-textures-v0/src/main/resources/fabric.mod.json
+++ b/fabric-textures-v0/src/main/resources/fabric.mod.json
@@ -22,5 +22,8 @@
   "description": "Hooks for texture loading and registration.",
   "mixins": [
     "fabric-textures-v0.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/fabric-tool-attribute-api-v1/src/main/resources/fabric.mod.json b/fabric-tool-attribute-api-v1/src/main/resources/fabric.mod.json
index 0e21a2639..d37b5c6ee 100644
--- a/fabric-tool-attribute-api-v1/src/main/resources/fabric.mod.json
+++ b/fabric-tool-attribute-api-v1/src/main/resources/fabric.mod.json
@@ -28,5 +28,8 @@
   "description": "Dynamic atttributes for tools.",
   "mixins": [
     "fabric-tool-attribute-api-v1.mixins.json"
-  ]
+  ],
+  "custom": {
+    "fabric-api:module-lifecycle": "stable"
+  }
 }
diff --git a/gradle/module-validation.gradle b/gradle/module-validation.gradle
new file mode 100644
index 000000000..a1ed31e8b
--- /dev/null
+++ b/gradle/module-validation.gradle
@@ -0,0 +1,61 @@
+import groovy.json.JsonSlurper
+
+/*
+ * This buildscript contains tasks related to the validation of each module in fabric api.
+ *
+ * Right now this task verifies each Fabric API module has a module lifecycle specified.
+ * More functionality will probably be added in the future.
+ */
+
+subprojects {
+	// Create the task
+	task validateModules(type: ValidateModuleTask)
+}
+
+/**
+ * Verifies that each module has the required custom values for module lifecycle in it's FMJ.
+ *
+ * <p>Example:
+ * <pre>{@code
+ * "custom": {
+ *   "fabric-api:module-lifecycle": "stable"
+ * }
+ * }</pre>
+ */
+class ValidateModuleTask extends DefaultTask {
+	ValidateModuleTask() {
+		group = "verification"
+
+		// Hook up validation to check task
+		project.tasks.check.dependsOn(this)
+	}
+
+	@TaskAction
+	void validate() {
+		def json = new JsonSlurper().parse(project.file("src/main/resources/fabric.mod.json") as File) as Map<String, Map<String, String>>;
+
+		if (json.custom == null) {
+			throw new GradleException("Module ${project} does not have a custom value containing module lifecycle!")
+		}
+
+		def moduleLifecycle = json.custom.get("fabric-api:module-lifecycle")
+
+		if (moduleLifecycle == null) {
+			throw new GradleException("Module ${project} does not have module lifecycle in custom values!")
+		}
+
+		if (!moduleLifecycle instanceof String) {
+			throw new GradleException("Module ${project} has an invalid module lifecycle value. The value must be a string but read a ${moduleLifecycle.class}")
+		}
+
+		// Validate the lifecycle value
+		switch (moduleLifecycle) {
+			case "stable":
+			case "experimental":
+			case "deprecated":
+				break;
+			default:
+				throw new GradleException("Module ${project} has an invalid module lifecycle ${json.custom.get('fabric-api:module-lifecycle')}");
+		}
+	}
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 490fda8577df6c95960ba7077c43220e5bb2c0d9..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644
GIT binary patch
delta 6763
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

delta 6251
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

diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index be52383ef..1f3fdbc52 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 2fe81a7d9..4f906e0c8 100755
--- a/gradlew
+++ b/gradlew
@@ -82,6 +82,7 @@ esac
 
 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 
+
 # Determine the Java command to use to start the JVM.
 if [ -n "$JAVA_HOME" ] ; then
     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -129,6 +130,7 @@ fi
 if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
     JAVACMD=`cygpath --unix "$JAVACMD"`
 
     # We build the pattern for arguments to be converted via cygpath
diff --git a/gradlew.bat b/gradlew.bat
index 62bd9b9cc..ac1b06f93 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -1,103 +1,89 @@
-@rem
-@rem Copyright 2015 the original author or authors.
-@rem
-@rem Licensed under the Apache License, Version 2.0 (the "License");
-@rem you may not use this file except in compliance with the License.
-@rem You may obtain a copy of the License at
-@rem
-@rem      https://www.apache.org/licenses/LICENSE-2.0
-@rem
-@rem Unless required by applicable law or agreed to in writing, software
-@rem distributed under the License is distributed on an "AS IS" BASIS,
-@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-@rem See the License for the specific language governing permissions and
-@rem limitations under the License.
-@rem
-
-@if "%DEBUG%" == "" @echo off
-@rem ##########################################################################
-@rem
-@rem  Gradle startup script for Windows
-@rem
-@rem ##########################################################################
-
-@rem Set local scope for the variables with windows NT shell
-if "%OS%"=="Windows_NT" setlocal
-
-set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
-set APP_BASE_NAME=%~n0
-set APP_HOME=%DIRNAME%
-
-@rem Resolve any "." and ".." in APP_HOME to make it shorter.
-for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
-
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
-
-@rem Find java.exe
-if defined JAVA_HOME goto findJavaFromJavaHome
-
-set JAVA_EXE=java.exe
-%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
-
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:findJavaFromJavaHome
-set JAVA_HOME=%JAVA_HOME:"=%
-set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-
-if exist "%JAVA_EXE%" goto init
-
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
-
-goto fail
-
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
-:execute
-@rem Setup the command line
-
-set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
-
-@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
-
-:end
-@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
-
-:fail
-rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
-rem the _cmd.exe /c_ return code!
-if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
-
-:mainEnd
-if "%OS%"=="Windows_NT" endlocal
-
-:omega
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega