From 46e34fb12feef27209bbe0e4f48f99bdc0499db0 Mon Sep 17 00:00:00 2001 From: tangmingyou <234767776@qq.com> Date: Mon, 13 Feb 2023 17:51:06 +0800 Subject: [PATCH] betting round --- api/operation.go | 5 +- api/poker.pb.go | 296 +++++++++++---- api/poker.proto | 18 +- api/proto.js | 723 ++++++++++++++++++++++++++++++++----- internal/game/player.go | 12 +- internal/game/table.go | 241 ++++++++----- internal/server/wsroute.go | 2 + internal/service/table.go | 173 ++++----- tool/collect/collect.go | 2 +- 9 files changed, 1129 insertions(+), 343 deletions(-) diff --git a/api/operation.go b/api/operation.go index eef8c1d..1daf257 100644 --- a/api/operation.go +++ b/api/operation.go @@ -47,9 +47,12 @@ var protoInstances = []proto.Message{ &ResDismissGameTable{}, &ReqGameStart{}, - &ReqPlaceBet{}, + &ReqBetting{}, &ResNoticePlayerLine{}, + &ResCalcWinnerChip{}, + + &ResGameEndSettle{}, } var ( diff --git a/api/poker.pb.go b/api/poker.pb.go index 657d036..be63f4b 100644 --- a/api/poker.pb.go +++ b/api/poker.pb.go @@ -1265,16 +1265,18 @@ type TablePlayer struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Robot bool `protobuf:"varint,1,opt,name=robot,proto3" json:"robot,omitempty"` // 是否机器人 - Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"` - Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` - Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` - Chip int32 `protobuf:"varint,5,opt,name=chip,proto3" json:"chip,omitempty"` // 筹码 - Status int32 `protobuf:"varint,6,opt,name=status,proto3" json:"status,omitempty"` // 玩家状态: 1待准备开始,2已准备开始,已开始(3等待其他玩家动作,4待大盲注,5待小盲注,6待跟注,7已弃) - LastStatus int32 `protobuf:"varint,7,opt,name=lastStatus,proto3" json:"lastStatus,omitempty"` // TODO 删, 前端通过消息监听获取下注金额信息 - Master bool `protobuf:"varint,8,opt,name=master,proto3" json:"master,omitempty"` // 是否房主` - BetRole *BetRole `protobuf:"bytes,14,opt,name=betRole,proto3" json:"betRole,omitempty"` // 下注时规则限制 - HandCard []*Card `protobuf:"bytes,15,rep,name=handCard,proto3" json:"handCard,omitempty"` // 手牌 + Robot bool `protobuf:"varint,1,opt,name=robot,proto3" json:"robot,omitempty"` // 是否机器人 + Id int64 `protobuf:"varint,2,opt,name=id,proto3" json:"id,omitempty"` + Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` + Avatar string `protobuf:"bytes,4,opt,name=avatar,proto3" json:"avatar,omitempty"` + Chip int32 `protobuf:"varint,5,opt,name=chip,proto3" json:"chip,omitempty"` // 筹码 + Status int32 `protobuf:"varint,6,opt,name=status,proto3" json:"status,omitempty"` // 玩家状态: 1待准备开始,2已准备开始,已开始(3等待其他玩家动作,4待大盲注,5待小盲注,6待跟注,7已弃) + LastStatus int32 `protobuf:"varint,7,opt,name=lastStatus,proto3" json:"lastStatus,omitempty"` // TODO 删, 前端通过消息监听获取下注金额信息 + Master bool `protobuf:"varint,8,opt,name=master,proto3" json:"master,omitempty"` // 是否房主 + RoundBetTimes int32 `protobuf:"varint,11,opt,name=roundBetTimes,proto3" json:"roundBetTimes,omitempty"` // 该局下注次数 + TotalBetChip int32 `protobuf:"varint,13,opt,name=totalBetChip,proto3" json:"totalBetChip,omitempty"` // 该局牌已下注筹码 + BetRole *BetRole `protobuf:"bytes,14,opt,name=betRole,proto3" json:"betRole,omitempty"` // 下注时规则限制 + HandCard []*Card `protobuf:"bytes,15,rep,name=handCard,proto3" json:"handCard,omitempty"` // 手牌 } func (x *TablePlayer) Reset() { @@ -1365,6 +1367,20 @@ func (x *TablePlayer) GetMaster() bool { return false } +func (x *TablePlayer) GetRoundBetTimes() int32 { + if x != nil { + return x.RoundBetTimes + } + return 0 +} + +func (x *TablePlayer) GetTotalBetChip() int32 { + if x != nil { + return x.TotalBetChip + } + return 0 +} + func (x *TablePlayer) GetBetRole() *BetRole { if x != nil { return x.BetRole @@ -1440,8 +1456,9 @@ type BetRole struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - MinChip int32 `protobuf:"varint,1,opt,name=minChip,proto3" json:"minChip,omitempty"` // 最低下注额:小盲注加注(按惯例至少2倍与大盲注) - MaxChip int32 `protobuf:"varint,2,opt,name=maxChip,proto3" json:"maxChip,omitempty"` // 最高下注额: + BetMin int32 `protobuf:"varint,1,opt,name=betMin,proto3" json:"betMin,omitempty"` // 最低下注额 + BetMax int32 `protobuf:"varint,2,opt,name=betMax,proto3" json:"betMax,omitempty"` // 最高下注额 + BetOpts []int32 `protobuf:"varint,13,rep,packed,name=betOpts,proto3" json:"betOpts,omitempty"` // status=[4,6]时下注可操作按钮: 1跟注,2加注(-[0]+),3All-In,4弃牌,5过牌 } func (x *BetRole) Reset() { @@ -1476,20 +1493,27 @@ func (*BetRole) Descriptor() ([]byte, []int) { return file_poker_proto_rawDescGZIP(), []int{25} } -func (x *BetRole) GetMinChip() int32 { +func (x *BetRole) GetBetMin() int32 { if x != nil { - return x.MinChip + return x.BetMin } return 0 } -func (x *BetRole) GetMaxChip() int32 { +func (x *BetRole) GetBetMax() int32 { if x != nil { - return x.MaxChip + return x.BetMax } return 0 } +func (x *BetRole) GetBetOpts() []int32 { + if x != nil { + return x.BetOpts + } + return nil +} + // 开始游戏 type ReqGameStart struct { state protoimpl.MessageState @@ -1607,17 +1631,17 @@ func (*ResDismissGameTable) Descriptor() ([]byte, []int) { } // 下注 -type ReqPlaceBet struct { +type ReqBetting struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - BetType int32 `protobuf:"varint,1,opt,name=betType,proto3" json:"betType,omitempty"` // 1跟注,2加注(-[0]+),3All-In,4弃牌,5过牌 + BetType int32 `protobuf:"varint,1,opt,name=betType,proto3" json:"betType,omitempty"` // 1跟注,2加注或跟注(-[0]+),3All-In,4弃牌,5过牌 BetChip int32 `protobuf:"varint,2,opt,name=betChip,proto3" json:"betChip,omitempty"` // 跟注/加注金额 } -func (x *ReqPlaceBet) Reset() { - *x = ReqPlaceBet{} +func (x *ReqBetting) Reset() { + *x = ReqBetting{} if protoimpl.UnsafeEnabled { mi := &file_poker_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1625,13 +1649,13 @@ func (x *ReqPlaceBet) Reset() { } } -func (x *ReqPlaceBet) String() string { +func (x *ReqBetting) String() string { return protoimpl.X.MessageStringOf(x) } -func (*ReqPlaceBet) ProtoMessage() {} +func (*ReqBetting) ProtoMessage() {} -func (x *ReqPlaceBet) ProtoReflect() protoreflect.Message { +func (x *ReqBetting) ProtoReflect() protoreflect.Message { mi := &file_poker_proto_msgTypes[29] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -1643,19 +1667,19 @@ func (x *ReqPlaceBet) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use ReqPlaceBet.ProtoReflect.Descriptor instead. -func (*ReqPlaceBet) Descriptor() ([]byte, []int) { +// Deprecated: Use ReqBetting.ProtoReflect.Descriptor instead. +func (*ReqBetting) Descriptor() ([]byte, []int) { return file_poker_proto_rawDescGZIP(), []int{29} } -func (x *ReqPlaceBet) GetBetType() int32 { +func (x *ReqBetting) GetBetType() int32 { if x != nil { return x.BetType } return 0 } -func (x *ReqPlaceBet) GetBetChip() int32 { +func (x *ReqBetting) GetBetChip() int32 { if x != nil { return x.BetChip } @@ -1734,6 +1758,101 @@ func (x *ResNoticePlayerLine) GetLine3() string { return "" } +type ResGameEndSettle struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Game *ResGameFullStatus `protobuf:"bytes,11,opt,name=game,proto3" json:"game,omitempty"` +} + +func (x *ResGameEndSettle) Reset() { + *x = ResGameEndSettle{} + if protoimpl.UnsafeEnabled { + mi := &file_poker_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResGameEndSettle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResGameEndSettle) ProtoMessage() {} + +func (x *ResGameEndSettle) ProtoReflect() protoreflect.Message { + mi := &file_poker_proto_msgTypes[31] + 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 ResGameEndSettle.ProtoReflect.Descriptor instead. +func (*ResGameEndSettle) Descriptor() ([]byte, []int) { + return file_poker_proto_rawDescGZIP(), []int{31} +} + +func (x *ResGameEndSettle) GetGame() *ResGameFullStatus { + if x != nil { + return x.Game + } + return nil +} + +// 玩家输赢筹码通知 +type ResCalcWinnerChip struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PlayersWinChip map[int64]int32 `protobuf:"bytes,9,rep,name=playersWinChip,proto3" json:"playersWinChip,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` +} + +func (x *ResCalcWinnerChip) Reset() { + *x = ResCalcWinnerChip{} + if protoimpl.UnsafeEnabled { + mi := &file_poker_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResCalcWinnerChip) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResCalcWinnerChip) ProtoMessage() {} + +func (x *ResCalcWinnerChip) ProtoReflect() protoreflect.Message { + mi := &file_poker_proto_msgTypes[32] + 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 ResCalcWinnerChip.ProtoReflect.Descriptor instead. +func (*ResCalcWinnerChip) Descriptor() ([]byte, []int) { + return file_poker_proto_rawDescGZIP(), []int{32} +} + +func (x *ResCalcWinnerChip) GetPlayersWinChip() map[int64]int32 { + if x != nil { + return x.PlayersWinChip + } + return nil +} + var File_poker_proto protoreflect.FileDescriptor var file_poker_proto_rawDesc = []byte{ @@ -1830,7 +1949,7 @@ var file_poker_proto_rawDesc = []byte{ 0x61, 0x72, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x0f, 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, - 0x9a, 0x02, 0x0a, 0x0b, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, + 0xe4, 0x02, 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, @@ -1842,36 +1961,56 @@ var file_poker_proto_rawDesc = []byte{ 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x12, 0x26, 0x0a, - 0x07, 0x62, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x07, 0x62, 0x65, - 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x08, 0x68, 0x61, 0x6e, 0x64, 0x43, 0x61, 0x72, - 0x64, 0x18, 0x0f, 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, 0x3d, 0x0a, 0x07, 0x42, 0x65, - 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x69, 0x6e, 0x43, 0x68, 0x69, 0x70, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, 0x69, 0x6e, 0x43, 0x68, 0x69, 0x70, 0x12, - 0x18, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x07, 0x6d, 0x61, 0x78, 0x43, 0x68, 0x69, 0x70, 0x22, 0x0e, 0x0a, 0x0c, 0x52, 0x65, 0x71, + 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6d, 0x61, 0x73, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, + 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x65, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x42, 0x65, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, 0x65, 0x74, 0x43, + 0x68, 0x69, 0x70, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x42, 0x65, 0x74, 0x43, 0x68, 0x69, 0x70, 0x12, 0x26, 0x0a, 0x07, 0x62, 0x65, 0x74, 0x52, 0x6f, + 0x6c, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x42, + 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x52, 0x07, 0x62, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x12, + 0x25, 0x0a, 0x08, 0x68, 0x61, 0x6e, 0x64, 0x43, 0x61, 0x72, 0x64, 0x18, 0x0f, 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, 0x53, 0x0a, 0x07, 0x42, 0x65, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x12, + 0x16, 0x0a, 0x06, 0x62, 0x65, 0x74, 0x4d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x06, 0x62, 0x65, 0x74, 0x4d, 0x69, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x65, 0x74, 0x4d, 0x61, + 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x65, 0x74, 0x4d, 0x61, 0x78, 0x12, + 0x18, 0x0a, 0x07, 0x62, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x05, + 0x52, 0x07, 0x62, 0x65, 0x74, 0x4f, 0x70, 0x74, 0x73, 0x22, 0x0e, 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x47, 0x61, 0x6d, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 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, 0x22, 0x41, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x50, 0x6c, - 0x61, 0x63, 0x65, 0x42, 0x65, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x65, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x62, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x18, 0x0a, 0x07, 0x62, 0x65, 0x74, 0x43, 0x68, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x07, 0x62, 0x65, 0x74, 0x43, 0x68, 0x69, 0x70, 0x22, 0x73, 0x0a, 0x13, 0x52, 0x65, - 0x73, 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4c, 0x69, 0x6e, - 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, 0x12, 0x14, 0x0a, - 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x31, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x69, - 0x6e, 0x65, 0x31, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x32, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x32, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6e, - 0x65, 0x33, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x33, 0x42, - 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x65, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x40, 0x0a, 0x0a, 0x52, 0x65, 0x71, 0x42, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x62, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x18, 0x0a, 0x07, 0x62, 0x65, 0x74, 0x43, 0x68, 0x69, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x07, 0x62, 0x65, 0x74, 0x43, 0x68, 0x69, 0x70, 0x22, 0x73, 0x0a, 0x13, 0x52, 0x65, 0x73, + 0x4e, 0x6f, 0x74, 0x69, 0x63, 0x65, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x4c, 0x69, 0x6e, 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, 0x12, 0x14, 0x0a, 0x05, + 0x6c, 0x69, 0x6e, 0x65, 0x31, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x69, 0x6e, + 0x65, 0x31, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x32, 0x18, 0x0c, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x32, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6e, 0x65, + 0x33, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x69, 0x6e, 0x65, 0x33, 0x22, 0x3e, + 0x0a, 0x10, 0x52, 0x65, 0x73, 0x47, 0x61, 0x6d, 0x65, 0x45, 0x6e, 0x64, 0x53, 0x65, 0x74, 0x74, + 0x6c, 0x65, 0x12, 0x2a, 0x0a, 0x04, 0x67, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x52, 0x65, 0x73, 0x47, 0x61, 0x6d, 0x65, 0x46, 0x75, + 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x04, 0x67, 0x61, 0x6d, 0x65, 0x22, 0xaa, + 0x01, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x43, 0x61, 0x6c, 0x63, 0x57, 0x69, 0x6e, 0x6e, 0x65, 0x72, + 0x43, 0x68, 0x69, 0x70, 0x12, 0x52, 0x0a, 0x0e, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x57, + 0x69, 0x6e, 0x43, 0x68, 0x69, 0x70, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x52, 0x65, 0x73, 0x43, 0x61, 0x6c, 0x63, 0x57, 0x69, 0x6e, 0x6e, 0x65, 0x72, + 0x43, 0x68, 0x69, 0x70, 0x2e, 0x50, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x57, 0x69, 0x6e, 0x43, + 0x68, 0x69, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x70, 0x6c, 0x61, 0x79, 0x65, 0x72, + 0x73, 0x57, 0x69, 0x6e, 0x43, 0x68, 0x69, 0x70, 0x1a, 0x41, 0x0a, 0x13, 0x50, 0x6c, 0x61, 0x79, + 0x65, 0x72, 0x73, 0x57, 0x69, 0x6e, 0x43, 0x68, 0x69, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0b, 0x5a, 0x09, 0x2e, + 0x2f, 0x61, 0x70, 0x69, 0x3b, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1886,7 +2025,7 @@ func file_poker_proto_rawDescGZIP() []byte { return file_poker_proto_rawDescData } -var file_poker_proto_msgTypes = make([]protoimpl.MessageInfo, 31) +var file_poker_proto_msgTypes = make([]protoimpl.MessageInfo, 34) var file_poker_proto_goTypes = []interface{}{ (*ProtoWrap)(nil), // 0: api.ProtoWrap (*Ping)(nil), // 1: api.Ping @@ -1917,8 +2056,11 @@ var file_poker_proto_goTypes = []interface{}{ (*ReqGameStart)(nil), // 26: api.ReqGameStart (*ReqDismissGameTable)(nil), // 27: api.ReqDismissGameTable (*ResDismissGameTable)(nil), // 28: api.ResDismissGameTable - (*ReqPlaceBet)(nil), // 29: api.ReqPlaceBet + (*ReqBetting)(nil), // 29: api.ReqBetting (*ResNoticePlayerLine)(nil), // 30: api.ResNoticePlayerLine + (*ResGameEndSettle)(nil), // 31: api.ResGameEndSettle + (*ResCalcWinnerChip)(nil), // 32: api.ResCalcWinnerChip + nil, // 33: api.ResCalcWinnerChip.PlayersWinChipEntry } var file_poker_proto_depIdxs = []int32{ 9, // 0: api.ResLobbyView.tables:type_name -> api.LobbyTable @@ -1927,11 +2069,13 @@ var file_poker_proto_depIdxs = []int32{ 23, // 3: api.ResGameFullStatus.players:type_name -> api.TablePlayer 25, // 4: api.TablePlayer.betRole:type_name -> api.BetRole 24, // 5: api.TablePlayer.handCard:type_name -> api.Card - 6, // [6:6] is the sub-list for method output_type - 6, // [6:6] is the sub-list for method input_type - 6, // [6:6] is the sub-list for extension type_name - 6, // [6:6] is the sub-list for extension extendee - 0, // [0:6] is the sub-list for field type_name + 22, // 6: api.ResGameEndSettle.game:type_name -> api.ResGameFullStatus + 33, // 7: api.ResCalcWinnerChip.playersWinChip:type_name -> api.ResCalcWinnerChip.PlayersWinChipEntry + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_poker_proto_init() } @@ -2289,7 +2433,7 @@ func file_poker_proto_init() { } } file_poker_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReqPlaceBet); i { + switch v := v.(*ReqBetting); i { case 0: return &v.state case 1: @@ -2312,6 +2456,30 @@ func file_poker_proto_init() { return nil } } + file_poker_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResGameEndSettle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_poker_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResCalcWinnerChip); 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{ @@ -2319,7 +2487,7 @@ func file_poker_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_poker_proto_rawDesc, NumEnums: 0, - NumMessages: 31, + NumMessages: 34, NumExtensions: 0, NumServices: 0, }, diff --git a/api/poker.proto b/api/poker.proto index 8ab5ce4..9662074 100644 --- a/api/poker.proto +++ b/api/poker.proto @@ -148,7 +148,10 @@ message TablePlayer { int32 chip = 5; // 筹码 int32 status = 6; // 玩家状态: 1待准备开始,2已准备开始,已开始(3等待其他玩家动作,4待大盲注,5待小盲注,6待跟注,7已弃) int32 lastStatus = 7; // TODO 删, 前端通过消息监听获取下注金额信息 - bool master = 8; // 是否房主` + bool master = 8; // 是否房主 + int32 roundBetTimes = 11; // 该局下注次数 + int32 totalBetChip = 13; // 该局牌已下注筹码 + BetRole betRole = 14; // 下注时规则限制 repeated Card handCard = 15; // 手牌 } @@ -160,8 +163,9 @@ message Card { // player status in (4,6) 跟注时规则 message BetRole { - int32 minChip = 1; // 最低下注额:小盲注加注(按惯例至少2倍与大盲注) - int32 maxChip = 2; // 最高下注额: + int32 betMin = 1; // 最低下注额 + int32 betMax = 2; // 最高下注额 + repeated int32 betOpts = 13; // status=[4,6]时下注可操作按钮: 1跟注,2加注(-[0]+),3All-In,4弃牌,5过牌 } // 加入游戏 ============= end @@ -178,8 +182,8 @@ message ResDismissGameTable { } // 下注 -message ReqPlaceBet { - int32 betType = 1; // 1跟注,2加注(-[0]+),3All-In,4弃牌,5过牌 +message ReqBetting { + int32 betType = 1; // 1跟注,2加注或跟注(-[0]+),3All-In,4弃牌,5过牌 int32 betChip = 2; // 跟注/加注金额 } @@ -192,6 +196,10 @@ message ResNoticePlayerLine { string line3 = 13; } +message ResGameEndSettle { + ResGameFullStatus game = 11; +} + // 玩家输赢筹码通知 message ResCalcWinnerChip { map playersWinChip = 9; diff --git a/api/proto.js b/api/proto.js index 293cce1..95953ab 100644 --- a/api/proto.js +++ b/api/proto.js @@ -5289,6 +5289,8 @@ export const api = $root.api = (() => { * @property {number|null} [status] TablePlayer status * @property {number|null} [lastStatus] TablePlayer lastStatus * @property {boolean|null} [master] TablePlayer master + * @property {number|null} [roundBetTimes] TablePlayer roundBetTimes + * @property {number|null} [totalBetChip] TablePlayer totalBetChip * @property {api.IBetRole|null} [betRole] TablePlayer betRole * @property {Array.|null} [handCard] TablePlayer handCard */ @@ -5373,6 +5375,22 @@ export const api = $root.api = (() => { */ TablePlayer.prototype.master = false; + /** + * TablePlayer roundBetTimes. + * @member {number} roundBetTimes + * @memberof api.TablePlayer + * @instance + */ + TablePlayer.prototype.roundBetTimes = 0; + + /** + * TablePlayer totalBetChip. + * @member {number} totalBetChip + * @memberof api.TablePlayer + * @instance + */ + TablePlayer.prototype.totalBetChip = 0; + /** * TablePlayer betRole. * @member {api.IBetRole|null|undefined} betRole @@ -5429,6 +5447,10 @@ export const api = $root.api = (() => { writer.uint32(/* id 7, wireType 0 =*/56).int32(message.lastStatus); if (message.master != null && Object.hasOwnProperty.call(message, "master")) writer.uint32(/* id 8, wireType 0 =*/64).bool(message.master); + if (message.roundBetTimes != null && Object.hasOwnProperty.call(message, "roundBetTimes")) + writer.uint32(/* id 11, wireType 0 =*/88).int32(message.roundBetTimes); + if (message.totalBetChip != null && Object.hasOwnProperty.call(message, "totalBetChip")) + writer.uint32(/* id 13, wireType 0 =*/104).int32(message.totalBetChip); if (message.betRole != null && Object.hasOwnProperty.call(message, "betRole")) $root.api.BetRole.encode(message.betRole, writer.uint32(/* id 14, wireType 2 =*/114).fork()).ldelim(); if (message.handCard != null && message.handCard.length) @@ -5500,6 +5522,14 @@ export const api = $root.api = (() => { message.master = reader.bool(); break; } + case 11: { + message.roundBetTimes = reader.int32(); + break; + } + case 13: { + message.totalBetChip = reader.int32(); + break; + } case 14: { message.betRole = $root.api.BetRole.decode(reader, reader.uint32()); break; @@ -5569,6 +5599,12 @@ export const api = $root.api = (() => { if (message.master != null && message.hasOwnProperty("master")) if (typeof message.master !== "boolean") return "master: boolean expected"; + if (message.roundBetTimes != null && message.hasOwnProperty("roundBetTimes")) + if (!$util.isInteger(message.roundBetTimes)) + return "roundBetTimes: integer expected"; + if (message.totalBetChip != null && message.hasOwnProperty("totalBetChip")) + if (!$util.isInteger(message.totalBetChip)) + return "totalBetChip: integer expected"; if (message.betRole != null && message.hasOwnProperty("betRole")) { let error = $root.api.BetRole.verify(message.betRole); if (error) @@ -5621,6 +5657,10 @@ export const api = $root.api = (() => { message.lastStatus = object.lastStatus | 0; if (object.master != null) message.master = Boolean(object.master); + if (object.roundBetTimes != null) + message.roundBetTimes = object.roundBetTimes | 0; + if (object.totalBetChip != null) + message.totalBetChip = object.totalBetChip | 0; if (object.betRole != null) { if (typeof object.betRole !== "object") throw TypeError(".api.TablePlayer.betRole: object expected"); @@ -5667,6 +5707,8 @@ export const api = $root.api = (() => { object.status = 0; object.lastStatus = 0; object.master = false; + object.roundBetTimes = 0; + object.totalBetChip = 0; object.betRole = null; } if (message.robot != null && message.hasOwnProperty("robot")) @@ -5688,6 +5730,10 @@ export const api = $root.api = (() => { object.lastStatus = message.lastStatus; if (message.master != null && message.hasOwnProperty("master")) object.master = message.master; + if (message.roundBetTimes != null && message.hasOwnProperty("roundBetTimes")) + object.roundBetTimes = message.roundBetTimes; + if (message.totalBetChip != null && message.hasOwnProperty("totalBetChip")) + object.totalBetChip = message.totalBetChip; if (message.betRole != null && message.hasOwnProperty("betRole")) object.betRole = $root.api.BetRole.toObject(message.betRole, options); if (message.handCard && message.handCard.length) { @@ -5960,8 +6006,9 @@ export const api = $root.api = (() => { * Properties of a BetRole. * @memberof api * @interface IBetRole - * @property {number|null} [minChip] BetRole minChip - * @property {number|null} [maxChip] BetRole maxChip + * @property {number|null} [betMin] BetRole betMin + * @property {number|null} [betMax] BetRole betMax + * @property {Array.|null} [betOpts] BetRole betOpts */ /** @@ -5973,6 +6020,7 @@ export const api = $root.api = (() => { * @param {api.IBetRole=} [properties] Properties to set */ function BetRole(properties) { + this.betOpts = []; if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -5980,20 +6028,28 @@ export const api = $root.api = (() => { } /** - * BetRole minChip. - * @member {number} minChip + * BetRole betMin. + * @member {number} betMin + * @memberof api.BetRole + * @instance + */ + BetRole.prototype.betMin = 0; + + /** + * BetRole betMax. + * @member {number} betMax * @memberof api.BetRole * @instance */ - BetRole.prototype.minChip = 0; + BetRole.prototype.betMax = 0; /** - * BetRole maxChip. - * @member {number} maxChip + * BetRole betOpts. + * @member {Array.} betOpts * @memberof api.BetRole * @instance */ - BetRole.prototype.maxChip = 0; + BetRole.prototype.betOpts = $util.emptyArray; /** * Creates a new BetRole instance using the specified properties. @@ -6019,10 +6075,16 @@ export const api = $root.api = (() => { BetRole.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); - if (message.minChip != null && Object.hasOwnProperty.call(message, "minChip")) - writer.uint32(/* id 1, wireType 0 =*/8).int32(message.minChip); - if (message.maxChip != null && Object.hasOwnProperty.call(message, "maxChip")) - writer.uint32(/* id 2, wireType 0 =*/16).int32(message.maxChip); + if (message.betMin != null && Object.hasOwnProperty.call(message, "betMin")) + writer.uint32(/* id 1, wireType 0 =*/8).int32(message.betMin); + if (message.betMax != null && Object.hasOwnProperty.call(message, "betMax")) + writer.uint32(/* id 2, wireType 0 =*/16).int32(message.betMax); + if (message.betOpts != null && message.betOpts.length) { + writer.uint32(/* id 13, wireType 2 =*/106).fork(); + for (let i = 0; i < message.betOpts.length; ++i) + writer.int32(message.betOpts[i]); + writer.ldelim(); + } return writer; }; @@ -6058,11 +6120,22 @@ export const api = $root.api = (() => { let tag = reader.uint32(); switch (tag >>> 3) { case 1: { - message.minChip = reader.int32(); + message.betMin = reader.int32(); break; } case 2: { - message.maxChip = reader.int32(); + message.betMax = reader.int32(); + break; + } + case 13: { + if (!(message.betOpts && message.betOpts.length)) + message.betOpts = []; + if ((tag & 7) === 2) { + let end2 = reader.uint32() + reader.pos; + while (reader.pos < end2) + message.betOpts.push(reader.int32()); + } else + message.betOpts.push(reader.int32()); break; } default: @@ -6100,12 +6173,19 @@ export const api = $root.api = (() => { BetRole.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; - if (message.minChip != null && message.hasOwnProperty("minChip")) - if (!$util.isInteger(message.minChip)) - return "minChip: integer expected"; - if (message.maxChip != null && message.hasOwnProperty("maxChip")) - if (!$util.isInteger(message.maxChip)) - return "maxChip: integer expected"; + if (message.betMin != null && message.hasOwnProperty("betMin")) + if (!$util.isInteger(message.betMin)) + return "betMin: integer expected"; + if (message.betMax != null && message.hasOwnProperty("betMax")) + if (!$util.isInteger(message.betMax)) + return "betMax: integer expected"; + if (message.betOpts != null && message.hasOwnProperty("betOpts")) { + if (!Array.isArray(message.betOpts)) + return "betOpts: array expected"; + for (let i = 0; i < message.betOpts.length; ++i) + if (!$util.isInteger(message.betOpts[i])) + return "betOpts: integer[] expected"; + } return null; }; @@ -6121,10 +6201,17 @@ export const api = $root.api = (() => { if (object instanceof $root.api.BetRole) return object; let message = new $root.api.BetRole(); - if (object.minChip != null) - message.minChip = object.minChip | 0; - if (object.maxChip != null) - message.maxChip = object.maxChip | 0; + if (object.betMin != null) + message.betMin = object.betMin | 0; + if (object.betMax != null) + message.betMax = object.betMax | 0; + if (object.betOpts) { + if (!Array.isArray(object.betOpts)) + throw TypeError(".api.BetRole.betOpts: array expected"); + message.betOpts = []; + for (let i = 0; i < object.betOpts.length; ++i) + message.betOpts[i] = object.betOpts[i] | 0; + } return message; }; @@ -6141,14 +6228,21 @@ export const api = $root.api = (() => { if (!options) options = {}; let object = {}; + if (options.arrays || options.defaults) + object.betOpts = []; if (options.defaults) { - object.minChip = 0; - object.maxChip = 0; + object.betMin = 0; + object.betMax = 0; + } + if (message.betMin != null && message.hasOwnProperty("betMin")) + object.betMin = message.betMin; + if (message.betMax != null && message.hasOwnProperty("betMax")) + object.betMax = message.betMax; + if (message.betOpts && message.betOpts.length) { + object.betOpts = []; + for (let j = 0; j < message.betOpts.length; ++j) + object.betOpts[j] = message.betOpts[j]; } - if (message.minChip != null && message.hasOwnProperty("minChip")) - object.minChip = message.minChip; - if (message.maxChip != null && message.hasOwnProperty("maxChip")) - object.maxChip = message.maxChip; return object; }; @@ -6706,25 +6800,25 @@ export const api = $root.api = (() => { return ResDismissGameTable; })(); - api.ReqPlaceBet = (function() { + api.ReqBetting = (function() { /** - * Properties of a ReqPlaceBet. + * Properties of a ReqBetting. * @memberof api - * @interface IReqPlaceBet - * @property {number|null} [betType] ReqPlaceBet betType - * @property {number|null} [betChip] ReqPlaceBet betChip + * @interface IReqBetting + * @property {number|null} [betType] ReqBetting betType + * @property {number|null} [betChip] ReqBetting betChip */ /** - * Constructs a new ReqPlaceBet. + * Constructs a new ReqBetting. * @memberof api - * @classdesc Represents a ReqPlaceBet. - * @implements IReqPlaceBet + * @classdesc Represents a ReqBetting. + * @implements IReqBetting * @constructor - * @param {api.IReqPlaceBet=} [properties] Properties to set + * @param {api.IReqBetting=} [properties] Properties to set */ - function ReqPlaceBet(properties) { + function ReqBetting(properties) { if (properties) for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) if (properties[keys[i]] != null) @@ -6732,43 +6826,43 @@ export const api = $root.api = (() => { } /** - * ReqPlaceBet betType. + * ReqBetting betType. * @member {number} betType - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @instance */ - ReqPlaceBet.prototype.betType = 0; + ReqBetting.prototype.betType = 0; /** - * ReqPlaceBet betChip. + * ReqBetting betChip. * @member {number} betChip - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @instance */ - ReqPlaceBet.prototype.betChip = 0; + ReqBetting.prototype.betChip = 0; /** - * Creates a new ReqPlaceBet instance using the specified properties. + * Creates a new ReqBetting instance using the specified properties. * @function create - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @static - * @param {api.IReqPlaceBet=} [properties] Properties to set - * @returns {api.ReqPlaceBet} ReqPlaceBet instance + * @param {api.IReqBetting=} [properties] Properties to set + * @returns {api.ReqBetting} ReqBetting instance */ - ReqPlaceBet.create = function create(properties) { - return new ReqPlaceBet(properties); + ReqBetting.create = function create(properties) { + return new ReqBetting(properties); }; /** - * Encodes the specified ReqPlaceBet message. Does not implicitly {@link api.ReqPlaceBet.verify|verify} messages. + * Encodes the specified ReqBetting message. Does not implicitly {@link api.ReqBetting.verify|verify} messages. * @function encode - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @static - * @param {api.IReqPlaceBet} message ReqPlaceBet message or plain object to encode + * @param {api.IReqBetting} message ReqBetting message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - ReqPlaceBet.encode = function encode(message, writer) { + ReqBetting.encode = function encode(message, writer) { if (!writer) writer = $Writer.create(); if (message.betType != null && Object.hasOwnProperty.call(message, "betType")) @@ -6779,33 +6873,33 @@ export const api = $root.api = (() => { }; /** - * Encodes the specified ReqPlaceBet message, length delimited. Does not implicitly {@link api.ReqPlaceBet.verify|verify} messages. + * Encodes the specified ReqBetting message, length delimited. Does not implicitly {@link api.ReqBetting.verify|verify} messages. * @function encodeDelimited - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @static - * @param {api.IReqPlaceBet} message ReqPlaceBet message or plain object to encode + * @param {api.IReqBetting} message ReqBetting message or plain object to encode * @param {$protobuf.Writer} [writer] Writer to encode to * @returns {$protobuf.Writer} Writer */ - ReqPlaceBet.encodeDelimited = function encodeDelimited(message, writer) { + ReqBetting.encodeDelimited = function encodeDelimited(message, writer) { return this.encode(message, writer).ldelim(); }; /** - * Decodes a ReqPlaceBet message from the specified reader or buffer. + * Decodes a ReqBetting message from the specified reader or buffer. * @function decode - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from * @param {number} [length] Message length if known beforehand - * @returns {api.ReqPlaceBet} ReqPlaceBet + * @returns {api.ReqBetting} ReqBetting * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - ReqPlaceBet.decode = function decode(reader, length) { + ReqBetting.decode = function decode(reader, length) { if (!(reader instanceof $Reader)) reader = $Reader.create(reader); - let end = length === undefined ? reader.len : reader.pos + length, message = new $root.api.ReqPlaceBet(); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.api.ReqBetting(); while (reader.pos < end) { let tag = reader.uint32(); switch (tag >>> 3) { @@ -6826,30 +6920,30 @@ export const api = $root.api = (() => { }; /** - * Decodes a ReqPlaceBet message from the specified reader or buffer, length delimited. + * Decodes a ReqBetting message from the specified reader or buffer, length delimited. * @function decodeDelimited - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @static * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from - * @returns {api.ReqPlaceBet} ReqPlaceBet + * @returns {api.ReqBetting} ReqBetting * @throws {Error} If the payload is not a reader or valid buffer * @throws {$protobuf.util.ProtocolError} If required fields are missing */ - ReqPlaceBet.decodeDelimited = function decodeDelimited(reader) { + ReqBetting.decodeDelimited = function decodeDelimited(reader) { if (!(reader instanceof $Reader)) reader = new $Reader(reader); return this.decode(reader, reader.uint32()); }; /** - * Verifies a ReqPlaceBet message. + * Verifies a ReqBetting message. * @function verify - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @static * @param {Object.} message Plain object to verify * @returns {string|null} `null` if valid, otherwise the reason why it is not */ - ReqPlaceBet.verify = function verify(message) { + ReqBetting.verify = function verify(message) { if (typeof message !== "object" || message === null) return "object expected"; if (message.betType != null && message.hasOwnProperty("betType")) @@ -6862,17 +6956,17 @@ export const api = $root.api = (() => { }; /** - * Creates a ReqPlaceBet message from a plain object. Also converts values to their respective internal types. + * Creates a ReqBetting message from a plain object. Also converts values to their respective internal types. * @function fromObject - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @static * @param {Object.} object Plain object - * @returns {api.ReqPlaceBet} ReqPlaceBet + * @returns {api.ReqBetting} ReqBetting */ - ReqPlaceBet.fromObject = function fromObject(object) { - if (object instanceof $root.api.ReqPlaceBet) + ReqBetting.fromObject = function fromObject(object) { + if (object instanceof $root.api.ReqBetting) return object; - let message = new $root.api.ReqPlaceBet(); + let message = new $root.api.ReqBetting(); if (object.betType != null) message.betType = object.betType | 0; if (object.betChip != null) @@ -6881,15 +6975,15 @@ export const api = $root.api = (() => { }; /** - * Creates a plain object from a ReqPlaceBet message. Also converts values to other types if specified. + * Creates a plain object from a ReqBetting message. Also converts values to other types if specified. * @function toObject - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @static - * @param {api.ReqPlaceBet} message ReqPlaceBet + * @param {api.ReqBetting} message ReqBetting * @param {$protobuf.IConversionOptions} [options] Conversion options * @returns {Object.} Plain object */ - ReqPlaceBet.toObject = function toObject(message, options) { + ReqBetting.toObject = function toObject(message, options) { if (!options) options = {}; let object = {}; @@ -6905,32 +6999,32 @@ export const api = $root.api = (() => { }; /** - * Converts this ReqPlaceBet to JSON. + * Converts this ReqBetting to JSON. * @function toJSON - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @instance * @returns {Object.} JSON object */ - ReqPlaceBet.prototype.toJSON = function toJSON() { + ReqBetting.prototype.toJSON = function toJSON() { return this.constructor.toObject(this, $protobuf.util.toJSONOptions); }; /** - * Gets the default type url for ReqPlaceBet + * Gets the default type url for ReqBetting * @function getTypeUrl - * @memberof api.ReqPlaceBet + * @memberof api.ReqBetting * @static * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") * @returns {string} The default type url */ - ReqPlaceBet.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + ReqBetting.getTypeUrl = function getTypeUrl(typeUrlPrefix) { if (typeUrlPrefix === undefined) { typeUrlPrefix = "type.googleapis.com"; } - return typeUrlPrefix + "/api.ReqPlaceBet"; + return typeUrlPrefix + "/api.ReqBetting"; }; - return ReqPlaceBet; + return ReqBetting; })(); api.ResNoticePlayerLine = (function() { @@ -7220,6 +7314,455 @@ export const api = $root.api = (() => { return ResNoticePlayerLine; })(); + api.ResGameEndSettle = (function() { + + /** + * Properties of a ResGameEndSettle. + * @memberof api + * @interface IResGameEndSettle + * @property {api.IResGameFullStatus|null} [game] ResGameEndSettle game + */ + + /** + * Constructs a new ResGameEndSettle. + * @memberof api + * @classdesc Represents a ResGameEndSettle. + * @implements IResGameEndSettle + * @constructor + * @param {api.IResGameEndSettle=} [properties] Properties to set + */ + function ResGameEndSettle(properties) { + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * ResGameEndSettle game. + * @member {api.IResGameFullStatus|null|undefined} game + * @memberof api.ResGameEndSettle + * @instance + */ + ResGameEndSettle.prototype.game = null; + + /** + * Creates a new ResGameEndSettle instance using the specified properties. + * @function create + * @memberof api.ResGameEndSettle + * @static + * @param {api.IResGameEndSettle=} [properties] Properties to set + * @returns {api.ResGameEndSettle} ResGameEndSettle instance + */ + ResGameEndSettle.create = function create(properties) { + return new ResGameEndSettle(properties); + }; + + /** + * Encodes the specified ResGameEndSettle message. Does not implicitly {@link api.ResGameEndSettle.verify|verify} messages. + * @function encode + * @memberof api.ResGameEndSettle + * @static + * @param {api.IResGameEndSettle} message ResGameEndSettle message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ResGameEndSettle.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.game != null && Object.hasOwnProperty.call(message, "game")) + $root.api.ResGameFullStatus.encode(message.game, writer.uint32(/* id 11, wireType 2 =*/90).fork()).ldelim(); + return writer; + }; + + /** + * Encodes the specified ResGameEndSettle message, length delimited. Does not implicitly {@link api.ResGameEndSettle.verify|verify} messages. + * @function encodeDelimited + * @memberof api.ResGameEndSettle + * @static + * @param {api.IResGameEndSettle} message ResGameEndSettle message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ResGameEndSettle.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ResGameEndSettle message from the specified reader or buffer. + * @function decode + * @memberof api.ResGameEndSettle + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {api.ResGameEndSettle} ResGameEndSettle + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ResGameEndSettle.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.api.ResGameEndSettle(); + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 11: { + message.game = $root.api.ResGameFullStatus.decode(reader, reader.uint32()); + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ResGameEndSettle message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof api.ResGameEndSettle + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {api.ResGameEndSettle} ResGameEndSettle + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ResGameEndSettle.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ResGameEndSettle message. + * @function verify + * @memberof api.ResGameEndSettle + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ResGameEndSettle.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.game != null && message.hasOwnProperty("game")) { + let error = $root.api.ResGameFullStatus.verify(message.game); + if (error) + return "game." + error; + } + return null; + }; + + /** + * Creates a ResGameEndSettle message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof api.ResGameEndSettle + * @static + * @param {Object.} object Plain object + * @returns {api.ResGameEndSettle} ResGameEndSettle + */ + ResGameEndSettle.fromObject = function fromObject(object) { + if (object instanceof $root.api.ResGameEndSettle) + return object; + let message = new $root.api.ResGameEndSettle(); + if (object.game != null) { + if (typeof object.game !== "object") + throw TypeError(".api.ResGameEndSettle.game: object expected"); + message.game = $root.api.ResGameFullStatus.fromObject(object.game); + } + return message; + }; + + /** + * Creates a plain object from a ResGameEndSettle message. Also converts values to other types if specified. + * @function toObject + * @memberof api.ResGameEndSettle + * @static + * @param {api.ResGameEndSettle} message ResGameEndSettle + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ResGameEndSettle.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.defaults) + object.game = null; + if (message.game != null && message.hasOwnProperty("game")) + object.game = $root.api.ResGameFullStatus.toObject(message.game, options); + return object; + }; + + /** + * Converts this ResGameEndSettle to JSON. + * @function toJSON + * @memberof api.ResGameEndSettle + * @instance + * @returns {Object.} JSON object + */ + ResGameEndSettle.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ResGameEndSettle + * @function getTypeUrl + * @memberof api.ResGameEndSettle + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ResGameEndSettle.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/api.ResGameEndSettle"; + }; + + return ResGameEndSettle; + })(); + + api.ResCalcWinnerChip = (function() { + + /** + * Properties of a ResCalcWinnerChip. + * @memberof api + * @interface IResCalcWinnerChip + * @property {Object.|null} [playersWinChip] ResCalcWinnerChip playersWinChip + */ + + /** + * Constructs a new ResCalcWinnerChip. + * @memberof api + * @classdesc Represents a ResCalcWinnerChip. + * @implements IResCalcWinnerChip + * @constructor + * @param {api.IResCalcWinnerChip=} [properties] Properties to set + */ + function ResCalcWinnerChip(properties) { + this.playersWinChip = {}; + if (properties) + for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i) + if (properties[keys[i]] != null) + this[keys[i]] = properties[keys[i]]; + } + + /** + * ResCalcWinnerChip playersWinChip. + * @member {Object.} playersWinChip + * @memberof api.ResCalcWinnerChip + * @instance + */ + ResCalcWinnerChip.prototype.playersWinChip = $util.emptyObject; + + /** + * Creates a new ResCalcWinnerChip instance using the specified properties. + * @function create + * @memberof api.ResCalcWinnerChip + * @static + * @param {api.IResCalcWinnerChip=} [properties] Properties to set + * @returns {api.ResCalcWinnerChip} ResCalcWinnerChip instance + */ + ResCalcWinnerChip.create = function create(properties) { + return new ResCalcWinnerChip(properties); + }; + + /** + * Encodes the specified ResCalcWinnerChip message. Does not implicitly {@link api.ResCalcWinnerChip.verify|verify} messages. + * @function encode + * @memberof api.ResCalcWinnerChip + * @static + * @param {api.IResCalcWinnerChip} message ResCalcWinnerChip message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ResCalcWinnerChip.encode = function encode(message, writer) { + if (!writer) + writer = $Writer.create(); + if (message.playersWinChip != null && Object.hasOwnProperty.call(message, "playersWinChip")) + for (let keys = Object.keys(message.playersWinChip), i = 0; i < keys.length; ++i) + writer.uint32(/* id 9, wireType 2 =*/74).fork().uint32(/* id 1, wireType 0 =*/8).int64(keys[i]).uint32(/* id 2, wireType 0 =*/16).int32(message.playersWinChip[keys[i]]).ldelim(); + return writer; + }; + + /** + * Encodes the specified ResCalcWinnerChip message, length delimited. Does not implicitly {@link api.ResCalcWinnerChip.verify|verify} messages. + * @function encodeDelimited + * @memberof api.ResCalcWinnerChip + * @static + * @param {api.IResCalcWinnerChip} message ResCalcWinnerChip message or plain object to encode + * @param {$protobuf.Writer} [writer] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + ResCalcWinnerChip.encodeDelimited = function encodeDelimited(message, writer) { + return this.encode(message, writer).ldelim(); + }; + + /** + * Decodes a ResCalcWinnerChip message from the specified reader or buffer. + * @function decode + * @memberof api.ResCalcWinnerChip + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @param {number} [length] Message length if known beforehand + * @returns {api.ResCalcWinnerChip} ResCalcWinnerChip + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ResCalcWinnerChip.decode = function decode(reader, length) { + if (!(reader instanceof $Reader)) + reader = $Reader.create(reader); + let end = length === undefined ? reader.len : reader.pos + length, message = new $root.api.ResCalcWinnerChip(), key, value; + while (reader.pos < end) { + let tag = reader.uint32(); + switch (tag >>> 3) { + case 9: { + if (message.playersWinChip === $util.emptyObject) + message.playersWinChip = {}; + let end2 = reader.uint32() + reader.pos; + key = 0; + value = 0; + while (reader.pos < end2) { + let tag2 = reader.uint32(); + switch (tag2 >>> 3) { + case 1: + key = reader.int64(); + break; + case 2: + value = reader.int32(); + break; + default: + reader.skipType(tag2 & 7); + break; + } + } + message.playersWinChip[typeof key === "object" ? $util.longToHash(key) : key] = value; + break; + } + default: + reader.skipType(tag & 7); + break; + } + } + return message; + }; + + /** + * Decodes a ResCalcWinnerChip message from the specified reader or buffer, length delimited. + * @function decodeDelimited + * @memberof api.ResCalcWinnerChip + * @static + * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from + * @returns {api.ResCalcWinnerChip} ResCalcWinnerChip + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + ResCalcWinnerChip.decodeDelimited = function decodeDelimited(reader) { + if (!(reader instanceof $Reader)) + reader = new $Reader(reader); + return this.decode(reader, reader.uint32()); + }; + + /** + * Verifies a ResCalcWinnerChip message. + * @function verify + * @memberof api.ResCalcWinnerChip + * @static + * @param {Object.} message Plain object to verify + * @returns {string|null} `null` if valid, otherwise the reason why it is not + */ + ResCalcWinnerChip.verify = function verify(message) { + if (typeof message !== "object" || message === null) + return "object expected"; + if (message.playersWinChip != null && message.hasOwnProperty("playersWinChip")) { + if (!$util.isObject(message.playersWinChip)) + return "playersWinChip: object expected"; + let key = Object.keys(message.playersWinChip); + for (let i = 0; i < key.length; ++i) { + if (!$util.key64Re.test(key[i])) + return "playersWinChip: integer|Long key{k:int64} expected"; + if (!$util.isInteger(message.playersWinChip[key[i]])) + return "playersWinChip: integer{k:int64} expected"; + } + } + return null; + }; + + /** + * Creates a ResCalcWinnerChip message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof api.ResCalcWinnerChip + * @static + * @param {Object.} object Plain object + * @returns {api.ResCalcWinnerChip} ResCalcWinnerChip + */ + ResCalcWinnerChip.fromObject = function fromObject(object) { + if (object instanceof $root.api.ResCalcWinnerChip) + return object; + let message = new $root.api.ResCalcWinnerChip(); + if (object.playersWinChip) { + if (typeof object.playersWinChip !== "object") + throw TypeError(".api.ResCalcWinnerChip.playersWinChip: object expected"); + message.playersWinChip = {}; + for (let keys = Object.keys(object.playersWinChip), i = 0; i < keys.length; ++i) + message.playersWinChip[keys[i]] = object.playersWinChip[keys[i]] | 0; + } + return message; + }; + + /** + * Creates a plain object from a ResCalcWinnerChip message. Also converts values to other types if specified. + * @function toObject + * @memberof api.ResCalcWinnerChip + * @static + * @param {api.ResCalcWinnerChip} message ResCalcWinnerChip + * @param {$protobuf.IConversionOptions} [options] Conversion options + * @returns {Object.} Plain object + */ + ResCalcWinnerChip.toObject = function toObject(message, options) { + if (!options) + options = {}; + let object = {}; + if (options.objects || options.defaults) + object.playersWinChip = {}; + let keys2; + if (message.playersWinChip && (keys2 = Object.keys(message.playersWinChip)).length) { + object.playersWinChip = {}; + for (let j = 0; j < keys2.length; ++j) + object.playersWinChip[keys2[j]] = message.playersWinChip[keys2[j]]; + } + return object; + }; + + /** + * Converts this ResCalcWinnerChip to JSON. + * @function toJSON + * @memberof api.ResCalcWinnerChip + * @instance + * @returns {Object.} JSON object + */ + ResCalcWinnerChip.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * Gets the default type url for ResCalcWinnerChip + * @function getTypeUrl + * @memberof api.ResCalcWinnerChip + * @static + * @param {string} [typeUrlPrefix] your custom typeUrlPrefix(default "type.googleapis.com") + * @returns {string} The default type url + */ + ResCalcWinnerChip.getTypeUrl = function getTypeUrl(typeUrlPrefix) { + if (typeUrlPrefix === undefined) { + typeUrlPrefix = "type.googleapis.com"; + } + return typeUrlPrefix + "/api.ResCalcWinnerChip"; + }; + + return ResCalcWinnerChip; + })(); + return api; })(); diff --git a/internal/game/player.go b/internal/game/player.go index d9eaa50..ef764f5 100644 --- a/internal/game/player.go +++ b/internal/game/player.go @@ -14,7 +14,7 @@ type Player struct { Cards [2]*Card // 手牌 Chip int32 // 玩家筹码 - RoundChip int32 // 该回合已下注筹码 + TotalBetChip int32 // 本次游戏已下注筹码 Status int32 // 状态: 1待准备开始,2已准备开始,3等待其他玩家动作,4第一回合小盲注跟注, [5待大盲注,5待小盲注,] 6待跟注,7已弃牌 LastStatus int32 // 变化前一个状态 BetOpts []int32 // status=[4,6]时下注可操作按钮: 1跟注,2加注(-[0]+),3All-In,4弃牌,5过牌 @@ -36,7 +36,15 @@ func (p *Player) Init() { // RoundInit 下一回合初始化 func (p *Player) RoundInit() { - p.RoundChip = 0 + p.SetStatus(1) + p.BetMin = 0 + p.BetMax = 0 + p.BetOpts = make([]int32, 0) + p.TotalBetChip = 0 + p.Hand = nil + p.Cards[0] = nil + p.Cards[1] = nil + p.RoundInit() } func (p *Player) SetStatus(status int32) { diff --git a/internal/game/table.go b/internal/game/table.go index ba35641..edcbba1 100644 --- a/internal/game/table.go +++ b/internal/game/table.go @@ -38,16 +38,29 @@ type Table struct { // TODO game logs7 } -// Init 初始化桌面 -func (t *Table) Init() { - t.PlayersLock = &sync.Mutex{} - t.ChipLock = &sync.Mutex{} +// InitGameAndPlayerStatus 初始化桌面 +func (t *Table) InitGameAndPlayerStatus() { + if t.PlayersLock == nil { + t.PlayersLock = &sync.Mutex{} + } + if t.ChipLock == nil { + t.ChipLock = &sync.Mutex{} + } t.PublicCards = [5]*Card{nil, nil, nil, nil, nil} - t.Dealer = NewDealer() - t.RoundTimes = 0 + if t.Dealer == nil { + t.Dealer = NewDealer() + } else { + t.Dealer.Init() + } t.Stage = 1 t.BigBlindPos = 0 t.SmallBlindPos = 0 + + for _, p := range t.Players { + if p != nil { + p.RoundInit() + } + } } func (t *Table) PlayerCount() int32 { @@ -142,15 +155,22 @@ func (t *Table) BuildResGameFullStatus() *api.ResGameFullStatus { continue } player := &api.TablePlayer{ - Robot: false, - Id: p.Id, - Username: p.Username, - Avatar: p.Avatar, - Chip: p.Chip, - Status: p.Status, - LastStatus: p.LastStatus, - Master: t.MasterId == p.Id, - HandCard: make([]*api.Card, 2), + Robot: false, + Id: p.Id, + Username: p.Username, + Avatar: p.Avatar, + Chip: p.Chip, + Status: p.Status, + LastStatus: p.LastStatus, + Master: t.MasterId == p.Id, + RoundBetTimes: p.RoundBetTimes, + TotalBetChip: p.TotalBetChip, + HandCard: make([]*api.Card, 2), + BetRole: &api.BetRole{ + BetMin: p.BetMin, + BetMax: p.BetMax, + BetOpts: p.BetOpts, + }, } // 玩家手牌 for j, card := range p.Cards { @@ -162,8 +182,6 @@ func (t *Table) BuildResGameFullStatus() *api.ResGameFullStatus { } resGame.Players[i] = player } - // TODO 机器人 - return resGame } @@ -185,6 +203,7 @@ func (t *Table) NoticeGameFullStatus() { } } +// NoticeAllPlayer 发送消息到牌桌所有玩家 func (t *Table) NoticeAllPlayer(message proto.Message) { for _, player := range t.Players { if player != nil && player.ProtoWriter != nil { @@ -193,69 +212,13 @@ func (t *Table) NoticeAllPlayer(message proto.Message) { } } -// CurrentRoundEnd 当前回合结束 -func (t *Table) CurrentRoundEnd() error { - // TODO 游戏结束,开牌结算 - if t.RoundTimes >= 4 { - // 比牌 - t.Stage = 7 - var winners []*Player = nil - for _, p := range t.Players { - if p != nil { - continue - } - hand, err := AnalyzeMaxHand(p.Cards, t.PublicCards) - if err != nil { - return err - } - p.Hand = hand - if winners == nil { - winners = []*Player{p} - } else { - if p.Hand.point > winners[0].Hand.point { - winners[0] = p - } else if p.Hand.point == winners[0].Hand.point { - // 手牌相同 - winners = append(winners, p) - } - } - } - winnerCount := int32(len(winners)) - // TODO 所有玩家输赢消息 ResCalcWinnerChip - if winnerCount == 1 { - // 只有一个玩家获胜 - winner := winners[0] - winner.Chip += t.Chip - t.Chip = 0 - } else { - // 平分奖池 - once := t.Chip / winnerCount - lessPos := winners[0].PosIndex - lessNear := lessPos - t.SmallBlindPos - for _, p := range winners { - p.Chip += once - // 计算最靠近发牌者的赢家 - pNear := p.PosIndex - t.SmallBlindPos - if pNear*lessPos < 0 { // 一正一负, 正的近 - if pNear >= 0 { - lessPos = p.PosIndex - } - } else if lessNear > pNear { - lessPos = p.PosIndex - } - } - // 无法平分之小额筹码,顺时针靠近发牌者得 - less := t.Chip - once*winnerCount - if less > 0 { - t.Players[lessPos].Chip += less - } - t.Chip = 0 - } - - go func() { - // TODO 等前端展示3秒钟后,牌桌回到初始状态,剔除掉线玩家 - }() - return nil +// RoundOver 当前回合结束 +func (t *Table) RoundOver() error { + // 游戏结束,开牌结算 + if t.RoundTimes >= 4 || 1 == len(collect.Filter(t.Players, func(i int, p *Player) bool { + return p != nil && p.Status != 7 + })) { + return t.cardFightAndSettle() } // 开启下一回合, 重置一些状态 @@ -264,7 +227,7 @@ func (t *Table) CurrentRoundEnd() error { for _, p := range t.Players { if p != nil { p.RoundBetTimes = 0 - p.RoundChip = 0 + p.TotalBetChip = 0 p.BetMin = 0 p.BetMax = 0 p.BetOpts = []int32{} @@ -279,6 +242,7 @@ func (t *Table) CurrentRoundEnd() error { begin := t.Players[nextBegin] begin.SetStatus(6) begin.BetOpts = []int32{1, 2, 4, 5} + // 根据回合发公共牌 switch t.RoundTimes { case 2: // 发3张公共牌(翻牌) @@ -300,6 +264,87 @@ func (t *Table) CurrentRoundEnd() error { return nil } +// cardFightAndSettle 斗牌并结算 +func (t *Table) cardFightAndSettle() error { + var winners []*Player = nil + leftPlayers := collect.Filter(t.Players, func(i int, p *Player) bool { + return p != nil && p.Status != 7 + }) + + if t.RoundTimes < 4 && 1 < len(leftPlayers) { + return errors.New("未到最后一轮下注且由1一个以上玩家持有牌") + } + t.Stage = 7 + + if 1 == len(leftPlayers) { + // 还剩一个玩家未弃牌 + winners = leftPlayers + } else { + // 剩余玩家大于1: 比牌 + for _, p := range t.Players { + if p != nil { + continue + } + hand, err := AnalyzeMaxHand(p.Cards, t.PublicCards) + if err != nil { + return err + } + p.Hand = hand + if winners == nil { + winners = []*Player{p} + } else { + if p.Hand.point > winners[0].Hand.point { + winners[0] = p + } else if p.Hand.point == winners[0].Hand.point { + // 手牌相同 + winners = append(winners, p) + } + } + } + } + winnerCount := int32(len(winners)) + // TODO 所有玩家输赢消息 ResCalcWinnerChip + if winnerCount == 1 { + // 只有一个玩家获胜 + winner := winners[0] + winner.Chip += t.Chip + t.Chip = 0 + } else { + // 平分奖池 + once := t.Chip / winnerCount + lessPos := winners[0].PosIndex + lessNear := lessPos - t.SmallBlindPos + for _, p := range winners { + p.Chip += once + // 计算最靠近发牌者的赢家 + pNear := p.PosIndex - t.SmallBlindPos + if pNear*lessPos < 0 { // 一正一负, 正的近 + if pNear >= 0 { + lessPos = p.PosIndex + } + } else if lessNear > pNear { + lessPos = p.PosIndex + } + } + // 无法平分之小额筹码,顺时针靠近发牌者得 + less := t.Chip - once*winnerCount + if less > 0 { + t.Players[lessPos].Chip += less + } + t.Chip = 0 + } + + // TODO 通知输赢金额 + + // TODO 初始化牌桌及状态 + t.InitGameAndPlayerStatus(); + + go func() { + // TODO 等前端展示3秒钟后,牌桌回到初始状态,剔除掉线玩家 + }() + return nil +} + // DiscardAllPlayerWin 其他玩家弃牌,玩家赢 func (t *Table) DiscardAllPlayerWin(player *Player) { @@ -310,20 +355,20 @@ func (t *Table) DiscardAllPlayerWin(player *Player) { // //} -type Stage int - -func (s *Stage) String() string { - return stageNames[*s] -} - -// 游戏阶段名称 -var stageNames = []string{"Stage00WaitBegin", "Stage10Perflop", "Stage20Flop", "Stage30Turn", "Stage40River"} - -// 游戏阶段 -const ( - Stage00WaitBegin Stage = iota // 等待游戏开始 - Stage10Perflop Stage = iota // 下大小盲注,然后没人发2张底牌,大盲注后面第一个玩家跟注、加注或放弃,依次顺时针表态 - Stage20Flop Stage = iota // 发三张公牌,由小盲注开始顺时针表态 - Stage30Turn Stage = iota // 发第四张公共牌,由小盲注开始顺时针表态 - Stage40River Stage = iota // 发第五张牌,由小盲注开始顺时针表态,然后亮牌比大小 -) +//type Stage int +// +//func (s *Stage) String() string { +// return stageNames[*s] +//} +// +//// 游戏阶段名称 +//var stageNames = []string{"Stage00WaitBegin", "Stage10Perflop", "Stage20Flop", "Stage30Turn", "Stage40River"} +// +//// 游戏阶段 +//const ( +// Stage00WaitBegin Stage = iota // 等待游戏开始 +// Stage10Perflop Stage = iota // 下大小盲注,然后没人发2张底牌,大盲注后面第一个玩家跟注、加注或放弃,依次顺时针表态 +// Stage20Flop Stage = iota // 发三张公牌,由小盲注开始顺时针表态 +// Stage30Turn Stage = iota // 发第四张公共牌,由小盲注开始顺时针表态 +// Stage40River Stage = iota // 发第五张牌,由小盲注开始顺时针表态,然后亮牌比大小 +//) diff --git a/internal/server/wsroute.go b/internal/server/wsroute.go index d631a3d..61a2585 100644 --- a/internal/server/wsroute.go +++ b/internal/server/wsroute.go @@ -37,6 +37,8 @@ func init() { HandleNetPlayerMsg(&api.ReqCancelReady{}, service.HandleReqCancelReady) // 开始游戏 HandleNetPlayerMsg(&api.ReqGameStart{}, service.HandleReqGameStart) + // 筹码下注 + HandleNetPlayerMsg(&api.ReqBetting{}, service.HandleReqBetting) } func checkExistsTypeHandler(op int32, err error) { diff --git a/internal/service/table.go b/internal/service/table.go index 96430c3..2b45959 100644 --- a/internal/service/table.go +++ b/internal/service/table.go @@ -48,21 +48,22 @@ func HandleReqCreateTable(account *session.NetAccount, msg *api.ReqCreateTable) LimitInAmount: msg.BigBlind * 100, TexasType: msg.TexasType, } - table.Init() + table.InitGameAndPlayerStatus() // 房主 [0] // 扣除DB账户余额 account.DecrementBalance(table.LimitInAmount) owner := &game.Player{ - Id: account.Id, - Username: account.UserName, - Avatar: account.Avatar, - Status: 1, - LastStatus: 0, - Chip: table.LimitInAmount, - Cards: [2]*game.Card{}, - GameTable: table, - ProtoWriter: account.Client, + Id: account.Id, + Username: account.UserName, + Avatar: account.Avatar, + Status: 1, + LastStatus: 0, + Chip: table.LimitInAmount, + TotalBetChip: 0, + Cards: [2]*game.Card{}, + GameTable: table, + ProtoWriter: account.Client, } owner.Init() // 挂载 player 到 account 上 @@ -148,15 +149,16 @@ func HandleReqJoinTable(account *session.NetAccount, msg *api.ReqJoinTable) (pro } player := &game.Player{ - Id: account.Id, - Username: account.UserName, - Avatar: account.Avatar, - Status: 1, - LastStatus: 0, - Chip: 0, - Cards: [2]*game.Card{nil, nil}, - GameTable: table, - ProtoWriter: account.Client, + Id: account.Id, + Username: account.UserName, + Avatar: account.Avatar, + Status: 1, + LastStatus: 0, + Chip: 0, + TotalBetChip: 0, + Cards: [2]*game.Card{nil, nil}, + GameTable: table, + ProtoWriter: account.Client, } player.Init() index, err := table.JoinPlayer(player) @@ -360,8 +362,11 @@ func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Messa // 扣除大小盲注金额 table.Players[table.SmallBlindPos].Chip -= table.SmallBlindChip + table.Players[table.SmallBlindPos].TotalBetChip += table.SmallBlindChip table.Players[table.BigBlindPos].Chip -= table.BigBlindChip + table.Players[table.BigBlindPos].TotalBetChip += table.BigBlindChip table.Chip += table.BigBlindChip + table.SmallBlindChip + // 回合下注次数 table.Players[table.BigBlindPos].RoundBetTimes++ // table.Players[table.SmallBlindPos].RoundBetTimes++ @@ -401,7 +406,7 @@ func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Messa optPos := table.NextPlayerPos(table.BigBlindPos) optPlayer := table.Players[optPos] optPlayer.SetStatus(4) - optPlayer.BetOpts = []int32{1, 2, 4} + optPlayer.BetOpts = []int32{2, 4} optPlayer.BetMax = table.BigBlindChip // 游戏类型处理最大下注额 switch table.TexasType { @@ -447,7 +452,7 @@ func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Messa return &api.ResSuccess{}, nil } -// HandleReqPlaceBet 下注 +// HandleReqBetting 下注 // 网易德州扑克:http://sports.163.com/special/poker_rule/?ivk_sa=1025883k // 天天德州: http://game.people.com.cn/n/2014/0220/c40130-24413078.html // wiki: https://zh.wikipedia.org/wiki/%E5%BE%B7%E5%B7%9E%E6%92%B2%E5%85%8B @@ -459,7 +464,7 @@ func HandleReqGameStart(player *game.Player, msg *api.ReqGameStart) (proto.Messa // 盖牌(fold),即舍弃并覆盖手中的牌,放弃已投入底池的筹码退出该局。 // 跟注(call)投入了与所有其他未盖牌的牌手等量的筹码。 // 全下(all-in),投入了尚余的全部筹码。 -func HandleReqPlaceBet(player *game.Player, msg *api.ReqPlaceBet) (proto.Message, error) { +func HandleReqBetting(player *game.Player, msg *api.ReqBetting) (proto.Message, error) { player.Lock.Lock() defer player.Lock.Unlock() player.GameTable.ChipLock.Lock() @@ -472,10 +477,13 @@ func HandleReqPlaceBet(player *game.Player, msg *api.ReqPlaceBet) (proto.Message return &api.ResFail{Msg: fmt.Sprintf("当前不可执行该操作#%d", msg.BetType)}, nil } + // 投注结束广播牌桌状态 + defer player.GameTable.NoticeGameFullStatus() + table := player.GameTable - var line1 string - var line2 string + var raise bool // 是否加注 + betNotice := &api.ResNoticePlayerLine{PlayerId: player.Id} switch msg.BetType { case 1: // 跟注 if msg.BetChip != player.BetMin { @@ -516,84 +524,90 @@ func HandleReqPlaceBet(player *game.Player, msg *api.ReqPlaceBet) (proto.Message case 4: // 弃牌 player.SetStatus(7) - line1 = "弃牌" + betNotice.Line1 = "弃牌" // 剩余牌手数为1则结束 leftPlayers := collect.Filter(player.GameTable.Players, func(i int, p *game.Player) bool { return p != nil && p.Status != 7 }) if len(leftPlayers) == 1 { - playerWin(leftPlayers[0]) + err := table.RoundOver() + if err != nil { + return &api.ResFail{Code: 500, Msg: err.Error()}, nil + } return &api.ResSuccess{}, nil } case 5: // 过牌 player.RoundBetTimes++ - line1 = "过牌" + betNotice.Line1 = "过牌" default: return &api.ResFail{Msg: fmt.Sprintf("未知操作#%d", msg.BetType)}, nil } + player.TotalBetChip += msg.BetChip // 通知下注结果 - if line1 != "" { - notice := &api.ResNoticePlayerLine{PlayerId: player.Id, Line1: line1, Line2: line2} - player.GameTable.NoticeAllPlayer(notice) + if betNotice.Line1 != "" { + player.GameTable.NoticeAllPlayer(betNotice) } player.SetStatus(3) // 下注完成:若还有玩家未下注、加注,下一玩家继续下注;若该轮下注完成,发牌开启下一轮下注 // 下一位玩家:跟注 - var nextPlayer *game.Player = player - for { - nextPlayerPos := table.NextPlayerPos(nextPlayer.PosIndex) - nextPlayer = table.Players[nextPlayerPos] - if nextPlayer.Id == player.Id { - // TODO 开启下一轮 - break - } - if nextPlayer.Status == 7 { // 已弃牌.. - continue + nextPlayerPos := table.NextHoldingCardPlayerPos(player.PosIndex) + nextPlayer := table.Players[nextPlayerPos] + if nextPlayer.Id == player.Id { + // 开启下一轮 + err := table.RoundOver() + if err != nil { + return &api.ResFail{Code: 500, Msg: err.Error()}, nil } - if !raise { - // 当前玩家未加注, 判断是否结束本轮下注 - if nextPlayer.RoundBetTimes > 0 { - // TODO 开启下一轮 + return &api.ResSuccess{}, nil + } + + if !raise { + // 当前玩家未加注, 判断是否结束本轮下注 + if nextPlayer.RoundBetTimes > 0 { + // 开启下一轮 + err := table.RoundOver() + if err != nil { + return &api.ResFail{Code: 500, Msg: err.Error()}, nil } } - // 判断下一玩家是否需要再下注: 下一玩家是否已下注,当前玩家是否跟注, - nextPlayer.SetStatus(6) - nextPlayer.BetMin = msg.BetChip - nextPlayer.BetOpts = []int32{1, 4} - - // 下一玩家需跟注 - // 如果当前玩家是小盲注第一次下注 - if player.RoundBetTimes == 1 && table.SmallBlindPos == player.PosIndex { - nextPlayer.BetMin += table.SmallBlindChip - } - // 如果下一玩家是大盲注第一次下注 - if nextPlayer.RoundBetTimes == 0 && table.BigBlindPos == nextPlayerPos { - nextPlayer.BetMin -= table.BigBlindChip - } - // 游戏类型处理最大下注额 - switch table.TexasType { - case 2: // 底池限注 + } + // 判断下一玩家是否需要再下注: 下一玩家是否已下注,当前玩家是否跟注, + nextPlayer.SetStatus(6) + nextPlayer.BetMin = msg.BetChip + nextPlayer.BetOpts = []int32{1, 4} + + // 下一玩家需跟注 + // 如果当前玩家是小盲注第一次下注 + if player.RoundBetTimes == 1 && table.SmallBlindPos == player.PosIndex { + nextPlayer.BetMin += table.SmallBlindChip + } + // 如果下一玩家是大盲注第一次下注 + if nextPlayer.RoundBetTimes == 0 && table.BigBlindPos == nextPlayerPos { + nextPlayer.BetMin -= table.BigBlindChip + } + // 游戏类型处理最大下注额 + switch table.TexasType { + case 2: // 底池限注 + nextPlayer.BetOpts = append(nextPlayer.BetOpts, 3) + nextPlayer.BetMax = table.Chip + table.LastPosBetChip*2 + case 3: // 无限注 + nextPlayer.BetOpts = append(nextPlayer.BetOpts, 2, 3) // 可 all in + nextPlayer.BetMax = -1 + case 1: // 限注 + fallthrough + default: + // 限注比赛只允许一次下注与三次加注 + if table.RoundRaiseTimes < 3 { nextPlayer.BetOpts = append(nextPlayer.BetOpts, 3) - nextPlayer.BetMax = table.Chip + table.LastPosBetChip*2 - case 3: // 无限注 - nextPlayer.BetOpts = append(nextPlayer.BetOpts, 2, 3) // 可 all in - nextPlayer.BetMax = -1 - case 1: // 限注 - fallthrough - default: - // 限注比赛只允许一次下注与三次加注 - if table.RoundRaiseTimes < 3 { - nextPlayer.BetOpts = append(nextPlayer.BetOpts, 3) - // 第1,2回合跟注加注需和大盲注相同, 3,4回合两倍 - nextPlayer.BetMax = table.BigBlindChip * ((table.RoundTimes+1)/2 + 1) - } else { - // 只能跟注 - nextPlayer.BetMax = msg.BetChip - } + // 第1,2回合跟注加注需和大盲注相同, 3,4回合两倍 + nextPlayer.BetMax = table.BigBlindChip * ((table.RoundTimes+1)/2 + 1) + } else { + // 只能跟注 + nextPlayer.BetMax = msg.BetChip } } @@ -603,8 +617,3 @@ func HandleReqPlaceBet(player *game.Player, msg *api.ReqPlaceBet) (proto.Message return &api.ResSuccess{}, nil } - -// playerWin 玩家获胜,结算牌局 -func playerWin(player *game.Player) { - -} diff --git a/tool/collect/collect.go b/tool/collect/collect.go index cee3547..3684ef5 100644 --- a/tool/collect/collect.go +++ b/tool/collect/collect.go @@ -20,7 +20,7 @@ func Count[T any](slice []T, isCount func(int, T) bool) int { } func Filter[T any](slice []T, predicate func(int, T) bool) []T { - res := []T{} + var res []T for i, item := range slice { if predicate(i, item) { res = append(res, item)