Skip to content

Commit 1fa3adf

Browse files
authored
Merge pull request #94 from knoxfighter/feature/mod-compatibility
Feature/mod compatibility
2 parents 5384838 + bd8a595 commit 1fa3adf

15 files changed

Lines changed: 242 additions & 47 deletions

File tree

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ install:
1212
- go get github.com/hpcloud/tail
1313
- go get github.com/gorilla/websocket
1414
- go get github.com/majormjr/rcon
15+
- go get github.com/Masterminds/semver
1516
- export GOPATH="$HOME/gopath/src/github.com/mroote/factorio-server-manager/:$GOPATH"
1617

1718
script:

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ go get github.com/gorilla/mux
145145
go get github.com/hpcloud/tail
146146
go get github.com/gorilla/websocket
147147
go get github.com/majormjr/rcon
148+
go get github.com/Masterminds/semver
148149
```
149150

150151
3. Now you will want to go into the src folder for example "C:\FS\factorio-server-manager\src" once there hold down left shift and right click an empty area of the folder. Then click "Open command windows here"

app/dist/dist/css/factorio-server-manager.css

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,12 @@ div.console-prompt-box {
6969
}
7070

7171
.sweet-alert table tr:nth-child(even) {
72-
background: rgba(68, 68, 68, 0.31);
72+
background: rgba(68, 68, 68, 0.21);
7373
}
74+
75+
.sweet-alert table tr.incompatible {
76+
background: rgba(255, 68, 68, 0.21);
77+
}
78+
.sweet-alert table tr:nth-child(even).incompatible {
79+
background: rgba(255, 0, 0, 0.31);
80+
}

gopkglist

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ github.com/go-ini/ini
33
github.com/gorilla/mux
44
github.com/gorilla/websocket
55
github.com/hpcloud/tail
6-
github.com/majormjr/rcon
6+
github.com/majormjr/rcon
7+
github.com/Masterminds/semver

src/factorio_server.go

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,26 @@ import (
1717
"time"
1818

1919
"github.com/majormjr/rcon"
20+
"regexp"
21+
"github.com/Masterminds/semver"
2022
)
2123

2224
type FactorioServer struct {
23-
Cmd *exec.Cmd `json:"-"`
24-
Savefile string `json:"savefile"`
25-
Latency int `json:"latency"`
26-
BindIP string `json:"bindip"`
27-
Port int `json:"port"`
28-
Running bool `json:"running"`
29-
StdOut io.ReadCloser `json:"-"`
30-
StdErr io.ReadCloser `json:"-"`
31-
StdIn io.WriteCloser `json:"-"`
32-
Settings map[string]interface{} `json:"-"`
33-
Rcon *rcon.RemoteConsole `json:"-"`
34-
LogChan chan []string `json:"-"`
25+
Cmd *exec.Cmd `json:"-"`
26+
Savefile string `json:"savefile"`
27+
Latency int `json:"latency"`
28+
BindIP string `json:"bindip"`
29+
Port int `json:"port"`
30+
Running bool `json:"running"`
31+
Version string `json:"fac_version"`
32+
BaseModVersion string `json:"base_mod_version"`
33+
SemVerVersion *semver.Version `json:"-"`
34+
StdOut io.ReadCloser `json:"-"`
35+
StdErr io.ReadCloser `json:"-"`
36+
StdIn io.WriteCloser `json:"-"`
37+
Settings map[string]interface{} `json:"-"`
38+
Rcon *rcon.RemoteConsole `json:"-"`
39+
LogChan chan []string `json:"-"`
3540
}
3641

3742
func randomPort() int {
@@ -92,6 +97,38 @@ func initFactorio() (f *FactorioServer, err error) {
9297

9398
log.Printf("Loaded Factorio settings from %s\n", settingsPath)
9499

100+
101+
//Load factorio version
102+
out, err := exec.Command(config.FactorioBinary, "--version").Output()
103+
if err != nil {
104+
log.Printf("error on loading factorio version: %s", err)
105+
return
106+
}
107+
108+
reg := regexp.MustCompile("Version.*?((\\d+\\.)?(\\d+\\.)?(\\*|\\d+)+)")
109+
found := reg.FindStringSubmatch(string(out))
110+
f.Version = found[1]
111+
112+
//Load baseMod version
113+
baseModInfoFile := filepath.Join(config.FactorioDir, "data", "base", "info.json")
114+
bmifBa, err := ioutil.ReadFile(baseModInfoFile)
115+
if err != nil {
116+
log.Printf("couldn't open baseMods info.json: %s", err)
117+
return
118+
}
119+
var modInfo ModInfo
120+
err = json.Unmarshal(bmifBa, &modInfo)
121+
if err != nil {
122+
log.Printf("error unmarshalling baseMods info.json to a modInfo: %s", err)
123+
return
124+
}
125+
126+
f.BaseModVersion = modInfo.Version
127+
f.SemVerVersion, err = semver.NewVersion(modInfo.Version)
128+
if err != nil {
129+
log.Fatalf("error loading semver-factorio-version: %s", err)
130+
}
131+
95132
return
96133
}
97134

src/handlers.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,24 @@ func CheckServer(w http.ResponseWriter, r *http.Request) {
435435
}
436436
}
437437

438+
func FactorioVersion(w http.ResponseWriter, r *http.Request) {
439+
resp := JSONResponse{
440+
Success: true,
441+
}
442+
443+
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
444+
445+
status := map[string]string{}
446+
status["version"] = FactorioServ.Version
447+
status["base_mod_version"] = FactorioServ.BaseModVersion
448+
449+
resp.Data = status
450+
451+
if err := json.NewEncoder(w).Encode(resp); err != nil {
452+
log.Printf("Error loading Factorio Version: %s", err)
453+
}
454+
}
455+
438456
func LoginUser(w http.ResponseWriter, r *http.Request) {
439457
resp := JSONResponse{
440458
Success: false,

src/mod_Mods.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ func (mods *Mods) listInstalledMods() ModsResultList {
5858
modsResult.Title = modInfo.Title
5959
modsResult.Version = modInfo.Version
6060
modsResult.FactorioVersion = modInfo.FactorioVersion
61+
modsResult.Compatibility = modInfo.Compatibility
6162

6263
for _, simpleMod := range mods.ModSimpleList.Mods {
6364
if simpleMod.Name == modsResult.Name {

src/mod_modInfo.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,22 @@ import (
1010
"log"
1111
"os"
1212
"path/filepath"
13+
"strings"
1314
)
1415

1516
type ModInfoList struct {
1617
Mods []ModInfo `json:"mods"`
1718
Destination string `json:"-"`
1819
}
1920
type ModInfo struct {
20-
Name string `json:"name"`
21-
Version string `json:"version"`
22-
Title string `json:"title"`
23-
Author string `json:"author"`
24-
FileName string `json:"file_name"`
25-
FactorioVersion string `json:"factorio_version"`
21+
Name string `json:"name"`
22+
Version string `json:"version"`
23+
Title string `json:"title"`
24+
Author string `json:"author"`
25+
FileName string `json:"file_name"`
26+
FactorioVersion string `json:"factorio_version"`
27+
Dependencies []string `json:"dependencies"`
28+
Compatibility bool `json:"compatibility"`
2629
}
2730

2831
func newModInfoList(destination string) (ModInfoList, error) {
@@ -46,6 +49,7 @@ func (modInfoList *ModInfoList) listInstalledMods() error {
4649

4750
err = filepath.Walk(modInfoList.Destination, func(path string, info os.FileInfo, err error) error {
4851
if !info.IsDir() && filepath.Ext(path) == ".zip" {
52+
4953
err = fileLock.RLock(path)
5054
if err != nil && err == lockfile.ErrorAlreadyLocked {
5155
log.Println(err)
@@ -69,6 +73,29 @@ func (modInfoList *ModInfoList) listInstalledMods() error {
6973
}
7074

7175
modInfo.FileName = info.Name()
76+
77+
var baseDependency string
78+
for _, dependency := range modInfo.Dependencies {
79+
if strings.HasPrefix(dependency, "base") {
80+
baseDependency = strings.Split(dependency, "=")[1]
81+
break
82+
}
83+
}
84+
if baseDependency != "" {
85+
modInfo.Compatibility, err = checkModCompatibility(baseDependency)
86+
if err != nil {
87+
log.Printf("error checking mod compatibility: %s", err)
88+
return err
89+
}
90+
} else {
91+
log.Println("error finding basemodDependency. Using FactorioVersion...")
92+
modInfo.Compatibility, err = checkModCompatibility(modInfo.FactorioVersion + ".0")
93+
if err != nil {
94+
log.Printf("error checking Compatibility with FactorioVersion: %s", err)
95+
return err
96+
}
97+
}
98+
7299
modInfoList.Mods = append(modInfoList.Mods, modInfo)
73100
}
74101

src/mods.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"os"
1313
"path/filepath"
1414
"strings"
15+
"github.com/Masterminds/semver"
1516
)
1617

1718
type LoginErrorResponse struct {
@@ -274,9 +275,9 @@ func modStartUp() {
274275
},
275276
},
276277
}
277-
new_json, _ := json.Marshal(modSimpleList)
278+
newJson, _ := json.Marshal(modSimpleList)
278279

279-
err = ioutil.WriteFile(modSimpleList.Destination+"/mod-list.json", new_json, 0664)
280+
err = ioutil.WriteFile(modSimpleList.Destination+"/mod-list.json", newJson, 0664)
280281
if err != nil {
281282
log.Printf("error when writing new mod-list: %s", err)
282283
return err
@@ -344,3 +345,19 @@ func modStartUp() {
344345
}
345346
}
346347
}
348+
349+
func checkModCompatibility(modVersion string) (compatible bool, err error) {
350+
compatible = false
351+
modVersion = strings.TrimSpace(modVersion)
352+
if !strings.HasPrefix(modVersion, "~") {
353+
modVersion = "~" + modVersion
354+
}
355+
356+
constraint, err := semver.NewConstraint(modVersion)
357+
if err != nil {
358+
log.Printf("error loading constraint: %s", err)
359+
return
360+
}
361+
362+
return constraint.Check(FactorioServ.SemVerVersion), nil
363+
}

src/routes.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,11 @@ var apiRoutes = Routes{
273273
"GET",
274274
"/server/status",
275275
CheckServer,
276+
}, {
277+
"FactorioVersion",
278+
"GET",
279+
"/server/facVersion",
280+
FactorioVersion,
276281
}, {
277282
"LogoutUser",
278283
"GET",

0 commit comments

Comments
 (0)