SoUI 0.5版本占坑
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.

371 lines
9.7 KiB

3 years ago
local w3xparser = require 'w3xparser'
local progress = require 'progress'
local table_concat = table.concat
local ipairs = ipairs
local string_char = string.char
local pairs = pairs
local table_sort = table.sort
local table_insert = table.insert
local math_floor = math.floor
local wtonumber = w3xparser.tonumber
local select = select
local table_unpack = table.unpack
local os_clock = os.clock
local type = type
local next = next
local report
local w2l
local metadata
local keys
local remove_unuse_object
local object
local function to_type(tp, value)
if tp == 0 then
if not value or value == 0 then
return nil
end
return value
elseif tp == 1 or tp == 2 then
if not value or value == 0 then
return nil
end
return ('%.4f'):format(value):gsub('[0]+$', ''):gsub('%.$', '')
elseif tp == 3 then
if not value then
return
end
if value:find(',', nil, false) then
value = '"' .. value .. '"'
end
return value
end
end
local function get_index_data(tp, l, n)
local null
for i = n, 1, -1 do
local v = to_type(tp, l[i])
if v then
l[i] = v
null = ''
else
l[i] = null
end
end
if #l == 0 then
return
end
if tp == 3 then
for i = #l, 2, -1 do
if l[i] == l[i-1] then
l[i] = nil
else
break
end
end
end
return table_concat(l, ',')
end
local function add_data(obj, meta, value, keyval)
local key = meta.field
if meta.index then
-- TODO: 有点奇怪的写法
if meta.index == 1 then
local value = get_index_data(meta.type, {obj[meta.key..':1'], obj[meta.key..':2']}, 2)
if not value then
if meta.cantempty then
value = ','
else
return
end
end
keyval[#keyval+1] = {key:sub(1,-3), value}
end
return
end
if meta.appendindex then
if type(value) == 'table' then
local len = 0
for n in pairs(value) do
if n > len then
len = n
end
end
if len == 0 then
return
end
if len > 1 then
keyval[#keyval+1] = {key..'count', len}
end
local flag
for i = 1, len do
local key = key
if i > 1 then
key = key .. (i-1)
end
if value[i] then
flag = true
if meta.concat then
keyval[#keyval+1] = {key, value[i]}
else
keyval[#keyval+1] = {key, to_type(meta.type, value[i])}
end
end
end
if not flag then
keyval[#keyval] = nil
end
else
if not value then
return
end
if meta.concat then
keyval[#keyval+1] = {key, value}
else
keyval[#keyval+1] = {key, to_type(meta.type, value)}
end
end
return
end
if meta.concat then
if value and value ~= 0 then
keyval[#keyval+1] = {key, value}
end
return
end
if type(value) == 'table' then
if #value == 0 then
return
end
value = get_index_data(meta.type, value, #value)
else
value = to_type(meta.type, value)
end
if not value or value == '' then
if meta.cantempty then
value = ','
else
return
end
end
if value then
keyval[#keyval+1] = {key, value}
end
end
local function create_keyval(obj)
local keyval = {}
for _, key in ipairs(keys) do
if key ~= 'editorsuffix' and key ~= 'editorname' then
add_data(obj, metadata[key], obj[key], keyval)
end
end
return keyval
end
local function stringify_obj(str, obj)
local keyval = create_keyval(obj)
if #keyval == 0 then
return
end
table_sort(keyval, function(a, b)
return a[1]:lower() < b[1]:lower()
end)
local empty = true
str[#str+1] = ('[%s]'):format(obj._id)
for _, kv in ipairs(keyval) do
local key, val = kv[1], kv[2]
if val ~= '' then
if type(val) == 'string' then
val = val:gsub('\r\n', '|n'):gsub('[\r\n]', '|n')
end
str[#str+1] = key .. '=' .. val
empty = false
end
end
if empty then
str[#str] = nil
else
str[#str+1] = ''
end
end
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 displaytype[o._type], o._id, (name:sub(1, 100):gsub('\r\n', ' '))
end
local function report_failed(obj, key, tip, info)
report.n = report.n + 1
if not report[tip] then
report[tip] = {}
end
if report[tip][obj._id] then
return
end
local type, id, name = get_displayname(obj)
report[tip][obj._id] = {
("%s %s %s"):format(type, id, name),
("%s %s"):format(key, info),
}
end
local function check_string(s)
return type(s) == 'string' and s:find(',', nil, false) and s:find('"', nil, false)
end
local function prebuild_data(obj, key, r)
if not obj[key] then
return
end
local name = obj._id
if type(obj[key]) == 'table' then
object[name][key] = {}
local t = {}
for k, v in pairs(obj[key]) do
if check_string(v) then
report_failed(obj, metadata[key].field, '文本内容同时包含了逗号和双引号', v)
object[name][key][k] = v
else
t[k] = v
end
end
if not next(object[name][key]) then
object[name][key] = nil
end
r[key] = t
else
if check_string(obj[key]) then
report_failed(obj, metadata[key].field, '文本内容同时包含了逗号和双引号', obj[key])
object[name][key] = obj[key]
else
r[key] = obj[key]
end
end
end
local function prebuild_obj(name, obj)
if remove_unuse_object and not obj._mark then
return
end
local r = {}
for _, key in ipairs(keys) do
prebuild_data(obj, key, r)
end
if next(r) then
r._id = obj._id
return r
end
end
local function prebuild_merge(obj, a, b)
-- TODO: 需要处理a和b类型不一样的情况
if a._type ~= b._type then
local tp1, _, name1 = get_displayname(a)
local tp2, _, name2 = get_displayname(b)
message('-report|2警告', ('对象的ID冲突[%s]'):format(obj._id))
message('-tip', ('[%s]%s --> [%s]%s'):format(tp1, name1, tp2, name2))
end
for k, v in pairs(b) do
if k == '_id' or k == '_type' then
goto CONTINUE
end
if type(v) == 'table' then
if type(a[k]) == 'table' then
for i, iv in pairs(v) do
if a[k][i] ~= iv then
report_failed(obj, metadata[k].field, '文本内容和另一个对象冲突', '--> ' .. a._id)
if obj[k] then
obj[k][i] = iv
else
obj[k] = {[i] = iv}
end
end
end
else
report_failed(obj, metadata[k].field, '文本内容和另一个对象冲突', '--> ' .. a._id)
for i, iv in pairs(v) do
if obj[k] then
obj[k][i] = iv
else
obj[k] = {[i] = iv}
end
end
end
else
if a[k] ~= v then
report_failed(obj, metadata[k].field, '文本内容和另一个对象冲突', '--> ' .. a._id)
obj[k] = v
end
end
::CONTINUE::
end
end
local function prebuild(type, input, output, list)
for name, obj in pairs(input) do
local r = prebuild_obj(name, obj)
if r then
r._type = type
name = name:lower()
if output[name] then
prebuild_merge(obj, output[name], r)
else
output[name] = r
list[#list+1] = r._id
end
end
end
end
local function update_constant(type)
metadata = w2l:metadata()[type]
keys = w2l:keydata()[type]
end
return function(w2l_, slk, report_, obj)
w2l = w2l_
report = report_
remove_unuse_object = w2l.config.remove_unuse_object
local txt = {}
local list = {}
for _, type in ipairs {'ability', 'buff', 'unit', 'item', 'upgrade'} do
list[type] = {}
object = obj[type]
update_constant(type)
prebuild(type, slk[type], txt, list[type])
end
local r = {}
for _, type in ipairs {'ability', 'buff', 'unit', 'item', 'upgrade'} do
update_constant(type)
local str = {}
table_sort(list[type])
for _, name in ipairs(list[type]) do
stringify_obj(str, txt[name:lower()])
end
r[type] = table_concat(str, '\r\n')
end
return r
end