NON-PRODUCTION
Baccarat — tài liệu ghép client
Cược Player / Banker / Tie + side bet. Envelope lobby game_event; payload bàn là bytes proto baccarat_event. Frame WS là binary, không JSON.
1. Tổng quan
| Mục | Giá trị |
|---|---|
| Connect | GET /ws?access_token=<JWT> trên domain game (không phải docs) |
| Lobby | internal/proto/game-event · package game_event |
| Gameplay | package baccarat_event. C→S bọc trong Request.data_send.data |
| Card id | rank * 4 + suit. Điểm cửa = tổng rank mod 10 (10/J/Q/K = 0, A = 1) |
| 1 user | Một connection. Duplicate login → lobby 102 |
Side enum
| Giá trị | Cửa |
|---|---|
| 0 Player | Nhà con, trái |
| 1 Banker | Nhà cái, phải (thường 0.95:1) |
| 2 Tie | Hòa |
| 3 PlayerPair | Player có đôi |
| 4 BankerPair | Banker có đôi |
| 5 Big | Khoảng cách điểm 5–6 |
| 6 Small | Khoảng cách điểm 4 |
| 7 PerfectPair | Đôi cùng chất |
| 8 EitherPair | Một trong hai cửa có đôi |
State enum
Pending=0 · Countdown=1 · DealTime=2 · ShowdownTime=3 · BetTime=4 · PreShowdownTime=5. Chỉ cược khi BetTime (sau start_bet).
2. Demo felt
PLAYER
0 · P8
0 · P8
TIE
2
2
BANKER
1 · B6
1 · B6
Viền vàng = cửa win (win_sides). Side bet (Pair/Big/Small) vẽ chip quanh felt; tỷ lệ lấy room_state.side_list.
3. WS envelope (đầy đủ)
Mọi frame là binary protobuf, không JSON. Handshake close code: 0 closed · 1 other device playing · 2 too many conn · 4 token expired · 5 banned.
GET /ws?access_token=<JWT> // domain game, ví dụ wss://baccarat.example/ws
Gameplay bytes: client marshal baccarat_event.Request → nhét vào lobby:
game_event.Request.data_send {
room_id: 42
data: <bytes baccarat_event.Request>
}
Server đẩy bàn qua:
game_event.Response.game_message {
room_id: 42
data: <bytes baccarat_event.Response>
}
Ngoài
data, game_message còn user_joined / user_left / start_countdown / start_game / reset_game / auto_leave.4. Lobby C→S / S→C
| C→S (game_event.Request) | Field |
|---|---|
room_config | rỗng → Response.room_config (room_types, play_now, best_choice, disable_*) |
get_room_list | bet |
create_room | bet, password, max_players, name |
join_room | room_id, password, is_viewer |
join_any_room | bet, max_players |
leave_room | room_id |
find_room | room_id → is_private |
invite | room_id, password, user_id |
free_users_list | bet |
send_chat_message | room_id, message, to[], is_private_chat |
data_send | room_id + data (bytes game) hoặc auto_leave |
| S→C (game_event.Response) | Field |
|---|---|
room_config / room_list | config sảnh, danh sách bàn |
game_message | payload bàn (bytes hoặc join/left/countdown) |
error | code + tag (xem mục 7) |
chat_message | room_id, user_id, message, name, vip |
invite / someone_invited_you | lời mời |
5. Gameplay proto baccarat_event
C→S Request (oneof) — gửi trong data_send.data
| Message | Field | Ghi chú |
|---|---|---|
bet TagBet=1 | side, bet_amount, count[{bet, count}] | Một cửa. count = số chip từng mệnh giá để animate |
multiple_bet | bets[] = repeated RequestBet | Nhiều cửa một lúc |
cheat | player_cards[], banker_cards[] | Non-prod / cheater |
// C→S bet Player 1000
Request { bet { side: Player bet_amount: 1000 count { bet: 1000 count: 1 } } }
// C→S multiple_bet
Request { multiple_bet { bets { side: Banker bet_amount: 500 } bets { side: Tie bet_amount: 100 } } }
S→C Response (oneof) — nhận từ game_message.data
| Message | Field chính |
|---|---|
room_state | state, count_down_millis, state_start_time, state_end_time, bet, players[], player_cards[], banker_cards[], player_score, banker_score, side_list[{side,multiplier,total_bet}], winning_sides[], logs[], bets[], is_registered_leave, max_bet, max_bet_by_vip |
start_bet | delay_millis — mở cửa cược |
bet / multiple_bet | echo: user_id, side, bet_amount, side_total_bet, seat, player_total_bet, count[] |
deal | rỗng — bắt đầu chia bài |
pre_showdown | result[{user_id, amount, user_money}], bet_sides[{side, bet_amount}] — sync chip sau khi trừ cược |
finish | player_cards[], banker_cards[], win_sides[], player_score, banker_score, sides_win_amount[{side,win_amount}], players_sides_win_amount[{user_id, sides_win_amount, avatar, name, total_amount, user_money}] |
error | code + tag (tag=1 RequestBet) |
// S→C start_bet
Response { start_bet { delay_millis: 20000 } }
// S→C finish (Banker thắng)
Response { finish {
player_cards: [4, 20]
banker_cards: [8, 16, 1]
win_sides: [Banker]
player_score: 8
banker_score: 6
sides_win_amount { side: Banker win_amount: 95000 }
players_sides_win_amount {
user_id: 1001 total_amount: 950 user_money: 500950
sides_win_amount { side: Banker win_amount: 950 }
}
} }
room_state — restore khi join giữa ván
| Field | Type | Client |
|---|---|---|
state | State | Khóa/mở chip. Chỉ BetTime mới gửi bet |
count_down_millis / state_end_time | int32 | Đồng hồ. Ưu tiên end_time unix |
players[] | PlayerInfo | user_id, name, chip, avatar, seat, disconnected, state (0 view / 1 play), bet_sides[], level, vip |
player_cards / banker_cards | int32[] | Có khi đang Deal/Showdown |
side_list | SideMultiplier[] | Paytable thật — multiplier + total_bet từng cửa |
bets | int64[] | Mệnh giá chip hợp lệ |
max_bet / max_bet_by_vip | int64 | Chặn cược / banner nạp |
logs | GameResult[] | Bead road: player_score, banker_score, win_sides |
// C→S echo bet (S→C)
Response { bet {
user_id: 1001 side: Player bet_amount: 1000
side_total_bet: 48000 seat: 2 player_total_bet: 1000
count { bet: 1000 count: 1 }
} }
// pre_showdown — trừ cược, ghi đè chip nếu UI lệch
Response { pre_showdown {
result { user_id: 1001 amount: -1000 user_money: 499000 }
bet_sides { side: Player bet_amount: 48000 }
} }
Chip UI lúc tap cược là optimistic. Khi
pre_showdown lệch thì ghi đè user_money. Win thật lấy từ finish.players_sides_win_amount.6. Luồng ghép
Connect /ws
room_config
join_room / join_any
start_bet
bet / multiple_bet
deal → pre_showdown → finish
- WS connect JWT. Nhận close 1/2/4/5 thì dừng, hiện lý do.
- Gửi
room_configrồijoin_any_room/create_room/join_room. - Nhận
room_state— restore felt, chip, cửa đang mở. - Khi
start_bet: đếmdelay_millis, enable chip. - Gửi
bet(Tag=1). Echo cập nhật total cửa. dealkhóa cược.pre_showdownsync money.finishlật bài, highlightwin_sides, cộng chip.
7. Error codes
| Handshake | Ý nghĩa |
|---|---|
| 0 / 1 / 2 / 4 / 5 | closed · other device playing · too many conn · token expired · banned |
| Lobby | Ý nghĩa |
|---|---|
| 100 | missing payload |
| 102 | duplicated login |
| 103 | room not found |
| 108 | bad password |
| 113 | room full |
| 114 | in other room |
| 115 | bet not found |
| 120 | not enough money |
| Gameplay (tag RequestBet=1) | Ý nghĩa |
|---|---|
| 1 NotBetTime | Không phải cửa cược |
| 2 InvalidBet | Mức cược không tồn tại |
| 3 NotEnoughChip | Không đủ chip |
| 4 SideBetNotAllowed | Cửa không hợp lệ |
| 5 UserNotFound | Không tìm thấy user |
| 6 ActionNotAllowed | Action không hợp lệ |
8. Checklist client
- Connect domain game, binary protobuf, một user một socket.
- Mọi action bàn đi qua
data_send.data= bytesbaccarat_event.Request. - Cược chỉ khi BetTime; tin
side_list/betstừ room_state. - Animate chip theo
count[]; money cuối từ pre_showdown + finish. - Card id = rank×4+suit. Highlight
win_sides. - Cheat chỉ non-prod.