gentity

package module
v1.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2024 License: MIT Imports: 22 Imported by: 9

README

gentity

实体对象的数据绑定(类似gorm),数据读写(序列化),缓存等接口,通过配置即可实现对象的数据保存加载,缓存更新,以简化业务编码,并使业务代码和数据库&缓存解耦

基于gentity,游戏服务器框架可以更快的构建

gentity

Entity-Component

Entity-Component模式是类似Unity的GameObject-Component的实体组件模式,便于组件解耦

比如游戏服务器中的玩家对象就属于Entity,玩家的任务模块就是一个Component

  • 组件模块注册
  • 组件消息回调接口注册
  • 组件事件分发
  • 组件事件响应接口注册

数据库和缓存

实体数据的加载和保存是游戏服务器最基础的功能,gentity利用go的struct tag,大大简化了实体数据加载和保存的接口

gentity抽象出了实体的数据库接口EntityDb和实体的缓存接口KvCache,并且可以自动检查增量更新,只把修改过的数据保存到数据库和缓存

gentity内置了EntityDb的mongodb实现,和KvCache的redis实现

数据绑定

类似gorm(go Object Relation Mapping)对SQL进行对象映射,gentity的数据绑定对组件进行数据库和缓存的映射

利用go的struct tag,设置对象组件的字段,框架接口会自动对这些字段进行数据库读取保存和缓存更新,极大的简化了业务代码对数据库和缓存的操作

设置组件保存数据

// entity的一个组件
type Money struct {
    DataComponent
    // 该字段必须导出(首字母大写)
    // 使用struct tag来标记该字段需要存数据库
    Data *pb.Money `db:""`
}

支持明文方式保存数据

// 玩家基础信息组件
type BaseInfo struct {
    DataComponent
    // plain表示明文存储,在保存到mongodb时,不会进行proto序列化
    Data *pb.BaseInfo `db:"plain"`
}

支持多个保存字段

// 任务组件
type Quest struct {
    BaseComponent
    // 保存数据的子模块:已完成的任务 使用明文保存方式
    // wrapper of []int32
    Finished *gentity.SliceData[int32] `child:"Finished;plain"`
    // 保存数据的子模块:当前任务列表
    // wrapper of map[int32]*pb.QuestData
    Quests *gentity.MapData[int32, *pb.QuestData] `child:"Quests"`
}

消息回调

支持自动注册消息回调,事件响应

// 客户端发给服务器的完成任务的消息回调
// 这种格式写的函数可以自动注册客户端消息回调
func (this *Quest) OnFinishQuestReq(reqCmd gnet.PacketCommand, req *pb.FinishQuestReq) {
	// logic code ...
}
// 这种格式写的函数可以自动注册非客户端的消息回调
func (this *BaseInfo) HandlePlayerEntryGameOk(cmd gnet.PacketCommand, msg *pb.PlayerEntryGameOk) { 
	// logic code ...
}
// 这种格式写的函数可以自动注册事件响应接口
// 当执行player.FireEvent(&EventPlayerEntryGame{})时,该响应接口会被调用
func (this *Quest) TriggerPlayerEntryGame(event *EventPlayerEntryGame) {
	// logic code ...
}

独立协程实体RoutineEntity

每个RoutineEntity分配一个独立的逻辑协程,在自己的独立协程中执行只涉及自身数据的代码,无需加锁

同时,RoutineEntity内置了一个协程安全的计时器

routine entity

示例:gserver 里的玩家对象Player

分布式实体DistributedEntity

分布式实体DistributedEntity在RoutineEntity的基础上增加了数据库加载接口,分布式锁接口

示例:gserver 里的公会对象Guild

distributed entity

项目演示

分布式游戏服务器框架gserver

讨论

QQ群: 764912827

Documentation

Index

Constants

View Source
const (
	DebugLevel int8 = iota - 1
	InfoLevel
	WarnLevel
	ErrorLevel
)

日志级别,参考zap

log level

Variables

View Source
var (
	ErrNotSaveableStruct     = errors.New("not saveable struct")
	ErrUnsupportedKeyType    = errors.New("unsupported key type")
	ErrUnsupportedType       = errors.New("unsupported type")
	ErrNotConnected          = errors.New("not connected")
	ErrSliceElemType         = errors.New("slice elem type error")
	ErrArrayLen              = errors.New("array len error")
	ErrNoUniqueColumn        = errors.New("no uniqueId column")
	ErrRouteServerId         = errors.New("route serverId error")
	ErrEntityNotExists       = errors.New("entity not exists")
	ErrConvertRoutineMessage = errors.New("convert routine message error")
	ErrSourceDataType        = errors.New("sourceData type error")
	ErrNotSaveable           = errors.New("not saveable")
)
View Source
var (
	// 单个保存字段的关键字
	KeywordDb = "db"
	// 子字段的关键字
	KeywordChild = "child"
	// 明文保存的关键字
	KeywordPlain = "plain"
)

定义数据的关键字,允许应用层自行修改

Functions

func ConvertInterfaceToRealType

func ConvertInterfaceToRealType(typ reflect.Type, v interface{}) interface{}

interface{} -> int or string or proto.Message

func ConvertStringToRealType added in v1.1.2

func ConvertStringToRealType(typ reflect.Type, v string) interface{}

支持int,float,string,[]byte,complex,bool,proto.Message

func ConvertValueToInt

func ConvertValueToInt(srcType reflect.Type, v reflect.Value) int64

reflect.Value -> int

func ConvertValueToInterface

func ConvertValueToInterface(srcType, dstType reflect.Type, srcValue reflect.Value) interface{}

reflect.Value -> interface{}

func FixEntityDataFromCache

func FixEntityDataFromCache(entity Entity, db EntityDb, kvCache KvCache, cacheKeyPrefix string, entityKey interface{})

根据缓存数据,修复数据 如:服务器crash时,缓存数据没来得及保存到数据库,服务器重启后读取缓存中的数据,保存到数据库,防止数据回档

func GetChildCacheKey

func GetChildCacheKey(parentName, childName string) string

func GetComponentSaveData

func GetComponentSaveData(component Component) (interface{}, error)

获取组件的完整保存数据

func GetComponentSaveName added in v1.1.7

func GetComponentSaveName(component Component) string

func GetEntityCacheKey added in v1.3.0

func GetEntityCacheKey(prefix string, entityId interface{}) string

func GetEntityComponentCacheKey

func GetEntityComponentCacheKey(prefix string, entityId interface{}, componentName string) string

获取对象组件的缓存key

func GetEntityComponentChildCacheKey

func GetEntityComponentChildCacheKey(prefix string, entityId interface{}, componentName string, childName string) string

获取对象组件子对象的缓存key

func GetEntitySaveData

func GetEntitySaveData(entity Entity, componentDatas map[string]interface{})

获取实体需要保存到数据库的完整数据

func GetFieldValue added in v1.4.0

func GetFieldValue(obj reflect.Value, fieldName string) reflect.Value

func GetSaveData

func GetSaveData(obj any, parentName string) (interface{}, error)

获取对象的完整保存数据

func IsDuplicateKeyError

func IsDuplicateKeyError(err error) bool

检查是否是key重复错误

func IsRedisError

func IsRedisError(redisError error) bool

检查redis返回的error是否是异常

func LoadEntityData added in v1.3.0

func LoadEntityData(entity Entity, entityData interface{}) error

func LoadFromCache

func LoadFromCache(obj interface{}, kvCache KvCache, cacheKey string, parentObj any) (bool, error)

从缓存中恢复数据

有缓存数据return true,否则return false
解析缓存数据错误return error,否则return nil

func LoadObjData added in v1.4.0

func LoadObjData(obj any, sourceData interface{}) error

func LogStack added in v0.2.0

func LogStack()

func MapDel added in v1.1.6

func MapDel[M ~map[K]V, K comparable, V any](mapDirtyMark MapDirtyMark, m M, k K)

map类型的数据的辅助接口,自动调用MapDirtyMark.SetDirty

func MapSet added in v1.2.0

func MapSet[M ~map[K]V, K comparable, V any](mapDirtyMark MapDirtyMark, m M, k K, v V)

map类型的数据的辅助接口,自动调用MapDirtyMark.SetDirty

func ParseEntitySaveableStruct added in v1.4.0

func ParseEntitySaveableStruct(entity Entity)

func SaveChangedDataToCache

func SaveChangedDataToCache(kvCache KvCache, obj any, cacheKeyName string, saveableField *SaveableField)

把修改数据保存到缓存

func SaveComponentChangedDataToCache

func SaveComponentChangedDataToCache(kvCache KvCache, cacheKeyPrefix string, entityKey interface{}, component Component)

把组件的修改数据保存到缓存

func SaveEntityChangedDataToDb

func SaveEntityChangedDataToDb(entityDb EntityDb, entity Entity, kvCache KvCache, removeCacheAfterSaveDb bool, cachePrefix string) error

Entity的变化数据保存到数据库

key为entity.GetId()

func SaveEntityChangedDataToDbByKey added in v1.1.0

func SaveEntityChangedDataToDbByKey(entityDb EntityDb, entity Entity, entityKey interface{}, kvCache KvCache, removeCacheAfterSaveDb bool, cachePrefix string) error

Entity的变化数据保存到数据库,只保存有数据变化的组件数据,但组件的数据不会分割,只要一个组件有数据变化,组件的数据就是全量覆盖

指定key

func SaveMapValueToCache added in v1.1.3

func SaveMapValueToCache(kvCache KvCache, cacheKeyName string, val reflect.Value, dirtyMark MapDirtyMark)

保存map类型字段到redis

func SaveObjectChangedDataToCache added in v1.3.0

func SaveObjectChangedDataToCache(kvCache KvCache, parentCacheKey string, obj any)

func SaveValueToCache added in v1.1.3

func SaveValueToCache(kvCache KvCache, cacheKeyName string, val reflect.Value)

保存单个字段到redis

func Set added in v1.2.0

func Set[Field cmp.Ordered](obj DirtyMark, field *Field, value Field)

func SetApplication added in v0.3.0

func SetApplication(application Application)

func SetFn added in v1.2.0

func SetFn(obj DirtyMark, setFieldValueFn func())

func SetLogLevel added in v1.3.0

func SetLogLevel(level int8)

func SetLogger

func SetLogger(w Logger, level int8)

Types

type Application added in v0.3.0

type Application interface {
	// 进程的唯一id
	GetId() int32

	GetContext() context.Context

	GetWaitGroup() *sync.WaitGroup

	// 初始化
	Init(ctx context.Context, configFile string) bool

	// 运行
	Run(ctx context.Context)

	// 定时更新
	OnUpdate(ctx context.Context, updateCount int64)

	// 退出
	Exit()
}

进程接口

func GetApplication added in v0.3.0

func GetApplication() Application

type ApplicationHook added in v0.3.0

type ApplicationHook interface {
	OnRegisterServerHandler(arg any)
	OnApplicationInit(initArg any)
	OnApplicationExit()
}

Application回调接口

type BaseComponent

type BaseComponent struct {
	// contains filtered or unexported fields
}

func NewBaseComponent added in v0.2.0

func NewBaseComponent(entity Entity, name string) *BaseComponent

func (*BaseComponent) GetEntity

func (this *BaseComponent) GetEntity() Entity

func (*BaseComponent) GetName

func (this *BaseComponent) GetName() string

组件名

func (*BaseComponent) SetEntity

func (this *BaseComponent) SetEntity(entity Entity)

type BaseDirtyMark

type BaseDirtyMark struct {
	// contains filtered or unexported fields
}

func (*BaseDirtyMark) IsChanged

func (this *BaseDirtyMark) IsChanged() bool

数据是否改变过

func (*BaseDirtyMark) IsDirty

func (this *BaseDirtyMark) IsDirty() bool

func (*BaseDirtyMark) ResetChanged

func (this *BaseDirtyMark) ResetChanged()

func (*BaseDirtyMark) ResetDirty

func (this *BaseDirtyMark) ResetDirty()

func (*BaseDirtyMark) SetDirty

func (this *BaseDirtyMark) SetDirty()

type BaseEntity

type BaseEntity struct {
	// Entity唯一id
	Id int64
	// contains filtered or unexported fields
}

func (*BaseEntity) AddComponent

func (this *BaseEntity) AddComponent(component Component)

func (*BaseEntity) AddEventReceiver added in v1.1.6

func (this *BaseEntity) AddEventReceiver(eventReceiver EventReceiver)

func (*BaseEntity) GetComponentByIndex

func (this *BaseEntity) GetComponentByIndex(componentIndex int) Component

func (*BaseEntity) GetComponentByName

func (this *BaseEntity) GetComponentByName(componentName string) Component

获取组件

func (*BaseEntity) GetComponents

func (this *BaseEntity) GetComponents() []Component

组件列表

func (*BaseEntity) GetId added in v0.2.0

func (this *BaseEntity) GetId() int64

Entity唯一id

func (*BaseEntity) RangeComponent

func (this *BaseEntity) RangeComponent(fun func(component Component) bool)

func (*BaseEntity) RangeEventReceiver added in v1.1.6

func (this *BaseEntity) RangeEventReceiver(f func(eventReceiver EventReceiver) bool)

func (*BaseEntity) SaveCache

func (this *BaseEntity) SaveCache(kvCache KvCache, cacheKeyPrefix string, entityKey interface{}) error

type BaseMapDirtyMark

type BaseMapDirtyMark struct {
	// contains filtered or unexported fields
}

func (*BaseMapDirtyMark) HasCached

func (this *BaseMapDirtyMark) HasCached() bool

func (*BaseMapDirtyMark) IsChanged

func (this *BaseMapDirtyMark) IsChanged() bool

func (*BaseMapDirtyMark) IsDirty

func (this *BaseMapDirtyMark) IsDirty() bool

func (*BaseMapDirtyMark) RangeDirtyMap

func (this *BaseMapDirtyMark) RangeDirtyMap(f func(dirtyKey interface{}, isAddOrUpdate bool))

func (*BaseMapDirtyMark) ResetChanged

func (this *BaseMapDirtyMark) ResetChanged()

func (*BaseMapDirtyMark) ResetDirty

func (this *BaseMapDirtyMark) ResetDirty()

func (*BaseMapDirtyMark) SetCached

func (this *BaseMapDirtyMark) SetCached()

func (*BaseMapDirtyMark) SetDirty

func (this *BaseMapDirtyMark) SetDirty(k interface{}, isAddOrUpdate bool)

type BaseRoutineEntity added in v0.3.0

type BaseRoutineEntity struct {
	BaseEntity
	// contains filtered or unexported fields
}

独立协程的实体

func NewRoutineEntity added in v0.2.0

func NewRoutineEntity(messageChanLen int) *BaseRoutineEntity

func (*BaseRoutineEntity) GetTimerEntries added in v0.3.0

func (this *BaseRoutineEntity) GetTimerEntries() *TimerEntries

func (*BaseRoutineEntity) PushMessage added in v0.3.0

func (this *BaseRoutineEntity) PushMessage(message any)

push a Message 将会在RoutineEntity的独立协程中被调用

func (*BaseRoutineEntity) RunProcessRoutine added in v0.3.0

func (this *BaseRoutineEntity) RunProcessRoutine(routineEntity RoutineEntity, routineArgs *RoutineEntityRoutineArgs) bool

开启消息处理协程 每个RoutineEntity一个独立的消息处理协程

func (*BaseRoutineEntity) Stop added in v0.3.0

func (this *BaseRoutineEntity) Stop()

停止协程

type Component

type Component interface {
	// 组件名
	GetName() string

	// 所属的实体
	GetEntity() Entity
	SetEntity(entity Entity)
}

实体组件接口

type ComponentCtor added in v1.1.5

type ComponentCtor[E Entity] func(entity E, arg any) Component

组件构造接口

type ComponentRegister added in v1.1.5

type ComponentRegister[E Entity] struct {
	RegisterInfos []*ComponentRegisterInfo[E]
}

组件注册信息管理

func (*ComponentRegister[E]) InitComponents added in v1.1.5

func (cr *ComponentRegister[E]) InitComponents(entity E, arg any)

初始化组件

func (*ComponentRegister[E]) Register added in v1.1.5

func (cr *ComponentRegister[E]) Register(componentName string, ctorOrder int, ctor ComponentCtor[E])

注册组件

type ComponentRegisterInfo added in v1.1.5

type ComponentRegisterInfo[E Entity] struct {
	// 组件名
	ComponentName string
	// 组件构造接口
	Ctor ComponentCtor[E]
	// 构造顺序,数值小的组件,先执行
	// 因为有的组件有依赖关系
	CtorOrder int
}

组件注册信息

type DataComponent

type DataComponent struct {
	BaseComponent
	BaseDirtyMark
}

func NewDataComponent

func NewDataComponent(entity Entity, componentName string) *DataComponent

type DbMgr

type DbMgr interface {
	GetEntityDb(name string) EntityDb
	GetKvDb(name string) KvDb
}

数据表管理接口

type DirtyMark

type DirtyMark interface {
	// 需要保存的数据是否修改了
	IsDirty() bool
	// 设置数据修改标记
	SetDirty()
	// 重置标记
	ResetDirty()
}

保存数据作为一个整体,只要一个字段修改了,整个数据都需要缓存

examples:

type ProteTest struct {
  BaseDirtyMark
  Data *pb.Data `db:"ProteTest"`
}

type MapTest struct {
  BaseDirtyMark
  Data map[int32]*pb.Data `db:"MapTest"`
}

type MapTest struct {
  BaseDirtyMark
  Data map[int32]string `db:"MapTest"`
}

type SliceTest struct {
  BaseDirtyMark
  Data []*pb.Data `db:"SliceTest"`
}

type DistributedEntityHelper added in v0.4.0

type DistributedEntityHelper interface {
	// 创建实体
	CreateEntity(entityData interface{}) RoutineEntity
	// 根据entityId路由到目标服务器
	// 返回值:服务器id
	RouteServerId(entityId int64) int32
}

DistributedEntity的回调接口

type DistributedEntityMgr added in v0.3.0

type DistributedEntityMgr struct {
	// contains filtered or unexported fields
}

分布式实体管理类

func NewDistributedEntityMgr added in v0.3.0

func NewDistributedEntityMgr(distributedLockName string,
	entityDb EntityDb,
	cache KvCache,
	routineArgs *RoutineEntityRoutineArgs,
	distributedEntityHelper DistributedEntityHelper) *DistributedEntityMgr

func (*DistributedEntityMgr) DeleteDistributeLocks added in v0.3.0

func (this *DistributedEntityMgr) DeleteDistributeLocks()

删除跟本服关联的分布式锁

func (*DistributedEntityMgr) DistributeLock added in v0.3.0

func (this *DistributedEntityMgr) DistributeLock(entityId int64) bool

分布式锁Lock redis实现的分布式锁,保证同一个实体的逻辑处理协程只会在一个服务器上

func (*DistributedEntityMgr) DistributeUnlock added in v0.3.0

func (this *DistributedEntityMgr) DistributeUnlock(entityId int64)

分布式锁UnLock

func (*DistributedEntityMgr) GetEntity added in v0.3.0

func (this *DistributedEntityMgr) GetEntity(entityId int64) RoutineEntity

获取已加载的分布式实体

func (*DistributedEntityMgr) GetEntityDb added in v0.3.0

func (this *DistributedEntityMgr) GetEntityDb() EntityDb

数据库接口

func (*DistributedEntityMgr) LoadEntity added in v0.3.0

func (this *DistributedEntityMgr) LoadEntity(entityId int64, entityData interface{}) RoutineEntity

加载分布式实体 加载成功后,开启独立协程

func (*DistributedEntityMgr) Range added in v0.3.0

func (this *DistributedEntityMgr) Range(f func(entity RoutineEntity) bool)

遍历

func (*DistributedEntityMgr) ReBalance added in v0.3.0

func (this *DistributedEntityMgr) ReBalance()

重新平衡 通知已不属于本服务器管理的实体关闭协程

func (*DistributedEntityMgr) StopAll added in v0.3.0

func (this *DistributedEntityMgr) StopAll()

关闭所有实体协程

type Entity

type Entity interface {
	// 唯一id
	GetId() int64

	AddComponent(component Component)

	// 查找某个组件
	GetComponentByName(componentName string) Component

	// 遍历组件
	RangeComponent(fun func(component Component) bool)
}

实体接口

type EntityDb

type EntityDb interface {
	// 根据id查找数据
	FindEntityById(entityKey interface{}, data interface{}) (bool, error)

	// 新建Entity(insert)
	InsertEntity(entityKey interface{}, entityData interface{}) (err error, isDuplicateKey bool)

	// 保存Entity数据(update entity by entityKey)
	SaveEntity(entityKey interface{}, entityData interface{}) error

	// 删除Entity数据(delete entity by entityKey)
	DeleteEntity(entityKey interface{}) error

	// 保存1个组件(update entity's component)
	SaveComponent(entityKey interface{}, componentName string, componentData interface{}) error

	// 批量保存组件(update entity's components...)
	SaveComponents(entityKey interface{}, components map[string]interface{}) error

	// 保存1个组件的一个字段(update entity's component.field)
	SaveComponentField(entityKey interface{}, componentName string, fieldName string, fieldData interface{}) error

	// 删除1个组件的某些字段
	DeleteComponentField(entityKey interface{}, componentName string, fieldName ...string) error
}

Entity的数据库接口

type EventHandlerInfo added in v1.1.6

type EventHandlerInfo struct {
	// 组件名,如果为空,就表示是直接写在Entity上的接口
	ComponentName string
	// 函数信息
	Method reflect.Method
	// 事件的reflect.Type
	EventType reflect.Type
}

组件事件响应接口信息

type EventHandlerMgr added in v1.1.6

type EventHandlerMgr struct {
	// contains filtered or unexported fields
}

组件事件响应接口管理类

func NewEventHandlerMgr added in v1.1.6

func NewEventHandlerMgr() *EventHandlerMgr

func (*EventHandlerMgr) AddHandlerInfo added in v1.1.6

func (this *EventHandlerMgr) AddHandlerInfo(handlerInfo *EventHandlerInfo)

func (*EventHandlerMgr) AutoRegister added in v1.1.6

func (this *EventHandlerMgr) AutoRegister(entity Entity, methodNamePrefix string)

扫描entity以及entity的组件,寻找匹配格式的事件响应接口

func (*EventHandlerMgr) Invoke added in v1.1.6

func (this *EventHandlerMgr) Invoke(entity Entity, evt any) bool

响应事件

如果没有注册对应事件的响应接口,return false

type EventReceiver

type EventReceiver interface {
	OnEvent(event interface{})
}

事件接口

type InterfaceMapLoader added in v1.1.7

type InterfaceMapLoader interface {
	// bytesMap: map[k][]byte
	LoadFromBytesMap(bytesMap any) error
}

map[k]any类型的字段,无法直接反序列化,因为不知道map的value具体是什么类型

因此提供一个自定义加载接口,由业务层自行实现特殊的反序列化逻辑 LoadFromCache处理map[k]any时,会把数据转换成map[k][]byte,传入LoadFromBytesMap 保存数据时,由于知道具体的value类型,所以无需特殊保存接口

type KvCache

type KvCache interface {
	// redis Get
	Get(key string) (string, error)

	// redis Set
	// value如果是proto.Message,会先进行序列化
	Set(key string, value interface{}, expiration time.Duration) error

	// redis SetNX
	// value如果是proto.Message,会先进行序列化
	SetNX(key string, value interface{}, expiration time.Duration) (bool, error)

	// redis Del
	Del(key ...string) (int64, error)

	// redis Type
	Type(key string) (string, error)

	// 缓存数据加载到map
	// m必须是一个类型明确有效的map,且key类型只能是int或string,value类型只能是int或string或proto.Message
	//
	// example:
	//   testDataMap := make(map[int64]*pb.TestData)
	//   HGetAll("myhash", testDataMap)
	GetMap(key string, m interface{}) error

	// map数据缓存
	// m必须是一个类型明确有效的map,且key类型只能是int或string,value类型只能是int或string或proto.Message
	// NOTE:批量写入数据,并不会删除之前缓存的数据
	//
	// example:
	//   - SetMap("myhash", map[int64]*pb.TestData{1:&pb.TestData{},2:&pb.TestData{}})
	//   - SetMap("myhash", map[string]interface{}{"key1": "value1", "key2": "value2"})
	SetMap(key string, m interface{}) error

	// redis HGetAll
	HGetAll(key string) (map[string]string, error)

	// redis HSet
	// HSet accepts values in following formats:
	//   - HSet("myhash", "key1", "value1", "key2", "value2")
	//   - HSet("myhash", []string{"key1", "value1", "key2", "value2"})
	//   - HSet("myhash", map[string]interface{}{"key1": "value1", "key2": "value2"})
	HSet(key string, values ...interface{}) (int64, error)

	// redis HSetNX
	HSetNX(key, field string, value interface{}) (bool, error)

	// 删除map的项
	HDel(key string, fields ...string) (int64, error)

	// 缓存数据加载到proto.Message
	GetProto(key string, value proto.Message) error
}

常用的kv缓存接口

type KvDb

type KvDb interface {
	Find(key interface{}) (interface{}, error)

	FindAndDecode(key interface{}, decodeData interface{}) error

	Insert(key interface{}, value interface{}) (err error, isDuplicateKey bool)

	Update(key interface{}, value interface{}, upsert bool) error

	Inc(key interface{}, value interface{}, upsert bool) (interface{}, error)

	Delete(key interface{}) error
}

Kv数据接口 游戏应用里,除了账号数据和玩家数据之外,其他以Key-Value存储的数据 KvDb接口是为了应用层能够灵活的更换存储数据库(mysql,mongo,redis等)

type Logger

type Logger interface {
	Debug(format string, args ...interface{})
	Info(format string, args ...interface{})
	Warn(format string, args ...interface{})
	Error(format string, args ...interface{})
}

func GetLogger added in v0.2.0

func GetLogger() Logger

func NewStdLogger added in v1.3.0

func NewStdLogger(callDepth int) Logger

type MapComponent added in v1.2.0

type MapComponent struct {
	BaseComponent
	BaseMapDirtyMark
}

func NewMapComponent added in v1.2.0

func NewMapComponent(entity Entity, componentName string) *MapComponent

type MapData added in v1.2.0

type MapData[K comparable, V any] struct {
	BaseMapDirtyMark
	Data map[K]V `db:""`
}

map类型的数据的辅助类

func NewMapData added in v1.2.0

func NewMapData[K comparable, V any]() *MapData[K, V]

func (*MapData[K, V]) Contains added in v1.3.0

func (md *MapData[K, V]) Contains(k K) bool

func (*MapData[K, V]) Delete added in v1.2.0

func (md *MapData[K, V]) Delete(k K)

delete(map, k)

func (*MapData[K, V]) Get added in v1.3.0

func (md *MapData[K, V]) Get(k K) (V, bool)

func (*MapData[K, V]) Init added in v1.2.0

func (md *MapData[K, V]) Init()

func (*MapData[K, V]) Range added in v1.3.0

func (md *MapData[K, V]) Range(fn func(k K, v V) bool)

func (*MapData[K, V]) Set added in v1.2.0

func (md *MapData[K, V]) Set(k K, v V)

map[k] = v

type MapDataComponent

type MapDataComponent[K comparable, V any] struct {
	BaseComponent
	*MapData[K, V] `db:""`
}

MapData+BaseComponent

func NewMapDataComponent

func NewMapDataComponent[K comparable, V any](entity Entity, componentName string) *MapDataComponent[K, V]

type MapDirtyMark

type MapDirtyMark interface {
	// 需要保存的数据是否修改了
	IsDirty() bool
	// 设置数据修改标记
	SetDirty(k interface{}, isAddOrUpdate bool)
	// 重置标记
	ResetDirty()

	// 是否把整体数据缓存过了
	HasCached() bool
	// 第一次有数据修改时,会把整体数据缓存一次,之后只保存修改过的项(增量更新)
	SetCached()

	RangeDirtyMap(f func(dirtyKey interface{}, isAddOrUpdate bool))
}

map格式的保存数据 第一次有数据修改时,会把整体数据缓存一次,之后只保存修改过的项(增量更新)

examples:

type MapTest struct {
  BaseMapDirtyMark
  Data map[int32]*pb.Data `db:"MapTest"`
}

type MapTest struct {
  BaseMapDirtyMark
  Data map[int32]string `db:"MapTest"`
}

type MapValueDirtyMark added in v1.4.0

type MapValueDirtyMark[K comparable] struct {
	// 父类才是真正的脏标记
	Parent MapDirtyMark
	MapKey K // key of parent map
}

用于InterfaceMap的map's value的DirtyMark

func NewMapValueDirtyMark added in v1.4.0

func NewMapValueDirtyMark[K comparable](parent MapDirtyMark, mapKey K) *MapValueDirtyMark[K]

func (*MapValueDirtyMark[K]) IsChanged added in v1.4.0

func (m *MapValueDirtyMark[K]) IsChanged() bool

只是为了实现Saveable接口,无实际作用

func (*MapValueDirtyMark[K]) ResetChanged added in v1.4.0

func (m *MapValueDirtyMark[K]) ResetChanged()

只是为了实现Saveable接口,无实际作用

func (*MapValueDirtyMark[K]) SetDirty added in v1.4.0

func (m *MapValueDirtyMark[K]) SetDirty()

设置脏标记,实际设置的是父类

type MongoCollection

type MongoCollection struct {
	// contains filtered or unexported fields
}

db.EntityDb的mongo实现

func (*MongoCollection) CreateIndex added in v0.5.0

func (this *MongoCollection) CreateIndex(key string, unique bool)

func (*MongoCollection) DeleteComponentField

func (this *MongoCollection) DeleteComponentField(entityKey interface{}, componentName string, fieldName ...string) error

删除1个组件的某些字段

func (*MongoCollection) DeleteEntity added in v1.1.7

func (this *MongoCollection) DeleteEntity(entityKey interface{}) error

func (*MongoCollection) FindEntityById

func (this *MongoCollection) FindEntityById(entityKey interface{}, data interface{}) (bool, error)

根据id查找数据

func (*MongoCollection) GetCollection

func (this *MongoCollection) GetCollection() *mongo.Collection

func (*MongoCollection) InsertEntity

func (this *MongoCollection) InsertEntity(entityKey interface{}, entityData interface{}) (err error, isDuplicateKey bool)

func (*MongoCollection) SaveComponent

func (this *MongoCollection) SaveComponent(entityKey interface{}, componentName string, componentData interface{}) error

func (*MongoCollection) SaveComponentField

func (this *MongoCollection) SaveComponentField(entityKey interface{}, componentName string, fieldName string, fieldData interface{}) error

func (*MongoCollection) SaveComponents

func (this *MongoCollection) SaveComponents(entityKey interface{}, components map[string]interface{}) error

func (*MongoCollection) SaveEntity

func (this *MongoCollection) SaveEntity(entityKey interface{}, entityData interface{}) error

func (*MongoCollection) Shard added in v1.1.7

func (this *MongoCollection) Shard() error

设置分片key

type MongoCollectionPlayer

type MongoCollectionPlayer struct {
	MongoCollection
	// contains filtered or unexported fields
}

db.PlayerDb的mongo实现

func (*MongoCollectionPlayer) FindAccountIdByPlayerId

func (this *MongoCollectionPlayer) FindAccountIdByPlayerId(playerId int64) (int64, error)

func (*MongoCollectionPlayer) FindPlayerByAccountId

func (this *MongoCollectionPlayer) FindPlayerByAccountId(accountId int64, regionId int32, playerData interface{}) (bool, error)

根据账号id查找玩家数据 适用于一个账号在一个区服只有一个玩家角色的游戏

func (*MongoCollectionPlayer) FindPlayerIdByAccountId

func (this *MongoCollectionPlayer) FindPlayerIdByAccountId(accountId int64, regionId int32) (int64, error)

func (*MongoCollectionPlayer) FindPlayerIdsByAccountId added in v0.2.0

func (this *MongoCollectionPlayer) FindPlayerIdsByAccountId(accountId int64, regionId int32) ([]int64, error)

type MongoDb

type MongoDb struct {
	// contains filtered or unexported fields
}

db.DbMgr的mongo实现

func NewMongoDb

func NewMongoDb(uri, dbName string) *MongoDb

func (*MongoDb) Connect

func (this *MongoDb) Connect() bool

func (*MongoDb) Disconnect

func (this *MongoDb) Disconnect()

func (*MongoDb) GetEntityDb

func (this *MongoDb) GetEntityDb(name string) EntityDb

func (*MongoDb) GetKvDb added in v0.4.0

func (this *MongoDb) GetKvDb(name string) KvDb

func (*MongoDb) GetMongoClient added in v0.5.0

func (this *MongoDb) GetMongoClient() *mongo.Client

func (*MongoDb) GetMongoDatabase

func (this *MongoDb) GetMongoDatabase() *mongo.Database

func (*MongoDb) RegisterEntityDb

func (this *MongoDb) RegisterEntityDb(collectionName string, hashedShardKey bool, uniqueId string) EntityDb

注册普通Entity对应的collection

func (*MongoDb) RegisterKvDb added in v0.4.0

func (this *MongoDb) RegisterKvDb(collectionName string, hashedShardKey bool, keyName, valueName string) KvDb

func (*MongoDb) RegisterPlayerDb added in v0.4.0

func (this *MongoDb) RegisterPlayerDb(collectionName string, hashedShardKey bool, playerId, accountId, region string) PlayerDb

注册玩家对应的collection

func (*MongoDb) ShardCollection added in v0.5.0

func (this *MongoDb) ShardCollection(collectionFullName, keyName string, hashedShardKey bool) error

设置database分片

func (*MongoDb) ShardDatabase added in v0.5.0

func (this *MongoDb) ShardDatabase(dbName string) error

设置database分片

type MongoKvDb added in v0.4.0

type MongoKvDb struct {
	// contains filtered or unexported fields
}

KvDb的mongo实现

func (*MongoKvDb) Delete added in v0.4.0

func (this *MongoKvDb) Delete(key interface{}) error

func (*MongoKvDb) Find added in v0.4.0

func (this *MongoKvDb) Find(key interface{}) (interface{}, error)

func (*MongoKvDb) FindAndDecode added in v0.4.0

func (this *MongoKvDb) FindAndDecode(key interface{}, decodeData interface{}) error

func (*MongoKvDb) GetCollection added in v0.4.0

func (this *MongoKvDb) GetCollection() *mongo.Collection

func (*MongoKvDb) Inc added in v0.4.0

func (this *MongoKvDb) Inc(key interface{}, value interface{}, upsert bool) (interface{}, error)

func (*MongoKvDb) Insert added in v0.4.0

func (this *MongoKvDb) Insert(key interface{}, value interface{}) (err error, isDuplicateKey bool)

func (*MongoKvDb) Shard added in v1.1.7

func (this *MongoKvDb) Shard() error

设置分片key

func (*MongoKvDb) Update added in v0.4.0

func (this *MongoKvDb) Update(key interface{}, value interface{}, upsert bool) error

type PlayerDb

type PlayerDb interface {
	EntityDb

	// 根据账号id查找角色id
	// 适用于一个账号在一个区服只有一个玩家角色的游戏
	FindPlayerIdByAccountId(accountId int64, regionId int32) (int64, error)

	// MMORPG类型的游戏,可能一个账号在一个服有多个角色
	FindPlayerIdsByAccountId(accountId int64, regionId int32) ([]int64, error)

	// 根据账号id查找玩家数据
	// 适用于一个账号在一个区服只有一个玩家角色的游戏
	FindPlayerByAccountId(accountId int64, regionId int32, playerData interface{}) (bool, error)

	// 根据角色id查找账号id
	FindAccountIdByPlayerId(playerId int64) (int64, error)
}

玩家数据接口 Db接口是为了应用层能够灵活的更换存储数据库(mysql,mongo,redis等)

type ProtoData added in v1.3.0

type ProtoData[E proto.Message] struct {
	BaseDirtyMark
	Data E `db:""`
}

保存数据是一个proto的辅助类

func NewProtoData added in v1.3.0

func NewProtoData[E proto.Message](e E) *ProtoData[E]

type RedisCache

type RedisCache struct {
	// contains filtered or unexported fields
}

KvCache的redis实现

func NewRedisCache

func NewRedisCache(redisClient redis.Cmdable) *RedisCache

func (*RedisCache) Del

func (this *RedisCache) Del(key ...string) (int64, error)

func (*RedisCache) Get

func (this *RedisCache) Get(key string) (string, error)

func (*RedisCache) GetMap

func (this *RedisCache) GetMap(key string, m interface{}) error

redis hash -> map

func (*RedisCache) GetProto

func (this *RedisCache) GetProto(key string, value proto.Message) error

func (*RedisCache) HDel added in v0.3.1

func (this *RedisCache) HDel(key string, fields ...string) (int64, error)

func (*RedisCache) HGetAll added in v0.3.1

func (this *RedisCache) HGetAll(key string) (map[string]string, error)

func (*RedisCache) HSet added in v0.3.1

func (this *RedisCache) HSet(key string, values ...interface{}) (int64, error)

func (*RedisCache) HSetNX added in v0.3.1

func (this *RedisCache) HSetNX(key, field string, value interface{}) (bool, error)

func (*RedisCache) Set

func (this *RedisCache) Set(key string, value interface{}, expiration time.Duration) error

func (*RedisCache) SetMap

func (this *RedisCache) SetMap(k string, m interface{}) error

map -> redis hash

func (*RedisCache) SetNX added in v0.3.1

func (this *RedisCache) SetNX(key string, value interface{}, expiration time.Duration) (bool, error)

func (*RedisCache) Type

func (this *RedisCache) Type(key string) (string, error)

type RoutineEntity added in v0.2.0

type RoutineEntity interface {
	Entity

	// push a Message
	// 将会在RoutineEntity的独立协程中被调用
	PushMessage(message any)

	// 开启消息处理协程
	// 每个RoutineEntity一个独立的消息处理协程
	RunProcessRoutine(routineEntity RoutineEntity, routineArgs *RoutineEntityRoutineArgs) bool

	// 停止协程
	Stop()
}

独立协程的实体接口

type RoutineEntityRoutineArgs added in v0.2.0

type RoutineEntityRoutineArgs struct {
	// 初始化,返回false时,协程不会启动
	InitFunc func(routineEntity RoutineEntity) bool
	// 消息处理函数
	ProcessMessageFunc func(routineEntity RoutineEntity, message any)
	// 有计时函数执行后调用
	AfterTimerExecuteFunc func(routineEntity RoutineEntity, t time.Time)
	// 协程结束时调用
	EndFunc func(routineEntity RoutineEntity)
}

RoutineEntity协程参数

type Saveable

type Saveable interface {
	// 数据是否改变过
	IsChanged() bool

	// 重置
	ResetChanged()
}

保存数据的接口 用于检查数据是否修改过

type SaveableDirtyMark

type SaveableDirtyMark interface {
	Saveable
	DirtyMark
}

同时需要保存数据库和缓存的接口 Saveable:

保存数据库的频率低,比如玩家下线时才会保存数据库,那么Saveable只会在上线期间记录有没有改变过就可以

DirtyMark:

缓存的保存频率高,比如玩家每一次操作都可能引起缓存的更新

type SaveableField

type SaveableField struct {
	StructField reflect.StructField
	// 如果该字段不是叶子节点,则SaveableStruct有值
	SaveableStruct *SaveableStruct
	FieldIndex     int
	// 是否明文保存
	IsPlain bool
	// 保存的字段名
	Name string
	// 节点深度
	Depth int32
	// contains filtered or unexported fields
}

字段

func (*SaveableField) InitNilField added in v1.1.6

func (this *SaveableField) InitNilField(val reflect.Value) bool

如果字段为nil,根据类型进行初始化

func (*SaveableField) IsInterfaceMap added in v1.1.7

func (this *SaveableField) IsInterfaceMap() bool

func (*SaveableField) NewBytesMap added in v1.1.7

func (this *SaveableField) NewBytesMap() any

map[k]any类型的字段,new一个map[k][]byte对象

type SaveableStruct

type SaveableStruct struct {
	// 单个db字段
	Field *SaveableField
	// 多个child字段
	Children []*SaveableField
	// 父节点
	ParentField *SaveableField
}

有需要保存字段的结构 SaveableStruct应该只针对第一层的对象(如Component),并设计为树型结构,在第一次解析结构时,就把层次关系记录下来

func GetObjSaveableStruct added in v1.4.0

func GetObjSaveableStruct(obj any) *SaveableStruct

获取对象的保存结构(一般对组件使用),如果没有保存字段,则返回nil

func (*SaveableStruct) GetChildSaveable added in v1.4.0

func (this *SaveableStruct) GetChildSaveable(obj any, childIndex int) (Saveable, *SaveableField)

func (*SaveableStruct) GetSingleSaveable added in v1.4.0

func (this *SaveableStruct) GetSingleSaveable(obj any) (Saveable, *SaveableField)

func (*SaveableStruct) IsSingleField

func (this *SaveableStruct) IsSingleField() bool

是否是单个db字段

type Sharding added in v1.1.7

type Sharding interface {
	Shard() error
}

type SliceData added in v1.2.0

type SliceData[E any] struct {
	BaseDirtyMark
	Data []E `db:""`
}

slice类型的数据的辅助类

func (*SliceData[E]) Add added in v1.2.0

func (sd *SliceData[E]) Add(v ...E)

func (*SliceData[E]) Delete added in v1.2.0

func (sd *SliceData[E]) Delete(i, j int)

see slices.Delete

type StdLogger added in v1.3.0

type StdLogger struct {
	// contains filtered or unexported fields
}

func (*StdLogger) Debug added in v1.3.0

func (s *StdLogger) Debug(format string, args ...interface{})

func (*StdLogger) Error added in v1.3.0

func (s *StdLogger) Error(format string, args ...interface{})

func (*StdLogger) Info added in v1.3.0

func (s *StdLogger) Info(format string, args ...interface{})

func (*StdLogger) Warn added in v1.3.0

func (s *StdLogger) Warn(format string, args ...interface{})

type TimerEntries

type TimerEntries struct {
	Timer *time.Timer
	// contains filtered or unexported fields
}

计时管理 参考https://github.com/robfig/cron 与cron主要用于任务计划不同,TimerEntries主要用于倒计时的管理 如果放在玩家的独立协程中使用,则倒计时的回调可以保证协程安全,使玩家的倒计时回调更简单

example:

go func() {
  defer timerEntries.Stop()
  timerEntries := NewTimerEntries()
  timerEntries.Start()
  for {
      select {
      case timeNow := <-timerEntries.TimerChan():
           timerEntries.Run(timeNow)
      case ...
      }
  }
}

func NewTimerEntries

func NewTimerEntries() *TimerEntries

func NewTimerEntriesWithArgs

func NewTimerEntriesWithArgs(nowFunc func() time.Time, minInterval time.Duration) *TimerEntries

func (*TimerEntries) AddTimer

func (this *TimerEntries) AddTimer(t time.Time, f TimerJob)

指定时间点执行回调

func (*TimerEntries) After

func (this *TimerEntries) After(d time.Duration, f TimerJob)

现在往后多少时间执行回调

func (*TimerEntries) GetMinInterval added in v0.6.1

func (this *TimerEntries) GetMinInterval() time.Duration

func (*TimerEntries) GetTimeOffset added in v0.6.1

func (this *TimerEntries) GetTimeOffset() time.Duration

func (*TimerEntries) Now added in v0.6.1

func (this *TimerEntries) Now() time.Time

func (*TimerEntries) Run

func (this *TimerEntries) Run(now time.Time) bool

func (*TimerEntries) SetMinInterval added in v0.6.1

func (this *TimerEntries) SetMinInterval(minInterval time.Duration)

func (*TimerEntries) SetTimeOffset added in v0.6.1

func (this *TimerEntries) SetTimeOffset(timeOffset time.Duration)

func (*TimerEntries) Start

func (this *TimerEntries) Start()

func (*TimerEntries) Stop

func (this *TimerEntries) Stop()

func (*TimerEntries) TimerChan

func (this *TimerEntries) TimerChan() <-chan time.Time

type TimerJob

type TimerJob func() time.Duration

倒计时回调函数 返回值:下一次执行的时间间隔,返回0表示该回调不会继续执行

Directories

Path Synopsis
pb

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL