Wind目前有一个Python的世界频道功能,在example/python目录下,运行脚本后,脚本会登录服务器并且持续发言。这个案例主要用来理解Wind的整个工作流程,如果你想要知道Wind的工作流程,建议跟踪这两条协议的内部处理过程。
python世界频道客户端与服务器通信主要包含两个协议,一条协议是PlayerLoginRequest ,用于登录Gateway,另一个条是SpeakOnWorldRequest 协议,在世界频道发言。

  1. message PlayerLoginRequest
  2. {
  3. string player_id = 1; // 玩家ID
  4. }
  5. message SpeakOnWorldRequest
  6. {
  7. string player_id = 1; // 玩家ID
  8. string name = 2;
  9. string content = 3; // 发言内容
  10. }

序列化与反序列化

  1. class ClientMsgPack(Singleton):
  2. def __init__(self):
  3. pass
  4. # protobuf对象序列化成二进制 用于网络传输
  5. # 二进制格式如下:
  6. # | msgId | megLen | bytedata |
  7. def pack(self, mess:ClientMessage): # 序列化
  8. data = bytearray()
  9. data += uint32_to_bytes(mess.msg_id) # 协议id
  10. data += uint32_to_bytes(len(mess.data)) # 协议长度
  11. data += mess.data # protobuf序列化后的二进制
  12. return data
  13. def unpack(self, data, index): # 反序列化
  14. mess = ClientMessage()
  15. mess.msg_id = uint_from_bytes(data[index:index+4])
  16. mess.data_len = uint_from_bytes(data[index+4:index+8])
  17. mess.data = data[index+8:index+8+mess.data_len]
  18. index+8+mess.data_len
  19. return mess, index

登录

  1. def send_pack(transport, pck):
  2. msg_id = CodecMgr().get_proto_id(pck.DESCRIPTOR.name) # 获取协议id
  3. mess = ClientMessage()
  4. mess.msg_id = msg_id
  5. mess.data = CodecMgr().encode(pck) # 序列化protobuf对象成二进制
  6. data = ClientMsgPack().pack(mess) # 将protobuf对象数据和协议ID打包成最终传输的数据
  7. transport.write(data)
  8. # 发送登录协议
  9. def send_player_login(player_id, transport):
  10. req = PlayerLoginRequest()
  11. req.player_id = player_id
  12. send_pack(transport, req) # 发送包
  13. # 发言
  14. def send_speak_world(player_id, name, transport):
  15. req = SpeakOnWorldRequest()
  16. req.player_id = player_id
  17. req.name = name
  18. req.content = "hello, i'm wind!"
  19. send_pack(transport, req) # 发送包