Skip to content

Groundwork for game logic complete #83

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 0 additions & 59 deletions config.example.json

This file was deleted.

2 changes: 1 addition & 1 deletion src/commands/google.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const googleModule: CommandType = {
const embed = new EmbedBuilder()
.setColor(Colors.Blue)
.setAuthor({
name: `Requested by ${interaction.user.displayName}`,
name: `Requested by ${interaction.user.nickname}`,
iconURL: `${interaction.user?.avatarURL()}`,
})
.setTimestamp();
Expand Down
235 changes: 235 additions & 0 deletions src/commands/minigame.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
import { logger, Config } from "@/config";
import { readFile } from 'fs';
import { EmbedBuilder, ActionRowBuilder, ButtonBuilder } from "@discordjs/builders";

import {
CacheType,
SlashCommandBuilder,
GuildMember,
ChatInputCommandInteraction,
Message,
Colors,
ComponentType,
Collection,
} from "discord.js";

// game config
const WORDBOMB_TURN_TIME = 10_000 // time each player gets in their turn
const JOIN_TIME = 8_000 // amt of time for people to join
const REQUIRED_PLAYERS = 1 // (CHANGE IN PRODUCTION) required players in order for the game to start and continue

// hello
// hi 🙂

function validateWord(word: string): Promise<boolean> {
return new Promise((resolve, reject) => {
readFile("data/wordlist.txt", (error, text) => {
if (error) {
logger.debug(error);
reject(error);
return;
}

const words = text.toString().split("\n").map((dWord) => dWord.trim());

let low: number = 0;
let high: number = words.length - 1;
while (low <= high) {
let mid: number = Math.floor((low + high) / 2);
let currentWord = words[mid];
if (currentWord === word) {
logger.info("found word: " + currentWord)
resolve(true);
return;
}

if (currentWord < word) {
low = mid + 1;
} else {
high = mid - 1;
}

}

resolve(false);
});
});
}

const minigameModule: CommandType = {
data: new SlashCommandBuilder()
.setName("minigame")
.setDescription("Play a minigame in the channel")
.addSubcommand((game : any) =>
game
.setName("wordbomb")
.setDescription("Find as much words as possible before time is up!")
),
execute: async (interaction: ChatInputCommandInteraction<CacheType>) => {
if (interaction.channel?.id !== Config.discord.bot_channel) {
return await interaction.reply(
{content: `You can only use this command in <#${Config.discord.bot_channel}>`,
ephemeral: true}
);
}

const subcommand = interaction.options.getSubcommand();
const {channel} = interaction

console.log(subcommand);

const embed = new EmbedBuilder()
.setColor(Colors.Blue)
.setTitle(`${"Word Bomb! 💣"}`)
.setDescription(`${"Click to join the Word-Bomb game!"}`)

const response = await interaction.reply({
embeds: [embed],
fetchReply: true,
});

if (subcommand === "wordbomb") {

type Player = {
Member: GuildMember,
Chances: number, // # number of chances until eliminated
CorrectGuess: Boolean,
}

let players: Array<Player> = []
let previousMessage: Message;

// Test Case Sigma
let sigmaValid = validateWord("sigma")
.then(async (valid) => {
if (valid) {
await interaction.reply("sigma is a word");
} else {
await interaction.reply("sigma is not a word");
}
})
.catch((error) => {
logger.debug(error);
})

const collector = interaction.channel.createMessageComponentCollector(
{
componentType: ComponentType.Button,
//filter: (i) => i.user,
time: JOIN_TIME,
}
)

collector.on("collect", async (i : ChatInputCommandInteraction) => {

if (players.find(p => p.Member.id === i.member.id)) {
return await i.reply({ content: "You are already in the game!", ephemeral: true});
}

players.push({
Member: i.member as GuildMember,
Chances: 2,
CorrectGuess: false
} as Player);

await i.reply({ content: "You have joined the game!", ephemeral: true});
})

const joinButton = new ButtonBuilder()
.setCustomId("join-minigame")
.setLabel("Join")
.setStyle(3);



const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
joinButton
);

await interaction.editReply({ embeds: [embed], components: [row] });

var resolveTurn : any
var currentPlayer : Player;
var refreshId : number;

async function wait(ms : number) : Promise<void> {
return new Promise(resolve => {
resolveTurn = resolve
setTimeout(resolve, ms)
})
}

setTimeout(async () => {

// checks for atleast two palyers
if (players.length < REQUIRED_PLAYERS){
interaction.channel.send(`Atleast 2 people are required for this game 😔`)
return
}

while (players.length >= REQUIRED_PLAYERS){
for (let i in players){

currentPlayer = players[i]
channel.send(`**its ${players[i].Member.user} turn!**`)

let guessedCorrectly : Boolean = false

const filter = (msg : Message) => (msg.member.id === players[i].Member.id );
const collector = channel.createMessageCollector({filter, time: WORDBOMB_TURN_TIME});
collector.on('collect', async (msg : Message) => {
let wordIsValid : Boolean = await validateWord(msg.content)
console.log(`${msg.content} is a valid word? : ${wordIsValid}` )

if (wordIsValid){
console.log("VALID WORD!")
collector.stop()
resolveTurn()
guessedCorrectly = true
channel.send(`**Correct! 👍**`)
}
});

await wait(WORDBOMB_TURN_TIME)
if (!guessedCorrectly){
currentPlayer.Chances -= 1

if (currentPlayer.Chances <= 0) {
const index = players.findIndex(p => p.Member.id == currentPlayer.Member.id)

if (index > -1){
players.splice(index, 1)
}else{
logger.info("could not find player")
}

channel.send(`**No more chances left, you have been Elimnated ❌**`)

} else{
channel.send(`Times up! 😕\n-1 Chance 👎`)
}

}

}
}

(players.length > 0) ?
interaction.channel.send(`The Winner is: ${players[0].Member.user} 🥳🏆`)
:
interaction.channel.send(`No one Won 😞`)



}, JOIN_TIME);


} else {
await interaction.editReply({ content: "Invalid game", embeds: [embed] });

}

}
}

export {minigameModule as command}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"lib": ["ES2022"],
"lib": ["ES2022", "DOM"],
"strict": true,
"allowJs": false,
"moduleResolution": "Node",
Expand Down