aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshedaniel <daniel@shedaniel.me>2023-11-19 03:04:21 +0800
committershedaniel <daniel@shedaniel.me>2023-11-19 03:04:21 +0800
commitb10f1308f5359ce73a9f4b899cf9516c4ad5388f (patch)
tree5b5700934ae88681918a620edc39754dbf82d496
parent11b87fdd96f5542d646aa8f5136095917f207564 (diff)
downloadRoughlyEnoughItems-b10f1308f5359ce73a9f4b899cf9516c4ad5388f.tar.gz
RoughlyEnoughItems-b10f1308f5359ce73a9f4b899cf9516c4ad5388f.tar.bz2
RoughlyEnoughItems-b10f1308f5359ce73a9f4b899cf9516c4ad5388f.zip
Support NeoForge
-rw-r--r--.github/workflows/curseforge.yml2
-rw-r--r--api/build.gradle8
-rwxr-xr-xbuild.gradle11
-rw-r--r--default-plugin/build.gradle10
-rw-r--r--fabric/build.gradle6
-rw-r--r--forge/build.gradle12
-rw-r--r--forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinRecipeToast.java4
-rw-r--r--gradle.properties7
-rwxr-xr-xgradle/wrapper/gradle-wrapper.properties2
-rw-r--r--neoforge/build.gradle233
-rw-r--r--neoforge/gradle.properties1
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/AnnotationUtils.java119
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/PluginDetectorImpl.java237
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/PrimitivePlatformAdapterImpl.java69
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPlugin.java38
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginClient.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginCommon.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginDedicatedServer.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginLoader.java38
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginLoaderClient.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginLoaderCommon.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/REIPluginLoaderDedicatedServer.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForge.java45
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/CodepointMapWrapper.java92
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/forge/CreativeModeTabCollectorImpl.java67
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/forge/ErrorDisplayerImpl.java55
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/gui/credits/forge/CreditsScreenImpl.java34
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/impl/client/gui/forge/ScreenOverlayImplForge.java76
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinClientPacketListener.java51
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinEffectRenderingInventoryScreen.java66
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinFontSet.java62
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinInputConstants.java52
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinInputConstantsKey.java57
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinPacketEncoder.java57
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinRecipeToast.java47
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinTagLoader.java134
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/mixin/forge/MixinTagManager.java47
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/plugin/client/forge/DefaultClientPluginImpl.java88
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/plugin/common/displays/crafting/forge/DefaultCraftingDisplayImpl.java40
-rw-r--r--neoforge/src/main/java/me/shedaniel/rei/plugin/common/forge/DefaultPluginImpl.java61
-rw-r--r--neoforge/src/main/resources/META-INF/accesstransformer.cfg50
-rw-r--r--neoforge/src/main/resources/META-INF/mods.toml38
-rw-r--r--neoforge/src/main/resources/META-INF/services/me.shedaniel.rei.impl.client.ErrorDisplayer$ErrorGuiInitializer1
-rw-r--r--neoforge/src/main/resources/META-INF/services/me.shedaniel.rei.impl.init.PluginDetector1
-rw-r--r--neoforge/src/main/resources/META-INF/services/me.shedaniel.rei.impl.init.PrimitivePlatformAdapter1
-rw-r--r--neoforge/src/main/resources/icon.pngbin0 -> 27270 bytes
-rw-r--r--neoforge/src/main/resources/pack.mcmeta6
-rw-r--r--neoforge/src/main/resources/rei.mixins.json22
-rw-r--r--neoforge/src/serverComponent/java/me/shedaniel/rei/forge/RoughlyEnoughItemsForgeServerComponent.java55
-rw-r--r--neoforge/src/serverComponent/resources/META-INF/mods.toml28
-rw-r--r--runtime/build.gradle10
-rw-r--r--runtime/src/main/java/me/shedaniel/rei/impl/client/search/collapsed/CollapsedEntriesCache.java2
-rwxr-xr-xsettings.gradle1
53 files changed, 2314 insertions, 33 deletions
diff --git a/.github/workflows/curseforge.yml b/.github/workflows/curseforge.yml
index 05ecb0459..c0c980a8d 100644
--- a/.github/workflows/curseforge.yml
+++ b/.github/workflows/curseforge.yml
@@ -31,7 +31,7 @@ jobs:
- name: Upload Mod
uses: gradle/gradle-build-action@v2
with:
- arguments: build publish forge:publishUnified fabric:publishUnified --stacktrace
+ arguments: build publish forge:publishUnified neoforge:publishUnified fabric:publishUnified --stacktrace
env:
danielshe_curse_api_key: ${{ secrets.CF_API_KEY }}
modrinth_key: ${{ secrets.MODRINTH_KEY }}
diff --git a/api/build.gradle b/api/build.gradle
index 44b099077..6c428a7d2 100644
--- a/api/build.gradle
+++ b/api/build.gradle
@@ -9,11 +9,11 @@ dependencies {
}
architectury {
- common(forgeEnabled.toBoolean())
+ common(platforms.split(","))
}
remapJar {
- classifier "raw"
+ archiveClassifier = "raw"
}
task fakeJar(type: Jar, dependsOn: remapJar) {
@@ -21,7 +21,7 @@ task fakeJar(type: Jar, dependsOn: remapJar) {
from(rootProject.file("fake/fabric.mod.json")) {
into ""
}
- classifier null
+ archiveClassifier = null
}
task fakeForgeJar(type: Jar, dependsOn: jar) {
@@ -35,7 +35,7 @@ task fakeForgeJar(type: Jar, dependsOn: jar) {
into "me/shedaniel/rei/forge"
}
}
- classifier "fake-forge"
+ archiveClassifier = "fake-forge"
}
artifacts {
diff --git a/build.gradle b/build.gradle
index 18a3a4456..b288a32e3 100755
--- a/build.gradle
+++ b/build.gradle
@@ -1,6 +1,6 @@
plugins {
id("architectury-plugin") version("3.4-SNAPSHOT")
- id("dev.architectury.loom") version("0.12.0-SNAPSHOT") apply false
+ id("dev.architectury.loom") version("1.4-SNAPSHOT") apply false
id("org.cadixdev.licenser") version("0.6.1")
id("me.shedaniel.unified-publishing") version("0.1.+")
id("maven-publish")
@@ -28,6 +28,10 @@ subprojects {
silentMojangMappingsLicense()
}
+ repositories {
+ maven { url "https://maven.neoforged.net/releases/" }
+ }
+
dependencies {
minecraft("com.mojang:minecraft:${rootProject.minecraft_version}")
mappings(loom.layered {
@@ -48,7 +52,7 @@ subprojects {
}
subprojects {
- if (project.path == ':fabric' || project.path == ':forge') {
+ if (project.path == ':fabric' || project.path == ':forge' || project.path == ':neoforge') {
loom {
mods {
main { // to match the default mod generated for Forge
@@ -154,6 +158,9 @@ task releaseOnCf {
if (subprojects.any { it.name == "forge" }) {
dependsOn project("forge").tasks.getByName("publishUnified")
}
+ if (subprojects.any { it.name == "neoforge" }) {
+ dependsOn project("neoforge").tasks.getByName("publishUnified")
+ }
if (subprojects.any { it.name == "fabric" }) {
dependsOn project("fabric").tasks.getByName("publishUnified")
}
diff --git a/default-plugin/build.gradle b/default-plugin/build.gradle
index c47536992..f696ad920 100644
--- a/default-plugin/build.gradle
+++ b/default-plugin/build.gradle
@@ -8,15 +8,15 @@ dependencies {
modCompileOnly("net.fabricmc:fabric-loader:${project.fabricloader_version}")
modApi("me.shedaniel.cloth:cloth-config:${cloth_config_version}")
modApi("dev.architectury:architectury:${architectury_version}")
- compileClasspath(project(path: ":api", configuration: "namedElements"))
+ compileOnly(project(path: ":api", configuration: "namedElements"))
}
architectury {
- common(forgeEnabled.toBoolean())
+ common(platforms.split(","))
}
remapJar {
- classifier "raw"
+ archiveClassifier = "raw"
}
task fakeJar(type: Jar, dependsOn: remapJar) {
@@ -24,7 +24,7 @@ task fakeJar(type: Jar, dependsOn: remapJar) {
from(rootProject.file("fake/fabric.mod.json")) {
into ""
}
- classifier null
+ archiveClassifier = null
}
task fakeForgeJar(type: Jar, dependsOn: jar) {
@@ -38,7 +38,7 @@ task fakeForgeJar(type: Jar, dependsOn: jar) {
into "me/shedaniel/rei/forge"
}
}
- classifier "fake-forge"
+ archiveClassifier = "fake-forge"
}
artifacts {
diff --git a/fabric/build.gradle b/fabric/build.gradle
index 518452b7e..d6fcdee6f 100644
--- a/fabric/build.gradle
+++ b/fabric/build.gradle
@@ -46,17 +46,17 @@ dependencies {
shadowJar {
configurations = [project.configurations.shadowCommon]
- classifier "dev-shadow"
+ archiveClassifier = "dev-shadow"
}
remapJar {
input.set shadowJar.archiveFile
dependsOn shadowJar
- classifier null
+ archiveClassifier = null
}
jar {
- classifier "dev"
+ archiveClassifier = "dev"
}
java {
diff --git a/forge/build.gradle b/forge/build.gradle
index 98386dd26..df2ee147c 100644
--- a/forge/build.gradle
+++ b/forge/build.gradle
@@ -133,17 +133,17 @@ def modRuntime(str) {
shadowJar {
configurations = [project.configurations.shadowCommon]
- classifier "dev-shadow"
+ archiveClassifier = "dev-shadow"
}
remapJar {
input.set shadowJar.archiveFile
dependsOn shadowJar
- classifier null
+ archiveClassifier = null
}
jar {
- classifier "dev"
+ archiveClassifier = "dev"
}
java {
@@ -161,7 +161,7 @@ sourcesJar {
}
task serverOnlyJar(type: Jar, dependsOn: [remapJar]) {
- classifier "server-only"
+ archiveClassifier = "server-only"
from(zipTree(remapJar.archiveFile.get().asFile)) {
exclude "META-INF/mods.toml", "mezz/**", "me/shedaniel/rei/forge/RoughlyEnoughItemsForge.class", "me/shedaniel/rei/forge/JEIStub.class"
}
@@ -187,12 +187,12 @@ publishing {
["api", "default-plugin"].forEach { projectName ->
def remapSrg = tasks.create("remapSrgJarFor$projectName", net.fabricmc.loom.task.RemapJarTask) {
inputFile = project(":" + projectName).tasks.jar.archiveFile
- classifier "srg-remapped-$projectName"
+ archiveClassifier = "srg-remapped-$projectName"
targetNamespace = "srg"
}
def remapSrgSourcesJar = tasks.create("remapSrgSourcesFor$projectName", net.fabricmc.loom.task.RemapSourcesJarTask) {
inputFile = project(":" + projectName).tasks.sourcesJar.archiveFile
- classifier "srg-remapped-$projectName-sources"
+ archiveClassifier = "srg-remapped-$projectName-sources"
targetNamespace = "srg"
}
create(projectName + "Forge", MavenPublication.class) { publication ->
diff --git a/forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinRecipeToast.java b/forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinRecipeToast.java
index 591cd987f..dc12ed85d 100644
--- a/forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinRecipeToast.java
+++ b/forge/src/main/java/me/shedaniel/rei/mixin/forge/MixinRecipeToast.java
@@ -26,7 +26,7 @@ package me.shedaniel.rei.mixin.forge;
import me.shedaniel.rei.api.client.config.ConfigObject;
import net.minecraft.client.gui.components.toasts.RecipeToast;
import net.minecraft.client.gui.components.toasts.ToastComponent;
-import net.minecraft.world.item.crafting.Recipe;
+import net.minecraft.world.item.crafting.RecipeHolder;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@@ -36,7 +36,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(RecipeToast.class)
public class MixinRecipeToast {
@Inject(method = "addOrUpdate", at = @At("HEAD"), cancellable = true)
- private static void addOrUpdate(ToastComponent toastGui, Recipe<?> recipe, CallbackInfo info) {
+ private static void addOrUpdate(ToastComponent toastGui, RecipeHolder<?> recipe, CallbackInfo info) {
if (disableRecipeBook()) info.cancel();
}
diff --git a/gradle.properties b/gradle.properties
index b8ea1c1e8..ac4e980d2 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -3,12 +3,13 @@ base_version=13.0
unstable=false
supported_version=1.20.2
minecraft_version=1.20.2
-forgeEnabled=true
+platforms=fabric,forge,neoforge
forge_version=48.0.1
+neoforge_version=20.2.52-beta
fabricloader_version=0.14.22
-cloth_config_version=12.0.109
+cloth_config_version=12.0.111
modmenu_version=7.0.0
fabric_api=0.89.2+1.20.2
-architectury_version=10.0.8
+architectury_version=10.0.13
api_exculde=
#api_include=me.shedaniel.cloth:cloth-events,me.shedaniel.cloth:config-2,me.sargunvohra.mcmods:autoconfig1u,org.jetbrains:annotations,net.fabricmc.fabric-api:fabric
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 8f6579526..4b8cf416a 100755
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
diff --git a/neoforge/build.gradle b/neoforge/build.gradle
new file mode 100644
index 000000000..b4c5f6d63
--- /dev/null
+++ b/neoforge/build.gradle
@@ -0,0 +1,233 @@
+plugins {
+ id "com.github.johnrengelman.shadow" version "7.0.0"
+}
+
+architectury {
+ platformSetupLoomIde()
+ neoForge()
+}
+
+configurations {
+ common
+ shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
+ compileClasspath.extendsFrom common
+ runtimeClasspath.extendsFrom common
+}
+
+processResources {
+ filesMatching("META-INF/mods.toml") {
+ expand "version": project.version
+ }
+ inputs.property "version", project.version
+}
+
+repositories {
+ maven { url "https://www.cursemaven.com" }
+ maven { url "https://dl.cloudsmith.io/public/geckolib3/geckolib/maven" }
+ maven {
+ name "Modmaven"
+ url "https://modmaven.dev/"
+ // For Gradle 5.1 and above, limit it to just AE2
+ content {
+ includeGroup 'appeng'
+ }
+ }
+}
+
+sourceSets {
+ serverComponent {
+ compileClasspath += main.compileClasspath
+ runtimeClasspath += main.runtimeClasspath
+ }
+}
+
+processServerComponentResources {
+ filesMatching("META-INF/mods.toml") {
+ expand "version": project.version
+ }
+ inputs.property "version", project.version
+}
+
+loom {
+}
+
+def depProjects = [":api", ":runtime", ":default-plugin"]
+
+dependencies {
+ neoForge("net.neoforged:neoforge:${rootProject.neoforge_version}")
+ modApi("me.shedaniel.cloth:cloth-config-neoforge:${cloth_config_version}")
+ modApi("dev.architectury:architectury-neoforge:${architectury_version}")
+
+ depProjects.forEach {
+ common(project(path: it, configuration: "namedElements")) { transitive false }
+ shadowCommon(project(path: it, configuration: "transformProductionNeoForge")) { transitive false }
+ }
+}
+
+def modRuntime(str) {
+ dependencies.modLocalRuntime(str)
+}
+
+shadowJar {
+ configurations = [project.configurations.shadowCommon]
+ archiveClassifier = "dev-shadow"
+}
+
+remapJar {
+ input.set shadowJar.archiveFile
+ dependsOn shadowJar
+ archiveClassifier = null
+}
+
+jar {
+ archiveClassifier = "dev"
+}
+
+java {
+ withSourcesJar()
+}
+
+sourcesJar {
+ afterEvaluate {
+ depProjects.forEach {
+ def depSources = project(it).sourcesJar
+ dependsOn depSources
+ from depSources.archiveFile.map { zipTree(it) }
+ }
+ }
+}
+
+task serverOnlyJar(type: Jar, dependsOn: [remapJar]) {
+ archiveClassifier = "server-only"
+ from(zipTree(remapJar.archiveFile.get().asFile)) {
+ exclude "META-INF/mods.toml", "mezz/**", "me/shedaniel/rei/forge/RoughlyEnoughItemsForge.class", "me/shedaniel/rei/forge/JEIStub.class"
+ }
+ from(sourceSets.serverComponent.output)
+}
+
+tasks.build {
+ dependsOn tasks.serverOnlyJar
+}
+
+components.java {
+ withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
+ skip()
+ }
+}
+
+publishing {
+ publications {
+ mavenNeoForge(MavenPublication) {
+ artifactId = rootProject.name + "-" + project.name
+ from components.java
+ }
+ ["api", "default-plugin"].forEach { projectName ->
+ def remapMojang = tasks.create("remapMojangJarFor$projectName", net.fabricmc.loom.task.RemapJarTask) {
+ inputFile = project(":" + projectName).tasks.jar.archiveFile
+ archiveClassifier = "mojang-remapped-$projectName"
+ targetNamespace = "mojang"
+ }
+ def remapMojangSourcesJar = tasks.create("remapMojangSourcesFor$projectName", net.fabricmc.loom.task.RemapSourcesJarTask) {
+ inputFile = project(":" + projectName).tasks.sourcesJar.archiveFile
+ archiveClassifier = "mojang-remapped-$projectName-sources"
+ targetNamespace = "mojang"
+ }
+ create(projectName + "NeoForge", MavenPublication.class) { publication ->
+ publication.artifactId = rootProject.name + "-" + projectName + "-neoforge"
+ project.afterEvaluate {
+ def project = project(":" + projectName)
+ remapMojang.inputFile = project.fakeForgeJar.archiveFile
+ publication.artifact(remapMojang) { classifier null }
+ publication.artifact(remapMojangSourcesJar) {
+ builtBy remapMojangSourcesJar
+ classifier "sources"
+ }
+ }
+ }
+ }
+ }
+}
+
+unifiedPublishing {
+ project {
+ displayName = "[NeoForge $rootProject.supported_version] v$project.version"
+ releaseType = "beta"
+ gameVersions = []
+ gameLoaders = ["neoforge"]
+ changelog = rootProject.releaseChangelog
+
+ mainPublication remapJar
+
+ relations {
+ depends {
+ curseforge = "architectury-api"
+ modrinth = "architectury-api"
+ }
+ depends {
+ curseforge = "cloth-config"
+ modrinth = "cloth-config"
+ }
+ }
+
+ if (project.hasProperty("danielshe_curse_api_key") || System.getenv("danielshe_curse_api_key") != null) {
+ curseforge {
+ token = project.hasProperty("danielshe_curse_api_key") ? project.property("danielshe_curse_api_key") : System.getenv("danielshe_curse_api_key")
+ id = "310111"
+ gameVersions.addAll "Java 17"
+ gameVersions.addAll project.minecraft_version
+
+ relations {
+ depends "roughly-enough-items-hacks"
+ }
+ }
+ }
+
+ if (project.hasProperty("modrinth_key") || System.getenv("modrinth_key") != null) {
+ modrinth {
+ token = project.hasProperty("modrinth_key") ? project.property("modrinth_key") : System.getenv("modrinth_key")
+ id = "nfn13YXA"
+ version = "$project.version+$project.name"
+ gameVersions.addAll project.minecraft_version
+ }
+ }
+ }
+ project {
+ displayName = "[NeoForge $rootProject.supported_version] v$project.version"
+ releaseType = "release"
+ gameVersions = []
+ gameLoaders = ["neoforge"]
+ changelog = rootProject.releaseChangelog
+
+ mainPublication serverOnlyJar
+
+ relations {
+ depends {
+ curseforge = "architectury-api"
+ modrinth = "architectury-api"
+ }
+ depends {
+ curseforge = "cloth-config"
+ modrinth = "cloth-config"
+ }
+ }
+
+ if (project.hasProperty("danielshe_curse_api_key") || System.getenv("danielshe_curse_api_key") != null) {
+ curseforge {
+ token = project.hasProperty("danielshe_curse_api_key") ? project.property("danielshe_curse_api_key") : System.getenv("danielshe_curse_api_key")
+ id = "567899"
+ gameVersions.addAll "Java 17"
+ gameVersions.addAll project.minecraft_version
+ }
+ }
+
+ if (project.hasProperty("modrinth_key") || System.getenv("modrinth_key") != null) {
+ modrinth {
+ releaseType = "release"
+ token = project.hasProperty("modrinth_key") ? project.property("modrinth_key") : System.getenv("modrinth_key")
+ id = "OM4ZYSws"
+ version = "$project.version+$project.name"
+ gameVersions.addAll project.minecraft_version
+ }
+ }
+ }
+}
diff --git a/neoforge/gradle.properties b/neoforge/gradle.properties
new file mode 100644
index 000000000..7da18ea6f
--- /dev/null
+++ b/neoforge/gradle.properties
@@ -0,0 +1 @@
+loom.platform=neoforge
diff --git a/neoforge/src/main/java/me/shedaniel/rei/forge/AnnotationUtils.java b/neoforge/src/main/java/me/shedaniel/rei/forge/AnnotationUtils.java
new file mode 100644
index 000000000..9a13e0cdc
--- /dev/null
+++ b/neoforge/src/main/java/me/shedaniel/rei/forge/AnnotationUtils.java
@@ -0,0 +1,119 @@
+/*
+ * This file is licensed under the MIT License, part of