Hearts tutorial: setSelectionMode() to restrict playable cards list doesn't work as coded
Posted: 16 August 2026, 23:42
The good news is I survived the rest of the tutorial and have a working game.
However, I couldn't get the client-side control for setSelectionMode() to work correctly. I'm following the code samples in the Rule Enforcements section:
The server-side logic correctly determines playable cards in the current player's hand and throws an exception if they attempt to play a disallowed card. I have it working with a call to this.game.handStock.setSelectionMode("single"); to just limit selection to one card, but anytime I try to send in a 2nd parameter for selectable cards, the result is the full hand grayed out with nothing selectable.
Here's the code from the tutorial:
I already had to do some tweaks to this:
If I pass that array of strings as the 2nd param in setSelectionMode, I get all grayed-out cards.
If I pass an array of integers as a hack, I still get all grayed-out cards.
Is it supposed to take an array of a different object type? The provided code seems to just expect it to work with an array of strings.
Looking at the documentation for setSelectionMode I'm having trouble understanding what a valid format for CardsInput should be.
Any ideas why this keeps failing and setting 0 cards as selectable?
The server-side logic correctly determines playable cards in the current player's hand and throws an exception if they attempt to play a disallowed card. I have it working with a call to this.game.handStock.setSelectionMode("single"); to just limit selection to one card, but anytime I try to send in a 2nd parameter for selectable cards, the result is the full hand grayed out with nothing selectable.
Here's the code from the tutorial:
Code: Select all
onEnteringState(args, isCurrentPlayerActive) {
console.log("Entering state: " + this.bga.states.currentStateName, args);
this.bga.statusBar.setTitle(
isCurrentPlayerActive
? _("${you} must play a card")
: _("${actplayer} must play a card"),
);
switch (stateName) {
case "PlayerTurn":
if (isCurrentPlayerActive) {
const playableCardsIds = args.playableCardsIds; // returned by the PlayerTurn::getArgs
const allCards = this.game.handStock.getCards();
const playableCards = allCards.filter(
(card) => playableCardIds.includes(parseInt(card.id)) // never know if we get int or string, this method cares
);
this.game.handStock.setSelectionMode("single", playableCards);
}
break;
}
},- Explicitly set stateName to trigger the switch statement: var stateName = this.bga.states.currentStateName;
- Loaded the playable cards list from args._private.playableCards instead of args.playableCardsIds since it seems to be nested one level down and have a slightly different name
- Corrected typo playableCardIds vs playableCardsIds (extra 's')
If I pass that array of strings as the 2nd param in setSelectionMode, I get all grayed-out cards.
If I pass an array of integers as a hack, I still get all grayed-out cards.
Is it supposed to take an array of a different object type? The provided code seems to just expect it to work with an array of strings.
Looking at the documentation for setSelectionMode I'm having trouble understanding what a valid format for CardsInput should be.
Any ideas why this keeps failing and setting 0 cards as selectable?