You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
251 lines
6.3 KiB
251 lines
6.3 KiB
local w3xparser = require 'w3xparser'
|
|
local progress = require 'progress'
|
|
|
|
local table_insert = table.insert
|
|
local table_sort = table.sort
|
|
local table_concat = table.concat
|
|
local string_char = string.char
|
|
local math_type = math.type
|
|
local math_floor = math.floor
|
|
local wtonumber = w3xparser.tonumber
|
|
local type = type
|
|
local pairs = pairs
|
|
local setmetatable = setmetatable
|
|
local os_clock = os.clock
|
|
|
|
local w2l
|
|
local has_level
|
|
local metadata
|
|
local hexs
|
|
local wts
|
|
local ttype
|
|
|
|
local displaytype = {
|
|
unit = '单位',
|
|
ability = '技能',
|
|
item = '物品',
|
|
buff = '魔法效果',
|
|
upgrade = '科技',
|
|
doodad = '装饰物',
|
|
destructable = '可破坏物',
|
|
}
|
|
|
|
local function get_displayname(o)
|
|
local name
|
|
if o._type == 'buff' then
|
|
name = o.bufftip or o.editorname or ''
|
|
elseif o._type == 'upgrade' then
|
|
name = o.name[1] or ''
|
|
else
|
|
name = o.name or ''
|
|
end
|
|
return o._id, (name:sub(1, 100):gsub('\r\n', ' '))
|
|
end
|
|
|
|
local function format_value(value)
|
|
if type(value) == 'table' then
|
|
local tbl = {}
|
|
for i = 1, 4 do
|
|
if value[i] then
|
|
tbl[i] = ('[%d]: %s'):format(i, tostring(value[i]):sub(1, 25):gsub('\r\n', ' '))
|
|
end
|
|
end
|
|
return table_concat(tbl, ' ')
|
|
else
|
|
return tostring(tip):sub(1, 100):gsub('\r\n', ' ')
|
|
end
|
|
end
|
|
|
|
local function report(reason, obj, key, tip)
|
|
message('-report|6%s', ('%s %s %s'):format(reason, displaytype[ttype], get_displayname(obj)))
|
|
message('-tip', ('[%s]: %s'):format(key, format_value(tip)))
|
|
end
|
|
|
|
local function write(format, ...)
|
|
hexs[#hexs+1] = (format):pack(...)
|
|
end
|
|
|
|
local function write_value(meta, level, value)
|
|
local id = meta.id
|
|
local tp = meta.type
|
|
write('c4l', id .. ('\0'):rep(4 - #id), tp)
|
|
if has_level then
|
|
write('l', level)
|
|
write('l', meta.data or 0)
|
|
end
|
|
if tp == 0 then
|
|
if math_type(value) ~= 'integer' then
|
|
value = math_floor(wtonumber(value))
|
|
end
|
|
write('l', value)
|
|
elseif tp == 1 or tp == 2 then
|
|
if type(value) ~= 'number' then
|
|
value = wtonumber(value)
|
|
end
|
|
write('f', value)
|
|
else
|
|
if #value > 1023 then
|
|
value = w2l:save_wts(wts, value, '物编里的文本长度超过1023字符')
|
|
end
|
|
write('z', value)
|
|
end
|
|
write('c4', '\0\0\0\0')
|
|
end
|
|
|
|
local function write_data(key, data, meta)
|
|
if meta['repeat'] then
|
|
if type(data) ~= 'table' then
|
|
data = {data}
|
|
end
|
|
end
|
|
if type(data) == 'table' then
|
|
local max_level = 0
|
|
for level in pairs(data) do
|
|
if level > max_level then
|
|
max_level = level
|
|
end
|
|
end
|
|
for level = 1, max_level do
|
|
if data[level] then
|
|
write_value(meta, level, data[level])
|
|
end
|
|
end
|
|
else
|
|
write_value(meta, 0, data)
|
|
end
|
|
end
|
|
|
|
local function write_object(chunk, name, obj)
|
|
if #name ~= 4 then
|
|
message('-report|6无效的物编对象', ('[%s] %s'):format(name, '对象ID不合法'))
|
|
return
|
|
end
|
|
local keys = {}
|
|
local metas = {}
|
|
for key in pairs(obj) do
|
|
if key:sub(1, 1) ~= '_' then
|
|
keys[#keys+1] = key
|
|
end
|
|
end
|
|
local code = obj._code
|
|
if metadata[ttype] then
|
|
for key, meta in pairs(metadata[ttype]) do
|
|
metas[key] = meta
|
|
end
|
|
end
|
|
if metadata[code] then
|
|
for key, meta in pairs(metadata[code]) do
|
|
metas[key] = meta
|
|
end
|
|
end
|
|
table_sort(keys)
|
|
|
|
local count = 0
|
|
for _, key in ipairs(keys) do
|
|
local data = obj[key]
|
|
if data then
|
|
if type(data) == 'table' then
|
|
for _ in pairs(data) do
|
|
count = count + 1
|
|
end
|
|
else
|
|
count = count + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
local parent = obj._parent
|
|
if name == parent or obj._slk then
|
|
write('c4', name)
|
|
write('c4', '\0\0\0\0')
|
|
else
|
|
write('c4', parent)
|
|
write('c4', name)
|
|
end
|
|
write('l', count)
|
|
for _, key in ipairs(keys) do
|
|
local data = obj[key]
|
|
if data then
|
|
if metas[key] then
|
|
write_data(key, obj[key], metas[key])
|
|
else
|
|
report('-report|6无效的物编数据', obj, key, obj[key])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local function write_chunk(names, data, n, max)
|
|
local clock = os_clock()
|
|
write('l', #names)
|
|
for i, name in ipairs(names) do
|
|
write_object(data, name, data[name])
|
|
if os_clock() - clock > 0.1 then
|
|
clock = os_clock()
|
|
progress((i+n) / max)
|
|
message(('正在转换%s: [%s] (%d/%d)'):format(ttype, data[name]._id, i+n, max))
|
|
end
|
|
end
|
|
end
|
|
|
|
local function write_head()
|
|
write('l', 2)
|
|
end
|
|
|
|
local function is_enable_obj(obj, remove_unuse_object)
|
|
if remove_unuse_object and not obj._mark then
|
|
return false
|
|
end
|
|
if not obj._slk and obj._id ~= obj._parent then
|
|
return true
|
|
end
|
|
for key, value in pairs(obj) do
|
|
if key:sub(1, 1) ~= '_' then
|
|
if type(value) == 'table' then
|
|
if next(value) then
|
|
return true
|
|
end
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function sort_chunk(chunk, remove_unuse_object)
|
|
local origin = {}
|
|
local user = {}
|
|
for name, obj in pairs(chunk) do
|
|
if is_enable_obj(obj, remove_unuse_object) then
|
|
local parent = obj._parent
|
|
if name == parent or obj._slk then
|
|
origin[#origin+1] = name
|
|
else
|
|
user[#user+1] = name
|
|
end
|
|
end
|
|
end
|
|
table_sort(origin)
|
|
table_sort(user)
|
|
return origin, user
|
|
end
|
|
|
|
return function (w2l_, type, data, wts_)
|
|
w2l = w2l_
|
|
wts = wts_
|
|
ttype = type
|
|
has_level = w2l.info.key.max_level[type]
|
|
metadata = w2l:metadata()
|
|
|
|
local origin_id, user_id = sort_chunk(data, w2l.config.remove_unuse_object)
|
|
local max = #origin_id + #user_id
|
|
if max == 0 then
|
|
return
|
|
end
|
|
hexs = {}
|
|
write_head()
|
|
write_chunk(origin_id, data, 0, max)
|
|
write_chunk(user_id, data, #origin_id, max)
|
|
return table_concat(hexs), report
|
|
end
|
|
|