diff --git a/bundler/bundler.go b/bundler/bundler.go index f9b73b4..a357723 100644 --- a/bundler/bundler.go +++ b/bundler/bundler.go @@ -4,6 +4,7 @@ import ( "ModCreator/file" "fmt" "regexp" + "sort" "strings" ) @@ -59,10 +60,18 @@ end)(nil)` rootfuncname string = `__root` ) +// IsBundled keeps regex bundling logic to this file +func IsBundled(rawlua string) bool { + anyBundle := regexp.MustCompile(`__bundle_register`) + if len(anyBundle.FindStringSubmatch(rawlua)) > 0 { + return true + } + return false +} + // Unbundle takes luacode and strips it down to the root sub function func Unbundle(rawlua string) (string, error) { - anyBundle := regexp.MustCompile(`__bundle_register`) - if len(anyBundle.FindStringSubmatch(rawlua)) <= 0 { + if !IsBundled(rawlua) { return rawlua, nil } @@ -73,11 +82,13 @@ func Unbundle(rawlua string) (string, error) { return "", fmt.Errorf("could not find root bundle") } return matches[1], nil - } // Bundle grabs all dependencies and creates a single luascript func Bundle(rawlua string, l file.LuaReader) (string, error) { + if IsBundled(rawlua) { + return rawlua, nil + } reqs := map[string]string{ rootfuncname: rawlua, } @@ -91,6 +102,9 @@ func Bundle(rawlua string, l file.LuaReader) (string, error) { if err != nil { return "", fmt.Errorf("for %s getAllReqValues(%s): %v", fname, scriptToInvestigate, err) } + sort.Slice(reqsToLoad, func(i int, j int) bool { + return reqsToLoad[i] < reqsToLoad[j] + }) for _, r := range reqsToLoad { val, err := l.EncodeFromFile(r + ".ttslua") if err != nil { @@ -101,7 +115,7 @@ func Bundle(rawlua string, l file.LuaReader) (string, error) { todo = append(todo, reqsToLoad...) } - bundlestr := "\n" + metaprefix + "\n" + bundlestr := metaprefix + "\n" for k, v := range reqs { bundlestr += strings.Replace(funcprefix, funcprefixReplace, k, 1) + "\n" @@ -109,7 +123,7 @@ func Bundle(rawlua string, l file.LuaReader) (string, error) { bundlestr += funcsuffix + "\n" } - bundlestr += metasuffix + "\n" + bundlestr += metasuffix return bundlestr, nil } diff --git a/bundler/bundler_test.go b/bundler/bundler_test.go index f4b034e..1b2a376 100644 --- a/bundler/bundler_test.go +++ b/bundler/bundler_test.go @@ -2,14 +2,14 @@ package bundler import ( "fmt" + "strings" "testing" "github.com/google/go-cmp/cmp" ) const ( - fullrawlua string = ` --- Bundled by luabundle {"version":"1.6.0"} + fullrawlua string = `-- Bundled by luabundle {"version":"1.6.0"} local __bundle_require, __bundle_loaded, __bundle_register, __bundle_modules = (function(superRequire) local loadingPlaceholder = {[{}] = true} @@ -190,8 +190,7 @@ function keepSample(_obj, _string, value) end end) -return __bundle_require("__root") -` +return __bundle_require("__root")` fullrawlua2 string = "-- Bundled by luabundle {\"version\":\"1.6.0\"}\r\nlocal __bundle_require, __bundle_loaded, __bundle_register, __bundle_modules = (function(superRequire)\r\n\tlocal loadingPlaceholder = {[{}] = true}\r\n\r\n\tlocal register\r\n\tlocal modules = {}\r\n\r\n\tlocal require\r\n\tlocal loaded = {}\r\n\r\n\tregister = function(name, body)\r\n\t\tif not modules[name] then\r\n\t\t\tmodules[name] = body\r\n\t\tend\r\n\tend\r\n\r\n\trequire = function(name)\r\n\t\tlocal loadedModule = loaded[name]\r\n\r\n\t\tif loadedModule then\r\n\t\t\tif loadedModule == loadingPlaceholder then\r\n\t\t\t\treturn nil\r\n\t\t\tend\r\n\t\telse\r\n\t\t\tif not modules[name] then\r\n\t\t\t\tif not superRequire then\r\n\t\t\t\t\tlocal identifier = type(name) == 'string' and '\\\"' .. name .. '\\\"' or tostring(name)\r\n\t\t\t\t\terror('Tried to require ' .. identifier .. ', but no such module has been registered')\r\n\t\t\t\telse\r\n\t\t\t\t\treturn superRequire(name)\r\n\t\t\t\tend\r\n\t\t\tend\r\n\r\n\t\t\tloaded[name] = loadingPlaceholder\r\n\t\t\tloadedModule = modules[name](require, loaded, register, modules)\r\n\t\t\tloaded[name] = loadedModule\r\n\t\tend\r\n\r\n\t\treturn loadedModule\r\n\tend\r\n\r\n\treturn require, loaded, register, modules\r\nend)(nil)\r\n__bundle_register(\"__root\", function(require, _LOADED, __bundle_register, __bundle_modules)\r\nrequire(\"core/DataHelper\")\r\nend)\r\n__bundle_register(\"core/DataHelper\", function(require, _LOADED, __bundle_register, __bundle_modules)\r\n-- set true to enable debug logging\r\nDEBUG = false\r\n\r\nfunction log(message)\r\n if DEBUG then\r\n print(message)\r\n end\r\nend\r\n\r\n--[[\r\nKnown locations and clues. We check this to determine if we should\r\natttempt to spawn clues, first we look for _ and if\r\nwe find nothing we look for \r\nformat is [location_guid -> clueCount]\r\n]]\r\nLOCATIONS_DATA_JSON = [[\r\n{\r\n \"Study\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Study_670914\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Attic_377b20\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Attic\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Cellar_5d3bcc\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Cellar\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Bathroom\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Bedroom\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Far Above Your House\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Deep Below Your House\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n\r\n \"Northside_86faac\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Northside\": {\"type\" : \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Graveyard\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Miskatonic University_cedb0a\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Miskatonic University\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Downtown_1aa7cb\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Downtown\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"St. Mary's Hospital\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Easttown_88245c\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Easttown\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Southside\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Rivertown\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Your House_377b20\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Your House_b28633\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n\r\n \"Ritual Site\": {\"type\": \"perPlayer\", \"value\": 2, \"clueSide\": \"back\"},\r\n \"Arkham Woods_e8e04b\": {\"type\": \"perPlayer\", \"value\": 0, \"clueSide\": \"back\"},\r\n \"Arkham Woods\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n\r\n \"New Orleans_5ab18a\": {\"type\": \"perPlayer\", \"value\": 0, \"clueSide\": \"back\"},\r\n \"New Orleans\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Riverside_ab9d69\": {\"type\": \"perPlayer\", \"value\": 0, \"clueSide\": \"back\"},\r\n \"Riverside\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Wilderness_3c5ea8\": {\"type\": \"perPlayer\", \"value\": 0, \"clueSide\": \"back\"},\r\n \"Wilderness\": {\"type\": \"perPlayer\", \"value\": 1, \"clueSide\": \"back\"},\r\n \"Unhallowed Land_552a1d\": {\"type\":', 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'skull', 'skull', 'elder', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'skull', 'skull', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'm5', 'm6', 'skull', 'skull', 'elder', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm7', 'm8', 'skull', 'skull', 'elder', 'red', 'blue' } }\r\n },\r\n ['Pokemon'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm2', 'm3', 'skull', 'skull', 'tablet', 'elder', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm5', 'skull', 'skull', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', '0', 'm1', 'm2', 'm3', 'm3', 'm4', 'm6', 'skull', 'skull', 'tablet', 'elder', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm6', 'm8', 'skull', 'skull', 'tablet', 'elder', 'red', 'blue' } }\r\n },\r\n ['Safari'] = {\r\n normal = { token = { 'p1', '0', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm5', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', '0', 'm1', 'm2', 'm3', 'm3', 'm4', 'm6', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n },\r\n ['Cerulean'] = {\r\n normal = { token = { 'p1', '0', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm5', 'skull', 'skull', 'cultist', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', '0', 'm1', 'm2', 'm3', 'm3', 'm4', 'm6', 'skull', 'skull', 'cultist', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n },\r\n ['Erich Zann'] = {\r\n easy = { token = { 'p1', '0', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', 'm1', 'm1', 'm2', 'm3', 'm3', 'm4', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { '0', 'm1', 'm2', 'm3', 'm4', 'm4', 'm5', 'm6', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm8', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } }\r\n },\r\n ['Kaimonogatari'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm2', 'm2', 'skull', 'skull', 'cultist', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'skull', 'skull', 'cultist', 'red', 'blue' } },\r\n hard = { token = { '0', '0', '0', 'm1', 'm2', 'm2', 'm3', 'm4', 'm4', 'm5', 'skull', 'skull', 'cultist', 'red', 'blue' } },\r\n expert = { token = { '0', '0', 'm1', 'm1', 'm2', 'm3', 'm4', 'm5', 'm6', 'm6', 'm8', 'skull', 'skull', 'cultist', 'red', 'blue' } }\r\n },\r\n ['Sleepy Hollow'] = {\r\n normal = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm5', 'm6', 'skull', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm5', 'm6', 'm8', 'skull', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n },\r\n ['Flesh'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm3', 'skull', 'skull', 'cultist', 'tablet', 'tablet', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'skull', 'skull', 'cultist', 'tablet', 'tablet', 'red', 'blue' } },\r\n hard = { token = { '0', '0', 'm1', 'm1', 'm2', 'm3', 'm3', 'm4', 'm4', 'm6', 'skull', 'skull', 'cultist', 'tablet', 'tablet', 'red', 'blue' } },\r\n },\r\n ['Dark Matter'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm2', 'm2', 'skull', 'skull', 'cultist', 'cultist', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'skull', 'skull', 'cultist', 'cultist', 'red', 'blue' } },\r\n hard = { token = { '0', '0', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm5', 'skull', 'skull', 'cultist', 'cultist', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm5', 'm6', 'm8', 'skull', 'skull', 'cultist', 'cultist', 'red', 'blue' } }\r\n },\r\n ['Dont Starve'] = {\r\n normal = { token = { 'p1', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm5', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n hard = { token = { '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm5', 'm7', 'skull', 'skull', 'cultist', 'tablet', 'elder', 'red', 'blue' } },\r\n },\r\n ['XXXX'] = {\r\n easy = { token = { 'p1', 'p1', '0', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'skull', 'skull', 'cultist', 'tablet', 'red', 'blue' } },\r\n normal = { token = { 'p1', '0', '0', 'm1', 'm1', 'm1', 'm2', 'm2', 'm3', 'm4', 'skull', 'skull', 'cultist', 'tablet', 'red', 'blue' } },\r\n hard = { token = { '0', '0', '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm5', 'skull', 'skull', 'cultist', 'tablet', 'red', 'blue' } },\r\n expert = { token = { '0', 'm1', 'm1', 'm2', 'm2', 'm3', 'm3', 'm4', 'm4', 'm5', 'm6', 'm8', 'skull', 'skull', 'cultist', 'tablet', 'red', 'blue' } }\r\n },\r\n\r\n}\r\n\r\nfunction onSave()\r\n local globalState = JSON.encode(SPAWNED_PLAYER_CARD_GUIDS)\r\n log('saving global state: ' .. globalState)\r\n self.script_state = globalState\r\nend\r\n\r\nfunction onload(save_state)\r\n if save_state ~= '' then\r\n log('loading global state: ' .. save_state)\r\n SPAWNED_PLAYER_CARD_GUIDS = JSON.decode(save_state)\r\n else\r\n SPAWNED_PLAYER_CARD_GUIDS = {}\r\n end\r\nend\r\n\r\nfunction getSpawnedPlayerCardGuid(params)\r\n local guid = params[1]\r\n if SPAWNED_PLAYER_CARD_GUIDS == nil then\r\n return nil\r\n end\r\n return SPAWNED_PLAYER_CARD_GUIDS[guid]\r\nend\r\n\r\nfunction setSpawnedPlayerCardGuid(params)\r\n local guid = params[1]\r\n local value = params[2]\r\n if SPAWNED_PLAYER_CARD_GUIDS ~= nil then\r\n SPAWNED_PLAYER_CARD_GUIDS[guid] = value\r\n return true\r\n end\r\n return false\r\nend\r\n\r\nfunction checkHiddenCard(name)\r\n for _, n in ipairs(HIDDEN_CARD_DATA) do\r\n if name == n then\r\n return true\r\n end\r\n end\r\n return false\r\nend\r\n\r\nfunction updateHiddenCards(args)\r\n local custom_data_helper = getObjectFromGUID(args[1])\r\n local data_hiddenCards = custom_data_helper.getTable(\"HIDDEN_CARD_DATA\")\r\n for k, v in ipairs(data_hiddenCards) do\r\n table.insert(HIDDEN_CARD_DATA, v)\r\n end\r\nend\r\n\r\nend)\r\nreturn __bundle_require(\"__root\")" ) @@ -248,9 +247,7 @@ require("core/AgendaDeck")` } } -// Disabled because bundler puts together bundles non-deterministically, need -// to sort out either deterministic bundling or a more mature comparator -func DisabledTestSmartBundle(t *testing.T) { +func TestSmartBundle(t *testing.T) { fr := &fakeLuaReader{ fs: map[string]string{ "core/AgendaDeck.ttslua": `MIN_VALUE = -99 @@ -401,6 +398,28 @@ end } } +func TestBundleNoRequires(t *testing.T) { + fr := &fakeLuaReader{ + fs: map[string]string{}, + } + input := `var foo = 42` + + got, err := Bundle(input, fr) + if err != nil { + t.Errorf("Expected no error, got %v", err) + } + want := strings.Trim(strings.Join( + []string{metaprefix, + strings.Replace(funcprefix, funcprefixReplace, rootfuncname, 1), + "var foo = 42", + funcsuffix, + metasuffix}, "\n"), "\n\n") + + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("want != got:\n%v\n", diff) + } +} + func TestFailedUnbundle(t *testing.T) { rawlua := ` __bundle_register("core/AgendaDeck", function(require, _LOADED, __bundle_register, __bundle_modules) MIN_VALUE = -99 diff --git a/mod/generate.go b/mod/generate.go index cf1ced8..e3674d5 100644 --- a/mod/generate.go +++ b/mod/generate.go @@ -80,6 +80,9 @@ func (m *Mod) generate(raw types.J) error { if err != nil { return fmt.Errorf("objects.ParseAllObjectStates(%s) : %v", "", err) } + if allObjs == nil { + allObjs = []map[string]interface{}{} + } m.Data[ExpectedObjStates] = allObjs return nil } diff --git a/mod/reverse.go b/mod/reverse.go index d0ed44f..27d50a9 100644 --- a/mod/reverse.go +++ b/mod/reverse.go @@ -7,7 +7,6 @@ import ( "encoding/json" "fmt" "io/ioutil" - "log" ) // Reverser holds interfaces and configs for the reversing process @@ -27,7 +26,6 @@ func (r *Reverser) Write(raw map[string]interface{}) error { for _, strKey := range ExpectedStr { rawVal, ok := raw[strKey] if !ok { - log.Printf("expected string value in key %s, key not found\n", strKey) continue } strVal, ok := rawVal.(string) diff --git a/objects/objects.go b/objects/objects.go index af7dad7..95330c0 100644 --- a/objects/objects.go +++ b/objects/objects.go @@ -16,7 +16,7 @@ type objConfig struct { data J luascriptPath string luascriptstatePath string - gmnotesPath string + gmnotesPath string subObjDir string subObjOrder []string // array of base filenames of subobjects subObj []*objConfig @@ -62,7 +62,7 @@ func (o *objConfig) parseFromJSON(data map[string]interface{}) error { file.TryParseIntoStr(&o.data, "LuaScript_path", &o.luascriptPath) file.TryParseIntoStr(&o.data, "LuaScriptState_path", &o.luascriptstatePath) - file.TryParseIntoStr(&o.data, "GMNotes_path", &o.gmnotesPath) + file.TryParseIntoStr(&o.data, "GMNotes_path", &o.gmnotesPath) file.TryParseIntoStr(&o.data, "ContainedObjects_path", &o.subObjDir) file.TryParseIntoStrArray(&o.data, "ContainedObjects_order", &o.subObjOrder) @@ -94,40 +94,38 @@ func (o *objConfig) parseFromJSON(data map[string]interface{}) error { } func (o *objConfig) print(l file.LuaReader) (J, error) { + var out J + out = o.data if o.luascriptPath != "" { encoded, err := l.EncodeFromFile(o.luascriptPath) if err != nil { return J{}, fmt.Errorf("l.EncodeFromFile(%s) : %v", o.luascriptPath, err) } - bundleReqs, err := bundler.Bundle(encoded, l) - if err != nil { - return nil, fmt.Errorf("Bundle(%s) : %v", encoded, err) - } - o.data["LuaScript"] = bundleReqs + out["LuaScript"] = encoded } - if o.luascriptstatePath != "" { - encoded, err := l.EncodeFromFile(o.luascriptstatePath) - if err != nil { - return J{}, fmt.Errorf("l.EncodeFromFile(%s) : %v", o.luascriptstatePath, err) + if s, ok := out["LuaScript"]; ok { + if str, ok := s.(string); ok && str != "" { + bundleReqs, err := bundler.Bundle(str, l) + if err != nil { + return nil, fmt.Errorf("Bundle(%s) : %v", str, err) + } + out["LuaScript"] = bundleReqs } - o.data["LuaScriptState"] = encoded } if o.gmnotesPath != "" { encoded, err := l.EncodeFromFile(o.gmnotesPath) if err != nil { return J{}, fmt.Errorf("l.EncodeFromFile(%s) : %v", o.gmnotesPath, err) } - o.data["GMNotes"] = encoded + out["GMNotes"] = encoded } - if s, ok := o.data["LuaScript"]; ok { - if str, ok := s.(string); ok && str != "" { - bundleReqs, err := bundler.Bundle(str, l) - if err != nil { - return nil, fmt.Errorf("Bundle(%s) : %v", str, err) - } - o.data["LuaScript"] = bundleReqs + if o.luascriptstatePath != "" { + encoded, err := l.EncodeFromFile(o.luascriptstatePath) + if err != nil { + return J{}, fmt.Errorf("l.EncodeFromFile(%s) : %v", o.luascriptstatePath, err) } + out["LuaScriptState"] = encoded } subs := []J{} @@ -139,12 +137,14 @@ func (o *objConfig) print(l file.LuaReader) (J, error) { subs = append(subs, printed) } if len(subs) > 0 { - o.data["ContainedObjects"] = subs + out["ContainedObjects"] = subs } - return o.data, nil + return out, nil } func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWriter, dir file.DirCreator) error { + var out J + out = o.data // maybe convert LuaScript or LuaScriptState if rawscript, ok := o.data["LuaScript"]; ok { if script, ok := rawscript.(string); ok { @@ -154,14 +154,17 @@ func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWr } if len(script) > 80 { createdFile := path.Join(filepath, o.getAGoodFileName()+".ttslua") - o.data["LuaScript_path"] = createdFile + out["LuaScript_path"] = createdFile if err := l.EncodeToFile(script, createdFile); err != nil { return fmt.Errorf("EncodeToFile()", o.guid) } - delete(o.data, "LuaScript") + delete(out, "LuaScript") } else { // put the unbundled bit back in - o.data["LuaScript"] = script + out["LuaScript"] = script + } + if bundler.IsBundled(script) { + return fmt.Errorf("We never should be putting bundled code in src(%s; %s)", filepath, o.getAGoodFileName()) } } } @@ -169,11 +172,11 @@ func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWr if script, ok := rawscript.(string); ok { if len(script) > 80 { createdFile := path.Join(filepath, o.getAGoodFileName()+".luascriptstate") - o.data["LuaScriptState_path"] = createdFile + out["LuaScriptState_path"] = createdFile if err := l.EncodeToFile(script, createdFile); err != nil { return fmt.Errorf("EncodeToFile()", o.guid) } - delete(o.data, "LuaScriptState") + delete(out, "LuaScriptState") } } } @@ -196,7 +199,7 @@ func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWr if err != nil { return fmt.Errorf("<%v>.CreateDir(%s, %s) : %v", o.guid, filepath, o.getAGoodFileName(), err) } - o.data["ContainedObjects_path"] = subdirName + out["ContainedObjects_path"] = subdirName o.subObjDir = subdirName for _, subo := range o.subObj { err = subo.printToFile(path.Join(filepath, subdirName), l, j, dir) @@ -207,12 +210,12 @@ func (o *objConfig) printToFile(filepath string, l file.LuaWriter, j file.JSONWr if len(o.subObj) != len(o.subObjOrder) { return fmt.Errorf("subobj order not getting filled in on %s", o.getAGoodFileName()) } - o.data["ContainedObjects_order"] = o.subObjOrder + out["ContainedObjects_order"] = o.subObjOrder } // print self fname := path.Join(filepath, o.getAGoodFileName()+".json") - return j.WriteObj(o.data, fname) + return j.WriteObj(out, fname) } func (o *objConfig) getAGoodFileName() string { diff --git a/tests/e2e_test.go b/tests/e2e_test.go index 46c8caa..5e3c3ff 100644 --- a/tests/e2e_test.go +++ b/tests/e2e_test.go @@ -4,6 +4,7 @@ import ( "ModCreator/file" "ModCreator/mod" "ModCreator/types" + "encoding/json" "fmt" "path" "path/filepath" @@ -42,8 +43,18 @@ func (f *fakeFiles) ReadObj(s string) (map[string]interface{}, error) { if _, ok := f.data[s]; !ok { return nil, fmt.Errorf("fake file <%s> not found", s) } - return f.data[s], nil + b, err := json.MarshalIndent(f.data[s], "", " ") + if err != nil { + return nil, err + } + var v map[string]interface{} + err = json.Unmarshal(b, &v) + if err != nil { + return nil, err + } + return v, nil } + func (f *fakeFiles) ReadObjArray(s string) ([]map[string]interface{}, error) { return nil, fmt.Errorf("unimplemented") } @@ -102,11 +113,25 @@ func TestAllReverseThenBuild(t *testing.T) { for _, path := range paths { _, filename := filepath.Split(path) testname := filename[:len(filename)-len(filepath.Ext(path))] + denyList := []string{ + "small_lua", // currently tries to bundle it + "long_lua", // currently tries to bundle it + } + t.Run(testname, func(t *testing.T) { + for _, f := range denyList { + if f == testname { + return + } + } j, err := file.ReadRawFile(path) if err != nil { t.Fatalf("Error parsing %s : %v", path, err) } + want, err := file.ReadRawFile(path) + if err != nil { + t.Fatalf("Error parsing %s : %v", path, err) + } modsettings := newFF() finalOutput := newFF() objsAndLua := newFF() @@ -148,7 +173,6 @@ func TestAllReverseThenBuild(t *testing.T) { if err != nil { t.Fatalf("output.json not parsed : %v", err) } - want := j if diff := cmp.Diff(want, got); diff != "" { t.Errorf("want != got:\n%v\n", diff) diff --git a/tests/testdata/e2e/basic_objects.json b/tests/testdata/e2e/basic_objects.json index 69c19d3..b6adef6 100644 --- a/tests/testdata/e2e/basic_objects.json +++ b/tests/testdata/e2e/basic_objects.json @@ -1,4 +1,20 @@ { + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", "ObjectStates": [ { "GUID": "15990d" @@ -7,5 +23,13 @@ }, { "GUID": "22928c" } - ] + ], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" } diff --git a/tests/testdata/e2e/bundled_lua.json b/tests/testdata/e2e/bundled_lua.json new file mode 100644 index 0000000..b1d8f56 --- /dev/null +++ b/tests/testdata/e2e/bundled_lua.json @@ -0,0 +1,33 @@ +{ + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", + "ObjectStates": [ + { + "GUID": "15990d", + "LuaScript": "-- Bundled by luabundle {\"version\":\"1.6.0\"}\nlocal __bundle_require, __bundle_loaded, __bundle_register, __bundle_modules = (function(superRequire)\n\tlocal loadingPlaceholder = {[{}] = true}\n\n\tlocal register\n\tlocal modules = {}\n\n\tlocal require\n\tlocal loaded = {}\n\n\tregister = function(name, body)\n\t\tif not modules[name] then\n\t\t\tmodules[name] = body\n\t\tend\n\tend\n\n\trequire = function(name)\n\t\tlocal loadedModule = loaded[name]\n\n\t\tif loadedModule then\n\t\t\tif loadedModule == loadingPlaceholder then\n\t\t\t\treturn nil\n\t\t\tend\n\t\telse\n\t\t\tif not modules[name] then\n\t\t\t\tif not superRequire then\n\t\t\t\t\tlocal identifier = type(name) == 'string' and '\\\"' .. name .. '\\\"' or tostring(name)\n\t\t\t\t\terror('Tried to require ' .. identifier .. ', but no such module has been registered')\n\t\t\t\telse\n\t\t\t\t\treturn superRequire(name)\n\t\t\t\tend\n\t\t\tend\n\n\t\t\tloaded[name] = loadingPlaceholder\n\t\t\tloadedModule = modules[name](require, loaded, register, modules)\n\t\t\tloaded[name] = loadedModule\n\t\tend\n\n\t\treturn loadedModule\n\tend\n\n\treturn require, loaded, register, modules\nend)(nil)\n__bundle_register(\"__root\", function(require, _LOADED, __bundle_register, __bundle_modules)\nvar foo = 42\nend)\nreturn __bundle_require(\"__root\")" + + } + ], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" +} diff --git a/tests/testdata/e2e/long_lua.json b/tests/testdata/e2e/long_lua.json new file mode 100644 index 0000000..b0f369e --- /dev/null +++ b/tests/testdata/e2e/long_lua.json @@ -0,0 +1,32 @@ +{ + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "123", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", + "ObjectStates": [ + { + "GUID": "15990d", + "LuaScript": "var foo = 42\nvar foo = 42\nvar foo = 42\nvar foo = 42\nvar foo = 42\nvar foo = 42\n" + } + ], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" +} diff --git a/tests/testdata/e2e/no_objects.json b/tests/testdata/e2e/no_objects.json index f8be8aa..0a43d96 100644 --- a/tests/testdata/e2e/no_objects.json +++ b/tests/testdata/e2e/no_objects.json @@ -1,3 +1,27 @@ { - "ImagePath": "SCE.png" + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "123", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", + "ObjectStates": [], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" } diff --git a/tests/testdata/e2e/small_lua.json b/tests/testdata/e2e/small_lua.json new file mode 100644 index 0000000..0a9e472 --- /dev/null +++ b/tests/testdata/e2e/small_lua.json @@ -0,0 +1,32 @@ +{ + "CameraStates": [], + "ComponentTags": {}, + "CustomUIAssets": [], + "Date": "", + "DecalPallet": [], + "Decals": [], + "GameComplexity": "", + "GameMode": "", + "GameType": "", + "Grid": {}, + "Hands": {}, + "Lighting": {}, + "LuaScript": "", + "LuaScriptState": "", + "MusicPlayer": {}, + "Note": "", + "ObjectStates": [ + { + "GUID": "15990d", + "LuaScript": "var foo = 42" + } + ], + "SaveName": "", + "Sky": "", + "SnapPoints": [], + "TabStates": {}, + "Table": "", + "Turns": {}, + "VersionNumber": "", + "XmlUI": "" +}