@enigma-lake/beerpong-v2-play-controller
v1.0.0
Published
A React component library for building gameplay interfaces
Keywords
Readme
Beerpong V2 Play Controller
@enigma-lake/beerpong-v2-play-controller — the React play-controller library for Enigma Lake Beerpong V2. A game-specific fork of @enigma-lake/multi-play-controller-sdk (v4.1.x) that renders the bet/play interface: two side-by-side manual controllers (LEFT / RIGHT), an autoplay tab, a single-controller Rush Mode, free rounds, a risk selector, i18n, and pluggable widgets.
Component Overview
The controller lets the player:
- Select a currency and adjust the play amount (per side, or one amount in autoplay/rush mode).
- Start a manual play on either board (LEFT / RIGHT) — or on a single board in Rush Mode.
- Run autoplay with a configurable number of rounds (including ∞).
- Pick a risk level (LOW / MEDIUM / HIGH / EXTREME, game-configurable).
- Engage and play free rounds (intro modal → locked stake → footer counter → summary modal).
Game modes
| Mode | Layout | CTA |
| ------------------------------ | --------------------------------------------------------------------------------------- | ---------------------------------- |
| Manual | Two mini controllers, LEFT + RIGHT | PLAY NOW (per side) |
| Autoplay | Full-size amount control + one full-width button | START AUTOPLAY / STOP AUTOPLAY |
| Rush Mode (singleLockedMode) | Identical to the autoplay layout — full-size amount control + one full-width button | PLAY NOW (manual play) |
Rush Mode is activated by the game via playOptions.singleLockedMode; freezing the amount/risk stays the game's job (disableInput / disableRisk).
Setup
This package is not published to npm — it is consumed by the game as a local tarball (file: dependency).
Development loop
# in this repo
npm run build # tsc && rollup
npm pack # -> enigma-lake-beerpong-v2-play-controller-<version>.tgzThen point the game at the tarball (already wired in el-games-beerpong-v2-ssh):
// client/package.json + skins/base/package.json
"@enigma-lake/beerpong-v2-play-controller": "file:../../_controlles/beerpong-v2-controller-sdk/enigma-lake-beerpong-v2-play-controller-1.0.0.tgz"When iterating, bump the version in
package.jsonbeforenpm pack, update thefile:ref, and re-runnpm installin the game client — otherwise npm may keep the cached tarball.
Import
import {
AutoManualPlayProvider,
GAME_MODE,
AUTO_PLAY_STATE,
PLAY_SIDE,
} from "@enigma-lake/beerpong-v2-play-controller";
import "@enigma-lake/beerpong-v2-play-controller/dist/style.css";Peer dependencies
@enigma-lake/zoot-platform-sdk (^2.1.0), @headlessui/react (^2.2.0), react / react-dom (18.2.0).
Public API
Provider (the main entry point)
AutoManualPlayProvider
Standalone free-rounds modals (the game mounts/unmounts them)
FreeRoundsIntroModal, FreeRoundsSummaryModal
Enums & constants
GAME_MODE MANUAL | AUTOPLAY
AUTO_PLAY_STATE IDLE | PLAYING
PLAY_SIDE LEFT | RIGHT | AUTO
WIDGET CENTER | SIDE
RiskTypes, DEFAULT_RISK_COLORS
i18n
SUPPORTED_LANGUAGE_CODES, SUPPORTED_LANGUAGES, DEFAULT_LANGUAGE,
resolveLanguage, createTranslator, I18nProvider, useTranslation
Utils
format(balance, decimals)
Types
PlayControllerProps, FreeRoundsOptionsProps, Widget,
FreeRoundsIntroModalProps, FreeRoundsSummaryModalProps,
SupportedLanguage, Messages, MessageKey, TranslationParams, TranslatorAutoManualPlayProvider
Wraps the game UI, renders the play controller panel, and manages manual play and autoplay state. Exposes state via React Context (also available render-prop style).
config props (PlayControllerProps)
1. Styling (StylingProps)
panelbottom: position of the panel relative to the window (e.g."70px").bgColorHex(optional): panel background; defaults to#221062.
dropdownbgColorHex(optional): dropdown / risk-selector background; defaults to#150C47.riskColorConfig(optional): per-risk colors, e.g.{ LOW: "#1AE380", MEDIUM: "#FAEB78", HIGH: "#FF5646" }; defaults toDEFAULT_RISK_COLORS.
2. Language
language(optional): aSupportedLanguagecode. Bundled locales:en(default),zh-CN. Resolved viaresolveLanguage.
3. Currency (currencyOptions, CurrencyProps from the platform SDK)
current: the currently selected currency, as aCurrencyMeta({ code, label, abbr, decimals, icon?, possibleWin? }).available:CurrencyMeta[]the user can pick from.
4. Actions (ActionsProps)
onPlay(side): fired when the user starts a manual play (PLAY_SIDE.LEFT/RIGHT).onAutoPlay(next, stop, state): fired on each autoplay round — callnext()to schedule the next round,stop()to end the loop;stateis the currentAUTO_PLAY_STATE.
5. Play settings (playOptions, PlaySettingsProps)
displayController: show/hide the whole panel.disabledController/disabledMenu/disableInput/disableRisk: granular disable flags (controller, currency menu, amount input, risk selector).lastPlayedSide: which side the Space shortcut targets.isManualButtonDisabled:{ [PLAY_SIDE.LEFT]: boolean, [PLAY_SIDE.RIGHT]: boolean }.playHook(): game-owned amounts state — returnsplayLimits(PlayLimitsV2, keyed by currency),leftPlayAmount/rightPlayAmount/autoPlayAmountand their setters (setLeftBetAmount/setRightBetAmount/setAutoBetAmount).currentRisk/risks/onRiskChange: risk selector state.autoPlayDelay(optional): delay in ms between autoplay rounds.autoPlayRoundsDefault/autoPlayRoundsMax(optional): default & max for the "Number of Plays" input (legacy fallback: 100 / 99).totalBalance: available balance for the current currency.singleLockedMode(optional) — Rush Mode:active: whiletrue, MANUAL mode renders ONE controller (autoplay-style layout,PLAY NOWCTA) instead of the LEFT+RIGHT pair.side(optional): which side's amount/callbacks the single controller drives (defaultLEFT).
6. Widgets
leftWidgets/centerWidgets/rightWidgets:Widget[]rendered below the controller. Each widget is{ type: WIDGET, renderElement({ state, displayPlayAmountView }) }.
7. Free rounds (freeRoundsOptions, optional — FreeRoundsOptionsProps)
Binary engagement model; the SDK does no fetching and owns no state — the game owns everything and the SDK renders + fires callbacks:
showIntroModal/onPlayNow/onPlayLater: the "PLAY NOW / PLAY LATER" intro modal — the ONLY entry point into free-rounds mode.engaged: whiletrue(and rounds remain) both boards lock to the grant stake.roundsRemaining/totalRounds: drive the footer counter and the intro modal.stakeCents: grant per-round value in cents; locks the amount input when engaged.coinType(B2C: SWEEPS=0 / GOLD=1) orcurrency(B2B, e.g."USD"): display/freeze only.expiresAt(optional): drives the "*Expires in N days" line in the intro modal.autoplayActive(optional):truewhile a game-driven autoplay loop runs — hides the manual CTA so stop-autoplay is the only action.
The END summary pop-up is a separate export (FreeRoundsSummaryModal) that the game shows after the last free round settles (totalWinAmount, coin, roundsPlayed, decimals?, onClose).
Example Usage
import "@enigma-lake/beerpong-v2-play-controller/dist/style.css";
import {
AutoManualPlayProvider,
PLAY_SIDE,
RiskTypes,
} from "@enigma-lake/beerpong-v2-play-controller";
import { Currency } from "@enigma-lake/zoot-platform-sdk";
const GameExample = () => {
const config = {
language: "en",
currencyOptions: {
// CurrencyMeta objects (usually taken from the platform's user-currency event)
current: {
code: Currency.SWEEPS,
label: "Sweeps",
abbr: "SC",
decimals: 2,
},
available: [
{ code: Currency.SWEEPS, label: "Sweeps", abbr: "SC", decimals: 2 },
{ code: Currency.GOLD, label: "Gold", abbr: "GC", decimals: 0 },
],
},
onPlay: (side) => console.log("Manual play on side:", side),
onAutoPlay: (next, stop, state) => {
// run a round, then either schedule the next one or stop the loop
next();
},
playOptions: {
displayController: true,
disabledController: false,
disabledMenu: false,
disableInput: false,
disableRisk: false,
lastPlayedSide: PLAY_SIDE.LEFT,
isManualButtonDisabled: {
[PLAY_SIDE.LEFT]: false,
[PLAY_SIDE.RIGHT]: false,
},
currentRisk: RiskTypes.LOW,
risks: [RiskTypes.LOW, RiskTypes.MEDIUM, RiskTypes.HIGH],
onRiskChange: (risk) => console.log("Risk:", risk),
totalBalance: 1000,
playHook: () => ({
playLimits, // PlayLimitsV2 from the platform, keyed by currency
leftPlayAmount: 10,
rightPlayAmount: 10,
autoPlayAmount: 10,
setLeftBetAmount: (value) => {},
setRightBetAmount: (value) => {},
setAutoBetAmount: (value) => {},
}),
// Rush Mode: one autoplay-style controller with a PLAY NOW CTA
singleLockedMode: { active: false, side: PLAY_SIDE.LEFT },
},
leftWidgets: [],
centerWidgets: [],
rightWidgets: [],
panel: {
bottom: window.innerWidth < 450 ? "55px" : "70px",
bgColorHex: "#08643F",
},
dropdown: {
bgColorHex: "#10243F",
riskColorConfig: {
LOW: "#1AE380",
MEDIUM: "#FAEB78",
HIGH: "#FF5646",
},
},
};
return (
<AutoManualPlayProvider config={config}>
{({ autoPlay: { state, playedRounds, numberOfPlays }, mode }) =>
// game content
null
}
</AutoManualPlayProvider>
);
};Scripts
npm run build # tsc && rollup -c --bundleConfigAsCjs
npm run start # webpack serve --mode development --open (dev harness)
npm run eslint:check # lint without fixing
npm run prettier:checkRepo structure
src/
components/
AutoManualPlayStateProvider/ # provider + panel layout (manual/autoplay switch)
base/
ManualMultiPlayController/ # LEFT+RIGHT pair + SingleManualPlayController (Rush Mode)
ManualPlayController/ # mini per-side controller
AutoPlayController/ # autoplay tab
PlayController/ # full-size + mini amount controls
FreeRoundsIntroModal/ # START pop-up (PLAY NOW / PLAY LATER)
FreeRoundsSummaryModal/ # END pop-up (game-mounted)
FreeRoundsFooter/ # "{N} FREE ROUNDS LEFT" counter
DifficultySelector/ # risk selector
... # Button, Input, SelectMenu, Switch, etc.
hooks/ # usePlayController, useAutoplay
Widgets/ # widget container
i18n/ # I18nProvider + locales (en, zh-CN)
types/ # PlayControllerProps & friends