server is a game server with horizontally-scalable and high-available. It was powered by go-micro and running in docker container.
- MongoDB
-
Download - git clone this repo and cd in its root path
-
Start MongoDB - running in
docker-compose
:
docker-compose run --service-ports -d mongo
- Start Gate - cd to
apps/gate
, run following command:
go run main.go
- Start Game - open another terminal session, cd to
apps/game
, run following command:
go run main.go
- Start Combat - open another terminal session, cd to
apps/combat
, run following command:
go run main.go
- Start Client - open another terminal session, cd to
apps/client
, run following command:
go run main.go
now you can communicate with server using (up down left right enter):
- first add a new store info
func init() {
// add store info
store.GetStore().AddStoreInfo(define.StoreType_Account, "account", "_id")
store.GetStore().AddStoreInfo(define.StoreType_Player, "player", "_id")
store.GetStore().AddStoreInfo(define.StoreType_Item, "item", "_id")
store.GetStore().AddStoreInfo(define.StoreType_Hero, "hero", "_id")
store.GetStore().AddStoreInfo(define.StoreType_Token, "token", "_id")
}
- load single object example
func (m *TokenManager) LoadAll() {
err := store.GetStore().FindOne(context.Background(), define.StoreType_Token, m.owner.GetID(), m)
if errors.Is(err, store.ErrNoResult) {
return nil
}
}
- load array example
func (m *HeroManager) LoadAll() error {
res, err := store.GetStore().FindAll(context.Background(), define.StoreType_Hero, "owner_id", m.owner.ID)
if errors.Is(err, store.ErrNoResult) {
return nil
}
if !utils.ErrCheck(err, "FindAll failed when HeroManager.LoadAll", m.owner.ID) {
return err
}
for _, v := range res {
vv := v.([]byte)
h := hero.NewHero()
err := json.Unmarshal(vv, h)
if !utils.ErrCheck(err, "Unmarshal failed when HeroManager.LoadAll") {
continue
}
if err := m.initLoadedHero(h); err != nil {
return fmt.Errorf("HeroManager LoadAll: %w", err)
}
}
return nil
}
- save example
func (m *HeroManager) AddHeroByTypeId(typeId int32) *hero.Hero {
heroEntry, ok := auto.GetHeroEntry(typeId)
if !ok {
log.Warn().Int32("type_id", typeId).Msg("GetHeroEntry failed")
return nil
}
// 重复获得卡牌,转换为对应碎片
_, ok = m.heroTypeSet[typeId]
if ok {
m.owner.FragmentManager().Inc(typeId, heroEntry.FragmentTransform)
return nil
}
h := m.createEntryHero(heroEntry)
if h == nil {
log.Warn().Int32("type_id", typeId).Msg("createEntryHero failed")
return nil
}
err := store.GetStore().UpdateOne(context.Background(), define.StoreType_Hero, h.Id, h)
if !utils.ErrCheck(err, "UpdateOne failed when AddHeroByTypeID", typeId, m.owner.ID) {
m.delHero(h)
return nil
}
m.SendHeroUpdate(h)
// prometheus ops
prom.OpsCreateHeroCounter.Inc()
return h
}
- save several fields example
func makeTokenKey(tp int32) string {
b := bytebufferpool.Get()
defer bytebufferpool.Put(b)
_, _ = b.WriteString("tokens.")
_, _ = b.WriteString(cast.ToString(tp))
return b.String()
}
func (m *TokenManager) save(tp int32) error {
fields := map[string]interface{}{
makeTokenKey(tp): m.Tokens[tp],
}
return store.GetStore().UpdateFields(context.Background(), define.StoreType_Token, m.owner.ID, fields)
}
server is MIT licensed.