NON-PRODUCTION

Farm Yard — tài liệu ghép client

Slot cluster 7×7. Market / storage, 3 loại buy FS (golden crop, market day, storage surplus). Client nói HTTP JSON. Trang này chỉ được serve khi ENVIRONMENT != production.

1. Tổng quan

MụcGiá trị
Grid7 cột × 7 hàng · reels[col][row], row 0 = trên cùng
PayCluster 4-neighbor. Hệ số theo pay_table từ server
SpecialRush → wild; Surge → 3×3 cùng symbol; Slash → xóa hàng+cột (không tính tiền)
free_spin_type0 normal · 1 golden_crop · 2 market_day · 3 storage_surplus
Trigger FS≥4 scatter → Golden Crop (8/10/12). Super+4 SC → Market Day (10). Super+5 SC → Storage Surplus (12)
Jackpot≥5 Super Scatter. Credit ngay, kể cả giữa FS
BuyChỉ mở FS. Mỗi lượt FS vẫn POST /spins
InitiatedRequiredBắt buộc GET /gameplay trước mọi spin/buy — thiếu = code 69
Base path/api/v1
Middleware InitiatedRequired gắn trên /spins và 3 route buy. Vào game mà spin ngay → code 69. Reconnect: gọi lại /gameplay.

2. Luồng ghép

  1. Mở game → GET /gameplay + GET /jackpot. Render board, bet, market/storage, sticky multipliers nếu đang FS.
  2. Base: POST /spins. Play tuần tự win_result[] (cluster → tumble → rush/surge/slash).
  3. Nếu is_bonus_free_spin: popup +N, chuyển UI theo bonus_free_spin_type.
  4. FS: không trừ bet, line win vào pot. Market/storage cập nhật từ field cùng tên. JP credit ngay.
  5. Buy một trong 3 endpoint → mở FS tương ứng; sau đó mỗi lượt vẫn POST /spins.
  6. is_finish_free_spin → credit pot, về base. Luôn tin user_money trên response.

3. Auth & envelope

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

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

{ "code": 0, "msg": { ... } }
codeÝ nghĩa
0OK
-1Unknown / JWT invalid (HTTP 401 nếu thiếu token)
-2Invalid input
69Wrong state — chưa GET /gameplay, đang FS đổi bet, bet sai
1000Popup i18n (buy không hợp lệ, đang FS)

4. Grid & symbol

Ô vàng = cluster thắng. Ô xanh = rush. Ô xanh lá = slash.

0
3
3
1
2
4
5
1
3
3
3
9
6
7
2
0
3
8
1
2
4
5
6
7
11
0
1
2
3
4
12
5
6
7
0
1
2
8
0
1
2
3
4
5
6
7
0
1
2
idSymbolidSymbol
0–7Chicken … Potato (paying)12Scatter
8Wild13SuperScatter
9Rush (biến 4–11 ô → wild)14Multiplier (chỉ FS)
10Surge (ô + 8 ô quanh → 1 symbol)15Market (chỉ FS)
11Slash (xóa hàng + cột, không tính tiền)16Storage (chỉ FS)

5. GET /api/v1/gameplay

Gọi 1 lần khi vào game — set session initiated. Thiếu bước này thì mọi spin/buy = code 69.

GET /api/v1/gameplay
FieldTypeClient dùng để
init_reelsint[7][7]Board preview idle
user_money / bet / bets / show_betsChip & mức bet hợp lệ
pay_tablefloat[][]Cluster pay
is_free_spin / free_spins / max_free_spins / free_spin_potRestore FS
free_spin_typeint0–3 — theme FS đang chạy
marketintHệ số market hiện tại (FS Market Day, init 2, max 10)
storageint64Tiền tích trong Storage Surplus
multipliersint[]Sticky hệ số theo symbol (FS)
golden_crop_price / market_day_price / storage_surplus_priceint64Hệ số giá buy. Giá thật = field × bet
{
  "code": 0,
  "msg": {
    "init_reels": [[0,1,2,3,4,5,6],[1,2,3,4,5,6,7],[2,3,4,5,6,7,0],[3,4,5,6,7,0,1],[4,5,6,7,0,1,2],[5,6,7,0,1,2,3],[6,7,0,1,2,3,4]],
    "user_money": 800000, "bet": 1000, "bets": [200,1000,2000,10000], "show_bets": [200,1000,2000,10000],
    "pay_table": [[10,25,50,100],[5,15,30,60],[3,10,20,40],[2,8,15,30],[1.5,6,12,25],[1,4,10,20],[0.8,3,8,15],[0.5,2,5,10]],
    "is_free_spin": false, "free_spins": 0, "max_free_spins": 0, "free_spin_pot": 0, "free_spin_type": 0,
    "market": 0, "storage": 0, "multipliers": [0,0,0,0,0,0,0,0],
    "golden_crop_price": 50, "market_day_price": 80, "storage_surplus_price": 120
  }
}

6. GET /api/v1/jackpot

GET /api/v1/jackpot
FieldÝ nghĩa
betMức cược
amountPool hiện tại
{ "code": 0, "msg": [{ "bet": 200, "amount": 120000 }, { "bet": 1000, "amount": 600000 }] }

7. POST /api/v1/spins

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

InitiatedRequired. Base trừ bet. FS không trừ, không đổi bet. reels chỉ cheat.

SpinResult

FieldÝ nghĩa
bet / price / user_money / win_amountBet; 0 spin thường; chip sau GD; win (FS giữa = spin, FS xong = pot)
is_free_spin / free_spins / free_spin_pot / max_free_spinsFS state
is_finish_free_spinCredit pot
is_bonus_free_spin / number_of_bonus_free_spinsPopup +N
bonus_free_spin_type / free_spin_typeLoại FS vừa mở / đang chạy (0–3)
win_resultTumble tuần tự
marketHệ số market sau spin
is_jackpot / jackpot_win_amount / jackpot_amountJP credit ngay

WinResult

FieldÝ nghĩa
linesCluster: symbol, positions, win_amount, line_size, multiplier, bonus_multiplier
reels / positionsBoard trước xóa; mọi ô thắng bước này
rush{rush_positions, positions} — ô rush / ô bị biến wild
surge[]{col,row,positions,symbol}
slash{slash_positions, positions} — tâm slash / ô bị xóa
multiplier[]{col,row,symbol,multiplier,total_multiplier}
market / market_count / market_multiplierMarket bước này
storage / multipliersStorage tích lũy; sticky theo symbol
{
  "code": 0,
  "msg": {
    "bet": 1000, "price": 0, "user_money": 799000, "win_amount": 4500,
    "is_free_spin": false, "free_spins": 8, "free_spin_pot": 0, "is_finish_free_spin": false,
    "is_bonus_free_spin": true, "bonus_free_spin_type": 1, "number_of_bonus_free_spins": 8,
    "free_spin_type": 1, "max_free_spins": 8, "market": 0,
    "is_jackpot": false, "jackpot_win_amount": 0, "jackpot_amount": 600000,
    "win_result": [{
      "lines": [{ "symbol": 3, "positions": [[],[1,2],[0,1,2],[1],[],[],[]], "win_amount": 4500, "line_size": 6, "multiplier": 4.5, "bonus_multiplier": 1 }],
      "reels": [[0,1,2,5,3,4,5],[1,3,3,4,5,6,7],[3,3,3,5,6,7,0],[3,3,5,6,7,0,1],[9,5,6,7,0,1,2],[5,6,7,0,1,2,3],[6,7,0,1,2,3,4]],
      "positions": [[],[1,2],[0,1,2],[1],[],[],[]], "win_amount": 4500, "total_win_amount": 4500,
      "rush": { "rush_positions": [[4],[0],[],[],[],[],[]], "positions": [[],[3],[3],[],[],[],[]] },
      "surge": [], "slash": { "slash_positions": [], "positions": [] }, "multiplier": [],
      "market": 0, "market_count": 0, "market_multiplier": 0, "storage": 0, "multipliers": [0,0,0,0,0,0,0,0]
    }]
  }
}

8. Buy FS — 3 endpoint

Cùng body {"bet": 1000}. Cấm khi đang FS → popup 1000. Buy chỉ mở FS (trừ giá, set free_spins); mỗi lượt FS vẫn POST /spins.

RouteGiáType mở
POST /buy-golden-cropgolden_crop_price × bet1 · ~8–12 FS
POST /buy-market-daymarket_day_price × bet2 · 10 FS, market init 2
POST /buy-storage-surplusstorage_surplus_price × bet3 · 12 FS
POST /api/v1/buy-golden-crop
{ "bet": 1000 }
{
  "code": 0,
  "msg": {
    "bet": 1000, "price": 0, "user_money": 750000, "win_amount": 0,
    "is_free_spin": false, "free_spins": 8, "free_spin_pot": 0, "is_finish_free_spin": false,
    "is_bonus_free_spin": true, "bonus_free_spin_type": 1, "number_of_bonus_free_spins": 8,
    "free_spin_type": 1, "max_free_spins": 8, "win_result": [],
    "market": 0, "is_jackpot": false, "jackpot_win_amount": 0, "jackpot_amount": 600000
  }
}
Chip đã trừ giá buy (xem user_money). price trên SpinResult buy có thể = 0 — tính giá từ hệ số × bet. Animate board (nếu có win_result) rồi vào FS, không cộng line win buy.

9. Tumble / special

  1. Vẽ reels. Highlight cluster lines / positions.
  2. Hết cluster: nếu có rush → biến rush.positions thành wild. Rồi surge, rồi slash (xóa, không cộng tiền).
  3. Gravity + fill. Board mới = win_result[i+1].reels.
  4. Market/storage/multipliers lấy từ field tumble + top-level, không tự tính.

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

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

Đủ 7×7. Production bỏ qua.

11. Error & tiền

Tình huốngHành vi client
HTTP 401Relogin
code 69GET /gameplay (initiated) rồi mới spin/buy
code 1000Popup i18n (buy khi đang FS)
code -1Hết tiền / lỗi — refresh /gameplay
HTTP 400 blockedUser đang room PvP khác
EventChip
Base spin−bet; +win; +JP ngay
Buy FS−(price×bet); không +WIN board mở
FS giữa chừngPot tăng; JP vẫn credit ngay
FS xong+pot vào user_money

12. Checklist client