完善服务器

This commit is contained in:
2025-07-01 00:08:27 +08:00
parent b45eb83fe4
commit 7c2c32a31a
37 changed files with 1307 additions and 160 deletions

View File

@@ -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
}

View File

@@ -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:

View File

@@ -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"`
}

View File

@@ -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{})
}

View File

@@ -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() {

View File

@@ -0,0 +1,9 @@
package instance
import "google.golang.org/protobuf/proto"
type Msg2Client struct {
SID string
UID int
Msg proto.Message
}

View 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()
}
}

View 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]
}

View 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
}