feat 初次提交

This commit is contained in:
2026-01-03 14:26:11 +08:00
parent 5afccdb8de
commit 04a8fa2344
15 changed files with 602 additions and 0 deletions

126
internal/ws/client.go Normal file
View File

@@ -0,0 +1,126 @@
package ws
import (
"common/log"
"common/proto/sc/sc_pb"
"context"
"crypto/tls"
"errors"
"fmt"
"github.com/gorilla/websocket"
"google.golang.org/protobuf/proto"
)
type Client struct {
addr string
token string
conn *websocket.Conn
ctx context.Context
cancel context.CancelFunc
writeChaen chan []byte
}
func NewClient(addr string, token string) *Client {
c := &Client{
addr: addr,
token: token,
writeChaen: make(chan []byte, 1024),
}
c.ctx, c.cancel = context.WithCancel(context.Background())
return c
}
func (c *Client) Start() {
go func() {
dialer := websocket.DefaultDialer
dialer.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
conn, _, err := dialer.Dial(fmt.Sprintf("%v?token=%v", c.addr, c.token), nil)
if err != nil {
log.Errorf("connect error %v", err.Error())
return
}
c.conn = conn
_ = c.WriteMessage(sc_pb.MessageID_MESSAGE_ID_ENTER_INSTANCE, &sc_pb.C2S_EnterInstance{
InstanceID: 1,
})
go c.startReader()
go c.startWriter()
select {
case <-c.ctx.Done():
c.onStop()
return
}
}()
}
func (c *Client) startReader() {
for {
select {
case <-c.ctx.Done():
return
default:
_, msgByte, err := c.conn.ReadMessage()
if err != nil {
log.Errorf("read error quit %s", err)
c.Stop()
return
}
msg := &sc_pb.Message{}
if err = proto.Unmarshal(msgByte, msg); err != nil {
continue
}
if r, ok := router[msg.ID]; ok {
r.Handle(msg.Payload, c)
}
}
}
}
func (c *Client) startWriter() {
for {
select {
case data, ok := <-c.writeChaen:
if ok {
if err := c.conn.WriteMessage(websocket.BinaryMessage, data); err != nil {
log.Errorf("Send Buff Data error:, %s Conn Writer exit", err)
return
}
} else {
log.Errorf("msgBuffChan is Closed")
}
case <-c.ctx.Done():
return
}
}
}
// WriteMessage 发送消息给服务器
func (c *Client) WriteMessage(msgID sc_pb.MessageID, data proto.Message) error {
d, err := proto.Marshal(data)
if err != nil {
return err
}
p := &sc_pb.Message{
ID: msgID,
Payload: d,
}
marshal, _ := proto.Marshal(p)
select {
case c.writeChaen <- marshal:
default:
return errors.New("send buff chan is full")
}
return nil
}
func (c *Client) Stop() {
c.cancel()
}
func (c *Client) onStop() {
if err := c.conn.Close(); err != nil {
log.Errorf("close client error %v", err)
}
}

70
internal/ws/handler.go Normal file
View File

@@ -0,0 +1,70 @@
package ws
import (
"common/log"
"common/proto/sc/sc_pb"
"google.golang.org/protobuf/proto"
"math"
"math/rand"
"sync"
"time"
)
type EnterInstance struct {
}
func (_ *EnterInstance) Handle(data []byte, client *Client) {
msg := &sc_pb.S2C_EnterInstance{}
if err := proto.Unmarshal(data, msg); err != nil {
log.Errorf("handle msg error")
client.Stop()
return
}
randDir := func() (float64, float64) {
randX := float64(rand.Intn(201) - 100)
randY := float64(rand.Intn(201) - 100)
var normalizedX, normalizedY float64
if length := math.Sqrt(randX*randX + randY*randY); length > 0 {
normalizedX = randX / length
normalizedY = randY / length
}
return normalizedX, normalizedY
}
go func() {
for {
x, y := randDir()
_ = client.WriteMessage(sc_pb.MessageID_MESSAGE_ID_ACTION, &sc_pb.C2S_Action{
Sequence: 0,
Timestamp: 0,
Action: sc_pb.ActionID_ACTION_ID_MOVE,
DirX: int32(x * 100),
DirY: int32(y * 100),
SkillID: 0,
})
time.Sleep(500 * time.Millisecond)
}
}()
}
var s2cPositionPool = sync.Pool{
New: func() interface{} {
return &sc_pb.Message{}
},
}
type Position struct {
}
func (_ *Position) Handle(data []byte, client *Client) {
//msg := s2cPositionPool.Get().(*sc_pb.Message)
//if err := proto.Unmarshal(data, msg); err != nil {
// log.Errorf("handle msg error")
// client.Stop()
// return
//}
//s2cPositionPool.Put(msg)
}

28
internal/ws/manager.go Normal file
View File

@@ -0,0 +1,28 @@
package ws
import (
"common/utils"
"robot/config"
"strconv"
"time"
)
type Manager struct {
addr string
}
func NewManager(addr string) *Manager {
c := &Manager{
addr: addr,
}
return c
}
func (c *Manager) Start() {
cfg := config.Get().Client
for i := int32(0); i < cfg.Count; i++ {
client := NewClient(c.addr, strconv.Itoa(utils.RandInt(int(cfg.USN[0]), int(cfg.USN[1]))))
client.Start()
time.Sleep(time.Millisecond * 10)
}
}

15
internal/ws/router.go Normal file
View File

@@ -0,0 +1,15 @@
package ws
import "common/proto/sc/sc_pb"
var router map[sc_pb.MessageID]BaseRouter
type BaseRouter interface {
Handle(data []byte, client *Client)
}
func init() {
router = make(map[sc_pb.MessageID]BaseRouter)
router[sc_pb.MessageID_MESSAGE_ID_ENTER_INSTANCE] = &EnterInstance{}
router[sc_pb.MessageID_MESSAGE_ID_POSITION] = &Position{}
}