初版提交

This commit is contained in:
2025-09-24 00:54:08 +08:00
commit ca040bc2b9
15 changed files with 1129 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
# config.yaml
template_dir: "./examples"
file_patterns:
- "*.erl"
- "*.hrl"
output_file: "./generated/app.config"
template_file: "./examples/templates/config_template.tplerl"
ignore_dirs:
- ".git"
- "_build"
- "deps"
- "node_modules"
keywords:
- name: "config"
description: "配置项定义"
required: true
- name: "module"
description: "模块配置"
required: false
- name: "function"
description: "函数配置"
required: false
- name: "param"
description: "参数配置"
required: false
- name: "type"
description: "类型配置"
required: false
+43
View File
@@ -0,0 +1,43 @@
package config
type ErlangGeneratorCfg struct {
TemplateDir string `yaml:"template_dir" json:"template_dir"` // 模板文件存放地址
Keywords []ErlangTemKey `yaml:"keywords" json:"keywords"`
}
type ErlangTemKey struct {
MainTemplate string `yaml:"main_template" json:"main_template"` // 主模板
Filename string `yaml:"filename" json:"filename"` // _port.erl
OutputDir string `yaml:"output_dir" json:"output_dir"` // 输出地址
OutFileExt string `yaml:"out_file_ext" json:"out_file_ext"` // .cfg
DefaultArgs []DefaultArg `yaml:"default_args" json:"default_args"` // 默认模板参数
}
type DefaultArg struct {
Key string `yaml:"key" json:"key"`
Value string `yaml:"val" json:"Value"`
}
func DefaultErlConfig() *ErlangGeneratorCfg {
return &ErlangGeneratorCfg{
TemplateDir: "./templates",
Keywords: []ErlangTemKey{
{
MainTemplate: "port.tpl",
Filename: "*_port.erl",
OutputDir: "output",
OutFileExt: ".cfg",
DefaultArgs: []DefaultArg{
{
Key: "template",
Value: "_Z_SESSION",
},
{
Key: "project",
Value: "Project",
},
},
},
},
}
}
+42
View File
@@ -0,0 +1,42 @@
// config/generator_config.go
package config
type GeneratorConfig struct {
// 扫描配置
ScanDir string `yaml:"scan_dir" json:"scan_dir"`
FilePatterns []string `yaml:"file_patterns" json:"file_patterns"`
OutputFile string `yaml:"output_file" json:"output_file"`
// 注解关键词配置
Keywords []KeywordConfig `yaml:"keywords" json:"keywords"`
// 模板配置
TemplateFile string `yaml:"template_file" json:"template_file"`
// 忽略的目录
IgnoreDirs []string `yaml:"ignore_dirs" json:"ignore_dirs"`
}
type KeywordConfig struct {
Name string `yaml:"name" json:"name"`
Description string `yaml:"description" json:"description"`
Required bool `yaml:"required" json:"required"`
}
// 默认配置
func DefaultConfig() *GeneratorConfig {
return &GeneratorConfig{
ScanDir: "./",
FilePatterns: []string{"*.erl", "*.hrl"},
OutputFile: "./generated/app.config",
TemplateFile: "./templates/config_template.tplerl",
IgnoreDirs: []string{".git", "node_modules", "_build", "deps"},
Keywords: []KeywordConfig{
{Name: "config", Description: "配置项定义", Required: true},
{Name: "module", Description: "模块配置", Required: false},
{Name: "function", Description: "函数配置", Required: false},
{Name: "param", Description: "参数配置", Required: false},
{Name: "type", Description: "类型配置", Required: false},
},
}
}
+518
View File
@@ -0,0 +1,518 @@
%%%-------------------------------------------------------------------
%%% @author Administrator
%%% @copyright (C) 2022, <COMPANY>
%%% @doc
%%% 巅峰擂台 接口
%%% @end
%%% Created : 27. 9月 2022 10:09
%%%-------------------------------------------------------------------
-module(peak_arena_port).
-decription("peak_arena_port").
-copyright('youkia,www.youkia.net').
-author("yyh,yangyuhang@youkia.net").
-vsn(1).
%%%========================EXPORT========================
-export([get_info/5, update_state/5, get_last_show/5, get_stage_info/5, get_preliminaries_group_info/5, get_group_info/5,
get_guess_info/5, get_preliminaries_p_log/5, get_p_log/5, get_simulated_fight_info/5, join/5, fight/5, guess/5,
redistribution/5, simulated_fight/5, get_index_garray/5, get_fail_info/5,
get_preliminaries_follow_info/5, fight_follow/5, get_logs/5]).
%%%========================INCLUDE=======================
-include("cross.hrl").
-include("peak_arena.hrl").
-include("../../game/include/error_lib.hrl").
-include("../../game/include/array.hrl").
-include("fight_type.hrl").
-include("table.hrl").
%%%========================DEFINE========================
-define(IS_FAIL_0, 0). %%成功晋级
-define(IS_FAIL_1, 1). %%淘汰
%%%========================RECORD========================
%%%=================EXPORTED FUNCTIONS===================
%% ----------------------------------------------------
%% @GamePort(cmd=\game\peak_arena\get_info, desc=获取信息, reconnect=1)
%% @FunOpenCheck(fun_id=93)
%% @PrePort(proto=pub_proto, message=single_int)
%% ----------------------------------------------------
get_info(_, _Session, Attr, Info, _Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
PABase = peak_arena_db:get_base(Src, ServerId),
Term = peak_arena_base:get_term(PABase),
ActivityTime = peak_arena_db:get_active_time(ServerId),
ActivityTime == none andalso ?ThrowErr("fun_open_limit"),
AlPlayer = peak_arena_db:refresh_player(Src, RoleUid, ServerId, Term),
Reply = peak_arena_pb_lib:format_player_info({Src, RoleUid, ServerId, PABase, ActivityTime, AlPlayer, Term}),
{ok, [], Info, [{gpb, pro_peak_arena, Reply}]}.
%% ----------------------------------------------------
%% Description: 获取玩家自己的淘汰信息
%% ----------------------------------------------------
get_fail_info(_, _Session, Attr, Info, _Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
PABase = peak_arena_db:get_base(Src, ServerId),
PlayerInfo = peak_arena_db:get_player_info(Src, RoleUid, ServerId),
FinalId = player_peak_arena:get_final_id(PlayerInfo),
{WinList, _FailList} = peak_arena_base:get_final_info(PABase),
IsFail = case lists:keyfind(FinalId, 1, WinList) of
false ->
?IS_FAIL_1;
_ ->
?IS_FAIL_0
end,
{ok, [], Info, [{gpb, pro_peak_arena, pro_peak_arena:init_s2c_role_fail_info(IsFail)}]}.
%% ----------------------------------------------------
%% Description: 报名
%% ----------------------------------------------------
join(_, _Session, Attr, Info, _Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
Reply = peak_arena_db:join(Src, RoleUid, ServerId),
{ok, [], Info, Reply}.
%% ----------------------------------------------------
%% Description: 获取海选赛分组信息
%% @GamePort(cmd=\game\peak_arena\get_preliminaries_group_info, desc=获取海选赛分组信息, pre_proto=pub_proto, pre_message=single_int)
%% ----------------------------------------------------
get_preliminaries_group_info(_, _Session, Attr, Info, Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
RoleUid = role_lib:get_uid(Attr),
ServerId = role_lib:get_server_id(Attr),
PB = z_lib:get_value(Msg, de_gpb, none),
GroupId = pub_proto:get_single_int_item(PB),
PABase = peak_arena_db:get_base(Src, ServerId),
Reply = peak_arena_pb_lib:format_preliminaries_group_info({Src, PABase, GroupId, RoleUid, ServerId}),
{ok, [], Info, [{gpb, pro_peak_arena, Reply}]}.
%% ----------------------------------------------------
%% Description: 获取海选赛分组追随者信息
%% ----------------------------------------------------
get_preliminaries_follow_info(_, _Session, Attr, Info, Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
RoleUid = role_lib:get_uid(Attr),
ServerId = role_lib:get_server_id(Attr),
PB = z_lib:get_value(Msg, de_gpb, none),
GroupId = pub_proto:get_kv_int_k(PB),
ChampionId = pub_proto:get_kv_int_v(PB),
[?ThrowErr("args_err") || (not lists:member(GroupId, ?PEAK_GROUPS_2) orelse (not lists:member(ChampionId, ?ALL_INDEX)))],
FollowList = peak_arena_db:get_follow_info(ServerId, GroupId, ChampionId),
LanguageType = language_lib:get_language_by_type(RoleUid, ServerId),
%% 追随者数据
F = fun
(Index, Acc) ->
FollowUid = case lists:keyfind(Index, 1, FollowList) of
{Index, ItemRoleUid} -> ItemRoleUid;
_ -> 0
end,
case peak_arena_pb_lib:format_i_arena_follow_show(Src, ServerId, FollowUid, LanguageType, Index, GroupId, ChampionId) of
none -> Acc;
ItemPb -> [ItemPb | Acc]
end
end,
{_, FollowSum} = zm_config:get(peak_arena_info, follow_sum),
Reply = lists:foldl(F, [], lists:seq(1, FollowSum)),
%% 获取擂主数据
PABase = peak_arena_db:get_base(Src, ServerId),
Winner = peak_arena_base:get_preliminaries_winner(PABase),
{_, WinnerPlayerL} = lists:keyfind(GroupId, 1, Winner),
{_, ChampionRoleUid, _ServerId} = lists:keyfind(ChampionId, 1, WinnerPlayerL),
ChampionPb = peak_arena_pb_lib:format_i_arena_champion_show(Src, ChampionRoleUid, ServerId, ChampionId),
{ok, [], Info, [{gpb, pro_peak_arena, pro_peak_arena:init_s2c_peak_arena_group_follow_info(ChampionPb, Reply)}]}.
%% ----------------------------------------------------
%% @Cmd(cmd=/game/peak_arena/fight_follow, desc=追随者战斗)
%% @Decode(mod=pro_peak_arena, message=c2s_peak_arena_fight_follow)
%% @FunOpenCheck(open_id=72)
%% ----------------------------------------------------
fight_follow(_, _Session, Attr, Info, Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
PB = z_lib:get_value(Msg, de_gpb, none),
GroupId = pro_peak_arena:get_c2s_peak_arena_fight_follow_group_id(PB),
Index = pro_peak_arena:get_c2s_peak_arena_fight_follow_index(PB),
FollowId = pro_peak_arena:get_c2s_peak_arena_fight_follow_follow_id(PB),
FightScene = pro_peak_arena:get_c2s_peak_arena_fight_follow_fight_scene(PB),
{_, FollowSum} = zm_config:get(peak_arena_info, follow_sum),
[?ThrowErr("args_err") || (not lists:member(Index, ?ALL_INDEX) orelse (FollowId > FollowSum) orelse FollowId < 0)],
Reply = peak_arena_db:fight_follow(Src, RoleUid, ServerId, GroupId, Index, FollowId, FightScene),
{ok, [], Info, [{gpb, pro_peak_arena, Reply}]}.
%% ----------------------------------------------------
%% @Cmd(cmd=/game/peak_arena/get_logs, desc=日志)
%% ----------------------------------------------------
get_logs(_, _Session, Attr, Info, _Msg) ->
%% Src = z_lib:get_value(Info, 'src', 'none'),
%% ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
Logs = peak_arena_db:get_logs(RoleUid),
Reply = peak_arena_pb_lib:format_log(Logs),
{ok, [], Info, [{gpb, pro_peak_arena, pro_peak_arena:init_s2c_peak_arena_logs(Reply)}]}.
%% ----------------------------------------------------
%% Description: 获取海选赛位置阵容数据
%% ----------------------------------------------------
get_index_garray(_, _Session, Attr, Info, Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
PB = z_lib:get_value(Msg, de_gpb, none),
RoleUid = role_lib:get_uid(Attr),
Index = pub_proto:get_single_int_item(PB),
PABase = peak_arena_db:get_base(Src, ServerId),
Reply = peak_arena_pb_lib:format_index_garray({Src, ServerId, RoleUid, PABase, Index, ServerId}),
{ok, [], Info, [{gpb, pro_peak_arena, Reply}]}.
%% ----------------------------------------------------
%% Description: 获取晋级赛分组信息
%% ----------------------------------------------------
get_group_info(_, _Session, Attr, Info, Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
RoleUid = role_lib:get_uid(Attr),
ServerId = role_lib:get_server_id(Attr),
PB = z_lib:get_value(Msg, de_gpb, none),
GroupId = pub_proto:get_single_int_item(PB),
PABase = peak_arena_db:get_base(Src, ServerId),
ActivityTime = peak_arena_db:get_active_time(ServerId),
Stage = time_peak_arena:get_stage(ActivityTime),
FightIds =
if
GroupId >= 1 andalso GroupId =< 8 ->
F = fun(R, I) ->
List = peak_arena_lib:get_fight_ids({I, GroupId}),
List ++ R
end,
z_lib:for(F, [], 1, Stage + 2);%%多取一场,因为下一阶段的战斗已被生成,则也需要显示
GroupId =:= 9 ->
[?ThrowErr("pa_stage_err") || Stage < ?Legend_Stage5],
F = fun(R, I) ->
List = peak_arena_lib:get_fight_ids({I, GroupId}),
List ++ R
end,
z_lib:for(F, [], 1, Stage + 2);
true ->
?ThrowErr("pa_group_id_err")
end,
FinalIds =
case GroupId of
?PEAK_GROUP_9 ->%%冠军组的finalId为8强
{StartId, EndId} = peak_arena_lib:stage_2_fight_id(?Legend_Stage5),
FightIng = peak_arena_base:get_fight_ing(PABase),
FightEd = peak_arena_base:get_fight_ed(PABase),
F2 = fun(FightItem, Acc) ->
FightId = fight_peak_arena:get_fight_id(FightItem),
if
FightId >= StartId andalso FightId =< EndId ->
FightId1 = fight_peak_arena:get_final_id1(FightItem),
FightId2 = fight_peak_arena:get_final_id2(FightItem),
[FightId1, FightId2 | Acc];
true ->
Acc
end
end,
lists:foldl(F2, [], FightIng ++ FightEd);
_ ->
{_, FinalIds0} = lists:keyfind(GroupId, 1, ?PEAK_ARENA_GROUP),
FinalIds0
end,
MyGroup = player_peak_arena:get_group(peak_arena_db:get_player_info(Src, RoleUid, ServerId)),
{Index, FollowId} = peak_arena_db:get_player_follow_monster_index(ServerId, MyGroup, RoleUid),
PreLiminar = peak_arena_base:get_preliminaries_winner(PABase),
%% 取出跟随数据
FollowRoleUid = if
Index =/= 0 ->
{_, IndexL} = lists:keyfind(MyGroup, 1, PreLiminar),
{_, ItemRoleUid, _} = lists:keyfind(Index, 1, IndexL),
ItemRoleUid;
true ->
0
end,
Reply = peak_arena_pb_lib:format_group_info({Src, FightIds, FinalIds, PABase, FollowRoleUid, FollowId}),
%% io:format("(st@~p)~p>Re:~p~n", [?MODULE, ?LINE, {MyGroup, Reply}]),
{ok, [], Info, [{gpb, pro_peak_arena, Reply}]}.
%% ----------------------------------------------------
%% Description: 挑战对手/登擂
%% ----------------------------------------------------
fight(_, _Session, Attr, Info, Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
PB = z_lib:get_value(Msg, de_gpb, none),
Index = pub_proto:get_kv_int_k(PB),
BattleSceneModel = pub_proto:get_kv_int_v(PB),
peak_arena_db:fight(Src, RoleUid, ServerId, Index, BattleSceneModel),
{ok, [], Info, game_lib:pb_str("ok")}.
%% ----------------------------------------------------
%% Description: 获取阶段
%% ----------------------------------------------------
get_stage_info(_, _Session, Attr, Info, _Msg) ->
ServerId = role_lib:get_server_id(Attr),
ActivityTime = peak_arena_db:get_active_time(ServerId),
Stage = time_peak_arena:get_stage(ActivityTime),
{ok, [], Info, game_lib:pb_int(Stage)}.
%% ----------------------------------------------------
%% Description: 换组
%% ----------------------------------------------------
redistribution(_, _Session, Attr, Info, _Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
NewGroup = peak_arena_db:redistribution(Src, RoleUid, ServerId),
{ok, [], Info, game_lib:pb_int(NewGroup)}.
%% ----------------------------------------------------
%% Description: 获取个人初赛战报
%% ----------------------------------------------------
get_preliminaries_p_log(_, _Session, Attr, Info, _Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
PlayerLogList = peak_arena_db:get_player_log(Src, RoleUid, ServerId),
Reply = peak_arena_pb_lib:format_player_log(PlayerLogList),
{ok, [], Info, [{gpb, pro_peak_arena, Reply}]}.
%% ----------------------------------------------------
%% Description: 修改状态
%% ----------------------------------------------------
update_state(_, _Session, Attr, Info, Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
PB = z_lib:get_value(Msg, de_gpb, none),
Type = pub_proto:get_single_int_item(PB),%% 1修改守擂, 2修改结算 3修改决赛弹窗
peak_arena_db:update_state(Src, RoleUid, ServerId, Type),
{ok, [], Info, game_lib:pb_str("ok")}.
%% ----------------------------------------------------
%% Description: 竞猜
%% ----------------------------------------------------
guess(_, _Session, Attr, Info, Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
PB = z_lib:get_value(Msg, de_gpb, none),
GuessFinalId = pub_proto:get_kv_int_k(PB),
Type = pub_proto:get_kv_int_v(PB),
Consume =
case zm_config:get(peak_arena_scuffle_guess, Type) of
{_, {Consume0, _, _}} -> Consume0;
_ -> ?ThrowErr("arg_err")
end,
Tables = consume_lib:get_consume_table(Src, RoleUid, ServerId, Consume, [{?PEAK_ARENA_GUESS_TABLE, ServerId, peak_arena_guess:init()},
{?PLAYER_PEAK_ARENA_TABLE, RoleUid, player_peak_arena:init()}]),
Args = {RoleUid, ServerId, GuessFinalId, Type, Consume},
case z_db_lib:dynamic(ServerId, fun peak_arena_db:guess/2, Args, Tables) of
{ok, ConsumeLog} ->
zm_event:notify(Src, 'war_token2_normal', {RoleUid, ServerId, war_token2_lib:convert(peak_arena, 1)}),
%%参与巅峰擂台收集事件
zm_event:notify(Src, fun_ok, {RoleUid, ServerId, [{peak_arena_action, 1}]}),
zm_event:notify(Src, consumes_awards_ok, [{role_uid, RoleUid}, {server_id, ServerId}, {consumes, ConsumeLog}, {act_method, peak_arena_guess}]),
BiList = [begin
BiMethod = {act_method, {peak_arena_guess, Type, GuessFinalId}},
bi_lib:init(consume_logs, ServerId, [{role_uid, RoleUid}, {logs, ConsumeLog}, BiMethod])
end || not consume_lib:log_is_empty(ConsumeLog)],
zm_event:notify(Src, bi_event, [bi_lib:init(sky_throne_guess, ServerId, [{role_uid, RoleUid},
{final_id, GuessFinalId},
{guess_type, Type}]) | BiList]),
Replay = data_pb_lib:format_log(none, ConsumeLog),
{ok, [], Info, [{gpb, pro_prop, Replay}]};
Err ->
throw(Err)
end.
%% ----------------------------------------------------
%% Description:获取竞猜信息
%% ----------------------------------------------------
get_guess_info(_, _Session, Attr, Info, _Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
PABase = peak_arena_db:get_base(Src, ServerId),
PAPlayer = peak_arena_db:get_player_info(Src, RoleUid, ServerId),
GuessL = peak_arena_db:get_guess_info(Src, ServerId),
PATime = z_db_lib:get(z_db_lib:get_table(?PEAK_ARENA_TIME_TABLE), {?PA_Time_Key, ServerId}, 'none'),
Reply = peak_arena_pb_lib:format_guess_info({Src, PAPlayer, PABase, GuessL, PATime}),
{ok, [], Info, [{gpb, pro_peak_arena, Reply}]}.
%% ----------------------------------------------------
%% Description: 获取模拟赛对手信息
%% ----------------------------------------------------
get_simulated_fight_info(_, _Session, Attr, Info, _Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
PABase = peak_arena_db:get_base(Src, ServerId),
PAPlayer = peak_arena_db:get_player_info(Src, RoleUid, ServerId),
FinalId = player_peak_arena:get_final_id(PAPlayer),
FightPAL = peak_arena_base:get_fight_ing(PABase),
{WinList, LoseList} = peak_arena_base:get_final_info(PABase),
AllList = WinList ++ LoseList,
F = fun(R, Item) ->
FinalId1 = fight_peak_arena:get_final_id1(Item),
FinalId2 = fight_peak_arena:get_final_id2(Item),
case FinalId1 =:= FinalId orelse FinalId2 =:= FinalId of
true -> {break, Item};
false -> R
end
end,
R =
case z_lib:foreach(F, none, FightPAL) of
none ->%%没有模拟战对手
pro_peak_arena:init_i_simulated_fight_show("", 0, []);
FightPA ->
case fight_peak_arena:get_final_id1(FightPA) of
FinalId ->%%一号位,对手是二号
Id2 = fight_peak_arena:get_final_id2(FightPA),
Id2 =:= 0 andalso ?ThrowErr("peak_arena_tar_final_id_err"),
{_, RoleUid2, ServerId2} = lists:keyfind(Id2, 1, AllList),
Power2 = power_db:get_array_power(Src, RoleUid2, ServerId2, ?ARRAY_8),
{_, [Array2], _} = array_db:get_array(Src, RoleUid2, ServerId2, ?ARRAY_8, 1),
ArrayList = array_item:get_array(Array2),
CardStorage = card_db:get_card(Src, RoleUid2, ServerId2),
Role = role_db:get_role(Src, RoleUid2, ServerId2),
CardShow2 = [begin
CardProp = storage_lib:find_by_sid(CardStorage, CardSid),
CardRecord = prop_kit_lib:get_prop_record(CardProp),
LittleStar = card:get_little_star(CardRecord),
RoleLevel = role:get_level(Role),
Level = card_lib:get_level(CardRecord, RoleLevel),
LQ = card:get_quality_cultivate(CardRecord),
AwakenLv = card:get_awaken_lv(CardRecord),
Stage = card:get_stage(CardRecord),
pro_arena_legend:init_i_card_show(CardSid, LittleStar, Level, LQ, AwakenLv, Stage)
end || {_, {_, CardSid}} <- ArrayList],
Role2 = role_db:get_role(Src, RoleUid2, ServerId2),
Name2 = role:get_name(Role2),
pro_peak_arena:init_i_simulated_fight_show(Name2, Power2, CardShow2);
OtherFinalId ->%%对手是一号
OtherFinalId =:= 0 andalso ?ThrowErr("peak_arena_tar_final_id_err"),
{_, RoleUid1, ServerId1} = lists:keyfind(OtherFinalId, 1, AllList),
Power1 = power_db:get_array_power(Src, RoleUid1, ServerId1, ?ARRAY_8),
{_, [Array1], _} = array_db:get_array(Src, RoleUid1, ServerId1, ?ARRAY_8, 1),
ArrayList = array_item:get_array(Array1),
CardStorage = card_db:get_card(Src, RoleUid1, ServerId1),
Role = role_db:get_role(Src, RoleUid1, ServerId1),
CardShow1 = [begin
CardProp = storage_lib:find_by_sid(CardStorage, CardSid),
CardRecord = prop_kit_lib:get_prop_record(CardProp),
LittleStar = card:get_little_star(CardRecord),
RoleLevel = role:get_level(Role),
Level = card_lib:get_level(CardRecord, RoleLevel),
LQ = card:get_quality_cultivate(CardRecord),
AwakenLv = card:get_awaken_lv(CardRecord),
Stage = card:get_stage(CardRecord),
pro_arena_legend:init_i_card_show(CardSid, LittleStar, Level, LQ, AwakenLv, Stage)
end || {_, {_, CardSid}} <- ArrayList],
Role1 = role_db:get_role(Src, RoleUid1, ServerId1),
Name1 = role:get_name(Role1),
pro_peak_arena:init_i_simulated_fight_show(Name1, Power1, CardShow1)
end
end,
{ok, [], Info, [{gpb, pro_peak_arena, R}]}.
%% ----------------------------------------------------
%% Description: 获取4强
%% ----------------------------------------------------
get_last_show(_, _Session, Attr, Info, _Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
LastInfo = peak_arena_db:get_last_info(Src, ServerId),
Replay = peak_arena_pb_lib:format_last_show(LastInfo),
{ok, [], Info, [{gpb, pro_peak_arena, Replay}]}.
%% ----------------------------------------------------
%% Description: 获取决赛战报
%% ----------------------------------------------------
get_p_log(_, _Session, Attr, Info, Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
PB = z_lib:get_value(Msg, de_gpb, none),
Stage = pub_proto:get_single_int_item(PB),
{StartId, EndId} = peak_arena_lib:stage_2_fight_id(Stage),
PABase = peak_arena_db:get_base(Src, ServerId),
FightEd = peak_arena_base:get_fight_ed(PABase),
FightIng = peak_arena_base:get_fight_ing(PABase),
F = fun(FightPAInfo, Acc) ->
FightId = fight_peak_arena:get_fight_id(FightPAInfo),
if
FightId >= StartId andalso FightId =< EndId ->
FinalId1 = fight_peak_arena:get_final_id1(FightPAInfo),
FinalId2 = fight_peak_arena:get_final_id2(FightPAInfo),
if
FinalId1 =:= 0 andalso FinalId2 =:= 0 ->
Acc;
true ->
LogUid =
case fight_peak_arena:get_log_uids(FightPAInfo) of
[] -> 0;
[LogUid0] -> LogUid0
end,
Group = peak_arena_lib:fight_id_2_group(FightId),
{WinList, LoseList} = peak_arena_base:get_final_info(PABase),
RoleFun = fun
(FinalId) ->
case lists:keyfind(FinalId, 1, WinList ++ LoseList) of
false ->
[];
{_, RoleUid, ServerId} ->
Role1 = role_db:get_role(Src, RoleUid, ServerId),
Name1 = role:get_name(Role1),
Level1 = role:get_level(Role1),
Style = role:get_style(Role1),
Skin = role:get_skin(Role1),
Sex = role:get_sex(Role1),
AvatarBorder1 = role:get_avatar_border(Role1),
Player = pro_peak_arena:init_i_player_show(Style, AvatarBorder1, Level1, Name1, FinalId, RoleUid, Skin, Sex),
[Player]
end
end,
WinFinalId =
case fight_peak_arena:get_win_uids(FightPAInfo) of
[] -> 0;
[WinFinalId0] -> WinFinalId0
end,
Acc ++ [pro_peak_arena:init_i_pa_log(LogUid, Group, WinFinalId, RoleFun(FinalId1) ++ RoleFun(FinalId2))]
end;
true ->
Acc
end
end,
LogList = lists:foldl(F, [], FightIng ++ FightEd),
R = pro_peak_arena:init_s2c_pa_l_log(LogList),
{ok, [], Info, [{gpb, pro_peak_arena, R}]}.
%% ----------------------------------------------------
%% Description: 模拟战斗
%% ----------------------------------------------------
simulated_fight(_, _Session, Attr, Info, _Msg) ->
Src = z_lib:get_value(Info, 'src', 'none'),
ServerId = role_lib:get_server_id(Attr),
RoleUid = role_lib:get_uid(Attr),
[?ThrowErr("pa_fight_ing") || fs_server:api_check_fighting({role_uid, ServerId, RoleUid}, [{role_uid, RoleUid}])],
{_, BattleSceneModel} = zm_config:get(peak_arena_info, battle_scene),
PABase = peak_arena_db:get_base(Src, ServerId),
PlayerInfo = peak_arena_db:get_player_info(Src, RoleUid, ServerId),
FinalId = player_peak_arena:get_final_id(PlayerInfo),
[?ThrowErr("peak_arena_not_join_err") || FinalId =:= 0],%%没有参赛
FightIng = peak_arena_base:get_fight_ing(PABase),
F = fun(R, FightItem) ->
FinalId1 = fight_peak_arena:get_final_id1(FightItem),
FinalId2 = fight_peak_arena:get_final_id2(FightItem),
if
FinalId1 =:= FinalId -> {break, FinalId2};
FinalId2 =:= FinalId -> {break, FinalId1};
true -> R
end
end,
TarFinalId = z_lib:foreach(F, 0, FightIng),
[?ThrowErr("peak_arena_tar_final_id_err") || TarFinalId =:= 0],%%没有对手
{WinList, _} = peak_arena_base:get_final_info(PABase),
F2 = fun(R, {WinFinalId, WinRoleUid, WinServerId}) ->
if
WinFinalId =:= TarFinalId ->
{break, {WinRoleUid, WinServerId}};
true ->
R
end
end,
{TarUid, TarServerId} = z_lib:foreach(F2, {0, 0}, WinList),
[?ThrowErr("peak_arena_tar_final_id_err") || TarUid =:= 0 orelse TarServerId =:= 0],%%对手错误
peak_arena_db:pa_test_fight(Src, RoleUid, ServerId, TarUid, TarServerId, PABase, ?PEAK_ARENA_TYPE3, BattleSceneModel),
{ok, [], Info, game_lib:pb_str("ok")}.
+13
View File
@@ -0,0 +1,13 @@
%% examples/sample.erl
-module(sample).
-export([start/0, process/1]).
%% @function(type="init", timeout=5000)
%% @param(name="data", type="binary")
start() ->
ok.
%% @function(type="worker", concurrency=10)
%% @param(name="input", type="list")
process(Input) ->
{ok, processed}.
+36
View File
@@ -0,0 +1,36 @@
%% Generated Erlang Configuration
%% DO NOT EDIT MANUALLY - Generated by annotation generator
%%%------------------------------------获取基本信息------------------------------
{ template, _Z_SESSION, {Project, "/game/peak_arena/get_info", [
{peak_arena_port, get_info, []}
]}}.
%%%------------------------------------修改状态------------------------------
{ template, _Z_SESSION, {Project, "/game/peak_arena/update_state", [
{reconnect_db, msg_start, []},
{fun_open_check, check, [98]},
{pre_port, decode, [pub_proto, single_int]},
{peak_arena_port, update_state, []},
{reconnect_db, msg_end, []}
]}}.
%%%---------------------------------成就start---------------------------------
{local, Achieve, z_lib, to_atom, [Project, "/achieve"]}.
{template, _FILE_TABLE_GAME_GLOBAL, {achieve, Achieve}}.
%%%---------------------------------成就end---------------------------------
%%%---------------------------------成就点start---------------------------------
{local, AchievePoint, z_lib, to_atom, [Project, "/achieve_point"]}.
{template, _FILE_TABLE_GAME_GLOBAL, {achieve_point, AchievePoint}}.
%%%---------------------------------成就点end---------------------------------
%%%---------------------------------成就点背包start---------------------------------
{local, AchieveStorage, z_lib, to_atom, [Project, "/achieve_storage"]}.
{template, _FILE_TABLE_GAME_GLOBAL, {achieve_storage, AchieveStorage}}.
%%%---------------------------------成就点背包end---------------------------------
%%%---------------------------------成就点start---------------------------------
{local, AchieveInfo, z_lib, to_atom, [Project, "/achieve_info"]}.
{template, _FILE_TABLE_GAME_GLOBAL, {achieve_info, AchieveInfo}}.
%%%---------------------------------成就点end---------------------------------
+11
View File
@@ -0,0 +1,11 @@
%% ----------------------------------------------------------------------------------
{{if .desc}}%% {{hd .desc}} {{end}}
{template, _Z_SESSION, {Project, "{{hd .cmd}}", [
{{if .reconnect}} { reconnect_db, msg_start, [] },
{{end}} {{if .fun_id}}{ fun_open_check, check, [{{hd .fun_id}}] }, {{end}}
{{if .pre_message}} { pre_port, decode, [{{hd .pre_proto }}, {{hd .pre_message}}] }, {{end}}
{{if .reconnect}} { {{hd .module}}, {{hd .func}}, [{{join .args ","}}] },
{ reconnect_db, msg_end, [] } {{else}} { {{hd .module}}, {{hd .func}}, [] }
{{end}}
]}}.
%% -----------------------------------------------------------------------------------
+5
View File
@@ -0,0 +1,5 @@
module complie-erlang
go 1.23.4
require gopkg.in/yaml.v2 v2.4.0 // indirect
+3
View File
@@ -0,0 +1,3 @@
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+74
View File
@@ -0,0 +1,74 @@
// main.go
package main
import (
"complie-erlang/config"
"complie-erlang/parser"
tm "complie-erlang/template"
"fmt"
"log"
"os"
"strings"
"text/template"
)
func main() {
cfg := config.DefaultErlConfig()
templates := tm.NewTemplate()
if err := templates.Load(cfg.TemplateDir); err != nil {
log.Fatalf("loading templates: %v", err)
return
}
erlangFile, _ := parser.ParseErlangFile("E:\\gopackage2\\2025.7\\complie-erl\\examples\\peak_arena_port.erl")
// fmt.Printf("ParseErlangFile: %v, %v\n", erlangFile, err)
for _, function := range erlangFile.Functions {
if len(function.KeyMap) > 0 {
fmt.Printf("Function: %v %v \n", function.Name, function.KeyMap)
}
}
}
func main1() {
erlangFile, _ := parser.ParseErlangFile("E:\\gopackage2\\2025.7\\complie-erl\\examples\\peak_arena_port.erl")
// fmt.Printf("ParseErlangFile: %v, %v\n", erlangFile, err)
for _, function := range erlangFile.Functions {
if len(function.KeyMap) > 0 {
fmt.Printf("Function: %v %v \n", function.Name, function.KeyMap)
}
}
bytes, _ := os.ReadFile("E:\\gopackage2\\2025.7\\complie-erl\\examples\\templates\\port.tpl")
// 解析模板
t := template.Must(template.New("test").Funcs(template.FuncMap{
"hd": hd,
"title": strings.Title,
"join": strings.Join,
"list": func(strs []string) string { return strings.Join(strs, ",") },
}).Parse(string(bytes)))
// 执行模板,填充数据
var args = map[string]interface{}{
"cmd": []string{"\\game\\role_port\\get_info"},
"desc": []string{"获取数据1", "获取数据2"},
"module": []string{"peak_arena_port"},
"func": []string{"get_info"},
//"args": []string{"game", "1", "2"},
"reconnect": []string{"1"},
"fun_id": []string{"98"},
"pre_proto": []string{"pub_proto"},
"pre_message": []string{"single_int"},
}
err := t.Execute(os.Stdout, args)
fmt.Println(err)
}
func hd(str []string) string {
return str[0]
}
+58
View File
@@ -0,0 +1,58 @@
package parser
import (
"regexp"
"strings"
)
// ErlangFunction 表示 Erlang 函数
type ErlangFunction struct {
Name string // 函数名
Arity int // 参数个数
Parameters []string // 参数列表
Comments []string // 函数注释
StartLine int // 函数起始行号
EndLine int // 函数结束行号
Export bool // 是否被导出
KeyMap map[string]map[string][]string // 注解
}
func (function *ErlangFunction) ParseComments() ErlangFunction {
var keyMap = make(map[string]map[string][]string)
//var parameters = make(map[string]string)
for _, comment := range function.Comments {
// 匹配注解格式: @keyword(param1=value1, param2=value2)
re := regexp.MustCompile(`@(\w+)(?:\s*\((.*)\))?`)
matches := re.FindStringSubmatch(comment)
if len(matches) < 2 {
continue
}
keyword := matches[1]
parameters, is := keyMap[keyword]
if !is {
parameters = make(map[string][]string)
}
// 解析参数
if len(matches) > 2 && matches[2] != "" {
paramsStr := matches[2]
paramRe := regexp.MustCompile(`(\w+)\s*=\s*('[^']*'|"[^"]*"|[^,]+)`)
paramMatches := paramRe.FindAllStringSubmatch(paramsStr, -1)
for _, match := range paramMatches {
if len(match) >= 3 {
value := strings.TrimSpace(match[2])
// 移除引号
value = strings.Trim(value, `'"`)
parameters[strings.TrimSpace(match[1])] = append(parameters[strings.TrimSpace(match[1])], value)
}
}
}
keyMap[keyword] = parameters
}
function.KeyMap = keyMap
return *function
}
+175
View File
@@ -0,0 +1,175 @@
package parser
import (
"fmt"
"os"
"regexp"
"strings"
)
// ModuleInfo 表示 Erlang 模块信息
type ModuleInfo struct {
ModuleName string
Functions []ErlangFunction
FilePath string
}
// ParseErlangFile 解析 Erlang 文件
func ParseErlangFile(filePath string) (*ModuleInfo, error) {
content, err := os.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("读取文件失败: %v", err)
}
lines := strings.Split(string(content), "\n")
moduleInfo := &ModuleInfo{
FilePath: filePath,
}
// 提取模块名
moduleInfo.ModuleName = extractModuleName(lines)
// 提取导出函数列表
exportedFunctions := extractExportedFunctions(lines)
// 解析函数
moduleInfo.Functions = parseFunctions(lines, exportedFunctions)
return moduleInfo, nil
}
// 提取模块名
func extractModuleName(lines []string) string {
moduleRegex := regexp.MustCompile(`^-module\(([^)]+)\)\.`)
for _, line := range lines {
matches := moduleRegex.FindStringSubmatch(line)
if len(matches) > 1 {
return strings.Trim(matches[1], " '\"")
}
}
return ""
}
// 提取导出函数列表
func extractExportedFunctions(lines []string) map[string]bool {
exported := make(map[string]bool)
// 匹配 -export([...]) 格式
exportRegex := regexp.MustCompile(`-export\(\[([^]]+)]\)`)
functionRegex := regexp.MustCompile(`(\w+)/(\d+)`)
for _, line := range lines {
if matches := exportRegex.FindStringSubmatch(line); len(matches) > 1 {
exports := strings.Split(matches[1], ",")
for _, export := range exports {
export = strings.TrimSpace(export)
if funcMatches := functionRegex.FindStringSubmatch(export); len(funcMatches) > 2 {
functionKey := fmt.Sprintf("%s/%s", funcMatches[1], funcMatches[2])
exported[functionKey] = true
}
}
}
}
return exported
}
// 解析所有函数
func parseFunctions(lines []string, exportedFunctions map[string]bool) []ErlangFunction {
var functions []ErlangFunction
var currentComments []string
inFunction := false
var currentFunction ErlangFunction
braceCount := 0
parenCount := 0
for i, line := range lines {
trimmedLine := strings.TrimSpace(line)
// 收集注释
if strings.HasPrefix(trimmedLine, "%") {
comment := strings.TrimPrefix(trimmedLine, "%")
comment = strings.TrimSpace(comment)
currentComments = append(currentComments, comment)
continue
}
// 检测函数开始
if !inFunction && isFunctionStart(trimmedLine) {
if funcInfo := parseFunctionSignature(trimmedLine); funcInfo != nil {
inFunction = true
currentFunction = *funcInfo
currentFunction.Comments = append([]string(nil), currentComments...)
currentFunction.StartLine = i + 1
currentFunction.Export = isExported(currentFunction, exportedFunctions)
// 重置注释收集
currentComments = nil
braceCount = 0
parenCount = 0
}
}
if inFunction {
// 统计括号和花括号来检测函数结束
braceCount += strings.Count(line, "{") - strings.Count(line, "}")
parenCount += strings.Count(line, "(") - strings.Count(line, ")")
// 函数结束条件:行以 . 结束,且括号和花括号匹配
if strings.HasSuffix(trimmedLine, ".") && braceCount == 0 && parenCount == 0 {
currentFunction.EndLine = i + 1
functions = append(functions, currentFunction.ParseComments())
inFunction = false
currentFunction = ErlangFunction{}
}
} else {
// 不在函数中时,遇到非注释行就清空注释缓存
if trimmedLine != "" && !strings.HasPrefix(trimmedLine, "%") {
currentComments = nil
}
}
}
return functions
}
// 检测是否为函数开始行
func isFunctionStart(line string) bool {
// 匹配函数定义模式: 函数名(参数) -> 或 函数名(参数) when ... ->
functionPattern := `^(\w+)\([^)]*\)\s*(when\s+[^>]*)?->`
matched, _ := regexp.MatchString(functionPattern, line)
return matched
}
// 解析函数签名
func parseFunctionSignature(line string) *ErlangFunction {
// 匹配函数名和参数
pattern := `^(\w+)\(([^)]*)\)\s*(when\s+[^>]*)?->`
regex := regexp.MustCompile(pattern)
matches := regex.FindStringSubmatch(line)
if len(matches) < 3 {
return nil
}
function := &ErlangFunction{
Name: matches[1],
}
// 解析参数
params := strings.Split(matches[2], ",")
for _, param := range params {
param = strings.TrimSpace(param)
if param != "" {
function.Parameters = append(function.Parameters, param)
}
}
function.Arity = len(function.Parameters)
return function
}
// 检查函数是否被导出
func isExported(function ErlangFunction, exportedFunctions map[string]bool) bool {
key := fmt.Sprintf("%s/%d", function.Name, function.Arity)
return exportedFunctions[key]
}
+56
View File
@@ -0,0 +1,56 @@
package run
import (
"complie-erlang/config"
"gopkg.in/yaml.v2"
"log"
"os"
)
type ConfigGenerator struct {
config *config.GeneratorConfig
}
func NewConfigGenerator(cfg *config.GeneratorConfig) *ConfigGenerator {
return &ConfigGenerator{config: cfg}
}
func (g *ConfigGenerator) Generate() error {
return nil
}
func Run1() {
// 加载配置
cfg := loadConfig()
generator := NewConfigGenerator(cfg)
if err := generator.Generate(); err != nil {
log.Fatalf("Error generating config: %v", err)
}
}
func loadConfig() *config.GeneratorConfig {
configFile := "config.yaml"
if len(os.Args) > 1 {
configFile = os.Args[1]
}
if _, err := os.Stat(configFile); os.IsNotExist(err) {
log.Printf("Config file not found, using default config")
return config.DefaultConfig()
}
data, err := os.ReadFile(configFile)
if err != nil {
log.Printf("Failed to read config file, using default: %v", err)
return config.DefaultConfig()
}
var cfg config.GeneratorConfig
if err := yaml.Unmarshal(data, &cfg); err != nil {
log.Printf("Failed to parse config file, using default: %v", err)
return config.DefaultConfig()
}
return &cfg
}
+55
View File
@@ -0,0 +1,55 @@
package template
import (
"os"
"path/filepath"
"strings"
"text/template"
)
type Template struct {
Templates map[string]*template.Template
}
var DefaultFuncMap = template.FuncMap{
"hd": hd,
"title": strings.Title,
"join": strings.Join,
"list": func(strs []string) string { return strings.Join(strs, ",") },
}
func hd(str []string) string {
return str[0]
}
func NewTemplate() *Template {
return &Template{
Templates: make(map[string]*template.Template),
}
}
func (t *Template) Load(dir string) error {
files, err := os.ReadDir(dir)
if err != nil {
return err
}
for _, file := range files {
if file.IsDir() {
continue
}
if strings.HasSuffix(file.Name(), ".tpl") {
templateName := strings.TrimSuffix(file.Name(), ".tpl")
path := filepath.Join(dir, file.Name())
bytes, err := os.ReadFile(path)
if err != nil {
return err
}
parse, err := template.New(templateName).Funcs(DefaultFuncMap).Parse(string(bytes))
if err != nil {
return err
}
t.Templates[templateName] = parse
}
}
return nil
}
+11
View File
@@ -0,0 +1,11 @@
%% ----------------------------------------------------------------------------------
{{if .desc}}%% {{hd .desc}} {{end}}
{template, {{.template}}, { {{.project}}, "{{hd .cmd}}", [
{{if .reconnect}} { reconnect_db, msg_start, [] },
{{end}} {{if .fun_id}}{ fun_open_check, check, [{{hd .fun_id}}] }, {{end}}
{{if .pre_message}} { pre_port, decode, [{{hd .pre_proto }}, {{hd .pre_message}}] }, {{end}}
{{if .reconnect}} { {{hd .module}}, {{hd .func}}, [{{join .args ","}}] },
{ reconnect_db, msg_end, [] } {{else}} { {{hd .module}}, {{hd .func}}, [] }
{{end}}
]}}.
%% -----------------------------------------------------------------------------------