Панель видит моды Build 42 и названия больших сборок
CI / test (push) Successful in 23s
Release / release (push) Successful in 29s

В Build 42 mod.info лежит не в корне мода, а в папке версии: common, 42,
42.16. Сканер смотрел только в корень, и такие моды выглядели нескачанными
с неизвестным Mod ID — включить их через панель было нельзя. На реальной
мастерской находилось 237 модов из 399.

Названия из мастерской фронтенд запрашивал одним списком, а эндпоинт не
принимает больше двухсот идентификаторов за раз. У сборки на 284 пакета
запрос падал целиком, ошибка молча проглатывалась, и вместо названий
оставались одни номера. Теперь запрос идёт партиями, а полная неудача
больше не остаётся незамеченной.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-07 17:38:23 +03:00
co-authored by Claude Opus 5
parent 5d9bedaad2
commit 6d27fd049d
5 changed files with 148 additions and 6 deletions
+54 -1
View File
@@ -91,7 +91,11 @@ func readModsDir(dir, workshopID string) []InstalledMod {
continue
}
modDir := filepath.Join(dir, entry.Name())
mod, ok := readModInfo(filepath.Join(modDir, "mod.info"))
info, found := modInfoPath(modDir)
if !found {
continue
}
mod, ok := readModInfo(info)
if !ok {
continue
}
@@ -105,6 +109,55 @@ func readModsDir(dir, workshopID string) []InstalledMod {
return out
}
// modInfoPath ищет mod.info внутри папки мода.
//
// В Build 41 он лежал в корне, а в Build 42 мод раскладывают по папкам версий:
// common — общая часть, 42 и 42.16 — под конкретные сборки игры. Если искать
// только в корне, мод из мастерской выглядит нескачанным, его Mod ID остаётся
// неизвестным и включить его через панель нельзя.
func modInfoPath(modDir string) (string, bool) {
if root := filepath.Join(modDir, "mod.info"); fileExists(root) {
return root, true
}
entries, err := os.ReadDir(modDir)
if err != nil {
return "", false
}
var versions []string
common := ""
for _, entry := range entries {
if !entry.IsDir() {
continue
}
if !fileExists(filepath.Join(modDir, entry.Name(), "mod.info")) {
continue
}
if strings.EqualFold(entry.Name(), "common") {
common = entry.Name()
continue
}
versions = append(versions, entry.Name())
}
// Сначала самая свежая версия: «42.16» важнее «42», а «common» —
// последняя, это общая часть на случай, когда версии своего mod.info не
// завели. Обратный порядок строк для номеров версий работает и здесь.
sort.Sort(sort.Reverse(sort.StringSlice(versions)))
if common != "" {
versions = append(versions, common)
}
if len(versions) == 0 {
return "", false
}
return filepath.Join(modDir, versions[0], "mod.info"), true
}
func fileExists(path string) bool {
info, err := os.Stat(path)
return err == nil && !info.IsDir()
}
// readModInfo разбирает mod.info — файл вида "ключ=значение" с необязательными
// комментариями. Нас интересуют id, name и description.
func readModInfo(path string) (InstalledMod, bool) {