mirror of
https://github.com/packwiz/packwiz.git
synced 2025-04-19 21:16:30 +02:00
Eradicate variable-size integer types where not used by interface or as index (fixes #107)
This commit is contained in:
parent
d051932bbb
commit
d5290ebd32
@ -117,7 +117,7 @@ var urlRegexes = [...]*regexp.Regexp{
|
|||||||
regexp.MustCompile("^(?P<slug>[a-z][\\da-z\\-_]{0,127})$"),
|
regexp.MustCompile("^(?P<slug>[a-z][\\da-z\\-_]{0,127})$"),
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSlugOrUrl(url string) (game string, category string, slug string, fileID int, err error) {
|
func parseSlugOrUrl(url string) (game string, category string, slug string, fileID uint32, err error) {
|
||||||
for _, r := range urlRegexes {
|
for _, r := range urlRegexes {
|
||||||
matches := r.FindStringSubmatch(url)
|
matches := r.FindStringSubmatch(url)
|
||||||
if matches != nil {
|
if matches != nil {
|
||||||
@ -132,7 +132,9 @@ func parseSlugOrUrl(url string) (game string, category string, slug string, file
|
|||||||
}
|
}
|
||||||
if i := r.SubexpIndex("fileID"); i >= 0 {
|
if i := r.SubexpIndex("fileID"); i >= 0 {
|
||||||
if matches[i] != "" {
|
if matches[i] != "" {
|
||||||
fileID, err = strconv.Atoi(matches[i])
|
var f uint64
|
||||||
|
f, err = strconv.ParseUint(matches[i], 10, 32)
|
||||||
|
fileID = uint32(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -214,7 +216,7 @@ func createModFile(modInfo modInfo, fileInfo modFileInfo, index *core.Index, opt
|
|||||||
return index.RefreshFileWithHash(path, format, hash, true)
|
return index.RefreshFileWithHash(path, format, hash, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSearchLoaderType(pack core.Pack) int {
|
func getSearchLoaderType(pack core.Pack) modloaderType {
|
||||||
dependencies := pack.Versions
|
dependencies := pack.Versions
|
||||||
|
|
||||||
_, hasFabric := dependencies["fabric"]
|
_, hasFabric := dependencies["fabric"]
|
||||||
@ -235,7 +237,7 @@ func getSearchLoaderType(pack core.Pack) int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchLoaderType(packLoaders []string, modLoaderType int) bool {
|
func matchLoaderType(packLoaders []string, modLoaderType modloaderType) bool {
|
||||||
if len(packLoaders) == 0 || modLoaderType == modloaderTypeAny {
|
if len(packLoaders) == 0 || modLoaderType == modloaderTypeAny {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
@ -290,8 +292,8 @@ func matchGameVersions(mcVersion string, modMcVersions []string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cfUpdateData struct {
|
type cfUpdateData struct {
|
||||||
ProjectID int `mapstructure:"project-id"`
|
ProjectID uint32 `mapstructure:"project-id"`
|
||||||
FileID int `mapstructure:"file-id"`
|
FileID uint32 `mapstructure:"file-id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u cfUpdateData) ToMap() (map[string]interface{}, error) {
|
func (u cfUpdateData) ToMap() (map[string]interface{}, error) {
|
||||||
@ -311,13 +313,13 @@ func (u cfUpdater) ParseUpdate(updateUnparsed map[string]interface{}) (interface
|
|||||||
type cachedStateStore struct {
|
type cachedStateStore struct {
|
||||||
modInfo
|
modInfo
|
||||||
hasFileInfo bool
|
hasFileInfo bool
|
||||||
fileID int
|
fileID uint32
|
||||||
fileInfo modFileInfo
|
fileInfo modFileInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u cfUpdater) CheckUpdate(mods []core.Mod, mcVersion string, pack core.Pack) ([]core.UpdateCheck, error) {
|
func (u cfUpdater) CheckUpdate(mods []core.Mod, mcVersion string, pack core.Pack) ([]core.UpdateCheck, error) {
|
||||||
results := make([]core.UpdateCheck, len(mods))
|
results := make([]core.UpdateCheck, len(mods))
|
||||||
modIDs := make([]int, len(mods))
|
modIDs := make([]uint32, len(mods))
|
||||||
modInfos := make([]modInfo, len(mods))
|
modInfos := make([]modInfo, len(mods))
|
||||||
|
|
||||||
for i, v := range mods {
|
for i, v := range mods {
|
||||||
@ -438,7 +440,7 @@ func (u cfUpdater) DoUpdate(mods []*core.Mod, cachedState []interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cfExportData struct {
|
type cfExportData struct {
|
||||||
ProjectID int `mapstructure:"project-id"`
|
ProjectID uint32 `mapstructure:"project-id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e cfExportData) ToMap() (map[string]interface{}, error) {
|
func (e cfExportData) ToMap() (map[string]interface{}, error) {
|
||||||
@ -461,9 +463,9 @@ func (c cfDownloader) GetFilesMetadata(mods []*core.Mod) ([]core.MetaDownloaderD
|
|||||||
}
|
}
|
||||||
|
|
||||||
downloaderData := make([]core.MetaDownloaderData, len(mods))
|
downloaderData := make([]core.MetaDownloaderData, len(mods))
|
||||||
indexMap := make(map[int]int)
|
indexMap := make(map[uint32]int)
|
||||||
projectMetadata := make([]cfUpdateData, len(mods))
|
projectMetadata := make([]cfUpdateData, len(mods))
|
||||||
fileIDs := make([]int, len(mods))
|
fileIDs := make([]uint32, len(mods))
|
||||||
for i, v := range mods {
|
for i, v := range mods {
|
||||||
updateData, ok := v.GetParsedUpdateData("curseforge")
|
updateData, ok := v.GetParsedUpdateData("curseforge")
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -480,7 +482,7 @@ func (c cfDownloader) GetFilesMetadata(mods []*core.Mod) ([]core.MetaDownloaderD
|
|||||||
return nil, fmt.Errorf("failed to get CurseForge file metadata: %w", err)
|
return nil, fmt.Errorf("failed to get CurseForge file metadata: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
modIDsToLookup := make([]int, 0)
|
modIDsToLookup := make([]uint32, 0)
|
||||||
fileNames := make([]string, len(mods))
|
fileNames := make([]string, len(mods))
|
||||||
for _, file := range fileData {
|
for _, file := range fileData {
|
||||||
if _, ok := indexMap[file.ModID]; !ok {
|
if _, ok := indexMap[file.ModID]; !ok {
|
||||||
@ -509,7 +511,7 @@ func (c cfDownloader) GetFilesMetadata(mods []*core.Mod) ([]core.MetaDownloaderD
|
|||||||
downloaderData[indexMap[mod.ID]] = &cfDownloadMetadata{
|
downloaderData[indexMap[mod.ID]] = &cfDownloadMetadata{
|
||||||
noDistribution: true, // Inverted so the default value is not this (probably doesn't matter)
|
noDistribution: true, // Inverted so the default value is not this (probably doesn't matter)
|
||||||
name: mod.Name,
|
name: mod.Name,
|
||||||
websiteUrl: mod.Links.WebsiteURL + "/files/" + strconv.Itoa(fileIDs[indexMap[mod.ID]]),
|
websiteUrl: mod.Links.WebsiteURL + "/files/" + strconv.FormatUint(uint64(fileIDs[indexMap[mod.ID]]), 10),
|
||||||
fileName: fileNames[indexMap[mod.ID]],
|
fileName: fileNames[indexMap[mod.ID]],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,8 @@ var detectCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Walk files in the mods folder
|
// Walk files in the mods folder
|
||||||
var hashes []int
|
var hashes []uint32
|
||||||
modPaths := make(map[int]string)
|
modPaths := make(map[uint32]string)
|
||||||
err = filepath.Walk("mods", func(path string, info os.FileInfo, err error) error {
|
err = filepath.Walk("mods", func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -51,8 +51,8 @@ var detectCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
hash := getByteArrayHash(bytes)
|
hash := getByteArrayHash(bytes)
|
||||||
hashes = append(hashes, int(hash))
|
hashes = append(hashes, hash)
|
||||||
modPaths[int(hash)] = path
|
modPaths[hash] = path
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -132,8 +132,8 @@ func init() {
|
|||||||
curseforgeCmd.AddCommand(detectCmd)
|
curseforgeCmd.AddCommand(detectCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getByteArrayHash(bytes []byte) uint64 {
|
func getByteArrayHash(bytes []byte) uint32 {
|
||||||
return uint64(murmur.MurmurHash2(computeNormalizedArray(bytes), 1))
|
return murmur.MurmurHash2(computeNormalizedArray(bytes), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func computeNormalizedArray(bytes []byte) []byte {
|
func computeNormalizedArray(bytes []byte) []byte {
|
||||||
|
@ -238,7 +238,7 @@ func createModlist(zw *zip.Writer, mods []*core.Mod) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
project := projectRaw.(cfUpdateData)
|
project := projectRaw.(cfUpdateData)
|
||||||
_, err = w.WriteString("<li><a href=\"https://www.curseforge.com/projects/" + strconv.Itoa(project.ProjectID) + "\">" + mod.Name + "</a></li>\r\n")
|
_, err = w.WriteString("<li><a href=\"https://www.curseforge.com/projects/" + strconv.FormatUint(uint64(project.ProjectID), 10) + "\">" + mod.Name + "</a></li>\r\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ var importCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
modsList := packImport.Mods()
|
modsList := packImport.Mods()
|
||||||
modIDs := make([]int, len(modsList))
|
modIDs := make([]uint32, len(modsList))
|
||||||
for i, v := range modsList {
|
for i, v := range modsList {
|
||||||
modIDs[i] = v.ProjectID
|
modIDs[i] = v.ProjectID
|
||||||
}
|
}
|
||||||
@ -198,17 +198,17 @@ var importCmd = &cobra.Command{
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
modInfosMap := make(map[int]modInfo)
|
modInfosMap := make(map[uint32]modInfo)
|
||||||
for _, v := range modInfos {
|
for _, v := range modInfos {
|
||||||
modInfosMap[v.ID] = v
|
modInfosMap[v.ID] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: multithreading????
|
// TODO: multithreading????
|
||||||
|
|
||||||
modFileInfosMap := make(map[int]modFileInfo)
|
modFileInfosMap := make(map[uint32]modFileInfo)
|
||||||
referencedModPaths := make([]string, 0, len(modsList))
|
referencedModPaths := make([]string, 0, len(modsList))
|
||||||
successes := 0
|
successes := 0
|
||||||
remainingFileIDs := make([]int, 0, len(modsList))
|
remainingFileIDs := make([]uint32, 0, len(modsList))
|
||||||
|
|
||||||
// 1st pass: query mod metadata for every CurseForge file
|
// 1st pass: query mod metadata for every CurseForge file
|
||||||
for _, v := range modsList {
|
for _, v := range modsList {
|
||||||
|
@ -46,7 +46,7 @@ var installCmd = &cobra.Command{
|
|||||||
|
|
||||||
game := gameFlag
|
game := gameFlag
|
||||||
category := categoryFlag
|
category := categoryFlag
|
||||||
var modID, fileID int
|
var modID, fileID uint32
|
||||||
var slug string
|
var slug string
|
||||||
|
|
||||||
// If mod/file IDs are provided in command line, use those
|
// If mod/file IDs are provided in command line, use those
|
||||||
@ -122,7 +122,7 @@ var installCmd = &cobra.Command{
|
|||||||
|
|
||||||
if len(fileInfoData.Dependencies) > 0 {
|
if len(fileInfoData.Dependencies) > 0 {
|
||||||
var depsInstallable []installableDep
|
var depsInstallable []installableDep
|
||||||
var depIDPendingQueue []int
|
var depIDPendingQueue []uint32
|
||||||
for _, dep := range fileInfoData.Dependencies {
|
for _, dep := range fileInfoData.Dependencies {
|
||||||
if dep.Type == dependencyTypeRequired {
|
if dep.Type == dependencyTypeRequired {
|
||||||
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
|
depIDPendingQueue = append(depIDPendingQueue, dep.ModID)
|
||||||
@ -133,7 +133,7 @@ var installCmd = &cobra.Command{
|
|||||||
fmt.Println("Finding dependencies...")
|
fmt.Println("Finding dependencies...")
|
||||||
|
|
||||||
cycles := 0
|
cycles := 0
|
||||||
var installedIDList []int
|
var installedIDList []uint32
|
||||||
for len(depIDPendingQueue) > 0 && cycles < maxCycles {
|
for len(depIDPendingQueue) > 0 && cycles < maxCycles {
|
||||||
if installedIDList == nil {
|
if installedIDList == nil {
|
||||||
// Get modids of all mods
|
// Get modids of all mods
|
||||||
@ -278,14 +278,14 @@ func (r modResultsList) Len() int {
|
|||||||
return len(r)
|
return len(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func searchCurseforgeInternal(searchTerm string, isSlug bool, game string, category string, mcVersion string, searchLoaderType int) (bool, modInfo) {
|
func searchCurseforgeInternal(searchTerm string, isSlug bool, game string, category string, mcVersion string, searchLoaderType modloaderType) (bool, modInfo) {
|
||||||
if isSlug {
|
if isSlug {
|
||||||
fmt.Println("Looking up CurseForge slug...")
|
fmt.Println("Looking up CurseForge slug...")
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Searching CurseForge...")
|
fmt.Println("Searching CurseForge...")
|
||||||
}
|
}
|
||||||
|
|
||||||
var gameID, categoryID, classID int
|
var gameID, categoryID, classID uint32
|
||||||
if game == "minecraft" {
|
if game == "minecraft" {
|
||||||
gameID = 432
|
gameID = 432
|
||||||
}
|
}
|
||||||
@ -308,7 +308,7 @@ func searchCurseforgeInternal(searchTerm string, isSlug bool, game string, categ
|
|||||||
fmt.Printf("Failed to lookup game %s: selected game does not have a public API!\n", game)
|
fmt.Printf("Failed to lookup game %s: selected game does not have a public API!\n", game)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
gameID = int(v.ID)
|
gameID = v.ID
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -409,7 +409,7 @@ func searchCurseforgeInternal(searchTerm string, isSlug bool, game string, categ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLatestFile(modInfoData modInfo, mcVersion string, fileID int, packLoaders []string) (modFileInfo, error) {
|
func getLatestFile(modInfoData modInfo, mcVersion string, fileID uint32, packLoaders []string) (modFileInfo, error) {
|
||||||
if fileID == 0 {
|
if fileID == 0 {
|
||||||
var fileInfoData modFileInfo
|
var fileInfoData modFileInfo
|
||||||
fileInfoObtained := false
|
fileInfoObtained := false
|
||||||
@ -455,8 +455,8 @@ func getLatestFile(modInfoData modInfo, mcVersion string, fileID int, packLoader
|
|||||||
return fileInfoData, nil
|
return fileInfoData, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var addonIDFlag int
|
var addonIDFlag uint32
|
||||||
var fileIDFlag int
|
var fileIDFlag uint32
|
||||||
|
|
||||||
var gameFlag string
|
var gameFlag string
|
||||||
var categoryFlag string
|
var categoryFlag string
|
||||||
@ -464,8 +464,8 @@ var categoryFlag string
|
|||||||
func init() {
|
func init() {
|
||||||
curseforgeCmd.AddCommand(installCmd)
|
curseforgeCmd.AddCommand(installCmd)
|
||||||
|
|
||||||
installCmd.Flags().IntVar(&addonIDFlag, "addon-id", 0, "The CurseForge project ID to use")
|
installCmd.Flags().Uint32Var(&addonIDFlag, "addon-id", 0, "The CurseForge project ID to use")
|
||||||
installCmd.Flags().IntVar(&fileIDFlag, "file-id", 0, "The CurseForge file ID to use")
|
installCmd.Flags().Uint32Var(&fileIDFlag, "file-id", 0, "The CurseForge file ID to use")
|
||||||
installCmd.Flags().StringVar(&gameFlag, "game", "minecraft", "The game to add files from (slug, as stored in URLs); the game in the URL takes precedence")
|
installCmd.Flags().StringVar(&gameFlag, "game", "minecraft", "The game to add files from (slug, as stored in URLs); the game in the URL takes precedence")
|
||||||
installCmd.Flags().StringVar(&categoryFlag, "category", "", "The category to add files from (slug, as stored in URLs); the category in the URL takes precedence")
|
installCmd.Flags().StringVar(&categoryFlag, "category", "", "The category to add files from (slug, as stored in URLs); the category in the URL takes precedence")
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ var openCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
cfUpdateData := updateData.(cfUpdateData)
|
cfUpdateData := updateData.(cfUpdateData)
|
||||||
fmt.Println("Opening browser...")
|
fmt.Println("Opening browser...")
|
||||||
url := "https://www.curseforge.com/projects/" + strconv.Itoa(cfUpdateData.ProjectID)
|
url := "https://www.curseforge.com/projects/" + strconv.FormatUint(uint64(cfUpdateData.ProjectID), 10)
|
||||||
err = open.Start(url)
|
err = open.Start(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Opening page failed, direct link:")
|
fmt.Println("Opening page failed, direct link:")
|
||||||
|
@ -8,14 +8,14 @@ type cursePackMeta struct {
|
|||||||
ModLoaders []modLoaderDef `json:"modLoaders"`
|
ModLoaders []modLoaderDef `json:"modLoaders"`
|
||||||
} `json:"minecraft"`
|
} `json:"minecraft"`
|
||||||
ManifestType string `json:"manifestType"`
|
ManifestType string `json:"manifestType"`
|
||||||
ManifestVersion int `json:"manifestVersion"`
|
ManifestVersion uint32 `json:"manifestVersion"`
|
||||||
NameInternal string `json:"name"`
|
NameInternal string `json:"name"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
Author string `json:"author"`
|
Author string `json:"author"`
|
||||||
ProjectID int `json:"projectID"`
|
ProjectID uint32 `json:"projectID"`
|
||||||
Files []struct {
|
Files []struct {
|
||||||
ProjectID int `json:"projectID"`
|
ProjectID uint32 `json:"projectID"`
|
||||||
FileID int `json:"fileID"`
|
FileID uint32 `json:"fileID"`
|
||||||
Required bool `json:"required"`
|
Required bool `json:"required"`
|
||||||
} `json:"files"`
|
} `json:"files"`
|
||||||
Overrides string `json:"overrides"`
|
Overrides string `json:"overrides"`
|
||||||
|
@ -17,10 +17,10 @@ type twitchInstalledPackMeta struct {
|
|||||||
} `json:"baseModLoader"`
|
} `json:"baseModLoader"`
|
||||||
ModpackOverrides []string `json:"modpackOverrides"`
|
ModpackOverrides []string `json:"modpackOverrides"`
|
||||||
ModsInternal []struct {
|
ModsInternal []struct {
|
||||||
ID int `json:"addonID"`
|
ID uint32 `json:"addonID"`
|
||||||
File struct {
|
File struct {
|
||||||
// I've given up on using this cached data, just going to re-request it
|
// I've given up on using this cached data, just going to re-request it
|
||||||
ID int `json:"id"`
|
ID uint32 `json:"id"`
|
||||||
// Used to determine if the mod is optional-disabled
|
// Used to determine if the mod is optional-disabled
|
||||||
FileNameOnDisk string
|
FileNameOnDisk string
|
||||||
} `json:"installedFile"`
|
} `json:"installedFile"`
|
||||||
|
@ -63,22 +63,22 @@ func ReadMetadata(s ImportPackSource) ImportPackMetadata {
|
|||||||
|
|
||||||
// AddonFileReference is a struct to reference a single file on CurseForge
|
// AddonFileReference is a struct to reference a single file on CurseForge
|
||||||
type AddonFileReference struct {
|
type AddonFileReference struct {
|
||||||
ProjectID int
|
ProjectID uint32
|
||||||
FileID int
|
FileID uint32
|
||||||
// OptionalDisabled is true if the file is optional and disabled (turned off in Twitch launcher)
|
// OptionalDisabled is true if the file is optional and disabled (turned off in Twitch launcher)
|
||||||
OptionalDisabled bool
|
OptionalDisabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteManifestFromPack(pack core.Pack, fileRefs []AddonFileReference, projectID int, out io.Writer) error {
|
func WriteManifestFromPack(pack core.Pack, fileRefs []AddonFileReference, projectID uint32, out io.Writer) error {
|
||||||
files := make([]struct {
|
files := make([]struct {
|
||||||
ProjectID int `json:"projectID"`
|
ProjectID uint32 `json:"projectID"`
|
||||||
FileID int `json:"fileID"`
|
FileID uint32 `json:"fileID"`
|
||||||
Required bool `json:"required"`
|
Required bool `json:"required"`
|
||||||
}, len(fileRefs))
|
}, len(fileRefs))
|
||||||
for i, fr := range fileRefs {
|
for i, fr := range fileRefs {
|
||||||
files[i] = struct {
|
files[i] = struct {
|
||||||
ProjectID int `json:"projectID"`
|
ProjectID uint32 `json:"projectID"`
|
||||||
FileID int `json:"fileID"`
|
FileID uint32 `json:"fileID"`
|
||||||
Required bool `json:"required"`
|
Required bool `json:"required"`
|
||||||
}{ProjectID: fr.ProjectID, FileID: fr.FileID, Required: !fr.OptionalDisabled}
|
}{ProjectID: fr.ProjectID, FileID: fr.FileID, Required: !fr.OptionalDisabled}
|
||||||
}
|
}
|
||||||
|
@ -85,16 +85,20 @@ func (c *cfApiClient) makePost(endpoint string, body io.Reader) (*http.Response,
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type fileType uint8
|
||||||
|
|
||||||
//noinspection GoUnusedConst
|
//noinspection GoUnusedConst
|
||||||
const (
|
const (
|
||||||
fileTypeRelease int = iota + 1
|
fileTypeRelease fileType = iota + 1
|
||||||
fileTypeBeta
|
fileTypeBeta
|
||||||
fileTypeAlpha
|
fileTypeAlpha
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type dependencyType uint8
|
||||||
|
|
||||||
//noinspection GoUnusedConst
|
//noinspection GoUnusedConst
|
||||||
const (
|
const (
|
||||||
dependencyTypeEmbedded int = iota + 1
|
dependencyTypeEmbedded dependencyType = iota + 1
|
||||||
dependencyTypeOptional
|
dependencyTypeOptional
|
||||||
dependencyTypeRequired
|
dependencyTypeRequired
|
||||||
dependencyTypeTool
|
dependencyTypeTool
|
||||||
@ -102,10 +106,12 @@ const (
|
|||||||
dependencyTypeInclude
|
dependencyTypeInclude
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type modloaderType uint8
|
||||||
|
|
||||||
//noinspection GoUnusedConst
|
//noinspection GoUnusedConst
|
||||||
const (
|
const (
|
||||||
// modloaderTypeAny should not be passed to the API - it does not work
|
// modloaderTypeAny should not be passed to the API - it does not work
|
||||||
modloaderTypeAny int = iota
|
modloaderTypeAny modloaderType = iota
|
||||||
modloaderTypeForge
|
modloaderTypeForge
|
||||||
modloaderTypeCauldron
|
modloaderTypeCauldron
|
||||||
modloaderTypeLiteloader
|
modloaderTypeLiteloader
|
||||||
@ -131,9 +137,11 @@ var modloaderIds = [...]string{
|
|||||||
"quilt",
|
"quilt",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type hashAlgo uint8
|
||||||
|
|
||||||
//noinspection GoUnusedConst
|
//noinspection GoUnusedConst
|
||||||
const (
|
const (
|
||||||
hashAlgoSHA1 int = iota + 1
|
hashAlgoSHA1 hashAlgo = iota + 1
|
||||||
hashAlgoMD5
|
hashAlgoMD5
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -142,7 +150,7 @@ type modInfo struct {
|
|||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Summary string `json:"summary"`
|
Summary string `json:"summary"`
|
||||||
Slug string `json:"slug"`
|
Slug string `json:"slug"`
|
||||||
ID int `json:"id"`
|
ID uint32 `json:"id"`
|
||||||
GameID uint32 `json:"gameId"`
|
GameID uint32 `json:"gameId"`
|
||||||
PrimaryCategoryID uint32 `json:"primaryCategoryId"`
|
PrimaryCategoryID uint32 `json:"primaryCategoryId"`
|
||||||
ClassID uint32 `json:"classId"`
|
ClassID uint32 `json:"classId"`
|
||||||
@ -151,10 +159,10 @@ type modInfo struct {
|
|||||||
// TODO: check how twitch launcher chooses which one to use, when you are on beta/alpha channel?!
|
// TODO: check how twitch launcher chooses which one to use, when you are on beta/alpha channel?!
|
||||||
// or does it not have the concept of release channels?!
|
// or does it not have the concept of release channels?!
|
||||||
GameVersion string `json:"gameVersion"`
|
GameVersion string `json:"gameVersion"`
|
||||||
ID int `json:"fileId"`
|
ID uint32 `json:"fileId"`
|
||||||
Name string `json:"filename"`
|
Name string `json:"filename"`
|
||||||
FileType int `json:"releaseType"`
|
FileType fileType `json:"releaseType"`
|
||||||
Modloader int `json:"modLoader"`
|
Modloader modloaderType `json:"modLoader"`
|
||||||
} `json:"latestFilesIndexes"`
|
} `json:"latestFilesIndexes"`
|
||||||
ModLoaders []string `json:"modLoaders"`
|
ModLoaders []string `json:"modLoaders"`
|
||||||
Links struct {
|
Links struct {
|
||||||
@ -162,12 +170,12 @@ type modInfo struct {
|
|||||||
} `json:"links"`
|
} `json:"links"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfApiClient) getModInfo(modID int) (modInfo, error) {
|
func (c *cfApiClient) getModInfo(modID uint32) (modInfo, error) {
|
||||||
var infoRes struct {
|
var infoRes struct {
|
||||||
Data modInfo `json:"data"`
|
Data modInfo `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
idStr := strconv.Itoa(modID)
|
idStr := strconv.FormatUint(uint64(modID), 10)
|
||||||
resp, err := c.makeGet("/v1/mods/" + idStr)
|
resp, err := c.makeGet("/v1/mods/" + idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return modInfo{}, fmt.Errorf("failed to request addon data for ID %d: %w", modID, err)
|
return modInfo{}, fmt.Errorf("failed to request addon data for ID %d: %w", modID, err)
|
||||||
@ -185,13 +193,13 @@ func (c *cfApiClient) getModInfo(modID int) (modInfo, error) {
|
|||||||
return infoRes.Data, nil
|
return infoRes.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfApiClient) getModInfoMultiple(modIDs []int) ([]modInfo, error) {
|
func (c *cfApiClient) getModInfoMultiple(modIDs []uint32) ([]modInfo, error) {
|
||||||
var infoRes struct {
|
var infoRes struct {
|
||||||
Data []modInfo `json:"data"`
|
Data []modInfo `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
modIDsData, err := json.Marshal(struct {
|
modIDsData, err := json.Marshal(struct {
|
||||||
ModIDs []int `json:"modIds"`
|
ModIDs []uint32 `json:"modIds"`
|
||||||
}{
|
}{
|
||||||
ModIDs: modIDs,
|
ModIDs: modIDs,
|
||||||
})
|
})
|
||||||
@ -214,32 +222,31 @@ func (c *cfApiClient) getModInfoMultiple(modIDs []int) ([]modInfo, error) {
|
|||||||
|
|
||||||
// modFileInfo is a subset of the deserialised JSON response from the Curse API for mod files
|
// modFileInfo is a subset of the deserialised JSON response from the Curse API for mod files
|
||||||
type modFileInfo struct {
|
type modFileInfo struct {
|
||||||
ID int `json:"id"`
|
ID uint32 `json:"id"`
|
||||||
ModID int `json:"modId"`
|
ModID uint32 `json:"modId"`
|
||||||
FileName string `json:"fileName"`
|
FileName string `json:"fileName"`
|
||||||
FriendlyName string `json:"displayName"`
|
FriendlyName string `json:"displayName"`
|
||||||
Date time.Time `json:"fileDate"`
|
Date time.Time `json:"fileDate"`
|
||||||
Length int `json:"fileLength"`
|
Length uint64 `json:"fileLength"`
|
||||||
FileType int `json:"releaseType"`
|
FileType fileType `json:"releaseType"`
|
||||||
// fileStatus? means latest/preferred?
|
|
||||||
// According to the CurseForge API T&Cs, this must not be saved or cached
|
// According to the CurseForge API T&Cs, this must not be saved or cached
|
||||||
DownloadURL string `json:"downloadUrl"`
|
DownloadURL string `json:"downloadUrl"`
|
||||||
GameVersions []string `json:"gameVersions"`
|
GameVersions []string `json:"gameVersions"`
|
||||||
Fingerprint int `json:"fileFingerprint"`
|
Fingerprint uint32 `json:"fileFingerprint"`
|
||||||
Dependencies []struct {
|
Dependencies []struct {
|
||||||
ModID int `json:"modId"`
|
ModID uint32 `json:"modId"`
|
||||||
Type int `json:"relationType"`
|
Type dependencyType `json:"relationType"`
|
||||||
} `json:"dependencies"`
|
} `json:"dependencies"`
|
||||||
|
|
||||||
Hashes []struct {
|
Hashes []struct {
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
Algorithm int `json:"algo"`
|
Algorithm hashAlgo `json:"algo"`
|
||||||
} `json:"hashes"`
|
} `json:"hashes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i modFileInfo) getBestHash() (hash string, hashFormat string) {
|
func (i modFileInfo) getBestHash() (hash string, hashFormat string) {
|
||||||
// TODO: check if the hash is invalid (e.g. 0)
|
// TODO: check if the hash is invalid (e.g. 0)
|
||||||
hash = strconv.Itoa(i.Fingerprint)
|
hash = strconv.FormatUint(uint64(i.Fingerprint), 10)
|
||||||
hashFormat = "murmur2"
|
hashFormat = "murmur2"
|
||||||
hashPreferred := 0
|
hashPreferred := 0
|
||||||
|
|
||||||
@ -263,13 +270,13 @@ func (i modFileInfo) getBestHash() (hash string, hashFormat string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfApiClient) getFileInfo(modID int, fileID int) (modFileInfo, error) {
|
func (c *cfApiClient) getFileInfo(modID uint32, fileID uint32) (modFileInfo, error) {
|
||||||
var infoRes struct {
|
var infoRes struct {
|
||||||
Data modFileInfo `json:"data"`
|
Data modFileInfo `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
modIDStr := strconv.Itoa(modID)
|
modIDStr := strconv.FormatUint(uint64(modID), 10)
|
||||||
fileIDStr := strconv.Itoa(fileID)
|
fileIDStr := strconv.FormatUint(uint64(fileID), 10)
|
||||||
|
|
||||||
resp, err := c.makeGet("/v1/mods/" + modIDStr + "/files/" + fileIDStr)
|
resp, err := c.makeGet("/v1/mods/" + modIDStr + "/files/" + fileIDStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -288,13 +295,13 @@ func (c *cfApiClient) getFileInfo(modID int, fileID int) (modFileInfo, error) {
|
|||||||
return infoRes.Data, nil
|
return infoRes.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfApiClient) getFileInfoMultiple(fileIDs []int) ([]modFileInfo, error) {
|
func (c *cfApiClient) getFileInfoMultiple(fileIDs []uint32) ([]modFileInfo, error) {
|
||||||
var infoRes struct {
|
var infoRes struct {
|
||||||
Data []modFileInfo `json:"data"`
|
Data []modFileInfo `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
fileIDsData, err := json.Marshal(struct {
|
fileIDsData, err := json.Marshal(struct {
|
||||||
FileIDs []int `json:"fileIds"`
|
FileIDs []uint32 `json:"fileIds"`
|
||||||
}{
|
}{
|
||||||
FileIDs: fileIDs,
|
FileIDs: fileIDs,
|
||||||
})
|
})
|
||||||
@ -315,16 +322,16 @@ func (c *cfApiClient) getFileInfoMultiple(fileIDs []int) ([]modFileInfo, error)
|
|||||||
return infoRes.Data, nil
|
return infoRes.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfApiClient) getSearch(searchTerm string, slug string, gameID int, classID int, categoryID int, gameVersion string, modloaderType int) ([]modInfo, error) {
|
func (c *cfApiClient) getSearch(searchTerm string, slug string, gameID uint32, classID uint32, categoryID uint32, gameVersion string, modloaderType modloaderType) ([]modInfo, error) {
|
||||||
var infoRes struct {
|
var infoRes struct {
|
||||||
Data []modInfo `json:"data"`
|
Data []modInfo `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
q := url.Values{}
|
q := url.Values{}
|
||||||
q.Set("gameId", strconv.Itoa(gameID))
|
q.Set("gameId", strconv.FormatUint(uint64(gameID), 10))
|
||||||
q.Set("pageSize", "10")
|
q.Set("pageSize", "10")
|
||||||
if classID != 0 {
|
if classID != 0 {
|
||||||
q.Set("classId", strconv.Itoa(classID))
|
q.Set("classId", strconv.FormatUint(uint64(classID), 10))
|
||||||
}
|
}
|
||||||
if slug != "" {
|
if slug != "" {
|
||||||
q.Set("slug", slug)
|
q.Set("slug", slug)
|
||||||
@ -332,7 +339,7 @@ func (c *cfApiClient) getSearch(searchTerm string, slug string, gameID int, clas
|
|||||||
// If classID and slug are provided, don't bother filtering by anything else (should be unique)
|
// If classID and slug are provided, don't bother filtering by anything else (should be unique)
|
||||||
if classID == 0 && slug == "" {
|
if classID == 0 && slug == "" {
|
||||||
if categoryID != 0 {
|
if categoryID != 0 {
|
||||||
q.Set("categoryId", strconv.Itoa(categoryID))
|
q.Set("categoryId", strconv.FormatUint(uint64(categoryID), 10))
|
||||||
}
|
}
|
||||||
if searchTerm != "" {
|
if searchTerm != "" {
|
||||||
q.Set("searchFilter", searchTerm)
|
q.Set("searchFilter", searchTerm)
|
||||||
@ -341,7 +348,7 @@ func (c *cfApiClient) getSearch(searchTerm string, slug string, gameID int, clas
|
|||||||
q.Set("gameVersion", gameVersion)
|
q.Set("gameVersion", gameVersion)
|
||||||
}
|
}
|
||||||
if modloaderType != modloaderTypeAny {
|
if modloaderType != modloaderTypeAny {
|
||||||
q.Set("modLoaderType", strconv.Itoa(modloaderType))
|
q.Set("modLoaderType", strconv.FormatUint(uint64(modloaderType), 10))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,9 +365,11 @@ func (c *cfApiClient) getSearch(searchTerm string, slug string, gameID int, clas
|
|||||||
return infoRes.Data, nil
|
return infoRes.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type gameStatus uint8
|
||||||
|
|
||||||
//noinspection GoUnusedConst
|
//noinspection GoUnusedConst
|
||||||
const (
|
const (
|
||||||
gameStatusDraft int = iota + 1
|
gameStatusDraft gameStatus = iota + 1
|
||||||
gameStatusTest
|
gameStatusTest
|
||||||
gameStatusPendingReview
|
gameStatusPendingReview
|
||||||
gameStatusRejected
|
gameStatusRejected
|
||||||
@ -368,9 +377,11 @@ const (
|
|||||||
gameStatusLive
|
gameStatusLive
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type gameApiStatus uint8
|
||||||
|
|
||||||
//noinspection GoUnusedConst
|
//noinspection GoUnusedConst
|
||||||
const (
|
const (
|
||||||
gameApiStatusPrivate int = iota + 1
|
gameApiStatusPrivate gameApiStatus = iota + 1
|
||||||
gameApiStatusPublic
|
gameApiStatusPublic
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -378,8 +389,8 @@ type cfGame struct {
|
|||||||
ID uint32 `json:"id"`
|
ID uint32 `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Slug string `json:"slug"`
|
Slug string `json:"slug"`
|
||||||
Status int `json:"status"`
|
Status gameStatus `json:"status"`
|
||||||
APIStatus int `json:"apiStatus"`
|
APIStatus gameApiStatus `json:"apiStatus"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfApiClient) getGames() ([]cfGame, error) {
|
func (c *cfApiClient) getGames() ([]cfGame, error) {
|
||||||
@ -401,18 +412,18 @@ func (c *cfApiClient) getGames() ([]cfGame, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cfCategory struct {
|
type cfCategory struct {
|
||||||
ID int `json:"id"`
|
ID uint32 `json:"id"`
|
||||||
Slug string `json:"slug"`
|
Slug string `json:"slug"`
|
||||||
IsClass bool `json:"isClass"`
|
IsClass bool `json:"isClass"`
|
||||||
ClassID int `json:"classId"`
|
ClassID uint32 `json:"classId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfApiClient) getCategories(gameID int) ([]cfCategory, error) {
|
func (c *cfApiClient) getCategories(gameID uint32) ([]cfCategory, error) {
|
||||||
var infoRes struct {
|
var infoRes struct {
|
||||||
Data []cfCategory `json:"data"`
|
Data []cfCategory `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := c.makeGet("/v1/categories?gameId=" + strconv.Itoa(gameID))
|
resp, err := c.makeGet("/v1/categories?gameId=" + strconv.FormatUint(uint64(gameID), 10))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []cfCategory{}, fmt.Errorf("failed to retrieve category list for game %v: %w", gameID, err)
|
return []cfCategory{}, fmt.Errorf("failed to retrieve category list for game %v: %w", gameID, err)
|
||||||
}
|
}
|
||||||
@ -428,24 +439,24 @@ func (c *cfApiClient) getCategories(gameID int) ([]cfCategory, error) {
|
|||||||
type addonFingerprintResponse struct {
|
type addonFingerprintResponse struct {
|
||||||
IsCacheBuilt bool `json:"isCacheBuilt"`
|
IsCacheBuilt bool `json:"isCacheBuilt"`
|
||||||
ExactMatches []struct {
|
ExactMatches []struct {
|
||||||
ID int `json:"id"`
|
ID uint32 `json:"id"`
|
||||||
File modFileInfo `json:"file"`
|
File modFileInfo `json:"file"`
|
||||||
LatestFiles []modFileInfo `json:"latestFiles"`
|
LatestFiles []modFileInfo `json:"latestFiles"`
|
||||||
} `json:"exactMatches"`
|
} `json:"exactMatches"`
|
||||||
ExactFingerprints []int `json:"exactFingerprints"`
|
ExactFingerprints []uint32 `json:"exactFingerprints"`
|
||||||
PartialMatches []int `json:"partialMatches"`
|
PartialMatches []uint32 `json:"partialMatches"`
|
||||||
PartialMatchFingerprints struct{} `json:"partialMatchFingerprints"`
|
PartialMatchFingerprints struct{} `json:"partialMatchFingerprints"`
|
||||||
InstalledFingerprints []int `json:"installedFingerprints"`
|
InstalledFingerprints []uint32 `json:"installedFingerprints"`
|
||||||
UnmatchedFingerprints []int `json:"unmatchedFingerprints"`
|
UnmatchedFingerprints []uint32 `json:"unmatchedFingerprints"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cfApiClient) getFingerprintInfo(hashes []int) (addonFingerprintResponse, error) {
|
func (c *cfApiClient) getFingerprintInfo(hashes []uint32) (addonFingerprintResponse, error) {
|
||||||
var infoRes struct {
|
var infoRes struct {
|
||||||
Data addonFingerprintResponse `json:"data"`
|
Data addonFingerprintResponse `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
hashesData, err := json.Marshal(struct {
|
hashesData, err := json.Marshal(struct {
|
||||||
Fingerprints []int `json:"fingerprints"`
|
Fingerprints []uint32 `json:"fingerprints"`
|
||||||
}{
|
}{
|
||||||
Fingerprints: hashes,
|
Fingerprints: hashes,
|
||||||
})
|
})
|
||||||
|
@ -56,7 +56,7 @@ type Mod struct {
|
|||||||
} `json:"license"`
|
} `json:"license"`
|
||||||
ClientSide string `json:"client_side"` //The support range for the client mod - required, optional, unsupported, or unknown
|
ClientSide string `json:"client_side"` //The support range for the client mod - required, optional, unsupported, or unknown
|
||||||
ServerSide string `json:"server_side"` //The support range for the server mod - required, optional, unsupported, or unknown
|
ServerSide string `json:"server_side"` //The support range for the server mod - required, optional, unsupported, or unknown
|
||||||
Downloads int `json:"downloads"` //The total number of downloads the mod has
|
Downloads uint32 `json:"downloads"` //The total number of downloads the mod has
|
||||||
Categories []string `json:"categories"` //A list of the categories that the mod is in
|
Categories []string `json:"categories"` //A list of the categories that the mod is in
|
||||||
Versions []string `json:"versions"` //A list of ids for versions of the mod
|
Versions []string `json:"versions"` //A list of ids for versions of the mod
|
||||||
IconUrl string `json:"icon_url"` //The URL of the icon of the mod (Optional)
|
IconUrl string `json:"icon_url"` //The URL of the icon of the mod (Optional)
|
||||||
@ -74,7 +74,7 @@ type ModResult struct {
|
|||||||
Description string `json:"description"` //A short description of the mod
|
Description string `json:"description"` //A short description of the mod
|
||||||
Categories []string `json:"categories"` //A list of the categories the mod is in
|
Categories []string `json:"categories"` //A list of the categories the mod is in
|
||||||
Versions []string `json:"versions"` //A list of the minecraft versions supported by the mod
|
Versions []string `json:"versions"` //A list of the minecraft versions supported by the mod
|
||||||
Downloads int `json:"downloads"` //The total number of downloads for the mod
|
Downloads uint32 `json:"downloads"` //The total number of downloads for the mod
|
||||||
PageUrl string `json:"page_url"` //A link to the mod's main page;
|
PageUrl string `json:"page_url"` //A link to the mod's main page;
|
||||||
IconUrl string `json:"icon_url"` //The url of the mod's icon
|
IconUrl string `json:"icon_url"` //The url of the mod's icon
|
||||||
AuthorUrl string `json:"author_url"` //The url of the mod's author
|
AuthorUrl string `json:"author_url"` //The url of the mod's author
|
||||||
@ -89,9 +89,9 @@ type ModResult struct {
|
|||||||
|
|
||||||
type ModSearchResult struct {
|
type ModSearchResult struct {
|
||||||
Hits []ModResult `json:"hits"` //The list of results
|
Hits []ModResult `json:"hits"` //The list of results
|
||||||
Offset int `json:"offset"` //The number of results that were skipped by the query
|
Offset uint32 `json:"offset"` //The number of results that were skipped by the query
|
||||||
Limit int `json:"limit"` //The number of mods returned by the query
|
Limit uint32 `json:"limit"` //The number of mods returned by the query
|
||||||
TotalHits int `json:"total_hits"` //The total number of mods that the query found
|
TotalHits uint32 `json:"total_hits"` //The total number of mods that the query found
|
||||||
}
|
}
|
||||||
|
|
||||||
type Version struct {
|
type Version struct {
|
||||||
@ -103,7 +103,7 @@ type Version struct {
|
|||||||
VersionNumber string `json:"version_number"` //The version number. Ideally will follow semantic versioning
|
VersionNumber string `json:"version_number"` //The version number. Ideally will follow semantic versioning
|
||||||
Changelog string `json:"changelog"` //The changelog for this version of the mod. (Optional)
|
Changelog string `json:"changelog"` //The changelog for this version of the mod. (Optional)
|
||||||
DatePublished string `json:"date_published"` //The date that this version was published
|
DatePublished string `json:"date_published"` //The date that this version was published
|
||||||
Downloads int `json:"downloads"` //The number of downloads this specific version has
|
Downloads uint32 `json:"downloads"` //The number of downloads this specific version has
|
||||||
VersionType string `json:"version_type"` //The type of the release - alpha, beta, or release
|
VersionType string `json:"version_type"` //The type of the release - alpha, beta, or release
|
||||||
Files []VersionFile `json:"files"` //A list of files available for download for this version
|
Files []VersionFile `json:"files"` //A list of files available for download for this version
|
||||||
//Dependencies []string `json:"dependencies"` //A list of specific versions of mods that this version depends on
|
//Dependencies []string `json:"dependencies"` //A list of specific versions of mods that this version depends on
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package modrinth
|
package modrinth
|
||||||
|
|
||||||
type Pack struct {
|
type Pack struct {
|
||||||
FormatVersion int `json:"formatVersion"`
|
FormatVersion uint32 `json:"formatVersion"`
|
||||||
Game string `json:"game"`
|
Game string `json:"game"`
|
||||||
VersionID string `json:"versionId"`
|
VersionID string `json:"versionId"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user