From 3858414dc38a6501509f133728307a3ac4e433b5 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Sat, 26 Jan 2019 23:28:20 +0100 Subject: [PATCH 01/25] Renamed factorioSaveTests to be less generic --- src/factorio_save_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/factorio_save_test.go b/src/factorio_save_test.go index cc4930e7..10a315d4 100644 --- a/src/factorio_save_test.go +++ b/src/factorio_save_test.go @@ -4,7 +4,7 @@ import ( "testing" ) -func Test0_16(t *testing.T) { +func TestFactorioSave0_16(t *testing.T) { file, err := OpenArchiveFile("factorio_save_testfiles/test_0_16.zip", "level.dat") if err != nil { t.Fatalf("Error opening level.dat: %s", err) @@ -48,7 +48,7 @@ func Test0_16(t *testing.T) { header.Equals(testHeader, t) } -func Test0_15(t *testing.T) { +func TestFactorioSave0_15(t *testing.T) { file, err := OpenArchiveFile("factorio_save_testfiles/test_0_15.zip", "level.dat") if err != nil { t.Fatalf("Error opening level.dat: %s", err) @@ -91,7 +91,7 @@ func Test0_15(t *testing.T) { header.Equals(testHeader, t) } -func Test0_14(t *testing.T) { +func TestFactorioSave0_14(t *testing.T) { file, err := OpenArchiveFile("factorio_save_testfiles/test_0_14.zip", "level.dat") if err != nil { t.Fatalf("Error opening level.dat: %s", err) @@ -134,7 +134,7 @@ func Test0_14(t *testing.T) { header.Equals(testHeader, t) } -func Test0_13(t *testing.T) { +func TestFactorioSave0_13(t *testing.T) { file, err := OpenArchiveFile("factorio_save_testfiles/test_0_13.zip", "level.dat") if err != nil { t.Fatalf("Error opening level.dat: %s", err) From e964f0d8e924a2d130ab0ee30598266853fde9c3 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Sat, 26 Jan 2019 23:28:54 +0100 Subject: [PATCH 02/25] added reading and writing of mod-settings.dat --- src/main.go | 11 ++ src/mod_settings_dat.go | 341 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 352 insertions(+) create mode 100644 src/mod_settings_dat.go diff --git a/src/main.go b/src/main.go index b9a9aa9f..f3ee68c4 100644 --- a/src/main.go +++ b/src/main.go @@ -4,6 +4,7 @@ import ( "encoding/json" "flag" "fmt" + "io/ioutil" "log" "net/http" "os" @@ -114,6 +115,16 @@ func main() { return } + var test FModData + test.Decode() + test.Encode() + + data, _ := ioutil.ReadFile(filepath.Join(config.FactorioModsDir, "mod-settings.dat")) + log.Println(data) + data2, _ := ioutil.ReadFile(filepath.Join(config.FactorioModsDir, "mod-settings.dat.new")) + log.Println(data2) + return + // Initialize authentication system Auth = initAuth() Auth.CreateAuth(config.DatabaseFile, config.CookieEncryptionKey) diff --git a/src/mod_settings_dat.go b/src/mod_settings_dat.go new file mode 100644 index 00000000..a97c2001 --- /dev/null +++ b/src/mod_settings_dat.go @@ -0,0 +1,341 @@ +package main + +import ( + "bytes" + "encoding/binary" + "fmt" + "log" + "os" + "path/filepath" + "reflect" +) + +const ( + NONE = 0 + BOOL = 1 + DOUBLE = 2 + STRING = 3 + LIST = 4 + DICT = 5 +) + +type FModData struct { + Version version64 + Data interface{} +} + +//func (d *FModData) Decode(file *os.File) error { +func (d *FModData) Decode() error { + var version version64 + var versionB [8]byte + + file, err := os.Open(filepath.Join(config.FactorioModsDir, "mod-settings.dat")) + if err != nil { + log.Printf("could not open mod-settings.dat") + return err + } + + err = binary.Read(file, binary.LittleEndian, versionB[:]) + if err != nil { + log.Printf("could not read version: %s", err) + } + err = version.UnmarshalBinary(versionB[:]) + if err != nil { + log.Printf("Error loading Version: %s", err) + return err + } + d.Version = version + + d.Data, err = d.unmarshalTree(file) + if err != nil { + log.Printf("error loading Data: %s", err) + return err + } + + return nil +} + +func (d *FModData) unmarshalTree(file *os.File) (interface{}, error) { + //type of embedded data + var _type byte + err := binary.Read(file, binary.LittleEndian, &_type) + if err != nil { + log.Printf("could not read first binary: %v", err) + return nil, err + } + + //anyType flag ... not useful + _, err = d.unmarshalBool(file) + if err != nil { + log.Printf("error loading anyType bool: %s", err) + return nil, err + } + + switch _type { + case BOOL: + return d.unmarshalBool(file) + case DOUBLE: + return d.unmarshalDouble(file) + case STRING: + return d.unmarshalString(file) + case LIST: + return d.unmarshalList(file) + case DICT: + return d.unmarshalDict(file) + default: + return nil, fmt.Errorf("Unknown type: %s ", err) + } +} + +func (d *FModData) unmarshalBool(file *os.File) (bool, error) { + var _data byte + err := binary.Read(file, binary.LittleEndian, &_data) + if err != nil { + log.Printf("could not read boolean byte: %s", err) + return false, err + } + + return _data != 0, nil +} + +func (d *FModData) unmarshalDouble(file *os.File) (float64, error) { + var _data float64 + err := binary.Read(file, binary.LittleEndian, &_data) + if err != nil { + log.Printf("could not read double-value: %s", err) + return 0, err + } + + return _data, nil +} + +func (d *FModData) unmarshalList(file *os.File) ([]interface{}, error) { + var length uint32 + length, err := readOptimUint(file, Version(d.Version), 32) + if err != nil { + log.Printf("could not read list length") + return nil, err + } + + list := make([]interface{}, length) + for i := uint32(0); i < length; i++ { + list[i], err = d.unmarshalTree(file) + if err != nil { + log.Printf("could not read tree of list: %s", err) + return nil, err + } + } + + return list, nil +} + +func (d *FModData) unmarshalDict(file *os.File) (map[string]interface{}, error) { + var length uint32 + err := binary.Read(file, binary.LittleEndian, &length) + if err != nil { + log.Printf("could not read dict length: %s", err) + return nil, err + } + + dict := make(map[string]interface{}) + + for i := uint32(0); i < length; i++ { + key, err := d.unmarshalString(file) + + if err != nil { + log.Printf("error loading key: %s", err) + return nil, err + } + + dict[key], err = d.unmarshalTree(file) + if err != nil { + log.Printf("error loading unmarshalTree: %s", err) + return nil, err + } + } + + return dict, nil +} + +func (d *FModData) unmarshalString(file *os.File) (string, error) { + // read "empty" flag + empty, err := d.unmarshalBool(file) + if err != nil { + log.Printf("error loading empty flag of string: %s", err) + return "", err + } + + if empty { + return "", nil + } + + key, err := readString(file, Version(d.Version), false) + if err != nil { + log.Printf("could not read key-string: %s", err) + return "", err + } + + return key, nil +} + +func (d *FModData) Encode() ([]byte, error) { + var output []byte + + _bytes, err := d.Version.MarshalBinary() + if err != nil { + log.Printf("couldn't create binary from version: %s", err) + return nil, err + } + + output = append(output, _bytes...) + + tree, err := d.marshalTree(d.Data) + if err != nil { + log.Printf("error loading first tree: %s", err) + return nil, err + } + output = append(output, tree...) + + return output, nil +} + +func (d *FModData) marshalTree(data interface{}) (output []byte , err error) { + // get type + _type := reflect.TypeOf(data).Kind() + + // write any-type flag + anyTypeFlag := d.marshalBool(_type == reflect.String) + + var typeByte byte + var marshalledBytes []byte + + switch _type { + case reflect.Bool: + typeByte = BOOL + marshalledBytes = []byte{d.marshalBool(data.(bool))} + break + case reflect.Float64: + { + floatValue, err := d.marshalFloat64(data.(float64)) + if err != nil { + log.Printf("could not read float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + } + break + case reflect.String: + typeByte = STRING + marshalledBytes = d.marshalString(data.(string)) + break + case reflect.Array: + // List + list, err := d.marshalList(data.([]interface{})) + if err != nil { + log.Printf("could not read List: %s", err) + return nil, err + } + typeByte = LIST + marshalledBytes = list + break + case reflect.Map: + // Dict + _map, err := d.marshalDict(data.(map[string]interface{})) + if err != nil { + log.Printf("could not read Dict: %s", err) + return nil, err + } + typeByte = DICT + marshalledBytes = _map + break + } + + output = append(output, typeByte) + output = append(output, anyTypeFlag) + output = append(output, marshalledBytes...) + + return output, nil +} + +func (d *FModData) marshalBool(data bool) byte { + if data { + return 0x1 + } else { + return 0x0 + } +} + +func (d *FModData) marshalFloat64(data float64) ([]byte, error) { + var buf bytes.Buffer + + err := binary.Write(&buf, binary.LittleEndian, data) + if err != nil { + log.Printf("could not write data into buffer: %s", err) + return nil, err + } + + return buf.Bytes(), nil +} + +func (d *FModData) marshalString(data string) []byte { + var output []byte + + length := uint32(len(data)) + output = []byte{d.marshalBool(length == 0)} + + output = append(output, d.marshalOptimUint(length)...) + stringBytes := []byte(data) + return append(output, stringBytes...) +} + +func (d *FModData) marshalOptimUint(data uint32) []byte { + if data < 256 { + intBinary := []byte{byte(data)} + return intBinary[:] + } else { + var intBinary [4]byte + binary.LittleEndian.PutUint32(intBinary[:], data) + return append([]byte{0xff}, intBinary[:]...) + } +} + +func (d *FModData) marshalList(data []interface{}) ([]byte, error) { + var output []byte + + length := uint32(len(data)) + output = d.marshalOptimUint(length) + + for i := uint32(0); i < length; i++ { + tree, err := d.marshalTree(data[i]) + if err != nil { + log.Printf("error loading tree of list-element: %s", err) + return nil, err + } + output = append(output, tree...) + } + + return output, nil +} + +func (d *FModData) marshalDict(data map[string]interface{}) ([]byte, error) { + var output []byte + + length := uint32(len(data)) + + var buf [4]byte + binary.LittleEndian.PutUint32(buf[:], length) + output = append(output, buf[:]...) + + for key, value := range data { + output = append(output, d.marshalString(key)...) + tree, err := d.marshalTree(value) + if err != nil { + log.Printf("error loading tree of dict-element: %s", err) + return nil, err + } + output = append(output, tree...) + } + + return output, nil +} From 0dec60a999a55c0f590e82a382801bc8785590c1 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Thu, 7 Feb 2019 23:39:15 +0100 Subject: [PATCH 03/25] added test for reading and writing mod settings & fixes --- .../mod_settings_0.16.dat | Bin 0 -> 7396 bytes .../mod_settings_0.16.json | 485 ++++++++++++++++++ src/main.go | 11 - src/mod_setting_dat_test.go | 64 +++ src/mod_settings_dat.go | 140 +++-- 5 files changed, 657 insertions(+), 43 deletions(-) create mode 100644 src/factorio_mod_settings_testfiles/mod_settings_0.16.dat create mode 100644 src/factorio_mod_settings_testfiles/mod_settings_0.16.json create mode 100644 src/mod_setting_dat_test.go diff --git a/src/factorio_mod_settings_testfiles/mod_settings_0.16.dat b/src/factorio_mod_settings_testfiles/mod_settings_0.16.dat new file mode 100644 index 0000000000000000000000000000000000000000..ee77eef4dc5f0aa2a653732ee9522bef9ba1284d GIT binary patch literal 7396 zcmbVRJD21}6|OcO);#uMug&fPyA1fj!^i0vQ}4GEy?WE2*j_RcU$;6YOK^yN|l>x?=1R`)QH){f_?oc3yIOQ&*N*si`U@JPiIB?a9*XW;&{pIrwdo%`Dt#UKqAAV0i z|6Q}^W8f7bWv!&JS6idoW=7SqXa8BV2f5`KMFK=3aW28Esf8$J z%szYjPrv->l_TE2icm$Gm}qqZDc?fli3TSus_S4(OWF zi7M;7KhX?Paqko3O6biV00!&J`V5ZPIm@NaoS0e7OS5KcT>AI|)FlFtpwl4Rm<{_X zoeHj?&kXW$_w(0v7YJLKmj;IB*IL*Gb`(@!1G^rZ7D<>#CrnZ>>B$I4x;3rLWidDL zihUVp;%0g+irS9mT2_^?ll%CyT*+#iI3r(P8(T$0ij_mnK=lH zzvucg_N0sB>{_}KS)>b7Ww}u%w(yG)u+MsPdJ0$&yoGj9&K+M1%xoiuvl(Gl{U0jYSa^D+a$4)u6~reytv;!PuS z_I!ZLy+)bnQY|}`+6fs2$KwI6yR6AY*5on*d7e2kutr|(+6D@D#SxJc!SA1VZp}72 z{tkYL&eCL1SX5heMEMq#%(@Q=?bQ9nTZC3dZ$B zLi4RcD5eP*`<}ndlt7E?Wt#WWG)={oTBds9sicP696Z+*L<>*~+E zTKXdK#^&V3le9uMXL*$fyFQ~ghx zmb$*`{$tHPJjZ4j?#K-jcl*2iaeb=7-ikAG#7)T)|7{&RFc8-WH{~!|oww$)Lp+nS z_6)@-x`b!3e2t_HMusafCMI4QjD3G@{eDP47e(}F>wcp69n&ve*%QaUPg36zKj0L_ z@r1|72D9J^N__V&6U0{Yp$q!ZUA@P8(cWFlVH0F8nBQ|aYrrs!r8P)t-xmPHeQ0W) z7B64jpw5l!*2HM^)(L%LFDgvam2l;;0VOKM1nbR&3=hq%BPk@Wj4o0XLA5D`!26!7 zBt>70{}(C_h4zQm>3Ps(4i_UOh={N@I)xF9kLQvBtrl zBaJ_8F{0f@mrFq{`q1pPzGSsVDm+|XRfnckcxgsDJomvgQrDHn%9fr`5j>@`le9UA zpkX>5b8hv%aUzLNnYo+Hh(6+;3XEH+^OPoYrLp|QGu@fl5|->7CeBW2L>dajmT#rH zqa#l*O3}Hq2J4}+b55*!7*snMQsY67L`f+=H3`M%ULHi#2VZ287~KO?sT+#PRQaBu zPsbElUm=k3DY8zto;K2LYS&gHft@H|t2?ia$=jizY`MdLeq4AK1=a(4SUMrhW}hHv zf(>Cafbj}#bEmhHun*urTrqz1C)lAxtod%O(QQ2+oD|{Cj3i5~-Sr9TIKv|;a@PzBxt zoV57Hc2+t0( zX>qqE{ib_1+E3&DOS@mM?{Dz^&ijMJxA5`>d!0Nox<_rLcDTY-e@p>6e4?R$KHC}f zGQ(C{VW_IGNTyF~* 0 { + t.Fatalf("Data has %d differences: %s", len(diff), diff) + } + + + // Change some value + modData.Data.(map[string]interface{})["runtime-per-user"].(map[string]interface{})["folk-fill-fuel-stack-size"].(map[string]interface{})["value"] = 150 + test.(map[string]interface{})["runtime-per-user"].(map[string]interface{})["folk-fill-fuel-stack-size"].(map[string]interface{})["value"] = float64(150) + + // write new data + newBytes, err := modData.Encode() + newBytesReader := bytes.NewReader(newBytes) + if err != nil { + t.Fatalf("couldn't Encode modData: %s", err) + } + + var newData FModData + err = newData.Decode(newBytesReader) + if err != nil { + t.Fatalf("couldn't Decode newBytes: %s", err) + } + + diff2 := deep.Equal(newData.Data, test) + if len(diff2) > 0 { + t.Fatalf("Data has %d differences: %s", len(diff2), diff2) + } +} diff --git a/src/mod_settings_dat.go b/src/mod_settings_dat.go index a97c2001..7d658630 100644 --- a/src/mod_settings_dat.go +++ b/src/mod_settings_dat.go @@ -4,9 +4,8 @@ import ( "bytes" "encoding/binary" "fmt" + "io" "log" - "os" - "path/filepath" "reflect" ) @@ -24,18 +23,11 @@ type FModData struct { Data interface{} } -//func (d *FModData) Decode(file *os.File) error { -func (d *FModData) Decode() error { +func (d *FModData) Decode(file io.Reader) error { var version version64 var versionB [8]byte - file, err := os.Open(filepath.Join(config.FactorioModsDir, "mod-settings.dat")) - if err != nil { - log.Printf("could not open mod-settings.dat") - return err - } - - err = binary.Read(file, binary.LittleEndian, versionB[:]) + err := binary.Read(file, binary.LittleEndian, versionB[:]) if err != nil { log.Printf("could not read version: %s", err) } @@ -55,7 +47,7 @@ func (d *FModData) Decode() error { return nil } -func (d *FModData) unmarshalTree(file *os.File) (interface{}, error) { +func (d *FModData) unmarshalTree(file io.Reader) (interface{}, error) { //type of embedded data var _type byte err := binary.Read(file, binary.LittleEndian, &_type) @@ -87,7 +79,7 @@ func (d *FModData) unmarshalTree(file *os.File) (interface{}, error) { } } -func (d *FModData) unmarshalBool(file *os.File) (bool, error) { +func (d *FModData) unmarshalBool(file io.Reader) (bool, error) { var _data byte err := binary.Read(file, binary.LittleEndian, &_data) if err != nil { @@ -98,7 +90,7 @@ func (d *FModData) unmarshalBool(file *os.File) (bool, error) { return _data != 0, nil } -func (d *FModData) unmarshalDouble(file *os.File) (float64, error) { +func (d *FModData) unmarshalDouble(file io.Reader) (float64, error) { var _data float64 err := binary.Read(file, binary.LittleEndian, &_data) if err != nil { @@ -109,7 +101,7 @@ func (d *FModData) unmarshalDouble(file *os.File) (float64, error) { return _data, nil } -func (d *FModData) unmarshalList(file *os.File) ([]interface{}, error) { +func (d *FModData) unmarshalList(file io.Reader) ([]interface{}, error) { var length uint32 length, err := readOptimUint(file, Version(d.Version), 32) if err != nil { @@ -129,7 +121,7 @@ func (d *FModData) unmarshalList(file *os.File) ([]interface{}, error) { return list, nil } -func (d *FModData) unmarshalDict(file *os.File) (map[string]interface{}, error) { +func (d *FModData) unmarshalDict(file io.Reader) (map[string]interface{}, error) { var length uint32 err := binary.Read(file, binary.LittleEndian, &length) if err != nil { @@ -144,20 +136,20 @@ func (d *FModData) unmarshalDict(file *os.File) (map[string]interface{}, error) if err != nil { log.Printf("error loading key: %s", err) - return nil, err + return dict, err } dict[key], err = d.unmarshalTree(file) if err != nil { log.Printf("error loading unmarshalTree: %s", err) - return nil, err + return dict, err } } return dict, nil } -func (d *FModData) unmarshalString(file *os.File) (string, error) { +func (d *FModData) unmarshalString(file io.Reader) (string, error) { // read "empty" flag empty, err := d.unmarshalBool(file) if err != nil { @@ -213,22 +205,105 @@ func (d *FModData) marshalTree(data interface{}) (output []byte , err error) { case reflect.Bool: typeByte = BOOL marshalledBytes = []byte{d.marshalBool(data.(bool))} - break + case reflect.Int: + floatValue, err := d.marshalFloat64(float64(data.(int))) + if err != nil { + log.Printf("could not write int to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Int8: + floatValue, err := d.marshalFloat64(float64(data.(int8))) + if err != nil { + log.Printf("could not write int8 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Int16: + floatValue, err := d.marshalFloat64(float64(data.(int16))) + if err != nil { + log.Printf("could not write int16 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Int32: + floatValue, err := d.marshalFloat64(float64(data.(int32))) + if err != nil { + log.Printf("could not write int32 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Int64: + floatValue, err := d.marshalFloat64(float64(data.(int64))) + if err != nil { + log.Printf("could not write int64 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint: + floatValue, err := d.marshalFloat64(float64(data.(uint))) + if err != nil { + log.Printf("could not write uint to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint8: + floatValue, err := d.marshalFloat64(float64(data.(uint8))) + if err != nil { + log.Printf("could not write uint8 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint16: + floatValue, err := d.marshalFloat64(float64(data.(uint16))) + if err != nil { + log.Printf("could not write uint16 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint32: + floatValue, err := d.marshalFloat64(float64(data.(uint32))) + if err != nil { + log.Printf("could not write uint32 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint64: + floatValue, err := d.marshalFloat64(float64(data.(uint64))) + if err != nil { + log.Printf("could not write uint64 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Float32: + floatValue, err := d.marshalFloat64(float64(data.(float32))) + if err != nil { + log.Printf("could not write float32 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue case reflect.Float64: - { - floatValue, err := d.marshalFloat64(data.(float64)) - if err != nil { - log.Printf("could not read float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue + floatValue, err := d.marshalFloat64(data.(float64)) + if err != nil { + log.Printf("could not write float64 to float64-value: %s", err) + return nil, err } - break + typeByte = DOUBLE + marshalledBytes = floatValue case reflect.String: typeByte = STRING marshalledBytes = d.marshalString(data.(string)) - break case reflect.Array: // List list, err := d.marshalList(data.([]interface{})) @@ -238,7 +313,6 @@ func (d *FModData) marshalTree(data interface{}) (output []byte , err error) { } typeByte = LIST marshalledBytes = list - break case reflect.Map: // Dict _map, err := d.marshalDict(data.(map[string]interface{})) @@ -248,7 +322,9 @@ func (d *FModData) marshalTree(data interface{}) (output []byte , err error) { } typeByte = DICT marshalledBytes = _map - break + default: + log.Println("Unknown Datatype") + return output, fmt.Errorf("unknown datatype") } output = append(output, typeByte) From fdab3e6994f4d27d58c65ff732c4d471f8ae0b38 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Fri, 8 Feb 2019 01:17:40 +0100 Subject: [PATCH 04/25] made writing and reading global --- src/factorio_data_types.go | 403 ++++++++++++++++++++++++++++++++++++ src/factorio_save.go | 57 ----- src/mod_setting_dat_test.go | 4 + src/mod_settings_dat.go | 340 +----------------------------- 4 files changed, 412 insertions(+), 392 deletions(-) create mode 100644 src/factorio_data_types.go diff --git a/src/factorio_data_types.go b/src/factorio_data_types.go new file mode 100644 index 00000000..d4803cdd --- /dev/null +++ b/src/factorio_data_types.go @@ -0,0 +1,403 @@ +package main + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" + "log" + "reflect" +) + + +/////////////////// +// Reading //////// +/////////////////// +func readOptimUint(r io.Reader, v Version, bitSize int) (uint32, error) { + var b [4]byte + if !v.Less(Version{0, 14, 14, 0}) { + _, err := r.Read(b[:1]) + if err != nil { + return 0, err + } + if b[0] != 0xFF { + return uint32(b[0]), nil + } + } + + if bitSize < 0 || bitSize > 64 || (bitSize%8 != 0) { + panic("invalid bit size") + } + + _, err := r.Read(b[:bitSize/8]) + if err != nil { + return 0, err + } + + switch bitSize { + case 16: + return uint32(binary.LittleEndian.Uint16(b[:2])), nil + case 32: + return binary.LittleEndian.Uint32(b[:4]), nil + default: + panic("invalid bit size") + } +} + +func readString(r io.Reader, game Version, forceOptimized bool) (s string, err error) { + var n uint32 + + if !game.Less(Version{0, 16, 0, 0}) || forceOptimized { + n, err = readOptimUint(r, game, 32) + if err != nil { + return "", err + } + } else { + var b [4]byte + _, err := r.Read(b[:]) + if err != nil { + return "", fmt.Errorf("failed to read string length: %v", err) + } + n = uint32(binary.LittleEndian.Uint32(b[:])) + } + + d := make([]byte, n) + _, err = r.Read(d) + if err != nil { + return "", fmt.Errorf("failed to read string: %v", err) + } + + return string(d), nil +} + +func readBool(file io.Reader) (bool, error) { + var _data byte + err := binary.Read(file, binary.LittleEndian, &_data) + if err != nil { + log.Printf("could not read boolean byte: %s", err) + return false, err + } + + return _data != 0, nil +} + +func readDouble(file io.Reader) (float64, error) { + var _data float64 + err := binary.Read(file, binary.LittleEndian, &_data) + if err != nil { + log.Printf("could not read double-value: %s", err) + return 0, err + } + + return _data, nil +} + +func readList(file io.Reader) ([]interface{}, error) { + var length uint32 + length, err := readOptimUint(file, FactorioServ.Version, 32) + if err != nil { + log.Printf("could not read list length") + return nil, err + } + + list := make([]interface{}, length) + for i := uint32(0); i < length; i++ { + list[i], err = readTree(file) + if err != nil { + log.Printf("could not read tree of list: %s", err) + return nil, err + } + } + + return list, nil +} + +func readDict(file io.Reader) (map[string]interface{}, error) { + var length uint32 + err := binary.Read(file, binary.LittleEndian, &length) + if err != nil { + log.Printf("could not read dict length: %s", err) + return nil, err + } + + dict := make(map[string]interface{}) + + for i := uint32(0); i < length; i++ { + key, err := readStringSettings(file) + + if err != nil { + log.Printf("error loading key: %s", err) + return dict, err + } + + dict[key], err = readTree(file) + if err != nil { + log.Printf("error loading readTree: %s", err) + return dict, err + } + } + + return dict, nil +} + +func readTree(file io.Reader) (interface{}, error) { + //type of embedded data + var _type byte + err := binary.Read(file, binary.LittleEndian, &_type) + if err != nil { + log.Printf("could not read first binary: %v", err) + return nil, err + } + + //anyType flag ... not useful + _, err = readBool(file) + if err != nil { + log.Printf("error loading anyType bool: %s", err) + return nil, err + } + + switch _type { + case BOOL: + return readBool(file) + case DOUBLE: + return readDouble(file) + case STRING: + return readStringSettings(file) + case LIST: + return readList(file) + case DICT: + return readDict(file) + default: + return nil, fmt.Errorf("Unknown type: %s ", err) + } +} + + + +/////////////////// +// Writing //////// +/////////////////// +func writeOptimUint(data uint32) []byte { + if data < 256 { + intBinary := []byte{byte(data)} + return intBinary[:] + } else { + var intBinary [4]byte + binary.LittleEndian.PutUint32(intBinary[:], data) + return append([]byte{0xff}, intBinary[:]...) + } +} + +func writeFloat64(data float64) ([]byte, error) { + var buf bytes.Buffer + + err := binary.Write(&buf, binary.LittleEndian, data) + if err != nil { + log.Printf("could not write data into buffer: %s", err) + return nil, err + } + + return buf.Bytes(), nil +} + +func writeBool(data bool) byte { + if data { + return 0x1 + } else { + return 0x0 + } +} + +func writeString(data string) []byte { + var output []byte + + length := uint32(len(data)) + output = []byte{writeBool(length == 0)} + + output = append(output, writeOptimUint(length)...) + stringBytes := []byte(data) + return append(output, stringBytes...) +} + +func writeList(data []interface{}) ([]byte, error) { + var output []byte + + length := uint32(len(data)) + output = writeOptimUint(length) + + for i := uint32(0); i < length; i++ { + tree, err := writeTree(data[i]) + if err != nil { + log.Printf("error loading tree of list-element: %s", err) + return nil, err + } + output = append(output, tree...) + } + + return output, nil +} + +func writeDict(data map[string]interface{}) ([]byte, error) { + var output []byte + + length := uint32(len(data)) + + var buf [4]byte + binary.LittleEndian.PutUint32(buf[:], length) + output = append(output, buf[:]...) + + for key, value := range data { + output = append(output, writeString(key)...) + tree, err := writeTree(value) + if err != nil { + log.Printf("error loading tree of dict-element: %s", err) + return nil, err + } + output = append(output, tree...) + } + + return output, nil +} + +func writeTree(data interface{}) (output []byte , err error) { + // get type + _type := reflect.TypeOf(data).Kind() + + // write any-type flag + anyTypeFlag := writeBool(_type == reflect.String) + + var typeByte byte + var marshalledBytes []byte + + switch _type { + case reflect.Bool: + typeByte = BOOL + marshalledBytes = []byte{writeBool(data.(bool))} + case reflect.Int: + floatValue, err := writeFloat64(float64(data.(int))) + if err != nil { + log.Printf("could not write int to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Int8: + floatValue, err := writeFloat64(float64(data.(int8))) + if err != nil { + log.Printf("could not write int8 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Int16: + floatValue, err := writeFloat64(float64(data.(int16))) + if err != nil { + log.Printf("could not write int16 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Int32: + floatValue, err := writeFloat64(float64(data.(int32))) + if err != nil { + log.Printf("could not write int32 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Int64: + floatValue, err := writeFloat64(float64(data.(int64))) + if err != nil { + log.Printf("could not write int64 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint: + floatValue, err := writeFloat64(float64(data.(uint))) + if err != nil { + log.Printf("could not write uint to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint8: + floatValue, err := writeFloat64(float64(data.(uint8))) + if err != nil { + log.Printf("could not write uint8 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint16: + floatValue, err := writeFloat64(float64(data.(uint16))) + if err != nil { + log.Printf("could not write uint16 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint32: + floatValue, err := writeFloat64(float64(data.(uint32))) + if err != nil { + log.Printf("could not write uint32 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Uint64: + floatValue, err := writeFloat64(float64(data.(uint64))) + if err != nil { + log.Printf("could not write uint64 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Float32: + floatValue, err := writeFloat64(float64(data.(float32))) + if err != nil { + log.Printf("could not write float32 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.Float64: + floatValue, err := writeFloat64(data.(float64)) + if err != nil { + log.Printf("could not write float64 to float64-value: %s", err) + return nil, err + } + typeByte = DOUBLE + marshalledBytes = floatValue + case reflect.String: + typeByte = STRING + marshalledBytes = writeString(data.(string)) + case reflect.Array: + // List + list, err := writeList(data.([]interface{})) + if err != nil { + log.Printf("could not read List: %s", err) + return nil, err + } + typeByte = LIST + marshalledBytes = list + case reflect.Map: + // Dict + _map, err := writeDict(data.(map[string]interface{})) + if err != nil { + log.Printf("could not read Dict: %s", err) + return nil, err + } + typeByte = DICT + marshalledBytes = _map + default: + log.Println("Unknown Datatype") + return output, fmt.Errorf("unknown datatype") + } + + output = append(output, typeByte) + output = append(output, anyTypeFlag) + output = append(output, marshalledBytes...) + + return output, nil +} diff --git a/src/factorio_save.go b/src/factorio_save.go index 3f843c6c..60b5f885 100644 --- a/src/factorio_save.go +++ b/src/factorio_save.go @@ -214,63 +214,6 @@ func (h *SaveHeader) ReadFrom(r io.Reader) (err error) { return nil } -func readOptimUint(r io.Reader, v Version, bitSize int) (uint32, error) { - var b [4]byte - if !v.Less(Version{0, 14, 14, 0}) { - _, err := r.Read(b[:1]) - if err != nil { - return 0, err - } - if b[0] != 0xFF { - return uint32(b[0]), nil - } - } - - if bitSize < 0 || bitSize > 64 || (bitSize%8 != 0) { - panic("invalid bit size") - } - - _, err := r.Read(b[:bitSize/8]) - if err != nil { - return 0, err - } - - switch bitSize { - case 16: - return uint32(binary.LittleEndian.Uint16(b[:2])), nil - case 32: - return binary.LittleEndian.Uint32(b[:4]), nil - default: - panic("invalid bit size") - } -} - -func readString(r io.Reader, game Version, forceOptimized bool) (s string, err error) { - var n uint32 - - if !game.Less(Version{0, 16, 0, 0}) || forceOptimized { - n, err = readOptimUint(r, game, 32) - if err != nil { - return "", err - } - } else { - var b [4]byte - _, err := r.Read(b[:]) - if err != nil { - return "", fmt.Errorf("failed to read string length: %v", err) - } - n = uint32(binary.LittleEndian.Uint32(b[:])) - } - - d := make([]byte, n) - _, err = r.Read(d) - if err != nil { - return "", fmt.Errorf("failed to read string: %v", err) - } - - return string(d), nil -} - func (h SaveHeader) readStats(r io.Reader) (stats map[byte][]map[uint16]uint32, err error) { var scratch [4]byte stats = make(map[byte][]map[uint16]uint32) diff --git a/src/mod_setting_dat_test.go b/src/mod_setting_dat_test.go index b546ca8a..762ffea0 100644 --- a/src/mod_setting_dat_test.go +++ b/src/mod_setting_dat_test.go @@ -11,6 +11,10 @@ import ( ) func TestModSettings0_16(t *testing.T) { + FactorioServ = &FactorioServer { + Version: Version{0, 16, 0, 0}, + } + // Read dat and compare to JSON file, err := os.Open(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.16.dat")) if err != nil { diff --git a/src/mod_settings_dat.go b/src/mod_settings_dat.go index 7d658630..efa62d18 100644 --- a/src/mod_settings_dat.go +++ b/src/mod_settings_dat.go @@ -1,12 +1,9 @@ package main import ( - "bytes" "encoding/binary" - "fmt" "io" "log" - "reflect" ) const ( @@ -38,7 +35,7 @@ func (d *FModData) Decode(file io.Reader) error { } d.Version = version - d.Data, err = d.unmarshalTree(file) + d.Data, err = readTree(file) if err != nil { log.Printf("error loading Data: %s", err) return err @@ -47,111 +44,9 @@ func (d *FModData) Decode(file io.Reader) error { return nil } -func (d *FModData) unmarshalTree(file io.Reader) (interface{}, error) { - //type of embedded data - var _type byte - err := binary.Read(file, binary.LittleEndian, &_type) - if err != nil { - log.Printf("could not read first binary: %v", err) - return nil, err - } - - //anyType flag ... not useful - _, err = d.unmarshalBool(file) - if err != nil { - log.Printf("error loading anyType bool: %s", err) - return nil, err - } - - switch _type { - case BOOL: - return d.unmarshalBool(file) - case DOUBLE: - return d.unmarshalDouble(file) - case STRING: - return d.unmarshalString(file) - case LIST: - return d.unmarshalList(file) - case DICT: - return d.unmarshalDict(file) - default: - return nil, fmt.Errorf("Unknown type: %s ", err) - } -} - -func (d *FModData) unmarshalBool(file io.Reader) (bool, error) { - var _data byte - err := binary.Read(file, binary.LittleEndian, &_data) - if err != nil { - log.Printf("could not read boolean byte: %s", err) - return false, err - } - - return _data != 0, nil -} - -func (d *FModData) unmarshalDouble(file io.Reader) (float64, error) { - var _data float64 - err := binary.Read(file, binary.LittleEndian, &_data) - if err != nil { - log.Printf("could not read double-value: %s", err) - return 0, err - } - - return _data, nil -} - -func (d *FModData) unmarshalList(file io.Reader) ([]interface{}, error) { - var length uint32 - length, err := readOptimUint(file, Version(d.Version), 32) - if err != nil { - log.Printf("could not read list length") - return nil, err - } - - list := make([]interface{}, length) - for i := uint32(0); i < length; i++ { - list[i], err = d.unmarshalTree(file) - if err != nil { - log.Printf("could not read tree of list: %s", err) - return nil, err - } - } - - return list, nil -} - -func (d *FModData) unmarshalDict(file io.Reader) (map[string]interface{}, error) { - var length uint32 - err := binary.Read(file, binary.LittleEndian, &length) - if err != nil { - log.Printf("could not read dict length: %s", err) - return nil, err - } - - dict := make(map[string]interface{}) - - for i := uint32(0); i < length; i++ { - key, err := d.unmarshalString(file) - - if err != nil { - log.Printf("error loading key: %s", err) - return dict, err - } - - dict[key], err = d.unmarshalTree(file) - if err != nil { - log.Printf("error loading unmarshalTree: %s", err) - return dict, err - } - } - - return dict, nil -} - -func (d *FModData) unmarshalString(file io.Reader) (string, error) { +func readStringSettings(file io.Reader) (string, error) { // read "empty" flag - empty, err := d.unmarshalBool(file) + empty, err := readBool(file) if err != nil { log.Printf("error loading empty flag of string: %s", err) return "", err @@ -161,7 +56,7 @@ func (d *FModData) unmarshalString(file io.Reader) (string, error) { return "", nil } - key, err := readString(file, Version(d.Version), false) + key, err := readString(file, FactorioServ.Version, false) if err != nil { log.Printf("could not read key-string: %s", err) return "", err @@ -181,7 +76,7 @@ func (d *FModData) Encode() ([]byte, error) { output = append(output, _bytes...) - tree, err := d.marshalTree(d.Data) + tree, err := writeTree(d.Data) if err != nil { log.Printf("error loading first tree: %s", err) return nil, err @@ -190,228 +85,3 @@ func (d *FModData) Encode() ([]byte, error) { return output, nil } - -func (d *FModData) marshalTree(data interface{}) (output []byte , err error) { - // get type - _type := reflect.TypeOf(data).Kind() - - // write any-type flag - anyTypeFlag := d.marshalBool(_type == reflect.String) - - var typeByte byte - var marshalledBytes []byte - - switch _type { - case reflect.Bool: - typeByte = BOOL - marshalledBytes = []byte{d.marshalBool(data.(bool))} - case reflect.Int: - floatValue, err := d.marshalFloat64(float64(data.(int))) - if err != nil { - log.Printf("could not write int to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Int8: - floatValue, err := d.marshalFloat64(float64(data.(int8))) - if err != nil { - log.Printf("could not write int8 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Int16: - floatValue, err := d.marshalFloat64(float64(data.(int16))) - if err != nil { - log.Printf("could not write int16 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Int32: - floatValue, err := d.marshalFloat64(float64(data.(int32))) - if err != nil { - log.Printf("could not write int32 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Int64: - floatValue, err := d.marshalFloat64(float64(data.(int64))) - if err != nil { - log.Printf("could not write int64 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Uint: - floatValue, err := d.marshalFloat64(float64(data.(uint))) - if err != nil { - log.Printf("could not write uint to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Uint8: - floatValue, err := d.marshalFloat64(float64(data.(uint8))) - if err != nil { - log.Printf("could not write uint8 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Uint16: - floatValue, err := d.marshalFloat64(float64(data.(uint16))) - if err != nil { - log.Printf("could not write uint16 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Uint32: - floatValue, err := d.marshalFloat64(float64(data.(uint32))) - if err != nil { - log.Printf("could not write uint32 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Uint64: - floatValue, err := d.marshalFloat64(float64(data.(uint64))) - if err != nil { - log.Printf("could not write uint64 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Float32: - floatValue, err := d.marshalFloat64(float64(data.(float32))) - if err != nil { - log.Printf("could not write float32 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.Float64: - floatValue, err := d.marshalFloat64(data.(float64)) - if err != nil { - log.Printf("could not write float64 to float64-value: %s", err) - return nil, err - } - typeByte = DOUBLE - marshalledBytes = floatValue - case reflect.String: - typeByte = STRING - marshalledBytes = d.marshalString(data.(string)) - case reflect.Array: - // List - list, err := d.marshalList(data.([]interface{})) - if err != nil { - log.Printf("could not read List: %s", err) - return nil, err - } - typeByte = LIST - marshalledBytes = list - case reflect.Map: - // Dict - _map, err := d.marshalDict(data.(map[string]interface{})) - if err != nil { - log.Printf("could not read Dict: %s", err) - return nil, err - } - typeByte = DICT - marshalledBytes = _map - default: - log.Println("Unknown Datatype") - return output, fmt.Errorf("unknown datatype") - } - - output = append(output, typeByte) - output = append(output, anyTypeFlag) - output = append(output, marshalledBytes...) - - return output, nil -} - -func (d *FModData) marshalBool(data bool) byte { - if data { - return 0x1 - } else { - return 0x0 - } -} - -func (d *FModData) marshalFloat64(data float64) ([]byte, error) { - var buf bytes.Buffer - - err := binary.Write(&buf, binary.LittleEndian, data) - if err != nil { - log.Printf("could not write data into buffer: %s", err) - return nil, err - } - - return buf.Bytes(), nil -} - -func (d *FModData) marshalString(data string) []byte { - var output []byte - - length := uint32(len(data)) - output = []byte{d.marshalBool(length == 0)} - - output = append(output, d.marshalOptimUint(length)...) - stringBytes := []byte(data) - return append(output, stringBytes...) -} - -func (d *FModData) marshalOptimUint(data uint32) []byte { - if data < 256 { - intBinary := []byte{byte(data)} - return intBinary[:] - } else { - var intBinary [4]byte - binary.LittleEndian.PutUint32(intBinary[:], data) - return append([]byte{0xff}, intBinary[:]...) - } -} - -func (d *FModData) marshalList(data []interface{}) ([]byte, error) { - var output []byte - - length := uint32(len(data)) - output = d.marshalOptimUint(length) - - for i := uint32(0); i < length; i++ { - tree, err := d.marshalTree(data[i]) - if err != nil { - log.Printf("error loading tree of list-element: %s", err) - return nil, err - } - output = append(output, tree...) - } - - return output, nil -} - -func (d *FModData) marshalDict(data map[string]interface{}) ([]byte, error) { - var output []byte - - length := uint32(len(data)) - - var buf [4]byte - binary.LittleEndian.PutUint32(buf[:], length) - output = append(output, buf[:]...) - - for key, value := range data { - output = append(output, d.marshalString(key)...) - tree, err := d.marshalTree(value) - if err != nil { - log.Printf("error loading tree of dict-element: %s", err) - return nil, err - } - output = append(output, tree...) - } - - return output, nil -} From a52cdbd2543b57dedca2e8ff56cca972ad4f9688 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Sat, 9 Feb 2019 18:52:49 +0100 Subject: [PATCH 05/25] added go-test/deep to dependencies --- .travis.yml | 1 + README.md | 1 + gopkglist | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 91c99481..a2298a3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ go: install: - go get github.com/apexskier/httpauth - go get github.com/go-ini/ini + - go get github.com/go-test/deep - go get github.com/gorilla/mux - go get github.com/hpcloud/tail - go get github.com/gorilla/websocket diff --git a/README.md b/README.md index 5c98b461..c0961f1c 100644 --- a/README.md +++ b/README.md @@ -151,6 +151,7 @@ Once everything is installed and ready to go you will need to compile the source ``` go get github.com/apexskier/httpauth go get github.com/go-ini/ini +go get github.com/go-test/deep go get github.com/gorilla/mux go get github.com/hpcloud/tail go get github.com/gorilla/websocket diff --git a/gopkglist b/gopkglist index fd98cb49..357f2dc4 100644 --- a/gopkglist +++ b/gopkglist @@ -1,6 +1,7 @@ github.com/apexskier/httpauth github.com/go-ini/ini +github.com/go-test/deep github.com/gorilla/mux github.com/gorilla/websocket github.com/hpcloud/tail -github.com/majormjr/rcon \ No newline at end of file +github.com/majormjr/rcon From db7bb90995b496ddc8c11e7f6438b1f1dee53fd5 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Mon, 25 Feb 2019 23:57:10 +0100 Subject: [PATCH 06/25] fixed naming typo --- src/{mod_setting_dat_test.go => mod_settings_dat_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{mod_setting_dat_test.go => mod_settings_dat_test.go} (100%) diff --git a/src/mod_setting_dat_test.go b/src/mod_settings_dat_test.go similarity index 100% rename from src/mod_setting_dat_test.go rename to src/mod_settings_dat_test.go From 359212d66eb9802211341a65b5f298e67dd639a1 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Wed, 27 Feb 2019 00:28:01 +0100 Subject: [PATCH 07/25] added frontend & first backend stuff --- src/mods_handler.go | 11 ++++++ src/routes.go | 14 ++++++++ ui/App/App.jsx | 2 ++ ui/App/components/ModConfigContent.jsx | 50 ++++++++++++++++++++++++++ ui/App/components/Sidebar.jsx | 5 +++ 5 files changed, 82 insertions(+) create mode 100644 ui/App/components/ModConfigContent.jsx diff --git a/src/mods_handler.go b/src/mods_handler.go index 50f11711..f222e676 100644 --- a/src/mods_handler.go +++ b/src/mods_handler.go @@ -908,3 +908,14 @@ func ModPackUpdateModHandler(w http.ResponseWriter, r *http.Request) { log.Printf("Error in DeleteModHandler: %s", err) } } + +func GetModConfig(w http.ResponseWriter, r *http.Request) { + var err error + resp := JSONResponse{ + Success: false, + } + + w.Header().Set("Content-Type", "application/json;charset=UTF-8") + + +} diff --git a/src/routes.go b/src/routes.go index 4ee0d329..c4def25a 100644 --- a/src/routes.go +++ b/src/routes.go @@ -76,6 +76,10 @@ func NewRouter() *mux.Router { Methods("GET"). Name("Mods"). Handler(AuthorizeHandler(http.StripPrefix("/mods", http.FileServer(http.Dir("./app/"))))) + r.Path("/mod-config"). + Methods("GET"). + Name("ModConfig"). + Handler(AuthorizeHandler(http.StripPrefix("/mod-config", http.FileServer(http.Dir("./app/"))))) r.Path("/saves"). Methods("GET"). Name("Saves"). @@ -363,5 +367,15 @@ var apiRoutes = Routes{ "POST", "/settings/update", UpdateServerSettings, + }, { + "GetModConfigs", + "GET", + "/mods/settings", + GetModConfig, + }, { + "UpdateModsConfigs", + "POST", + "/mods/settings", + UpdateModConfig, }, } diff --git a/ui/App/App.jsx b/ui/App/App.jsx index 1d8036db..d66cc026 100644 --- a/ui/App/App.jsx +++ b/ui/App/App.jsx @@ -12,6 +12,7 @@ import LogsContent from "./components/LogsContent"; import SavesContent from "./components/SavesContent"; import ConfigContent from "./components/ConfigContent"; import ConsoleContent from "./components/ConsoleContent"; +import ModConfigContent from "./components/ModConfigContent"; class App extends React.Component { constructor(props) { @@ -180,6 +181,7 @@ class App extends React.Component { {return }}/> {return }}/> {return }}/> + {return }}/> {return }}/> diff --git a/ui/App/components/ModConfigContent.jsx b/ui/App/components/ModConfigContent.jsx new file mode 100644 index 00000000..a4908fc7 --- /dev/null +++ b/ui/App/components/ModConfigContent.jsx @@ -0,0 +1,50 @@ +import React from "react"; +import {Link} from "react-router-dom"; +import FontAwesomeIcon from "./FontAwesomeIcon"; + +export default class ModConfigContent extends React.Component { + componentDidMount() { + + } + + render() { + return ( +
+
+

+ Mod-Configuration + + +
    +
  1. + Server Control +
  2. +
  3. + Mod-Configuration +
  4. +
+
+

+
+ +
+
+
+

Configure Mods

+
+ +
+
+ +
+ +

Help text for Tests

+
+
+
+
+
+
+ ); + } +} diff --git a/ui/App/components/Sidebar.jsx b/ui/App/components/Sidebar.jsx index ec759395..5df6ed60 100644 --- a/ui/App/components/Sidebar.jsx +++ b/ui/App/components/Sidebar.jsx @@ -56,6 +56,11 @@ class Sidebar extends React.Component {

Mods

+
  • + +

    Mod Configuration

    +
    +
  • Logs

    From cbce1982e385291aa800072e5487557acefb0806 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Thu, 28 Feb 2019 14:20:04 +0100 Subject: [PATCH 08/25] added 0.17 test (broken) --- .../mod_settings_0.17.dat | Bin 0 -> 6145 bytes .../mod_settings_0.17.json | 368 ++++++++++++++++++ src/mod_settings_dat.go | 15 + src/mod_settings_dat_test.go | 69 ++++ src/mods_handler.go | 21 +- src/routes.go | 6 +- 6 files changed, 466 insertions(+), 13 deletions(-) create mode 100644 src/factorio_mod_settings_testfiles/mod_settings_0.17.dat create mode 100644 src/factorio_mod_settings_testfiles/mod_settings_0.17.json diff --git a/src/factorio_mod_settings_testfiles/mod_settings_0.17.dat b/src/factorio_mod_settings_testfiles/mod_settings_0.17.dat new file mode 100644 index 0000000000000000000000000000000000000000..9f25235861c860bd5b7c290573e2f5d5e8507db2 GIT binary patch literal 6145 zcma)A%Z}Vc6s-=7NESc>2ts%zJOTlXB0vabLC-HBA+avo)$JnXDyJSj)AJ|r2Ydo+ zR!Hyx?2uR?vEUOpWp~xsuJUxen33K0aq8Y%_eIDpa*aGo$O(Cd;Caqis;%ozNb6s3 ze@``Qlrvmz3tlN%n2HL#oRF3O{bWalV=KJe9aC1S+ZRG@xv{(|%-&em&NybW4L`Sx z$)Z&?ODNwdRf!)=L5*Q;DfUIxu$BW!C#bY$#;_u9B@DHPA_UW%rQ~lX*2Y9;oD z>6HGxC3?xLmR1dy86~eLOdF>qtumw^B&4kqmUm8f%CJSY^cac@%{G9OJ@(5%O{Ij= zuB)k?+kQpjS(${%8GIl(lcv_HL!j^ttupqH4hu|7(o(QxhIa#$DT8EZ%RKMrc}z=% zSmt^yaB&IWTDTX1Dz~2}F_a-}m1ZenGqeiPzbxJ2;Mo5f+5s#)^3TBY74(^>Dj$B6cCD%sm0nID28%^8HmCV2k8WtV> zAcWebqQG;^0U0B9ykl3|9`0UXyVCaePs#lhXfV2F74$CThBxzk)@Oz^s1~%?W46e6 z*=>D3r?O&;#*gW?<Yqwr2mive2m=#LEz9RxOtux`82Pk)6h{_zTBx~g@qL#2iui$~B#tLCMmCrQPXuxADifqu3!w}CSoDI&2Gzk`%V86BFPJ|_ zIBLMyyyOw&&<_a!aUW|<;I*1cgFH9RTN9)CF({_*Eo;#rx6C#ed9=@s6WU-V-0)a) zdX}2gR>?ZY5ur^vSj#jOS&ktY{kH1%uuHThC5mXxBC95pyg9rhnEX z_Q<^ki;>`Bnf}j_3N+H8aFx`Z^I0nNMvcwIh_+HCk`F#i%sO$wh}wgCYFZ`gr=`Up zlcmie#zgp-VY*5YM}LkGKXK@sE|SCLNHyw^NTud57%ni2JS_&}1SZS`Lma6`aBZVB zcYZ2L$a9b_mpRhdw2mb^xy8~TOP@Pp-!OUp1W3G_Bk31hRyibd(2egfja4!|Uu*<> zv4}Jzh?16EpfQ?Y2t^guXnIf|og1xMWt-kPDfHMs_By!4AdicZ13op0kIyaNF*5|; z1WtOhJoP}BySg!%Ou-Kf!*$HD4H*JAKF8K$8+a3JQ@c8e3v5{pTU~i7T zQGoOLSw{0@|Ft495Dp5k2*P3nN1Z{z7A~ax1LclNj6AfYS~HQ^+l^{hr_PuzXjM5Z zn<(JV19Eklk_Xz2a2&3|l;X(~EOEUwP@`@q*Km9B$-R9B#j z+vcz0H`tn_OqE00Z@ux%)abC?w_IZn-e0gsUq5_!7t3yMn&HD&_|RvR$vY}YQEIdT zkG{n3emUt^(Ku0qTlwfAxfj5OO%Xi)#G&*QJ|}F1I-5AqyXBSsTtj$R 0 { + t.Fatalf("Data has %d differences: %s", len(diff), diff) + } + + + // Change some value + modData.Data.(map[string]interface{})["runtime-per-user"].(map[string]interface{})["max-inventory-cleanup-drop-range"].(map[string]interface{})["value"] = 150 + test.(map[string]interface{})["runtime-per-user"].(map[string]interface{})["max-inventory-cleanup-drop-range"].(map[string]interface{})["value"] = float64(150) + + // write new data + newBytes, err := modData.Encode() + newBytesReader := bytes.NewReader(newBytes) + if err != nil { + t.Fatalf("couldn't Encode modData: %s", err) + } + + fmt.Println(newBytes) + data, _ := ioutil.ReadFile(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.17.dat")) + fmt.Println(data) + + var newData FModData + err = newData.Decode(newBytesReader) + if err != nil { + t.Fatalf("couldn't Decode newBytes: %s", err) + } + + diff2 := deep.Equal(newData.Data, test) + if len(diff2) > 0 { + t.Fatalf("Data has %d differences: %s", len(diff2), diff2) + } +} diff --git a/src/mods_handler.go b/src/mods_handler.go index f222e676..cddafccc 100644 --- a/src/mods_handler.go +++ b/src/mods_handler.go @@ -909,13 +909,14 @@ func ModPackUpdateModHandler(w http.ResponseWriter, r *http.Request) { } } -func GetModConfig(w http.ResponseWriter, r *http.Request) { - var err error - resp := JSONResponse{ - Success: false, - } - - w.Header().Set("Content-Type", "application/json;charset=UTF-8") - - -} +//func GetModConfig(w http.ResponseWriter, r *http.Request) { +// var err error +// resp := JSONResponse{ +// Success: false, +// } +// +// w.Header().Set("Content-Type", "application/json;charset=UTF-8") +// +// // load correct +// file, err := os.Open(filepath.Join(config.FactorioModsDir, "mod-settings.dat")) +//} diff --git a/src/routes.go b/src/routes.go index c4def25a..48c55999 100644 --- a/src/routes.go +++ b/src/routes.go @@ -367,15 +367,15 @@ var apiRoutes = Routes{ "POST", "/settings/update", UpdateServerSettings, - }, { + }, /*{ "GetModConfigs", "GET", "/mods/settings", GetModConfig, - }, { + },*/ /*{ "UpdateModsConfigs", "POST", "/mods/settings", UpdateModConfig, - }, + },*/ } From 22f01a02942eecda0fe96c07ec1511e29b031834 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Thu, 28 Feb 2019 23:13:07 +0100 Subject: [PATCH 09/25] added debug output --- src/factorio_data_types.go | 2 ++ src/mod_settings_dat_test.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/factorio_data_types.go b/src/factorio_data_types.go index d4803cdd..e6a4d1fc 100644 --- a/src/factorio_data_types.go +++ b/src/factorio_data_types.go @@ -372,6 +372,8 @@ func writeTree(data interface{}) (output []byte , err error) { case reflect.String: typeByte = STRING marshalledBytes = writeString(data.(string)) + log.Println(data) + log.Println(marshalledBytes) case reflect.Array: // List list, err := writeList(data.([]interface{})) diff --git a/src/mod_settings_dat_test.go b/src/mod_settings_dat_test.go index 10a17ba7..13043da8 100644 --- a/src/mod_settings_dat_test.go +++ b/src/mod_settings_dat_test.go @@ -56,6 +56,10 @@ func TestModSettings0_16(t *testing.T) { t.Fatalf("couldn't Encode modData: %s", err) } + fmt.Println(newBytes) + data, _ := ioutil.ReadFile(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.16.dat")) + fmt.Println(data) + var newData FModData err = newData.Decode(newBytesReader) if err != nil { From 74bb1d4b1fae66b5b193724f9c0fb8ff248d8156 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Thu, 7 Mar 2019 03:15:15 +0100 Subject: [PATCH 10/25] fixed wrong written bytes --- src/factorio_data_types.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/factorio_data_types.go b/src/factorio_data_types.go index e6a4d1fc..41d5c645 100644 --- a/src/factorio_data_types.go +++ b/src/factorio_data_types.go @@ -212,11 +212,17 @@ func writeString(data string) []byte { var output []byte length := uint32(len(data)) - output = []byte{writeBool(length == 0)} + // True if the string is empty ... not used by factorio, so set to false + //output = []byte{writeBool(length == 0)} + output = []byte{writeBool(false)} output = append(output, writeOptimUint(length)...) - stringBytes := []byte(data) - return append(output, stringBytes...) + + if length != 0 { + stringBytes := []byte(data) + output = append(output, stringBytes...) + } + return output } func writeList(data []interface{}) ([]byte, error) { @@ -263,8 +269,9 @@ func writeTree(data interface{}) (output []byte , err error) { // get type _type := reflect.TypeOf(data).Kind() - // write any-type flag - anyTypeFlag := writeBool(_type == reflect.String) + // write any-type flag -- Not used by factorio ... so set to false + //anyTypeFlag := writeBool(_type == reflect.String) + anyTypeFlag := writeBool(false) var typeByte byte var marshalledBytes []byte @@ -372,8 +379,6 @@ func writeTree(data interface{}) (output []byte , err error) { case reflect.String: typeByte = STRING marshalledBytes = writeString(data.(string)) - log.Println(data) - log.Println(marshalledBytes) case reflect.Array: // List list, err := writeList(data.([]interface{})) From 08171bb1d60c3ec375324780d6e66f1189c6032b Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Thu, 7 Mar 2019 03:28:12 +0100 Subject: [PATCH 11/25] removed test output --- src/mod_settings_dat_test.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/mod_settings_dat_test.go b/src/mod_settings_dat_test.go index 13043da8..df36680e 100644 --- a/src/mod_settings_dat_test.go +++ b/src/mod_settings_dat_test.go @@ -3,7 +3,6 @@ package main import ( "bytes" "encoding/json" - "fmt" "github.com/go-test/deep" "io/ioutil" "os" @@ -44,7 +43,6 @@ func TestModSettings0_16(t *testing.T) { t.Fatalf("Data has %d differences: %s", len(diff), diff) } - // Change some value modData.Data.(map[string]interface{})["runtime-per-user"].(map[string]interface{})["folk-fill-fuel-stack-size"].(map[string]interface{})["value"] = 150 test.(map[string]interface{})["runtime-per-user"].(map[string]interface{})["folk-fill-fuel-stack-size"].(map[string]interface{})["value"] = float64(150) @@ -56,10 +54,6 @@ func TestModSettings0_16(t *testing.T) { t.Fatalf("couldn't Encode modData: %s", err) } - fmt.Println(newBytes) - data, _ := ioutil.ReadFile(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.16.dat")) - fmt.Println(data) - var newData FModData err = newData.Decode(newBytesReader) if err != nil { @@ -89,13 +83,6 @@ func TestModSettings0_17(t *testing.T) { t.Fatalf("could not decode FModData: %s", err) } - //fmt.Println(modData) - //ttt, err := json.MarshalIndent(modData.Data, "", " ") - //if err != nil { - // t.Fatalf("could not create json data: %s", err) - //} - //ioutil.WriteFile(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.17.json"), ttt, 0666) - modDataJson, err := ioutil.ReadFile(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.17.json")) if err != nil { t.Fatalf("could not read json-file: %s", err) @@ -112,7 +99,6 @@ func TestModSettings0_17(t *testing.T) { t.Fatalf("Data has %d differences: %s", len(diff), diff) } - // Change some value modData.Data.(map[string]interface{})["runtime-per-user"].(map[string]interface{})["max-inventory-cleanup-drop-range"].(map[string]interface{})["value"] = 150 test.(map[string]interface{})["runtime-per-user"].(map[string]interface{})["max-inventory-cleanup-drop-range"].(map[string]interface{})["value"] = float64(150) @@ -124,10 +110,6 @@ func TestModSettings0_17(t *testing.T) { t.Fatalf("couldn't Encode modData: %s", err) } - fmt.Println(newBytes) - data, _ := ioutil.ReadFile(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.17.dat")) - fmt.Println(data) - var newData FModData err = newData.Decode(newBytesReader) if err != nil { From c5afe97d721c0c4b672a679a59c2a35a38408cec Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Tue, 12 Mar 2019 02:27:52 +0100 Subject: [PATCH 12/25] added load and show mod config --- src/mods_handler.go | 53 ++++++++--- src/routes.go | 6 +- ui/App/App.jsx | 1 - ui/App/components/ModConfigContent.jsx | 120 ++++++++++++++++++++++--- 4 files changed, 151 insertions(+), 29 deletions(-) diff --git a/src/mods_handler.go b/src/mods_handler.go index cddafccc..d75b4cda 100644 --- a/src/mods_handler.go +++ b/src/mods_handler.go @@ -909,14 +909,45 @@ func ModPackUpdateModHandler(w http.ResponseWriter, r *http.Request) { } } -//func GetModConfig(w http.ResponseWriter, r *http.Request) { -// var err error -// resp := JSONResponse{ -// Success: false, -// } -// -// w.Header().Set("Content-Type", "application/json;charset=UTF-8") -// -// // load correct -// file, err := os.Open(filepath.Join(config.FactorioModsDir, "mod-settings.dat")) -//} +func GetModConfigHandler(w http.ResponseWriter, r *http.Request) { + var err error + resp := JSONResponse{ + Success: false, + } + + w.Header().Set("Content-Type", "application/json;charset=UTF-8") + + // load correct + file, err := os.Open(filepath.Join(config.FactorioModsDir, "mod-settings.dat")) + if err != nil { + log.Printf("Error opening mod-settings.dat") + sendErrorResponse(err, resp, w) + return + } + + var modSetttings FModData + err = modSetttings.Decode(file) + if err != nil { + log.Printf("Error decoding modSettings: %s", err) + sendErrorResponse(err, resp, w) + return + } + + resp.Data = modSetttings.Data + resp.Success = true + + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in GetModConfigHandler: %s", err) + } +} + +func sendErrorResponse(err error, resp JSONResponse, w http.ResponseWriter) { + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + resp.Data = fmt.Sprintf("Error in GetModConfigHandler: %s", err) + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in GetModConfigHandler: %s", err) + } + return + } +} diff --git a/src/routes.go b/src/routes.go index 48c55999..4622f59f 100644 --- a/src/routes.go +++ b/src/routes.go @@ -367,12 +367,12 @@ var apiRoutes = Routes{ "POST", "/settings/update", UpdateServerSettings, - }, /*{ + }, { "GetModConfigs", "GET", "/mods/settings", - GetModConfig, - },*/ /*{ + GetModConfigHandler, + }, /*{ "UpdateModsConfigs", "POST", "/mods/settings", diff --git a/ui/App/App.jsx b/ui/App/App.jsx index 000648a2..27f252bd 100644 --- a/ui/App/App.jsx +++ b/ui/App/App.jsx @@ -129,7 +129,6 @@ class App extends React.Component { url: "/api/server/facVersion", // dataType: "json", success: (data) => { - console.log(data); this.setState({ factorioVersion: data.data.base_mod_version }); diff --git a/ui/App/components/ModConfigContent.jsx b/ui/App/components/ModConfigContent.jsx index a4908fc7..f950df74 100644 --- a/ui/App/components/ModConfigContent.jsx +++ b/ui/App/components/ModConfigContent.jsx @@ -1,13 +1,112 @@ import React from "react"; import {Link} from "react-router-dom"; import FontAwesomeIcon from "./FontAwesomeIcon"; +import {ReactSwalDanger} from "../../js/customSwal"; export default class ModConfigContent extends React.Component { + constructor(props) { + super(props); + + this.state = { + config: null + }; + } + componentDidMount() { + this.loadConfig(); + } + + loadConfig() { + $.ajax({ + url: "/api/mods/settings", + type: "GET", + dataType: "json", + success: (data) => { + if(data.success) { + this.setState({ + config: data.data + }); + } else { + ReactSwalDanger.fire({ + title: "Loading mod-settings failed", + text: data.data, + type: "error" + }); + } + }, + error: (xhr, status, err) => { + console.log('api/server/status', status, err.toString()); + let json_data = JSON.parse(jqXHR.responseJSON.data); + ReactSwalNormal.fire({ + title: json_data.detail, + type: "error" + }); + } + }); } render() { + let categories = []; + if(this.state.config) { + for(let confCat in this.state.config) { + let singles = []; + + for(let confSingle in this.state.config[confCat]) { + let ttt = typeof this.state.config[confCat][confSingle].value; + console.log(ttt); + + let input; + switch (ttt) { + case "boolean": + input = + break; + case "number": + input = + break; + case "string": + input = + break; + default: + input = + break; + } + + singles.push(
    + +
    + {input} +
    +
    ); + } + + categories.push(
    +
    +

    {confCat}

    +
    + +
    + {singles} +
    +
    ); + } + } + return (
    @@ -28,21 +127,14 @@ export default class ModConfigContent extends React.Component {
    -
    -
    -

    Configure Mods

    -
    - -
    -
    - -
    - -

    Help text for Tests

    -
    -
    -
    +
    + Mod settings only can have specific values (like enums). If invalid values are set, they will get reset, + when the factorio-server will load those. Currently it's not implemented, to read the possible values!
    + + {categories} + +
    ); From dd1f47a02a53ec47bef042053668190a682069a4 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Tue, 12 Mar 2019 19:02:49 +0100 Subject: [PATCH 13/25] added save of mod config --- src/mods_handler.go | 66 ++++++++++++++++-- src/routes.go | 6 +- ui/App/components/ModConfigContent.jsx | 94 +++++++++++++++++++++++--- ui/index.scss | 3 +- ui/scss/pages/mod-config.scss | 5 ++ 5 files changed, 155 insertions(+), 19 deletions(-) create mode 100644 ui/scss/pages/mod-config.scss diff --git a/src/mods_handler.go b/src/mods_handler.go index d75b4cda..0d431d5d 100644 --- a/src/mods_handler.go +++ b/src/mods_handler.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "io/ioutil" "lockfile" "log" "net/http" @@ -917,7 +918,6 @@ func GetModConfigHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json;charset=UTF-8") - // load correct file, err := os.Open(filepath.Join(config.FactorioModsDir, "mod-settings.dat")) if err != nil { log.Printf("Error opening mod-settings.dat") @@ -925,15 +925,17 @@ func GetModConfigHandler(w http.ResponseWriter, r *http.Request) { return } - var modSetttings FModData - err = modSetttings.Decode(file) + var modSettings FModData + err = modSettings.Decode(file) if err != nil { log.Printf("Error decoding modSettings: %s", err) sendErrorResponse(err, resp, w) return } - resp.Data = modSetttings.Data + log.Println(modSettings ) + + resp.Data = modSettings.Data resp.Success = true if err := json.NewEncoder(w).Encode(resp); err != nil { @@ -941,6 +943,62 @@ func GetModConfigHandler(w http.ResponseWriter, r *http.Request) { } } +func UpdateModConfigHandler(w http.ResponseWriter, r *http.Request) { + var err error + resp := JSONResponse{ + Success: false, + } + + w.Header().Set("Content-Type", "application/json;charset=UTF-8") + + data := r.FormValue("data") + + var dataObj interface{} + err = json.Unmarshal([]byte(data), &dataObj) + + file, err := os.Open(filepath.Join(config.FactorioModsDir, "mod-settings.dat")) + if err != nil { + log.Printf("Error opening mod-settings.dat") + sendErrorResponse(err, resp, w) + return + } + + // save new data + var modSettings FModData + err = modSettings.Decode(file) + if err != nil { + log.Printf("Error decoding modSettings: %s", err) + sendErrorResponse(err, resp, w) + return + } + + log.Println(modSettings) + + modSettings.Data = dataObj + + log.Println(modSettings) + + encodedSettings, err := modSettings.Encode() + if err != nil { + log.Printf("Error encoding modSettings: %s", err) + sendErrorResponse(err, resp, w) + return + } + + err = ioutil.WriteFile(filepath.Join(config.FactorioModsDir, "mod-settings.dat"), encodedSettings, 0644) + if err != nil { + log.Printf("Error writing new settings to file: %s", err) + sendErrorResponse(err, resp, w) + return + } + + resp.Success = true + + if err := json.NewEncoder(w).Encode(resp); err != nil { + log.Printf("Error in UpdateModConfigHandler: %s", err) + } +} + func sendErrorResponse(err error, resp JSONResponse, w http.ResponseWriter) { if err != nil { w.WriteHeader(http.StatusInternalServerError) diff --git a/src/routes.go b/src/routes.go index 4622f59f..fce8bd8e 100644 --- a/src/routes.go +++ b/src/routes.go @@ -372,10 +372,10 @@ var apiRoutes = Routes{ "GET", "/mods/settings", GetModConfigHandler, - }, /*{ + }, { "UpdateModsConfigs", "POST", "/mods/settings", - UpdateModConfig, - },*/ + UpdateModConfigHandler, + }, } diff --git a/ui/App/components/ModConfigContent.jsx b/ui/App/components/ModConfigContent.jsx index f950df74..2bf8132d 100644 --- a/ui/App/components/ModConfigContent.jsx +++ b/ui/App/components/ModConfigContent.jsx @@ -7,6 +7,8 @@ export default class ModConfigContent extends React.Component { constructor(props) { super(props); + this.updateConfig = this.updateConfig.bind(this); + this.state = { config: null }; @@ -46,6 +48,67 @@ export default class ModConfigContent extends React.Component { }); } + updateConfig(e) { + let config = this.state.config; + let configElem = $('.mod-config'); + + $.each(configElem, (_, v) => { + let configName = v.id; + let configValue = v.value; + let category = v.getAttribute("data-cat"); + let type = v.getAttribute("data-type"); + + switch (type) { + case "boolean": + configValue = configValue == "true" ? true : false; + break; + case "number": + configValue = parseFloat(configValue); + break; + } + + if (!config[category]) { + config[category] = []; + } + if (!config[category][configName]) { + config[category][configName] = {}; + } + config[category][configName].value = configValue; + }); + + let configString = JSON.stringify(config); + $.ajax({ + url: "/api/mods/settings", + type: "POST", + data: { + data: configString + }, + dataType: "json", + success: (data) => { + if(data.success) { + this.setState({ + config: config + }); + } else { + ReactSwalDanger.fire({ + title: "Loading mod-settings failed", + text: data.data, + type: "error" + }); + } + }, + error: (xhr, status, err) => { + console.log('api/server/status', status, err.toString()); + let json_data = JSON.parse(jqXHR.responseJSON.data); + + ReactSwalNormal.fire({ + title: json_data.detail, + type: "error" + }); + } + }); + } + render() { let categories = []; if(this.state.config) { @@ -53,36 +116,45 @@ export default class ModConfigContent extends React.Component { let singles = []; for(let confSingle in this.state.config[confCat]) { - let ttt = typeof this.state.config[confCat][confSingle].value; - console.log(ttt); - + let singleType = typeof this.state.config[confCat][confSingle].value; let input; - switch (ttt) { + switch (singleType) { case "boolean": - input = break; case "number": input = break; case "string": input = break; default: input = break; } @@ -134,7 +206,7 @@ export default class ModConfigContent extends React.Component { {categories} - + ); diff --git a/ui/index.scss b/ui/index.scss index 167b6761..6b960083 100644 --- a/ui/index.scss +++ b/ui/index.scss @@ -32,4 +32,5 @@ */ @import "scss/pages/serverCtl"; @import "scss/pages/logs"; -@import "scss/pages/saves"; \ No newline at end of file +@import "scss/pages/saves"; +@import "scss/pages/mod-config"; diff --git a/ui/scss/pages/mod-config.scss b/ui/scss/pages/mod-config.scss new file mode 100644 index 00000000..851681b1 --- /dev/null +++ b/ui/scss/pages/mod-config.scss @@ -0,0 +1,5 @@ +#mod-config { + .content { + margin-bottom: 10px; + } +} \ No newline at end of file From c05aedc03ccbfeac3a3483dda94555ce62a06640 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Tue, 12 Mar 2019 19:12:51 +0100 Subject: [PATCH 14/25] updated info --- ui/App/components/ModConfigContent.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/App/components/ModConfigContent.jsx b/ui/App/components/ModConfigContent.jsx index 2bf8132d..9f53816f 100644 --- a/ui/App/components/ModConfigContent.jsx +++ b/ui/App/components/ModConfigContent.jsx @@ -201,7 +201,9 @@ export default class ModConfigContent extends React.Component {
    Mod settings only can have specific values (like enums). If invalid values are set, they will get reset, - when the factorio-server will load those. Currently it's not implemented, to read the possible values! + when the factorio-server is started.
    + If no configs are shown, or configs are missing, start the factorio-server, + so the mod-settings.dat file is updated.
    {categories} From d4de8e471bda53e95c0eac88627252c5bca1928d Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Mon, 29 Jul 2019 16:09:12 +0200 Subject: [PATCH 15/25] added warning --- ui/App/components/ModConfigContent.jsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ui/App/components/ModConfigContent.jsx b/ui/App/components/ModConfigContent.jsx index 9f53816f..b5e1458b 100644 --- a/ui/App/components/ModConfigContent.jsx +++ b/ui/App/components/ModConfigContent.jsx @@ -205,6 +205,11 @@ export default class ModConfigContent extends React.Component { If no configs are shown, or configs are missing, start the factorio-server, so the mod-settings.dat file is updated. +
    + Changing startup while server is running, has no effects. + Also when changing startup, please backup the save, cause it could be corrupted after the changes!
    + Except startup-settings, all settings can be changed ingame. Use of "/admin" command should be priorized. +
    {categories} From bf061a34c678b2d0c332e66ea55a28e51e197ed3 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Wed, 29 Jan 2020 15:27:39 +0100 Subject: [PATCH 16/25] added go-test/deep as go dependency --- src/go.mod | 1 + src/go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/go.mod b/src/go.mod index 942c3121..5f071350 100644 --- a/src/go.mod +++ b/src/go.mod @@ -6,6 +6,7 @@ require ( github.com/apexskier/httpauth v1.3.2 github.com/go-ini/ini v1.49.0 github.com/go-sql-driver/mysql v1.4.1 // indirect + github.com/go-test/deep v1.0.5 github.com/gorilla/mux v1.7.3 github.com/gorilla/sessions v1.2.0 // indirect github.com/gorilla/websocket v1.4.1 diff --git a/src/go.sum b/src/go.sum index 9f7d8481..776a43b7 100644 --- a/src/go.sum +++ b/src/go.sum @@ -6,6 +6,8 @@ github.com/go-ini/ini v1.49.0 h1:ymWFBUkwN3JFPjvjcJJ5TSTwh84M66QrH+8vOytLgRY= github.com/go-ini/ini v1.49.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-test/deep v1.0.5 h1:AKODKU3pDH1RzZzm6YZu77YWtEAq6uh1rLIAQlay2qc= +github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= From b2274c53826cb07190cf9619ae6f260367eb0c20 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Thu, 5 Aug 2021 03:30:49 +0200 Subject: [PATCH 17/25] mod_settings backend adjusted to new layout --- src/{ => factorio}/factorio_data_types.go | 33 ++++++------ src/{ => factorio}/mod_settings_dat.go | 23 ++++---- src/{ => factorio}/mod_settings_dat_test.go | 19 ++----- src/factorio/save.go | 58 --------------------- src/go.mod | 1 + src/go.sum | 6 +-- 6 files changed, 35 insertions(+), 105 deletions(-) rename src/{ => factorio}/factorio_data_types.go (91%) rename src/{ => factorio}/mod_settings_dat.go (86%) rename src/{ => factorio}/mod_settings_dat_test.go (82%) diff --git a/src/factorio_data_types.go b/src/factorio/factorio_data_types.go similarity index 91% rename from src/factorio_data_types.go rename to src/factorio/factorio_data_types.go index 41d5c645..36cd146f 100644 --- a/src/factorio_data_types.go +++ b/src/factorio/factorio_data_types.go @@ -1,4 +1,4 @@ -package main +package factorio import ( "bytes" @@ -9,7 +9,6 @@ import ( "reflect" ) - /////////////////// // Reading //////// /////////////////// @@ -44,11 +43,11 @@ func readOptimUint(r io.Reader, v Version, bitSize int) (uint32, error) { } } -func readString(r io.Reader, game Version, forceOptimized bool) (s string, err error) { +func readString(r io.Reader, version Version, forceOptimized bool) (s string, err error) { var n uint32 - if !game.Less(Version{0, 16, 0, 0}) || forceOptimized { - n, err = readOptimUint(r, game, 32) + if !version.Less(Version{0, 16, 0, 0}) || forceOptimized { + n, err = readOptimUint(r, version, 32) if err != nil { return "", err } @@ -92,9 +91,9 @@ func readDouble(file io.Reader) (float64, error) { return _data, nil } -func readList(file io.Reader) ([]interface{}, error) { +func readList(file io.Reader, version Version) ([]interface{}, error) { var length uint32 - length, err := readOptimUint(file, FactorioServ.Version, 32) + length, err := readOptimUint(file, version, 32) if err != nil { log.Printf("could not read list length") return nil, err @@ -102,7 +101,7 @@ func readList(file io.Reader) ([]interface{}, error) { list := make([]interface{}, length) for i := uint32(0); i < length; i++ { - list[i], err = readTree(file) + list[i], err = readTree(file, version) if err != nil { log.Printf("could not read tree of list: %s", err) return nil, err @@ -112,7 +111,7 @@ func readList(file io.Reader) ([]interface{}, error) { return list, nil } -func readDict(file io.Reader) (map[string]interface{}, error) { +func readDict(file io.Reader, version Version) (map[string]interface{}, error) { var length uint32 err := binary.Read(file, binary.LittleEndian, &length) if err != nil { @@ -123,14 +122,14 @@ func readDict(file io.Reader) (map[string]interface{}, error) { dict := make(map[string]interface{}) for i := uint32(0); i < length; i++ { - key, err := readStringSettings(file) + key, err := readStringSettings(file, version) if err != nil { log.Printf("error loading key: %s", err) return dict, err } - dict[key], err = readTree(file) + dict[key], err = readTree(file, version) if err != nil { log.Printf("error loading readTree: %s", err) return dict, err @@ -140,7 +139,7 @@ func readDict(file io.Reader) (map[string]interface{}, error) { return dict, nil } -func readTree(file io.Reader) (interface{}, error) { +func readTree(file io.Reader, version Version) (interface{}, error) { //type of embedded data var _type byte err := binary.Read(file, binary.LittleEndian, &_type) @@ -162,18 +161,16 @@ func readTree(file io.Reader) (interface{}, error) { case DOUBLE: return readDouble(file) case STRING: - return readStringSettings(file) + return readStringSettings(file, version) case LIST: - return readList(file) + return readList(file, version) case DICT: - return readDict(file) + return readDict(file, version) default: return nil, fmt.Errorf("Unknown type: %s ", err) } } - - /////////////////// // Writing //////// /////////////////// @@ -265,7 +262,7 @@ func writeDict(data map[string]interface{}) ([]byte, error) { return output, nil } -func writeTree(data interface{}) (output []byte , err error) { +func writeTree(data interface{}) (output []byte, err error) { // get type _type := reflect.TypeOf(data).Kind() diff --git a/src/mod_settings_dat.go b/src/factorio/mod_settings_dat.go similarity index 86% rename from src/mod_settings_dat.go rename to src/factorio/mod_settings_dat.go index 68e4195a..80ecf3ca 100644 --- a/src/mod_settings_dat.go +++ b/src/factorio/mod_settings_dat.go @@ -1,4 +1,4 @@ -package main +package factorio import ( "encoding/binary" @@ -8,12 +8,12 @@ import ( ) const ( - NONE = 0 - BOOL = 1 - DOUBLE = 2 - STRING = 3 - LIST = 4 - DICT = 5 + NONE = 0 + BOOL = 1 + DOUBLE = 2 + STRING = 3 + LIST = 4 + DICT = 5 ) type FModData struct { @@ -29,13 +29,14 @@ func (d *FModData) Decode(file io.Reader) error { if err != nil { log.Printf("could not read version: %s", err) } + err = version.UnmarshalBinary(versionB[:]) if err != nil { log.Printf("Error loading Version: %s", err) return err } - d.Version = version + d.Version = version if Version(version).Greater(Version{0, 17, 0, 0}) { //FIXME correct naming @@ -46,7 +47,7 @@ func (d *FModData) Decode(file io.Reader) error { } } - d.Data, err = readTree(file) + d.Data, err = readTree(file, Version(d.Version)) if err != nil { log.Printf("error loading Data: %s", err) return err @@ -55,7 +56,7 @@ func (d *FModData) Decode(file io.Reader) error { return nil } -func readStringSettings(file io.Reader) (string, error) { +func readStringSettings(file io.Reader, version Version) (string, error) { // read "empty" flag empty, err := readBool(file) if err != nil { @@ -67,7 +68,7 @@ func readStringSettings(file io.Reader) (string, error) { return "", nil } - key, err := readString(file, FactorioServ.Version, false) + key, err := readString(file, version, false) if err != nil { log.Printf("could not read key-string: %s", err) return "", err diff --git a/src/mod_settings_dat_test.go b/src/factorio/mod_settings_dat_test.go similarity index 82% rename from src/mod_settings_dat_test.go rename to src/factorio/mod_settings_dat_test.go index df36680e..328851f3 100644 --- a/src/mod_settings_dat_test.go +++ b/src/factorio/mod_settings_dat_test.go @@ -1,4 +1,4 @@ -package main +package factorio import ( "bytes" @@ -6,17 +6,12 @@ import ( "github.com/go-test/deep" "io/ioutil" "os" - "path/filepath" "testing" ) func TestModSettings0_16(t *testing.T) { - FactorioServ = &FactorioServer { - Version: Version{0, 16, 0, 0}, - } - // Read dat and compare to JSON - file, err := os.Open(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.16.dat")) + file, err := os.Open("../factorio_mod_settings_testfiles/mod_settings_0.16.dat") if err != nil { t.Fatalf("could not open mod-settings.dat: %s", err) } @@ -27,7 +22,7 @@ func TestModSettings0_16(t *testing.T) { t.Fatalf("could not decode FModData: %s", err) } - modDataJson, err := ioutil.ReadFile(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.16.json")) + modDataJson, err := ioutil.ReadFile("../factorio_mod_settings_testfiles/mod_settings_0.16.json") if err != nil { t.Fatalf("could not read json-file: %s", err) } @@ -67,12 +62,8 @@ func TestModSettings0_16(t *testing.T) { } func TestModSettings0_17(t *testing.T) { - FactorioServ = &FactorioServer { - Version: Version{0, 17, 0, 0}, - } - // Read data and compare to JSON - file, err := os.Open(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.17.dat")) + file, err := os.Open("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") if err != nil { t.Fatalf("could not open mod-settings.dat: %s", err) } @@ -83,7 +74,7 @@ func TestModSettings0_17(t *testing.T) { t.Fatalf("could not decode FModData: %s", err) } - modDataJson, err := ioutil.ReadFile(filepath.Join("factorio_mod_settings_testfiles", "mod_settings_0.17.json")) + modDataJson, err := ioutil.ReadFile("../factorio_mod_settings_testfiles/mod_settings_0.17.json") if err != nil { t.Fatalf("could not read json-file: %s", err) } diff --git a/src/factorio/save.go b/src/factorio/save.go index a97cd6e3..16a4331b 100644 --- a/src/factorio/save.go +++ b/src/factorio/save.go @@ -235,64 +235,6 @@ func (h *SaveHeader) ReadFrom(r io.Reader) (err error) { return nil } -func readOptimUint(r io.Reader, v Version, bitSize int) (uint32, error) { - var b [4]byte - if !v.Less(Version{0, 14, 14, 0}) { - _, err := r.Read(b[:1]) - if err != nil { - return 0, err - } - if b[0] != 0xFF { - return uint32(b[0]), nil - } - } - - if bitSize < 0 || bitSize > 64 || (bitSize%8 != 0) { - panic("invalid bit size") - } - - _, err := r.Read(b[:bitSize/8]) - if err != nil { - return 0, err - } - - switch bitSize { - case 16: - return uint32(binary.LittleEndian.Uint16(b[:2])), nil - case 32: - return binary.LittleEndian.Uint32(b[:4]), nil - default: - panic("invalid bit size") - } -} - -func readString(r io.Reader, game Version, forceOptimized bool) (s string, err error) { - var n uint32 - - // since 0.16 read optimized uint - if !game.Less(Version{0, 16, 0, 0}) || forceOptimized { - n, err = readOptimUint(r, game, 32) - if err != nil { - return "", err - } - } else { - var b [4]byte - _, err := r.Read(b[:]) - if err != nil { - return "", fmt.Errorf("failed to read string length: %v", err) - } - n = uint32(binary.LittleEndian.Uint32(b[:])) - } - - d := make([]byte, n) - _, err = r.Read(d) - if err != nil { - return "", fmt.Errorf("failed to read string: %v", err) - } - - return string(d), nil -} - func (h SaveHeader) readStats(r io.Reader) (stats map[byte][]map[uint16]uint32, err error) { var scratch [4]byte stats = make(map[byte][]map[uint16]uint32) diff --git a/src/go.mod b/src/go.mod index 6cefaf56..523c9ea7 100644 --- a/src/go.mod +++ b/src/go.mod @@ -5,6 +5,7 @@ go 1.13 require ( github.com/OpenFactorioServerManager/rcon v0.0.0-20120923215419-8fbb8268b60a github.com/go-ini/ini v1.49.0 + github.com/go-test/deep v1.0.7 github.com/golang/protobuf v1.3.1 // indirect github.com/gorilla/mux v1.7.3 github.com/gorilla/securecookie v1.1.1 diff --git a/src/go.sum b/src/go.sum index 75460a0e..d85a6364 100644 --- a/src/go.sum +++ b/src/go.sum @@ -6,7 +6,8 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-ini/ini v1.49.0 h1:ymWFBUkwN3JFPjvjcJJ5TSTwh84M66QrH+8vOytLgRY= github.com/go-ini/ini v1.49.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= +github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -57,17 +58,14 @@ golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf h1:fnPsqIDRbCSgumaMCRpoIo golang.org/x/crypto v0.0.0-20191029031824-8986dd9e96cf/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= From 362fc57fbe949d80221df8f026cd81a846b81b94 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Fri, 6 Aug 2021 02:32:55 +0200 Subject: [PATCH 18/25] trackingoutput for EOF bug --- src/factorio/factorio_data_types.go | 39 +++++++++++++++++++++++++++++ src/factorio/mod_settings_dat.go | 21 ---------------- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/factorio/factorio_data_types.go b/src/factorio/factorio_data_types.go index 36cd146f..1f0afd7a 100644 --- a/src/factorio/factorio_data_types.go +++ b/src/factorio/factorio_data_types.go @@ -13,6 +13,8 @@ import ( // Reading //////// /////////////////// func readOptimUint(r io.Reader, v Version, bitSize int) (uint32, error) { + log.Println("readOptimUint") + var b [4]byte if !v.Less(Version{0, 14, 14, 0}) { _, err := r.Read(b[:1]) @@ -44,6 +46,8 @@ func readOptimUint(r io.Reader, v Version, bitSize int) (uint32, error) { } func readString(r io.Reader, version Version, forceOptimized bool) (s string, err error) { + log.Println("readString") + var n uint32 if !version.Less(Version{0, 16, 0, 0}) || forceOptimized { @@ -60,6 +64,8 @@ func readString(r io.Reader, version Version, forceOptimized bool) (s string, er n = uint32(binary.LittleEndian.Uint32(b[:])) } + log.Printf("string-size: %d", n) + d := make([]byte, n) _, err = r.Read(d) if err != nil { @@ -69,7 +75,32 @@ func readString(r io.Reader, version Version, forceOptimized bool) (s string, er return string(d), nil } +func readStringSettings(file io.Reader, version Version) (string, error) { + log.Println("readStringSettings") + + // read "empty" flag + empty, err := readBool(file) + if err != nil { + log.Printf("error loading empty flag of string: %s", err) + return "", err + } + + if empty { + return "", nil + } + + key, err := readString(file, version, false) + if err != nil { + log.Printf("could not read key-string: %s", err) + return "", err + } + + return key, nil +} + func readBool(file io.Reader) (bool, error) { + log.Println("readBool") + var _data byte err := binary.Read(file, binary.LittleEndian, &_data) if err != nil { @@ -81,6 +112,8 @@ func readBool(file io.Reader) (bool, error) { } func readDouble(file io.Reader) (float64, error) { + log.Println("readDouble") + var _data float64 err := binary.Read(file, binary.LittleEndian, &_data) if err != nil { @@ -92,6 +125,8 @@ func readDouble(file io.Reader) (float64, error) { } func readList(file io.Reader, version Version) ([]interface{}, error) { + log.Println("readList") + var length uint32 length, err := readOptimUint(file, version, 32) if err != nil { @@ -112,6 +147,8 @@ func readList(file io.Reader, version Version) ([]interface{}, error) { } func readDict(file io.Reader, version Version) (map[string]interface{}, error) { + log.Println("readDict") + var length uint32 err := binary.Read(file, binary.LittleEndian, &length) if err != nil { @@ -140,6 +177,8 @@ func readDict(file io.Reader, version Version) (map[string]interface{}, error) { } func readTree(file io.Reader, version Version) (interface{}, error) { + log.Println("readTree") + //type of embedded data var _type byte err := binary.Read(file, binary.LittleEndian, &_type) diff --git a/src/factorio/mod_settings_dat.go b/src/factorio/mod_settings_dat.go index 80ecf3ca..22da2ba6 100644 --- a/src/factorio/mod_settings_dat.go +++ b/src/factorio/mod_settings_dat.go @@ -56,27 +56,6 @@ func (d *FModData) Decode(file io.Reader) error { return nil } -func readStringSettings(file io.Reader, version Version) (string, error) { - // read "empty" flag - empty, err := readBool(file) - if err != nil { - log.Printf("error loading empty flag of string: %s", err) - return "", err - } - - if empty { - return "", nil - } - - key, err := readString(file, version, false) - if err != nil { - log.Printf("could not read key-string: %s", err) - return "", err - } - - return key, nil -} - func (d *FModData) Encode() ([]byte, error) { var output []byte From 4ba48d4febde2b5dbd8d3d72e8f85442b7ed73d1 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Fri, 6 Aug 2021 02:37:23 +0200 Subject: [PATCH 19/25] trackingoutput for EOF bug --- src/factorio/factorio_data_types.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/factorio/factorio_data_types.go b/src/factorio/factorio_data_types.go index 1f0afd7a..e59c0272 100644 --- a/src/factorio/factorio_data_types.go +++ b/src/factorio/factorio_data_types.go @@ -72,6 +72,8 @@ func readString(r io.Reader, version Version, forceOptimized bool) (s string, er return "", fmt.Errorf("failed to read string: %v", err) } + log.Println(string(d)) + return string(d), nil } From 8bbf131a22764cd6907994ea0937444f2a11a5bd Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Fri, 6 Aug 2021 02:53:17 +0200 Subject: [PATCH 20/25] dump file before reading --- src/factorio/mod_settings_dat_test.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/factorio/mod_settings_dat_test.go b/src/factorio/mod_settings_dat_test.go index 328851f3..2907583f 100644 --- a/src/factorio/mod_settings_dat_test.go +++ b/src/factorio/mod_settings_dat_test.go @@ -5,6 +5,7 @@ import ( "encoding/json" "github.com/go-test/deep" "io/ioutil" + "log" "os" "testing" ) @@ -62,11 +63,19 @@ func TestModSettings0_16(t *testing.T) { } func TestModSettings0_17(t *testing.T) { - // Read data and compare to JSON - file, err := os.Open("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") + readFile, err := ioutil.ReadFile("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") if err != nil { - t.Fatalf("could not open mod-settings.dat: %s", err) + t.Fatalf("could not read full testfile: %s", err) } + log.Println(readFile) + + file := bytes.NewReader(readFile) + + // Read data and compare to JSON + //file, err := os.Open("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") + //if err != nil { + // t.Fatalf("could not open mod-settings.dat: %s", err) + //} var modData FModData err = modData.Decode(file) From f2b9242ea3b082181ca66feebbf78ff52cfd1dec Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Fri, 6 Aug 2021 03:02:45 +0200 Subject: [PATCH 21/25] dump file in hex --- src/factorio/mod_settings_dat_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/factorio/mod_settings_dat_test.go b/src/factorio/mod_settings_dat_test.go index 2907583f..012069d8 100644 --- a/src/factorio/mod_settings_dat_test.go +++ b/src/factorio/mod_settings_dat_test.go @@ -67,7 +67,7 @@ func TestModSettings0_17(t *testing.T) { if err != nil { t.Fatalf("could not read full testfile: %s", err) } - log.Println(readFile) + log.Printf("%x", readFile) file := bytes.NewReader(readFile) From eff22af6db4b263ec81642533a8f4f0d2a9ee4f6 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Fri, 6 Aug 2021 03:26:38 +0200 Subject: [PATCH 22/25] potential fix of the EOF bug --- src/factorio/factorio_data_types.go | 5 +++++ src/factorio/mod_settings_dat_test.go | 23 +++++++++++------------ 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/factorio/factorio_data_types.go b/src/factorio/factorio_data_types.go index e59c0272..597844f5 100644 --- a/src/factorio/factorio_data_types.go +++ b/src/factorio/factorio_data_types.go @@ -66,6 +66,11 @@ func readString(r io.Reader, version Version, forceOptimized bool) (s string, er log.Printf("string-size: %d", n) + // do not read the string, when it is empty + if n < 1 { + return "", nil + } + d := make([]byte, n) _, err = r.Read(d) if err != nil { diff --git a/src/factorio/mod_settings_dat_test.go b/src/factorio/mod_settings_dat_test.go index 012069d8..8b10df19 100644 --- a/src/factorio/mod_settings_dat_test.go +++ b/src/factorio/mod_settings_dat_test.go @@ -5,7 +5,6 @@ import ( "encoding/json" "github.com/go-test/deep" "io/ioutil" - "log" "os" "testing" ) @@ -63,19 +62,19 @@ func TestModSettings0_16(t *testing.T) { } func TestModSettings0_17(t *testing.T) { - readFile, err := ioutil.ReadFile("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") - if err != nil { - t.Fatalf("could not read full testfile: %s", err) - } - log.Printf("%x", readFile) - - file := bytes.NewReader(readFile) - - // Read data and compare to JSON - //file, err := os.Open("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") + //readFile, err := ioutil.ReadFile("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") //if err != nil { - // t.Fatalf("could not open mod-settings.dat: %s", err) + // t.Fatalf("could not read full testfile: %s", err) //} + //log.Printf("%x", readFile) + // + //file := bytes.NewReader(readFile) + + // Read data and compare to JSON + file, err := os.Open("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") + if err != nil { + t.Fatalf("could not open mod-settings.dat: %s", err) + } var modData FModData err = modData.Decode(file) From 634513f7e406db9c99ebbec8db608b33ce3a3c47 Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Sat, 7 Aug 2021 02:33:17 +0200 Subject: [PATCH 23/25] 1.0 and 1.1 mod_settings.dat tests --- src/factorio/mod_settings_dat_test.go | 112 +++- .../mod_settings_1.0.dat | Bin 0 -> 8974 bytes .../mod_settings_1.0.json | 554 +++++++++++++++++ .../mod_settings_1.1.dat | Bin 0 -> 9117 bytes .../mod_settings_1.1.json | 557 ++++++++++++++++++ 5 files changed, 1215 insertions(+), 8 deletions(-) create mode 100644 src/factorio_mod_settings_testfiles/mod_settings_1.0.dat create mode 100644 src/factorio_mod_settings_testfiles/mod_settings_1.0.json create mode 100644 src/factorio_mod_settings_testfiles/mod_settings_1.1.dat create mode 100644 src/factorio_mod_settings_testfiles/mod_settings_1.1.json diff --git a/src/factorio/mod_settings_dat_test.go b/src/factorio/mod_settings_dat_test.go index 8b10df19..b7d85d48 100644 --- a/src/factorio/mod_settings_dat_test.go +++ b/src/factorio/mod_settings_dat_test.go @@ -62,14 +62,6 @@ func TestModSettings0_16(t *testing.T) { } func TestModSettings0_17(t *testing.T) { - //readFile, err := ioutil.ReadFile("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") - //if err != nil { - // t.Fatalf("could not read full testfile: %s", err) - //} - //log.Printf("%x", readFile) - // - //file := bytes.NewReader(readFile) - // Read data and compare to JSON file, err := os.Open("../factorio_mod_settings_testfiles/mod_settings_0.17.dat") if err != nil { @@ -120,3 +112,107 @@ func TestModSettings0_17(t *testing.T) { t.Fatalf("Data has %d differences: %s", len(diff2), diff2) } } + +func TestModSettings1_0(t *testing.T) { + // Read data and compare to JSON + file, err := os.Open("../factorio_mod_settings_testfiles/mod_settings_1.0.dat") + if err != nil { + t.Fatalf("could not open mod-settings.dat: %s", err) + } + + var modData FModData + err = modData.Decode(file) + if err != nil { + t.Fatalf("could not decode FModData: %s", err) + } + + modDataJson, err := ioutil.ReadFile("../factorio_mod_settings_testfiles/mod_settings_1.0.json") + if err != nil { + t.Fatalf("could not read json-file: %s", err) + } + + var test interface{} + err = json.Unmarshal(modDataJson, &test) + if err != nil { + t.Fatalf("could not Unmarshal JSON: %s", err) + } + + diff := deep.Equal(modData.Data, test) + if len(diff) > 0 { + t.Fatalf("Data has %d differences: %s", len(diff), diff) + } + + // Change some value + modData.Data.(map[string]interface{})["startup"].(map[string]interface{})["angels-pavement-stack-size"].(map[string]interface{})["value"] = 200 + test.(map[string]interface{})["startup"].(map[string]interface{})["angels-pavement-stack-size"].(map[string]interface{})["value"] = float64(200) + + // write new data + newBytes, err := modData.Encode() + newBytesReader := bytes.NewReader(newBytes) + if err != nil { + t.Fatalf("couldn't Encode modData: %s", err) + } + + var newData FModData + err = newData.Decode(newBytesReader) + if err != nil { + t.Fatalf("couldn't Decode newBytes: %s", err) + } + + diff2 := deep.Equal(newData.Data, test) + if len(diff2) > 0 { + t.Fatalf("Data has %d differences: %s", len(diff2), diff2) + } +} + +func TestModSettings1_1(t *testing.T) { + // Read data and compare to JSON + file, err := os.Open("../factorio_mod_settings_testfiles/mod_settings_1.1.dat") + if err != nil { + t.Fatalf("could not open mod-settings.dat: %s", err) + } + + var modData FModData + err = modData.Decode(file) + if err != nil { + t.Fatalf("could not decode FModData: %s", err) + } + + modDataJson, err := ioutil.ReadFile("../factorio_mod_settings_testfiles/mod_settings_1.1.json") + if err != nil { + t.Fatalf("could not read json-file: %s", err) + } + + var test interface{} + err = json.Unmarshal(modDataJson, &test) + if err != nil { + t.Fatalf("could not Unmarshal JSON: %s", err) + } + + diff := deep.Equal(modData.Data, test) + if len(diff) > 0 { + t.Fatalf("Data has %d differences: %s", len(diff), diff) + } + + // Change some value + modData.Data.(map[string]interface{})["startup"].(map[string]interface{})["angels-pavement-stack-size"].(map[string]interface{})["value"] = 200 + test.(map[string]interface{})["startup"].(map[string]interface{})["angels-pavement-stack-size"].(map[string]interface{})["value"] = float64(200) + + // write new data + newBytes, err := modData.Encode() + newBytesReader := bytes.NewReader(newBytes) + if err != nil { + t.Fatalf("couldn't Encode modData: %s", err) + } + + var newData FModData + err = newData.Decode(newBytesReader) + if err != nil { + t.Fatalf("couldn't Decode newBytes: %s", err) + } + + diff2 := deep.Equal(newData.Data, test) + if len(diff2) > 0 { + t.Fatalf("Data has %d differences: %s", len(diff2), diff2) + } +} diff --git a/src/factorio_mod_settings_testfiles/mod_settings_1.0.dat b/src/factorio_mod_settings_testfiles/mod_settings_1.0.dat new file mode 100644 index 0000000000000000000000000000000000000000..a8cc6273f50734305c1e6634dd2b1dbfa677a4ee GIT binary patch literal 8974 zcmb7KyRsxV8P>7ulpSH?E#KC68y0M6S795fh|Um_^8)H_O}98|saNWr@oYpuKt>F2 z;Dnr*h({o!$`Kilz^Cq(rgiC=VUj)P?Dt>v>%VL6$nv=-FWaA9F$2}Z*x!@C*fOdVio|WG~qt$shjs;cv)Cj#ks7U>bB> z76S(*?bIlT3>_h_?#KrVUC#!sZl?Npp)ws41DDOsgijViCTS^HVYpBxQ0)%qdnW`P zsb;Mj4NH;lhDa_2m#i45d`y_W7eaf@j2ZO?_|p(<2Bm4k3SKE$n2JJ56A2)()?C)3 z88pvm9i6XIU9TjQLwr6$-U#&=Sk)$SoeeY_MlB1drdiE1?C!|>3%j$#0v=dB;vQbG zfbr~EWcTMCd2=D+a?d4)7oIp1bq-Cw*%4=Ep^osq8)*Lf;3dpXu@@t+HG3XNux{ae z=aI2~L|o8{hiX{R+o8p9VFyG5(+M|std`fT*oHZwi^E!(@ipC%PZpsyH;u@U`*FYG489>dlF6unRwCZ?f zzgM~&1x;+}(9THXpo)@e&9Z?KUD0#_2bH-?cicgr`a$)rDmg9o&{x*t1kdG2ig3tC zopaQ*&x=OWzU5VFf0y?<3MMVWx*WNv5j;5Hzyp>`ED*Bu0hCY;ybJYM5xH>pL`c!w zQVzJnET=|Yu|jDU)(#si7vWz8MzB@qBK+$Jeueut z5&R1GUqaU!-hgy3Slf0)3pq^~W!rvO2L=#^oc{NGQ=6c?N5)H*XlBSg%IzWD;hiV2(-^6KUw^~}+>c%VdyIjp20mUEq!}3PF7kfr%(qY+ z;R6~!=VqWMNJ9eU-;GM>9a0tEav-#_jOwbLrtlQ^n!}-#5zhz0}n|Qc6Ipg59Fs;SoBJWF~i{N>GO{V^5v}zY!4A- z6<10A{Xl+pjm_#B0^_^0pr`O*?W`D?BQ4U7_@58y^?TwT?k0xQE!Nz=5Xa=IJ$>Fx z4&hjAA0umnmEl@UHrYnyC$aUX8gkW(P?zUV;=gP9ts^_)^zO6N7yJjD5<#lf4p$B6o721oIqm009Dbh!4Qi$|nAp~N zD=?aE$9%D9Scf60V?%qw&eZ0{0PDnhyQaj{y!0QACxm$HGqg@~*I`~D*N?j}*H6QIrnZR=@feEoOlB)i}-c#pE4+&59gU+IG7cmtBiey6QxF7mt8-gY6vVl1zD z%w3KZd~D0$K8zN&xH&r-YP>o{dgI;G-Qa@75)<1wSUW-bS!O{l4?**rOZL&_tjF{) zN2_YYqLjiasjYp=>L={Hzi#Y{w8baNoDDL;r-jNk+9$Y~IecW8pD0p2-t_jE7%zrS z+O6I=-Lr>av8a$!iPNNHlj?+5||O&3p({P#a%VD5if4Gd-e2 zXhQsukV9LAV$WP1*pc8d5V2Tf9B*}Z4vZZ~9{F@HcsYN`1i1hk2~!|r<9j1j_yr2r lfd6(!UU$~Cz?H5(X}EQzDW=EcBfbcsj)4te+n3dT|3AFNK8yeW literal 0 HcmV?d00001 diff --git a/src/factorio_mod_settings_testfiles/mod_settings_1.0.json b/src/factorio_mod_settings_testfiles/mod_settings_1.0.json new file mode 100644 index 00000000..637904c8 --- /dev/null +++ b/src/factorio_mod_settings_testfiles/mod_settings_1.0.json @@ -0,0 +1,554 @@ +{ + "runtime-global": { + "bobmods-classes-class-select": { + "value": false + }, + "bobmods-classes-class-select-user": { + "value": false + }, + "bobmods-classes-editor-mode": { + "value": false + }, + "bobmods-classes-god-mode": { + "value": false + }, + "flib-translations-per-tick": { + "value": 50 + }, + "loader-snapping": { + "value": true + }, + "loader-use-trains": { + "value": "disabled" + } + }, + "runtime-per-user": { + "bobmods-inserters-show-window": { + "value": "off" + } + }, + "startup": { + "angels-cab-energy-transfer-rate-mk1": { + "value": 500000 + }, + "angels-components-stack-size": { + "value": 1000 + }, + "angels-crawlertrain-tier-amount": { + "value": 3 + }, + "angels-disable-bobs-chemical-plants": { + "value": true + }, + "angels-disable-bobs-distilleries": { + "value": true + }, + "angels-disable-bobs-electrolysers": { + "value": true + }, + "angels-disable-vanilla-chemical-plants": { + "value": true + }, + "angels-enable-acids": { + "value": true + }, + "angels-enable-auto-barreling": { + "value": false + }, + "angels-enable-components": { + "value": false + }, + "angels-enable-converter": { + "value": true + }, + "angels-enable-hide-void": { + "value": true + }, + "angels-enable-industries": { + "value": true + }, + "angels-enable-inline-tank": { + "value": true + }, + "angels-enable-pressure-tank": { + "value": true + }, + "angels-enable-silos": { + "value": true + }, + "angels-enable-storage-icon-scaling": { + "value": false + }, + "angels-enable-tech": { + "value": false + }, + "angels-enable-warehouses": { + "value": true + }, + "angels-enablefluidreq": { + "value": true + }, + "angels-hide-converter": { + "value": true + }, + "angels-hq-graphics": { + "value": true + }, + "angels-infinite-yield": { + "value": 20 + }, + "angels-keepuranacid": { + "value": true + }, + "angels-lower-infinite-yield": { + "value": 1 + }, + "angels-marathon-buildingmulti": { + "value": 2 + }, + "angels-marathon-buildingtime": { + "value": 2 + }, + "angels-marathon-intermediatemulti": { + "value": 1 + }, + "angels-marathon-rawmulti": { + "value": 1 + }, + "angels-pavement-stack-size": { + "value": 200 + }, + "angels-petrotrain-tier-amount": { + "value": 3 + }, + "angels-return-ingredients": { + "value": true + }, + "angels-show-chemical-formula": { + "value": true + }, + "angels-smeltingtrain-tier-amount": { + "value": 3 + }, + "angels-starting-resource-base": { + "value": 40000 + }, + "angels-starting-resource-ore1": { + "value": true + }, + "angels-starting-resource-ore2": { + "value": false + }, + "angels-starting-resource-ore3": { + "value": true + }, + "angels-starting-resource-ore4": { + "value": false + }, + "angels-starting-resource-ore5": { + "value": true + }, + "angels-starting-resource-ore6": { + "value": true + }, + "angels-tryptophobia-friendly-stiratite": { + "value": false + }, + "bobmods-assembly-burner": { + "value": true + }, + "bobmods-assembly-centrifuge": { + "value": true + }, + "bobmods-assembly-chemicalplants": { + "value": true + }, + "bobmods-assembly-distilleries": { + "value": true + }, + "bobmods-assembly-electrolysers": { + "value": true + }, + "bobmods-assembly-electronicmachines": { + "value": true + }, + "bobmods-assembly-furnaces": { + "value": true + }, + "bobmods-assembly-limits": { + "value": false + }, + "bobmods-assembly-multipurposefurnaces": { + "value": true + }, + "bobmods-assembly-oilfurnaces": { + "value": true + }, + "bobmods-assembly-oilrefineries": { + "value": true + }, + "bobmods-burnerphase": { + "value": false + }, + "bobmods-colorupdate": { + "value": true + }, + "bobmods-enemies-aliensdropartifacts": { + "value": true + }, + "bobmods-enemies-biggersooner": { + "value": false + }, + "bobmods-enemies-enableartifacts": { + "value": true + }, + "bobmods-enemies-enablenewartifacts": { + "value": true + }, + "bobmods-enemies-enablesmallartifacts": { + "value": true + }, + "bobmods-enemies-healthincrease": { + "value": false + }, + "bobmods-enemies-leviathanfrequency": { + "value": 0.05 + }, + "bobmods-enemies-superspawner": { + "value": false + }, + "bobmods-gems-amethystratio": { + "value": 0.5 + }, + "bobmods-gems-diamondratio": { + "value": 0.2 + }, + "bobmods-gems-emeraldratio": { + "value": 0.6 + }, + "bobmods-gems-rubyratio": { + "value": 1 + }, + "bobmods-gems-sapphireratio": { + "value": 0.8 + }, + "bobmods-gems-topazratio": { + "value": 0.4 + }, + "bobmods-inserters-long2": { + "value": true + }, + "bobmods-inserters-more2": { + "value": true + }, + "bobmods-logistics-beltoverhaul": { + "value": true + }, + "bobmods-logistics-beltoverhaulspeed": { + "value": false + }, + "bobmods-logistics-beltperlevel": { + "value": 4 + }, + "bobmods-logistics-beltrequireprevious": { + "value": true + }, + "bobmods-logistics-beltspeedperlevel": { + "value": 15 + }, + "bobmods-logistics-beltstarting": { + "value": 3 + }, + "bobmods-logistics-disableroboports": { + "value": false + }, + "bobmods-logistics-drainlessinserters": { + "value": false + }, + "bobmods-logistics-fluidwagonbase": { + "value": 25 + }, + "bobmods-logistics-flyingrobotframes": { + "value": true + }, + "bobmods-logistics-inserteroverhaul": { + "value": true + }, + "bobmods-logistics-inserterrequireprevious": { + "value": true + }, + "bobmods-logistics-pipeperlevel": { + "value": 4 + }, + "bobmods-logistics-pipestarting": { + "value": 11 + }, + "bobmods-logistics-roboportrecipeupdate": { + "value": true + }, + "bobmods-logistics-robotparts": { + "value": true + }, + "bobmods-logistics-robotrequireprevious": { + "value": true + }, + "bobmods-logistics-storagetankbase": { + "value": 25 + }, + "bobmods-logistics-trains": { + "value": true + }, + "bobmods-logistics-ugdistanceoverhaul": { + "value": true + }, + "bobmods-mining-areadrills": { + "value": true + }, + "bobmods-mining-miningaxes": { + "value": true + }, + "bobmods-mining-miningdrills": { + "value": true + }, + "bobmods-mining-pumpjacks": { + "value": true + }, + "bobmods-mining-steamminingdrills": { + "value": true + }, + "bobmods-mining-waterminers": { + "value": true + }, + "bobmods-modules-enablegodmodules": { + "value": false + }, + "bobmods-modules-enablegreenmodules": { + "value": true + }, + "bobmods-modules-enableproductivitylimitation": { + "value": true + }, + "bobmods-modules-enablerawproductivitymodules": { + "value": true + }, + "bobmods-modules-enablerawspeedmodules": { + "value": true + }, + "bobmods-modules-perlevel-bonus-consumption": { + "value": 0.1 + }, + "bobmods-modules-perlevel-bonus-pollution": { + "value": 0.15 + }, + "bobmods-modules-perlevel-bonus-pollutioncreate": { + "value": 0.5 + }, + "bobmods-modules-perlevel-bonus-productivity": { + "value": 0.05 + }, + "bobmods-modules-perlevel-bonus-speed": { + "value": 0.2 + }, + "bobmods-modules-perlevel-penalty-consumption": { + "value": 0.1 + }, + "bobmods-modules-perlevel-penalty-pollution": { + "value": 0.15 + }, + "bobmods-modules-perlevel-penalty-speed": { + "value": 0.05 + }, + "bobmods-modules-productivityhasspeed": { + "value": false + }, + "bobmods-modules-start-bonus-consumption": { + "value": 0 + }, + "bobmods-modules-start-bonus-pollution": { + "value": 0 + }, + "bobmods-modules-start-bonus-pollutioncreate": { + "value": 0 + }, + "bobmods-modules-start-bonus-productivity": { + "value": 0 + }, + "bobmods-modules-start-bonus-speed": { + "value": 0 + }, + "bobmods-modules-start-penalty-consumption": { + "value": 0 + }, + "bobmods-modules-start-penalty-pollution": { + "value": 0 + }, + "bobmods-modules-start-penalty-speed": { + "value": 0.2 + }, + "bobmods-modules-transmitproductivity": { + "value": false + }, + "bobmods-ores-enablebauxite": { + "value": false + }, + "bobmods-ores-enablecobaltore": { + "value": false + }, + "bobmods-ores-enablegemsore": { + "value": false + }, + "bobmods-ores-enablegoldore": { + "value": false + }, + "bobmods-ores-enableleadore": { + "value": false + }, + "bobmods-ores-enablenickelore": { + "value": false + }, + "bobmods-ores-enablequartz": { + "value": false + }, + "bobmods-ores-enablerutile": { + "value": false + }, + "bobmods-ores-enablesilverore": { + "value": false + }, + "bobmods-ores-enablesulfur": { + "value": false + }, + "bobmods-ores-enablethoriumore": { + "value": false + }, + "bobmods-ores-enabletinore": { + "value": false + }, + "bobmods-ores-enabletungstenore": { + "value": false + }, + "bobmods-ores-enablewaterores": { + "value": false + }, + "bobmods-ores-enablezincore": { + "value": false + }, + "bobmods-ores-gemprobability": { + "value": 0.05 + }, + "bobmods-ores-gemsfromotherores": { + "value": false + }, + "bobmods-ores-infiniteore": { + "value": false + }, + "bobmods-ores-leadgivesnickel": { + "value": false + }, + "bobmods-ores-leadnickelratio": { + "value": 0.6 + }, + "bobmods-ores-nickelcobaltratio": { + "value": 0.4 + }, + "bobmods-ores-nickelgivescobalt": { + "value": false + }, + "bobmods-ores-unsortedgemore": { + "value": false + }, + "bobmods-plates-batteryupdate": { + "value": true + }, + "bobmods-plates-bluedeuterium": { + "value": false + }, + "bobmods-plates-cheapersteel": { + "value": true + }, + "bobmods-plates-convert-recipes": { + "value": true + }, + "bobmods-plates-groundwater": { + "value": false + }, + "bobmods-plates-inventorysize": { + "value": 80 + }, + "bobmods-plates-newsteel": { + "value": true + }, + "bobmods-plates-nuclearupdate": { + "value": true + }, + "bobmods-plates-oreoverride": { + "value": true + }, + "bobmods-plates-purewater": { + "value": true + }, + "bobmods-plates-vanillabarrelling": { + "value": false + }, + "bobmods-power-accumulators": { + "value": true + }, + "bobmods-power-burnergenerator": { + "value": true + }, + "bobmods-power-fluidgenerator": { + "value": true + }, + "bobmods-power-heatsources": { + "value": true + }, + "bobmods-power-nuclear": { + "value": true + }, + "bobmods-power-poles": { + "value": true + }, + "bobmods-power-solar": { + "value": true + }, + "bobmods-power-steam": { + "value": true + }, + "bobmods-revamp-hardmode": { + "value": true + }, + "bobmods-revamp-nuclear": { + "value": true + }, + "bobmods-revamp-oil": { + "value": true + }, + "bobmods-revamp-old-oil": { + "value": true + }, + "bobmods-revamp-rtg": { + "value": true + }, + "bobmods-tech-colorupdate": { + "value": true + }, + "bobmods-vehicleequipment-enablevehiclegrids": { + "value": true + }, + "bobmods-warfare-drainlesslaserturrets": { + "value": false + }, + "bobmods-warfare-robotupdate": { + "value": true + }, + "replace-electronics": { + "value": true + }, + "replace-research-icons": { + "value": true + }, + "replace-warfare": { + "value": true + } + } +} \ No newline at end of file diff --git a/src/factorio_mod_settings_testfiles/mod_settings_1.1.dat b/src/factorio_mod_settings_testfiles/mod_settings_1.1.dat new file mode 100644 index 0000000000000000000000000000000000000000..363c0cde5160346e41872b801d2e3e487bc1f775 GIT binary patch literal 9117 zcmb7KyRsxV8P>7ulpTSw%eVF2#%sWCSAh*xL}#cXA?F3u-Rd53)Kah1J+reB0Rb5? zya6d0F%geIMwKHn9)VBYElumvGs7fj&)NU->DPbP+>tx-IlV?hjOq>?Qk8^7}u0_$%^}Ru_Ud>R-zeRUf+n_f)Jyc!aZp7`wPs16AU(eN>)A?md{@&=98~5~-MI&S>Ic>D zRmo}50JyBh2`dNd8SkentAX5&0GAKaa?-NdLwEL0(dmy}Cbsw1g{pv;qZM2PRFeRgVUdH?&Glf+`&|mAq|HLll~XxQ>ytLpT+465ba7X)Jzb zkPLm+7Nj5Mc}z!9em1$hwH&lPqhf$dRGP)HX46W7Ot1qo-JZ$@{lLg%bqd1yCGwX) z+s|JgQk$8vhsk<+%-PI46_+T^NU5d}O15#LLpR~heJ1SC+opv6sDhW8>J##9#d|as zf>CJ)fmL^J!`L6y(c9KeDxokNZ1J3RsMgl*$`mEqbcF_IPe+mH@XiOR8G6$*7WYqt zY$$;-aTzRB;!4|VJL01+)Mc-YYldd~z|q0q3UPvVQRUaWEu^mE1-cwk3`S?md#fyM zkyfSZl};j(5byry)75qm6PO{qX9NoEb${%f=gc+rwny43xm9e)FLxw!ag8|H#vTZV zM$;~nC^P4B&^A5f$0$doJQ^xTgC;))>d*VE4F#TzR-3U-OvSM zlBTsr*PkkgNoNlFJmYG?h8A3&#;Y zpz-hAz;%|c>Jfp9O^lt@T2-S-vww)3XH||C0>_~llX;#y@|8yvXz4Y6tpXY24(-n6MVGrQ7G=5HGl=e7eQ#MVklgF8zAyXyP*2lAsUB6=mn zm=W;J^!djF`TAA?wsVN$+~xLvKael4iCJAkV0?ELbP_($oE0N;q-E1F|MMZee$U*) z-Nb<6e%+ee7vh9mwWrTy$swGG?PFwZurk~p^GvpN_#(Fcl+~|#5h~^UN&I)szjb8C zoZfww`-1;KQsT#fjFk-{=kXwXC2)3M3rMZzTo?Sl6o;Jdy0+cM>)tTGlW^65zU#;% z$f2LxZ}@!@G^k?IU`|`-t-xruLGtOlWgSMNjt%=0R;D&L2DHvhh;Uz}CKl{LIwjGH zr5qkw$bsQqQ<3GElhJn%?pV@z5T=tQj>Q?I4+u=OE)D zCP(U9>9yohwrHEO^tmHW4U^?hfOxN7Nq>RKJ%_~igA*;>2T@$ z*5w+lIyLMki>G*e8#(E4?+Q6I;W@3-wfw-$>`?(68vrTwOqh#DpCLl6ntPC0GNz>Sx5cy3a zR$;X3i#^qL@Jz4McOMJk7XH^Aw1p0f=tOBO3&py~(Z#a#5I=9POfg?uhHtKdK!Vp5+9yi^6_-S()eZ<7Y r0^G{c6z#|hyw-3lI8Y6c_nNo+;hbg8T+ Date: Sat, 7 Aug 2021 02:34:59 +0200 Subject: [PATCH 24/25] removed testoutput to fix mod_settings reading --- src/factorio/factorio_data_types.go | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/factorio/factorio_data_types.go b/src/factorio/factorio_data_types.go index 597844f5..78dc7ee7 100644 --- a/src/factorio/factorio_data_types.go +++ b/src/factorio/factorio_data_types.go @@ -13,8 +13,6 @@ import ( // Reading //////// /////////////////// func readOptimUint(r io.Reader, v Version, bitSize int) (uint32, error) { - log.Println("readOptimUint") - var b [4]byte if !v.Less(Version{0, 14, 14, 0}) { _, err := r.Read(b[:1]) @@ -46,8 +44,6 @@ func readOptimUint(r io.Reader, v Version, bitSize int) (uint32, error) { } func readString(r io.Reader, version Version, forceOptimized bool) (s string, err error) { - log.Println("readString") - var n uint32 if !version.Less(Version{0, 16, 0, 0}) || forceOptimized { @@ -64,8 +60,6 @@ func readString(r io.Reader, version Version, forceOptimized bool) (s string, er n = uint32(binary.LittleEndian.Uint32(b[:])) } - log.Printf("string-size: %d", n) - // do not read the string, when it is empty if n < 1 { return "", nil @@ -77,14 +71,10 @@ func readString(r io.Reader, version Version, forceOptimized bool) (s string, er return "", fmt.Errorf("failed to read string: %v", err) } - log.Println(string(d)) - return string(d), nil } func readStringSettings(file io.Reader, version Version) (string, error) { - log.Println("readStringSettings") - // read "empty" flag empty, err := readBool(file) if err != nil { @@ -106,8 +96,6 @@ func readStringSettings(file io.Reader, version Version) (string, error) { } func readBool(file io.Reader) (bool, error) { - log.Println("readBool") - var _data byte err := binary.Read(file, binary.LittleEndian, &_data) if err != nil { @@ -119,8 +107,6 @@ func readBool(file io.Reader) (bool, error) { } func readDouble(file io.Reader) (float64, error) { - log.Println("readDouble") - var _data float64 err := binary.Read(file, binary.LittleEndian, &_data) if err != nil { @@ -132,8 +118,6 @@ func readDouble(file io.Reader) (float64, error) { } func readList(file io.Reader, version Version) ([]interface{}, error) { - log.Println("readList") - var length uint32 length, err := readOptimUint(file, version, 32) if err != nil { @@ -154,8 +138,6 @@ func readList(file io.Reader, version Version) ([]interface{}, error) { } func readDict(file io.Reader, version Version) (map[string]interface{}, error) { - log.Println("readDict") - var length uint32 err := binary.Read(file, binary.LittleEndian, &length) if err != nil { @@ -184,8 +166,6 @@ func readDict(file io.Reader, version Version) (map[string]interface{}, error) { } func readTree(file io.Reader, version Version) (interface{}, error) { - log.Println("readTree") - //type of embedded data var _type byte err := binary.Read(file, binary.LittleEndian, &_type) From e74487ef49879ae308d4e68c9f9f022a408e27ff Mon Sep 17 00:00:00 2001 From: knoxfighter Date: Sun, 8 Aug 2021 03:23:16 +0200 Subject: [PATCH 25/25] removed not used scss file --- ui/scss/pages/mod-config.scss | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 ui/scss/pages/mod-config.scss diff --git a/ui/scss/pages/mod-config.scss b/ui/scss/pages/mod-config.scss deleted file mode 100644 index 851681b1..00000000 --- a/ui/scss/pages/mod-config.scss +++ /dev/null @@ -1,5 +0,0 @@ -#mod-config { - .content { - margin-bottom: 10px; - } -} \ No newline at end of file