商队修改

This commit is contained in:
meixiongfeng 2023-04-27 17:03:02 +08:00
parent 91fd5c0823
commit 041bcb7d37
11 changed files with 175 additions and 287 deletions

View File

@ -10,7 +10,7 @@
"n": 1 "n": 1
} }
], ],
"action": "25004_cheer_act", "action": "ceshi",
"stage": 1 "stage": 1
}, },
{ {
@ -24,7 +24,7 @@
"n": 2 "n": 2
} }
], ],
"action": "25004_cheer_act", "action": "ceshi",
"stage": 2 "stage": 2
}, },
{ {
@ -38,7 +38,21 @@
"n": 3 "n": 3
} }
], ],
"action": "25004_cheer_act", "action": "ceshi",
"stage": 3
},
{
"key": 4,
"id_tag": 2,
"active": 160,
"reword": [
{
"a": "item",
"t": "60002",
"n": 4
}
],
"action": "ceshi",
"stage": 3 "stage": 3
} }
] ]

View File

@ -968,7 +968,7 @@
}, },
"type": 61, "type": 61,
"valid": 0, "valid": 0,
"NPC": 102, "NPC": 105,
"data1": 1100105, "data1": 1100105,
"data2": 0, "data2": 0,
"data3": 0, "data3": 0,
@ -1704,7 +1704,7 @@
}, },
"type": 61, "type": 61,
"valid": 0, "valid": 0,
"NPC": 102, "NPC": 105,
"data1": 1100106, "data1": 1100106,
"data2": 0, "data2": 0,
"data3": 0, "data3": 0,

View File

@ -55,6 +55,20 @@
], ],
"goto": 0 "goto": 0
}, },
{
"id": 105,
"heroid": 44004,
"datas": [
"CommandScene",
"主线入口_原石",
"905"
],
"event": [
10,
166
],
"goto": 0
},
{ {
"id": 10010, "id": 10010,
"heroid": 25001, "heroid": 25001,
@ -257,7 +271,7 @@
"datas": [ "datas": [
"GameMain", "GameMain",
"20070_骇客蛛_1", "20070_骇客蛛_1",
"905" "901"
], ],
"event": [ "event": [
2, 2,

View File

@ -10,7 +10,7 @@
"n": 1 "n": 1
} }
], ],
"action": "25004_cheer_act", "action": "ceshi",
"stage": 1 "stage": 1
}, },
{ {
@ -24,7 +24,7 @@
"n": 2 "n": 2
} }
], ],
"action": "25004_cheer_act", "action": "ceshi",
"stage": 2 "stage": 2
}, },
{ {
@ -38,7 +38,21 @@
"n": 3 "n": 3
} }
], ],
"action": "25004_cheer_act", "action": "ceshi",
"stage": 3
},
{
"key": 4,
"id_tag": 2,
"active": 160,
"reword": [
{
"a": "item",
"t": "60002",
"n": 4
}
],
"action": "ceshi",
"stage": 3 "stage": 3
} }
] ]

View File

@ -3,166 +3,22 @@ package caravan
import ( import (
"go_dreamfactory/comm" "go_dreamfactory/comm"
"go_dreamfactory/pb" "go_dreamfactory/pb"
"go_dreamfactory/sys/configure"
"math"
) )
//参数校验 //参数校验
func (this *apiComp) BuyOrSellCheck(session comm.IUserSession, req *pb.TrollBuyOrSellReq) (code pb.ErrorCode) { func (this *apiComp) BuyOrSellCheck(session comm.IUserSession, req *pb.CaravanBuyOrSellReq) (code pb.ErrorCode) {
if len(req.Items) == 0 { if len(req.Items) == 0 {
code = pb.ErrorCode_ReqParameterError code = pb.ErrorCode_ReqParameterError
} }
return return
} }
func (this *apiComp) BuyOrSell(session comm.IUserSession, req *pb.TrollBuyOrSellReq) (code pb.ErrorCode, data *pb.ErrorData) { func (this *apiComp) BuyOrSell(session comm.IUserSession, req *pb.CaravanBuyOrSellReq) (code pb.ErrorCode, data *pb.ErrorData) {
var (
bSell bool // 是否有出售 //update := make(map[string]interface{})
gold int32 // 当次交易 获得的金币
earn int32 // 只统计赚的金币
update map[string]interface{}
gridNum int32 // 格子数量
trolltrain *pb.DBTrollTrain
)
update = make(map[string]interface{})
if code = this.BuyOrSellCheck(session, req); code != pb.ErrorCode_Success { if code = this.BuyOrSellCheck(session, req); code != pb.ErrorCode_Success {
return // 参数校验失败直接返回 return // 参数校验失败直接返回
} }
_, err := this.module.modelCaravan.getCaravanList(session.GetUserId())
if err != nil {
code = pb.ErrorCode_DBError
return
}
dayMaxCount := this.configure.GetTrollRule(comm.TrollBuyCount)
aiMaxCount := this.configure.GetTrollRule(comm.TrollAIBuyCount)
for k, v := range req.Items {
if v == 0 { // 过滤数量为0 的消息
continue
}
if trolltrain.RangeId == 0 {
trolltrain.RangeId = 1
update["rangeId"] = trolltrain.RangeId
}
if v < 0 {
if !bSell {
bSell = true
trolltrain.SellCount += 1 // 交易次数+1
if trolltrain.SellCount > dayMaxCount || (trolltrain.SellCount+trolltrain.AiCount) > aiMaxCount {
code = pb.ErrorCode_TrollMaxSellCount // 达到最大交易次数 直接返回
return
}
update["sellCount"] = trolltrain.SellCount
}
}
if _, ok := trolltrain.Shop[k]; !ok {
if v > 0 {
trolltrain.Shop[k] = v // 限购
}
} else {
if v > 0 {
trolltrain.Shop[k] += v // 限购
}
}
// 校验 是否大于买入最大限制
goods := this.configure.GetTrollGoods(k)
if goods == nil {
return
}
if trolltrain.Shop[k] > goods.Max { // 判断是否有效交易
// 买入上限 直接返回
code = pb.ErrorCode_TrollBuyMax
return
} else if trolltrain.Items[k]+v < 0 { //卖出数量不足
code = pb.ErrorCode_TrollSellMax
return
}
// 第一次购买商品
if trolltrain.TarinPos == 0 {
if _, ok := trolltrain.Price[k]; !ok {
trolltrain.Price[k] = 0
}
trolltrain.Price[k] = goods.Goodsprice * goods.StarMoney / 1000
trolltrain.RefreshTime = configure.Now().Unix()
//消耗的金币
gold -= trolltrain.Price[k] * trolltrain.Items[k]
} else {
p := this.configure.GetTrollCoefficient(trolltrain.RangeId)
if p == nil {
return
}
var sellPrice int32 // 交易价格
if trolltrain.TarinPos == 0 {
sellPrice = goods.Goodsprice * goods.StarMoney / 1000
} else {
sellPrice = int32(p.Coefficient) * goods.Goodsprice / 1000
}
// 校验是不是惊喜价格
if d1, ok := trolltrain.SurpriseID[trolltrain.TarinPos-1]; ok {
if d1 == k {
sellPrice = this.configure.GetTrollRule(comm.TrollSurprise) / 1000
}
}
if v < 0 { // 卖出
trolltrain.Items[k] += v
if sellPrice > trolltrain.Price[k] { // 赚了
earn += (sellPrice - trolltrain.Price[k]) * v
}
gold -= sellPrice * v
} else { // 买入 计算平均价格
totalGold := trolltrain.Items[k] * trolltrain.Price[k]
totalGold += v * sellPrice
trolltrain.Items[k] += v
trolltrain.Price[k] = totalGold / trolltrain.Items[k]
gold -= v * sellPrice
}
}
}
// 重新计算格子数量
grid := this.configure.GetTrollRule(comm.TrollItemCount)
for _, v := range trolltrain.Items {
if v > 0 {
gridNum += int32(math.Ceil(float64(v) / float64(grid)))
}
}
trolltrain.GridNum = gridNum
if gridNum > this.configure.GetTrollRule(comm.TrollGridCount) { // 背包格子上限
code = pb.ErrorCode_TrollMaxItemCount
return
}
code = this.module.ModuleUser.AddAttributeValue(session, comm.ResGold, int32(gold), true)
if code != pb.ErrorCode_Success { // 金币不足
code = pb.ErrorCode_GoldNoEnough
return
}
// 清除数量为0 的
for k, v := range trolltrain.Items {
if v == 0 {
delete(trolltrain.Items, k)
if _, ok := trolltrain.Price[k]; ok {
delete(trolltrain.Price, k) // 清除价格
}
}
}
trolltrain.TotalEarn += -int64(earn) // 累计获得的金币
// check npc level
if confLv := this.configure.GetTrollLv(trolltrain.GetNpcLv() + 1); confLv != nil {
if trolltrain.TotalEarn >= int64(confLv.Money) {
trolltrain.NpcLv += 1 // npc levelUp
update["npcLv"] = trolltrain.NpcLv
}
}
update["items"] = trolltrain.Items
update["price"] = trolltrain.Price
update["totalEarn"] = trolltrain.TotalEarn
update["gridNum"] = trolltrain.GridNum
update["shop"] = trolltrain.Shop
//this.module.ModifyTrollData(session.GetUserId(), update)
// this.module.ModuleRtask.SendToRtask(session, comm.Rtype153, 1) // this.module.ModuleRtask.SendToRtask(session, comm.Rtype153, 1)
go this.module.ModuleRtask.TriggerTask(session.GetUserId(), comm.GettaskParam(comm.Rtype153, 1)) go this.module.ModuleRtask.TriggerTask(session.GetUserId(), comm.GettaskParam(comm.Rtype153, 1))

View File

@ -6,7 +6,6 @@ import (
"go_dreamfactory/modules" "go_dreamfactory/modules"
"go_dreamfactory/sys/configure" "go_dreamfactory/sys/configure"
cfg "go_dreamfactory/sys/configure/structs" cfg "go_dreamfactory/sys/configure/structs"
"sync"
) )
const ( const (
@ -14,17 +13,10 @@ const (
game_caravan_lv = "game_itinerant_lv.json" game_caravan_lv = "game_itinerant_lv.json"
game_caravan_reward = "game_itinerant_reward.json" game_caravan_reward = "game_itinerant_reward.json"
game_caravan_thing = "game_itinerant_thing.json" game_caravan_thing = "game_itinerant_thing.json"
game_trollgoods = "game_trollgoods.json"
game_trollcoefficient = "game_trollcoefficient.json"
game_trolltrain = "game_trolltrain.json"
game_trollrule = "game_trollrule.json"
game_trolllv = "game_trolllv.json"
) )
///配置管理基础组件 ///配置管理基础组件
type configureComp struct { type configureComp struct {
hlock sync.RWMutex
modules.MCompConfigure modules.MCompConfigure
} }
@ -53,133 +45,66 @@ func (this *configureComp) GetConfigure(name string) (v interface{}, err error)
} }
// 获取列车货物信息 // 获取列车货物信息
func (this *configureComp) GetTrollGoods(itemId int32) (data *cfg.GameTrollGoodsData) { func (this *configureComp) GetCaravanCity(cityId int32) (data *cfg.Gameitinerant_cityData) {
if v, err := this.GetConfigure(game_trollgoods); err == nil { if v, err := this.GetConfigure(game_caravan); err == nil {
if configure, ok := v.(*cfg.GameTrollGoods); ok { if configure, ok := v.(*cfg.Gameitinerant_city); ok {
data = configure.Get(cityId)
return
}
} else {
log.Errorf("get GetCaravanCity conf err:%v", err)
}
return
}
// 获取货物基本信息
func (this *configureComp) GetCaravanLv(lv int32) (data *cfg.Gameitinerant_lvData) {
if v, err := this.GetConfigure(game_caravan_lv); err == nil {
if configure, ok := v.(*cfg.Gameitinerant_lv); ok {
data = configure.Get(lv)
return
}
} else {
log.Errorf("get GetCaravanGoods conf err:%v", err)
}
return
}
func (this *configureComp) GetCaravanGoods(itemId int32) (data *cfg.Gameitinerant_thingData) {
if v, err := this.GetConfigure(game_caravan_thing); err == nil {
if configure, ok := v.(*cfg.Gameitinerant_thing); ok {
data = configure.Get(itemId) data = configure.Get(itemId)
return return
} }
} else { } else {
log.Errorf("get GameTrollGoodsData conf err:%v", err) log.Errorf("get GetCaravanGoods conf err:%v", err)
} }
return return
} }
// 获取商人位置信息 func (this *configureComp) GetAllCaravanCity() (data []*cfg.Gameitinerant_cityData) {
func (this *configureComp) GetTrollTrain(id int32) (data *cfg.GameTrollTrainData) { if v, err := this.GetConfigure(game_caravan); err == nil {
if v, err := this.GetConfigure(game_trolltrain); err == nil { if configure, ok := v.(*cfg.Gameitinerant_city); ok {
if configure, ok := v.(*cfg.GameTrollTrain); ok {
data = configure.Get(id)
return
}
} else {
log.Errorf("get GameTrollTrainData conf err:%v", err)
}
return
}
// 获取基本规则
func (this *configureComp) GetTrollRule(id int32) int32 {
if v, err := this.GetConfigure(game_trollrule); err == nil {
if configure, ok := v.(*cfg.GameTrollRule); ok {
return configure.Get(id).Quantity
}
}
log.Errorf("get GetTrollRule conf err:%d", id)
return 1
}
func (this *configureComp) GetTrollCoefficient(id int32) (data *cfg.GameTrollCoefficientData) {
if v, err := this.GetConfigure(game_trollcoefficient); err == nil {
if configure, ok := v.(*cfg.GameTrollCoefficient); ok {
data = configure.Get(id)
return
}
} else {
log.Errorf("get GameTrollCoefficientData conf err:%v", err)
}
return
}
func (this *configureComp) GetTrollLv(id int32) (data *cfg.GameTrollLvData) {
if v, err := this.GetConfigure(game_trolllv); err == nil {
if configure, ok := v.(*cfg.GameTrollLv); ok {
data = configure.Get(id)
return
}
} else {
log.Errorf("get GameTrollCoefficientData conf err:%v", err)
}
return
}
func (this *configureComp) GetTrollAllTrain() (data []int32) {
data = make([]int32, 0)
if v, err := this.GetConfigure(game_trolltrain); err == nil {
if configure, ok := v.(*cfg.GameTrollTrain); ok {
for _, v := range configure.GetDataList() { for _, v := range configure.GetDataList() {
time := v.Time data = append(data, v)
data = append(data, time)
} }
return return
} }
} else { } else {
log.Errorf("get GameTrollTrainData conf err:%v", err) log.Errorf("get GetAllCaravanCity conf err:%v", err)
} }
return return
} }
func (this *configureComp) GetAllCaravanItem() (data []*cfg.Gameitinerant_thingData) {
func (this *configureComp) GetTrollMaxCoefficientNux() int32 { if v, err := this.GetConfigure(game_caravan_thing); err == nil {
if v, err := this.GetConfigure(game_trollcoefficient); err == nil { if configure, ok := v.(*cfg.Gameitinerant_thing); ok {
if configure, ok := v.(*cfg.GameTrollCoefficient); ok {
return int32(len(configure.GetDataList()))
}
} else {
log.Errorf("get GameTrollTrainData conf err:%v", err)
}
return 0
}
// 获取车站的数量
func (this *configureComp) GetTrollMaxTraintNum() int32 {
if v, err := this.GetConfigure(game_trolltrain); err == nil {
if configure, ok := v.(*cfg.GameTrollTrain); ok {
return int32(len(configure.GetDataList()))
}
} else {
log.Errorf("get GameTrollTrainData conf err:%v", err)
}
return 1 // 至少有1个车站
}
func (this *configureComp) GetTrollAllGoods() (data []*cfg.GameTrollGoodsData) {
if v, err := this.GetConfigure(game_trollgoods); err == nil {
if configure, ok := v.(*cfg.GameTrollGoods); ok {
data = configure.GetDataList()
return
}
} else {
log.Errorf("get GameTrollGoodsData conf err:%v", err)
}
return
}
// 返回商人货物信息
func (this *configureComp) GetTrollGoodsFor(trainID int32) (data []int32) {
if v, err := this.GetConfigure(game_trollgoods); err == nil {
if configure, ok := v.(*cfg.GameTrollGoods); ok {
for _, v := range configure.GetDataList() { for _, v := range configure.GetDataList() {
if v.Goodsfor == trainID { data = append(data, v)
data = append(data, v.Id)
}
} }
return return
} }
} else { } else {
log.Errorf("get GameTrollGoodsData conf err:%v", err) log.Errorf("get GetAllCaravanItem conf err:%v", err)
} }
return return
} }

View File

@ -44,7 +44,9 @@ func (this *modelCaravan) getCaravanList(uid string) (result *pb.DBCaravan, err
if err = this.Get(uid, result); err != nil && mgo.MongodbNil == err { if err = this.Get(uid, result); err != nil && mgo.MongodbNil == err {
// 创建一条数据 // 创建一条数据
result.Resettime = configure.Now().Unix() // 设置起始刷新时间 result.Resettime = configure.Now().Unix() // 设置起始刷新时间
result.Lv = 1 // 初始1级 result.Lv = 1
this.module.InitCaravanCityData(uid, result) // 初始1级
this.module.InitCaravanItemData(uid, result)
err = this.Add(uid, result) err = this.Add(uid, result)
return return
} }

View File

@ -5,6 +5,8 @@ import (
"go_dreamfactory/lego/core" "go_dreamfactory/lego/core"
"go_dreamfactory/modules" "go_dreamfactory/modules"
"go_dreamfactory/pb" "go_dreamfactory/pb"
"go_dreamfactory/sys/configure"
"go_dreamfactory/utils"
) )
type Caravan struct { type Caravan struct {
@ -43,3 +45,62 @@ func (this *Caravan) ModifyCaravanData(uid string, data map[string]interface{})
} }
return return
} }
// 初始化城市信息
func (this *Caravan) InitCaravanCityData(uid string, data *pb.DBCaravan) {
list := this.configure.GetAllCaravanCity()
data.City = make(map[int32]*pb.CityGoods, 0)
for _, v := range list {
city := &pb.CityGoods{
Like: []int32{},
Unlike: []int32{},
}
if v.Citytype == 1 { //
city.Like = append(city.Like, v.Special...)
city.Unlike = append(city.Like, v.Exspecial...)
} else { // 不喜欢的 随机 citytypenum 个
if len(v.Special) > int(v.Citytypenum) {
ids := utils.RandomNumbers(0, len(v.Special), int(v.Citytypenum))
for _, id := range ids {
city.Like = append(city.Like, v.Special[id])
}
} else {
city.Like = append(city.Like, v.Special...)
}
if len(v.Exspecial) > int(v.Exspecialnum) {
ids := utils.RandomNumbers(0, len(v.Exspecial), int(v.Exspecialnum))
for _, id := range ids {
city.Like = append(city.Like, v.Exspecial[id])
}
} else {
city.Unlike = append(city.Like, v.Exspecial...)
}
}
data.City[v.Id] = city
}
}
// 初始化货物信息
func (this *Caravan) InitCaravanItemData(uid string, data *pb.DBCaravan) {
items := this.configure.GetAllCaravanItem()
data.Goods = make(map[int32]*pb.Goods, 0)
for _, v := range items {
goods := &pb.Goods{
Count: 0, // 货物数量
Period: 0, // 变动周期
CurPeriod: 1, // 当前变动周期
Price: 0, // 当前价格
Time: configure.Now().Unix(), // 刷新时间
}
if len(v.Changeperiod) != 2 {
continue
}
goods.Period = comm.GetRandNum(v.Changeperiod[0], v.Changeperiod[1])
goods.Price = v.Goodsprice
data.Goods[v.Id] = goods
}
}

View File

@ -112,6 +112,11 @@ type sumy struct {
} }
func Test_Main(t *testing.T) { func Test_Main(t *testing.T) {
ids := utils.RandomNumbers(0, 10, 5)
for _, v := range ids {
fmt.Printf("%d", v)
}
c := map[int32]int32{ c := map[int32]int32{
3: 100, 3: 100,
6: 250, 6: 250,
@ -203,10 +208,7 @@ func Test_Main(t *testing.T) {
} }
} }
} }
ids := utils.RandomNumbers(0, 10, 5)
for _, v := range ids {
fmt.Printf("%d", v)
}
oldHero := new(pb.DBHero) oldHero := new(pb.DBHero)
oldHero.Lv = 2 oldHero.Lv = 2
new := copyPoint(oldHero) new := copyPoint(oldHero)

View File

@ -118,7 +118,7 @@ func (this *Practice) AddItems(session comm.IUserSession, items map[string]int32
}) })
} else { } else {
room := &pb.DBPracticeRoom{} room := &pb.DBPracticeRoom{}
conn, err := db.Local() conn, err := db.Cross()
if err != nil { if err != nil {
this.Errorln(err) this.Errorln(err)
return return

View File

@ -25,11 +25,11 @@ type Goods struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count"` // Count int32 `protobuf:"varint,1,opt,name=count,proto3" json:"count"` // 货物数量
Period int32 `protobuf:"varint,2,opt,name=period,proto3" json:"period"` // 变动周期 Period int32 `protobuf:"varint,2,opt,name=period,proto3" json:"period"` // 变动周期
CurPeriod int32 `protobuf:"varint,3,opt,name=curPeriod,proto3" json:"curPeriod"` // 当前变动周期 CurPeriod int32 `protobuf:"varint,3,opt,name=curPeriod,proto3" json:"curPeriod"` // 当前变动周期
Price int32 `protobuf:"varint,4,opt,name=price,proto3" json:"price"` // 当前价格 Price int32 `protobuf:"varint,4,opt,name=price,proto3" json:"price"` // 当前价格
Time int32 `protobuf:"varint,5,opt,name=time,proto3" json:"time"` // 刷新时间 Time int64 `protobuf:"varint,5,opt,name=time,proto3" json:"time"` // 刷新时间
} }
func (x *Goods) Reset() { func (x *Goods) Reset() {
@ -92,7 +92,7 @@ func (x *Goods) GetPrice() int32 {
return 0 return 0
} }
func (x *Goods) GetTime() int32 { func (x *Goods) GetTime() int64 {
if x != nil { if x != nil {
return x.Time return x.Time
} }
@ -104,8 +104,8 @@ type CityGoods struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Like []string `protobuf:"bytes,1,rep,name=like,proto3" json:"like"` // 习惯的货物 Like []int32 `protobuf:"varint,1,rep,packed,name=like,proto3" json:"like"` // 习惯的货物
Unlike []string `protobuf:"bytes,2,rep,name=unlike,proto3" json:"unlike"` // 不喜欢的货物 Unlike []int32 `protobuf:"varint,2,rep,packed,name=unlike,proto3" json:"unlike"` // 不喜欢的货物
} }
func (x *CityGoods) Reset() { func (x *CityGoods) Reset() {
@ -140,14 +140,14 @@ func (*CityGoods) Descriptor() ([]byte, []int) {
return file_caravan_caravan_db_proto_rawDescGZIP(), []int{1} return file_caravan_caravan_db_proto_rawDescGZIP(), []int{1}
} }
func (x *CityGoods) GetLike() []string { func (x *CityGoods) GetLike() []int32 {
if x != nil { if x != nil {
return x.Like return x.Like
} }
return nil return nil
} }
func (x *CityGoods) GetUnlike() []string { func (x *CityGoods) GetUnlike() []int32 {
if x != nil { if x != nil {
return x.Unlike return x.Unlike
} }
@ -278,10 +278,10 @@ var file_caravan_caravan_db_proto_rawDesc = []byte{
0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x75, 0x72, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x75, 0x72, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12,
0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05,
0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20,
0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x37, 0x0a, 0x09, 0x43, 0x69, 0x74, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x37, 0x0a, 0x09, 0x43, 0x69, 0x74,
0x79, 0x47, 0x6f, 0x6f, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6b, 0x65, 0x18, 0x01, 0x79, 0x47, 0x6f, 0x6f, 0x64, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6b, 0x65, 0x18, 0x01,
0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6b, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x6e, 0x20, 0x03, 0x28, 0x05, 0x52, 0x04, 0x6c, 0x69, 0x6b, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x6e,
0x6c, 0x69, 0x6b, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x75, 0x6e, 0x6c, 0x69, 0x6c, 0x69, 0x6b, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x52, 0x06, 0x75, 0x6e, 0x6c, 0x69,
0x6b, 0x65, 0x22, 0xff, 0x02, 0x0a, 0x09, 0x44, 0x42, 0x43, 0x61, 0x72, 0x61, 0x76, 0x61, 0x6e, 0x6b, 0x65, 0x22, 0xff, 0x02, 0x0a, 0x09, 0x44, 0x42, 0x43, 0x61, 0x72, 0x61, 0x76, 0x61, 0x6e,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75,