From dea0ae36bba49f60f24cc21c47b87de7a95054ba Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Sun, 8 Jul 2018 01:28:43 +0200 Subject: [PATCH 01/10] created new package --- src/vendor/factorioSave/factorioSave.go | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/vendor/factorioSave/factorioSave.go diff --git a/src/vendor/factorioSave/factorioSave.go b/src/vendor/factorioSave/factorioSave.go new file mode 100644 index 00000000..5305b328 --- /dev/null +++ b/src/vendor/factorioSave/factorioSave.go @@ -0,0 +1 @@ +package factorioSave From 702ba38ca5f83726bb8f64af63cb1d7a4d6ebdee Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Sun, 8 Jul 2018 03:15:28 +0200 Subject: [PATCH 02/10] added reading of FactorioSave && added reading of saves in frontend --- src/vendor/factorioSave/factorioSave.go | 344 ++++++++++++++++++++++++ ui/App/components/Mods/ModLoadSave.jsx | 48 ++++ ui/App/components/Mods/ModOverview.jsx | 12 + 3 files changed, 404 insertions(+) create mode 100644 ui/App/components/Mods/ModLoadSave.jsx diff --git a/src/vendor/factorioSave/factorioSave.go b/src/vendor/factorioSave/factorioSave.go index 5305b328..a3f03b01 100644 --- a/src/vendor/factorioSave/factorioSave.go +++ b/src/vendor/factorioSave/factorioSave.go @@ -1 +1,345 @@ package factorioSave + +import ( + "log" + "os" + "encoding/binary" +) + +type version16 struct { + versionShort16 + Revision uint16 +} +type versionShort16 struct { + Major uint16 + Minor uint16 + Build uint16 +} +type versionShort8 struct { + Major uint8 + Minor uint8 + Build uint8 +} +type Header struct { + FactorioVersion version16 + Campaign string + Name string + BaseMod string + Difficulty uint8 + Finished bool + PlayerWon bool + NextLevel string + CanContinue bool + FinishedButContinuing bool + SavingReplay bool + AllowNonAdminDebugOptions bool + LoadedFrom versionShort8 + LoadedFromBuild uint16 + AllowedCommads uint8 + NumMods uint8 + Mods []singleMod +} +type singleMod struct { + Name string + Version versionShort8 + CRC uint32 +} + + +func ReadHeader(filePath string) (Header, error) { + var data Header + + fp, err := os.Open(filePath) + if err != nil { + log.Printf("error opening file: %s", err) + return data, err + } + defer fp.Close() + + data.FactorioVersion, err = readVersion16(fp) + if err != nil { + log.Printf("Cant read FactorioVersion: %s", err) + return data, err + } + + if !data.FactorioVersion.CheckCompatibility(0, 16, 0) { + log.Printf("NOT COMPATIBLE Save-File") + return data, err + } + + data.Campaign, err = readUTF8String(fp) + if err != nil { + log.Printf("Cant read Campaign: %s", err) + return data, err + } + + data.Name, err = readUTF8String(fp) + if err != nil { + log.Printf("Cant read Name: %s", err) + return data, err + } + + data.BaseMod, err = readUTF8String(fp) + if err != nil { + log.Printf("Cant read BaseMod: %s", err) + return data, err + } + + data.Difficulty, err = readUint8(fp) + if err != nil { + log.Printf("Cant read Difficulty: %s", err) + return data, err + } + + data.Finished, err = readBool(fp) + if err != nil { + log.Printf("Couln't read Finished bool: %s", err) + return data, err + } + + data.PlayerWon, err = readBool(fp) + if err != nil { + log.Printf("Couldn't read PlayerWon: %s", err) + return data, err + } + + data.NextLevel, err = readUTF8String(fp) + if err != nil { + log.Printf("Couldn't read NextLevel: %s", err) + return data, err + } + + data.CanContinue, err = readBool(fp) + if err != nil { + log.Printf("Couldn't read CanContinue: %s", err) + return data, err + } + + data.FinishedButContinuing, err = readBool(fp) + if err != nil { + log.Printf("Couldn't read FinishedButContinuing: %s", err) + return data, err + } + + data.SavingReplay, err = readBool(fp) + if err != nil { + log.Printf("Couldn't read SavingReplay: %s", err) + return data, err + } + + data.AllowNonAdminDebugOptions, err = readBool(fp) + if err != nil { + log.Printf("Couldn't read allow_non_admin_debug_options: %s", err) + return data, err + } + + data.LoadedFrom, err = readVersionShort8(fp) + if err != nil { + log.Printf("Couldn't read LoadedFrom: %s", err) + return data, err + } + + data.LoadedFromBuild, err = readUint16(fp) + if err != nil { + log.Printf("Couldn't read LoadedFromBuild: %s", err) + return data, err + } + + data.AllowedCommads, err = readUint8(fp) + if err != nil { + log.Printf("Couldn't read AllowedCommands: %s", err) + return data, err + } + + data.NumMods, err = readUint8(fp) + if err != nil { + log.Printf("Couldn't read NumMods: %s", err) + return data, err + } + + for i := uint8(0); i < data.NumMods; i++ { + SingleMod, err := readSingleMod(fp) + if err != nil { + log.Printf("Couldn't read SingleMod: %s", err) + return data, err + } + + data.Mods = append(data.Mods, SingleMod) + } + + log.Println(data) + return data, nil +} + +func readUTF8String(file *os.File) (string, error) { + var err error + infoByte := make([]byte, 1) + + _, err = file.Read(infoByte) + if err != nil { + log.Printf("Error reading infoByte: %s", err) + return "", nil + } + stringLengthInBytes := int8(infoByte[0]) + + stringBytes := make([]byte, stringLengthInBytes) + _, err = file.Read(stringBytes) + if err != nil { + log.Printf("error reading bytes: %s", err) + return "", err + } + finalizedString := string(stringBytes[:]) + + return finalizedString, nil +} + +func readUint8(file *os.File) (uint8, error) { + var err error + var temp [1]byte + _, err = file.Read(temp[:]) + if err != nil { + log.Printf("error reading byte: %s", err) + return 0, nil + } + + return uint8(temp[0]), nil +} + +func readUint16(file *os.File) (uint16, error) { + var err error + var temp [2]byte + + _, err = file.Read(temp[:]) + if err != nil { + log.Printf("error reading bytes: %s", err) + return 0, err + } + + return binary.LittleEndian.Uint16(temp[:]), nil +} + +func readUint32(file *os.File) (uint32, error) { + var err error + var temp [4]byte + + _, err = file.Read(temp[:]) + if err != nil { + log.Printf("error reading bytes: %s", err) + return 0, err + } + + return binary.LittleEndian.Uint32(temp[:]), nil +} + +func readBool(file *os.File) (bool, error) { + byteAsInt, err := readUint8(file) + if err != nil { + log.Printf("error loading Uint8: %s", err) + return false, err + } + + return byteAsInt != 0, nil +} + +func readVersion16(file *os.File) (version16, error) { + var Version version16 + var VersionShort versionShort16 + var err error + + VersionShort, err = readVersionShort16(file) + if err != nil { + log.Printf("error reading VersionShort") + return Version, err + } + + Version.Major = VersionShort.Major + Version.Minor = VersionShort.Minor + Version.Build = VersionShort.Build + + Version.Revision, err = readUint16(file) + if err != nil { + log.Printf("error reading revision: %s", err) + return Version, err + } + + return Version, nil +} + +func readVersionShort16(file *os.File) (versionShort16, error) { + var Version versionShort16 + var err error + + Version.Major, err = readUint16(file) + if err != nil { + log.Printf("error reading major: %s", err) + return Version, err + } + + Version.Minor, err = readUint16(file) + if err != nil { + log.Printf("error reading minor: %s", err) + return Version, err + } + + Version.Build, err = readUint16(file) + if err != nil { + log.Printf("error reading build: %s", err) + return Version, err + } + + return Version, err +} + +func readVersionShort8(file *os.File) (versionShort8, error) { + var Version versionShort8 + var err error + + Version.Major, err = readUint8(file) + if err != nil { + log.Printf("error reading major: %s", err) + return Version, err + } + + Version.Minor, err = readUint8(file) + if err != nil { + log.Printf("error reading minor: %s", err) + return Version, err + } + + Version.Build, err = readUint8(file) + if err != nil { + log.Printf("error reading build: %s", err) + return Version, err + } + + return Version, nil +} + +func readSingleMod(file *os.File) (singleMod, error) { + var Mod singleMod + var err error + + Mod.Name, err = readUTF8String(file) + if err != nil { + log.Printf("error loading modName: %s", err) + return Mod, err + } + + Mod.Version, err = readVersionShort8(file) + if err != nil { + log.Printf("error loading modVersion: %s", err) + return Mod, err + } + + Mod.CRC, err = readUint32(file) + if err != nil { + log.Printf("error loading CRC: %s", err) + return Mod, err + } + + return Mod, err +} + +func (Version *versionShort16) CheckCompatibility(Major uint16, Minor uint16, Build uint16) (bool) { + return Major >= Version.Major && Minor >= Version.Minor && Build >= Version.Build +} diff --git a/ui/App/components/Mods/ModLoadSave.jsx b/ui/App/components/Mods/ModLoadSave.jsx new file mode 100644 index 00000000..08d6b129 --- /dev/null +++ b/ui/App/components/Mods/ModLoadSave.jsx @@ -0,0 +1,48 @@ +import React from 'react'; + +class ModOverview extends React.Component { + constructor(props) { + super(props); + + this.loadMods = this.loadMods.bind(this); + } + + componentDidMount() { + //Load Saves + this.props.getSaves(); + } + + loadMods() { + console.log("baum"); + } + + render() { + console.log(this.props.saves); + + let saves = []; + this.props.saves.forEach((value, index) => { + if(index != this.props.saves.length - 1) { + saves.push( + + ) + } + }); + + return ( +
+
+ +
+ +
+
+
+ ) + } +} + +export default ModOverview; diff --git a/ui/App/components/Mods/ModOverview.jsx b/ui/App/components/Mods/ModOverview.jsx index d872b9d9..251f2fe9 100644 --- a/ui/App/components/Mods/ModOverview.jsx +++ b/ui/App/components/Mods/ModOverview.jsx @@ -5,6 +5,7 @@ import ModUpload from "./ModUpload.jsx"; import ModManager from "./ModManager.jsx"; import ModPacks from "./packs/ModPackOverview.jsx"; import {instanceOfModsContent} from "./ModsPropTypes.js"; +import ModLoadSave from "./ModLoadSave.jsx"; class ModOverview extends React.Component { constructor(props) { @@ -83,6 +84,17 @@ class ModOverview extends React.Component { /> +
+
+ +

Load Mods From Save

+
+ + +
+
From a6afd913c88f53d3ce9dd4f57260ca0e19c71c26 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Fri, 13 Jul 2018 00:58:18 +0200 Subject: [PATCH 03/10] finished reading factorioSaveDat --- src/mods_handler.go | 40 ++++++++ src/routes.go | 5 + src/vendor/factorioSave/factorioSave.go | 122 ++++++++++++------------ src/vendor/factorioSave/openSave.go | 35 +++++++ ui/App/components/Mods/ModLoadSave.jsx | 43 ++++++--- 5 files changed, 175 insertions(+), 70 deletions(-) create mode 100644 src/vendor/factorioSave/openSave.go diff --git a/src/mods_handler.go b/src/mods_handler.go index 94abb4c2..f4d98db6 100644 --- a/src/mods_handler.go +++ b/src/mods_handler.go @@ -12,6 +12,7 @@ import ( "net/http" "os" "path/filepath" + "factorioSave" ) // Returns JSON response of all mods installed in factorio/mods @@ -455,6 +456,45 @@ func DownloadModsHandler(w http.ResponseWriter, r *http.Request) { writerHeader.Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", "all_installed_mods.zip")) } +//Returns JSON response with the found mods +func LoadModsFromSaveHandler(w http.ResponseWriter, r *http.Request) { + var err error + resp := JSONResponse{ + Success: false, + } + + w.Header().Set("Content-Type", "application/json;charset=UTF-8") + + //Get Data out of the request + SaveFile := r.FormValue("saveFile") + + SaveFileComplete := filepath.Join(config.FactorioSavesDir, SaveFile) + resp.Data, err = factorioSave.ReadHeader(SaveFileComplete) + + if err == factorioSave.ErrorIncompatible { + w.WriteHeader(500) + resp.Data = fmt.Sprintf("%s", err) + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in loadModsFromSave: %s", err) + } + return + } + if err != nil { + w.WriteHeader(500) + resp.Data = fmt.Sprintf("Error in searchModPortal: %s", err) + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in loadModsFromSave: %s", err) + } + return + } + + resp.Success = true + + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in LoadModsFromSave: %s", err) + } +} + func ListModPacksHandler(w http.ResponseWriter, r *http.Request) { var err error resp := JSONResponse{ diff --git a/src/routes.go b/src/routes.go index 8d9c7134..9e740a28 100644 --- a/src/routes.go +++ b/src/routes.go @@ -213,6 +213,11 @@ var apiRoutes = Routes{ "GET", "/mods/download", DownloadModsHandler, + }, { + "LoadModsFromSave", + "POST", + "/mods/save/load", + LoadModsFromSaveHandler, }, { "ListSaves", "GET", diff --git a/src/vendor/factorioSave/factorioSave.go b/src/vendor/factorioSave/factorioSave.go index a3f03b01..e496e548 100644 --- a/src/vendor/factorioSave/factorioSave.go +++ b/src/vendor/factorioSave/factorioSave.go @@ -2,61 +2,65 @@ package factorioSave import ( "log" - "os" "encoding/binary" + "errors" + "io" ) type version16 struct { versionShort16 - Revision uint16 + Revision uint16 `json:"revision"` } type versionShort16 struct { - Major uint16 - Minor uint16 - Build uint16 + Major uint16 `json:"major"` + Minor uint16 `json:"minor"` + Build uint16 `json:"build"` } type versionShort8 struct { - Major uint8 - Minor uint8 - Build uint8 + Major uint8 `json:"major"` + Minor uint8 `json:"minor"` + Build uint8 `json:"build"` } type Header struct { - FactorioVersion version16 - Campaign string - Name string - BaseMod string - Difficulty uint8 - Finished bool - PlayerWon bool - NextLevel string - CanContinue bool - FinishedButContinuing bool - SavingReplay bool - AllowNonAdminDebugOptions bool - LoadedFrom versionShort8 - LoadedFromBuild uint16 - AllowedCommads uint8 - NumMods uint8 - Mods []singleMod + FactorioVersion version16 `json:"factorio_version"` + Campaign string `json:"campaign"` + Name string `json:"name"` + BaseMod string `json:"base_mod"` + Difficulty uint8 `json:"difficulty"` + Finished bool `json:"finished"` + PlayerWon bool `json:"player_won"` + NextLevel string `json:"next_level"` + CanContinue bool `json:"can_continue"` + FinishedButContinuing bool `json:"finished_but_continuing"` + SavingReplay bool `json:"saving_replay"` + AllowNonAdminDebugOptions bool `json:"allow_non_admin_debug_options"` + LoadedFrom versionShort8 `json:"loaded_from"` + LoadedFromBuild uint16 `json:"loaded_from_build"` + AllowedCommads uint8 `json:"allowed_commads"` + NumMods uint8 `json:"num_mods"` + Mods []singleMod `json:"mods"` } type singleMod struct { - Name string - Version versionShort8 - CRC uint32 + Name string `json:"name"` + Version versionShort8 `json:"version"` + CRC uint32 `json:"crc"` } +var ErrorIncompatible = errors.New("incompatible save") + func ReadHeader(filePath string) (Header, error) { var data Header + var err error - fp, err := os.Open(filePath) + datFile, err := openSave(filePath) if err != nil { log.Printf("error opening file: %s", err) return data, err } - defer fp.Close() + defer datFile.Close() - data.FactorioVersion, err = readVersion16(fp) + data.FactorioVersion, err = readVersion16(datFile) if err != nil { log.Printf("Cant read FactorioVersion: %s", err) return data, err @@ -64,101 +68,102 @@ func ReadHeader(filePath string) (Header, error) { if !data.FactorioVersion.CheckCompatibility(0, 16, 0) { log.Printf("NOT COMPATIBLE Save-File") - return data, err + log.Println(data) + return data, ErrorIncompatible } - data.Campaign, err = readUTF8String(fp) + data.Campaign, err = readUTF8String(datFile) if err != nil { log.Printf("Cant read Campaign: %s", err) return data, err } - data.Name, err = readUTF8String(fp) + data.Name, err = readUTF8String(datFile) if err != nil { log.Printf("Cant read Name: %s", err) return data, err } - data.BaseMod, err = readUTF8String(fp) + data.BaseMod, err = readUTF8String(datFile) if err != nil { log.Printf("Cant read BaseMod: %s", err) return data, err } - data.Difficulty, err = readUint8(fp) + data.Difficulty, err = readUint8(datFile) if err != nil { log.Printf("Cant read Difficulty: %s", err) return data, err } - data.Finished, err = readBool(fp) + data.Finished, err = readBool(datFile) if err != nil { log.Printf("Couln't read Finished bool: %s", err) return data, err } - data.PlayerWon, err = readBool(fp) + data.PlayerWon, err = readBool(datFile) if err != nil { log.Printf("Couldn't read PlayerWon: %s", err) return data, err } - data.NextLevel, err = readUTF8String(fp) + data.NextLevel, err = readUTF8String(datFile) if err != nil { log.Printf("Couldn't read NextLevel: %s", err) return data, err } - data.CanContinue, err = readBool(fp) + data.CanContinue, err = readBool(datFile) if err != nil { log.Printf("Couldn't read CanContinue: %s", err) return data, err } - data.FinishedButContinuing, err = readBool(fp) + data.FinishedButContinuing, err = readBool(datFile) if err != nil { log.Printf("Couldn't read FinishedButContinuing: %s", err) return data, err } - data.SavingReplay, err = readBool(fp) + data.SavingReplay, err = readBool(datFile) if err != nil { log.Printf("Couldn't read SavingReplay: %s", err) return data, err } - data.AllowNonAdminDebugOptions, err = readBool(fp) + data.AllowNonAdminDebugOptions, err = readBool(datFile) if err != nil { log.Printf("Couldn't read allow_non_admin_debug_options: %s", err) return data, err } - data.LoadedFrom, err = readVersionShort8(fp) + data.LoadedFrom, err = readVersionShort8(datFile) if err != nil { log.Printf("Couldn't read LoadedFrom: %s", err) return data, err } - data.LoadedFromBuild, err = readUint16(fp) + data.LoadedFromBuild, err = readUint16(datFile) if err != nil { log.Printf("Couldn't read LoadedFromBuild: %s", err) return data, err } - data.AllowedCommads, err = readUint8(fp) + data.AllowedCommads, err = readUint8(datFile) if err != nil { log.Printf("Couldn't read AllowedCommands: %s", err) return data, err } - data.NumMods, err = readUint8(fp) + data.NumMods, err = readUint8(datFile) if err != nil { log.Printf("Couldn't read NumMods: %s", err) return data, err } for i := uint8(0); i < data.NumMods; i++ { - SingleMod, err := readSingleMod(fp) + SingleMod, err := readSingleMod(datFile) if err != nil { log.Printf("Couldn't read SingleMod: %s", err) return data, err @@ -167,11 +172,10 @@ func ReadHeader(filePath string) (Header, error) { data.Mods = append(data.Mods, SingleMod) } - log.Println(data) return data, nil } -func readUTF8String(file *os.File) (string, error) { +func readUTF8String(file io.ReadCloser) (string, error) { var err error infoByte := make([]byte, 1) @@ -193,7 +197,7 @@ func readUTF8String(file *os.File) (string, error) { return finalizedString, nil } -func readUint8(file *os.File) (uint8, error) { +func readUint8(file io.ReadCloser) (uint8, error) { var err error var temp [1]byte _, err = file.Read(temp[:]) @@ -205,7 +209,7 @@ func readUint8(file *os.File) (uint8, error) { return uint8(temp[0]), nil } -func readUint16(file *os.File) (uint16, error) { +func readUint16(file io.ReadCloser) (uint16, error) { var err error var temp [2]byte @@ -218,7 +222,7 @@ func readUint16(file *os.File) (uint16, error) { return binary.LittleEndian.Uint16(temp[:]), nil } -func readUint32(file *os.File) (uint32, error) { +func readUint32(file io.ReadCloser) (uint32, error) { var err error var temp [4]byte @@ -231,7 +235,7 @@ func readUint32(file *os.File) (uint32, error) { return binary.LittleEndian.Uint32(temp[:]), nil } -func readBool(file *os.File) (bool, error) { +func readBool(file io.ReadCloser) (bool, error) { byteAsInt, err := readUint8(file) if err != nil { log.Printf("error loading Uint8: %s", err) @@ -241,7 +245,7 @@ func readBool(file *os.File) (bool, error) { return byteAsInt != 0, nil } -func readVersion16(file *os.File) (version16, error) { +func readVersion16(file io.ReadCloser) (version16, error) { var Version version16 var VersionShort versionShort16 var err error @@ -265,7 +269,7 @@ func readVersion16(file *os.File) (version16, error) { return Version, nil } -func readVersionShort16(file *os.File) (versionShort16, error) { +func readVersionShort16(file io.ReadCloser) (versionShort16, error) { var Version versionShort16 var err error @@ -290,7 +294,7 @@ func readVersionShort16(file *os.File) (versionShort16, error) { return Version, err } -func readVersionShort8(file *os.File) (versionShort8, error) { +func readVersionShort8(file io.ReadCloser) (versionShort8, error) { var Version versionShort8 var err error @@ -315,7 +319,7 @@ func readVersionShort8(file *os.File) (versionShort8, error) { return Version, nil } -func readSingleMod(file *os.File) (singleMod, error) { +func readSingleMod(file io.ReadCloser) (singleMod, error) { var Mod singleMod var err error @@ -341,5 +345,5 @@ func readSingleMod(file *os.File) (singleMod, error) { } func (Version *versionShort16) CheckCompatibility(Major uint16, Minor uint16, Build uint16) (bool) { - return Major >= Version.Major && Minor >= Version.Minor && Build >= Version.Build + return Version.Major >= Major && Version.Minor >= Minor && Version.Build >= Build } diff --git a/src/vendor/factorioSave/openSave.go b/src/vendor/factorioSave/openSave.go new file mode 100644 index 00000000..bd5c426d --- /dev/null +++ b/src/vendor/factorioSave/openSave.go @@ -0,0 +1,35 @@ +package factorioSave + +import ( + "archive/zip" + "log" + "io" + "errors" +) + +var ErrorLevelDatNotFound = errors.New("couldn't find level.dat") + +func openSave(filePath string) (io.ReadCloser, error) { + var err error + + saveFile, err := zip.OpenReader(filePath) + if err != nil { + log.Printf("error opening saveFile: %s", err) + return nil, err + } + + for _, singleFile := range saveFile.File { + if singleFile.FileInfo().Name() == "level.dat" { + //open level.dat + rc, err := singleFile.Open() + if err != nil { + log.Printf("Couldn't open level.dat: %s", err) + return nil, err + } + + return rc, nil + } + } + + return nil, ErrorLevelDatNotFound +} diff --git a/ui/App/components/Mods/ModLoadSave.jsx b/ui/App/components/Mods/ModLoadSave.jsx index 08d6b129..9a43ea0f 100644 --- a/ui/App/components/Mods/ModLoadSave.jsx +++ b/ui/App/components/Mods/ModLoadSave.jsx @@ -1,6 +1,6 @@ import React from 'react'; -class ModOverview extends React.Component { +class ModLoadSave extends React.Component { constructor(props) { super(props); @@ -12,8 +12,27 @@ class ModOverview extends React.Component { this.props.getSaves(); } - loadMods() { - console.log("baum"); + loadMods(e) { + e.preventDefault(); + + // let save = $(e.target).find("select").val(); + + $.ajax({ + url: "/api/mods/save/load", + method: "POST", + data: $(e.target).serialize(), + dataType: "JSON", + success: (data) => { + }, + error: (jqXHR) => { + let json_data = JSON.parse(jqXHR.responseJSON.data); + + swal({ + title: json_data.detail, + type: "error" + }); + } + }); } render() { @@ -32,17 +51,19 @@ class ModOverview extends React.Component { return (
-
- -
- +
+
+ +
+ +
-
+
) } } -export default ModOverview; +export default ModLoadSave; From 51f8bf22387ed65c72348622b70adde3a75dfd72 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Sat, 14 Jul 2018 19:47:30 +0200 Subject: [PATCH 04/10] use semver for Compatibility-checking --- src/vendor/factorioSave/factorioSave.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/vendor/factorioSave/factorioSave.go b/src/vendor/factorioSave/factorioSave.go index e496e548..24f18dbe 100644 --- a/src/vendor/factorioSave/factorioSave.go +++ b/src/vendor/factorioSave/factorioSave.go @@ -5,6 +5,8 @@ import ( "encoding/binary" "errors" "io" + "strconv" + "github.com/Masterminds/semver" ) type version16 struct { @@ -66,7 +68,13 @@ func ReadHeader(filePath string) (Header, error) { return data, err } - if !data.FactorioVersion.CheckCompatibility(0, 16, 0) { + Constraint, _ := semver.NewConstraint("0.16.0 - 0.17.0") + Compatible, err := data.FactorioVersion.CheckCompatibility(Constraint) + if err != nil { + log.Printf("Error checking compatibility: %s", err) + return data, err + } + if !Compatible { log.Printf("NOT COMPATIBLE Save-File") log.Println(data) return data, ErrorIncompatible @@ -344,6 +352,12 @@ func readSingleMod(file io.ReadCloser) (singleMod, error) { return Mod, err } -func (Version *versionShort16) CheckCompatibility(Major uint16, Minor uint16, Build uint16) (bool) { - return Version.Major >= Major && Version.Minor >= Minor && Version.Build >= Build +func (Version *versionShort16) CheckCompatibility(constraints *semver.Constraints) (bool, error) { + Ver, err := semver.NewVersion(strconv.Itoa(int(Version.Major)) + "." + strconv.Itoa(int(Version.Minor)) + "." + strconv.Itoa(int(Version.Build))) + if err != nil { + log.Printf("Error creating semver-version: %s", err) + return false, err + } + + return constraints.Check(Ver), nil } From 66fb795b06ebc3ca72f37611143b7bc1138ccb50 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Mon, 16 Jul 2018 02:50:19 +0200 Subject: [PATCH 05/10] made popup for mods to be installed --- ui/App/components/Mods/ModLoadSave.jsx | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/ui/App/components/Mods/ModLoadSave.jsx b/ui/App/components/Mods/ModLoadSave.jsx index 9a43ea0f..bcba1e51 100644 --- a/ui/App/components/Mods/ModLoadSave.jsx +++ b/ui/App/components/Mods/ModLoadSave.jsx @@ -1,10 +1,12 @@ import React from 'react'; +import ReactDOMServer from 'react-dom/server'; class ModLoadSave extends React.Component { constructor(props) { super(props); this.loadMods = this.loadMods.bind(this); + this.loadModsSwalHandler = this.loadModsSwalHandler.bind(this); } componentDidMount() { @@ -23,6 +25,57 @@ class ModLoadSave extends React.Component { data: $(e.target).serialize(), dataType: "JSON", success: (data) => { + let checkboxes = []; + + data.data.mods.forEach((mod) => { + let singleCheckbox = + + {mod.name} + + + + {mod.version.major + "." + mod.version.minor + "." + mod.version.build} + + + + + checkboxes.push(singleCheckbox); + }); + + let table =
+ All Mods will be installed +
+
+ + + + + + + + + {checkboxes} + +
+ ModName + + ModVersion +
+
+
+
+ + swal({ + title: "Mods to install", + text: ReactDOMServer.renderToStaticMarkup(table), + html: true, + type: 'info', + showCancelButton: true, + closeOnConfirm: false, + confirmButtonText: "Download Mods!", + cancelButtonText: "Cancel", + showLoaderOnConfirm: true + }, this.loadModsSwalHandler); }, error: (jqXHR) => { let json_data = JSON.parse(jqXHR.responseJSON.data); @@ -35,6 +88,13 @@ class ModLoadSave extends React.Component { }); } + loadModsSwalHandler() { + $.ajax({ + url: "/api/mods/install/multiple" + }) + console.log($("#swalForm").serialize()); + } + render() { console.log(this.props.saves); From f9e900fc16b6685151f30e4697e5fe254ceb1a4d Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Tue, 17 Jul 2018 03:53:21 +0200 Subject: [PATCH 06/10] finished downloading multiple mods from save --- src/mods_handler.go | 109 ++++++++++++++++++++++++- src/routes.go | 5 ++ ui/App/components/Mods/ModLoadSave.jsx | 44 +++++++--- 3 files changed, 145 insertions(+), 13 deletions(-) diff --git a/src/mods_handler.go b/src/mods_handler.go index f4d98db6..b67ccf1b 100644 --- a/src/mods_handler.go +++ b/src/mods_handler.go @@ -13,8 +13,27 @@ import ( "os" "path/filepath" "factorioSave" + "time" ) +type ModPortalStruct struct { + DownloadsCount int `json:"downloads_count"` + Name string `json:"name"` + Owner string `json:"owner"` + Releases []struct { + DownloadURL string `json:"download_url"` + FileName string `json:"file_name"` + InfoJSON struct { + FactorioVersion string `json:"factorio_version"` + } `json:"info_json"` + ReleasedAt time.Time `json:"released_at"` + Sha1 string `json:"sha1"` + Version string `json:"version"` + } `json:"releases"` + Summary string `json:"summary"` + Title string `json:"title"` +} + // Returns JSON response of all mods installed in factorio/mods func listInstalledModsHandler(w http.ResponseWriter, r *http.Request) { var err error @@ -212,7 +231,7 @@ func ModPortalInstallHandler(w http.ResponseWriter, r *http.Request) { } if err != nil { - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) resp.Data = fmt.Sprintf("Error in installMod: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in installMod: %s", err) @@ -228,6 +247,90 @@ func ModPortalInstallHandler(w http.ResponseWriter, r *http.Request) { } } +func ModPortalInstallMultipleHandler(w http.ResponseWriter, r *http.Request) { + var err error + resp := JSONResponse{ + Success: false, + } + + w.Header().Set("Content-Type", "application/json;charset=UTF-8") + r.ParseForm() + + modsList := make([]string, 0) + versionsList := make([]string, 0) + + //Parse incoming data + for key, values := range r.PostForm { + if key == "mod_name" { + for _, v := range values { + modsList = append(modsList, v) + } + } else if key == "mod_version" { + for _, v := range values { + versionsList = append(versionsList, v) + } + } + } + + mods, err := newMods(config.FactorioModsDir) + if err != nil { + log.Printf("error creating mods: %s", err) + + w.WriteHeader(http.StatusInternalServerError) + resp.Data = fmt.Sprintf("Error in searchModPortal: %s", err) + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in searchModPortal: %s", err) + } + return + } + + for modIndex, mod := range modsList { + var err error + + //get details of mod + modDetails, err, statusCode := getModDetails(mod) + if err != nil { + w.WriteHeader(statusCode) + resp.Data = fmt.Sprintf("Error in searchModPortal: %s", err) + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in searchModPortal: %s", err) + } + return + } + + modDetailsArray := []byte(modDetails) + var modDetailsStruct ModPortalStruct + + //read mod-data into Struct + err = json.Unmarshal(modDetailsArray, &modDetailsStruct) + if err != nil { + log.Printf("error reading modPortalDetails: %s", err) + + w.WriteHeader(http.StatusInternalServerError) + resp.Data = fmt.Sprintf("Error in searchModPortal: %s", err) + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in searchModPortal: %s", err) + } + return + } + + //find correct mod-version + for _, release := range modDetailsStruct.Releases { + if release.Version == versionsList[modIndex] { + mods.downloadMod(release.DownloadURL, release.FileName, modDetailsStruct.Name) + break + } + } + } + + resp.Data = mods.listInstalledMods() + + resp.Success = true + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in ToggleModHandler: %s", err) + } +} + func ToggleModHandler(w http.ResponseWriter, r *http.Request) { var err error resp := JSONResponse{ @@ -245,7 +348,7 @@ func ToggleModHandler(w http.ResponseWriter, r *http.Request) { } if err != nil { - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) resp.Data = fmt.Sprintf("Error in listInstalledModsByFolder: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in listInstalledModsByFolder: %s", err) @@ -277,7 +380,7 @@ func DeleteModHandler(w http.ResponseWriter, r *http.Request) { } if err != nil { - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) resp.Data = fmt.Sprintf("Error in deleteMod: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in DeleteModHandler: %s", err) diff --git a/src/routes.go b/src/routes.go index 9e740a28..4ee0d329 100644 --- a/src/routes.go +++ b/src/routes.go @@ -183,6 +183,11 @@ var apiRoutes = Routes{ "POST", "/mods/install", ModPortalInstallHandler, + }, { + "ModPortalInstallMultiple", + "POST", + "/mods/install/multiple", + ModPortalInstallMultipleHandler, }, { "ToggleMod", "POST", diff --git a/ui/App/components/Mods/ModLoadSave.jsx b/ui/App/components/Mods/ModLoadSave.jsx index bcba1e51..55081f3e 100644 --- a/ui/App/components/Mods/ModLoadSave.jsx +++ b/ui/App/components/Mods/ModLoadSave.jsx @@ -1,5 +1,6 @@ import React from 'react'; import ReactDOMServer from 'react-dom/server'; +import {instanceOfModsContent} from "./ModsPropTypes"; class ModLoadSave extends React.Component { constructor(props) { @@ -17,8 +18,6 @@ class ModLoadSave extends React.Component { loadMods(e) { e.preventDefault(); - // let save = $(e.target).find("select").val(); - $.ajax({ url: "/api/mods/save/load", method: "POST", @@ -28,14 +27,17 @@ class ModLoadSave extends React.Component { let checkboxes = []; data.data.mods.forEach((mod) => { + if(mod.name == "base") return; + + let modVersion = mod.version.major + "." + mod.version.minor + "." + mod.version.build; let singleCheckbox = {mod.name} - + - {mod.version.major + "." + mod.version.minor + "." + mod.version.build} - + {modVersion} + @@ -82,7 +84,7 @@ class ModLoadSave extends React.Component { swal({ title: json_data.detail, - type: "error" + type: "error", }); } }); @@ -90,14 +92,32 @@ class ModLoadSave extends React.Component { loadModsSwalHandler() { $.ajax({ - url: "/api/mods/install/multiple" + url: "/api/mods/install/multiple", + method: "POST", + dataType: "JSON", + data: $("#swalForm").serialize(), + success: (data) => { + swal({ + title: "All Mods installed successfully!", + type: "success" + }); + + this.props.modContentClass.setState({ + installedMods: data.data.mods + }); + }, + error: (jqXHR) => { + let json_data = JSON.parse(jqXHR.responseJSON.data); + + swal({ + title: json_data.detail, + type: "error", + }); + } }) - console.log($("#swalForm").serialize()); } render() { - console.log(this.props.saves); - let saves = []; this.props.saves.forEach((value, index) => { if(index != this.props.saves.length - 1) { @@ -126,4 +146,8 @@ class ModLoadSave extends React.Component { } } +ModLoadSave.propTypes = { + modContentClass: instanceOfModsContent.isRequired, +} + export default ModLoadSave; From 68257e5a539019e491c00b21ae920ade2ca8158a Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Tue, 17 Jul 2018 04:28:58 +0200 Subject: [PATCH 07/10] tried to update to read older saves && fixed error messages --- src/mods_handler.go | 6 +++--- src/vendor/factorioSave/factorioSave.go | 28 +++++++++++++++++++------ ui/App/components/Mods/ModLoadSave.jsx | 5 ++--- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/mods_handler.go b/src/mods_handler.go index b67ccf1b..101e6489 100644 --- a/src/mods_handler.go +++ b/src/mods_handler.go @@ -575,15 +575,15 @@ func LoadModsFromSaveHandler(w http.ResponseWriter, r *http.Request) { resp.Data, err = factorioSave.ReadHeader(SaveFileComplete) if err == factorioSave.ErrorIncompatible { - w.WriteHeader(500) - resp.Data = fmt.Sprintf("%s", err) + w.WriteHeader(http.StatusInternalServerError) + resp.Data = fmt.Sprintf("%s
Only can read 0.16.x save files", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in loadModsFromSave: %s", err) } return } if err != nil { - w.WriteHeader(500) + w.WriteHeader(http.StatusInternalServerError) resp.Data = fmt.Sprintf("Error in searchModPortal: %s", err) if err := json.NewEncoder(w).Encode(resp); err != nil { log.Printf("Error in loadModsFromSave: %s", err) diff --git a/src/vendor/factorioSave/factorioSave.go b/src/vendor/factorioSave/factorioSave.go index 24f18dbe..14ff95ea 100644 --- a/src/vendor/factorioSave/factorioSave.go +++ b/src/vendor/factorioSave/factorioSave.go @@ -49,10 +49,9 @@ type singleMod struct { } var ErrorIncompatible = errors.New("incompatible save") - +var data Header func ReadHeader(filePath string) (Header, error) { - var data Header var err error datFile, err := openSave(filePath) @@ -140,11 +139,19 @@ func ReadHeader(filePath string) (Header, error) { return data, err } - data.AllowNonAdminDebugOptions, err = readBool(datFile) + Constraint, _ = semver.NewConstraint(">= 0.16.0") + Used, err := data.FactorioVersion.CheckCompatibility(Constraint) if err != nil { - log.Printf("Couldn't read allow_non_admin_debug_options: %s", err) + log.Printf("Error checking if used: %s", err) return data, err } + if Used { + data.AllowNonAdminDebugOptions, err = readBool(datFile) + if err != nil { + log.Printf("Couldn't read allow_non_admin_debug_options: %s", err) + return data, err + } + } data.LoadedFrom, err = readVersionShort8(datFile) if err != nil { @@ -180,6 +187,7 @@ func ReadHeader(filePath string) (Header, error) { data.Mods = append(data.Mods, SingleMod) } + log.Println(data) return data, nil } @@ -343,11 +351,19 @@ func readSingleMod(file io.ReadCloser) (singleMod, error) { return Mod, err } - Mod.CRC, err = readUint32(file) + Constraint, _ := semver.NewConstraint("> 0.15.0") + Used, err := data.FactorioVersion.CheckCompatibility(Constraint) if err != nil { - log.Printf("error loading CRC: %s", err) + log.Printf("Error checking used of CRC: %s", err) return Mod, err } + if Used { + Mod.CRC, err = readUint32(file) + if err != nil { + log.Printf("error loading CRC: %s", err) + return Mod, err + } + } return Mod, err } diff --git a/ui/App/components/Mods/ModLoadSave.jsx b/ui/App/components/Mods/ModLoadSave.jsx index 55081f3e..a83b738e 100644 --- a/ui/App/components/Mods/ModLoadSave.jsx +++ b/ui/App/components/Mods/ModLoadSave.jsx @@ -80,10 +80,9 @@ class ModLoadSave extends React.Component { }, this.loadModsSwalHandler); }, error: (jqXHR) => { - let json_data = JSON.parse(jqXHR.responseJSON.data); - swal({ - title: json_data.detail, + title: jqXHR.responseJSON.data, + html: true, type: "error", }); } From 597d7b3b233192ab38c61d858305f80d82e7c5d5 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Wed, 18 Jul 2018 03:33:00 +0200 Subject: [PATCH 08/10] added compatibility for 0.14.14 - 0.17.0 --- src/vendor/factorioSave/factorioSave.go | 62 ++++++++++++++++++------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/src/vendor/factorioSave/factorioSave.go b/src/vendor/factorioSave/factorioSave.go index 14ff95ea..236adb04 100644 --- a/src/vendor/factorioSave/factorioSave.go +++ b/src/vendor/factorioSave/factorioSave.go @@ -39,7 +39,7 @@ type Header struct { LoadedFrom versionShort8 `json:"loaded_from"` LoadedFromBuild uint16 `json:"loaded_from_build"` AllowedCommads uint8 `json:"allowed_commads"` - NumMods uint8 `json:"num_mods"` + NumMods uint32 `json:"num_mods"` Mods []singleMod `json:"mods"` } type singleMod struct { @@ -50,10 +50,13 @@ type singleMod struct { var ErrorIncompatible = errors.New("incompatible save") var data Header +var constraintGreaterThan0_16 *semver.Constraints func ReadHeader(filePath string) (Header, error) { var err error + constraintGreaterThan0_16, _ = semver.NewConstraint(">= 0.16.0") + datFile, err := openSave(filePath) if err != nil { log.Printf("error opening file: %s", err) @@ -67,7 +70,7 @@ func ReadHeader(filePath string) (Header, error) { return data, err } - Constraint, _ := semver.NewConstraint("0.16.0 - 0.17.0") + Constraint, _ := semver.NewConstraint("0.14.14 - 0.17.0") Compatible, err := data.FactorioVersion.CheckCompatibility(Constraint) if err != nil { log.Printf("Error checking compatibility: %s", err) @@ -79,19 +82,19 @@ func ReadHeader(filePath string) (Header, error) { return data, ErrorIncompatible } - data.Campaign, err = readUTF8String(datFile) + data.Campaign, err = readUTF8String(datFile, false) if err != nil { log.Printf("Cant read Campaign: %s", err) return data, err } - data.Name, err = readUTF8String(datFile) + data.Name, err = readUTF8String(datFile, false) if err != nil { log.Printf("Cant read Name: %s", err) return data, err } - data.BaseMod, err = readUTF8String(datFile) + data.BaseMod, err = readUTF8String(datFile, false) if err != nil { log.Printf("Cant read BaseMod: %s", err) return data, err @@ -115,7 +118,7 @@ func ReadHeader(filePath string) (Header, error) { return data, err } - data.NextLevel, err = readUTF8String(datFile) + data.NextLevel, err = readUTF8String(datFile, false) if err != nil { log.Printf("Couldn't read NextLevel: %s", err) return data, err @@ -139,8 +142,7 @@ func ReadHeader(filePath string) (Header, error) { return data, err } - Constraint, _ = semver.NewConstraint(">= 0.16.0") - Used, err := data.FactorioVersion.CheckCompatibility(Constraint) + Used, err := data.FactorioVersion.CheckCompatibility(constraintGreaterThan0_16) if err != nil { log.Printf("Error checking if used: %s", err) return data, err @@ -171,13 +173,25 @@ func ReadHeader(filePath string) (Header, error) { return data, err } - data.NumMods, err = readUint8(datFile) + New, err := data.FactorioVersion.CheckCompatibility(constraintGreaterThan0_16) + if err != nil { + log.Printf("error checking compatibility: %s", err) + return data, err + } + + if New { + numMods8, err2 := readUint8(datFile) //TODO read Optim. int + err = err2 + data.NumMods = uint32(numMods8) + } else { + data.NumMods, err = readUint32(datFile) + } if err != nil { log.Printf("Couldn't read NumMods: %s", err) return data, err } - for i := uint8(0); i < data.NumMods; i++ { + for i := uint32(0); i < data.NumMods; i++ { SingleMod, err := readSingleMod(datFile) if err != nil { log.Printf("Couldn't read SingleMod: %s", err) @@ -191,18 +205,30 @@ func ReadHeader(filePath string) (Header, error) { return data, nil } -func readUTF8String(file io.ReadCloser) (string, error) { +func readUTF8String(file io.ReadCloser, forcedOptim bool) (string, error) { var err error - infoByte := make([]byte, 1) - _, err = file.Read(infoByte) + New, err := data.FactorioVersion.CheckCompatibility(constraintGreaterThan0_16) if err != nil { - log.Printf("Error reading infoByte: %s", err) - return "", nil + log.Printf("Couldn't checkCompatibility: %s", err) + return "", err + } + + var infoByteStringLength uint32 + if New || forcedOptim { + infoByteInt8, err2 := readUint8(file) //TODO read optimized int + err = err2 + infoByteStringLength = uint32(infoByteInt8) + } else { + infoByteStringLength, err = readUint32(file) //uint32 + } + + if err != nil { + log.Printf("Couldn't read infoByteStringLength: %s", err) + return "", err } - stringLengthInBytes := int8(infoByte[0]) - stringBytes := make([]byte, stringLengthInBytes) + stringBytes := make([]byte, infoByteStringLength) _, err = file.Read(stringBytes) if err != nil { log.Printf("error reading bytes: %s", err) @@ -339,7 +365,7 @@ func readSingleMod(file io.ReadCloser) (singleMod, error) { var Mod singleMod var err error - Mod.Name, err = readUTF8String(file) + Mod.Name, err = readUTF8String(file, true) if err != nil { log.Printf("error loading modName: %s", err) return Mod, err From 0886920356f58d648ec621d89f40d332d7c592b6 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Wed, 18 Jul 2018 03:39:36 +0200 Subject: [PATCH 09/10] added error screen, if no mods are in the save --- src/vendor/factorioSave/factorioSave.go | 2 +- ui/App/components/Mods/ModLoadSave.jsx | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/vendor/factorioSave/factorioSave.go b/src/vendor/factorioSave/factorioSave.go index 236adb04..19e61380 100644 --- a/src/vendor/factorioSave/factorioSave.go +++ b/src/vendor/factorioSave/factorioSave.go @@ -54,6 +54,7 @@ var constraintGreaterThan0_16 *semver.Constraints func ReadHeader(filePath string) (Header, error) { var err error + data = Header{} constraintGreaterThan0_16, _ = semver.NewConstraint(">= 0.16.0") @@ -201,7 +202,6 @@ func ReadHeader(filePath string) (Header, error) { data.Mods = append(data.Mods, SingleMod) } - log.Println(data) return data, nil } diff --git a/ui/App/components/Mods/ModLoadSave.jsx b/ui/App/components/Mods/ModLoadSave.jsx index a83b738e..cb6d1bfc 100644 --- a/ui/App/components/Mods/ModLoadSave.jsx +++ b/ui/App/components/Mods/ModLoadSave.jsx @@ -44,6 +44,14 @@ class ModLoadSave extends React.Component { checkboxes.push(singleCheckbox); }); + if(checkboxes.length == 0) { + swal({ + title: "No mods in this save!", + type: "error" + }); + return; + } + let table =
All Mods will be installed
From 8bf495f5c0c6b35568566203f76cf8eb2801af9c Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Wed, 18 Jul 2018 04:27:14 +0200 Subject: [PATCH 10/10] added mickael9 to the ReadMe --- README.md | 3 +++ src/vendor/factorioSave/factorioSave.go | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3f73baad..02a77127 100644 --- a/README.md +++ b/README.md @@ -177,6 +177,9 @@ go build * **Mitch Roote** - [roote.ca](https://roote.ca) +## Special Thanks +- **mickael9** for reverseengineering the factorio-save-file: https://forums.factorio.com/viewtopic.php?f=5&t=8568# + ## License This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details diff --git a/src/vendor/factorioSave/factorioSave.go b/src/vendor/factorioSave/factorioSave.go index 19e61380..b258575f 100644 --- a/src/vendor/factorioSave/factorioSave.go +++ b/src/vendor/factorioSave/factorioSave.go @@ -50,13 +50,13 @@ type singleMod struct { var ErrorIncompatible = errors.New("incompatible save") var data Header -var constraintGreaterThan0_16 *semver.Constraints +var constraintGreaterThan016 *semver.Constraints func ReadHeader(filePath string) (Header, error) { var err error data = Header{} - constraintGreaterThan0_16, _ = semver.NewConstraint(">= 0.16.0") + constraintGreaterThan016, _ = semver.NewConstraint(">= 0.16.0") datFile, err := openSave(filePath) if err != nil { @@ -143,7 +143,7 @@ func ReadHeader(filePath string) (Header, error) { return data, err } - Used, err := data.FactorioVersion.CheckCompatibility(constraintGreaterThan0_16) + Used, err := data.FactorioVersion.CheckCompatibility(constraintGreaterThan016) if err != nil { log.Printf("Error checking if used: %s", err) return data, err @@ -174,7 +174,7 @@ func ReadHeader(filePath string) (Header, error) { return data, err } - New, err := data.FactorioVersion.CheckCompatibility(constraintGreaterThan0_16) + New, err := data.FactorioVersion.CheckCompatibility(constraintGreaterThan016) if err != nil { log.Printf("error checking compatibility: %s", err) return data, err @@ -208,7 +208,7 @@ func ReadHeader(filePath string) (Header, error) { func readUTF8String(file io.ReadCloser, forcedOptim bool) (string, error) { var err error - New, err := data.FactorioVersion.CheckCompatibility(constraintGreaterThan0_16) + New, err := data.FactorioVersion.CheckCompatibility(constraintGreaterThan016) if err != nil { log.Printf("Couldn't checkCompatibility: %s", err) return "", err