Browse Source

game start,dismiss,ready,blind

master
tangmingyou 4 years ago
parent
commit
6dc682f30d
  1. 8
      api/operation.go
  2. 641
      api/poker.pb.go
  3. 31
      api/poker.proto
  4. 1207
      api/proto.js
  5. 36
      internal/game/game.go
  6. 8
      internal/game/player.go
  7. 61
      internal/game/table.go
  8. 22
      internal/server/ws.go
  9. 11
      internal/server/wsroute.go
  10. 5
      internal/service/auth.go
  11. 9
      internal/service/store/store.go
  12. 199
      internal/service/table.go
  13. 28
      internal/session/net_client.go

8
api/operation.go

@ -38,9 +38,17 @@ var protoInstances = []proto.Message{
&ResGameFullStatus{},
&ReqReadyStart{},
&ReqCancelReady{},
&ReqKickOutTable{},
&ResKickOutTable{},
&ReqDismissGameTable{},
&ResDismissGameTable{},
&ReqGameStart{},
&ResBigBlindChip{},
&ResSmallBlindChip{},
}
var (

641
api/poker.pb.go

@ -351,8 +351,9 @@ type ResIdentity struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Status int32 `protobuf:"varint,1,opt,name=status,proto3" json:"status,omitempty"`
Msg string `protobuf:"bytes,2,opt,name=msg,proto3" json:"msg,omitempty"`
Id int64 `protobuf:"varint,3,opt,name=id,proto3" json:"id,omitempty"`
Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"`
Avatar string `protobuf:"bytes,5,opt,name=avatar,proto3" json:"avatar,omitempty"`
}
func (x *ResIdentity) Reset() {
@ -387,16 +388,23 @@ func (*ResIdentity) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{6}
}
func (x *ResIdentity) GetStatus() int32 {
func (x *ResIdentity) GetId() int64 {
if x != nil {
return x.Status
return x.Id
}
return 0
}
func (x *ResIdentity) GetMsg() string {
func (x *ResIdentity) GetUsername() string {
if x != nil {
return x.Msg
return x.Username
}
return ""
}
func (x *ResIdentity) GetAvatar() string {
if x != nil {
return x.Avatar
}
return ""
}
@ -858,6 +866,45 @@ func (*ReqReadyStart) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{15}
}
// 取消准备
type ReqCancelReady struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *ReqCancelReady) Reset() {
*x = ReqCancelReady{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReqCancelReady) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ReqCancelReady) ProtoMessage() {}
func (x *ReqCancelReady) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ReqCancelReady.ProtoReflect.Descriptor instead.
func (*ReqCancelReady) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{16}
}
// 房主踢人
type ReqKickOutTable struct {
state protoimpl.MessageState
@ -870,7 +917,7 @@ type ReqKickOutTable struct {
func (x *ReqKickOutTable) Reset() {
*x = ReqKickOutTable{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[16]
mi := &file_poker_proto_msgTypes[17]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -883,7 +930,7 @@ func (x *ReqKickOutTable) String() string {
func (*ReqKickOutTable) ProtoMessage() {}
func (x *ReqKickOutTable) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[16]
mi := &file_poker_proto_msgTypes[17]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -896,7 +943,7 @@ func (x *ReqKickOutTable) ProtoReflect() protoreflect.Message {
// Deprecated: Use ReqKickOutTable.ProtoReflect.Descriptor instead.
func (*ReqKickOutTable) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{16}
return file_poker_proto_rawDescGZIP(), []int{17}
}
func (x *ReqKickOutTable) GetPlayerId() int64 {
@ -916,7 +963,7 @@ type ResKickOutTable struct {
func (x *ResKickOutTable) Reset() {
*x = ResKickOutTable{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[17]
mi := &file_poker_proto_msgTypes[18]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -929,7 +976,7 @@ func (x *ResKickOutTable) String() string {
func (*ResKickOutTable) ProtoMessage() {}
func (x *ResKickOutTable) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[17]
mi := &file_poker_proto_msgTypes[18]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -942,7 +989,7 @@ func (x *ResKickOutTable) ProtoReflect() protoreflect.Message {
// Deprecated: Use ResKickOutTable.ProtoReflect.Descriptor instead.
func (*ResKickOutTable) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{17}
return file_poker_proto_rawDescGZIP(), []int{18}
}
type ReqGameAction struct {
@ -957,7 +1004,7 @@ type ReqGameAction struct {
func (x *ReqGameAction) Reset() {
*x = ReqGameAction{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[18]
mi := &file_poker_proto_msgTypes[19]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -970,7 +1017,7 @@ func (x *ReqGameAction) String() string {
func (*ReqGameAction) ProtoMessage() {}
func (x *ReqGameAction) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[18]
mi := &file_poker_proto_msgTypes[19]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -983,7 +1030,7 @@ func (x *ReqGameAction) ProtoReflect() protoreflect.Message {
// Deprecated: Use ReqGameAction.ProtoReflect.Descriptor instead.
func (*ReqGameAction) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{18}
return file_poker_proto_rawDescGZIP(), []int{19}
}
func (x *ReqGameAction) GetAction() int32 {
@ -1009,7 +1056,7 @@ type ResGameAction struct {
func (x *ResGameAction) Reset() {
*x = ResGameAction{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[19]
mi := &file_poker_proto_msgTypes[20]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1022,7 +1069,7 @@ func (x *ResGameAction) String() string {
func (*ResGameAction) ProtoMessage() {}
func (x *ResGameAction) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[19]
mi := &file_poker_proto_msgTypes[20]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1035,7 +1082,7 @@ func (x *ResGameAction) ProtoReflect() protoreflect.Message {
// Deprecated: Use ResGameAction.ProtoReflect.Descriptor instead.
func (*ResGameAction) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{19}
return file_poker_proto_rawDescGZIP(), []int{20}
}
// 查询玩家当前游戏状态
@ -1048,7 +1095,7 @@ type ReqGameFullStatus struct {
func (x *ReqGameFullStatus) Reset() {
*x = ReqGameFullStatus{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[20]
mi := &file_poker_proto_msgTypes[21]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1061,7 +1108,7 @@ func (x *ReqGameFullStatus) String() string {
func (*ReqGameFullStatus) ProtoMessage() {}
func (x *ReqGameFullStatus) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[20]
mi := &file_poker_proto_msgTypes[21]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1074,7 +1121,7 @@ func (x *ReqGameFullStatus) ProtoReflect() protoreflect.Message {
// Deprecated: Use ReqGameFullStatus.ProtoReflect.Descriptor instead.
func (*ReqGameFullStatus) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{20}
return file_poker_proto_rawDescGZIP(), []int{21}
}
type ResGameFullStatus struct {
@ -1095,7 +1142,7 @@ type ResGameFullStatus struct {
func (x *ResGameFullStatus) Reset() {
*x = ResGameFullStatus{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[21]
mi := &file_poker_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1108,7 +1155,7 @@ func (x *ResGameFullStatus) String() string {
func (*ResGameFullStatus) ProtoMessage() {}
func (x *ResGameFullStatus) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[21]
mi := &file_poker_proto_msgTypes[22]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1121,7 +1168,7 @@ func (x *ResGameFullStatus) ProtoReflect() protoreflect.Message {
// Deprecated: Use ResGameFullStatus.ProtoReflect.Descriptor instead.
func (*ResGameFullStatus) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{21}
return file_poker_proto_rawDescGZIP(), []int{22}
}
func (x *ResGameFullStatus) GetInGame() bool {
@ -1198,7 +1245,7 @@ type TablePlayer struct {
func (x *TablePlayer) Reset() {
*x = TablePlayer{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[22]
mi := &file_poker_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1211,7 +1258,7 @@ func (x *TablePlayer) String() string {
func (*TablePlayer) ProtoMessage() {}
func (x *TablePlayer) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[22]
mi := &file_poker_proto_msgTypes[23]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1224,7 +1271,7 @@ func (x *TablePlayer) ProtoReflect() protoreflect.Message {
// Deprecated: Use TablePlayer.ProtoReflect.Descriptor instead.
func (*TablePlayer) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{22}
return file_poker_proto_rawDescGZIP(), []int{23}
}
func (x *TablePlayer) GetRobot() bool {
@ -1295,7 +1342,7 @@ type Card struct {
func (x *Card) Reset() {
*x = Card{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[23]
mi := &file_poker_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -1308,7 +1355,7 @@ func (x *Card) String() string {
func (*Card) ProtoMessage() {}
func (x *Card) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[23]
mi := &file_poker_proto_msgTypes[24]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -1321,7 +1368,7 @@ func (x *Card) ProtoReflect() protoreflect.Message {
// Deprecated: Use Card.ProtoReflect.Descriptor instead.
func (*Card) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{23}
return file_poker_proto_rawDescGZIP(), []int{24}
}
func (x *Card) GetDot() int32 {
@ -1338,6 +1385,218 @@ func (x *Card) GetSuit() string {
return ""
}
// 开始游戏
type ReqGameStart struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *ReqGameStart) Reset() {
*x = ReqGameStart{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReqGameStart) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ReqGameStart) ProtoMessage() {}
func (x *ReqGameStart) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[25]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ReqGameStart.ProtoReflect.Descriptor instead.
func (*ReqGameStart) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{25}
}
// 扣除大盲注
type ResBigBlindChip struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Chip int32 `protobuf:"varint,1,opt,name=chip,proto3" json:"chip,omitempty"`
}
func (x *ResBigBlindChip) Reset() {
*x = ResBigBlindChip{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ResBigBlindChip) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ResBigBlindChip) ProtoMessage() {}
func (x *ResBigBlindChip) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[26]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ResBigBlindChip.ProtoReflect.Descriptor instead.
func (*ResBigBlindChip) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{26}
}
func (x *ResBigBlindChip) GetChip() int32 {
if x != nil {
return x.Chip
}
return 0
}
// 扣除小盲注消息, 然后发牌
type ResSmallBlindChip struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Chip int32 `protobuf:"varint,1,opt,name=chip,proto3" json:"chip,omitempty"`
}
func (x *ResSmallBlindChip) Reset() {
*x = ResSmallBlindChip{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[27]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ResSmallBlindChip) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ResSmallBlindChip) ProtoMessage() {}
func (x *ResSmallBlindChip) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[27]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ResSmallBlindChip.ProtoReflect.Descriptor instead.
func (*ResSmallBlindChip) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{27}
}
func (x *ResSmallBlindChip) GetChip() int32 {
if x != nil {
return x.Chip
}
return 0
}
// 解散房间
type ReqDismissGameTable struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *ReqDismissGameTable) Reset() {
*x = ReqDismissGameTable{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[28]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ReqDismissGameTable) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ReqDismissGameTable) ProtoMessage() {}
func (x *ReqDismissGameTable) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[28]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ReqDismissGameTable.ProtoReflect.Descriptor instead.
func (*ReqDismissGameTable) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{28}
}
type ResDismissGameTable struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *ResDismissGameTable) Reset() {
*x = ResDismissGameTable{}
if protoimpl.UnsafeEnabled {
mi := &file_poker_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ResDismissGameTable) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ResDismissGameTable) ProtoMessage() {}
func (x *ResDismissGameTable) ProtoReflect() protoreflect.Message {
mi := &file_poker_proto_msgTypes[29]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ResDismissGameTable.ProtoReflect.Descriptor instead.
func (*ResDismissGameTable) Descriptor() ([]byte, []int) {
return file_poker_proto_rawDescGZIP(), []int{29}
}
var File_poker_proto protoreflect.FileDescriptor
var file_poker_proto_rawDesc = []byte{
@ -1360,87 +1619,99 @@ var file_poker_proto_rawDesc = []byte{
0x64, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x03, 0x6d, 0x73, 0x67, 0x22, 0x23, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x49, 0x64, 0x65, 0x6e, 0x74,
0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x37, 0x0a, 0x0b, 0x52, 0x65, 0x73,
0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74,
0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x12, 0x10, 0x0a, 0x03, 0x6d, 0x73, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d,
0x73, 0x67, 0x22, 0x0e, 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x4c, 0x6f, 0x62, 0x62, 0x79, 0x56, 0x69,
0x65, 0x77, 0x22, 0x37, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x4c, 0x6f, 0x62, 0x62, 0x79, 0x56, 0x69,
0x65, 0x77, 0x12, 0x27, 0x0a, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x6f, 0x62, 0x62, 0x79, 0x54, 0x61,
0x62, 0x6c, 0x65, 0x52, 0x06, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x0a,
0x4c, 0x6f, 0x62, 0x62, 0x79, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61,
0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x74, 0x61, 0x62,
0x6c, 0x65, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4e, 0x75,
0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4e,
0x75, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x4e, 0x75, 0x6d, 0x18, 0x03,
0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x4e, 0x75, 0x6d, 0x12, 0x2a,
0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x6f, 0x62, 0x62, 0x79, 0x50, 0x6c, 0x61, 0x79, 0x65,
0x72, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x22, 0x67, 0x0a, 0x0b, 0x4c, 0x6f,
0x62, 0x62, 0x79, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x62,
0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12,
0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61,
0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61,
0x74, 0x61, 0x72, 0x22, 0x42, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12,
0x16, 0x0a, 0x06, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
0x06, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x73, 0x22, 0x2a, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x43, 0x72,
0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x62,
0x6c, 0x65, 0x4e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x74, 0x61, 0x62, 0x6c,
0x65, 0x4e, 0x6f, 0x22, 0x28, 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x4a, 0x6f, 0x69, 0x6e, 0x54, 0x61,
0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x51, 0x0a, 0x0b, 0x52, 0x65, 0x73,
0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03,
0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72,
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x05,
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x0e, 0x0a, 0x0c,
0x52, 0x65, 0x71, 0x4c, 0x6f, 0x62, 0x62, 0x79, 0x56, 0x69, 0x65, 0x77, 0x22, 0x37, 0x0a, 0x0c,
0x52, 0x65, 0x73, 0x4c, 0x6f, 0x62, 0x62, 0x79, 0x56, 0x69, 0x65, 0x77, 0x12, 0x27, 0x0a, 0x06,
0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61,
0x70, 0x69, 0x2e, 0x4c, 0x6f, 0x62, 0x62, 0x79, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x06, 0x74,
0x61, 0x62, 0x6c, 0x65, 0x73, 0x22, 0x8c, 0x01, 0x0a, 0x0a, 0x4c, 0x6f, 0x62, 0x62, 0x79, 0x54,
0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x18,
0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x12, 0x1c,
0x0a, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28,
0x05, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4e, 0x75, 0x6d, 0x12, 0x1a, 0x0a, 0x08,
0x72, 0x6f, 0x62, 0x6f, 0x74, 0x4e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
0x72, 0x6f, 0x62, 0x6f, 0x74, 0x4e, 0x75, 0x6d, 0x12, 0x2a, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79,
0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e,
0x4c, 0x6f, 0x62, 0x62, 0x79, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x07, 0x70, 0x6c, 0x61,
0x79, 0x65, 0x72, 0x73, 0x22, 0x67, 0x0a, 0x0b, 0x4c, 0x6f, 0x62, 0x62, 0x79, 0x50, 0x6c, 0x61,
0x79, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01,
0x28, 0x08, 0x52, 0x05, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65,
0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65,
0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18,
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x22, 0x42, 0x0a,
0x0e, 0x52, 0x65, 0x71, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12,
0x18, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x6f, 0x62,
0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x72, 0x6f, 0x62, 0x6f, 0x74,
0x73, 0x22, 0x2a, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61,
0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x18, 0x01,
0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x22, 0x0f, 0x0a,
0x0d, 0x52, 0x65, 0x71, 0x4c, 0x65, 0x61, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x0f,
0x0a, 0x0d, 0x52, 0x65, 0x71, 0x52, 0x65, 0x61, 0x64, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x22,
0x2d, 0x0a, 0x0f, 0x52, 0x65, 0x71, 0x4b, 0x69, 0x63, 0x6b, 0x4f, 0x75, 0x74, 0x54, 0x61, 0x62,
0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x22, 0x11,
0x0a, 0x0f, 0x52, 0x65, 0x73, 0x4b, 0x69, 0x63, 0x6b, 0x4f, 0x75, 0x74, 0x54, 0x61, 0x62, 0x6c,
0x65, 0x22, 0x3b, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01,
0x28, 0x05, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x68,
0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x68, 0x69, 0x70, 0x22, 0x0f,
0x0a, 0x0d, 0x52, 0x65, 0x73, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22,
0x13, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x47, 0x61, 0x6d, 0x65, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x22, 0x8a, 0x02, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x47, 0x61, 0x6d, 0x65,
0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e,
0x47, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x6e, 0x47, 0x61,
0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x18, 0x02, 0x20,
0x01, 0x28, 0x05, 0x52, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09,
0x67, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
0x09, 0x67, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x68,
0x69, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x68, 0x69, 0x70, 0x12, 0x1e,
0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01,
0x28, 0x05, 0x52, 0x0a, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x1a,
0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03,
0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x0a, 0x70, 0x75,
0x62, 0x6c, 0x69, 0x63, 0x43, 0x61, 0x72, 0x64, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09,
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x61, 0x72, 0x64, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69,
0x63, 0x43, 0x61, 0x72, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73,
0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x61, 0x62,
0x6c, 0x65, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72,
0x73, 0x22, 0xd2, 0x01, 0x0a, 0x0b, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x61, 0x79, 0x65,
0x72, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08,
0x52, 0x05, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x63,
0x68, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x68, 0x69, 0x70, 0x12,
0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52,
0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x73, 0x74, 0x65,
0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x12,
0x25, 0x0a, 0x08, 0x68, 0x61, 0x6e, 0x64, 0x43, 0x61, 0x72, 0x64, 0x18, 0x08, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x09, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x61, 0x72, 0x64, 0x52, 0x08, 0x68, 0x61,
0x6e, 0x64, 0x43, 0x61, 0x72, 0x64, 0x22, 0x2c, 0x0a, 0x04, 0x43, 0x61, 0x72, 0x64, 0x12, 0x10,
0x0a, 0x03, 0x64, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x64, 0x6f, 0x74,
0x12, 0x12, 0x0a, 0x04, 0x73, 0x75, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x73, 0x75, 0x69, 0x74, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70,
0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x22, 0x28, 0x0a,
0x0c, 0x52, 0x65, 0x71, 0x4a, 0x6f, 0x69, 0x6e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x18, 0x0a,
0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07,
0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x4c, 0x65,
0x61, 0x76, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x0f, 0x0a, 0x0d, 0x52, 0x65, 0x71, 0x52,
0x65, 0x61, 0x64, 0x79, 0x53, 0x74, 0x61, 0x72, 0x74, 0x22, 0x10, 0x0a, 0x0e, 0x52, 0x65, 0x71,
0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x61, 0x64, 0x79, 0x22, 0x2d, 0x0a, 0x0f, 0x52,
0x65, 0x71, 0x4b, 0x69, 0x63, 0x6b, 0x4f, 0x75, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1a,
0x0a, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03,
0x52, 0x08, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x52, 0x65,
0x73, 0x4b, 0x69, 0x63, 0x6b, 0x4f, 0x75, 0x74, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3b, 0x0a,
0x0d, 0x52, 0x65, 0x71, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16,
0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06,
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x68, 0x69, 0x70, 0x18, 0x02,
0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x68, 0x69, 0x70, 0x22, 0x0f, 0x0a, 0x0d, 0x52, 0x65,
0x73, 0x47, 0x61, 0x6d, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x13, 0x0a, 0x11, 0x52,
0x65, 0x71, 0x47, 0x61, 0x6d, 0x65, 0x46, 0x75, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
0x22, 0x8a, 0x02, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x47, 0x61, 0x6d, 0x65, 0x46, 0x75, 0x6c, 0x6c,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x47, 0x61, 0x6d, 0x65,
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x69, 0x6e, 0x47, 0x61, 0x6d, 0x65, 0x12, 0x18,
0x0a, 0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
0x07, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x67, 0x61, 0x6d, 0x65,
0x53, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x67, 0x61, 0x6d,
0x65, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x68, 0x69, 0x70, 0x18, 0x04,
0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x68, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x6f,
0x75, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a,
0x72, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c,
0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x6c,
0x61, 0x79, 0x65, 0x72, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
0x43, 0x61, 0x72, 0x64, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x61, 0x70, 0x69,
0x2e, 0x43, 0x61, 0x72, 0x64, 0x52, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x43, 0x61, 0x72,
0x64, 0x12, 0x2a, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x0a, 0x20, 0x03,
0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c,
0x61, 0x79, 0x65, 0x72, 0x52, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x22, 0xd2, 0x01,
0x0a, 0x0b, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x14, 0x0a,
0x05, 0x72, 0x6f, 0x62, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x72, 0x6f,
0x62, 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52,
0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12,
0x16, 0x0a, 0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x61, 0x76, 0x61, 0x74, 0x61, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x68, 0x69, 0x70, 0x18,
0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x68, 0x69, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x73,
0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61,
0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x18, 0x07, 0x20,
0x01, 0x28, 0x08, 0x52, 0x06, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x12, 0x25, 0x0a, 0x08, 0x68,
0x61, 0x6e, 0x64, 0x43, 0x61, 0x72, 0x64, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x09, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x43, 0x61, 0x72, 0x64, 0x52, 0x08, 0x68, 0x61, 0x6e, 0x64, 0x43, 0x61,
0x72, 0x64, 0x22, 0x2c, 0x0a, 0x04, 0x43, 0x61, 0x72, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x6f,
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x64, 0x6f, 0x74, 0x12, 0x12, 0x0a, 0x04,
0x73, 0x75, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x75, 0x69, 0x74,
0x22, 0x0e, 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x47, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74,
0x22, 0x25, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x42, 0x69, 0x67, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x43,
0x68, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x68, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28,
0x05, 0x52, 0x04, 0x63, 0x68, 0x69, 0x70, 0x22, 0x27, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x53, 0x6d,
0x61, 0x6c, 0x6c, 0x42, 0x6c, 0x69, 0x6e, 0x64, 0x43, 0x68, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04,
0x63, 0x68, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x68, 0x69, 0x70,
0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x71, 0x44, 0x69, 0x73, 0x6d, 0x69, 0x73, 0x73, 0x47, 0x61,
0x6d, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x73, 0x44, 0x69,
0x73, 0x6d, 0x69, 0x73, 0x73, 0x47, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x0b,
0x5a, 0x09, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
}
var (
@ -1455,39 +1726,45 @@ func file_poker_proto_rawDescGZIP() []byte {
return file_poker_proto_rawDescData
}
var file_poker_proto_msgTypes = make([]protoimpl.MessageInfo, 24)
var file_poker_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
var file_poker_proto_goTypes = []interface{}{
(*ProtoWrap)(nil), // 0: api.ProtoWrap
(*Ping)(nil), // 1: api.Ping
(*Pong)(nil), // 2: api.Pong
(*ResSuccess)(nil), // 3: api.ResSuccess
(*ResFail)(nil), // 4: api.ResFail
(*ReqIdentity)(nil), // 5: api.ReqIdentity
(*ResIdentity)(nil), // 6: api.ResIdentity
(*ReqLobbyView)(nil), // 7: api.ReqLobbyView
(*ResLobbyView)(nil), // 8: api.ResLobbyView
(*LobbyTable)(nil), // 9: api.LobbyTable
(*LobbyPlayer)(nil), // 10: api.LobbyPlayer
(*ReqCreateTable)(nil), // 11: api.ReqCreateTable
(*ResCreateTable)(nil), // 12: api.ResCreateTable
(*ReqJoinTable)(nil), // 13: api.ReqJoinTable
(*ReqLeaveTable)(nil), // 14: api.ReqLeaveTable
(*ReqReadyStart)(nil), // 15: api.ReqReadyStart
(*ReqKickOutTable)(nil), // 16: api.ReqKickOutTable
(*ResKickOutTable)(nil), // 17: api.ResKickOutTable
(*ReqGameAction)(nil), // 18: api.ReqGameAction
(*ResGameAction)(nil), // 19: api.ResGameAction
(*ReqGameFullStatus)(nil), // 20: api.ReqGameFullStatus
(*ResGameFullStatus)(nil), // 21: api.ResGameFullStatus
(*TablePlayer)(nil), // 22: api.TablePlayer
(*Card)(nil), // 23: api.Card
(*ProtoWrap)(nil), // 0: api.ProtoWrap
(*Ping)(nil), // 1: api.Ping
(*Pong)(nil), // 2: api.Pong
(*ResSuccess)(nil), // 3: api.ResSuccess
(*ResFail)(nil), // 4: api.ResFail
(*ReqIdentity)(nil), // 5: api.ReqIdentity
(*ResIdentity)(nil), // 6: api.ResIdentity
(*ReqLobbyView)(nil), // 7: api.ReqLobbyView
(*ResLobbyView)(nil), // 8: api.ResLobbyView
(*LobbyTable)(nil), // 9: api.LobbyTable
(*LobbyPlayer)(nil), // 10: api.LobbyPlayer
(*ReqCreateTable)(nil), // 11: api.ReqCreateTable
(*ResCreateTable)(nil), // 12: api.ResCreateTable
(*ReqJoinTable)(nil), // 13: api.ReqJoinTable
(*ReqLeaveTable)(nil), // 14: api.ReqLeaveTable
(*ReqReadyStart)(nil), // 15: api.ReqReadyStart
(*ReqCancelReady)(nil), // 16: api.ReqCancelReady
(*ReqKickOutTable)(nil), // 17: api.ReqKickOutTable
(*ResKickOutTable)(nil), // 18: api.ResKickOutTable
(*ReqGameAction)(nil), // 19: api.ReqGameAction
(*ResGameAction)(nil), // 20: api.ResGameAction
(*ReqGameFullStatus)(nil), // 21: api.ReqGameFullStatus
(*ResGameFullStatus)(nil), // 22: api.ResGameFullStatus
(*TablePlayer)(nil), // 23: api.TablePlayer
(*Card)(nil), // 24: api.Card
(*ReqGameStart)(nil), // 25: api.ReqGameStart
(*ResBigBlindChip)(nil), // 26: api.ResBigBlindChip
(*ResSmallBlindChip)(nil), // 27: api.ResSmallBlindChip
(*ReqDismissGameTable)(nil), // 28: api.ReqDismissGameTable
(*ResDismissGameTable)(nil), // 29: api.ResDismissGameTable
}
var file_poker_proto_depIdxs = []int32{
9, // 0: api.ResLobbyView.tables:type_name -> api.LobbyTable
10, // 1: api.LobbyTable.players:type_name -> api.LobbyPlayer
23, // 2: api.ResGameFullStatus.publicCard:type_name -> api.Card
22, // 3: api.ResGameFullStatus.players:type_name -> api.TablePlayer
23, // 4: api.TablePlayer.handCard:type_name -> api.Card
24, // 2: api.ResGameFullStatus.publicCard:type_name -> api.Card
23, // 3: api.ResGameFullStatus.players:type_name -> api.TablePlayer
24, // 4: api.TablePlayer.handCard:type_name -> api.Card
5, // [5:5] is the sub-list for method output_type
5, // [5:5] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
@ -1694,7 +1971,7 @@ func file_poker_proto_init() {
}
}
file_poker_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReqKickOutTable); i {
switch v := v.(*ReqCancelReady); i {
case 0:
return &v.state
case 1:
@ -1706,7 +1983,7 @@ func file_poker_proto_init() {
}
}
file_poker_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResKickOutTable); i {
switch v := v.(*ReqKickOutTable); i {
case 0:
return &v.state
case 1:
@ -1718,7 +1995,7 @@ func file_poker_proto_init() {
}
}
file_poker_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReqGameAction); i {
switch v := v.(*ResKickOutTable); i {
case 0:
return &v.state
case 1:
@ -1730,7 +2007,7 @@ func file_poker_proto_init() {
}
}
file_poker_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResGameAction); i {
switch v := v.(*ReqGameAction); i {
case 0:
return &v.state
case 1:
@ -1742,7 +2019,7 @@ func file_poker_proto_init() {
}
}
file_poker_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReqGameFullStatus); i {
switch v := v.(*ResGameAction); i {
case 0:
return &v.state
case 1:
@ -1754,7 +2031,7 @@ func file_poker_proto_init() {
}
}
file_poker_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResGameFullStatus); i {
switch v := v.(*ReqGameFullStatus); i {
case 0:
return &v.state
case 1:
@ -1766,7 +2043,7 @@ func file_poker_proto_init() {
}
}
file_poker_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TablePlayer); i {
switch v := v.(*ResGameFullStatus); i {
case 0:
return &v.state
case 1:
@ -1778,6 +2055,18 @@ func file_poker_proto_init() {
}
}
file_poker_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TablePlayer); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_poker_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Card); i {
case 0:
return &v.state
@ -1789,6 +2078,66 @@ func file_poker_proto_init() {
return nil
}
}
file_poker_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReqGameStart); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_poker_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResBigBlindChip); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_poker_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResSmallBlindChip); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_poker_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ReqDismissGameTable); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_poker_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResDismissGameTable); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -1796,7 +2145,7 @@ func file_poker_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_poker_proto_rawDesc,
NumEnums: 0,
NumMessages: 24,
NumMessages: 30,
NumExtensions: 0,
NumServices: 0,
},

31
api/poker.proto

@ -40,8 +40,9 @@ message ReqIdentity {
}
message ResIdentity {
int32 status = 1;
string msg = 2;
int64 id = 3;
string username = 4;
string avatar = 5;
}
// ============= begin
@ -88,11 +89,14 @@ message ReqJoinTable {
//
message ReqLeaveTable {
}
//
message ReqReadyStart {
}
//
message ReqCancelReady {
}
//
@ -148,3 +152,24 @@ message Card {
}
// ============= end
//
message ReqGameStart {
}
//
message ResBigBlindChip {
int32 chip = 1;
}
// ,
message ResSmallBlindChip {
int32 chip = 1;
}
//
message ReqDismissGameTable {
}
message ResDismissGameTable {
}

1207
api/proto.js

File diff suppressed because it is too large Load Diff

36
internal/game/game.go

@ -2,6 +2,12 @@ package game
import (
"math/rand"
"sync"
)
const (
BigBlindChip int32 = 2 // 大盲注金额
SmallBlinds int32 = BigBlindChip / 2 // 小盲注金额
)
// Dealer 发牌员, 有打乱的一副牌
@ -10,11 +16,22 @@ type Dealer struct {
// cardList *collect.LinkedList[Card]
cards []*Card
index int
lock *sync.Mutex
}
func NewDealer() *Dealer {
return &Dealer{
cards: make([]*Card, 52),
index: 0,
lock: new(sync.Mutex),
}
}
func (d *Dealer) Init() *Dealer {
d.lock.Lock()
defer d.lock.Unlock()
d.index = 0
d.cards = make([]*Card, 52)
// 初始化一副牌,13张牌
for i := 0; i < 13; i++ {
// 4 种花色
@ -29,23 +46,22 @@ func (d *Dealer) Init() *Dealer {
// Deal 发牌堆第一张牌
func (d *Dealer) Deal() *Card {
d.lock.Lock()
defer d.lock.Unlock()
card := d.cards[d.index]
d.index++
return card
}
// disorder 洗牌
// disorder 乱序洗牌
func disorder(cards []*Card) {
length := len(cards)
// 洗13
for i := 0; i < 13; i++ {
// 洗52
for i := 0; i < length; i++ {
for j := 0; j < length; j++ {
repIdx := rand.Intn(length)
cards[i], cards[repIdx] = cards[repIdx], cards[i]
repIdx := (rand.Intn(length) + rand.Intn(length)) / 2
cards[j], cards[repIdx] = cards[repIdx], cards[j]
}
}
}
func NewDealer() *Dealer {
return new(Dealer).Init()
}

8
internal/game/player.go

@ -1,6 +1,7 @@
package game
import (
"sync"
"texas-poker-bk/internal/letter"
)
@ -11,12 +12,13 @@ type Player struct {
Avatar string
Cards [2]*Card // 手牌
Chip int32 // 玩家筹码
Status int32 // 状态: 1待准备开始,2已准备开始,3等待其他玩家动作,4待大盲注,5待小盲注,6待跟注,7已弃
Status int32 // 状态: 1待准备开始,2已准备开始,3等待其他玩家动作,4小盲注跟注, [5待大盲注,5待小盲注,] 6待跟注,7已弃
GameTable *Table // 当前牌桌
ProtoWriter letter.ProtoWriter
Lock *sync.Mutex
}
func NewPlayer() *Player {
return &Player{}
func (p *Player) Init() {
p.Lock = new(sync.Mutex)
}

61
internal/game/table.go

@ -11,24 +11,59 @@ type Table struct {
TableNo int32 // 牌桌编号
MasterId int64 // 房主Id
RoundTimes int32 // 回合次数
Stage int32 // 游戏阶段: 1等待玩家准备;2下大盲注;3下小盲注;4发公共牌;5发第四张公共牌,轮流下注;6发第五张公共牌,轮流下注,7比牌结算
Stage int32 // 游戏阶段: 1等待玩家准备;2游戏开始(自动扣大小盲注,发牌,轮流下注) [2(开始发牌)下大盲注;3下小盲注;4发公共牌;] 5发第四张公共牌,轮流下注;6发第五张公共牌,轮流下注,7比牌结算,9已解散
chip int32 // 牌桌当前筹码
Chip int32 // 牌桌当前筹码
robotChip int32 // 牌桌当前机器人下注筹码
Dealer *Dealer // 发牌员
PublicCards [5]*Card // 公共牌
PlayerNum int32 // 玩家数
RobotNum int32 // 机器人数
Players []*Player // 玩家
Robots []*Robot
BigBlindsPos int32 // 大盲注位
PlayerNum int32 // 玩家数
RobotNum int32 // 机器人数
Players []*Player // 玩家
Robots []*Robot
BigBlindPos int // 大盲注位
SmallBlindPos int // 小盲注位
PlayersLock *sync.Mutex
ChipLock *sync.Mutex // 桌面筹码更新锁
// TODO game logs7
}
func (t *Table) PlayerCount() int32 {
var count int32 = 0
for _, p := range t.Players {
if p != nil {
count++
}
}
return count
}
func (t *Table) NextPosPlayer(current int) int {
for i := current; i < len(t.Players); i++ {
if t.Players[i] == nil {
continue
}
return i
}
for i, p := range t.Players {
if p != nil {
return i
}
}
return 0
}
func (t *Table) FindPlayerPos(player *Player) int32 {
for i, p := range t.Players {
if p != nil && p.Id == player.Id {
return int32(i)
}
}
return -1
}
func (t *Table) JoinPlayer(player *Player) error {
t.PlayersLock.Lock()
defer t.PlayersLock.Unlock()
@ -48,7 +83,7 @@ func (t *Table) BuildResGameFullStatus() *api.ResGameFullStatus {
resGame.InGame = collect.In(t.Stage, 2, 3, 4, 5, 6, 7)
resGame.TableNo = t.TableNo
resGame.GameStage = t.Stage
resGame.Chip = t.chip
resGame.Chip = t.Chip
resGame.RoundTimes = t.RoundTimes
// 公共牌
@ -93,12 +128,18 @@ func (t *Table) BuildResGameFullStatus() *api.ResGameFullStatus {
}
func (t *Table) NoticeGameFullStatus() {
resGame := t.BuildResGameFullStatus()
// 发送当前游戏状态消息到牌桌所有用户
for _, player := range t.Players {
if player != nil && player.ProtoWriter != nil {
resGame := t.BuildResGameFullStatus()
resGame.PlayerId = player.Id
// 只返回自己的手牌 TODO 结算时全部返回
for _, p := range resGame.Players {
if p != nil && p.Id != player.Id {
p.HandCard[0] = nil
p.HandCard[1] = nil
}
}
player.ProtoWriter.Write(resGame)
}
}

22
internal/server/ws.go

@ -47,6 +47,20 @@ func upgradeWs(resWriter http.ResponseWriter, req *http.Request) (*websocket.Con
return upgrader.Upgrade(resWriter, req, nil)
}
const (
// Time allowed to write a message to the peer.
writeWait = 10 * time.Second
// Time allowed to read the next pong message from the peer.
pongWait = 60 * time.Second
// Send pings to peer with this period. Must be less than pongWait.
pingPeriod = (pongWait * 9) / 10
// Maximum message size allowed from peer.
maxMessageSize = 512
)
// 处理新建的websocket
func handleNetClient(client *session.NetClient) {
//defer (func() {
@ -57,12 +71,16 @@ func handleNetClient(client *session.NetClient) {
//var player *session.Player
// https://github.com/gorilla/websocket/blob/a68708917c6a4f06314ab4e52493cc61359c9d42/examples/chat/conn.go#L50
client.Conn.SetReadLimit(1024 * 1024)
//err := client.Conn.SetWriteDeadline(time.Now().Add(time.Millisecond * 50))
client.Conn.SetReadLimit(maxMessageSize)
// TODO readDeadLine 读取超时后关闭连接
// err := client.Conn.SetReadDeadline(time.Now().Add(pongWait))
//if err != nil {
// log.Printf("set deadline error: %v", err)
// return
//}
client.Conn.SetPongHandler(func(string) error {
return client.Conn.SetReadDeadline(time.Now().Add(pongWait))
})
// TODO 1分钟后过期
for {

11
internal/server/wsroute.go

@ -23,13 +23,20 @@ func init() {
// 获取牌桌当前所有状态
HandleNetPlayerMsg(&api.ReqGameFullStatus{}, service.HandleReqGameFullStatus)
// 加入桌面
HandleNetAccountMsg(&api.ReqJoinTable{}, service.HandleJoinTable)
HandleNetAccountMsg(&api.ReqJoinTable{}, service.HandleReqJoinTable)
// 踢人
HandleNetPlayerMsg(&api.ReqKickOutTable{}, service.HandleReqKickOutTable)
// 离开房间
HandleNetPlayerMsg(&api.ReqLeaveTable{}, service.HandleReqLeaveTable)
// 解散房间
HandleNetPlayerMsg(&api.ReqDismissGameTable{}, service.HandleReqDismissGameTable)
// 玩家准备
HandleNetPlayerMsg(&api.ReqReadyStart{}, service.HandleReqReadyStart)
// 玩家取消准备
HandleNetPlayerMsg(&api.ReqCancelReady{}, service.HandleReqCancelReady)
// 开始游戏
HandleNetPlayerMsg(&api.ReqGameStart{}, service.HandleReqGameStart)
}
func checkExistsTypeHandler(op int32, err error) {

5
internal/service/auth.go

@ -179,11 +179,10 @@ func HandleReqIdentity(client *session.NetClient, msg *api.ReqIdentity) (proto.M
Lock: &sync.Mutex{},
}
// TODO 查询 DB 账户余额
account = store.SaveNetAccounts(account)
account = store.SaveAndTryRecoverNetAccounts(account)
client.Account = account
// response
res := &api.ResIdentity{Status: 200, Msg: "ok"}
// client.Write(res)
res := &api.ResIdentity{Id: subject.Id, Username: subject.Name, Avatar: subject.Avatar}
return res, nil
}

9
internal/service/store/store.go

@ -14,7 +14,7 @@ var (
LobbyTables map[int32]*game.Table
lobbyLock *sync.Mutex
// NetAccounts 存储一下在线用户
// NetAccounts 存储一下在线用户, TODO 连接终端,未在牌局或牌局未开始中回收账号,机器人代打后回收账号
NetAccounts map[int64]*session.NetAccount
accountLock *sync.Mutex
)
@ -39,8 +39,8 @@ func SaveNewTable(table *game.Table) error {
return nil
}
// SaveNetAccounts 保存一下在线账户映射关系 TODO 处理断线、重连问题
func SaveNetAccounts(account *session.NetAccount) *session.NetAccount {
// SaveAndTryRecoverNetAccounts 保存一下在线账户映射关系 TODO 处理断线、重连问题
func SaveAndTryRecoverNetAccounts(account *session.NetAccount) *session.NetAccount {
accountLock.Lock()
defer accountLock.Unlock()
current := NetAccounts[account.Id]
@ -50,5 +50,8 @@ func SaveNetAccounts(account *session.NetAccount) *session.NetAccount {
}
// 掉线重连的用户, TODO 重复登录的用户
current.Client = account.Client
if current.Player != nil {
current.Player.ProtoWriter = account.Client
}
return current
}

199
internal/service/table.go

@ -30,13 +30,14 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable)
Dealer: game.NewDealer(),
PublicCards: [5]*game.Card{&game.Card{Dot: 0, Suit: 3}, &game.Card{Dot: 1, Suit: 3}, nil, nil, nil},
PlayerNum: playerNum + 1,
RobotNum: robotNum,
Players: make([]*game.Player, playerNum+1),
Robots: make([]*game.Robot, robotNum),
BigBlindsPos: 0,
PlayersLock: &sync.Mutex{},
ChipLock: &sync.Mutex{},
PlayerNum: playerNum + 1,
RobotNum: robotNum,
Players: make([]*game.Player, playerNum+1),
Robots: make([]*game.Robot, robotNum),
BigBlindPos: 0,
SmallBlindPos: 0,
PlayersLock: &sync.Mutex{},
ChipLock: &sync.Mutex{},
}
// 房主 [0]
@ -50,6 +51,7 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable)
GameTable: table,
ProtoWriter: account.Client,
}
owner.Init()
// 扣除DB账户余额 TODO 账户金额限制
account.DecrementBalance(500)
account.Player = owner // 挂载 player 到 account 上
@ -109,8 +111,8 @@ func HandleReqLobbyView(account *session.NetAccount, msg *api.ReqLobbyView) (pro
return res, nil
}
// HandleJoinTable 加入牌桌
func HandleJoinTable(account *session.NetAccount, msg *api.ReqJoinTable) (proto.Message, error) {
// HandleReqJoinTable 加入牌桌
func HandleReqJoinTable(account *session.NetAccount, msg *api.ReqJoinTable) (proto.Message, error) {
account.Lock.Lock()
defer account.Lock.Unlock()
@ -121,9 +123,14 @@ func HandleJoinTable(account *session.NetAccount, msg *api.ReqJoinTable) (proto.
// TODO 账户余额限制
table := store.LobbyTables[msg.TableNo]
table.ChipLock.Lock()
defer table.ChipLock.Unlock()
if table == nil {
return &api.ResFail{Msg: "牌桌不存在"}, nil
}
if table.Stage != 1 {
return &api.ResFail{Msg: "牌桌正在进行中"}, nil
}
player := &game.Player{
Id: account.Id,
Username: account.UserName,
@ -134,7 +141,7 @@ func HandleJoinTable(account *session.NetAccount, msg *api.ReqJoinTable) (proto.
GameTable: table,
ProtoWriter: account.Client,
}
player.Init()
err := table.JoinPlayer(player)
if err != nil {
return nil, err
@ -149,34 +156,6 @@ func HandleJoinTable(account *session.NetAccount, msg *api.ReqJoinTable) (proto.
return &api.ResSuccess{}, nil
}
// HandleLeaveTable 离开牌桌
func HandleLeaveTable(account session.NetAccount, msg *api.ReqCreateTable) (proto.Message, error) {
account.Lock.Lock()
defer account.Lock.Unlock()
// 结算, player -> nil
if account.Player == nil {
return &api.ResFail{Msg: "当前未加入牌桌"}, nil
}
// 根据玩家游戏状态判断可否退出
switch account.Player.Status {
case 1, 2, 7: // 未在游戏中 可退出
// 结算金额
account.IncrementBalance(account.Player.Chip)
gameTable := account.Player.GameTable
// table player remove
for i := range gameTable.Players {
if gameTable.Players[i] == account.Player {
gameTable.Players[i] = nil
}
}
account.Player = nil
// TODO notice 牌桌其他玩家 gameTable.notice(ResGameStatus)
return &api.ResSuccess{}, nil
default:
return &api.ResFail{Msg: "游戏进行中,不能退出"}, nil
}
}
// HandleReqKickOutTable 踢人
func HandleReqKickOutTable(player *game.Player, msg *api.ReqKickOutTable) (proto.Message, error) {
player.GameTable.PlayersLock.Lock()
@ -212,6 +191,7 @@ func HandleReqKickOutTable(player *game.Player, msg *api.ReqKickOutTable) (proto
func HandleReqLeaveTable(player *game.Player, msg *api.ReqLeaveTable) (proto.Message, error) {
player.GameTable.PlayersLock.Lock()
defer player.GameTable.PlayersLock.Unlock()
if player.GameTable.Stage != 1 {
return &api.ResFail{Msg: "牌局进行中不能退出"}, nil
}
@ -245,12 +225,149 @@ func HandleReqGameFullStatus(player *game.Player, msg *api.ReqGameFullStatus) (p
}
resGame := player.GameTable.BuildResGameFullStatus()
resGame.PlayerId = player.Id
// TODO 其他玩家手牌不返回,计算自己的5张推荐牌
// 其他玩家手牌不返回,TODO 计算自己的5张推荐牌
for _, p := range resGame.Players {
if p != nil && p.Id != player.Id {
p.HandCard[0] = nil
p.HandCard[1] = nil
}
}
return resGame, nil
}
// HandleReqReadyStart 准备开始游戏
func HandleReqReadyStart(player game.Player, msg *api.ReqReadyStart) (proto.Message, error) {
func HandleReqReadyStart(player *game.Player, msg *api.ReqReadyStart) (proto.Message, error) {
player.Lock.Lock()
defer player.Lock.Unlock()
if player.Id == player.GameTable.MasterId {
return &api.ResFail{Msg: "房主不用准备"}, nil
}
if player.Status != 1 {
msg := ""
switch player.Status {
case 2:
msg = "已准备"
default:
msg = fmt.Sprintf("异常状态#%d", player.Status)
}
return &api.ResFail{Msg: msg}, nil
}
player.Status = 2
player.GameTable.NoticeGameFullStatus()
return &api.ResSuccess{}, nil
}
func HandleReqCancelReady(player *game.Player, msg *api.ReqCancelReady) (proto.Message, error) {
player.Lock.Lock()
defer player.Lock.Unlock()
if player.Id == player.GameTable.MasterId {
return &api.ResFail{Msg: "房主不用准备"}, nil
}
if player.Status != 2 {
return &api.ResFail{Msg: "当前未准备"}, nil
}
player.Status = 1
player.GameTable.NoticeGameFullStatus()
return &api.ResSuccess{}, nil
}
return nil, nil
func HandleReqDismissGameTable(player *game.Player, msg *api.ReqDismissGameTable) (proto.Message, error) {
player.GameTable.ChipLock.Lock()
defer player.GameTable.ChipLock.Unlock()
if player.GameTable.Stage != 1 {
return &api.ResFail{Msg: fmt.Sprintf("#%d,牌局进行中", player.GameTable.Stage)}, nil
}
player.GameTable.Stage = 9
delete(store.LobbyTables, player.GameTable.TableNo)
// 通知所有玩家,解除账号绑定,结算玩家金额
for i, p := range player.GameTable.Players {
if p == nil {
continue
}
account := store.NetAccounts[p.Id]
account.IncrementBalance(p.Chip)
account.Player = nil
player.GameTable.Players[i] = nil
if p.Id != player.Id {
p.ProtoWriter.Write(&api.ResDismissGameTable{})
}
}
return &api.ResDismissGameTable{}, nil
}
func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Message, error) {
player.GameTable.ChipLock.Lock()
defer player.GameTable.ChipLock.Unlock()
// 锁定牌桌所有玩家
for _, p := range player.GameTable.Players {
if p != nil {
p.Lock.Lock()
defer p.Lock.Unlock()
}
}
table := player.GameTable
if player.Id != table.MasterId {
return &api.ResFail{Msg: "你不是房主"}, nil
}
if table.Stage != 1 {
return &api.ResFail{Msg: fmt.Sprintf("牌局状态有误%d", table.Stage)}, nil
}
// 检查所有玩家准备状态
for _, p := range table.Players {
if p != nil && p.Id != table.MasterId && p.Status != 2 {
return &api.ResFail{Msg: "有玩家未准备"}, nil
}
}
// 游戏状态开始
table.Stage = 2
// 大盲注位
if table.RoundTimes == 0 {
table.BigBlindPos = 0
} else {
table.BigBlindPos = table.NextPosPlayer(table.BigBlindPos)
}
// 小盲注位
table.SmallBlindPos = table.NextPosPlayer(table.BigBlindPos)
// 回合数+1
table.RoundTimes++
// 扣除大小盲注金额
table.Players[table.BigBlindPos].Chip -= game.BigBlindChip
table.Players[table.SmallBlindPos].Chip -= game.SmallBlinds
table.Chip += game.BigBlindChip + game.SmallBlinds
table.Players[table.BigBlindPos].ProtoWriter.Write(&api.ResBigBlindChip{Chip: game.BigBlindChip})
table.Players[table.SmallBlindPos].ProtoWriter.Write(&api.ResSmallBlindChip{Chip: game.SmallBlinds})
// 开始发牌(手牌,公共牌)
table.Dealer.Init() // 初始化发牌员
for _, p := range table.Players {
if p == nil {
continue
}
for i := range p.Cards {
p.Cards[i] = table.Dealer.Deal()
}
// 玩家状态置为等待
p.Status = 3
}
// 发3张公共牌
for i := 0; i < 5; i++ {
if i < 3 {
table.PublicCards[i] = table.Dealer.Deal()
continue
}
// 第4,5张牌置空
table.PublicCards[i] = nil
}
// 待小盲注位玩家下注
table.Players[table.SmallBlindPos].Status = 4
// 广播牌桌状态
table.NoticeGameFullStatus()
return &api.ResSuccess{}, nil
}

28
internal/session/net_client.go

@ -5,15 +5,24 @@ import (
"github.com/golang/protobuf/proto"
"github.com/gorilla/websocket"
"log"
"sync"
"texas-poker-bk/api"
"time"
)
// NetClient 长连接客户端
type NetClient struct {
Id int64
Conn *websocket.Conn
Account *NetAccount
// Id int64
Conn *websocket.Conn
Account *NetAccount
WriteLock *sync.Mutex
}
func NewNetClient(conn *websocket.Conn) *NetClient {
return &NetClient{
Conn: conn,
WriteLock: new(sync.Mutex),
}
}
func (c *NetClient) Close(reason string) {
@ -28,6 +37,7 @@ func (c *NetClient) Write(msg proto.Message) {
}
func (c *NetClient) WriteSeq(success bool, seq int32, msg proto.Message) {
// 序列化 protobuf 消息
op, err := api.GetProtoOp(msg)
if err != nil {
fmt.Println("write msg match op err:", err)
@ -36,8 +46,12 @@ func (c *NetClient) WriteSeq(success bool, seq int32, msg proto.Message) {
bytes, err := proto.Marshal(msg)
wrap := &api.ProtoWrap{Ver: 1, Op: op, Seq: seq, Success: success, Body: bytes}
wrapBytes, err := proto.Marshal(wrap)
// 向ws客户端写
c.WriteLock.Lock()
defer c.WriteLock.Unlock()
// TODO 看文档 SetWriteDeadline
err = c.Conn.SetWriteDeadline(time.Now().Add(time.Millisecond * 100))
err = c.Conn.SetWriteDeadline(time.Now().Add(10 * time.Second))
if err != nil {
fmt.Println("set dead line err:", err)
return
@ -47,9 +61,3 @@ func (c *NetClient) WriteSeq(success bool, seq int32, msg proto.Message) {
fmt.Println("write msg err:", err)
}
}
func NewNetClient(conn *websocket.Conn) *NetClient {
return &NetClient{
Conn: conn,
}
}

Loading…
Cancel
Save