1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
-- script to verify CDDA JSON(verifies all mods)
-- run this script with: lua lua/json_verifier.lua
--
-- requires luafilesystem to scan for files, installation instructions:
-- arch linux: pacman -S lua-filesystem
-- debian linux: aptitude install liblua5.1-filesystem0
-- other linux distributions: search for "lua file system" in the
-- package manager of your choice
local json = require("lua/dkjson")
local lfs = require("lfs")
local exit_code = 0
-- function to read a file completely into a string
function read_file(filename)
local f = io.open(filename, "r")
local content = f:read("*all")
f:close()
return content
end
decode_cache = {}
-- parse the JSON of an entire cataclysm file
function parse_cata_json(filename, handler)
local root, pos, err
if not decode_cache[filename] then
local content = read_file(filename)
root, pos, err = json.decode(content, 1, nil)
decode_cache[filename] = root
else
root = decode_cache[filename]
end
if err then
print("Error in ", filename ,":", err)
os.exit(1)
else
-- top level should be a json array
if type(root) ~= "table" then
print("Wrong root element to JSON file ", filename, " :", type(root))
end
for _, entry in ipairs(root) do
if not entry.type then
print("Invalid entry type in ", filename, ": ", entry.type)
end
if handler[entry.type] then
handler[entry.type](entry, filename)
end
end
end
end
local definitions = {}
local material_definitions = {}
function load_item_definition(entry, filename)
-- store that this item was defined
definitions[entry.id] = true
end
-- define load_definition handlers
local load_definition = {}
local item_types = { "BOOK", "TOOL", "GUN", "GUNMOD", "TOOL_ARMOR", "ARMOR", "BIONIC_ITEM", "GENERIC", "AMMO", "CONTAINER", "COMESTIBLE", "VAR_VEH_PART" }
for _, item_type in ipairs(item_types) do
load_definition[item_type] = load_item_definition
end
-- load definition handler for materials
function load_material_definition(entry, filename)
-- store that this material was defined
material_definitions[entry.ident] = true
end
load_definition.material = load_material_definition
local verify_handler = {}
function ensure_definition(id, filename, parent_id)
if not definitions[id] then
-- signify that something went wrong
exit_code = 1
print("Trying to access non-existent item id ", id, " in ", filename, "(", parent_id, ")")
end
end
function ensure_material_definition(id, filename, parent_id)
if not material_definitions[id] then
-- signify that something went wrong
exit_code = 1
print("Trying to access non-existent material id ", id, " in ", filename, "(", parent_id, ")")
end
end
verify_handler.recipe = function(entry, filename)
ensure_definition(entry.result, filename, entry.result)
for _, alternatives in ipairs(entry.components) do
for _, item in ipairs(alternatives) do
ensure_definition(item[1], filename, entry.result)
end
end
if entry.tools then
for _, alternatives in ipairs(entry.tools) do
for _, item in ipairs(alternatives) do
ensure_definition(item[1], filename, entry.result)
end
end
end
end
function verify_item_definition(entry, filename)
local materials
if not entry.material or entry.material == "" then
return
elseif type(entry.material) == "string" then
materials = { entry.material }
elseif type(entry.material == "table") then
materials = entry.material
else
exit_code = 1
print("Invalid material for ", entry.id, " in ", filename)
end
for _, material in ipairs(materials) do
ensure_material_definition(material, filename, entry.id)
end
end
for _, item_type in ipairs(item_types) do
verify_handler[item_type] = verify_item_definition
end
function string.endswith(mystr, myend)
return myend=="" or string.sub(mystr,string.len(mystr)-string.len(myend)+1)==myend
end
function load_all_jsons_recursive(path, handler)
for file in lfs.dir(path) do
if file ~= "." and file ~= ".." then
local f = path..'/'..file
local attr = lfs.attributes(f)
if attr.mode == "directory" then
load_all_jsons_recursive(f, handler)
elseif attr.mode == "file" and string.endswith(f, ".json") then
parse_cata_json(f, handler)
end
end
end
end
function load_all_jsons(handler)
load_all_jsons_recursive("data/json", handler)
load_all_jsons_recursive("data/mods", handler)
end
-- first load all item definitions
load_all_jsons(load_definition)
-- some hardcoded item definitions
definitions["cvd_machine"] = true
definitions["corpse"] = true
definitions["apparatus"] = true
definitions["toolset"] = true
definitions["fire"] = true
-- then verify recipes
load_all_jsons(verify_handler)
os.exit(exit_code)
|