Skip to content

Commit

Permalink
asset: fix reading saved state
Browse files Browse the repository at this point in the history
The problem identified by the stack trace below is caused by the json
library changing the key type to a string for both the _priority and
_intel tables. Since LUA differentiates between a number and string
when looking up a key in a table you can actually have a table
construction like the following;
	{ 1 = 1234, "1" = 789, }

This will result in two different values being returned depending on
if you asked for the key `"1"` or `1`.

The solution is to turn these table keys back into numbers when reading
in the state file.

Stack trace:
2020-05-01 22:45:15.811 ERROR   SCRIPTING: DCT|Theater: protected call - [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\Asset.lua"]:149: attempt to index field '?' (a nil value)
stack traceback:
    [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\Theater.lua"]:338: in function <[string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\Theater.lua"]:336>
    [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\Asset.lua"]:149: in function 'getPriority'
    [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\ai\Commander.lua"]:25: in function 'heapsort_tgtlist'
    [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\ai\Commander.lua"]:191: in function 'requestMission'
    [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\ui\cmds.lua"]:171: in function '_execute'
    [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\ui\cmds.lua"]:48: in function 'execute'
    [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\Theater.lua"]:318: in function '_exec'
    [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\Theater.lua"]:341: in function <[string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\Theater.lua"]:340>
    [C]: in function 'xpcall'
    [string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\Theater.lua"]:344: in function <[string "C:\Saved Games\DCS.openbeta\Mods\tech\DCT\lua\dct\Theater.lua"]:335>

Finally, add a unit-test to catch this issue in the future by triggering
a user command after the state file has been read back in.

Closes: #74
Fixes: 942e4c4 ("asset: use composition to represent different asset types")
  • Loading branch information
jtoppins committed May 2, 2020
1 parent bdfe2af commit 12d788e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
10 changes: 10 additions & 0 deletions src/dct/Asset.lua
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,16 @@ function Asset:unmarshal(data)
local collectiondata = data.collection
data.collection = nil
utils.mergetables(self, data)
-- need to handle the intel and priority tables special because even
-- though their keys were numbers when the state was serialized
-- in json's wisdom it decided to convert them to strings. So we need to
-- convert back so we can access the data in our lookups.
for _, tbl in ipairs({"_intel", "_priority"}) do
self[tbl] = {}
for k, v in pairs(data[tbl]) do
self[tbl][tonumber(k)] = v
end
end
self._collection = getcollection(data.type, self)
self._collection:unmarshal(collectiondata)
self._initcomplete = true
Expand Down
27 changes: 26 additions & 1 deletion tests/test-theater.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ require("io")
local md5 = require("md5")
require("dcttestlibs")
require("dct")
local enum = require("dct.enum")
local settings = _G.dct.settings

local events = {
Expand Down Expand Up @@ -204,7 +205,7 @@ end
local function main()
local playergrp = Group(4, {
["id"] = 15,
["name"] = "Uzi 35",
["name"] = "Uzi 41",
["coalition"] = coalition.side.BLUE,
["exists"] = true,
})
Expand Down Expand Up @@ -242,6 +243,30 @@ local function main()
-- verify the units read in do not include the asset we killed off
assert(newtheater:getAssetMgr():getAsset(name) == nil,
"state saving has an issue")

-- attempt to get theater status
newtheater:onEvent({
["id"] = world.event.S_EVENT_BIRTH,
["initiator"] = player1,
})

local status = {
["data"] = {
["name"] = playergrp:getName(),
["type"] = enum.uiRequestType.THEATERSTATUS,
},
["assert"] = true,
["expected"] = "== Theater Threat Status ==\n Sea: medium\n"..
" Air: parity\n ELINT: medium\n SAM: medium\n\n"..
"== Current Active Air Missions ==\n No Active Missions\n\n"..
"Recommended Mission Type: CAP\n",
}
local uicmds = require("dct.ui.cmds")
trigger.action.setassert(status.assert)
trigger.action.setmsgbuffer(status.expected)
local cmd = uicmds[status.data.type](newtheater, status.data)
cmd:execute(400)

newtheater:export()
f = io.open(settings.statepath, "r")
local sumsave = md5.sum(f:read("*all"))
Expand Down

0 comments on commit 12d788e

Please sign in to comment.