You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
4.7 KiB

  1. package main
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "github.com/golang/protobuf/proto"
  7. "io"
  8. "math/rand"
  9. "net"
  10. "os"
  11. "os/signal"
  12. "time"
  13. "zinx/zinx_app_demo/mmo_game/pb"
  14. )
  15. type Message struct {
  16. Len uint32
  17. MsgId uint32
  18. Data []byte
  19. }
  20. type TcpClient struct {
  21. conn net.Conn
  22. X float32
  23. Y float32
  24. Z float32
  25. V float32
  26. Pid int32
  27. }
  28. func (this *TcpClient) Unpack(headdata []byte) (head *Message, err error) {
  29. headbuf := bytes.NewReader(headdata)
  30. head = &Message{}
  31. // 读取Len
  32. if err = binary.Read(headbuf, binary.LittleEndian, &head.Len); err != nil {
  33. return nil, err
  34. }
  35. // 读取MsgId
  36. if err = binary.Read(headbuf, binary.LittleEndian, &head.MsgId); err != nil {
  37. return nil, err
  38. }
  39. // 封包太大
  40. //if head.Len > MaxPacketSize {
  41. // return nil, packageTooBig
  42. //}
  43. return head, nil
  44. }
  45. func (this *TcpClient) Pack(msgId uint32, dataBytes []byte) (out []byte, err error) {
  46. outbuff := bytes.NewBuffer([]byte{})
  47. // 写Len
  48. if err = binary.Write(outbuff, binary.LittleEndian, uint32(len(dataBytes))); err != nil {
  49. return
  50. }
  51. // 写MsgId
  52. if err = binary.Write(outbuff, binary.LittleEndian, msgId); err != nil {
  53. return
  54. }
  55. //all pkg data
  56. if err = binary.Write(outbuff, binary.LittleEndian, dataBytes); err != nil {
  57. return
  58. }
  59. out = outbuff.Bytes()
  60. return
  61. }
  62. func (this *TcpClient) SendMsg(msgID uint32, data proto.Message) {
  63. // 进行编码
  64. binary_data, err := proto.Marshal(data)
  65. if err != nil {
  66. fmt.Println(fmt.Sprintf("marshaling error: %s", err))
  67. return
  68. }
  69. sendData, err := this.Pack(msgID, binary_data)
  70. if err == nil {
  71. this.conn.Write(sendData)
  72. } else {
  73. fmt.Println(err)
  74. }
  75. return
  76. }
  77. func (this *TcpClient) AIRobotAction() {
  78. //聊天或者移动
  79. //随机获得动作
  80. tp := rand.Intn(2)
  81. if tp == 0 {
  82. content := fmt.Sprintf("hello 我是player %d, 你是谁?", this.Pid)
  83. msg := &pb.Talk{
  84. Content: content,
  85. }
  86. this.SendMsg(2, msg)
  87. } else {
  88. //移动
  89. x := this.X
  90. z := this.Z
  91. randpos := rand.Intn(2)
  92. if randpos == 0 {
  93. x -= float32(rand.Intn(10))
  94. z -= float32(rand.Intn(10))
  95. } else {
  96. x += float32(rand.Intn(10))
  97. z += float32(rand.Intn(10))
  98. }
  99. //纠正坐标位置
  100. if x > 410 {
  101. x = 410
  102. } else if x < 85 {
  103. x = 85
  104. }
  105. if z > 400 {
  106. z = 400
  107. } else if z < 75 {
  108. z = 75
  109. }
  110. //移动方向角度
  111. randv := rand.Intn(2)
  112. v := this.V
  113. if randv == 0 {
  114. v = 25
  115. } else {
  116. v = 335
  117. }
  118. //封装Postsition消息
  119. msg := &pb.Position{
  120. X: x,
  121. Y: this.Y,
  122. Z: z,
  123. V: v,
  124. }
  125. fmt.Println(fmt.Sprintf("player ID: %d. Walking...", this.Pid))
  126. //发送移动MsgID:3的指令
  127. this.SendMsg(3, msg)
  128. }
  129. }
  130. /*
  131. 处理一个回执业务
  132. */
  133. func (this *TcpClient) DoMsg(msg *Message) {
  134. //处理消息
  135. //fmt.Println(fmt.Sprintf("msg id :%d, data len: %d", msg.MsgId, msg.Len))
  136. if msg.MsgId == 1 {
  137. //服务器回执给客户端 分配ID
  138. //解析proto
  139. syncpid := &pb.SyncPid{}
  140. proto.Unmarshal(msg.Data, syncpid)
  141. //给当前客户端ID进行赋值
  142. this.Pid = syncpid.Pid
  143. } else if msg.MsgId == 200 {
  144. //服务器回执客户端广播数据
  145. //解析proto
  146. bdata := &pb.BroadCast{}
  147. proto.Unmarshal(msg.Data, bdata)
  148. //初次玩家上线 广播位置消息
  149. if bdata.Tp == 2 && bdata.Pid == this.Pid {
  150. //本人
  151. //更新客户端坐标
  152. this.X = bdata.GetP().X
  153. this.Y = bdata.GetP().Y
  154. this.Z = bdata.GetP().Z
  155. this.V = bdata.GetP().V
  156. fmt.Println(fmt.Sprintf("player ID: %d online.. at(%f,%f,%f,%f)", bdata.Pid, this.X, this.Y, this.Z, this.V))
  157. //自动AI业务
  158. go func() {
  159. for {
  160. this.AIRobotAction()
  161. time.Sleep(3 * time.Second)
  162. }
  163. }()
  164. } else if bdata.Tp == 1 {
  165. fmt.Println(fmt.Sprintf("世界聊天,玩家%d说的话是: %s", bdata.Pid, bdata.GetContent()))
  166. }
  167. }
  168. }
  169. func (this *TcpClient) Start() {
  170. go func() {
  171. for {
  172. //read per head data
  173. headdata := make([]byte, 8)
  174. if _, err := io.ReadFull(this.conn, headdata); err != nil {
  175. fmt.Println(err)
  176. return
  177. }
  178. pkgHead, err := this.Unpack(headdata)
  179. if err != nil {
  180. return
  181. }
  182. //data
  183. if pkgHead.Len > 0 {
  184. pkgHead.Data = make([]byte, pkgHead.Len)
  185. if _, err := io.ReadFull(this.conn, pkgHead.Data); err != nil {
  186. return
  187. }
  188. }
  189. //处理服务器回执业务
  190. this.DoMsg(pkgHead)
  191. }
  192. }()
  193. }
  194. func NewTcpClient(ip string, port int) *TcpClient {
  195. addrStr := fmt.Sprintf("%s:%d", ip, port)
  196. conn, err := net.Dial("tcp", addrStr)
  197. if err == nil {
  198. client := &TcpClient{
  199. conn: conn,
  200. Pid: 0,
  201. X: 0,
  202. Y: 0,
  203. Z: 0,
  204. V: 0,
  205. }
  206. return client
  207. } else {
  208. panic(err)
  209. }
  210. }
  211. func main() {
  212. for i := 0; i < 1000; i++ {
  213. client := NewTcpClient("127.0.0.1", 8999)
  214. client.Start()
  215. time.Sleep(1 * time.Second)
  216. }
  217. // close
  218. c := make(chan os.Signal, 1)
  219. signal.Notify(c, os.Interrupt, os.Kill)
  220. sig := <-c
  221. fmt.Println("=======", sig)
  222. }