完善服务器
This commit is contained in:
@@ -5,9 +5,7 @@ import (
|
||||
"common/discover"
|
||||
"common/log"
|
||||
"common/net/grpc/service"
|
||||
"common/net/socket/websocket"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/judwhite/go-svc"
|
||||
"runtime/debug"
|
||||
"scene/config"
|
||||
@@ -16,11 +14,9 @@ import (
|
||||
)
|
||||
|
||||
type Program struct {
|
||||
wg *sync.WaitGroup
|
||||
server service.IService // grpc服务
|
||||
webServer *gin.Engine // web服务
|
||||
wsServer *websocket.WSServer // websocket服务
|
||||
stop chan bool
|
||||
wg *sync.WaitGroup
|
||||
server service.IService // grpc服务
|
||||
stop chan bool
|
||||
}
|
||||
|
||||
func (p *Program) Init(_ svc.Environment) error {
|
||||
@@ -47,14 +43,6 @@ func (p *Program) Start() error {
|
||||
discover.Listen()
|
||||
p.server = grpc_server.NewServer(config.Get().Serve.Grpc.TTL)
|
||||
p.server.Init(config.Get().Serve.Grpc.Address, config.Get().Serve.Grpc.Port)
|
||||
go func() {
|
||||
cfg := config.Get()
|
||||
_ = p.wsServer.Run(
|
||||
log.GetLogger().Named("gnet"),
|
||||
fmt.Sprintf("tcp4://0.0.0.0:%v", cfg.Serve.Socket.Web.Port),
|
||||
true, true, false, false, true, 8,
|
||||
)
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
app:
|
||||
name: "gateway-dev"
|
||||
name: "scene-dev"
|
||||
|
||||
log:
|
||||
debug: true
|
||||
level: "debug"
|
||||
max_size: 100
|
||||
max_backups: 3
|
||||
max_age: 7
|
||||
maxSize: 100
|
||||
maxBackups: 3
|
||||
maxAge: 7
|
||||
|
||||
db:
|
||||
etcd:
|
||||
|
||||
@@ -13,9 +13,9 @@ type AppConfig struct {
|
||||
|
||||
type LogConfig struct {
|
||||
Debug bool `yaml:"debug"`
|
||||
MaxSize int `yaml:"max_size"`
|
||||
MaxBackups int `yaml:"max_backups"`
|
||||
MaxAge int `yaml:"max_age"`
|
||||
MaxSize int `yaml:"maxSize"`
|
||||
MaxBackups int `yaml:"maxBackups"`
|
||||
MaxAge int `yaml:"maxAge"`
|
||||
Level string `yaml:"level"`
|
||||
}
|
||||
|
||||
@@ -27,17 +27,8 @@ type DBConfig struct {
|
||||
|
||||
type ServeConfig struct {
|
||||
Grpc *struct {
|
||||
AddressConfig
|
||||
TTL int64 `yaml:"ttl"`
|
||||
Address string `yaml:"address"`
|
||||
Port int `yaml:"port"`
|
||||
TTL int64 `yaml:"ttl"`
|
||||
} `yaml:"grpc"`
|
||||
Socket *struct {
|
||||
Web *AddressConfig `yaml:"web"`
|
||||
Raw *AddressConfig `yaml:"raw"`
|
||||
} `yaml:"socket"`
|
||||
Http *AddressConfig `yaml:"http"`
|
||||
}
|
||||
|
||||
type AddressConfig struct {
|
||||
Address string `yaml:"address"`
|
||||
Port int `yaml:"port"`
|
||||
}
|
||||
|
||||
@@ -3,10 +3,43 @@ package grpc_server
|
||||
import (
|
||||
"common/log"
|
||||
"common/proto/gen/common"
|
||||
"common/proto/gen/grpc_pb"
|
||||
"context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"scene/instance"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func (s *Server) SendMessage(ctx context.Context, req *common.Empty) (*common.Empty, error) {
|
||||
log.Infof("未实现函数")
|
||||
return nil, nil
|
||||
func (s *Server) Enter(ctx context.Context, req *grpc_pb.EnterReq) (*grpc_pb.EnterResp, error) {
|
||||
log.Infof("enter 触发 %v", req.SID)
|
||||
return nil, status.Errorf(codes.Unimplemented, "")
|
||||
}
|
||||
|
||||
func (s *Server) Action(server grpc_pb.Scene_ActionServer) error {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
log.Errorf("Action panic: %v", err)
|
||||
}
|
||||
}()
|
||||
for {
|
||||
if args, err := server.Recv(); err != nil {
|
||||
return
|
||||
} else {
|
||||
if ins := instance.Mgr.GetByUniqueNo(args.UniqueNo); ins != nil {
|
||||
select {
|
||||
case ins.EventIn <- args:
|
||||
default:
|
||||
log.Warnf("instance event in full: %v, %v", ins.InstanceID, ins.UniqueNo)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
wg.Wait()
|
||||
return server.SendAndClose(&common.Empty{})
|
||||
}
|
||||
|
||||
@@ -8,14 +8,14 @@ import (
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
grpc_pb.UnimplementedGatewayServer
|
||||
grpc_pb.UnimplementedSceneServer
|
||||
service.Base
|
||||
}
|
||||
|
||||
func NewServer(ttl int64) *Server {
|
||||
s := &Server{
|
||||
Base: service.Base{
|
||||
Target: common.KeyDiscoverGateway,
|
||||
Target: common.KeyDiscoverScene,
|
||||
EtcdTTL: ttl,
|
||||
},
|
||||
}
|
||||
@@ -25,7 +25,7 @@ func NewServer(ttl int64) *Server {
|
||||
}
|
||||
|
||||
func (s *Server) OnInit(serve *grpc.Server) {
|
||||
grpc_pb.RegisterGatewayServer(serve, s)
|
||||
grpc_pb.RegisterSceneServer(serve, s)
|
||||
}
|
||||
|
||||
func (s *Server) OnClose() {
|
||||
|
||||
9
Server/scene/instance/define.go
Normal file
9
Server/scene/instance/define.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package instance
|
||||
|
||||
import "google.golang.org/protobuf/proto"
|
||||
|
||||
type Msg2Client struct {
|
||||
SID string
|
||||
UID int
|
||||
Msg proto.Message
|
||||
}
|
||||
97
Server/scene/instance/instance.go
Normal file
97
Server/scene/instance/instance.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package instance
|
||||
|
||||
import (
|
||||
"common/discover"
|
||||
"common/log"
|
||||
"common/proto/gen/grpc_pb"
|
||||
"common/utils"
|
||||
"context"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Instance 场景类
|
||||
type Instance struct {
|
||||
wg sync.WaitGroup
|
||||
players map[int]*PlayerNode // 存储所有玩家节点 [uid]
|
||||
ctx context.Context // 停止指令
|
||||
cancel context.CancelFunc // 停止函数
|
||||
|
||||
SID int64 // 服务ID
|
||||
InstanceID int // 副本ID
|
||||
UniqueNo int64 // 唯一编号
|
||||
EventIn chan proto.Message // 消息入口
|
||||
EventOut chan *Msg2Client // 消息出口
|
||||
}
|
||||
|
||||
// NewScene 初始化场景
|
||||
func NewScene(sid int64, instanceID int) *Instance {
|
||||
s := &Instance{
|
||||
players: make(map[int]*PlayerNode),
|
||||
SID: sid,
|
||||
InstanceID: instanceID,
|
||||
UniqueNo: utils.SnowflakeInstance().Generate().Int64(),
|
||||
EventIn: make(chan proto.Message),
|
||||
EventOut: make(chan *Msg2Client),
|
||||
}
|
||||
s.ctx, s.cancel = context.WithCancel(context.Background())
|
||||
return s
|
||||
}
|
||||
|
||||
func (i *Instance) Start(ttl int64) {
|
||||
i.wg.Add(1)
|
||||
go func() {
|
||||
defer i.wg.Done()
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
log.Infof("instance err: %v, uniqueNo: %v", err, i.UniqueNo)
|
||||
debug.PrintStack()
|
||||
}
|
||||
}()
|
||||
Mgr.Add(i.UniqueNo, i)
|
||||
defer func() {
|
||||
log.Infof("instance destroy: %v, %v", i.InstanceID, i.UniqueNo)
|
||||
discover.UnRegisterInstance(i.UniqueNo)
|
||||
close(i.EventIn)
|
||||
Mgr.Delete(i.UniqueNo)
|
||||
}()
|
||||
|
||||
if err := discover.RegisterInstance(i.SID, i.InstanceID, i.UniqueNo, ttl); err != nil {
|
||||
log.Errorf("register discover error")
|
||||
return
|
||||
}
|
||||
// 场景心跳
|
||||
tick := time.NewTicker(50 * time.Millisecond)
|
||||
for {
|
||||
select {
|
||||
case <-i.ctx.Done():
|
||||
return
|
||||
case <-tick.C:
|
||||
i.onLogic()
|
||||
case e := <-i.EventIn:
|
||||
i.onEvent(e)
|
||||
}
|
||||
}
|
||||
}()
|
||||
log.Infof("new scene start: %v, %v", i.InstanceID, i.UniqueNo)
|
||||
}
|
||||
|
||||
// 网络帧
|
||||
func (i *Instance) onEvent(e proto.Message) {
|
||||
switch v := e.(type) {
|
||||
case *grpc_pb.ActionReq:
|
||||
if node, ok := i.players[int(v.UID)]; ok {
|
||||
node.addAction(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 逻辑帧
|
||||
func (i *Instance) onLogic() {
|
||||
// 优先处理移动指令
|
||||
for _, node := range i.players {
|
||||
node.logicMove()
|
||||
}
|
||||
}
|
||||
42
Server/scene/instance/manager.go
Normal file
42
Server/scene/instance/manager.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package instance
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var Mgr *insManager
|
||||
|
||||
type insManager struct {
|
||||
sync.RWMutex
|
||||
insMap map[int64]*Instance // [uniqueNo]
|
||||
}
|
||||
|
||||
func init() {
|
||||
Mgr = &insManager{
|
||||
insMap: make(map[int64]*Instance),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *insManager) Add(uniqueNo int64, ins *Instance) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
m.insMap[uniqueNo] = ins
|
||||
}
|
||||
|
||||
func (m *insManager) Delete(uniqueNo int64) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
delete(m.insMap, uniqueNo)
|
||||
}
|
||||
|
||||
func (m *insManager) GetAll() map[int64]*Instance {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
return m.insMap
|
||||
}
|
||||
|
||||
func (m *insManager) GetByUniqueNo(uniqueNo int64) *Instance {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
return m.insMap[uniqueNo]
|
||||
}
|
||||
63
Server/scene/instance/player.go
Normal file
63
Server/scene/instance/player.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package instance
|
||||
|
||||
import (
|
||||
"common/proto/gen/grpc_pb"
|
||||
)
|
||||
|
||||
// PlayerNode 定义玩家节点结构体
|
||||
type PlayerNode struct {
|
||||
ID int
|
||||
Position [2]float64 // 二维坐标 [x, y]
|
||||
MoveCross int8 // 移动十字,1 上 2 下 4 左 8 右
|
||||
Action []*grpc_pb.ActionReq // 其他操作
|
||||
}
|
||||
|
||||
// 将指令存储到玩家身上
|
||||
func (p *PlayerNode) addAction(e *grpc_pb.ActionReq) {
|
||||
if e.Action < 16 {
|
||||
p.MoveCross = int8(e.Action)
|
||||
} else {
|
||||
p.Action = append(p.Action, e)
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
DirUp int8 = 1 << iota // 1 (00000001)
|
||||
DirDown // 2 (00000010)
|
||||
DirLeft // 4 (00000100)
|
||||
DirRight // 8 (00001000)
|
||||
)
|
||||
|
||||
// 逻辑帧-移动
|
||||
func (p *PlayerNode) logicMove() {
|
||||
if p.MoveCross&DirUp != 0 && p.MoveCross&DirDown != 0 {
|
||||
p.MoveCross &^= DirUp | DirDown
|
||||
}
|
||||
if p.MoveCross&DirLeft != 0 && p.MoveCross&DirRight != 0 {
|
||||
p.MoveCross &^= DirLeft | DirRight
|
||||
}
|
||||
|
||||
var moveX, moveY float64
|
||||
if p.MoveCross&DirUp != 0 {
|
||||
moveY += 1
|
||||
}
|
||||
if p.MoveCross&DirDown != 0 {
|
||||
moveY -= 1
|
||||
}
|
||||
if p.MoveCross&DirLeft != 0 {
|
||||
moveX -= 1
|
||||
}
|
||||
if p.MoveCross&DirRight != 0 {
|
||||
moveX += 1
|
||||
}
|
||||
|
||||
if moveX != 0 && moveY != 0 {
|
||||
const diagonalFactor = 0.7071
|
||||
moveX *= diagonalFactor
|
||||
moveY *= diagonalFactor
|
||||
}
|
||||
|
||||
speed := 100.0
|
||||
p.Position[0] += moveX * speed
|
||||
p.Position[1] += moveY * speed
|
||||
}
|
||||
Reference in New Issue
Block a user