181 lines
3.9 KiB
Go
181 lines
3.9 KiB
Go
package modlist
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/charmbracelet/log"
|
|
)
|
|
|
|
// fileRegex matches
|
|
const fileRegex string = "([\\w\\s-]+)_([0-9.]+)\\.zip"
|
|
|
|
/// Modlist types and related functions.
|
|
|
|
// Mod holds data about a single mod.
|
|
type Mod struct {
|
|
Name string `json:"name"`
|
|
Enabled bool `json:"enabled"`
|
|
}
|
|
|
|
// Modlist holds a slice of mods.
|
|
type Modlist struct {
|
|
Mods []Mod `json:"mods"`
|
|
}
|
|
|
|
/// Non exported functions
|
|
|
|
func (modlist *Modlist) setModStatus(name string, status bool) {
|
|
for i := range modlist.Mods {
|
|
mod := &modlist.Mods[i]
|
|
if mod.Name == name && mod.Enabled != status {
|
|
mod.Enabled = status
|
|
log.Debugf("Setting status of mod %s to %v", mod.Name, mod.Enabled)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (modlist *Modlist) setAllStatus(status bool) {
|
|
for i := range modlist.Mods {
|
|
mod := &modlist.Mods[i]
|
|
mod.Enabled = status
|
|
log.Debugf("Setting status of mod %s to %v", mod.Name, mod.Enabled)
|
|
}
|
|
}
|
|
|
|
// EnableMod enables the given mod.
|
|
func (modlist *Modlist) EnableMod(name string) {
|
|
modlist.setModStatus(name, true)
|
|
}
|
|
|
|
// EnableMods enables the given mods.
|
|
func (modlist *Modlist) EnableMods(names ...string) {
|
|
for _, name := range names {
|
|
modlist.EnableMod(name)
|
|
}
|
|
}
|
|
|
|
// DisableMod disables the given mod.
|
|
func (modlist *Modlist) DisableMod(name string) {
|
|
modlist.setModStatus(name, false)
|
|
}
|
|
|
|
// DisableMods disables the given mods.
|
|
func (modlist *Modlist) DisableMods(names ...string) {
|
|
for _, name := range names {
|
|
modlist.DisableMod(name)
|
|
}
|
|
}
|
|
|
|
// EnableAll enables all mods.
|
|
func (modlist *Modlist) EnableAll() {
|
|
modlist.setAllStatus(true)
|
|
}
|
|
|
|
// DisableAll disables all mods.
|
|
func (modlist *Modlist) DisableAll() {
|
|
modlist.setAllStatus(false)
|
|
}
|
|
|
|
// HasMod reports if a modlist has a mod with name `s`
|
|
func (modlist *Modlist) HasMod(s string) bool {
|
|
for _, mod := range modlist.Mods {
|
|
if mod.Name == s {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// HasMod reports if a modlist has an enabled mod with name `s`
|
|
func (modlist *Modlist) HasModEnabled(s string) bool {
|
|
for _, mod := range modlist.Mods {
|
|
if mod.Name == s && mod.Enabled {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Print out each mod and its status.
|
|
func (modlist *Modlist) Print(prefix string) {
|
|
log.Info(prefix + ": {")
|
|
for _, mod := range modlist.Mods {
|
|
var endis string
|
|
// I wish go had a ternary so this could all be in one line
|
|
if mod.Enabled {
|
|
endis = "en"
|
|
} else {
|
|
endis = "dis"
|
|
}
|
|
log.Infof("\t%s: %sabled,", mod.Name, endis)
|
|
}
|
|
log.Info("}")
|
|
}
|
|
|
|
func (modlist *Modlist) String() {
|
|
modlist.Print("mods")
|
|
}
|
|
|
|
/// Functions related to the modlist but that shouldn't be attached to the types
|
|
|
|
// WriteToFile writes the modlist to the given filename.
|
|
func WriteToFile(filename string, mods *Modlist) error {
|
|
data, err := json.MarshalIndent(&mods, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
os.WriteFile(filename, data, os.FileMode(0744))
|
|
log.Infof("Wrote modlist to file %s.", filename)
|
|
return nil
|
|
}
|
|
|
|
// ReadFromFile reads the modlist from the given filename.
|
|
func ReadFromFile(filename string) (Modlist, error) {
|
|
var mods Modlist = Modlist{}
|
|
|
|
data, err := os.ReadFile(filename)
|
|
if err != nil {
|
|
return Modlist{}, err
|
|
}
|
|
|
|
err = json.Unmarshal(data, &mods)
|
|
if err != nil {
|
|
return Modlist{}, err
|
|
}
|
|
|
|
log.Infof("Read modlist from file %s.", filename)
|
|
return mods, nil
|
|
}
|
|
|
|
// AddModsNotInList finds mod archives in the mod folder that aren't in the modlist, and adds them.
|
|
func AddModsNotInList(modsdir string, mods *Modlist) error {
|
|
r := regexp.MustCompile(fileRegex)
|
|
|
|
files, err := os.ReadDir(modsdir)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, file := range files {
|
|
if strings.HasSuffix(file.Name(), ".zip") && !file.IsDir() {
|
|
groups := r.FindAllStringSubmatch(file.Name(), -1)
|
|
name := groups[0][1]
|
|
version := groups[0][2]
|
|
|
|
if !mods.HasMod(name) {
|
|
log.Info("Found %s not in modlist, adding v%s in disabled state.", name, version)
|
|
mods.Mods = append(mods.Mods, Mod{
|
|
Name: name,
|
|
Enabled: false,
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|