Skip to content
This repository was archived by the owner on Sep 1, 2023. It is now read-only.

Commit f0da2e8

Browse files
committed
split card pick into 2 if required
1 parent 3b0eeff commit f0da2e8

File tree

6 files changed

+81
-44
lines changed

6 files changed

+81
-44
lines changed

src/commands/fixgame.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ export const cmd = {
6363
delete games[msg.channel.id];
6464
respond(msg, `👍 Deleted the game in this channel and gave **${getUsername(winner, true, guild)}** the win`);
6565
}
66-
else if (Object.values(game.cards).some(c => Object.keys(cardArrayToCount(c)).length > 23)) {
67-
const badPlayer = Object.entries(game.cards).find(c => Object.keys(cardArrayToCount(c[1])).length > 23)![0];
66+
else if (Object.values(game.cards).some(c => Object.keys(cardArrayToCount(c)).length > 48)) {
67+
const badPlayer = Object.entries(game.cards).find(c => Object.keys(cardArrayToCount(c[1])).length > 48)![0];
6868
game.players.splice(game.players.indexOf(badPlayer), 1);
6969
respond(msg, `Removed **${getUsername(badPlayer, true, msg.guild)}**`);
7070
if (game.players.length <= 1) return;

src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export const ButtonIDs = Object.freeze({
9393

9494
export const SelectIDs = Object.freeze({
9595
CHOOSE_CARD: "choose-card",
96+
CHOOSE_CARD_ABOVE_25: "choose-card-2",
9697
CHOOSE_COLOR: "choose-color",
9798
FORCEFUL_DRAW: "draw-or-stack",
9899
EDIT_GAME_SETTINGS: "change-settings",

src/gameLogic/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,10 +135,14 @@ export function onSelectMenu(ctx: ComponentInteraction<ComponentTypes.STRING_SEL
135135
const game = games[ctx.channel.id];
136136
if (!game) return;
137137

138-
if (ctx.data.customID === SelectIDs.CHOOSE_CARD && hasStarted(game)) onCardPlayed(ctx, game);
139-
else if (ctx.data.customID === SelectIDs.CHOOSE_COLOR && hasStarted(game)) onColorPlayed(ctx, game);
140-
else if (ctx.data.customID === SelectIDs.FORCEFUL_DRAW && hasStarted(game)) onForceDrawPlayed(ctx, game);
141-
else if (ctx.data.customID === SelectIDs.EDIT_GAME_SETTINGS && !hasStarted(game)) onSettingsChange(ctx, game);
138+
if ((ctx.data.customID === SelectIDs.CHOOSE_CARD || ctx.data.customID === SelectIDs.CHOOSE_CARD_ABOVE_25) && hasStarted(game))
139+
onCardPlayed(ctx, game);
140+
else if (ctx.data.customID === SelectIDs.CHOOSE_COLOR && hasStarted(game))
141+
onColorPlayed(ctx, game);
142+
else if (ctx.data.customID === SelectIDs.FORCEFUL_DRAW && hasStarted(game))
143+
onForceDrawPlayed(ctx, game);
144+
else if (ctx.data.customID === SelectIDs.EDIT_GAME_SETTINGS && !hasStarted(game))
145+
onSettingsChange(ctx, game);
142146
}
143147

144148
export function onModalSubmit(ctx: ModalSubmitInteraction) {

src/gameLogic/playedCards.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { cardEmotes, cards, colors, SelectIDs, uniqueVariants, variants } from "
66
import { config } from "../index.js";
77
import timeouts from "../timeouts.js";
88
import { Card, UnoGame } from "../types.js";
9-
import { cardArrayToCount, getUsername, next, PickCardSelect, toTitleCase, wasLastTurnBlocked } from "../utils.js";
9+
import { getUsername, next, PickCardSelect, toTitleCase, wasLastTurnBlocked } from "../utils.js";
1010
import { games, onTimeout, sendGameMessage } from "./index.js";
1111

1212
export function onColorPlayed(ctx: ComponentInteraction<ComponentTypes.STRING_SELECT>, game: UnoGame<true>) {
@@ -130,14 +130,16 @@ export function onCardPlayed(ctx: ComponentInteraction<ComponentTypes.STRING_SEL
130130
game.cards[ctx.member.id].push(newCards[0]);
131131
game.cards[ctx.member.id].sort((a, b) => cards.indexOf(a) - cards.indexOf(b));
132132
game.deck = newDeck;
133-
if (game.settings.allowSkipping)
134-
ctx.editOriginal({
133+
if (game.settings.allowSkipping) {
134+
const components = PickCardSelect(game, ctx.member.id);
135+
if (components) ctx.editOriginal({
135136
content: config.emoteless
136137
? `You drew a ${cardEmotes[newCards[0]]} ${toTitleCase(newCards[0])}`
137138
: `${game.cards[ctx.member.id].map(c => cardEmotes[c]).join(" ")}
138139
You drew ${cardEmotes[newCards[0]]}`,
139-
components: PickCardSelect(game, cardArrayToCount(game.cards[ctx.member.id]))
140+
components
140141
});
142+
}
141143
else
142144
ctx.deleteOriginal();
143145
}

src/gameLogic/started.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ export function onGameButtonPress(ctx: ComponentInteraction<ComponentTypes.BUTTO
5555
flags: MessageFlags.EPHEMERAL
5656
});
5757

58-
ctx.createFollowup({
58+
const components = PickCardSelect(game, ctx.member.id);
59+
if (components) ctx.createFollowup({
5960
content: config.emoteless ? null : game.cards[ctx.member.id].map(c => cardEmotes[c]).join(" "),
60-
components: PickCardSelect(game, cardArrayToCount(game.cards[ctx.member.id])),
61+
components,
6162
flags: MessageFlags.EPHEMERAL
6263
});
6364
break;

src/utils.ts

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { ComponentBuilder } from "@oceanicjs/builders";
22
import { AnyGuildTextChannel, ButtonStyles, ComponentTypes, Guild, MessageActionRow } from "oceanic.js";
33

4-
import { client } from "./client.js";
4+
import { client, sendMessage } from "./client.js";
55
import { ButtonIDs, cardEmotes, cards, defaultSettings, SelectIDs, SettingsIDs } from "./constants.js";
66
import database from "./database.js";
7-
import { games } from "./gameLogic/index.js";
7+
import { games, sendGameMessage } from "./gameLogic/index.js";
88
import { Card, PlayerStorage, UnoGame } from "./types.js";
99

1010
export const GameButtons = (() => {
@@ -42,35 +42,64 @@ export function onMsgError(e: Error, ctx: { channelID: string }) {
4242
console.log(e);
4343
}
4444

45-
export const PickCardSelect = (game: UnoGame<true>, cards: { [k in Card]?: number }) =>
46-
new ComponentBuilder<MessageActionRow>()
47-
.addSelectMenu({
48-
customID: SelectIDs.CHOOSE_CARD,
49-
placeholder: "Choose a card",
50-
options: [
51-
...Object.keys(cards).map(c => {
52-
return {
53-
label: `${toTitleCase(c)}${cards[c] >= 2 ? ` x${cards[c]}` : ""}`,
54-
value: c,
55-
emoji: ComponentBuilder.emojiToPartial(cardEmotes[c])
56-
};
57-
}),
58-
{
59-
label: "Draw a card",
60-
value: "draw",
61-
emoji: ComponentBuilder.emojiToPartial("🃏")
62-
}
63-
].concat(game.lastPlayer.id === game.currentPlayer && game.settings.allowSkipping &&
64-
(game.players.length === 2 ? (wasLastTurnBlocked(game) ? game.lastPlayer.duration >= 1 : true) : true)
65-
? [{
66-
label: "Skip your turn",
67-
value: "skip",
68-
emoji: ComponentBuilder.emojiToPartial("➡")
69-
}]
70-
: []),
71-
type: ComponentTypes.STRING_SELECT
72-
})
73-
.toJSON();
45+
export function PickCardSelect(game: UnoGame<true>, id: string): MessageActionRow[] | false {
46+
if (!game.players.includes(id))
47+
throw new Error(`Player ${id} not in game ${game.channelID}`);
48+
49+
const cards = cardArrayToCount(game.cards[id]);
50+
const entries = [
51+
...Object.keys(cards).map(c => {
52+
return {
53+
label: `${toTitleCase(c)}${cards[c] >= 2 ? ` x${cards[c]}` : ""}`,
54+
value: c,
55+
emoji: ComponentBuilder.emojiToPartial(cardEmotes[c])
56+
};
57+
}),
58+
{
59+
label: "Draw a card",
60+
value: "draw",
61+
emoji: ComponentBuilder.emojiToPartial("🃏")
62+
}
63+
];
64+
65+
if (game.lastPlayer.id === game.currentPlayer
66+
&& game.settings.allowSkipping
67+
&& (game.players.length !== 2 || !wasLastTurnBlocked(game) || game.lastPlayer.duration >= 1)
68+
)
69+
entries.push({
70+
label: "Skip your turn",
71+
value: "skip",
72+
emoji: ComponentBuilder.emojiToPartial("➡")
73+
});
74+
75+
if (entries.length > 50) {
76+
game.players.splice(game.players.indexOf(id), 1);
77+
sendMessage(game.channelID, `Removed **${getUsername(id, true, client.guilds.get(game.guildID))}**`);
78+
if (game.players.length <= 1) return;
79+
if (game.currentPlayer === id) {
80+
game.currentPlayer = next(game.players, game.players.indexOf(game.currentPlayer));
81+
game.lastPlayer.duration = 0;
82+
}
83+
sendGameMessage(game);
84+
return false;
85+
}
86+
87+
const row = new ComponentBuilder<MessageActionRow>();
88+
row.addSelectMenu({
89+
customID: SelectIDs.CHOOSE_CARD,
90+
placeholder: "Choose a card",
91+
type: ComponentTypes.STRING_SELECT,
92+
options: entries.slice(0, 25)
93+
});
94+
if (entries.length > 25) row.addSelectMenu({
95+
customID: SelectIDs.CHOOSE_CARD_ABOVE_25,
96+
placeholder: "Choose a card",
97+
type: ComponentTypes.STRING_SELECT,
98+
options: entries.slice(25)
99+
});
100+
101+
return row.toJSON();
102+
}
74103

75104
export const DrawStackedCardSelect = (game: UnoGame<true>, cards: { [k in Card]?: number }) => new ComponentBuilder<MessageActionRow>()
76105
.addSelectMenu({
@@ -177,7 +206,7 @@ export const cardArrayToCount = (a: Card[]) => a
177206
.sort((a, b) => cards.indexOf(a) - cards.indexOf(b))
178207
.reduce((obj, c) => {
179208
obj[c] = (obj[c] + 1) || 1; return obj;
180-
}, {} as { [k in Card]: number; });
209+
}, {} as { [k in Card]?: number; });
181210

182211
export const getPlayerMember = (game: UnoGame<boolean>, player: string) => game.message.channel.guild.members.get(player);
183212

0 commit comments

Comments
 (0)