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.

181 lines
5.1 KiB

inject_code = {}
-- 注入代码表
inject_code.new_table = {}
inject_code.old_table = {}
local root = fs.ydwe_path():parent_path():remove_filename():remove_filename() / "Component"
if not fs.exists(root) then
root = fs.ydwe_path()
end
function inject_code:inject_file(op, path_in_archive)
op.inject_file(root / "share" / "mpq" / "units" / path_in_archive, path_in_archive)
end
-- 侦测需要注入哪些代码
-- op.input - 脚本的路径,fs.path变量
-- op.option - 选项,table类型,支持成员:
-- runtime_version - 表示魔兽版本
-- 返回:一个table,数组形式,包含所有需要注入的文件名(注意不是fs.path)
function inject_code:detect(op)
-- 结果变量
local r = {}
-- 读入所有文本
local s, e = io.load(op.input)
-- 文件存在
if s then
-- 检查是否有需要注入的函数
local all_table = op.option.runtime_version:is_new() and self.new_table or self.old_table
for function_name, file in pairs(all_table) do
if not r[file] and s:find(function_name) then
r[file] = true
end
end
else
log.error("Error occured when opening map script.")
log.error(e)
end
return r
end
-- 注入代码到Jass代码文件(最常见的是war3map.j)中
-- op.output - war3map.j的路径,fs.path对象
-- tbl - 所有需要注入的代码文件路径,table,table中可以是
-- string - 此时为YDWE / "jass" 目录下的对应名称的文件
-- fs.path - 此时取其路径
-- 注:该table必须是数组形式的,哈希表形式的不处理
-- 返回值:0 - 成功;-1 - 出错失败;1 - 什么都没做
function inject_code:do_inject(op, tbl)
-- 结果
local result = 1
if tbl and next(tbl) then
-- 默认成功
result = 0
log.trace("Writing code to " .. op.output:filename():string())
-- 打开文件供写入(追加模式)
local map_script_file, e = io.open(op.output, "a+b")
if map_script_file then
-- 循环处理每个需要注入的文件
for path in pairs(tbl) do
log.trace("Injecting " .. path:string())
local code_content, e = io.load(path)
if code_content then
-- 插入代码到原文件最后
map_script_file:write(code_content)
-- 写上一个换行符(我日他妈的cJass你居然不支持Linux格式的换行符)
map_script_file:write("\r\n")
-- 成功
log.trace("Injection completed")
else
result = -1
log.error("Error occured when reading code to inject.")
log.error(e)
end
end
-- 关闭文件
map_script_file:close()
else
result = -1
log.error("Error occured when writing code to map script")
log.error(e)
end
end
return result
end
function inject_code:compile(op)
op.output = op.input
return self:do_inject(op, self:detect(op))
end
-- 扫描注入代码
-- config_dir - 需要扫描的路径
-- 返回值无,修改全局变量inject_code_table_new以及inject_code_table_old
-- inject_code_table_new - 新版(1.24)函数表
-- inject_code_table_old - 旧版函数表
function inject_code:scan(config_dir)
local counter = 0
log.trace("Scanning for inject files in " .. config_dir:string())
local once = {}
-- 遍历目录
for full_path in config_dir:list_directory() do
if fs.is_directory(full_path) then
-- 递归处理
counter = counter + self:scan(full_path)
elseif full_path:extension():string() == ".cfg" then
-- 插入新表
local new_table = {}
local old_table = {}
-- 解析状态,默认0
-- 0 - 1.24/1.20通用
-- 1 - 1.24专用
-- 2 - 1.20专用
local state = 0
-- 循环处理每一行
for line in io.lines(full_path) do
-- 插入函数名
local trimed = line:trim()
if trimed ~= "" and trimed:sub(1, 1) ~= "#" then
if trimed == "[general]" then
state = 0
elseif trimed == "[new]" then
state = 1
elseif trimed == "[old]" then
state = 2
else
if state == 0 then
table.insert(new_table, trimed)
table.insert(old_table, trimed)
elseif state == 1 then
table.insert(new_table, trimed)
elseif state == 2 then
table.insert(old_table, trimed)
end
end
end
end
-- 插入全局表中(替换文件扩展名)
local substitution = full_path
substitution = substitution:replace_extension(fs.path(".j"))
local function insert(file, a, b)
for _, fname in ipairs(a) do
if b[fname] then
local unuse = file
log.warn('注入函数['..fname..']重复定义')
if fs.last_write_time(file) > fs.last_write_time(b[fname]) then
unuse = b[fname]
b[fname] = file
end
if not once[fname] then
log.warn('注入函数['..fname..']重复定义')
log.warn(' 生效', b[fname], fs.last_write_time(b[fname]))
log.warn(' 失效', unuse, fs.last_write_time(unuse) )
once[fname] = true
end
else
b[fname] = file
end
end
end
insert(substitution, old_table, self.old_table)
insert(substitution, new_table, self.new_table)
counter = counter + 1
end
end
return counter
end
function inject_code:initialize()
local counter = self:scan(root / "jass")
log.trace(string.format("Scanned file: %d", counter))
end