NON-PRODUCTION
Bandar QQ — tài liệu ghép client
Betting kiểu Baccarat nhưng lá là domino (bộ 28). Red vs Blue, mỗi bên 2 lá. Điểm = tổng pip mod 10. Có tip dealer. Envelope game_event + proto bandarqq_event.
1. Tổng quan
| Mục | Giá trị |
|---|---|
| Connect | GET /ws?access_token=<JWT> trên domain game |
| Lobby | internal/proto/game-event · package game_event |
| Gameplay | package bandarqq_event trong data_send.data |
| Card id | head * 7 + tail (head, tail ∈ 0…6) |
| Tip | C→S tip_dealer TagTipDealer=2 → user_id, amount, user_money |
| 1 user | Một connection. Duplicate → lobby 102 |
Side enum
| Giá trị | Cửa |
|---|---|
| 0 Red | Đỏ thắng điểm |
| 1 Blue | Xanh thắng điểm |
| 2 Draw | Hòa điểm |
| 3 QiuQiu | Cả hai = 9 |
| 4 Twins | Cả 4 lá đều double (đầu=đuôi) |
| 5 QiuRed / 6 QiuBlue | Bên đó 9 điểm |
| 7 TwinRed / 8 TwinBlue | Bên đó 2 lá double |
State: Pending · Countdown · DealTime · ShowdownTime · BetTime · PreShowdownTime. room_state.tip_dealer_amount = số chip mỗi lần tip.
2. Demo Red vs Blue
3
3
2
0
DRAW
3
1
3
4
Red 3-3 + 2-0 = 8; Blue 3-1 + 3-4 = 11 → 1. Red thắng. Twin: lá 3-3.
3. WS envelope (đầy đủ)
Frame binary protobuf. Handshake: 0 closed · 1 other device playing · 2 too many conn · 4 token expired · 5 banned.
GET /ws?access_token=<JWT> // domain game bandarqq
game_event.Request.data_send { room_id: 3 data: <bytes bandarqq_event.Request> }
game_event.Response.game_message { room_id: 3 data: <bytes bandarqq_event.Response> }
Ngoài data: user_joined / user_left / start_countdown / start_game / reset_game / auto_leave.
4. Lobby C→S / S→C
| C→S | Field |
|---|---|
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 |
invite | room_id, password, user_id |
free_users_list | bet |
send_chat_message | room_id, message, to[], is_private_chat |
data_send | bytes game hoặc auto_leave |
| S→C | Field |
|---|---|
room_config / room_list | sảnh / bàn |
game_message | payload bàn |
error | code + tag |
chat_message | chat |
invite / someone_invited_you | mời |
5. Gameplay proto bandarqq_event
C→S Request (oneof)
| Message | Field | Ghi chú |
|---|---|---|
bet TagBet=1 | side, bet_amount, count[{bet,count}] | Một cửa |
multiple_bet | bets[] | Nhiều cửa |
tip_dealer Tag=2 | rỗng | Trừ tip_dealer_amount |
cheat | red_cards[], blue_cards[] | Non-prod |
Request { bet { side: Red bet_amount: 1000 count { bet: 1000 count: 1 } } }
Request { tip_dealer {} }
S→C Response (oneof)
| Message | Field |
|---|---|
room_state | state, timers, bet, players[], red_cards[], blue_cards[], red_score, blue_score, side_list[], winning_sides[], logs[{red_score,blue_score,red_twin,blue_twin,red_qiu,blue_qiu,six_twins}], bets[], tip_dealer_amount, max_bet, max_bet_by_vip |
start_bet | delay_millis |
bet / multiple_bet | user_id, side, bet_amount, side_total_bet, seat, player_total_bet, count[] |
tip_dealer | user_id, amount, user_money |
deal | rỗng |
pre_showdown | result[{user_id,amount,user_money}], bet_sides[] |
finish | red_cards[], blue_cards[], win_sides[], red_score, blue_score, sides_win_amount[], players_sides_win_amount[] |
error | code + tag (1=bet, 2=tip) |
Response { tip_dealer { user_id: 1001 amount: 1000 user_money: 499000 } }
Response { finish {
red_cards: [24, 14]
blue_cards: [22, 25]
win_sides: [Red]
red_score: 8
blue_score: 1
sides_win_amount { side: Red win_amount: 50000 }
players_sides_win_amount {
user_id: 1001 total_amount: 1000 user_money: 501000 vip: 1
sides_win_amount { side: Red win_amount: 1000 }
}
} }
room_state — restore
| Field | Client |
|---|---|
state + timers | Khóa cược ngoài BetTime |
players[] | user_id, name, chip, avatar, seat, state, bet_sides[], vip, level |
red_cards[], blue_cards[], red_score, blue_score | 4 lá nếu đang showdown |
side_list[], winning_sides[], bets[] | Paytable (Red/Blue 1:1, Draw 8, QiuQiu 90, Twins 300…) |
logs[] | red/blue score + twin/qiu/six_twins flags |
tip_dealer_amount, max_bet, max_bet_by_vip | Giá tip + trần cược |
Response { bet {
user_id: 1001 side: Red bet_amount: 1000
side_total_bet: 15000 seat: 1 player_total_bet: 1000
} }
Response { pre_showdown {
result { user_id: 1001 amount: -1000 user_money: 498000 }
bet_sides { side: Red bet_amount: 15000 }
} }
Decode lá: id 24 → head=3 tail=3 (3×7+3). id 14 → 2×7+0. Điểm = (pip1+pip2) mod 10. Luôn tin red_score/blue_score server. Twin = cả hai đầu lá bằng nhau.
Lobby payload mẫu
Request { room_config {} }
Request { join_any_room { bet: 1000 max_players: 0 } }
Request { data_send { room_id: 3 data: <bandarqq_event.Request tip_dealer> } }
Tip Tag=2 có thể gửi ngoài BetTime (tùy server ActionNotAllowed). amount trên ResponseTipDealer = số đã trừ, không phải số dư.
6. Luồng ghép
Connect /ws
room_config
join_room
start_bet
bet / tip_dealer
deal → finish
- Connect JWT. Close 1/2/4/5 → dừng.
- Join. Restore từ room_state (kể cả 4 lá nếu đang showdown).
- start_bet → cược Red/Blue/side. Tip bất kỳ lúc đủ chip (Tag=2).
- deal khóa cược. finish lật 2 cặp domino, highlight win_sides, cập nhật money.
7. Error codes
| Handshake | 0 closed · 1 other device playing · 2 too many conn · 4 token expired · 5 banned |
|---|
| Lobby | 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 | 1 NotBetTime · 2 InvalidBet · 3 NotEnoughChip · 4 SideBetNotAllowed · 5 UserNotFound · 6 ActionNotAllowed · tag 1=bet · tag 2=tip |
|---|
Khi nào chip đổi
| Event | Chip |
|---|---|
| Tap bet | Optimistic trừ; confirm ở pre_showdown |
tip_dealer | −amount ngay, echo user_money |
finish | +total_amount; tin user_money |
8. Checklist client
- Binary protobuf, domain game, một socket / user.
- Bàn = bytes
bandarqq_event.Requesttrong data_send. - Card id = head×7+tail. Vẽ 2 pip, không phải bài tây.
- Nút tip enable khi user_money ≥ tip_dealer_amount.
- Money: echo tip + pre_showdown + finish. Cheat chỉ non-prod.