From 234f927be9ce70406731c1b1e3345324ae9862aa Mon Sep 17 00:00:00 2001
From: comp500 <comp500@users.noreply.github.com>
Date: Sun, 30 Jul 2023 14:55:34 +0100
Subject: [PATCH] Support NeoForge as a loader (compatible with Forge mods)

TODO: implement support in migrate command
---
 core/pack.go             |  5 ++++-
 core/versionutil.go      |  5 +++++
 curseforge/curseforge.go | 22 +++++++++-------------
 modrinth/export.go       |  2 ++
 modrinth/modrinth.go     |  2 +-
 5 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/core/pack.go b/core/pack.go
index 7f25f95..2fb4d27 100644
--- a/core/pack.go
+++ b/core/pack.go
@@ -198,7 +198,10 @@ func (pack Pack) GetLoaders() (loaders []string) {
 	} else if _, hasFabric := pack.Versions["fabric"]; hasFabric {
 		loaders = append(loaders, "fabric")
 	}
-	if _, hasForge := pack.Versions["forge"]; hasForge {
+	if _, hasNeoForge := pack.Versions["neoforge"]; hasNeoForge {
+		loaders = append(loaders, "neoforge")
+		loaders = append(loaders, "forge") // Backwards-compatible; for now (could be configurable later)
+	} else if _, hasForge := pack.Versions["forge"]; hasForge {
 		loaders = append(loaders, "forge")
 	}
 	return
diff --git a/core/versionutil.go b/core/versionutil.go
index fe4ca5c..7773a0b 100644
--- a/core/versionutil.go
+++ b/core/versionutil.go
@@ -51,6 +51,11 @@ var ModLoaders = map[string]ModLoaderComponent{
 		FriendlyName:      "Quilt loader",
 		VersionListGetter: FetchMavenVersionList("https://maven.quiltmc.org/repository/release/org/quiltmc/quilt-loader/maven-metadata.xml"),
 	},
+	"neoforge": {
+		Name:              "neoforge",
+		FriendlyName:      "NeoForge",
+		VersionListGetter: FetchMavenVersionPrefixedListStrip("https://maven.neoforged.net/releases/net/neoforged/forge/maven-metadata.xml", "NeoForge"),
+	},
 }
 
 func FetchMavenVersionList(url string) func(mcVersion string) ([]string, string, error) {
diff --git a/curseforge/curseforge.go b/curseforge/curseforge.go
index dc1b30f..209d68b 100644
--- a/curseforge/curseforge.go
+++ b/curseforge/curseforge.go
@@ -230,23 +230,19 @@ func getSearchLoaderType(pack core.Pack) modloaderType {
 	_, hasFabric := dependencies["fabric"]
 	_, hasQuilt := dependencies["quilt"]
 	_, hasForge := dependencies["forge"]
-	if (hasFabric || hasQuilt) && hasForge {
-		return modloaderTypeAny
-	} else if hasFabric || hasQuilt {
+	_, hasNeoForge := dependencies["neoforge"]
+	if hasFabric && !hasQuilt && !hasForge && !hasNeoForge {
 		return modloaderTypeFabric
-	} else if hasQuilt {
-		// Backwards-compatible with Fabric for now (could be configurable later)
-		// since we can't filter by more than one loader, just accept any and filter the response
-		return modloaderTypeAny
-	} else if hasForge {
-		return modloaderTypeForge
-	} else {
-		return modloaderTypeAny
 	}
+	if hasForge && !hasNeoForge && !hasFabric && !hasQuilt {
+		return modloaderTypeForge
+	}
+	// We can't filter by more than one loader: accept any and filter the response
+	return modloaderTypeAny
 }
 
-// Crude way of preferring Quilt to Fabric: larger types are preferred
-// so Quilt > Fabric > Forge > Any
+// Crude way of preferring Quilt to Fabric / NeoForge to Forge: larger types are preferred
+// so NeoForge > Quilt > Fabric > Forge > Any
 
 func filterLoaderTypeIndex(packLoaders []string, modLoaderType modloaderType) (modloaderType, bool) {
 	if len(packLoaders) == 0 || modLoaderType == modloaderTypeAny {
diff --git a/modrinth/export.go b/modrinth/export.go
index 14c64aa..295fe62 100644
--- a/modrinth/export.go
+++ b/modrinth/export.go
@@ -193,6 +193,8 @@ var exportCmd = &cobra.Command{
 			dependencies["fabric-loader"] = fabricVersion
 		} else if forgeVersion, ok := pack.Versions["forge"]; ok {
 			dependencies["forge"] = forgeVersion
+		} else if neoforgeVersion, ok := pack.Versions["neoforge"]; ok {
+			dependencies["neoforge"] = neoforgeVersion
 		}
 
 		manifest := Pack{
diff --git a/modrinth/modrinth.go b/modrinth/modrinth.go
index 240a7ce..3bdc8f7 100644
--- a/modrinth/modrinth.go
+++ b/modrinth/modrinth.go
@@ -155,7 +155,7 @@ func getProjectTypeFolder(projectType string, fileLoaders []string, packLoaders
 		}
 		return "shaderpacks", nil
 	} else if projectType == "mod" {
-		// Look up pack loaders in the list of loaders (note this is currently filtered to quilt/fabric/forge)
+		// Look up pack loaders in the list of loaders (note this is currently filtered to quilt/fabric/neoforge/forge)
 		bestLoaderIdx := math.MaxInt
 		for _, v := range fileLoaders {
 			if slices.Contains(packLoaders, v) {