Mercurial > wow > cyborg-mmo7
comparison support/casc/dbc.lua @ 65:8b8b0bade520
Fixed support for mounts using the new MountJournal and mount IDs (no conversion of old profiles at the moment).
author | Jerome Vuarand <jerome.vuarand@gmail.com> |
---|---|
date | Thu, 23 Oct 2014 13:44:59 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
64:49ae7191821f | 65:8b8b0bade520 |
---|---|
1 local M, bin = {}, require("casc.bin") | |
2 local assert, loadstring, smatch = assert, loadstring or load, string.match | |
3 | |
4 local uint32_le, int32_le, float32_le = bin.uint32_le, bin.int32_le, bin.float32_le | |
5 | |
6 local function unpacker(data, format, rows, stride, hsize, sbase, tfunc) | |
7 tfunc = type(tfunc) == "function" and tfunc or nil | |
8 | |
9 local skip, p, pe = 0, [=[-- casc.dbc:iterator | |
10 local smatch, uint32_le, int32_le, float32_le, tfunc, data, rows, stride, sbase, rpos, i = ... | |
11 return function() | |
12 if i < rows then | |
13 rpos, i = rpos + stride, i + 1 | |
14 return ]=] .. (tfunc and "tfunc(i" or "i"), (tfunc and ")" or "") .. '\nend\nend' | |
15 | |
16 for r, t in format:gmatch("(%d*)(.)") do | |
17 r = tonumber(r) or 1 | |
18 for i=1,r do | |
19 if t == '.' then | |
20 skip = skip + 4 * r | |
21 break | |
22 elseif t == 'u' then | |
23 p, skip = p .. ', uint32_le(data, rpos+' .. skip .. ')', skip + 4 | |
24 elseif t == 'i' then | |
25 p, skip = p .. ', int32_le(data, rpos+' .. skip .. ')', skip + 4 | |
26 elseif t == 'f' then | |
27 p, skip = p .. ', float32_le(data, rpos+' .. skip .. ')', skip + 4 | |
28 elseif t == 's' then | |
29 assert(sbase, "invalid signature: 's' requires a string block") | |
30 p, skip = p .. ', smatch(data, "%Z*", sbase + uint32_le(data,rpos+' .. skip .. '))', skip + 4 | |
31 else | |
32 error('Unknown signature field type "' .. t .. '"') | |
33 end | |
34 end | |
35 end | |
36 | |
37 return loadstring(p .. pe)(smatch, uint32_le, int32_le, float32_le, | |
38 tfunc, data, rows, stride, sbase, hsize - stride, 0), skip | |
39 end | |
40 | |
41 local header do | |
42 local function dbc(data) | |
43 assert(data:sub(1,4) == "WDBC", "DBC magic signature") | |
44 local rows, fields, stride, stringSize = uint32_le(data, 4), uint32_le(data, 8), uint32_le(data, 12), uint32_le(data, 16) | |
45 assert(20 + rows*stride + stringSize <= #data, "Data too short") | |
46 | |
47 return rows, fields, stride, 20, 21 + rows * stride | |
48 end | |
49 local function db2(data) | |
50 local hsize = 48 | |
51 local rows, fields, stride, stringSize = uint32_le(data, 4), uint32_le(data, 8), uint32_le(data, 12), uint32_le(data, 16) | |
52 local build, minId, maxId, locale, rid = uint32_le(data, 24), uint32_le(data, 32), uint32_le(data, 36), uint32_le(data, 40) | |
53 | |
54 if maxId > 0 then | |
55 local n, p = maxId-minId + 1, hsize | |
56 rid, hsize = {}, hsize + 6 * n | |
57 for i=1,n do | |
58 rid[i], p = uint32_le(data, p), p + 6 | |
59 end | |
60 end | |
61 assert(hsize + rows*stride + stringSize <= #data, "Data too short") | |
62 | |
63 return rows, fields, stride, hsize, hsize + 1 + rows * stride, rid, minId, maxId, build, locale | |
64 end | |
65 header = {WDBC=dbc, WDB2=db2, WCH2=db2} | |
66 end | |
67 | |
68 function M.header(data) | |
69 assert(type(data) == "string", 'Syntax: casc.dbc.header("data")') | |
70 local fourCC = data:sub(1,4) | |
71 return assert(header[fourCC], "Unsupported format")(data) | |
72 end | |
73 | |
74 function M.rows(data, sig, loose) | |
75 assert(type(data) == "string" and type(sig) == "string", 'Syntax: casc.dbc.rows("data", "rowSignature"[, loose])') | |
76 | |
77 local rows, _, stride, hsize, sbase, rid = M.header(data) | |
78 local iter, skip = unpacker(data, sig, rows, stride, hsize, sbase, rid and function(i, ...) return rid[i], ... end) | |
79 assert(skip <= stride, 'signature exceeds stride') | |
80 assert(loose or skip == stride, 'signature/stride mismatch') | |
81 | |
82 return iter | |
83 end | |
84 | |
85 return M |