%%---------------------------------------------------- %% 战场配置数据处理 %% @author yeahoo2000@gmail.com %% @end %%---------------------------------------------------- -module(main). -export([ compile/1 ,gen_lua/0 ] ). -include("common.hrl"). -include("battle.hrl"). -define(SRV_PATH, "../../server/src/"). -define(LUA_PATH, "./lua/"). -define(ul2b(S), unicode:characters_to_binary(S)). -define(ub2l(S), unicode:characters_to_list(S)). %% ---------------------------------------------------- %% 外部接口 %% ---------------------------------------------------- compile(all) -> io:setopts([{encoding,unicode}]), ?P("---------------------------------~n"), ?P("> 正在编译战场配置数据...~n"), ?P("---------------------------------~n"), List = cfg_file(), all(List); compile(Name) -> Mod = list_to_atom(Name), B = Mod:cfg(), gen_data(B). %% 生成战场编辑工具lua配置文件 gen_lua() -> io:setopts([{encoding, unicode}]), ?P("---------------------------------~n"), ?P("> 正在生成战场编辑工具选项数据...~n"), ?P("---------------------------------~n"), UnitStr = ?S(" -- ------------------------------------ -- 战场编辑工具单位选项 -- ------------------------------------ BattleCfgUnits = { ~ts } ", [string:join([?S("\t{name=[[~ts]], desc=[[~ts]]}", [Name,Desc]) || #tpl_unit{name=Name, desc=Desc} <- battle_unit:list()], ",\n")]), case file:write_file(lists:concat([?LUA_PATH, "battle_cfg_unit.lua"]), format_str(UnitStr)) of ok -> ?P("> battle_cfg_unit.lua~n"); _Err -> ?P("生成battle_cfg_unit.lua数据时发生异常: ~w~n", [_Err]) end, ValStr = ?S(" -- ------------------------------------ -- 战场编辑工具变量选项 -- ------------------------------------ BattleCfgVals = { ~ts } ", [string:join([?S("\t{name=[[~ts]], desc=[[~ts]]}", [Name,Desc]) || #tpl_val{name=Name, desc=Desc} <- battle_val:list()], ",\n")]), case file:write_file(lists:concat([?LUA_PATH, "battle_cfg_val.lua"]), format_str(ValStr)) of ok -> ?P("> battle_cfg_val.lua~n"); _Err1 -> ?P("生成battle_cfg_val.lua数据时发生异常: ~w~n", [_Err1]) end, ActStr = ?S(" -- ------------------------------------ -- 战场编辑工具动作选项 -- ------------------------------------ BattleCfgActs = { ~ts } ", [string:join([?S("\t{name=[[~ts]], type=[[~w]], desc=[[~ts]]}", [Name, Type,Desc]) || #tpl_act{name=Name, type = Type, desc=Desc} <- battle_act:list()], ",\n")]), case file:write_file(lists:concat([?LUA_PATH, "battle_cfg_act.lua"]), format_str(ActStr)) of ok -> ?P("> battle_cfg_act.lua~n"); _Err2 -> ?P("生成battle_cfg_act.lua数据时发生异常: ~w~n", [_Err2]) end, CondStr = ?S(" -- ------------------------------------ -- 战场编辑工具条件选项 -- ------------------------------------ BattleCfgConds = { ~ts } ", [string:join([?S("\t{name=[[~ts]], desc=[[~ts]]}", [Name, Desc]) || #tpl_cond{name=Name, desc=Desc} <- battle_cond:list()], ",\n")]), case file:write_file(lists:concat([?LUA_PATH, "battle_cfg_cond.lua"]), format_str(CondStr)) of ok -> ?P("> battle_cfg_cond.lua~n"); _Err3 -> ?P("生成battle_cfg_cond.lua数据时发生异常: ~w~n", [_Err3]) end, FunStr = ?S(" -- ------------------------------------ -- 战场编辑工具方法选项 -- ------------------------------------ BattleCfgFuns = { ~ts } ", [string:join([?S("\t{name=[[~ts]], ret=[[~w]], label=[[~ts]], desc=[[~ts]]}", [Name, Ret, Label, Desc]) || #tpl_fun{name=Name, return = Ret, label = Label, desc=Desc} <- battle_fun:list()], ",\n")]), case file:write_file(lists:concat([?LUA_PATH, "battle_cfg_fun.lua"]), format_str(FunStr)) of ok -> ?P("> battle_cfg_fun.lua~n"); _Err4 -> ?P("生成battle_cfg_fun.lua数据时发生异常: ~w~n", [_Err4]) end, KVStr = ?S(" -- ------------------------------------ -- 战场编辑工具方法选项 -- ------------------------------------ BattleCfgKvs = { ~ts } ", [string:join([?S("\t~s={~ts}", [Name, string:join([?S("[[~ts]]", [K]) || {K,_V}<-L1], ", ")]) || {Name, L1} <- battle_kv:list()], ",\n")]), case file:write_file(lists:concat([?LUA_PATH, "battle_cfg_kv.lua"]), format_str(KVStr)) of ok -> ?P("> battle_cfg_kv.lua~n"); _Err5 -> ?P("生成battle_cfg_kv.lua数据时发生异常: ~w~n", [_Err5]) end, EvtStr = ?S(" -- ------------------------------------ -- 战场编辑工具方法选项 -- ------------------------------------ BattleCfgEvts = { ~ts } ", [string:join([?S("\t{name=[[~ts]], desc=[[~ts]]}", [Name, Desc]) || #tpl_evt{name=Name, desc=Desc} <- battle_evt:list()], ",\n")]), case file:write_file(lists:concat([?LUA_PATH, "battle_cfg_evt.lua"]), format_str(EvtStr)) of ok -> ?P("> battle_cfg_evt.lua~n"); _Err6 -> ?P("生成battle_cfg_evt.lua数据时发生异常: ~w~n", [_Err6]) end, ok. format_str(Str) -> unicode:characters_to_binary(Str). %% ---------------------------------------------------- %% 私有函数 %% ---------------------------------------------------- %% 处理所有配置文件 all([]) -> ok; all([H | T]) -> compile(H), all(T). %% 生成数据文件 gen_data(#battle_base{id = Id, name = Mod, type = Type, map = Map, unit = Unit, point = Point, region = Region, global = Global, trigger = L, enter_point = EnterPoint = {MapId,_,_}, combat_launcher = CombatLauncher}) -> Tri = gen_trigger(L, []), Vars = [ {description, "描述文字"} %% ,{cfg, util:tuplelist_to_record_string(?record_to_tuplelist(battle, Cfg))} ,{id, Id} ,{name, Mod} ,{type, Type} ,{enter_point, util:to_string(EnterPoint)} ,{map, util:to_string([MapId | lists:delete(MapId, Map)])} ,{unit, gen_unit(Unit)} ,{point, util:to_string(Point)} ,{region, util:to_string(Region)} ,{global, gen_val(Global)} ,{battle_trigger, do_trigger(L, [])} ,{mod_name, Mod} ,{trigger, Tri} ,{combat_launcher, CombatLauncher} ], %% Text = binary_to_list(unicode:characters_to_binary(util:template("./tpl/battle_data.tpl.erl", Vars))), Text = unicode:characters_to_binary(util:template("./tpl/battle_data.tpl.erl", Vars)), Path = lists:concat([?SRV_PATH, "mod/battle_data/", Mod, ".erl"]), %% ?P("====~s ~w~n", [Path, Text]), case file:write_file(Path, Text) of ok -> ?P("> ~ts.erl~n", [Mod]); Err -> ?P("生成战场配置数据[~ts]时发生异常: ~w~n", [Mod, Err]) end. %% 处理trigger数据 do_trigger([], Rtn) -> "[\n" ++ string:join(lists:reverse(Rtn), ",\n") ++ "\n ]"; do_trigger([#battle_trigger{name = Name, status = Status, event = Event, vars = Vars, condition = Conds} | T], Rtn) -> Cond = gen_cond(Conds), Evt = gen_evt(Event), S = io_lib:format(" #battle_trigger{name = \"~ts\",status = ~w,event = ~ts,vars = ~w,condition = ~ts}",[Name, to_status(Status), Evt, Vars, Cond]), do_trigger(T, [S | Rtn]). to_status(1) -> open; to_status(0) -> close; to_status(S) -> S. gen_unit(Unit) -> "[\n" ++ string:join(make_unit(Unit, []), ",\n ") ++ "\n ]". make_unit([], Rtn) -> lists:reverse(Rtn); make_unit([#cfg_unit{tpl = Name, cfg = Cfg} | T], Rtn) -> case battle_unit:get(Name) of {ok, #tpl_unit{code = Code, args = []}} -> S = io_lib:format(Code, []), make_unit(T, [S | Rtn]); {ok, #tpl_unit{code = Code, args = Args}} -> GetVal = gen_args(Args, Cfg, unit, []), S = io_lib:format(" "++Code, GetVal), make_unit(T, [S | Rtn]); Reason -> ?P("查找单位配置模板[~ts]时发生异常: ~w", [Name, Reason]), make_unit(T, Rtn) end. gen_evt(Event) -> "[" ++ string:join(make_evt(Event, []), ", ") ++ "]". make_evt([], Rtn) -> lists:reverse(Rtn); make_evt([#cfg_evt{tpl = Name, cfg = Cfg} | T], Rtn) -> case battle_evt:get(Name) of {ok, #tpl_evt{code = Code, args = []}} -> S = io_lib:format(Code, []), make_evt(T, [S | Rtn]); {ok, #tpl_evt{code = Code, args = Args}} -> Args0 = gen_args(Args, Cfg, evt, []), S = io_lib:format(Code, Args0), make_evt(T, [S | Rtn]); Reason -> ?P("查找事件模板[~ts]时发生异常: ~w~n", [Name, Reason]), make_evt(T, Rtn) end. gen_val(Event) -> "[\n" ++ string:join(make_val(Event, []), ",\n") ++ "\n ]". make_val([], Rtn) -> lists:reverse(Rtn); make_val([#cfg_val{tpl = Name, cfg = Cfg} | T], Rtn) -> case battle_val:get(Name) of {ok, #tpl_val{code = Code, args = []}} -> S = io_lib:format(Code, []), make_val(T, [S | Rtn]); {ok, #tpl_val{code = Code, args = Args}} -> GetVal = gen_args(Args, Cfg, val, []), S = io_lib:format(" "++Code, GetVal), make_val(T, [S | Rtn]); Reason -> ?P("查找事件模板[~ts]时发生异常: ~w~n", [Name, Reason]), make_val(T, Rtn) end. %% 生成触发器代码 gen_trigger([], Funs) -> lists:reverse(Funs); gen_trigger([#battle_trigger{name = Name, action = Act} | T], Funs) -> F = gen_action(Name, Act), gen_trigger(T, [F | Funs]). %% 生成action代码 gen_action(Name, Acts) -> ?S("trigger(\"~ts\") ->\n~ts,\n ok;\n\n", [Name, make_action(Acts, [])]). make_action([], Fun) -> string:join(lists:reverse(Fun), ",\n"); make_action([#cfg_act{tpl = Name, cfg = Cfg} | T], Fun) -> case battle_act:get(Name) of {error, Reason} -> ?P("查找动作模板[~ts]时发生异常: ~w~n", [Name, Reason]); {ok, #tpl_act{code = Code, args = Args}} -> Rtn = gen_args(Args, Cfg, act, []), case catch io_lib:format(" " ++ Code, Rtn) of {'EXIT', _} -> ?P("处理动作模板[~ts]时发生异常: ~ts 与 ~w 参数不匹配~n", [Name, Code, Rtn]), make_action(T, Fun); S -> make_action(T, [S | Fun]) end end. %% 获取所有的配置文件 cfg_file() -> case file:list_dir("./cfg") of {ok, L} -> do_cfg_file(L, []); {error, Why} -> ?P("获取战场配置文件时发生异常: ~w~n", [Why]), [] end. %% 返回所有的配置文件 do_cfg_file([], List) -> List; do_cfg_file([F | T], List) -> L = case filename:extension(F) =:= ".erl" of true -> M = filename:basename(filename:rootname(F)), [M | List]; _ -> List end, do_cfg_file(T, L). gen_cond(Conds) -> "[" ++ string:join(make_cond(Conds, []), ", ") ++ "]". make_cond([], Conds) -> lists:reverse(Conds); make_cond([#cfg_cond{tpl = Name, cfg = Cfg} | T], Conds) -> case battle_cond:get(Name) of {ok, #tpl_cond{code = Code, args = [condition]}} -> [{condition, Ncfg}] = Cfg, S = io_lib:format(Code, [gen_cond(Ncfg)]), make_cond(T, [S | Conds]); {ok, #tpl_cond{code = Code, args = Args}} -> Rtn = gen_args(Args, Cfg, condition, []), S = io_lib:format(Code, Rtn), make_cond(T, [S | Conds]); Reason -> ?P("查找条件模板[~ts]时发生异常: ~w~n", [Name, Reason]), make_cond(T, Conds) end. %% 参数处理 gen_args([], _, _Type, Args) -> lists:reverse(Args); gen_args([Key | T], CfgArgs, Type, Args) -> case find_args(Key, CfgArgs) of Evt = #cfg_evt{} -> Rtn = gen_evt([Evt]), gen_args(T, CfgArgs, Type, [Rtn | Args]); {pos, [Id, X, Y]} -> Rtn = io_lib:format("{~w, ~w, ~w}",[Id, X, Y]), gen_args(T, CfgArgs, Type, [Rtn | Args]); {gvar, GVar} -> Rtn = io_lib:format("get({global,~s})",[GVar]), gen_args(T, CfgArgs, Type, [Rtn | Args]); {action, []} -> Rtn = "\tskip", gen_args(T, CfgArgs, Type, [Rtn | Args]); {action, Acts} when is_list(Acts) -> Rtn = make_action(Acts, []), gen_args(T, CfgArgs, Type, [Rtn | Args]); {condition, Conds} when is_list(Conds) -> Rtn = gen_cond(Conds), gen_args(T, CfgArgs, Type, [Rtn | Args]); {key, KeyName, Val} -> case lists:keyfind(Val, 1, battle_kv:get(KeyName)) of {_, La} -> Rtn = case is_binary(La) of true -> io_lib:format("\"~ts\"", [La]); false -> util:to_list(La) end, gen_args(T, CfgArgs, Type, [Rtn | Args]); _ -> ?P("查找键值发送错误[~w]~n",[KeyName]), gen_args(T, CfgArgs, Type, Args) end; {func, Fname, CfgArgs0} when is_list(CfgArgs0) -> case battle_fun:get(Fname) of {error, Reason} -> ?P("~ts查找事件函数模板[~ts]时发生异常: ~w~n", [Key, Fname, Reason]), gen_args(T, CfgArgs, Type, Args); {ok, #tpl_fun{code = Code0, mfa_code = MfaCode, args = Args0}} -> Rtn = gen_args(Args0, CfgArgs0, func, []), Code = case Code0 of [_ | _] when Type =:= act orelse MfaCode =:= [] -> Code0; _ -> MfaCode end, case catch io_lib:format(Code, Rtn) of {'EXIT', _} -> ?P("~ts处理事件函数模板[~ts]时发生异常: ~ts 与 ~w 参数不匹配~n", [Key, Fname, Code, Rtn]), gen_args(T, CfgArgs, Type, Args); S -> gen_args(T, CfgArgs, Type, [S | Args]) end end; I -> gen_args(T, CfgArgs, Type, [util:to_list(I) | Args]) end. find_args(Key, Args) -> case lists:keyfind(Key,1, Args) of {Key, Val} -> Val; _ -> ?P("查找不到参数:~w ~n", [Key]), Key end.