fffff
[QuestHelper.git] / db_get.lua
blobd9949618e435fab455d0992bd17fe3e040e2705d
1 QuestHelper_File["db_get.lua"] = "Development Version"
2 QuestHelper_Loadtime["db_get.lua"] = GetTime()
4 local dev_mode = (QuestHelper_File["db_get.lua"] == "Development Version")
6 -- yoink
7 --[[
8 local QHDB_temp = QHDB
9 QHDB = nil
10 local QHDB = QHDB_temp]]
11 QuestHelper: Assert(dev_mode or #QHDB == 4)
13 local weak_v = { __mode = 'v' }
14 local weak_k = { __mode = 'k' }
16 local cache = {}
18 local frequencies = setmetatable({}, weak_k)
20 -- guhhh just want this to work
21 local freq_group = setmetatable({}, weak_k)
22 local freq_id = setmetatable({}, weak_k)
24 local function DBC_Get(group, id)
25 if not cache[group] then return end
26 return cache[group][id]
27 end
29 local function DBC_Put(group, id, item)
30 if not cache[group] then cache[group] = setmetatable({}, weak_v) end
31 QuestHelper: Assert(not cache[group][id])
32 cache[group][id] = item
34 --DB_how_many_are_used()
35 end
37 local function mark(tab, tomark)
38 for k, v in pairs(tab) do
39 if k ~= "__owner" and type(v) == "table" then
40 mark(v, tomark)
41 end
42 end
43 tab.__owner = tomark
44 end
46 local function read_adaptint(data, offset)
47 local stx = 0
48 local acu = 1
49 while true do
50 local v = strbyte(data, offset)
51 QuestHelper: Assert(v, string.format("%d %d", #data, offset))
52 stx = stx + acu * math.floor(v / 2)
53 offset = offset + 1
54 acu = acu * 128
55 if mod(v, 2) == 0 then break end
56 end
57 return stx, offset
58 end
60 local function search_index(index, data, item)
61 --[[Header format:
63 Itemid (0 for endnode)
64 Offset
65 Length
66 Rightlink]]
68 local cofs = 1
69 assert(index and type(index) == "string")
70 assert(data and type(data) == "string")
72 while true do
73 local idx, ofs, len, rlink
74 idx, cofs = read_adaptint(index, cofs)
75 if idx == 0 then return end
76 ofs, cofs = read_adaptint(index, cofs)
77 len, cofs = read_adaptint(index, cofs)
78 rlink, cofs = read_adaptint(index, cofs)
80 if idx == item then
81 return strsub(data, ofs, ofs + len)
82 end
84 if idx < item then cofs = cofs + rlink end
85 end
86 end
88 local initted = false
89 function DB_Init()
90 QuestHelper: Assert(not initted)
91 for _, db in ipairs(QHDB) do
92 for _, v in pairs(db) do
93 --print("db", not not v.__dictionary, not not v.__tokens)
94 if v.__dictionary and v.__tokens then
95 local redictix = v.__dictionary
96 if not redictix:find("\"") then redictix = redictix .. "\"" end
97 if not redictix:find(",") then redictix = redictix .. "," end
98 if not redictix:find("\\") then redictix = redictix .. "\\" end
99 local tokens = loadstring("return {" .. QH_LZW_Decompress_Dicts_Arghhacky(v.__tokens, redictix) .. "}")()
100 QuestHelper: Assert(tokens)
102 local _, _, prep = QH_LZW_Prepare_Arghhacky(v.__dictionary, tokens)
103 QuestHelper: Assert(prep)
105 QuestHelper: Assert(type(prep) == "table")
107 v.__tokens = prep
111 initted = true
112 QH_UpdateQuests() -- just in case it's been waiting on us (it has almost certainly been waiting on us)
115 function DB_Ready()
116 return initted
119 function DB_HasItem(group, id)
120 QuestHelper: Assert(initted)
122 for _, db in ipairs(QHDB) do
123 if db[group] then
124 if db[group][id] then
125 return true
128 if type(id) == "number" and id > 0 and db[group].__serialize_index and db[group].__serialize_data and search_index(db[group].__serialize_index, db[group].__serialize_data, id) then
129 return true
134 return false
137 function DB_GetItem(group, id, silent, register)
138 QuestHelper: Assert(initted)
140 QuestHelper: Assert(group, string.format("%s %s", tostring(group), tostring(id)))
141 QuestHelper: Assert(id, string.format("%s %s", tostring(group), tostring(id)))
142 local ite = DBC_Get(group, id)
144 if not ite then
145 if type(id) == "string" then QuestHelper: Assert(not id:match("__.*")) end
147 --QuestHelper:TextOut(string.format("%s %d", group, id))
149 for _, db in ipairs(QHDB) do
150 --print(db, db[group], db[group] and db[group][id], type(group), type(id))
151 if db[group] then
152 local dat
153 if db[group][id] then
154 dat = db[group][id]
157 --print(not dat, type(id), id, not not db[group].__serialize_index, not not db[group].__serialize_index)
158 if not dat and type(id) == "number" and id > 0 and db[group].__serialize_index and db[group].__serialize_data then
159 dat = search_index(db[group].__serialize_index, db[group].__serialize_data, id)
162 if dat then
163 if not ite then ite = QuestHelper:CreateTable("db") end
165 local srctab
167 if type(dat) == "string" then
168 QuestHelper: Assert(db[group].__tokens == nil or type(db[group].__tokens) == "table")
169 srctab = loadstring("return {" .. (db[group].__prefix or "") .. QH_LZW_Decompress_Dicts_Prepared_Arghhacky(dat, db[group].__dictionary, nil, db[group].__tokens) .. (db[group].__suffix or "") .. "}")()
170 elseif type(dat) == "table" then
171 srctab = dat
172 else
173 QuestHelper: Assert()
176 for k, v in pairs(srctab) do
177 QuestHelper: Assert(not ite[k] or k == "used")
178 ite[k] = v
184 if ite then
185 --print("marking", group, id, silent, register)
186 mark(ite, ite)
187 --print("done marking")
189 DBC_Put(group, id, ite)
191 freq_group[ite] = group
192 freq_id[ite] = id
193 else
194 if not silent then
195 QuestHelper:TextOut(string.format("Tried to get %s/%s, failed", tostring(group), tostring(id)))
200 if ite then
201 frequencies[ite] = (frequencies[ite] or 0) + (register and 1 or 1000000000) -- effectively infinity
204 return ite
207 local function incinerate(ite, crunchy)
208 if dev_mode then return end -- wellllp
210 if not crunchy[ite] then
211 crunchy[ite] = true
213 for k, v in pairs(ite) do
214 if type(k) == "table" then incinerate(k, crunchy) end
215 if type(v) == "table" then incinerate(v, crunchy) end
220 function DB_ReleaseItem(ite)
221 QuestHelper: Assert(ite)
222 frequencies[ite] = frequencies[ite] - 1
224 if frequencies[ite] == 0 then
225 --print("incinerating", freq_group[ite], freq_id[ite])
226 cache[freq_group[ite]][freq_id[ite]] = nil
227 freq_group[ite] = nil
228 freq_id[ite] = nil
230 local incin = QuestHelper:CreateTable("incinerate")
231 incinerate(ite, incin)
232 for k, _ in pairs(incin) do
233 QuestHelper:ReleaseTable(k)
234 end -- burn baby burn
235 QuestHelper:ReleaseTable(incin)
239 function DB_ListItems(group)
240 local tab = {}
241 for _, db in ipairs(QHDB) do
242 if db[group] then
243 QuestHelper: Assert(not db.__serialize_index and not db.__serialize_data)
244 for k, _ in pairs(db[group]) do
245 if type(k) ~= "string" or not k:match("__.*") then
246 tab[k] = true
252 local rv = {}
253 for k, _ in pairs(tab) do
254 table.insert(rv, k)
257 return rv
260 function DB_how_many_are_used()
261 local count = 0
262 for k, v in pairs(cache) do
263 for k2, v2 in pairs(v) do
264 count = count + 1
267 print(count)
270 function DB_DumpItems()
271 local dt = {}
272 for k, v in pairs(freq_group) do
273 dt[string.format("%s/%s", freq_group[k], tostring(freq_id[k]))] = true
275 return dt