forked from CleverRaven/Cataclysm-DDA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson_verifier.lua
175 lines (145 loc) · 5.05 KB
/
json_verifier.lua
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)