@adiakys/feeling-lucky 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +73 -5
- package/dist/config/types.d.ts +11 -0
- package/dist/{de-Cp-ILcpM.js → de-CmzpGbNK.js} +19 -3
- package/dist/developer/panel.d.ts +2 -0
- package/dist/developer/settings.d.ts +2 -0
- package/dist/engine/dealer.d.ts +21 -0
- package/dist/{es-DHZIstf4.js → es-k_kS6Fn2.js} +19 -3
- package/dist/feeling-lucky.iife.js +417 -249
- package/dist/feeling-lucky.js +17 -39
- package/dist/{fr-BPFoerSF.js → fr-GuCZB1l4.js} +19 -3
- package/dist/games/blackjack/blackjack.d.ts +1 -0
- package/dist/games/cards/dealer.d.ts +9 -0
- package/dist/games/cards/table.d.ts +7 -1
- package/dist/games/holdem/holdem.d.ts +2 -0
- package/dist/{i18n-CihzHMU5.js → i18n-Cid8bj2R.js} +23 -7
- package/dist/icons-DTaPp44c.js +863 -0
- package/dist/{it-B95CFDto.js → it-BNztlqHd.js} +19 -3
- package/dist/locales/de/cards.d.ts +7 -0
- package/dist/locales/de/developer.d.ts +7 -0
- package/dist/locales/de/room.d.ts +2 -0
- package/dist/locales/en/cards.d.ts +7 -0
- package/dist/locales/en/developer.d.ts +7 -0
- package/dist/locales/en/room.d.ts +2 -0
- package/dist/locales/es/cards.d.ts +7 -0
- package/dist/locales/es/developer.d.ts +7 -0
- package/dist/locales/es/room.d.ts +2 -0
- package/dist/locales/fr/cards.d.ts +7 -0
- package/dist/locales/fr/developer.d.ts +7 -0
- package/dist/locales/fr/room.d.ts +2 -0
- package/dist/locales/it/cards.d.ts +7 -0
- package/dist/locales/it/developer.d.ts +7 -0
- package/dist/locales/it/room.d.ts +2 -0
- package/dist/mount-CMm0qSYk.js +6257 -0
- package/dist/multiplayer/blackjack.d.ts +35 -0
- package/dist/multiplayer/client.d.ts +55 -0
- package/dist/multiplayer/holdem.d.ts +21 -0
- package/dist/multiplayer/index.d.ts +2 -0
- package/dist/multiplayer/seats.d.ts +16 -0
- package/dist/multiplayer/shared.d.ts +33 -0
- package/dist/multiplayer-CN0t0j_F.js +502 -0
- package/dist/{panel-D1hKmQL7.js → panel-BVgq3Cm5.js} +167 -139
- package/dist/resolve-Dc48n2Jo.js +28 -0
- package/dist/room/boost.d.ts +1 -1
- package/dist/room/lobby.d.ts +1 -0
- package/dist/room/room.d.ts +11 -1
- package/dist/room/stage.d.ts +2 -1
- package/dist/runtime/context.d.ts +3 -1
- package/dist/runtime/sound.d.ts +1 -1
- package/package.json +2 -2
- package/dist/mount-BxDaFww2.js +0 -7034
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Tier } from '../config/types';
|
|
2
|
+
import '../room/chips';
|
|
3
|
+
import type { SharedSeat, TableView } from './client';
|
|
4
|
+
import { SharedTableElement } from './shared';
|
|
5
|
+
export declare class SharedBlackjack extends SharedTableElement {
|
|
6
|
+
protected readonly game = "blackjack";
|
|
7
|
+
private chosen;
|
|
8
|
+
private chips;
|
|
9
|
+
private history;
|
|
10
|
+
private lastBet;
|
|
11
|
+
protected willUpdate(): void;
|
|
12
|
+
protected betting(previous: TableView | null, view: TableView): void;
|
|
13
|
+
private get open();
|
|
14
|
+
private get turn();
|
|
15
|
+
private get hand();
|
|
16
|
+
private get theirs();
|
|
17
|
+
private beats;
|
|
18
|
+
private bet;
|
|
19
|
+
private undo;
|
|
20
|
+
private rebet;
|
|
21
|
+
private clearChips;
|
|
22
|
+
private deal;
|
|
23
|
+
protected outcome(mine: SharedSeat): {
|
|
24
|
+
game: 'blackjack';
|
|
25
|
+
tier: Tier;
|
|
26
|
+
prizeId: string;
|
|
27
|
+
award: import("../engine/awards").Award;
|
|
28
|
+
detail: {
|
|
29
|
+
key: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
private hands;
|
|
33
|
+
private chipsOf;
|
|
34
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Multiplayer, Player, Tier } from '../config/types';
|
|
2
|
+
import type { Card } from '../engine/cards';
|
|
3
|
+
export type SharedGame = 'blackjack' | 'holdem';
|
|
4
|
+
export interface TableView {
|
|
5
|
+
game: SharedGame;
|
|
6
|
+
round: number;
|
|
7
|
+
phase: 'betting' | 'dealing' | 'acting' | 'dealer' | 'done';
|
|
8
|
+
deadline: number | null;
|
|
9
|
+
boost: number;
|
|
10
|
+
you: number | null;
|
|
11
|
+
dealer: (Card | null)[];
|
|
12
|
+
board: (Card | null)[];
|
|
13
|
+
seats: (SharedSeat | null)[];
|
|
14
|
+
}
|
|
15
|
+
export interface SharedHand {
|
|
16
|
+
cards: (Card | null)[];
|
|
17
|
+
stacks: number;
|
|
18
|
+
done: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface SharedSeat {
|
|
21
|
+
name: string | null;
|
|
22
|
+
avatar: string | null;
|
|
23
|
+
ready: boolean;
|
|
24
|
+
playing: boolean;
|
|
25
|
+
prize: string | null;
|
|
26
|
+
chips: number;
|
|
27
|
+
hands: SharedHand[];
|
|
28
|
+
active: number;
|
|
29
|
+
folded: boolean;
|
|
30
|
+
decided: boolean;
|
|
31
|
+
result: string | null;
|
|
32
|
+
tier: Tier | null;
|
|
33
|
+
}
|
|
34
|
+
export declare function events(body: ReadableStream<Uint8Array>): AsyncGenerator<TableView>;
|
|
35
|
+
export declare class SharedTable {
|
|
36
|
+
server: Multiplayer;
|
|
37
|
+
readonly game: SharedGame;
|
|
38
|
+
private memory;
|
|
39
|
+
private connections;
|
|
40
|
+
constructor(server: Multiplayer, game: SharedGame);
|
|
41
|
+
private get key();
|
|
42
|
+
private get token();
|
|
43
|
+
private set token(value);
|
|
44
|
+
private request;
|
|
45
|
+
private reconnect;
|
|
46
|
+
listen(onView: (view: TableView) => void, signal: AbortSignal): Promise<void>;
|
|
47
|
+
sit(seat: number, player: Player | null): Promise<void>;
|
|
48
|
+
stand(): Promise<void>;
|
|
49
|
+
private leave;
|
|
50
|
+
act(action: string, details?: {
|
|
51
|
+
prize?: string;
|
|
52
|
+
chips?: number;
|
|
53
|
+
}): Promise<boolean>;
|
|
54
|
+
}
|
|
55
|
+
export declare function sharedTable(server: Multiplayer, game: SharedGame): SharedTable;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Tier } from '../config/types';
|
|
2
|
+
import type { SharedSeat } from './client';
|
|
3
|
+
import { SharedTableElement } from './shared';
|
|
4
|
+
export declare class SharedHoldem extends SharedTableElement {
|
|
5
|
+
protected readonly game = "holdem";
|
|
6
|
+
private handName;
|
|
7
|
+
private made;
|
|
8
|
+
protected outcome(mine: SharedSeat): {
|
|
9
|
+
game: 'holdem';
|
|
10
|
+
tier: Tier;
|
|
11
|
+
prizeId: string;
|
|
12
|
+
award: import("../engine/awards").Award;
|
|
13
|
+
detail: {
|
|
14
|
+
key: string;
|
|
15
|
+
params: {
|
|
16
|
+
hand: string;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
render(): import("lit-html").TemplateResult<1>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { nothing, type TemplateResult } from 'lit';
|
|
2
|
+
import type { Card } from '../engine/cards';
|
|
3
|
+
import type { RoomContext } from '../runtime/context';
|
|
4
|
+
import type { SharedSeat, TableView } from './client';
|
|
5
|
+
export declare const BACK: Card;
|
|
6
|
+
export declare const cardOf: (dealt: Card | null, options?: {
|
|
7
|
+
lit?: boolean;
|
|
8
|
+
}) => TemplateResult<1>;
|
|
9
|
+
export declare function tableSeats(room: RoomContext, view: TableView, { cards, chips, outcome, sit, stand, }: {
|
|
10
|
+
cards: (seat: SharedSeat, mine: boolean) => TemplateResult | typeof nothing;
|
|
11
|
+
chips?: (seat: SharedSeat, mine: boolean) => TemplateResult | typeof nothing;
|
|
12
|
+
outcome: (seat: SharedSeat) => 'won' | 'lost' | null;
|
|
13
|
+
sit: ((seat: number) => void) | null;
|
|
14
|
+
stand: (() => void) | null;
|
|
15
|
+
}): TemplateResult<1>;
|
|
16
|
+
export declare const secondsLeft: (deadline: number | null) => number | null;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Outcome } from '../engine/outcome';
|
|
2
|
+
import type { GameOptions } from '../runtime/context';
|
|
3
|
+
import { LuckyElement } from '../runtime/element';
|
|
4
|
+
import { type SharedGame, type SharedSeat, type SharedTable, type TableView } from './client';
|
|
5
|
+
export declare abstract class SharedTableElement extends LuckyElement {
|
|
6
|
+
options: GameOptions;
|
|
7
|
+
protected view: TableView | null;
|
|
8
|
+
protected offline: boolean;
|
|
9
|
+
protected clearing: boolean;
|
|
10
|
+
private felt?;
|
|
11
|
+
protected abstract readonly game: SharedGame;
|
|
12
|
+
protected table: SharedTable;
|
|
13
|
+
private stop;
|
|
14
|
+
private next;
|
|
15
|
+
private ticker;
|
|
16
|
+
private finished;
|
|
17
|
+
constructor();
|
|
18
|
+
protected get mine(): SharedSeat | null;
|
|
19
|
+
protected get canSit(): boolean;
|
|
20
|
+
protected sit: (seat: number) => void;
|
|
21
|
+
protected get canStand(): boolean;
|
|
22
|
+
protected stand: () => void;
|
|
23
|
+
connectedCallback(): void;
|
|
24
|
+
disconnectedCallback(): void;
|
|
25
|
+
protected act(action: string, details?: {
|
|
26
|
+
prize?: string;
|
|
27
|
+
chips?: number;
|
|
28
|
+
}): void;
|
|
29
|
+
private receive;
|
|
30
|
+
private show;
|
|
31
|
+
protected betting(_previous: TableView | null, _view: TableView): void;
|
|
32
|
+
protected abstract outcome(mine: SharedSeat): Outcome;
|
|
33
|
+
}
|
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
import { t as e } from "./resolve-Dc48n2Jo.js";
|
|
2
|
+
import { J as t, N as n, Q as r, W as i, X as a, Y as o, Z as s, g as c, n as l, r as u, t as d, tt as f, x as p } from "./icons-DTaPp44c.js";
|
|
3
|
+
import { A as m, E as h, M as g, N as _, O as v, T as y, a as b, c as x, d as S, f as C, h as w, i as T, j as ee, k as E, l as D, m as O, n as k, o as A, p as j, r as M, s as N, u as P, w as F } from "./mount-CMm0qSYk.js";
|
|
4
|
+
// node_modules/lucide/dist/esm/icons/armchair.mjs
|
|
5
|
+
var I = [
|
|
6
|
+
["path", { d: "M19 9V6a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v3" }],
|
|
7
|
+
["path", { d: "M3 16a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5a2 2 0 0 0-4 0v1.5a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5V11a2 2 0 0 0-4 0z" }],
|
|
8
|
+
["path", { d: "M5 18v2" }],
|
|
9
|
+
["path", { d: "M19 18v2" }]
|
|
10
|
+
], L = [
|
|
11
|
+
["path", { d: "m16 17 5-5-5-5" }],
|
|
12
|
+
["path", { d: "M21 12H9" }],
|
|
13
|
+
["path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }]
|
|
14
|
+
], R = {
|
|
15
|
+
rank: 2,
|
|
16
|
+
suit: "spades"
|
|
17
|
+
}, z = (e, t = {}) => k(e ?? R, {
|
|
18
|
+
hidden: !e,
|
|
19
|
+
...t
|
|
20
|
+
}), B = (e, t, n) => {
|
|
21
|
+
let r = e * Math.PI / 180;
|
|
22
|
+
return `left: ${50 + 50 * t * Math.cos(r)}%; top: ${100 * n * Math.sin(r)}%`;
|
|
23
|
+
};
|
|
24
|
+
function V(e, t, { cards: n, chips: i = () => r, outcome: a, sit: o, stand: s }) {
|
|
25
|
+
let c = (e) => 160 - e * 140 / Math.max(1, t.seats.length - 1);
|
|
26
|
+
return f`${t.seats.map((l, u) => {
|
|
27
|
+
if (!l) return f`<button
|
|
28
|
+
class="lk-seat is-free"
|
|
29
|
+
style=${B(c(u), 1, 1)}
|
|
30
|
+
?disabled=${!o}
|
|
31
|
+
aria-label=${e.t("cards.sit")}
|
|
32
|
+
data-tip=${e.t("cards.sit")}
|
|
33
|
+
@click=${() => o?.(u)}
|
|
34
|
+
>
|
|
35
|
+
${d(I)}
|
|
36
|
+
</button>`;
|
|
37
|
+
let p = u === t.you, m = a(l), h = n(l, p), g = i(l, p);
|
|
38
|
+
return f`
|
|
39
|
+
<div class="lk-seat ${p ? "is-mine" : "is-taken"} ${l.ready || l.playing ? "is-in" : ""} ${m ? `is-${m}` : ""}" style=${B(c(u), 1, 1)}>
|
|
40
|
+
${l.avatar ? f`<img src=${l.avatar} alt="" />` : T}
|
|
41
|
+
<b>${l.name || e.t(p ? "cards.you" : "cards.player")}</b>
|
|
42
|
+
${p && s ? f`<button class="lk-seat-leave ${u < (t.seats.length - 1) / 2 ? "is-left" : ""}" aria-label=${e.t("cards.stand")} data-tip=${e.t("cards.stand")} @click=${s}>${d(L)}</button>` : r}
|
|
43
|
+
</div>
|
|
44
|
+
${g === r ? r : f`<div class="lk-seat-play lk-seat-bet ${p ? "is-mine" : ""}" style=${B(c(u), .84, .86)}>${g}</div>`}
|
|
45
|
+
${h === r ? r : f`<div class="lk-seat-play ${p ? "is-mine" : ""} ${l.folded ? "is-folded" : ""}" style=${g === r ? B(c(u), .76, .82) : B(c(u), .6, .66)}>
|
|
46
|
+
${h}
|
|
47
|
+
</div>`}
|
|
48
|
+
`;
|
|
49
|
+
})}`;
|
|
50
|
+
}
|
|
51
|
+
var H = (e) => e === null ? null : Math.max(0, Math.ceil((e - Date.now()) / 1e3)), U = 3;
|
|
52
|
+
async function* W(e) {
|
|
53
|
+
let t = e.getReader(), n = new TextDecoder(), r = "";
|
|
54
|
+
for (;;) {
|
|
55
|
+
let { value: e, done: i } = await t.read();
|
|
56
|
+
if (i) return;
|
|
57
|
+
r += n.decode(e, { stream: !0 }).replace(/\r\n?/g, "\n");
|
|
58
|
+
for (let e = r.indexOf("\n\n"); e >= 0; e = r.indexOf("\n\n")) {
|
|
59
|
+
let t = r.slice(0, e).split("\n").filter((e) => e.startsWith("data:")).map((e) => e.slice(e.startsWith("data: ") ? 6 : 5)).join("\n");
|
|
60
|
+
r = r.slice(e + 2), t && (yield JSON.parse(t));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
var te = (e, t) => new Promise((n) => {
|
|
65
|
+
let r = setTimeout(n, e);
|
|
66
|
+
t.addEventListener("abort", () => (clearTimeout(r), n()), { once: !0 });
|
|
67
|
+
}), ne = class {
|
|
68
|
+
constructor(e, t) {
|
|
69
|
+
this.server = e, this.game = t, this.memory = null, this.connections = /* @__PURE__ */ new Set();
|
|
70
|
+
}
|
|
71
|
+
get key() {
|
|
72
|
+
return `feeling-lucky:${this.server.url}:${this.game}`;
|
|
73
|
+
}
|
|
74
|
+
get token() {
|
|
75
|
+
try {
|
|
76
|
+
return localStorage.getItem(this.key);
|
|
77
|
+
} catch {
|
|
78
|
+
return this.memory;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
set token(e) {
|
|
82
|
+
this.memory = e;
|
|
83
|
+
try {
|
|
84
|
+
e ? localStorage.setItem(this.key, e) : localStorage.removeItem(this.key);
|
|
85
|
+
} catch {}
|
|
86
|
+
}
|
|
87
|
+
async request(t, n = {}) {
|
|
88
|
+
let r = {
|
|
89
|
+
"Content-Type": "application/json",
|
|
90
|
+
...this.server.headers ? await e(this.server.headers) : {},
|
|
91
|
+
...n.headers
|
|
92
|
+
};
|
|
93
|
+
return fetch(`${this.server.url.replace(/\/$/, "")}/${this.game}${t}`, {
|
|
94
|
+
...n,
|
|
95
|
+
headers: r
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
reconnect() {
|
|
99
|
+
this.connections.forEach((e) => e.abort());
|
|
100
|
+
}
|
|
101
|
+
async listen(e, t) {
|
|
102
|
+
let n = (e) => e.key === this.key && this.reconnect();
|
|
103
|
+
addEventListener("storage", n);
|
|
104
|
+
try {
|
|
105
|
+
for (let n = 0; !t.aborted; await te(1e3 * n, t)) {
|
|
106
|
+
let r = new AbortController();
|
|
107
|
+
this.connections.add(r);
|
|
108
|
+
try {
|
|
109
|
+
let i = this.token, a = await this.request("", {
|
|
110
|
+
headers: i ? { "X-Seat-Token": i } : {},
|
|
111
|
+
signal: AbortSignal.any([t, r.signal])
|
|
112
|
+
});
|
|
113
|
+
if (a.status === 404 && i) {
|
|
114
|
+
this.token = null;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (!a.ok || !a.body) throw Error(`feeling-lucky: the ${this.game} table did not answer (${a.status})`);
|
|
118
|
+
n = 0;
|
|
119
|
+
for await (let t of W(a.body)) e(t);
|
|
120
|
+
} catch (e) {
|
|
121
|
+
if (t.aborted || r.signal.aborted) continue;
|
|
122
|
+
if (++n > U) throw e;
|
|
123
|
+
} finally {
|
|
124
|
+
this.connections.delete(r);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} finally {
|
|
128
|
+
removeEventListener("storage", n);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async sit(e, t) {
|
|
132
|
+
await this.leave();
|
|
133
|
+
let n = await this.request("/seats", {
|
|
134
|
+
method: "POST",
|
|
135
|
+
body: JSON.stringify({
|
|
136
|
+
seat: e,
|
|
137
|
+
name: t?.name ?? null,
|
|
138
|
+
avatar: t?.avatar ?? null
|
|
139
|
+
})
|
|
140
|
+
});
|
|
141
|
+
this.token = n.ok ? (await n.json()).token : null, this.reconnect();
|
|
142
|
+
}
|
|
143
|
+
async stand() {
|
|
144
|
+
await this.leave(), this.reconnect();
|
|
145
|
+
}
|
|
146
|
+
async leave() {
|
|
147
|
+
let e = this.token;
|
|
148
|
+
this.token = null, e && await this.request("/seats", {
|
|
149
|
+
method: "DELETE",
|
|
150
|
+
headers: { "X-Seat-Token": e }
|
|
151
|
+
}).catch(() => void 0);
|
|
152
|
+
}
|
|
153
|
+
async act(e, t = {}) {
|
|
154
|
+
let n = this.token;
|
|
155
|
+
return n ? (await this.request("/actions", {
|
|
156
|
+
method: "POST",
|
|
157
|
+
headers: { "X-Seat-Token": n },
|
|
158
|
+
body: JSON.stringify({
|
|
159
|
+
action: e,
|
|
160
|
+
...t
|
|
161
|
+
})
|
|
162
|
+
})).ok : !1;
|
|
163
|
+
}
|
|
164
|
+
}, G = /* @__PURE__ */ new Map();
|
|
165
|
+
function re(e, t) {
|
|
166
|
+
let n = `${e.url} ${t}`, r = G.get(n) ?? new ne(e, t);
|
|
167
|
+
return G.set(n, r), r.server = e, r;
|
|
168
|
+
}
|
|
169
|
+
// src/multiplayer/shared.ts
|
|
170
|
+
var K = (e) => e.dealer.length + e.seats.reduce((e, t) => e + (t?.hands.reduce((e, t) => e + t.cards.length, 0) ?? 0), 0), q = (e) => [
|
|
171
|
+
...e.dealer,
|
|
172
|
+
...e.board,
|
|
173
|
+
...e.seats.flatMap((e) => e?.hands.flatMap((e) => e.cards) ?? [])
|
|
174
|
+
].filter(Boolean).length, J = class extends l {
|
|
175
|
+
constructor() {
|
|
176
|
+
super(), this.options = {}, this.view = null, this.offline = !1, this.clearing = !1, this.stop = new AbortController(), this.next = null, this.ticker = 0, this.finished = -1, this.sit = (e) => {
|
|
177
|
+
this.canSit && this.table.sit(e, this.room.player);
|
|
178
|
+
}, this.stand = () => {
|
|
179
|
+
this.canStand && this.table.stand();
|
|
180
|
+
}, this.watch(p);
|
|
181
|
+
}
|
|
182
|
+
get mine() {
|
|
183
|
+
return this.view?.you == null ? null : this.view.seats[this.view.you] ?? null;
|
|
184
|
+
}
|
|
185
|
+
get canSit() {
|
|
186
|
+
return !this.mine || this.view?.phase === "betting" && !this.mine.ready;
|
|
187
|
+
}
|
|
188
|
+
get canStand() {
|
|
189
|
+
return !!this.mine && this.view?.phase === "betting" && !this.mine.ready;
|
|
190
|
+
}
|
|
191
|
+
connectedCallback() {
|
|
192
|
+
super.connectedCallback(), this.table = re(this.room.multiplayer, this.game), this.stop = new AbortController(), this.table.listen((e) => this.receive(e), this.stop.signal).catch(() => this.offline = !0), this.ticker = window.setInterval(() => this.view?.deadline && this.requestUpdate(), 250);
|
|
193
|
+
}
|
|
194
|
+
disconnectedCallback() {
|
|
195
|
+
super.disconnectedCallback(), this.stop.abort(), clearInterval(this.ticker);
|
|
196
|
+
}
|
|
197
|
+
act(e, t) {
|
|
198
|
+
this.table.act(e, t);
|
|
199
|
+
}
|
|
200
|
+
receive(e) {
|
|
201
|
+
this.clearing ? this.next = e : this.view?.phase === "done" && e.phase === "betting" ? (this.clearing = !0, this.next = e, b.play("whoosh", .4), this.later(() => {
|
|
202
|
+
this.clearing = !1, this.next && this.show(this.next), this.next = null;
|
|
203
|
+
}, D() ? 0 : 650)) : this.show(e);
|
|
204
|
+
}
|
|
205
|
+
show(e) {
|
|
206
|
+
let t = this.view;
|
|
207
|
+
this.view = e, t && e.phase === "dealing" && t.phase === "betting" && b.play("whoosh", .6), t && K(e) > K(t) ? b.play("tick", 1.25) : t && q(e) > q(t) && b.play("tick", 1.1), this.betting(t, e);
|
|
208
|
+
let n = this.mine;
|
|
209
|
+
if (!n?.result || this.finished === e.round) return;
|
|
210
|
+
if (this.finished = e.round, !n.tier || n.tier === "none") {
|
|
211
|
+
b.play("stop", .7);
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
let r = this.outcome(n);
|
|
215
|
+
b.play(r.tier === "jackpot" ? "jackpot" : "win");
|
|
216
|
+
let i = this.felt?.getBoundingClientRect();
|
|
217
|
+
i && !D() && x.burst(i.left + i.width / 2, i.top + i.height * .55, {
|
|
218
|
+
count: 50,
|
|
219
|
+
type: "spark",
|
|
220
|
+
speed: 640,
|
|
221
|
+
life: .8,
|
|
222
|
+
gravity: 300,
|
|
223
|
+
colors: N
|
|
224
|
+
}), this.later(() => this.room.finish(r), D() ? 300 : 1700);
|
|
225
|
+
}
|
|
226
|
+
betting(e, t) {}
|
|
227
|
+
};
|
|
228
|
+
u([a({ attribute: !1 })], J.prototype, "options", void 0), u([o()], J.prototype, "view", void 0), u([o()], J.prototype, "offline", void 0), u([o()], J.prototype, "clearing", void 0), u([t(".lk-cards")], J.prototype, "felt", void 0);
|
|
229
|
+
// src/multiplayer/blackjack.ts
|
|
230
|
+
var Y = 5, ie = [
|
|
231
|
+
"win",
|
|
232
|
+
"dealerBust",
|
|
233
|
+
"natural",
|
|
234
|
+
"spades"
|
|
235
|
+
], X = (e) => O(e.filter((e) => !!e)).total, Z = class extends J {
|
|
236
|
+
constructor(...e) {
|
|
237
|
+
super(...e), this.game = "blackjack", this.chosen = "", this.chips = [], this.history = [], this.lastBet = null;
|
|
238
|
+
}
|
|
239
|
+
willUpdate() {
|
|
240
|
+
this.room.prizeIds.includes(this.chosen) || (this.chosen = this.room.prizeIds[0]);
|
|
241
|
+
}
|
|
242
|
+
betting(e, t) {
|
|
243
|
+
t.phase === "betting" && e?.phase !== "betting" && (this.chips = [], this.history = []);
|
|
244
|
+
}
|
|
245
|
+
get open() {
|
|
246
|
+
let e = this.mine;
|
|
247
|
+
return this.view?.phase === "betting" && !!e && !e.ready;
|
|
248
|
+
}
|
|
249
|
+
get turn() {
|
|
250
|
+
let e = this.mine;
|
|
251
|
+
return this.view?.phase === "acting" && !!e?.playing && !e.decided;
|
|
252
|
+
}
|
|
253
|
+
get hand() {
|
|
254
|
+
return this.mine?.hands[this.mine.active];
|
|
255
|
+
}
|
|
256
|
+
get theirs() {
|
|
257
|
+
return X(this.view?.dealer ?? []);
|
|
258
|
+
}
|
|
259
|
+
beats(e) {
|
|
260
|
+
return X(e) <= 21 && (this.theirs > 21 || this.theirs < X(e));
|
|
261
|
+
}
|
|
262
|
+
bet() {
|
|
263
|
+
!this.open || this.chips.length >= Y || (this.history = [...this.history, [...this.chips]], this.chips = [...this.chips, this.chosen]);
|
|
264
|
+
}
|
|
265
|
+
undo() {
|
|
266
|
+
let e = this.history.at(-1);
|
|
267
|
+
e && (this.history = this.history.slice(0, -1), this.chips = e);
|
|
268
|
+
}
|
|
269
|
+
rebet() {
|
|
270
|
+
this.lastBet && !this.chips.length && (this.history = [...this.history, []], this.chips = this.lastBet.filter((e) => this.room.prizeIds.includes(e)));
|
|
271
|
+
}
|
|
272
|
+
clearChips() {
|
|
273
|
+
this.history = [...this.history, [...this.chips]], this.chips = [];
|
|
274
|
+
}
|
|
275
|
+
deal() {
|
|
276
|
+
this.open && this.chips.length && (this.lastBet = [...this.chips], this.act("bet", {
|
|
277
|
+
prize: this.chips[0],
|
|
278
|
+
chips: this.chips.length
|
|
279
|
+
}));
|
|
280
|
+
}
|
|
281
|
+
outcome(e) {
|
|
282
|
+
let t = e.prize && this.room.prizeIds.includes(e.prize) ? e.prize : this.room.prizeIds[0], r = e.tier;
|
|
283
|
+
return {
|
|
284
|
+
game: "blackjack",
|
|
285
|
+
tier: r,
|
|
286
|
+
prizeId: t,
|
|
287
|
+
award: n(this.room.prize(t), r),
|
|
288
|
+
detail: { key: `detail.blackjack.${e.result}` }
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
hands(e, t, n = -1) {
|
|
292
|
+
return e.hands.map((e, i) => f`
|
|
293
|
+
<div class="lk-split ${i === n ? "is-active" : ""}">
|
|
294
|
+
<div class="lk-hand">${e.cards.map((n) => z(n, { lit: t(e.cards) }))}</div>
|
|
295
|
+
${e.cards.length ? f`<span class="lk-hand-total ${X(e.cards) > 21 ? "is-bust" : ""}"
|
|
296
|
+
>${X(e.cards)}${e.stacks > 1 ? f`<small>×2</small>` : r}</span
|
|
297
|
+
>` : r}
|
|
298
|
+
</div>
|
|
299
|
+
`);
|
|
300
|
+
}
|
|
301
|
+
chipsOf(e, t, n) {
|
|
302
|
+
let { room: r } = this;
|
|
303
|
+
return Array.from({ length: t }, (i, a) => e.map((e, i) => f`<i class="lk-bet-chip ${n ? "is-winning" : ""}" style="--lk-chip: ${r.color(e)}; --n: ${i}; --stack: ${a - (t - 1) / 2}"><img src=${r.icon(e)} alt="" /></i>`));
|
|
304
|
+
}
|
|
305
|
+
render() {
|
|
306
|
+
if (this.offline) return f`<fl-blackjack .options=${this.options}></fl-blackjack>`;
|
|
307
|
+
let { room: e, view: t, mine: n } = this, i = t?.phase ?? "betting", a = n?.result ?? null, o = !!a && ie.includes(a) && !!n?.tier && n.tier !== "none", s = i === "dealing" || i === "dealer", c = n?.ready || n?.playing ? Array.from({ length: n.chips }, () => n.prize ?? e.prizeIds[0]) : this.chips, l = n?.hands.reduce((e, t) => e + t.stacks, 0) || 1, u = H(t?.deadline ?? null), b = t ? n ? !n.playing && i !== "betting" ? this.t("cards.nextHand") : i === "betting" && u !== null ? this.t("cards.dealingIn", { seconds: u }) : this.turn && u !== null ? this.t("cards.playIn", { seconds: u }) : null : this.t("cards.chooseSeat") : null, x = f`
|
|
308
|
+
<span class="lk-hand-name">${this.t("cards.dealer")}${t?.dealer.length ? f`<b>${this.theirs}</b>` : r}</span>
|
|
309
|
+
<div class="lk-hand">${t?.dealer.map((e) => z(e)) ?? r}</div>
|
|
310
|
+
`, S = f`${a ? f`<p class="lk-cards-result ${o ? "is-won" : ""}">${this.t(`blackjack.result.${a}`)}</p>` : b ? f`<p class="lk-cards-status">${b}</p>` : r}`, w = f`
|
|
311
|
+
<button
|
|
312
|
+
class="lk-bet ${this.open && c.length < Y ? "is-open" : ""}"
|
|
313
|
+
?disabled=${!this.open || c.length >= Y}
|
|
314
|
+
aria-label=${this.t("blackjack.bet", { prize: e.name(this.chosen) })}
|
|
315
|
+
@click=${this.bet}
|
|
316
|
+
>
|
|
317
|
+
${this.chipsOf(c, l, o)}
|
|
318
|
+
</button>
|
|
319
|
+
`, T = t ? V(e, t, {
|
|
320
|
+
cards: (e, t) => e.playing ? f`${this.hands(e, (e) => t && o && (a === "natural" || a === "spades" || this.beats(e)), t && e.hands.length > 1 && this.turn ? e.active : -1)}` : r,
|
|
321
|
+
chips: (t, n) => n ? w : t.ready || t.playing ? f`<span class="lk-bet">${this.chipsOf(Array.from({ length: t.chips }, () => t.prize ?? e.prizeIds[0]), t.hands.reduce((e, t) => e + t.stacks, 0) || 1, !1)}</span>` : r,
|
|
322
|
+
outcome: (e) => e.result ? e.tier && e.tier !== "none" ? "won" : "lost" : null,
|
|
323
|
+
sit: this.canSit ? this.sit : null,
|
|
324
|
+
stand: this.canStand ? this.stand : null
|
|
325
|
+
}) : void 0;
|
|
326
|
+
return A(e.t, {
|
|
327
|
+
state: o ? "won" : s ? "spinning" : "idle",
|
|
328
|
+
rules: this.t("games.blackjack.rules"),
|
|
329
|
+
multiplier: t?.boost ?? 1,
|
|
330
|
+
dealer: !0
|
|
331
|
+
}, f`
|
|
332
|
+
<div class="lk-cards lk-cards--blackjack lk-cards--shared ${this.clearing ? "is-clearing" : ""}">
|
|
333
|
+
${M(e, this.t("blackjack.print"), {
|
|
334
|
+
dealer: x,
|
|
335
|
+
centre: S,
|
|
336
|
+
player: f``,
|
|
337
|
+
seats: T
|
|
338
|
+
}, {
|
|
339
|
+
on: p.value,
|
|
340
|
+
dealing: s
|
|
341
|
+
})}
|
|
342
|
+
<div class="lk-rl-rack lk-cards-rack">
|
|
343
|
+
<fl-chips
|
|
344
|
+
.chosen=${this.chosen}
|
|
345
|
+
.disabled=${!this.open}
|
|
346
|
+
.locked=${c[0] ?? null}
|
|
347
|
+
.count=${{
|
|
348
|
+
used: c.length,
|
|
349
|
+
max: Y
|
|
350
|
+
}}
|
|
351
|
+
@choose=${(e) => this.chosen = e.detail}
|
|
352
|
+
></fl-chips>
|
|
353
|
+
<div class="lk-rl-actions">
|
|
354
|
+
<div class="lk-rl-quick">
|
|
355
|
+
<button
|
|
356
|
+
class="lk-round"
|
|
357
|
+
aria-label=${this.t("roulette.undo")}
|
|
358
|
+
data-tip=${this.t("roulette.undo")}
|
|
359
|
+
?disabled=${!this.history.length || !this.open}
|
|
360
|
+
@click=${this.undo}
|
|
361
|
+
>
|
|
362
|
+
${d(F)}
|
|
363
|
+
</button>
|
|
364
|
+
<button
|
|
365
|
+
class="lk-round"
|
|
366
|
+
aria-label=${this.t("roulette.rebet")}
|
|
367
|
+
data-tip=${this.t("roulette.rebet")}
|
|
368
|
+
?disabled=${!this.lastBet || !!this.chips.length || !this.open}
|
|
369
|
+
@click=${this.rebet}
|
|
370
|
+
>
|
|
371
|
+
${d(v)}
|
|
372
|
+
</button>
|
|
373
|
+
<button
|
|
374
|
+
class="lk-round"
|
|
375
|
+
aria-label=${this.t("roulette.clear")}
|
|
376
|
+
data-tip=${this.t("roulette.clear")}
|
|
377
|
+
?disabled=${!this.chips.length || !this.open}
|
|
378
|
+
@click=${this.clearChips}
|
|
379
|
+
>
|
|
380
|
+
${d(y)}
|
|
381
|
+
</button>
|
|
382
|
+
</div>
|
|
383
|
+
${i === "acting" && n?.playing ? f`
|
|
384
|
+
<button class="lk-btn lk-btn--primary lk-btn--lg" ?disabled=${!this.turn} @click=${() => this.act("hit")}>
|
|
385
|
+
${d(g)}${this.t("blackjack.hit")}
|
|
386
|
+
</button>
|
|
387
|
+
<button class="lk-btn lk-btn--outline lk-btn--lg" ?disabled=${!this.turn} @click=${() => this.act("stand")}>
|
|
388
|
+
${d(m)}${this.t("blackjack.stand")}
|
|
389
|
+
</button>
|
|
390
|
+
<button
|
|
391
|
+
class="lk-btn lk-btn--outline lk-btn--lg"
|
|
392
|
+
?disabled=${!this.turn || this.hand?.cards.length !== 2}
|
|
393
|
+
@click=${() => this.act("double")}
|
|
394
|
+
>
|
|
395
|
+
${d(_)}${this.t("blackjack.double")}
|
|
396
|
+
</button>
|
|
397
|
+
<button
|
|
398
|
+
class="lk-btn lk-btn--outline lk-btn--lg"
|
|
399
|
+
?disabled=${!this.turn || n.hands.length !== 1 || !C(n.hands[0].cards.filter((e) => !!e))}
|
|
400
|
+
@click=${() => this.act("split")}
|
|
401
|
+
>
|
|
402
|
+
${d(h)}${this.t("blackjack.split")}
|
|
403
|
+
</button>
|
|
404
|
+
` : f`<button class="lk-btn lk-btn--primary lk-btn--lg" ?disabled=${!this.open || !this.chips.length} @click=${this.deal}>
|
|
405
|
+
${d(E)}${this.t("cards.deal")}
|
|
406
|
+
</button>`}
|
|
407
|
+
</div>
|
|
408
|
+
</div>
|
|
409
|
+
</div>
|
|
410
|
+
`);
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
u([o()], Z.prototype, "chosen", void 0), u([o()], Z.prototype, "chips", void 0), u([o()], Z.prototype, "history", void 0), u([o()], Z.prototype, "lastBet", void 0), Z = u([s("fl-blackjack-shared")], Z);
|
|
414
|
+
// src/multiplayer/holdem.ts
|
|
415
|
+
var Q = (e) => e.every(Boolean) ? e : null, $ = class extends J {
|
|
416
|
+
constructor(...e) {
|
|
417
|
+
super(...e), this.game = "holdem";
|
|
418
|
+
}
|
|
419
|
+
handName(e) {
|
|
420
|
+
return this.t(`holdem.hands.${P[e]}`);
|
|
421
|
+
}
|
|
422
|
+
made(e) {
|
|
423
|
+
let t = this.view, n = Q(t?.board ?? []), r = Q(e), i = Q(t?.dealer ?? []);
|
|
424
|
+
return n?.length === 5 && r?.length && i?.length ? w(r, i, n) : null;
|
|
425
|
+
}
|
|
426
|
+
outcome(e) {
|
|
427
|
+
let t = c("holdem", this.room.prizeIds), r = e.tier, i = this.made(e.hands[0]?.cards ?? []);
|
|
428
|
+
return {
|
|
429
|
+
game: "holdem",
|
|
430
|
+
tier: r,
|
|
431
|
+
prizeId: t,
|
|
432
|
+
award: n(this.room.prize(t), r),
|
|
433
|
+
detail: {
|
|
434
|
+
key: "detail.holdem",
|
|
435
|
+
params: { hand: i ? this.handName(i.mine.category) : "" }
|
|
436
|
+
}
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
render() {
|
|
440
|
+
if (this.offline) return f`<fl-holdem .options=${this.options}></fl-holdem>`;
|
|
441
|
+
let { room: e, view: t, mine: n } = this, a = t?.phase ?? "betting", o = n?.hands[0]?.cards ?? [], s = n?.folded ? null : this.made(o), c = !!n?.tier && n.tier !== "none", l = a === "dealing" || a === "dealer", u = a === "acting" && !!n?.playing && !n.decided, m = H(t?.deadline ?? null), h = t ? n ? !n.playing && a !== "betting" ? this.t("cards.nextHand") : a === "betting" && m !== null ? this.t("cards.dealingIn", { seconds: m }) : u && m !== null ? this.t("cards.playIn", { seconds: m }) : null : this.t("cards.chooseSeat") : null, g = !s || this.clearing ? [] : s.lost ? j(s.theirs) : c ? j(s.mine) : [...j(s.mine), ...j(s.theirs)], _ = (e) => !!e && g.some((t) => t.rank === e.rank && t.suit === e.suit), v = f`
|
|
442
|
+
<span class="lk-hand-name">${this.t("cards.dealer")}${s ? f`<b>${this.handName(s.theirs.category)}</b>` : r}</span>
|
|
443
|
+
<div class="lk-hand">${t?.dealer.map((e) => z(e, { lit: _(e) })) ?? r}</div>
|
|
444
|
+
`, y = n?.result === "folded" ? this.t("holdem.result.folded") : s && n?.result ? c ? this.t("holdem.result.won", { hand: this.handName(s.mine.category) }) : s.lost ? this.t("holdem.result.lost", { hand: this.handName(s.theirs.category) }) : this.t("holdem.result.split") : null, b = f`
|
|
445
|
+
<div class="lk-board">
|
|
446
|
+
${(t?.board.length ? t.board : Array.from({ length: 5 }, () => null)).map((e) => e ? z(e, { lit: _(e) }) : f`<i class="lk-board-slot"></i>`)}
|
|
447
|
+
</div>
|
|
448
|
+
${y ? f`<p class="lk-cards-result ${c ? "is-won" : ""}">${y}</p>` : h ? f`<p class="lk-cards-status">${h}</p>` : r}
|
|
449
|
+
`, x = f`
|
|
450
|
+
<div class="lk-hand">${o.map((e) => z(e, { lit: _(e) }))}</div>
|
|
451
|
+
${s ? f`<span class="lk-hand-total is-name">${this.handName(s.mine.category)}</span>` : r}
|
|
452
|
+
`, C = t ? V(e, t, {
|
|
453
|
+
cards: (e, n) => {
|
|
454
|
+
if (!e.playing) return r;
|
|
455
|
+
if (n) return x;
|
|
456
|
+
let i = Q(e.hands[0]?.cards ?? []), a = Q(t.board);
|
|
457
|
+
return f`
|
|
458
|
+
<div class="lk-hand">${e.hands[0]?.cards.map((e) => z(e)) ?? r}</div>
|
|
459
|
+
${i?.length && a?.length === 5 && !e.folded ? f`<span class="lk-hand-total is-name">${this.handName(S([...i, ...a]).category)}</span>` : r}
|
|
460
|
+
`;
|
|
461
|
+
},
|
|
462
|
+
outcome: (e) => e.result ? e.tier && e.tier !== "none" ? "won" : "lost" : null,
|
|
463
|
+
sit: this.canSit ? this.sit : null,
|
|
464
|
+
stand: this.canStand ? this.stand : null
|
|
465
|
+
}) : void 0;
|
|
466
|
+
return A(e.t, {
|
|
467
|
+
state: c && n?.result ? "won" : l ? "spinning" : "idle",
|
|
468
|
+
rules: this.t("games.holdem.rules"),
|
|
469
|
+
multiplier: t?.boost ?? 1,
|
|
470
|
+
dealer: !0
|
|
471
|
+
}, f`
|
|
472
|
+
<div class="lk-cards lk-cards--holdem lk-cards--shared ${this.clearing ? "is-clearing" : ""}">
|
|
473
|
+
${M(e, this.t("holdem.print"), {
|
|
474
|
+
dealer: v,
|
|
475
|
+
centre: b,
|
|
476
|
+
player: f``,
|
|
477
|
+
seats: C
|
|
478
|
+
}, {
|
|
479
|
+
on: p.value,
|
|
480
|
+
dealing: l
|
|
481
|
+
})}
|
|
482
|
+
<div class="lk-controls lk-cards-controls">
|
|
483
|
+
${a === "acting" && n?.playing ? f`
|
|
484
|
+
<button class="lk-btn lk-btn--primary lk-btn--lg" ?disabled=${!u} @click=${() => this.act("call")}>
|
|
485
|
+
${d(ee)}${this.t("holdem.call")}
|
|
486
|
+
</button>
|
|
487
|
+
<button class="lk-btn lk-btn--outline lk-btn--lg" ?disabled=${!u} @click=${() => this.act("fold")}>
|
|
488
|
+
${d(i)}${this.t("holdem.fold")}
|
|
489
|
+
</button>
|
|
490
|
+
` : f`<button
|
|
491
|
+
class="lk-btn lk-btn--primary lk-btn--lg"
|
|
492
|
+
?disabled=${a !== "betting" || !n || n.ready}
|
|
493
|
+
@click=${() => this.act("deal")}
|
|
494
|
+
>
|
|
495
|
+
${d(E)}${this.t("cards.deal")}
|
|
496
|
+
</button>`}
|
|
497
|
+
</div>
|
|
498
|
+
</div>
|
|
499
|
+
`);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
502
|
+
$ = u([s("fl-holdem-shared")], $);
|