NON-PRODUCTION

Neko Megaways — tài liệu ghép client

Slot Megaways 6×5 + top reel. Mallet tích lũy, Mallet Wish, jackpot, buy bonus. Client nói HTTP JSON với server game. Trang này chỉ được serve khi ENVIRONMENT != production.

1. Tổng quan

MụcGiá trị
Grid6 cột × 5 hàng + top reel 4 ô (cột 1–4). reels có 7 phần tử: 6 cột chính rồi top reel
Cell packedsymbol | mallet | border trong 1 int — client phải unpack trước khi vẽ
PayMegaways tumble. Wild (10) thay thế paying symbol. Scatter (11) trigger feature
MalletBit mallet trên ô. Đủ max_mallets → vào Mallet Wish
JackpotCredit ngay (kể cả giữa FS). Line win FS vào pot
Buy bonusGiá = free_spin_price × bet. Board planted, không credit WIN của board đó
Base path/api/v1
Session in-memory. Bắt buộc GET /api/v1/gameplay trước khi spin. Reconnect thì đọc lại state từ /gameplay (mini_game_type, FS, mallet).

2. Luồng ghép

  1. Vào game → GET /gameplay + GET /jackpot. Render board preview, bet, paytable, mallet meter, FS/wish nếu đang dở.
  2. Base: POST /spins {"bet":...}. Play tuần tự win_result[].
  3. bonus_mini_game_type = 2 (Mallet Wish) → khóa spin, lặp POST /mallet-wish tới is_stopped / is_win rồi vào FS.
  4. FS: is_free_spin, không trừ bet. Line win cộng pot; jackpot credit ngay qua total_jackpot_win_amount.
  5. Buy → POST /buy-bonus (cấm khi đang FS/wish). Animate board planted rồi vào FS; đừng cộng WIN của board buy.
  6. Luôn lấy số dư từ user_money của response vừa nhận.

3. Auth & envelope

Authorization: Bearer <access_token>
Content-Type: application/json

Mọi API dưới /api/v1 cần JWT. Trang docs không cần token. HTTP 200 + code = 0 là thành công; payload nằm trong msg.

{ "code": 0, "msg": { ... } }
codeÝ nghĩa
0OK
-1Unknown / thiếu JWT / token invalid (tùy HTTP status)
-2Invalid input (body JSON sai)
69Wrong game state — chưa /gameplay, đang wish/FS mà đổi bet, bet không hợp lệ
1000Popup error (message i18n)

4. Grid, packed cell & symbol

Mỗi ô là int packed: bit 0–4 symbol, bit 5 mallet, bit 6–7 border (0 none · 1 silver · 2 gold).

symbol = packed & 31
is_mallet = (packed & 32) != 0
border   = (packed >> 6) & 3     // 0 none, 1 silver, 2 gold
// ví dụ 42 = Wild(10) + mallet(32)

Top reel (4 ô, nằm trên cột 1–4). Ô xanh = wild, vàng = scatter, xanh dương = mallet.

8
10
9
7
0
1
5
6
2
3
4
10
42
7
8
9
11
0
1
10
5
11
6
37
2
3
4
8
9
0
12
1
7
5
idSymbolidSymbol
0–4A / K / Q / J / 108Sushi
5Drum9SushiRoll
6Lantern10Wild
7PaperFan11 / 12Scatter / Multiplier

mini_game_type: 0 base · 1 free spin · 2 mallet wish. Dùng pay_table từ /gameplay, đừng hardcode.

5. GET /api/v1/gameplay

Gọi 1 lần khi vào game. Thiếu bước này thì spin/buy/wish trả code 69.

GET /api/v1/gameplay
FieldTypeClient dùng để
user_moneyint64Chip hiện tại
bet / bets / show_betsint64 / []Bet server; chỉ gửi giá trị trong bets
pay_tablefloat[][]Bảng trả thưởng
is_free_spin / free_spins / max_free_spins / free_spin_potRestore FS UI
free_spin_multiplierint64Hệ số đang bank trong FS
init_reelsint[][]Board preview (packed). 7 cột, cột cuối = top reel 4 ô
mini_game_typeint0 base · 1 FS · 2 wish — restore đúng màn
total_malletsint[]Số mallet theo từng mức show_bets
max_malletsintMeter đầy thì vào wish
mallet_wish_free_spins / mallet_wish_win_ratesint[]Bảng FS / tỉ lệ thắng từng bậc wish
mallet_wish_current_levelintBậc đang đứng nếu đang wish
free_spin_priceint64Hệ số giá buy. Giá thật = field này × bet
{
  "code": 0,
  "msg": {
    "user_money": 500000, "bet": 1000, "bets": [200,1000,2000,10000], "show_bets": [200,1000,2000,10000],
    "pay_table": [[10,25,50],[5,15,30],[3,10,20],[2,8,15],[1.5,6,12],[1,4,10],[0.8,3,8],[0.5,2,5],[0.4,1.5,4],[0.3,1,3]],
    "is_free_spin": false, "free_spins": 0, "max_free_spins": 0, "free_spin_pot": 0, "free_spin_multiplier": 1,
    "init_reels": [[0,1,2,3,4],[5,6,7,8,9],[0,10,1,2,3],[11,4,5,6,7],[8,9,0,1,2],[3,4,5,6,7],[8,9,10,11]],
    "mini_game_type": 0, "total_mallets": [2,4,1,0], "max_mallets": 8,
    "mallet_wish_free_spins": [8,10,12,15], "mallet_wish_win_rates": [80,60,40,20],
    "mallet_wish_current_level": 0, "free_spin_price": 100
  }
}

6. GET /api/v1/jackpot

GET /api/v1/jackpot
FieldÝ nghĩa
betMức cược (show bet)
amountPool jackpot hiện tại của mức đó
{ "code": 0, "msg": [{ "bet": 200, "amount": 480000 }, { "bet": 1000, "amount": 2400000 }] }

7. POST /api/v1/spins

POST /api/v1/spins
{ "bet": 1000 }

SpinResult

FieldÝ nghĩa
bet / priceBet server; 0 với spin thường, giá đã trừ nếu từ buy
user_money / win_amountChip sau giao dịch; win (FS giữa chừng = win spin, chưa credit chip; FS xong = cả pot)
mini_game_typeState sau spin
is_free_spin / free_spins / free_spin_potFS flags. Source of truth số lượt = free_spins
is_finish_free_spinCredit pot vào user_money
is_bonus_free_spin / number_of_bonus_free_spinsPopup +N FS
bonus_mini_game_typeFeature vừa mở: 1 FS · 2 wish
free_spin_init_multiplier / multiplierHệ số khởi tạo FS / hệ số spin
win_resultChuỗi tumble, play tuần tự
total_jackpot_win_amount / jackpot_amountJP đã credit ngay; pool còn lại

WinResult / WinLine

FieldÝ nghĩa
lines[]symbol, positions[col]=[row…], win_amount, line_size, number_of_lines
reels / positionsBoard packed trước xóa ô thắng; mọi ô thắng bước này
multiplier / bonus_multiplier / mega_waysHệ số / ways
total_bonus_mallets / total_malletsMallet nhặt bước này / tổng meter sau bước
is_jackpot / jackpot_win_amountJP của bước tumble (credit ngay, không vào pot)
{
  "code": 0,
  "msg": {
    "bet": 1000, "price": 0, "user_money": 499000, "win_amount": 8000,
    "mini_game_type": 0, "is_free_spin": false, "free_spins": 0, "free_spin_pot": 0,
    "is_finish_free_spin": false, "is_bonus_free_spin": false, "bonus_mini_game_type": 2,
    "number_of_bonus_free_spins": 0, "max_free_spins": 0, "free_spin_init_multiplier": 1, "multiplier": 1,
    "total_jackpot_win_amount": 0, "jackpot_amount": 2400000,
    "win_result": [{
      "lines": [{ "symbol": 8, "positions": [[0,1],[0],[],[],[],[],[]], "win_amount": 8000, "line_size": 8, "number_of_lines": 12 }],
      "reels": [[8,8,2,3,4],[8,6,7,8,9],[0,10,1,2,3],[4,4,5,6,7],[8,9,0,1,2],[3,4,5,6,7],[8,9,10,11]],
      "positions": [[0,1],[0],[],[],[],[],[]], "multiplier": 1, "bonus_multiplier": 0, "mega_ways": 3240,
      "total_bonus_mallets": 2, "total_mallets": 8, "is_jackpot": false, "jackpot_win_amount": 0
    }]
  }
}

8. POST /api/v1/buy-bonus

POST /api/v1/buy-bonus
{ "bet": 1000 }
{
  "code": 0,
  "msg": {
    "bet": 1000, "price": 100000, "user_money": 400000, "win_amount": 0,
    "mini_game_type": 1, "is_free_spin": false, "free_spins": 10, "free_spin_pot": 0,
    "is_finish_free_spin": false, "is_bonus_free_spin": true, "bonus_mini_game_type": 1,
    "number_of_bonus_free_spins": 10, "max_free_spins": 10, "free_spin_init_multiplier": 1, "multiplier": 1,
    "total_jackpot_win_amount": 0, "jackpot_amount": 2400000, "win_result": []
  }
}
Nút Buy chỉ enable khi mini_game_type = 0user_money >= free_spin_price * bet.

9. POST /api/v1/mallet-wish

POST /api/v1/mallet-wish
{ "request_stop": false }
FieldÝ nghĩa
request_stoptrue = thu FS ở bậc hiện tại; false = leo tiếp (có thể thua về bậc 0)
levelBậc sau bước này
number_of_bonus_free_spins / free_spin_init_multiplierFS / hệ số sẽ nhận khi dừng thắng
is_stopped / is_winHết ladder. Win → vào FS; lose (is_win=false) vẫn dừng, FS bậc 0

Lặp đến khi is_stopped (hoặc is_win ở đỉnh). Sau đó mini_game_type = FS — tiếp tục POST /spins.

{ "code": 0, "msg": { "bet": 1000, "level": 2, "number_of_bonus_free_spins": 12, "free_spin_init_multiplier": 1, "is_stopped": true, "is_win": true } }

10. Animation / tumble

  1. Unpack từng ô win_result[i].reels. Vẽ 6×5 + top reel.
  2. Highlight positions / từng lines. Ô mallet (bit 5) pulse meter.
  3. Xóa ô thắng, gravity theo cột, fill từ trên. Board mới = phần tử tiếp theo — đừng tự random.
  4. Nếu is_jackpot: fanfare + cộng chip ngay (không chờ hết FS).
  5. FS: cộng line win vào counter pot; chỉ credit chip khi is_finish_free_spin.

11. Cheat (chỉ non-prod / cheater)

{ "bet": 1000, "reels": [[8,8,2,3,4],[8,6,7,8,9],[0,10,1,2,3],[11,11,11,6,7],[8,9,0,1,2],[3,4,5,6,7],[8,9,10,11]] }

7 cột packed. Production bỏ qua reels, luôn random.

12. Error & tiền

Tình huốngHành vi client
HTTP 401Token hết hạn — relogin
code 69GET /gameplay lại, sync state, đừng spam spin
code 1000Popup msg (string i18n)
code -1 khi spin/buyHết tiền hoặc lỗi nội bộ — refresh qua /gameplay
Spin khi user đang room PvP khácHTTP 400 body "blocked"
EventChip
Base spin−bet ngay; +win cùng response; +JP ngay
Buy bonus−price ngay; không +WIN board planted
FS giữa chừngKhông đổi chip (trừ JP). Tăng free_spin_pot
FS kết thúc+pot vào user_money

13. Checklist client