-
Notifications
You must be signed in to change notification settings - Fork 4
/
global_entity.go
142 lines (127 loc) · 4.57 KB
/
global_entity.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package game
import (
"fmt"
"github.com/fish-tennis/gentity"
. "github.com/fish-tennis/gnet"
"github.com/fish-tennis/gserver/cache"
"github.com/fish-tennis/gserver/db"
"github.com/fish-tennis/gserver/logger"
"github.com/fish-tennis/gserver/pb"
"google.golang.org/protobuf/proto"
"reflect"
"time"
)
const (
// mongo表名
GlobalEntityCollectionName = "global"
// global表的key
GlobalEntityCollectionKeyName = "key"
// GlobalEntity在redis里的前缀
GlobalEntityCachePrefix = GlobalEntityCollectionName
// GlobalEntity在mongo表里的key
GlobalEntityCollectionKey = "GlobalEntity"
)
// 演示全局类的非玩家实体
// 这里演示的GlobalEntity,每个game进程一个实例
type GlobalEntity struct {
gentity.BaseRoutineEntity
// 保存在global表中
globalDb gentity.EntityDb
// global表中的key
key string
}
func NewGlobalEntity() *GlobalEntity {
return &GlobalEntity{
BaseRoutineEntity: *gentity.NewRoutineEntity(32),
// NOTE: 需要在服务器初始化时调用mongoDb.RegisterEntityDb("global", "key")
globalDb: db.GetDbMgr().GetEntityDb(GlobalEntityCollectionName),
key: fmt.Sprintf("%v%v", GlobalEntityCollectionKey, gentity.GetApplication().GetId()),
}
}
func (this *GlobalEntity) LoadData(data interface{}) error {
_, err := this.globalDb.FindEntityById(this.key, data)
return err
}
func (this *GlobalEntity) SaveCache(kvCache gentity.KvCache) error {
// redis中的key
return this.BaseEntity.SaveCache(kvCache, GlobalEntityCachePrefix, this.key)
}
func (this *GlobalEntity) SaveDb(removeCacheAfterSaveDb bool) error {
return gentity.SaveEntityChangedDataToDbByKey(this.globalDb, this, this.key,
cache.Get(), removeCacheAfterSaveDb, GlobalEntityCachePrefix)
}
func (this *GlobalEntity) checkDataDirty() {
// 对于非玩家实体,数据修改后是保存缓存还是直接保存数据库,需要根据实际业务需求来决定
// 保存缓存不是必须的
// 这里直接保存数据库了
this.SaveDb(false)
//this.SaveCache(cache.Get())
}
func (this *GlobalEntity) RunRoutine() bool {
logger.Debug("GlobalEntity RunRoutine %v", this.key)
ok := this.RunProcessRoutine(this, &gentity.RoutineEntityRoutineArgs{
EndFunc: func(routineEntity gentity.RoutineEntity) {
logger.Debug("GlobalEntity Routine End %v", this.key)
},
ProcessMessageFunc: func(routineEntity gentity.RoutineEntity, message interface{}) {
this.processMessage(message.(*ProtoPacket))
this.checkDataDirty()
},
AfterTimerExecuteFunc: func(routineEntity gentity.RoutineEntity, t time.Time) {
this.checkDataDirty()
},
})
return ok
}
func (this *GlobalEntity) processMessage(message *ProtoPacket) {
defer func() {
if err := recover(); err != nil {
logger.Error("recover:%v", err)
logger.LogStack()
}
}()
logger.Debug("processMessage %v", proto.MessageName(message.Message()).Name())
// 先找组件接口
if gentity.ProcessComponentHandler(this, message.Command(), message.Message()) {
return
}
logger.Error("unhandle message:%v", message.Command())
}
// 从数据库加载的数据构造出GlobalEntity对象
func CreateGlobalEntityFromDb() *GlobalEntity {
globalEntity := NewGlobalEntity()
globalEntityData := &pb.GlobalEntityData{}
has, err := globalEntity.globalDb.FindEntityById(globalEntity.key, globalEntityData)
globalEntity = createGlobalEntityFromData(globalEntity, globalEntityData)
if err == nil && !has {
// 数据库还没数据,则插入一条新数据
newData := make(map[string]interface{})
newData[GlobalEntityCollectionKeyName] = globalEntity.key
gentity.GetEntitySaveData(globalEntity, newData)
globalEntity.globalDb.InsertEntity(globalEntity.key, newData)
}
return globalEntity
}
func CreateTempGlobalEntity() *GlobalEntity {
globalEntity := NewGlobalEntity()
globalEntityData := &pb.GlobalEntityData{}
return createGlobalEntityFromData(globalEntity, globalEntityData)
}
func createGlobalEntityFromData(globalEntity *GlobalEntity, globalEntityData *pb.GlobalEntityData) *GlobalEntity {
// 初始化各个模块
globalEntity.AddComponent(NewProcessStatInfo(globalEntity, globalEntityData.ProcessStatInfo), nil)
return globalEntity
}
// 注册GlobalEntity的结构体和消息回调
func InitGlobalEntityStructAndHandler() {
tmpGlobalEntity := CreateTempGlobalEntity()
tmpGlobalEntity.RangeComponent(func(component gentity.Component) bool {
gentity.GetSaveableStruct(reflect.TypeOf(component))
return true
})
gentity.AutoRegisterComponentHandler(tmpGlobalEntity, nil,
"", "Handle", "gserver")
}
func (this *GlobalEntity) GetProcessStatInfo() *ProcessStatInfo {
return this.GetComponentByName("ProcessStatInfo").(*ProcessStatInfo)
}