package cs; /* 约定: CM前缀:客户端发给服务器的消息(client message) SM前缀:服务器发给客户的的消息(server message) MF前缀:消息的内嵌字段,只能作为其他消息的内嵌字段不能send(message field) _e后缀:枚举类型 _uniid后缀:唯一id union_前缀:联合体 _前缀:该字段仅服务器使用客户端无需处理 网络包格式:msghead + msgbody msghead: packagelen + msgid + seqid + magiccode + reserved = 2 + 2 + 4 + 2 + 2 = 12字节 msgbody: protobuf数据 msghead说明 packagelen(unsigned short): 双字节网络包长度, msgid(unsigned short): 双字节消息id seqid(unsigned int): 4字节序号id magiccode(unsigned short): 2字节魔数,并且为固定常数KS,占位符客户端不需什么处理 reserved(unsigned short): 保留 十六进制位运算数据表示法 0x01 == 1<<0 0x02 == 1<<1 0x04 == 1<<2 data_flags字段的意义 由于protobuf的二义性无法描述repeated字段是否有值(非repeated的字段可以通过msg.xxx == null来a判断) 所以给协议添加了data_flags这样的字段用来描述字段是否有值 data_flags32:描述id 1-31的字段哪些是赋值 data_flags64: 描述id 31-63直接的字段是否赋值 data_flags128...... 以此类推 message MFRoleInfo { optional int32 role_id = 1; optional int32 role_name = 2; optional int32 role_level = 34; optional uint32 data_flags32 = 256; optional uint32 data_flags64 = 257; } role_id是否赋值 (data_flags32 & (1<<(1 - 1))) != 0 role_name是否赋值 (data_flags32 & (1<<(2 - 1))) != 0 role_level是否赋值 (data_flags64 & (1<<(34 - 33)) != 0 客户端可以根据protobuf反射得到字段名和字段id的对应关系做到自动化判断 */ //心跳 message CMPing { } message SMPing { optional int32 param1 = 1; } //rpc调用错误 message SMRpcError { optional int32 error_code = 1; optional string error_msg = 2; optional string debug_msg = 3; optional string file = 4; optional int32 lineno = 5; optional int32 error_param = 6; } //int32键值对 message MFPair { optional int32 key = 1; //key optional int32 value = 2; //val } //int64键值对 message MFPair64 { optional int64 key = 1; //key optional int64 value = 2; //val } //向量 message MFVector2D { optional float x = 1; //x轴 optional float y = 2; //y轴 } //地图物件 message MFMapObject { optional int32 object_id = 1; //物件id(mapThing表id) optional MFVector2D pos = 2; //位置 } //玩家信息 message MFPlayerInfo { optional int32 player_id = 1; optional int32 team_id = 2; optional string name = 3; } message MFGoods { optional string name = 1; optional int32 num = 2; } //视野 x1 x4 x8 message MFPlug { optional string name = 1; optional int32 id = 2; optional int32 param = 3; } //武器 message MFWeapon { optional int32 weapon_id = 1; //武器id 当weapon_id == 0时表示无装备(装备位置显示空) optional int32 weapon_lv = 2; //武器等级 optional int32 ammo = 4; //弹药数 } //玩家信息-部分 message MFPlayerPart { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional MFVector2D dir = 3; //朝向 } //玩家信息-全量 message MFPlayerFull { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional MFVector2D dir = 3; //朝向 optional float health = 6; //血量 optional bool dead = 7; //是否已死亡 optional bool downed = 8; //是否跌倒 optional bool disconnected = 9; //是否断网 optional int32 anim_type = 10; // optional int32 anim_seq = 11; // //optional int32 action_type = 12; //0: none 1:reload 2:useitem 3:relive //optional int32 action_duration = 22; //持续时间毫秒 optional int32 skin = 13; //皮肤id optional int32 backpack = 14; //背包 optional int32 helmet = 16; //头盔 optional int32 chest = 17; //防弹衣 optional MFWeapon weapon = 18; //武器 optional int32 energy_shield = 19; //能量护盾 optional int32 vip = 20; //vip optional int32 sdmg = 21; } //阻挡物-部分 message MFObstaclePart { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional float scale = 3; //缩放比 } //阻挡物-全量 message MFObstacleFull { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional float scale = 3; //缩放比 optional int32 obstacle_id = 6; //阻挡物id optional float health = 7; //血量 optional bool dead = 8; //是否已死亡 optional bool dead_at_thisframe = 9; //是否当前帧死亡(播放死亡特效) optional bool is_door = 20; //是否门 //只有当is_door==ture时以下字段才有意义 //门状态定义: 0:关 1:开 当door_old_state != door_new_state时播动画(开/关门) optional int32 door_id = 22; //门id optional int32 door_old_state = 23; //门前一个状态 optional int32 door_new_state = 24; //门当前状态 optional int32 door_house_uniid = 25; //门所属房间唯一id optional int32 door_house_id = 26; //门所属房间id optional float door_width = 27; //门宽度 optional float door_height = 28; //门高度 } //建筑物-部分 message MFBuildingPart { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 } //建筑物-全量 message MFBuildingFull { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional int32 building_id = 3; //建筑物id optional bool ceiling_dead = 6; } //loot出生点-部分 补给箱 message MFLootSpawnerPart { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional int32 loot_id = 3; //id } //loot出生点-全量 message MFLootSpawnerFull { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional int32 loot_id = 3; //id } //loot-部分 message MFLootPart { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 } //loot-全量 message MFLootFull { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional int32 item_id = 6; optional int32 count = 7; optional int32 age_ms = 8; } //尸体-部分 message MFDeadBodyPart { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 } //尸体-全量 message MFDeadBodyFull { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional int32 player_id = 3; //玩家id optional int32 inkjet = 6; } //decal-部分 message MFDecalPart { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional int32 decal_id = 3; //id } //decal-全量 message MFDecalFull { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional int32 decal_id = 3; //id } //发射体-部分 message MFProjectilePart { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional float pos_z = 3; //没用到 } //发射体-全量 message MFProjectileFull { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional float pos_z = 3; //没用到 } //烟雾-部分 message MFSmokePart { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional float rad = 3; //半径 } //烟雾-全量 message MFSmokeFull { optional int32 obj_uniid = 1; //唯一id optional MFVector2D pos = 2; //位置 optional float rad = 3; //半径 } //对象信息-部分 message MFObjectPart { //1:player 2:obstacle 3:building 4:lootspawner 5:loot 6:deadbody 7:decal 8:projectile 9:smoke optional int32 object_type = 1; optional MFPlayerPart union_obj_1 = 2; optional MFObstaclePart union_obj_2 = 3; optional MFBuildingPart union_obj_3 = 4; optional MFLootSpawnerPart union_obj_4 = 5; optional MFLootPart union_obj_5 = 6; optional MFDeadBodyPart union_obj_6 = 7; optional MFDecalPart union_obj_7 = 8; optional MFProjectilePart union_obj_8 = 9; optional MFSmokePart union_obj_9 = 10; } //对象信息-全量 message MFObjectFull { //1:player 2:obstacle 3:building 4:lootspawner 5:loot 6:deadbody 7:decal 8:projectile 9:smoke optional int32 object_type = 1; optional MFPlayerFull union_obj_1 = 2; optional MFObstacleFull union_obj_2 = 3; optional MFBuildingFull union_obj_3 = 4; optional MFLootSpawnerFull union_obj_4 = 5; optional MFLootFull union_obj_5 = 6; optional MFDeadBodyFull union_obj_6 = 7; optional MFDecalFull union_obj_7 = 8; optional MFProjectileFull union_obj_8 = 9; optional MFSmokeFull union_obj_9 = 10; } //活跃玩家数据(当前) message MFActivePlayerData { optional int32 action_type = 3; //0: none 1:reload 2:useitem 3:relive optional int32 action_duration = 5; //持续时间毫秒 optional int32 action_item_id = 6; optional int32 action_target_id = 7; optional int32 skin = 30; //皮肤id optional int32 backpack = 31; //背包 optional int32 helmet = 32; //头盔 optional int32 chest = 33; //防弹衣 optional int32 cur_scope = 10; //当前视野倍数 1 2 4 8 15 /* 0: 9mm 1: 556mm 2: 762mm 3: 12gauge 4: rpg火药(榴弹炮) 5: frag 手雷 6: smoke 烟雾弹 7: healthkit 医疗包 8: 止痛药 9: 10: 11: 12: 1xscope 13: 2xscope 14: 4xscope 15: 8xscope 16: 15xscope */ repeated int32 inventory = 11; //库存 optional int32 cur_weapon_idx = 15; //当前武器索引 0-4 repeated MFWeapon weapons = 16; //武器列表1-4 0:拳头 1:枪 2:枪 3:手雷 4:烟雾弹 optional int32 spectator_count = 20; } //毒圈数据 message MFGasData { /* 0: 进入战前准备 1: 辐射区将在多少时间后扩大 2: 辐射区正在扩大 */ optional int32 mode = 1; //0:inactive 1:waiting 2:moving optional float duration = 2; //持续时间(秒) optional MFVector2D pos_old = 3; //前一个圆心 optional MFVector2D pos_new = 4; //新圆心 optional float rad_old = 5; //前一个圆半径 optional float rad_new = 6; //新圆半径 } //队伍数据 message MFTeamData { optional int32 player_id = 1; //玩家id optional MFVector2D pos = 2; //位置 optional MFVector2D dir = 3; //方向 optional float health = 4; //血量 optional bool disconnected = 5; //是否短线 optional bool dead = 6; //是否死亡 optional bool downed = 7; //是否倒下 } //同队队友数据 message MFTeammateInfo { optional int32 team_id = 1; //队伍id repeated int32 player_ids = 2; //成员id列表 } //子弹 message MFBullet { optional int32 player_id = 1; //玩家id optional int32 bullet_id = 2; //子弹id optional MFVector2D pos = 3; //位置 optional MFVector2D dir = 4; //方向 optional float variance_t = 5; optional int32 bulletskin = 6; //子弹皮肤 optional bool crit = 7; optional int32 reflect_count = 8; optional int32 reflect_objid = 9; optional int32 gun_id = 10; //抢id optional float fly_distance = 11; //只有手雷和烟雾弹时这个字段才有意义 } //射击 message MFShot { optional int32 player_id = 1; //玩家id optional MFWeapon weapon = 2; //武器id optional bool offhand = 3; optional int32 bullskin = 4; } //爆炸 message MFExplosion { optional int32 item_id = 1; //配置表id optional MFVector2D pos = 2; //位置 optional int32 player_id = 3; //玩家id } //烟雾 message MFSmoke { optional int32 item_id = 1; //配置表id optional MFVector2D pos = 2; //位置 optional int32 player_id = 4; //玩家id } //表情 message MFEmote { optional int32 type = 1; optional int32 is_ping = 2; optional int32 player_id = 3; //玩家id optional MFVector2D pos = 4; //位置 optional string msg = 5; } //游戏结束时玩家统计信息 message MFPlayerStats { optional int32 player_id = 1; //玩家id optional string player_avatar_url = 2; //玩家头像 //本次成绩 optional int32 time_alive = 3; //存活时间(毫秒) optional int32 kills = 4; //击杀敌人数 optional int32 damage_amount = 8; //伤害总量 optional int32 heal_amount = 20; //治疗总量 //历史最佳成绩 optional int32 history_time_alive = 30; //存活时间(毫秒) optional int32 history_kills = 31; //击杀敌人数 optional int32 history_damage_amount = 32; //伤害总量 optional int32 history_heal_amount = 33; //治疗总量 optional int32 gold = 10; //金币 optional int32 score = 11; //积分 optional bool dead = 5; //是否已死亡 optional int32 killer_id = 7; //杀手id(自杀时为自己) 特殊id: -1:倒在安全区 optional string killer_name = 40; //杀手名称 optional string account_id = 21; //账号id } //end mfmsg //加入 message CMJoin { optional int32 server_id = 1; //serverid optional string team_uuid = 2; //队伍唯一id (没组队时为空字符串) optional int32 team_mode = 3; //队伍模式 0:单人 1:多人 optional int32 player_count = 4; //玩家数(单人时为1) optional bool auto_fill = 5; //是否自动填充玩家 optional int32 bot = 6; //是否机器人 optional string name = 7; //角色名 optional bool use_touch = 8; //zzz optional string account_id = 9; //账号id account_id repeated int32 emotes = 10; //表情列表 optional string avatar_url = 11; //头像 optional int32 energy_shield = 12; //能量护盾 optional int32 baseskin = 13; //皮肤id optional int32 basemelee = 14; //xx optional int32 elo_score = 15; repeated MFPlug plugs = 16; optional string gmode = 21; } //移动 message CMMove { optional int32 seq = 1; //序号 optional MFVector2D move_dir = 24; //移动-方向 optional MFVector2D attack_dir = 20; //攻击方向(朝向) optional bool shot_start = 6; //射击-单发 optional bool shot_hold = 7; //射击-连发 optional bool reload = 8; //装弹 optional float fly_distance = 12; //子弹飞行距离(只有手雷和烟雾弹时这个字段才有意义) optional int32 select_weapon = 10; //切换武器(没切换是不用发) optional int32 drop_weapon = 11; //丢弃武器 optional bool cancel_action = 26; //取消当前操作(比如取消使用道具装弹等) optional int32 use_item_idx = 22; //使用道具(对应库存索引0-16) optional int32 use_scope = 25; //使用倍镜 0-4 optional bool interaction = 9; //是否有交互 repeated int32 interaction_objids = 23; //交互的对象id列表 optional bool spectate = 30; //自杀 } //丢弃道具 message CMDropItem { optional int32 item_id = 1; //道具id optional int32 weapon_idx = 2; //武器索引 0-4 } //发送表情 message CMEmote { optional int32 type = 1; optional MFVector2D pos = 2; optional bool team_only = 4; } //语音 message CMVoice { optional int32 mode = 1; //模式 optional bytes msg = 2; //语音内容 } //endcmmsg //加入成功 message SMJoinedNotify { optional int32 team_mode = 1; //队伍模式 0:单人 1:多人 optional int32 player_id = 2; //玩家id(自己) optional bool started = 3; //游戏是否已开始 repeated MFPlayerInfo player_infos = 4; //玩家信息 optional int32 map_type = 5; //目前没用到 optional bool elo_start = 6; //目前没用到 optional int32 error_code = 7; //错误 } //地图信息 message SMMapInfo { optional int32 map_id = 1; //地图id repeated MFMapObject objects = 6; //地图对象 } //玩家信息 message SMPlayerInfo { optional MFPlayerInfo info = 1; //玩家信息 } //帧事件 message SMUpdate { repeated int32 del_objids = 2; //对象-待删除(移出视野) repeated MFObjectFull full_objects = 3; //对象-全量(出现在视野) repeated MFObjectPart part_objects = 4; //对象-部分(用于插值更新) optional int32 active_player_id = 5; //当前活跃玩家id(如果玩家死亡后是观战对象的id) optional MFActivePlayerData active_player_data = 6; //活跃玩家数据(如果玩家死亡后是观战对象的数据) optional int32 alive_count = 15; //存活数量 optional int32 gas_progress = 16; //毒圈进度,表示缩进的像素数(只有当gas_data.mode == moving时才会发进度) optional MFVector2D gas_pos_old = 30; //毒圈当前圆心坐标 optional MFGasData gas_data = 17; //毒圈数据 repeated MFTeamData team_data = 18; repeated MFTeammateInfo teams = 19; //同队队友数据 repeated MFBullet bullets = 20; //子弹 repeated MFShot shots = 21; //射击 repeated MFExplosion explosions = 22; //爆炸 repeated MFSmoke smokes = 25; //烟雾 repeated MFEmote emotes = 23; //表情 optional int32 ack = 24; //服务器最后处理的req id } //击杀 message SMKillMsg { optional int32 damage_type = 1; //source_type optional int32 target_id = 2; optional int32 killer_id =3; optional int32 kill_credit_id = 4; optional int32 killer_kills = 5; optional int32 downed = 6; optional int32 killed =7; } //个人信息统计 message SMPlayerStats { optional MFPlayerStats player_stats = 1; } //游戏结束 message SMGameOver { optional int32 team_id = 1; //队伍id optional int32 team_rank = 2; //队伍排名 optional int32 team_allcnt = 3; optional bool game_over = 4; //是否结束 optional bool victory = 5; //是否胜利 repeated MFPlayerStats player_stats = 6; //玩家信息统计 } //拾取 message SMPickup { optional int32 error_code = 1; //0:没有错误 1:背包空间不足 2:物品已拥有 3:物品已装备 optional int32 item_id = 2; //道具id optional int32 count = 3; //获得数量 } //断线通知 message SMDisconnectNotify { optional string reason = 1; //断线原因 } //语音通知 message SMVoiceNotify { optional int32 mode = 1; //模式 optional string account_id = 2; //唯一id optional bytes msg = 3; //语音内容 }