98 lines
2.2 KiB
Go
98 lines
2.2 KiB
Go
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()
|
|
}
|
|
}
|