diff --git a/commands/games/external_game_functions.js b/commands/games/external_game_functions.js index c95fd8e..6a84b3c 100644 --- a/commands/games/external_game_functions.js +++ b/commands/games/external_game_functions.js @@ -38,7 +38,7 @@ function loseGame(user_dbo, xp_collection, message, bot = null) { } -function winGame(client, bot, db, user_dbo, xp_collection, message) { +function winGame(client, bot, db, user_dbo, xp_collection, message, singlePlayer = false) { user_dbo.find({"game": {$exists: true}}).toArray(function(err, docs){ const doc = docs[0]; @@ -54,14 +54,18 @@ function winGame(client, bot, db, user_dbo, xp_collection, message) { } //Delete the bot's record of the game - client.db('B|S' + bot.user.id).collection(message.guild.id).drop(); + if (!singlePlayer) { + client.db('B|S' + bot.user.id).collection(message.guild.id).drop(); + } //Update the player with xp user_dbo.updateOne({"game": {$exists: true}}, { $set: { game: null, opponent: null, state: STATE.IDLE, xp: doc.xp + (BASE.XP * doc.rank), 'hpmp.hp': doc.hpmp.maxhp, 'hpmp.mp': doc.hpmp.maxmp }}); - const channel = bot.channels.cache.get(message.channel.parentId); - channel.send(`<@${user_dbo.s.namespace.collection}> just won a game of "${docs[0].game}"!`); + if (!singlePlayer) { + const channel = bot.channels.cache.get(message.channel.parentId); + channel.send(`<@${user_dbo.s.namespace.collection}> just won a game of "${docs[0].game}"!`); + } message.channel.delete(); }); } diff --git a/commands/games/game.js b/commands/games/game.js index 3528964..51f7e7d 100644 --- a/commands/games/game.js +++ b/commands/games/game.js @@ -7,6 +7,7 @@ let ecoimport = require("../db/econ.js"); const battle = require("./battle.js"); const ttt = require('./tictactoe.js'); const trivia = require('./trivia.js'); +const mnswpr = require('./minesweeper.js'); //#endregion @@ -29,9 +30,7 @@ const allGames = ['battle', 'Tic Tac Toe']; */ async function Initialize(bot, user_dbo, command, message, first, second, other_dbo = null) { return new Promise(async function(resolve, reject) { - user_dbo.find({"game": {$exists: true}}).toArray(function(err, docs){ - let doc = docs[0]; - console.log(command); + user_dbo.findOne({"game": {$exists: true}}).then(function(doc){ if (allGames.indexOf(command) != -1) { if (other_dbo != null) { user_dbo.updateOne( { "game": {$exists: true} }, { $set: { game: command, opponent: other_dbo.s.namespace.collection, state: STATE.FIGHTING }}); @@ -250,7 +249,7 @@ module.exports ={ //Check if the client is currently in a game and act accordingly //#region Check Game - dbo.find({"game": {$exists: true}}).toArray(async function(err, docs){ + dbo.find({"game": {$exists: true}}).toArray(async function(err, docs) { if (err) { return console.log(err); } let doc = docs[0]; let game = null; @@ -384,9 +383,20 @@ module.exports ={ message.channel.send(`${other_discord}, <@${message.author.id}> has invited you to play _"Tic Tac Toe"_. To accept, please reply to this message with _!game accept_`); } else if (game == 'trivia' || command == 'trivia') { trivia.execute(message, args, Discord, client, bot); + } else if (game == "minesweeper" || command == 'minesweeper') { + if (game == "minesweeper" && command == 'minesweeper') { + return message.reply("You're already in a game!"); + } + const threadname = `${message.author.username} has started a solo game of Minesweeper`; + const thread = await message.channel.threads.create({ + name: threadname, + // type: 'GUILD_PRIVATE_THREAD', + autoArchiveDuration: 60, + reason: `N/A`, + }); + mnswpr.handle(bot, null, thread, message, args); } - //Catch statement (invalid command) else { message.reply(`'${bot.prefix}game ${command}' is not a command!`); diff --git a/commands/games/minesweeper.js b/commands/games/minesweeper.js new file mode 100644 index 0000000..c00ce3c --- /dev/null +++ b/commands/games/minesweeper.js @@ -0,0 +1,161 @@ +const { MessageActionRow, MessageButton, Interaction } = require('discord.js'); +const { winGame, loseGame, equipItem } = require('./external_game_functions.js'); +const wait = require('node:timers/promises').setTimeout; +const { STATE } = require('../db/econ.js') + +function startGame(bot, channel, args) { + let componentlist = []; + var diff; + + if (args.length < 1 || args[0] == 'easy') { + diff = 0; + } else if (args[0] == 'medium') { + diff = 0.1; + } else if (args[0] == 'hard') { + diff = 0.2; + } else { + diff = 0; + } + + for (let i = 0; i < 5; i ++) { + const row = new MessageActionRow(); + + for (let j = 0; j < 5; j ++) { + //customId = (spot in row)|(spot in column) + const btn = new MessageButton(); + const isbmb = (Math.random() > (0.70 - diff)); + + if (isbmb) { + btn.setCustomId(`mswpr|${i}|${j}|t`); + } else { + btn.setCustomId(`mswpr|${i}|${j}|f`); + } + + btn.setLabel('?') + .setStyle('SECONDARY') + row.addComponents(btn); + } + + //Add the row to the list of rows + componentlist.push(row); + } + + channel.send({ content: `SCORE: \`0\`\nTILES LEFT: \`25\``, components: componentlist }); +} + + +function gameOver(interaction, won = false) { + var components = interaction.message.components; + + return new Promise((resolve, reject) => { + for (i in components) { + for (j in components[i].components) { + if (components[i].components[j].customId.split("|")[3] === 't') { + components[i].components[j].label = "💣"; + components[i].components[j].style = "DANGER"; + } else { + components[i].components[j].style = "SUCCESS"; + components[i].components[j].label = "5"; + } + + components[i].components[j].setDisabled(true); + } + } + + if (won) { + resolve(components); + } else { + interaction.message.edit({ components: components }); + } + }); +} + + +/** + * @param {Interaction} interaction + */ +async function changeBoard(bot, interaction, xp_collection) { + interaction.deferUpdate(); + const id = interaction.customId.split('|'); + + //"mswpr|y|x" + const col = id[1]; + const row = id[2]; + const isbmb = (id[3] === 't'); + + var components = interaction.message.components; + var btn = components[col].components[row]; + + if (isbmb) { + gameOver(interaction); + bot.mongoconnection.then((client) => { client.db(interaction.guildId).collection(interaction.user.id).updateOne({ game: {$exists: true} }, { $set: { game: null } }); }); + const channel = bot.channels.cache.get(interaction.message.channel.parentId); + channel.send(`${interaction.user} found a bomb in Minesweeper!`); + interaction.channel.send(`\`Thread closing\` `); + + await wait(7000); + interaction.channel.delete(); + } else { + btn.setDisabled(true); + btn.label = "1"; + btn.style = "SUCCESS"; + components[col].components[row] = btn; + + let content = interaction.message.content; + let score = Number(content.split('`')[1]); + let tLeft = Number(content.split('`')[3]); + + //Win the game (just clicked the last tile) + if (tLeft <= 1) { + gameOver(interaction, true).then(async (newComp) => { + interaction.message.edit({ content: `GAME WON!!!\nSCORE: \`${score + 1}\``, components: newComp }); + const channel = bot.channels.cache.get(interaction.message.channel.parentId); + channel.send(`${interaction.user} won a game of Minesweeper with a score of ${score + 1}!`); + interaction.channel.send(`\`Thread closing\` `); + + await wait(7000); + // interaction.channel.delete(); + bot.mongoconnection.then(client => { + const db = client.db(interaction.guildId); + const dbo = db.collection(interaction.user.id); + winGame(client, bot, db, dbo, xp_collection, interaction.message, true); + }); + }); + } else { + interaction.message.edit({ content: `SCORE: \`${score + 1}\`\nTILES LEFT: \`${tLeft - 1}\``, components: components }); + } + } +} + + +function checkAndStartGame(bot, message, channel, args) { + bot.mongoconnection.then(client => { + const db = client.db(message.guild.id); + const dbo = db.collection(message.author.id); + dbo.findOne({game: {$exists: true}}).then((doc) => { + try { + if (doc.game != null) { return message.reply("You're already in a game!"); } + + dbo.updateOne({ "game": {$exists: true} }, { $set: { game: "minesweeper", state: STATE.FIGHTING }}); + startGame(bot, channel, args); + } catch (err) { + console.log(err); + const { addComplaintButton } = require('../dev only/submitcomplaint.js'); + addComplaintButton(bot, message); + } + }); + }); +} + + +function handle(bot, interaction, channel = null, message = null, args = null, xp_collection = null) { + if (channel != null && args != null) { + checkAndStartGame(bot, message, channel, args); + } else { + //Maybe add player checking later? + changeBoard(bot, interaction, xp_collection); + } +} + + +module.exports = { handle } \ No newline at end of file diff --git a/commands/interactionhandler.js b/commands/interactionhandler.js index fbef3c1..78ba961 100644 --- a/commands/interactionhandler.js +++ b/commands/interactionhandler.js @@ -4,6 +4,7 @@ const { pause_start_stop, playNext, showQueue } = require('./misc/playAudio.js') const { resolveComplaint } = require('./dev only/submitcomplaint.js'); const reminders = require('./premium/reminders.js'); const tuto = require('../commands/Selmer Specific/intro'); +const mswpr = require('./games/minesweeper.js'); // const { RSSInteractionHandler } = require('./premium/rssFeed.js'); const { Interaction } = require('discord.js') @@ -85,6 +86,8 @@ async function handle_interaction(interaction, mongouri, turnManager, bot, STATE } else if (interaction.customId.indexOf("tutoQueue") != -1){ const page = Number(interaction.customId.split('|')[1]); tuto.postEmbd(bot, interaction, page, true); + } else if (interaction.customId.indexOf("mswpr|") != -1) { + mswpr.handle(bot, interaction, interaction.channel, interaction.message, null, xp_collection); } //Button else ifs here }); } diff --git a/index.html b/index.html new file mode 100644 index 0000000..aca9a2f --- /dev/null +++ b/index.html @@ -0,0 +1,44 @@ + + + + + + + + + + Selmer Bot Directory + + + + +
+
+ + +
+
+ +
Copyright @ION606 2022
+ + \ No newline at end of file