syntax = "proto3";
package AxibugProtobuf;
option optimize_for = SPEED;

enum CommandID
{
    CMD_DEFAUL = 0;//缺省不使用
	
	//服务器或客户端,均可主动ping请求,对方响应。(这里测全流程延迟,即序 列化->发送->传输过程->接收->反序列化)
	CMD_PING = 1;  //Ping | 请求 对应 Protobuf_Ping
	CMD_PONG = 2;  //Pong | 响应 对应 Protobuf_Pong
	
	CMD_LOGIN = 2001;  //自动登录上行 | 下行 对应 Protobuf_Login | Protobuf_Login_RESP
	
	CMD_USER_ONLINELIST = 3000;  //获取在线用户列表 上行 | 下行 对应 Protobuf_UserList | Protobuf_UserList_RESP
	CMD_USER_JOIN = 3031;  //用户上线 下行 对应 Protobuf_UserOnline_RESP
	CMD_USER_LEAVE = 3032;  //用户下线 下行 对应 Protobuf_UserOffline_RESP
	CMD_USER_STATE_UPDATE = 3033;  //更新在线用户状态 下行 对应 Protobuf_UserState_RESP
	
	CMD_Modify_NickName = 3101;  //修改名称上行 | 下行 对应 Protobuf_Modify_NickName | Protobuf_Modify_NickName_RESP
	CMD_Update_SelfUserInfo = 3110;  //更新用户信息 下行 Protobuf_Update_UserInfo_RESP
	CMD_Update_OtherUserInfo = 3112;  //更新其他用户信息 下行 Protobuf_Update_OtherUserInfo_RESP
	
	CMD_CHATMSG = 4001;  //广播聊天信息上行 | 下行 对应 Protobuf_ChatMsg | Protobuf_ChatMsg_RESP
	
	//房间列表相关(仅用于列表显示)
	CMD_Room_List = 5001;  //房间列表 上行 | 下行 对应 Protobuf_Room_List | Protobuf_Room_List_RESP
	CMD_Room_List_Update = 5002;  //房间单个房间信息更新 对应 Protobuf_Room_Update_RESP
	CMD_Room_Get_Screen = 5011;  //房间列表 上行 | 下行 对应 Protobuf_Room_Get_Screen | Protobuf_Room_Get_Screen_RESP
	
	//房间内相关
	CMD_Room_Create = 5101;  //房间创建 对应 Protobuf_Room_Create | Protobuf_Room_Create_RESP
	CMD_Room_Join = 5105;  //房间加入 对应 Protobuf_Room_Join | Protobuf_Room_Join_RESP //建议Join之前按照房间信息,提前下载并读取本地Rom
	CMD_Room_Leave = 5106;  //房间离开 对应 Protobuf_Room_Leave | Protobuf_Room_Leave_RESP
	CMD_Room_MyRoom_State_Changed = 5110;  //我所在的房间内状态发生变化 对应 Protobuf_Room_MyRoom_State_Change
	CMD_Room_ChangePlayerWithJoy = 5130;  //更换操作槽位 对应 Protobuf_Room_Change_PlaySlotWithJoy | Protobuf_Room_Change_PlaySlotWithJoy_RESP
	
		//准备和开始流程(5201 ~ 5204 ~ 5208)
		//
		// 我们采用,玩家可以随时进入的方式开发
		//
		// 设计流程: 
		//
		// Step0:服务器广播"等待-主机上报即使存档" CMD_Room_WaitStep WaitStep=[0] ---> 客户端:暂停模拟器核心:全员等待(主机玩家一人上传即时存档)
		// 			主机玩家 上行 CMD_Room_HostPlayer_UpdateStateRaw消息,上传即时存档
		// 			主机玩家上传完毕之后,服务器会通知进入Step1
		//
		// Step1:服务器广播"等待-全员加载即时存档" CMD_Room_WaitStep WaitStep=[1] 附带即时存档 ---> 客户端:全员等待
		//			所有玩家确保加载ROM和即时存档,并保持模拟器暂停,准备完毕后 发送 CMD_Room_Player_Ready
		//			所有玩家Ready之后,服务器会根据所有玩家延迟提前跑若干Frame,通知进入Step2 
		//			
		// Step2:服务器广播"开始" CMD_Room_WaitStep WaitStep=[2] ---> 客户端:立即开始
		//
		//
		// PS:[联机过程中加载即时存档] 房间在游玩过程中,单个玩家发送CMD_Room_HostPlayer_UpdateStateRaw 上报即时存档
		// 		重新从Step1走流程
		// 
	CMD_Room_WaitStep = 5201;  //服务器等待Step通知 下行 Protobuf_Room_WaitStep_RESP
	CMD_Room_HostPlayer_UpdateStateRaw = 5204;  //主机玩家上传即时存档 上行 | 下行 对应 Protobuf_Room_HostPlayer_UpdateStateRaw | Protobuf_Room_HostPlayer_UpdateStateRaw_RESP
	CMD_Room_Player_Ready = 5208;  //玩家准备完毕 上行 Protobuf_Room_Player_Ready
	
	//游戏同步
	CMD_Room_Singel_PlayerInput = 6010; //单个玩家操作同步上行 对应 Protobuf_Room_SinglePlayerInputData
	CMD_ROOM_SYN_PlayerInput = 6015; //所有玩家操作同步下行  对应 Protobuf_Room_Syn_RoomFrameAllInputData
	
	//画面采集
	CMD_Screen = 7001;  //画面采集 | 同步广播 对应 Protobuf_Screnn_Frame
	
	//即时存档
	CMD_GAMESAV_GetGameSavList = 8001;//玩家即时存档列表获取 上行 | 下行 对应 Protobuf_Mine_GetGameSavList | Protobuf_Mine_GetGameSavList_RESP
	CMD_GAMESAV_DelGameSav = 8005;//玩家删除即时存档 上行 | 下行 对应 Protobuf_Mine_DelGameSavList | Protobuf_Mine_DelGameSavList_RESP
	CMD_GAMESAV_UploadGameSav = 8010;//玩家上传即时存档 上行 | 下行 对应 Protobuf_Mine_UpLoadGameSavList | Protobuf_Mine_UpLoadGameSavList_RESP
	
	CMD_GAME_MARK = 10101;  //获取即时存档列表 上行 | 下行 对应 Protobuf_Game_Mark | Protobuf_Game_Mark_RESP
}

enum ErrorCode
{
    ERROR_DEFAUL = 0;//缺省不使用
	ERROR_OK = 1;   //成功
	
	ERROR_ROOM_NOT_FOUND = 10;//房间不存在
	ERROR_ROOM_SLOT_ALREADLY_HAD_PLAYER=11;//加入目标位置已经有人
	
	ERROR_ROOM_CANT_DO_CURR_STATE =50;//当前房间状态不允许本操作
	
	ERROR_ROM_DONT_HAD_SAVEDATA = 80;//即时存档不存在
	
	ERROR_ROM_ALREADY_HAD_STAR =403;//已经收藏
	ERROR_ROM_DONT_HAD_STAR =404;//并没有收藏

}

enum LoginType
{
	UseDevice = 0;//使用设备登录
	UseAccount = 1;//使用账户
	UseHaoYueAccount = 2;//使用皓月通行证
}

enum DeviceType //设备类型
{
    DeviceType_Default = 0;//通用
	PC = 1;
	Android = 2;
	IOS = 3;
	PSV = 4;
	PS3 = 5;
	PS4 = 6;
	XBOX360 = 7;
	XBOXONE = 8;
	WiiU = 9;
	Nintendo3DS = 10;
	AndroidCarApp = 11;//汽车Android车机
}

enum GamePadType //手柄类型
{
    Keyboard = 0;//键盘
	GlobalGamePad = 1;//通用手柄
	TouchPanel = 2;//触屏
	DS3Control = 3;
	DS4Control = 4;
	DS5Control = 5;
	SwitchProControl = 6;
	SwitchJoyCon = 7;
	XBOX360Control = 8;
	XBOXONEControl = 9;
	PSVitaControl = 10;
	WiiUPadControl = 11;
	WiiRemoteControl = 12;
	Nintendo3DSControl = 13;
}

enum RomPlatformType
{
    Invalid = 0;
    Nes = 1;
    Master_System = 2;
	Game_Gear = 3;
	Game_Boy = 4;
	Game_Boy_Color = 5;
	Coleco_Vision = 6;
	SC_3000 = 7;
	SG_1000 = 8;
	NEOGEO = 20;
	IGS = 21;
	CPS1 = 22;
	CPS2 = 23;
	Arcade_OLD = 30
	All = 999;
}

//enum RoomPlayerState
//{
//    None_PlayerState = 0;//缺省
//	OnlyP1 = 1;   //仅P1
//	OnlyP2 = 2;   //仅P2
//	BothOnline = 3;   //玩家都在
//}

enum RoomGameState
{
    None_GameState = 0;//缺省
    OnlyHost = 1;//仅主机,待加入
	WaitRawUpdate = 2;//等待即时存档
	WaitReady = 3;//等待Ready
	Pause = 4;//暂停
	InOnlineGame = 5;//联机中
}


enum LoginResultStatus
{
    LoginResultStatus_BaseDefault = 0;//缺省不使用
	OK = 1;
	AccountErr = 2;
}

//聊天 上行
message Protobuf_ChatMsg
{
	string ChatMsg = 1;//消息
}

//聊天 下行
message Protobuf_ChatMsg_RESP
{
	string NickName = 1;//昵称
	string ChatMsg = 2;//消息
	int64 Date = 3;//时间
}

message Protobuf_Ping
{
	int32 Seed = 1;//随机数
}

message Protobuf_Pong
{
	int32 Seed = 1;//原样返回随机数
}

//登录数据上行
message Protobuf_Login
{
	LoginType loginType = 1;//登录操作类型
	DeviceType deviceType = 2;//设备类型 [0] PC [1] AndroidPad预留 [3] IPad预留
	string deviceStr = 3;//设备串
	string Account = 4;//用户名
	string Password = 5;//密码
}

//登录数据下行
message Protobuf_Login_RESP
{
	string NickName = 1;//昵称(第一次是自动生成)
	string Token = 2;//登录凭据 (本次登录之后,所有业务请求凭据,需要存储在内存中)
	string LastLoginDate = 3;//上次登录时间(只用于呈现的字符串,若界面需求需要)
	string RegDate = 4;//注册时间(只用于呈现的字符串,若界面需求需要)
	LoginResultStatus Status = 5;//账号状态 (预留) [1]正常[0]被禁封
	int64 UID = 6;
}


//Token结构,但用于逻辑里配置加密密钥,放置于服务端加密后,发放token
message Protobuf_Token_Struct
{
	int64 UID = 1;
	int64 TokenGenDate = 2;
	int64 Seed = 3;
}

//获取在线用户列表 上行
message Protobuf_UserList
{
}

//获取在线用户列表 下行
message Protobuf_UserList_RESP
{
	int32 UserCount = 1;//玩家数量
	repeated UserMiniInfo UserList = 2;//用户列表
}

//用户上线 下行
message Protobuf_UserJoin_RESP
{
	UserMiniInfo UserInfo = 1;//用户
}

//用户下线 下行
message Protobuf_UserLeave_RESP
{
	int64 UID = 1;//用户ID
}

//更新在线用户状态 下行
message Protobuf_UserState_RESP
{
	int64 UID = 1;//用户ID
	int32 State = 2;//状态
}

message UserMiniInfo
{
	int64 UID = 1;//用户ID
	string NickName = 2;//昵称
	DeviceType deviceType = 3;//设备类型
}

//修改昵称上行
message Protobuf_Modify_NickName
{
	string NickName = 1;//昵称
}

//修改昵称下行
message Protobuf_Modify_NickName_RESP
{

}

//用户信息更新
message Protobuf_Update_UserInfo_RESP
{
	UserMiniInfo UserInfo = 1;//用户
}

//其他用户信息更新
message Protobuf_Update_OtherUserInfo_RESP
{
	int64 UID = 1;//用户ID
	UserMiniInfo UserInfo = 2;//用户
}

message Protobuf_Room_List
{
	
}

message Protobuf_Room_List_RESP
{
	repeated Protobuf_Room_MiniInfo RoomMiniInfoList = 1;//房间列表
}

message Protobuf_Room_MiniInfo
{
	int32 RoomID = 1;//房间ID
	int32 GameRomID = 2;//游戏ID
	string GameRomHash = 3;
	RomPlatformType GamePlatformType = 4;
	int64 HostPlayerUID = 5;//主机玩家ID
	RoomGameState GameState = 6;//游戏状态
	int32 ObsUserCount = 7;//观战用户数量
	int64 ScreenProviderUID = 8;//屏幕数据供应者
	repeated Protobuf_Room_GamePlaySlot GamePlaySlotList = 9;//游玩槽位信息P1~P4 固定4个
}

message Protobuf_Room_GamePlaySlot
{
	int64 Player_UID = 1;//玩家 UID
	string Player_NickName = 2;//玩家 昵称
	DeviceType deviceType = 3;//用户设备类型
	int32 PlayerLocalJoyIdx = 4;//客户端JoyIdx
	GamePadType PlayerLocalGamePadType = 5;//客户端手柄类型
}

message Protobuf_Room_Update_RESP
{
	int32 UpdateType = 1;//[0] 更新或新增 [1] 删除
	Protobuf_Room_MiniInfo RoomMiniInfo = 2;//房间信息
}

message Protobuf_Screnn_Frame
{
	int32 RoomID = 1;//房间ID
	int32 FrameID = 2;//帧编号
    bytes RawBitmap = 3;//渲染层画面
}

message Protobuf_Room_SinglePlayerInputData
{
	uint32 FrameID = 1;//帧编号
	uint32 InputData = 2;//单个玩家操作位运算汇总
}

message Protobuf_Room_Syn_RoomFrameAllInputData
{
	uint32 FrameID = 1;//帧编号
	uint64 InputData = 2;//所有玩家操作位运算汇总
	uint32 ServerFrameID = 3;//服务器帧编号
	uint32 ServerForwardCount = 4;//服务器提前量
}

message Protobuf_Room_Create
{
	int32 GameRomID = 1;
	string GameRomHash = 2;
}

message Protobuf_Room_Create_RESP
{
	Protobuf_Room_MiniInfo RoomMiniInfo = 1;//房间信息
}

message Protobuf_Room_Join
{
	int32 RoomID = 1;//房间ID
}

message Protobuf_Room_Join_RESP
{
	Protobuf_Room_MiniInfo RoomMiniInfo = 1;//房间信息
}

message Protobuf_Room_Leave
{
	int32 RoomID = 1;//离开的房间ID
}

message Protobuf_Room_Leave_RESP
{
	int32 RoomID = 1;//离开的房间ID
}

message Protobuf_Room_MyRoom_State_Change
{
	Protobuf_Room_MiniInfo RoomMiniInfo = 1;//更新房间信息
}

message Protobuf_Room_Change_PlaySlotWithJoy
{
	repeated Protobuf_PlaySlotIdxWithJoyIdx SlotWithJoy = 1;//P1~P4编号
}

message Protobuf_PlaySlotIdxWithJoyIdx
{
	int32 PlayerSlotIdx = 1;//P1~P4编号
	int32 PlayerLocalJoyIdx = 2;//客户端Joy编号
	GamePadType PlayerLocalGamePadType = 3;//客户端手柄类型
}

message Protobuf_Room_Change_PlaySlotWithJoy_RESP
{
}

message Protobuf_Room_WaitStep_RESP
{
	int32 WaitStep = 1;//状态 [0]等待主机上报即时存档 [1]要求客户端准备 [2]开始(收到本状态时,立即开始跑模拟器核心)
	
	//如下是 WaitStep = 1 时,才有值。广播即时存档
    bytes LoadStateRaw = 2;//即时存档byte数据
}

message Protobuf_Room_HostPlayer_UpdateStateRaw
{
    bytes LoadStateRaw = 1;//即时存档byte数据
}

message Protobuf_Room_HostPlayer_UpdateStateRaw_RESP
{
}

message Protobuf_Room_Player_Ready
{
	float PushFrameNeedTimeUs = 1;//push帧所需平均时间(微秒)
	float LoadStateNeedTimeUs = 2;//加载即时存档所需平均时间(微秒)
	float VideoFrameShowNeedTimeUs = 3;//视频一帧所需时间(微秒)
	float AudioFramePlayNeedTimeUs = 4;//音频处理一帧所需时间(微秒)
}

message Protobuf_Room_Get_Screen
{
	int32 RoomID = 1;//房间ID
}

message Protobuf_Room_Get_Screen_RESP
{
	int32 RoomID = 1;//房间ID
	int32 FrameID = 2;//帧编号
    bytes RawBitmap = 3;//渲染层画面
}


message Protobuf_Game_Mark
{
	int32 RomID = 1;//RomID
	int32 motion = 2;//[0]取消收藏[1]收藏
}

message Protobuf_Game_Mark_RESP
{
	int32 RomID = 1;//RomID
	int32 IsStar = 2;//当前状态 [0]未收藏[1]已收藏
	int32 stars = 3;//当前收藏计数
}


message Protobuf_Mine_GetGameSavList
{
	int32 RomID = 1;
}

message Protobuf_Mine_GetGameSavList_RESP
{
	int32 RomID = 1;
	repeated Protobuf_Mine_GameSavInfo SavDataList = 2;
}

message Protobuf_Mine_GameSavInfo
{
	bool bHadSaveData = 1;//是否有存档
	int64 SavID = 2;//即时存档唯一ID(用于今后分享)
	int64 uid = 3;//所属用户UID(用于今后分享)
	int32 SavDataIdx = 4;//即时存档下标(其中第0个是自动存档位置)
	int32 RomID = 5;
	RomPlatformType GamePlatformType = 6;
	string SavDate = 7;//存档时间
	string SavName = 8;
	string Note = 9;//备注
	string SavImgUrl = 10;//即时存档截图Url
	string SavUrl = 11;//即时存档下载Url
}

message Protobuf_Mine_DelGameSav
{
	int32 RomID = 1;//RomID
	int32 SavDataIdx = 2;//即时存档下标(其中第0个是自动存档位置)
}

message Protobuf_Mine_DelGameSav_RESP
{
	int32 RomID = 1;//RomID
	int32 SavDataIdx = 2;//删除的即时存档下标
}

message Protobuf_Mine_UpLoadGameSav
{
	int32 RomID = 1;//RomID
	int32 SavDataIdx = 2;//即时存档下标(其中第0个是自动存档位置)
	string Name = 3;//存档名(留空时,服务器自动)
	string Note = 4;//备注(留空时,服务器自动)
	bytes SavImg = 5;//即时存档截图模拟器原生数据
    bytes StateRaw = 6;//即时存档byte数据
}

message Protobuf_Mine_UpLoadGameSav_RESP
{
	int32 RomID = 1;//RomID
	int32 SavDataIdx = 2;//即时存档下标(其中第0个是自动存档位置)
	Protobuf_Mine_GameSavInfo UploadSevInfo = 3;//上传成功的存档详情
}