syntax = "proto3"; package protocol; // Define services service GeneralService { // Get server info from server. // // This parameter actually doesn't accept any arguments, // but it is still required owing to Protobuf grammar. rpc GetServerInfo(Empty) returns (ServerInfo); } service GameService { rpc Login(LoginRequest) returns (LoginResponse); rpc Signup(SignupRequest) returns (SignupResponse); } // Define messages enum RequestResult { Success = 0; Fail = 1; } message Empty {} message ServerInfo { string Lang = 1; string ver = 2; } message LoginRequest { string Username = 1; string Password = 2; } message LoginResponse { RequestResult result = 1; string message = 2; } message SignupRequest { string Username = 1; string Password = 2; } message SignupResponse { RequestResult result = 1; string message = 2; } // 导入 google/protobuf/empty.proto 用于不需要参数或返回值的 RPC import "google/protobuf/empty.proto"; // 导入 google/protobuf/timestamp.proto 用于时间戳 import "google/protobuf/timestamp.proto"; // 可以根据需要导入其他标准 Protobuf 类型 // =================================================================== // 1. 基础公共类型和枚举 // =================================================================== // 表示一个唯一的实体ID message EntityID { string value = 1; // 例如:UUID, "player_123", "enemy_A_45" } // 2D 向量(位置或方向) message Vec2D { float x = 1; float y = 2; } // 房间状态枚举 enum RoomStatus { UNKNOWN_ROOM_STATUS = 0; // 未知状态,通常作为默认值 WAITING = 1; // 等待玩家加入 IN_GAME = 2; // 游戏进行中 FINISHED = 3; // 游戏已结束,等待结算 } // 游戏版本信息 message GameVersion { uint32 major = 1; // 主版本号 uint32 minor = 2; // 次版本号 uint32 patch = 3; // 补丁版本号 } // 包信息 (用于核对客户端资源包) message PackageInfo { string package_id = 1; // 包的唯一ID (如 "map_pack_001", "character_skins") GameVersion version = 2; // 包的版本 string checksum = 3; // 包的校验和 (MD5, SHA256等),用于完整性检查 } // =================================================================== // 2. 身份验证与连接服务 (Authentication and Connection Service) // 用于客户端连接、核对版本和资源包 // =================================================================== service AuthService { // 客户端连接服务器时进行初始化认证 rpc Authenticate (AuthRequest) returns (AuthResponse); } // 认证请求 message AuthRequest { string client_id = 1; // 客户端唯一ID (如设备ID或用户ID) GameVersion game_version = 2; // 客户端的游戏版本 repeated PackageInfo client_packages = 3; // 客户端拥有的资源包列表及其版本和校验和 string auth_token = 4; // 可选:OAuth token 或其他认证凭证 } // 认证响应 message AuthResponse { bool success = 1; // 是否认证成功 optional string message = 2; // 认证失败时的错误消息 // 如果认证失败,可能需要提供不匹配的包信息 repeated PackageInfo mismatched_packages = 3; // 服务器端不匹配或过时的包信息 // 注意:此处可以考虑更详细的错误码系统 // 如果成功,可能返回一些会话信息 optional string session_id = 4; // 会话ID,用于后续请求 } // =================================================================== // 3. 房间管理服务 (Room Management Service) // 用于查询、建立、加入和离开房间 // =================================================================== service RoomService { // 查询可用房间列表 rpc ListRooms (ListRoomsRequest) returns (ListRoomsResponse); // 创建一个新房间 rpc CreateRoom (CreateRoomRequest) returns (CreateRoomResponse); // 加入一个现有房间 rpc JoinRoom (JoinRoomRequest) returns (JoinRoomResponse); // 离开当前房间 rpc LeaveRoom (LeaveRoomRequest) returns (google.protobuf.Empty); // 无需特定响应体 // 撤销一个房间 (通常由房主或服务器管理员操作) rpc DisbandRoom (DisbandRoomRequest) returns (google.protobuf.Empty); } // 房间信息(公共可见部分) message RoomInfo { string room_id = 1; string room_name = 2; RoomStatus status = 3; uint32 current_players = 4; uint32 max_players = 5; string map_id = 6; // 当前房间使用的地图ID bool is_private = 7; // 是否是私人房间,需要密码或邀请 string host_player_id = 8; // 房主ID google.protobuf.Timestamp created_at = 9; // 房间创建时间 GameVersion game_version = 10; // 房间创建时使用的游戏版本,确保一致性 } // 查询房间请求 message ListRoomsRequest { // 可以根据不同的过滤条件查询房间 optional string map_id_filter = 1; optional RoomStatus status_filter = 2; bool only_available = 3; // 只返回可加入的房间 uint32 max_results = 4; // 最大返回数量 } // 查询房间响应 message ListRoomsResponse { repeated RoomInfo rooms = 1; } // 创建房间请求 message CreateRoomRequest { string room_name = 1; uint32 max_players = 2; string map_id = 3; optional string password = 4; // 私人房间密码 bool is_private = 5; string player_id = 6; // 创建者的玩家ID } // 创建房间响应 message CreateRoomResponse { bool success = 1; optional string message = 2; optional RoomInfo room_info = 3; // 成功创建后返回房间信息 } // 加入房间请求 message JoinRoomRequest { string room_id = 1; string player_id = 2; optional string password = 3; // 如果是私人房间,需要提供密码 } // 加入房间响应 message JoinRoomResponse { bool success = 1; optional string message = 2; optional RoomInfo room_info = 3; // 成功加入后返回房间信息 optional string player_session_token = 4; // 玩家在房间内的会话令牌 } // 离开房间请求 message LeaveRoomRequest { string room_id = 1; string player_id = 2; } // 撤销房间请求 message DisbandRoomRequest { string room_id = 1; string player_id = 2; // 执行撤销的玩家ID (需验证权限) } // =================================================================== // 4. 游戏同步服务 (Game Synchronization Service) // 用于游戏内实体、地图、状态等数据的同步 // 这是一个双向流RPC,客户端和服务器可以持续发送更新 // =================================================================== service GameSyncService { // Bi-directional streaming RPC for real-time game state synchronization // 客户端和服务器持续发送 GameSyncMessage rpc SyncGame (stream GameSyncMessage) returns (stream GameSyncMessage); } // 实体属性(运行时属性,例如血量、能量等) message EntityRuntimeProperties { map string_properties = 1; // 字符串属性 (例如 "state": "idle", "team_id": "blue") map int_properties = 2; // 整型属性 (例如 "health": 100, "attack": 10) map float_properties = 3; // 浮点型属性 (例如 "speed": 5.5, "mana_regen": 1.2) map bool_properties = 4; // 布尔属性 (例如 "is_dead": false, "can_move": true) // 可以添加更多常用类型或更复杂的嵌套消息来表示特定属性 } // 实体信息 message Entity { EntityID id = 1; // 实体的唯一运行时ID string def_name = 2; // 实体的定义名称 (例如 "PlayerCharacterA", "GoblinWarrior", "HealthPotion") Vec2D position = 3; // 位置 Vec2D orientation = 4; // 朝向 (归一化向量) // 运行时属性 EntityRuntimeProperties properties = 5; // 实体所属的维度ID (例如 "world_0", "dungeon_level_1", "instance_arena_3") string dimension_id = 6; // 实体创建时间 (可选) optional google.protobuf.Timestamp created_at = 7; } // 维度信息 (例如一个地图区域,一个副本实例) message Dimension { string id = 1; // 维度ID (如 "main_world", "dungeon_level_1") string map_id = 2; // 维度所使用的地图静态ID // 其他维度相关的状态,例如天气,时间OfDay等 map custom_data = 3; } // 单个游戏状态更新包 message GameStateUpdate { string room_id = 1; // 房间ID google.protobuf.Timestamp timestamp = 2; // 更新时间戳 // 实体更新 repeated Entity entities_to_add = 3; // 要添加或完全更新的实体 repeated Entity entities_to_update = 4; // 要更新的实体(可能是部分更新,根据实现) repeated EntityID entities_to_remove = 5; // 要移除的实体ID // 维度更新 repeated Dimension dimensions_to_add = 6; repeated Dimension dimensions_to_update = 7; repeated string dimensions_to_remove = 8; // 移除维度的ID // 其他全局游戏状态(例如游戏阶段、得分、时间限制等) map global_state_properties = 9; } // 游戏事件 message GameEvent { enum EventType { UNKNOWN_EVENT = 0; PLAYER_HIT = 1; ITEM_PICKUP = 2; ENTITY_KILLED = 3; SKILL_CAST = 4; // ... 更多事件类型 } EventType type = 1; string room_id = 2; google.protobuf.Timestamp timestamp = 3; string source_entity_id = 4; // 导致事件的实体ID optional string target_entity_id = 5; // 事件影响的实体ID // 事件的具体数据,使用 oneof 模式更优雅 oneof event_data { PlayerHitEvent player_hit = 6; ItemPickupEvent item_pickup = 7; // ... 更多事件的详细数据 } } // 具体的事件数据示例 message PlayerHitEvent { int32 damage_dealt = 1; string weapon_id = 2; } message ItemPickupEvent { string item_def_name = 1; int32 quantity = 2; } // 通用游戏同步消息(客户端和服务器双向) message GameSyncMessage { string room_id = 1; // 当前消息所属的房间ID string player_id = 2; // 发送消息的玩家ID (客户端发送时) 或目标玩家ID (服务器发送时) // 使用 oneof 来区分消息类型 oneof content { GameStateUpdate state_update = 3; // 服务器发送完整的游戏状态或增量更新 GameEvent client_event = 4; // 客户端发送的游戏操作事件 (如移动、攻击) GameEvent server_event = 5; // 服务器发送的游戏事件 (如伤害、物品掉落) ClientHeartbeat heartbeat = 6; // 客户端发送的心跳包 ServerPing ping = 7; // 服务器发送的ping消息 ClientInput input = 8; // 客户端的输入 (键盘/鼠标/手柄) } } // 客户端心跳 message ClientHeartbeat { google.protobuf.Timestamp client_time = 1; // 客户端本地时间 } // 服务器 ping (用于延迟计算) message ServerPing { google.protobuf.Timestamp server_time = 1; // 服务器发送时间 } // 客户端输入(示例,可以更复杂) message ClientInput { // 按键状态,例如:map keys_pressed; repeated string keys_pressed = 1; // 当前按下的键名列表 Vec2D mouse_position = 2; // 鼠标屏幕坐标 bool left_mouse_click = 3; bool right_mouse_click = 4; Vec2D movement_direction = 5; // 玩家移动的期望方向向量 // 可以添加更多输入相关的数据 }