%%%-----------------------------------
%%% @Module  : pt_120
%%% @Author  : xyao
%%% @Email   : jiexiaowen@gmail.com
%%% @Created : 2011.06.23
%%% @Description: 场景信息
%%%-----------------------------------
-module(pt_120).
-export([read/2, write/2, pack_elem_list/1, pack_npc_list/1]).
-include("server.hrl").
-include("scene.hrl").
-include("attr.hrl").
-include("figure.hrl").
-include("common.hrl").
-include("team.hrl").
-include("battle.hrl").
-include("skill.hrl").
-define (MAX_SENT_NUM, 20).
%%
%%客户端 -> 服务端 ----------------------------
%%

%%走路
read(12001, <<S:32, X:16, Y:16, MotionType:8, BroadcastX:16, BroadcastY:16, FlyX:16, FlyY:16>>) ->
    {ok, [S, X, Y, MotionType, BroadcastX, BroadcastY, FlyX, FlyY]};

%%加载场景
read(12002, _) ->
    {ok, []};

%%切换场景
read(12005, <<DunId:32, ChangeSceneId:32, CallBackValue:8, TransType:8, TX:16, TY:16>>) ->
    {ok, [DunId, ChangeSceneId, CallBackValue, TransType, TX, TY]};

%% 请求该场景npc状态
read(12018, _) ->
    {ok, []};

%% 请求该场景npc状态
read(12020, _) ->
    {ok, []};

%%动作播放
read(12025,<<Type:8>>) ->
    {ok, [Type]};

%% 请求切换场景
read(12031, _) ->
    {ok, []};

%% 请求场景动态特效
read(12032, _) ->
    {ok, []};

%% 小飞鞋
read(12033, _) ->
    {ok, []};

%% 超链接场景传送
read(12034, <<SceneId:32, LineNo:16, X:16, Y:16>>) ->
    {ok, [SceneId, LineNo, X, Y]};

%% 通知完成了场景切换
read(12035, _) ->
    {ok, []};

%% 获取场景线路
read(12040, _) ->
    {ok, []};

%% 切换线路
read(12041, <<LineNo:16>>) ->
    {ok, LineNo};

%% 玩家改变区域（客户端使用）
read(12085, <<Type:8>>) ->
    {ok, Type};

read(12087, <<>>) ->
    {ok, []};

read(12088, <<>>) ->
    {ok, []};

read(_Cmd, _R) ->
    ?PRINT("120 error pt ~w~n", [{_Cmd, _R}]),
    {error, no_match}.

%%
%%服务端 -> 客户端 ------------------------------------
%%

%%走路
write(12001, [TargetX, TargetY, Id, MotionType, Param1, Param2, Param3, Param4]) ->
    case MotionType > 0 of
        true  -> {ok, pt:pack(12001, <<TargetX:16, TargetY:16, Id:64, MotionType:8, Param1:16, Param2:16, Param3:16, Param4:16>>)};
        false -> {ok, pt:pack(12001, <<TargetX:16, TargetY:16, Id:64, MotionType:8>>)}
    end;

%%加场景信息
write(12002, [User, Object, AreaMarkL]) ->
    Data1 = pack_scene_user_list(User),
    Data2 = pack_scene_object_list(Object),
    Data3 = pack_area_mark(AreaMarkL),
    Data = << Data1/binary, Data2/binary, Data3/binary>>,
    {ok, pt:pack(12002, Data, 1)};


%%进入新场景广播给本场景的人
write(12003, D) ->
    {ok, pt:pack(12003, binary_to_12003(D))};

%%离开场景
write(12004, Id) ->
    {ok, pt:pack(12004, <<Id:64>>)};

%%切换场景
write(12005, [Id, X, Y, ErrCode, DunId, Callback, TransType]) ->
    Data = <<Id:32, X:16, Y:16, ErrCode:32, DunId:32, Callback:8, TransType:8>>,
    {ok, pt:pack(12005, Data)};

%% 怪物消失
write(12006, Id) ->
    {ok, pt:pack(12006, <<Id:32>>)};

%% 有怪物进入场景
write(12007, Info) ->
    NowTime = utime:longunixtime(),
    {ok, pt:pack(12007, binary_12007(Info, NowTime))};

%% 场景对象移动
write(12008, [X, Y, Id]) ->
    {ok, pt:pack(12008, <<X:16, Y:16, Id:32>>)};

%% 血量变化
write(12009, [PlayerId, Hp, HpLim]) ->
    {ok, pt:pack(12009, <<PlayerId:64, Hp:64, HpLim:64>>)};

%% 主角属性更新
write(12010, [Id, Attrs]) ->
    AttrsBin = pt:write_array(fun({Type, Value}) ->
        ValueStr = pt:write_string(Value),
        <<Type:8, ValueStr/binary>> end, Attrs),
    {ok, pt:pack(12010, <<Id:64, AttrsBin/binary>>)};

%% 9宫格加场景信息
write(12011, [User1, User2]) ->
    Data1 = pack_scene_user_list(User1),
    Data2 = pack_leave_list(User2),
    Data = << Data1/binary, Data2/binary>>,
    {ok, pt:pack(12011, Data)};

%% 九宫格加载怪物
write(12012, [ObjectAdd, ObjectDel]) ->
    Data1 = pack_scene_object_list(ObjectAdd),
    Data2 = pack_scene_object_leave_list(ObjectDel),
    {ok, pt:pack(12012, << Data1/binary, Data2/binary>>)};

%% （部分玩法全场景广播）通知角色进入
write(12013, [FigureOrRecPicture]) ->
    PictureInfo = pt:write_picture(FigureOrRecPicture),
    {ok, pt:pack(12013, PictureInfo)};

%% 场景一般对象
write(12014, Info) ->
    {ok, pt:pack(12014, binary_12014(Info))};

%% 场景假人
write(12015, Info) ->
    {ok, pt:pack(12015, binary_12015(Info))};

%% 通用状态变更
write(12016, [Mod,Type, RoleId, NewValue]) ->
    NameBin = pt:write_string(NewValue),
  {ok, pt:pack(12016, <<Mod:32, Type:32, RoleId:64, NameBin/binary>>)};

%%掉落包生成
write(12017, [MonId, Time, Scene, DropBin, X, Y, Boss]) ->
    ListNum = length(DropBin),
    ListBin = list_to_binary(DropBin),
    {ok, pt:pack(12017, <<MonId:32, Time:32, Scene:32, ListNum:16,
                          ListBin/binary, X:16, Y:16, Boss:8>>)};

%% 请求玩家可以拾取的掉落
write(12018, [DropBin]) ->
    ListNum = length(DropBin),
    ListBin = list_to_binary(DropBin),
    {ok, pt:pack(12018, <<ListNum:16, ListBin/binary >>)};

%% 掉落消失
write(12019, DropId) ->
    {ok, pt:pack(12019, <<DropId:32>>)};

%% 改变NPC状态图标
write(12020, []) ->
    {ok, pt:pack(12020, <<>>)};
write(12020, [NpcList]) ->
    NL = length(NpcList),
    Bin = list_to_binary([<<Id:32, Ico:8>> || [Id, Ico] <- NpcList]),
    Data = <<NL:16, Bin/binary>>,
    {ok, pt:pack(12020, Data)};

%% 掉落捡取信息
write(12021, [PlayerId, DropId, PlayerName]) ->
    Bin = pt:write_string(PlayerName),
    {ok, pt:pack(12021, <<PlayerId:64, DropId:32, Bin/binary>>)};

%% boss的归属(根据伤害最高)
write(12022, [PlayerId, BossFlag]) ->
    {ok, pt:pack(12022, <<PlayerId:64, BossFlag:8>>)};

%% 怪物说话
write(12023, [AutoId, Msg]) ->
    MsgBin = pt:write_string(Msg),
    {ok, pt:pack(12023, <<AutoId:32, MsgBin/binary>>)};

%% 攻防两方都飘字的角色血量变化
write(12024, [AttackId, DefendId, Hp, HpLim]) ->
    {ok, pt:pack(12024, <<AttackId:64, DefendId:64, Hp:64, HpLim:64>>)};

write (12025,[Rcode,Type]) ->
    Data = <<Rcode:32,Type:8>>,
    {ok, pt:pack(12025, Data)};

%% 怪物死亡
write(12027, Id) ->
    {ok, pt:pack(12027, <<Id:32>>)};

%% 掉落捡取信息
write(12030, AreaMarkL) ->
    Data = pack_area_mark(AreaMarkL),
    {ok, pt:pack(12030, Data)};

%% 请求切换场景
write(12031, Err) ->
    {ok, pt:pack(12031, <<Err:8>>)};

%% 场景特效改变通知
write(12032, [SceneId, EffValues]) ->
    EffValuesBin = pt:write_array(fun({EffId, DelOrAdd}) -> <<EffId:16, DelOrAdd:8>> end, EffValues),
    {ok, pt:pack(12032, <<SceneId:32, EffValuesBin/binary>>)};

%% 小飞鞋
write(12033, [Code]) ->
    {ok, pt:pack(12033, <<Code:32>>)};

%% 超链接场景传送
write(12034, [Code, X, Y]) ->
    {ok, pt:pack(12034, <<Code:32, X:16, Y:16>>)};

%% 查询线路状态
write(12040, [SceneId, LineNo, LineRoleNums]) ->
    Len = length(LineRoleNums),
    LineRoleNumsBin = list_to_binary([
            begin
                    Status = if
                        Num >= 25 -> 3;
                        Num >= 20 -> 2;
                        true -> 1
                    end,
                    <<Line:16, Status:8>>
            end || {Line, Num} <- LineRoleNums
        ]),
    {ok, pt:pack(12040, <<SceneId:32, LineNo:16, Len:16, LineRoleNumsBin/binary>>)};

%% 切换场景线路
write(12041, ErrCode) ->
    {ok, pt:pack(12041, <<ErrCode:32>>)};

%% 隐身字段广播
write(12070, [Sign, Id, Hide]) ->
    {ok, pt:pack(12070, <<Sign:8, Id:64, Hide:8>>)};

%% 幽灵字段广播
write(12071, [Sign, Id, Ghost]) ->
    {ok, pt:pack(12071, <<Sign:8, Id:64, Ghost:8>>)};

%% 分组字段广播
write(12072, [Sign, Id, Group]) ->
    {ok, pt:pack(12072, <<Sign:8, Id:64, Group:64>>)};

%% 嘲讽buff追踪对象
write(12073, [Sign, Id]) ->
    {ok, pt:pack(12073, <<Sign:8, Id:64>>)};

%% pk状态广播
write(12074, [Sign, Id, PkStatus]) ->
    {ok, pt:pack(12074, <<Sign:8, Id:64, PkStatus:8>>)};

%% 展示状态广播
write(12075, [Sign, Id, Show]) ->
    {ok, pt:pack(12075, <<Sign:8, Id:64, Show:8>>)};

write(12076, [Id, Id2]) ->
  {ok, pt:pack(12076, <<Id:64, Id2:64>>)};

write(12078, [Id, Figure]) ->
  FigureB = pt:write_figure(Figure),
  {ok, pt:pack(12078, <<Id:64, FigureB/binary>>)};

%% 怪物属性更新
write(12080, [Id, Attrs]) ->
    AttrsBin = pt:write_array(fun({Type, Value}) -> <<Type:8, Value:64>> end, Attrs),
    {ok, pt:pack(12080, <<Id:32, AttrsBin/binary>>)};

%% 怪物加血
write(12081, [Id, Hp]) ->
    {ok, pt:pack(12081, <<Id:32, Hp:64>>)};

%%改变速度
write(12082, [Sign, PlayerId, PlayerSpeed]) ->
    {ok, pt:pack(12082, <<Sign:8, PlayerId:64, PlayerSpeed:16>>)};

write(12083, [ReviveType,ScenceId, X,Y,ScenceName,Hp,Gold,BGold,AttProtectedTime]) ->
    ScenceNameBin = pt:write_string(ScenceName),
    {ok, pt:pack(12083, <<ReviveType:8,ScenceId:32, X:16,Y:16,ScenceNameBin/binary,Hp:64,Gold:32,BGold:32,AttProtectedTime:16>>)};

%% 改变攻速
write(12084, [Sign, Id, Value]) ->
    {ok, pt:pack(12084, <<Sign:8, Id:64, Value:16>>)};

%%玩家改变区域（客户端使用）
write(12085, [PlayerId, Type]) ->
    {ok, pt:pack(12085, <<PlayerId:64, Type:8>>)};

%%玩家改名通知
write(12086, [PlayerId, PlayerName]) ->
    Bin = pt:write_string(PlayerName),
    {ok, pt:pack(12086, <<PlayerId:64, Bin/binary>>)};

write(12087, [Num]) ->
    {ok, pt:pack(12087, <<Num:16>>)};

write(12088, [Users]) ->
    Len = length(Users),
    Bin = list_to_binary([pack_simple_user(U) || U <- Users]),
    {ok, pt:pack(12088, <<Len:16, Bin/binary>>)};

%% 主角通用活动标识更新
write(12089, [Id, ActLabel]) ->
    LabelBin = pt:write_array(fun({Type, Value}) -> <<Type:8, Value:64>> end, ActLabel),
    {ok, pt:pack(12089, <<Id:64, LabelBin/binary>>)};

write(12090, [Id, Attrs]) ->
    AttrsBin = pt:write_array(fun({Type, Val, Val1}) -> 
        String = pt:write_string(Val1), <<Type:8, Val:64, String/binary>> 
    end, Attrs),
    {ok, pt:pack(12090, <<Id:64, AttrsBin/binary>>)};

write(12099, [ReqtSceneId, CurrSceneId, TargetX, TargetY, MotionType, CurrX, CurrY, ErrCode]) ->
    Bin = <<ReqtSceneId:32, CurrSceneId:32, TargetX:16, TargetY:16, MotionType:8, CurrX:16, CurrY:16, ErrCode:8>>,
    {ok, pt:pack(12099, Bin)};

write(_Cmd, _R) ->
    ?DEBUG("error cmd ~w R:~p~n", [_Cmd, _R]),
    {ok, pt:pack(0, <<>>)}.

%% =====私有函数=======

%% 打包元素列表
pack_elem_list([]) ->
    <<0:16>>;
pack_elem_list(Elem) ->
    Rlen = length(Elem),
    F = fun([Sid, Name, X, Y]) ->
                Name1 = pt:write_string(Name),
                <<Sid:32, Name1/binary, X:16, Y:16>>
        end,
    RB = list_to_binary([F(D) || D <- Elem]),
    <<Rlen:16, RB/binary>>.

%% 打包场景元素
pack_scene_object_list([]) ->
    <<0:16, 0:16, 0:16>>;
pack_scene_object_list(List) ->
    NowTime = utime:unixtime(),
    F = fun(D, [TmpMonList, TmpNormalList, TmpDummyList]) ->
                if
                    D#scene_object.battle_attr#battle_attr.hp =< 0 -> [TmpMonList, TmpNormalList, TmpDummyList];
                    D#scene_object.sign == ?BATTLE_SIGN_MON     -> [[binary_12007(D, NowTime)|TmpMonList], TmpNormalList, TmpDummyList];
                    D#scene_object.sign == ?BATTLE_SIGN_DUMMY   -> [TmpMonList, TmpNormalList, [binary_12015(D)|TmpDummyList]];
                    is_record(D, scene_object) -> [TmpMonList, [binary_12014(D)|TmpNormalList], TmpDummyList];
                    true -> [TmpMonList, TmpNormalList, TmpDummyList]
                end
        end,
    [MonList, NormalList, DummyList] = lists:foldl(F, [[],[],[]], List),
    MonLen = length(MonList),
    NormalLen = length(NormalList),
    DummyLen = length(DummyList),
    MonListBin = list_to_binary(MonList),
    NormalListBin = list_to_binary(NormalList),
    DummyListBin = list_to_binary(DummyList),
    <<MonLen:16, MonListBin/binary, NormalLen:16, NormalListBin/binary, DummyLen:16, DummyListBin/binary>>.

%% 打包NPC列表
pack_npc_list([]) ->
    <<0:16>>;
pack_npc_list(Npc) ->
    Rlen = length(Npc),
    F = fun(EtsNpc) ->
                Id = EtsNpc#ets_npc.id,
                Name = pt:write_string(EtsNpc#ets_npc.name),
                X = EtsNpc#ets_npc.x,
                Y = EtsNpc#ets_npc.y,
                Icon = EtsNpc#ets_npc.icon,
                Image = EtsNpc#ets_npc.image,
                Func = EtsNpc#ets_npc.func,
                Realm = EtsNpc#ets_npc.realm,
                <<Id:32, Id:32, Name/binary, X:16, Y:16, Icon:32, Func:8, Realm:8, Image:32>>
        end,
    RB = list_to_binary([F(D) || D <- Npc]),
    <<Rlen:16, RB/binary>>.

pack_scene_user_list([]) ->
    <<0:16, <<>>/binary>>;
pack_scene_user_list(User) ->
    UserBin = pack_scene_user_list_helper(User, [], 1),
    Rlen = length(UserBin),
    RB = list_to_binary(UserBin),
    <<Rlen:16, RB/binary>>.

pack_scene_user_list_helper([D | T], List, Num) when Num =< ?MAX_SENT_NUM ->
    case binary_to_12003(D) of
        false ->
            pack_scene_user_list_helper(T, List, Num);
        D1 ->
            pack_scene_user_list_helper(T, [D1 | List], Num+1)
    end;
pack_scene_user_list_helper(_, List, _) -> List.

%% 打包玩家离开列表
pack_leave_list([]) ->
    <<0:16, <<>>/binary>>;
pack_leave_list(User) ->
    Rlen = length(User),
    RB = list_to_binary([<<Id:64>> || Id <- User]),
    <<Rlen:16, RB/binary>>.

%% 打包场景对象离开列表
pack_scene_object_leave_list([]) ->
    <<0:16, <<>>/binary>>;
pack_scene_object_leave_list(List) ->
    Rlen = length(List),
    RB = list_to_binary([<<Id:32>> || Id <- List]),
    <<Rlen:16, RB/binary>>.

pack_area_mark([]) -> <<0:16>>;
pack_area_mark(List) ->
    Rlen = length(List),
    RB = list_to_binary([<<AreaId:8, ClientType:8>> || {AreaId, ClientType} <- List]),
    <<Rlen:16, RB/binary>>.

%% 假人
binary_12015(S) ->
    #scene_object{
       id      = Id,
       x       = X,
       y       = Y,
       figure  = Figure,
       battle_attr = BA,
       dummy = Dummy,
       combat_power = CombatPower} = S,
    #battle_attr{hp=Hp, hp_lim=HpLim, speed=Speed, hide=Hide, ghost=Ghost, group=Group} = BA,
    FigureB = pt:write_figure(Figure),
    case is_record(Dummy, scene_dummy) of
        true ->
            IsDance = Dummy#scene_dummy.is_dance, SerNum = Dummy#scene_dummy.server_num;
        _ ->
            IsDance = 0, SerNum = 0
    end,
    <<Id:32, 0:16, 1:16, FigureB/binary, X:16, Y:16, Hp:64, HpLim:64, Speed:16, Hide:8, Ghost:8, Group:64, CombatPower:32, IsDance:8, SerNum:16>>.

%% 一般场景物
binary_12014(S) ->
    #scene_object{
       x       = X,
       y       = Y,
       id      = Id,
       figure  = Figure,
       icon_effect = IconEffect,
       is_be_clicked = IsBeClicked,
       skill_owner = SkillOwer,
       battle_attr = BA} = S,
    #figure{name=Name, body=Body} = Figure,
    #battle_attr{speed=Speed} = BA,
    case SkillOwer of
        #skill_owner{id=PlayerId, team_id=TeamId} -> skip;
        _ -> PlayerId=0, TeamId=0
    end,
    NameBin = pt:write_string(Name),
    IconEffBin = pt:write_string(IconEffect),
    <<X:16, Y:16, Id:32, NameBin/binary, Body:32, IconEffBin/binary, Speed:16, IsBeClicked:8, TeamId:64, PlayerId:64>>.

%% 怪物
binary_12007(#scene_object{sign=?BATTLE_SIGN_MON} = S, NowTime) ->
    #scene_object{
       x = X, y = Y, id = Id, angle=Angle,
       figure  = Figure, battle_attr = BA,
       att_type = AttType, color = Color,
       is_be_atted = IsBeAtted, is_be_clicked = IsBeClicked,
       icon_effect = IconEffect, icon_texture = IconTextrue,
       weapon_id = WeaponId,
       mon = Mon, skill_owner = SkillOwer, act_label = ActLabel} = S,
    #figure{lv=Lv, name=Name, body=Body, title = Title} = Figure,
    #battle_attr{speed=Speed, hp=Hp, hp_lim=HpLim, hide=Hide, other_buff_list = BuffList,
        ghost=Ghost, group=Group, pk = #pk{pk_protect_time = PkProtectTime}} = BA,
    #scene_mon{mid=Mid, kind=Kind, out=Out, boss=Boss, collect_time=CollectTime,
        owner = Owner, owner_name = OwnerName} = Mon,
    NeedPackList = case Boss =:= ?MON_WORLD_BOSS orelse Boss =:= ?MON_KEEP_ALIVE of
        true  ->
            BuffList;
        false ->
            []
    end,
    PackBuffList = lib_skill_buff:pack_buff(NeedPackList, NowTime, []),
    NameBin = pt:write_string(Name),
    IconEffBin = pt:write_string(IconEffect),
    case SkillOwer of #skill_owner{guild_id = GuildId} -> skip; _ -> GuildId = 0 end,
    case SkillOwer of #skill_owner{id = RoleId} -> skip; _ -> RoleId = 0 end,
    ActLabelFun = fun({ActType, Label}) -> <<ActType:8, Label:32>> end,
    ActLabelBin = pt:write_array(ActLabelFun, ActLabel),
    OwnerNameBin = pt:write_string(OwnerName),
    <<X:16, Y:16, Id:32, Mid:32, Hp:64, HpLim:64, Lv:16, NameBin/binary, Speed:16, Body:32, IconEffBin/binary, IconTextrue:32, WeaponId:32, AttType:8, Kind:8,
      Color:8, Out:8, Boss:8, CollectTime:32, IsBeClicked:8, IsBeAtted:8, Hide:8, Ghost:8, Group:64, GuildId:64, RoleId:64, Angle:16, Owner:64, OwnerNameBin/binary, Title:32, PkProtectTime:32,
      ActLabelBin/binary, PackBuffList/binary>>.

%% 人物
binary_to_12003(D) when is_record(D, ets_scene_user) ->
    PlatFomrBin = pt:write_string(D#ets_scene_user.platform),
    % ServerNameBin = pt:write_string(D#ets_scene_user.server_name),
    FigureBin = pt:write_figure(D#ets_scene_user.figure),
    BA = D#ets_scene_user.battle_attr,
    FunActLabel = fun({Key,Value}) -> <<Key:8,Value:64>> end,
    ActLabelBin = pt:write_array(FunActLabel, D#ets_scene_user.act_label),
    MateNameBin = pt:write_string(D#ets_scene_user.mate_name),
    MateTitleBin = pt:write_string(D#ets_scene_user.mate_title),
    {GodId, GodHp, GodHpLim} = god_api:pack_scene_user(D),
    #ets_scene_user{
        id = RoleId, x = X, y = Y,
        server_id = ServerId, server_num = ServerNum,
        role_dance = RoleDance,
        mate_role_id = MateRoleId, mate_lv = MateLv
    } = D,
    <<
    RoleId:64,
    PlatFomrBin/binary,
    ServerId:16,
    ServerNum:16,
    % ServerNameBin/binary,
    FigureBin/binary,
    X:16,
    Y:16,
    (D#ets_scene_user.battle_attr#battle_attr.hp):64,
    (D#ets_scene_user.battle_attr#battle_attr.hp_lim):64,
    (D#ets_scene_user.battle_attr#battle_attr.speed):16,
    (D#ets_scene_user.battle_attr#battle_attr.hide):8,
    (D#ets_scene_user.battle_attr#battle_attr.ghost):8,
    (D#ets_scene_user.battle_attr#battle_attr.group):64,
    (D#ets_scene_user.bl_who):8, %% boss归属标志
    (D#ets_scene_user.team#status_team.team_id):64,
    (D#ets_scene_user.team#status_team.positon):8,
    (BA#battle_attr.pk#pk.pk_status):8,
    (D#ets_scene_user.battle_attr#battle_attr.combat_power):32,
    (D#ets_scene_user.is_ride):8,
    (D#ets_scene_user.mount_figure):32,
    (BA#battle_attr.pk#pk.pk_value):16,
    0:32,  %% 宠物形象
    0:8,   %% 宠物状态
    (BA#battle_attr.pk#pk.pk_protect_time):32,
    MateRoleId:64,
    ActLabelBin/binary,
    MateNameBin/binary,
    MateTitleBin/binary,
    RoleDance:8,
    MateLv:8,
    GodId:16,
    GodHp:64,
    GodHpLim:64,
    (D#ets_scene_user.reb_protect_time):32,
    (D#ets_scene_user.deb_protect_time):32
    >>;

binary_to_12003(D) when is_record(D, player_status)->
    PlatFomrBin = pt:write_string(D#player_status.platform),
    % ServerNameBin = pt:write_string(D#player_status.server_name),
    FigureBin = pt:write_figure(D#player_status.figure),
    BA = D#player_status.battle_attr,
    FunActLabel = fun({Key,Value}) -> <<Key:8,Value:64>> end,
    ActLabelBin = pt:write_array(FunActLabel, D#player_status.act_label),
    {MateName, MateTitle, MateLv} = mate_api:role_get_wear_mate(D),
    MateNameBin = pt:write_string(MateName),
    MateTitleBin = pt:write_string(MateTitle),
    {GodId, GodHp, GodHpLim} = god_api:pack_role_user(D),
    #player_status{
        id = RoleId, x = X, y = Y,
        server_id = ServerId, server_num = ServerNum,
        role_dance = RoleDance,
        mate_role_id = MateRoleId
    } = D,
    <<
    RoleId:64,
    PlatFomrBin/binary,
    ServerId:16,
    ServerNum:16,
    % ServerNameBin/binary,
    FigureBin/binary,
    X:16,
    Y:16,
    (D#player_status.battle_attr#battle_attr.hp):64,
    (D#player_status.battle_attr#battle_attr.hp_lim):64,
    (D#player_status.battle_attr#battle_attr.speed):16,
    (D#player_status.battle_attr#battle_attr.hide):8,
    (D#player_status.battle_attr#battle_attr.ghost):8,
    (D#player_status.battle_attr#battle_attr.group):64,
    0:8, %% boss归属标志
    (D#player_status.team#status_team.team_id):64,
    (D#player_status.team#status_team.positon):8,
    (BA#battle_attr.pk#pk.pk_status):8,
    (D#player_status.battle_attr#battle_attr.combat_power):32,
    0:8,
    0:32,
    (BA#battle_attr.pk#pk.pk_value):16,
    0:32, %% 宠物
    0:8,  %% 宠物
    (BA#battle_attr.pk#pk.pk_protect_time):32,
    MateRoleId:64,
    ActLabelBin/binary,
    MateNameBin/binary,
    MateTitleBin/binary,
    RoleDance:8,
    MateLv:8,
    GodId:16,
    GodHp:64,
    GodHpLim:64,
    (D#player_status.reb_protect_time):32,
    (D#player_status.deb_protect_time):32
    >>;

binary_to_12003(_Status) ->
    false.

pack_simple_user(User) ->
    #ets_scene_user{platform = Platform, figure = Figure, server_num = SerNum, id = Id} = User,
    #figure{name = Name, sex = Sex, realm = Realm, career = Career, lv = Lv, picture = Pic, picture_ver = PicVer} = Figure,
    PlatFomrBin = pt:write_string(Platform),
    NameBin = pt:write_string(Name),
    PicBin = pt:write_string(Pic),
    <<PlatFomrBin/binary, SerNum:16, Id:64, Sex:8, Realm:8, Career:8, Lv:16, NameBin/binary, PicBin/binary, PicVer:32>>.
