Improved memory usage

Added permission checks on command use
Fixed Unknown Message error
Added console and stop command
some more
This commit is contained in:
AffluentAvo
2020-08-04 22:55:22 +02:00
parent 0225b2675a
commit 4034e235b3
3 changed files with 271 additions and 194 deletions
+55 -18
View File
@@ -2,37 +2,74 @@ import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder;
import net.dv8tion.jda.api.sharding.ShardManager;
import javax.security.auth.login.LoginException;
import java.io.IOException;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Scanner;
public class Bot {
static HashMap<Guild, String> prefixes = new HashMap<Guild, String>();
static HashMap<Long, String> prefixes = new HashMap<>();
public static void main(String[] args) throws LoginException, IOException {
DefaultShardManagerBuilder builder = new DefaultShardManagerBuilder();
String token = new String(Files.readAllBytes(Paths.get("token.txt")));
builder.setToken(token);
private static ShardManager shardManager;
public static void main(String[] args) throws LoginException {
String token = null;
try {
File tokenFile = Paths.get("token.txt").toFile();
if (!tokenFile.exists()) {
System.out.println("[ERROR] Could not find token.txt file");
System.out.println("[ERROR] Please create a file called \"token.txt\" in the same folder as the jar " + "file and paste in your bot token.");
return;
}
token = new String(Files.readAllBytes(tokenFile.toPath()));
} catch (Exception ex) {
ex.printStackTrace();
}
if (token == null) return;
DefaultShardManagerBuilder builder = DefaultShardManagerBuilder.createDefault(token);
builder.setStatus(OnlineStatus.ONLINE);
builder.setActivity(Activity.playing("@Sokobot for info!"));
builder.addEventListeners(new Commands());
builder.build();
shardManager = builder.build();
Thread consoleThread = new Thread(() -> {
Scanner s = new Scanner(System.in);
while (s.hasNextLine()) {
processCommand(s.nextLine());
}
});
consoleThread.setDaemon(true);
consoleThread.setName("Console Thread");
consoleThread.start();
}
static void setPrefix(Guild guild, String prefix)
{
prefixes.put(guild, prefix);
}
static String getPrefix(Guild guild)
{
if (!prefixes.containsKey(guild))
{
return "!";
private static void processCommand(String cmd) {
if (cmd.equalsIgnoreCase("help")) {
System.out.println("Commands:\nstop - Shuts down the bot and exits the program");
return;
}
return prefixes.get(guild);
if (cmd.equalsIgnoreCase("stop")) {
System.out.println("Shutting down...");
shardManager.shutdown();
System.out.println("Bye!");
System.exit(0);
return;
}
System.out.println("Unknown command. Please use \"help\" for a list of commands.");
}
public static ShardManager getShardManager() {
return shardManager;
}
static void setPrefix(Guild guild, String prefix) {
prefixes.put(guild.getIdLong(), prefix);
}
static String getPrefix(Guild guild) {
return prefixes.getOrDefault(guild.getIdLong(), "!");
}
}
+177 -130
View File
@@ -1,172 +1,219 @@
import com.vdurmont.emoji.EmojiManager;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.guild.GuildLeaveEvent;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.events.message.guild.react.GuildMessageReactionAddEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import com.vdurmont.emoji.EmojiManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.*;
public class Commands extends ListenerAdapter {
HashMap<User, Game> games = new HashMap<User, Game>();
ArrayList<String> commandsPrefix = new ArrayList<String>(Arrays.asList("play", "continue", "stop"));
ArrayList<String> commandsNoPrefix = new ArrayList<String>(Arrays.asList("w", "a", "s", "d", "up", "left", "down", "right", "r"));
public void onGuildLeave(GuildLeaveEvent event) //removes bot's stored prefix for a server if removed from that server
{
if (Bot.prefixes.containsKey(event.getGuild()))
{
Bot.prefixes.remove(event.getGuild());
}
HashMap<Long, Game> games = new HashMap<>();
ArrayList<String> commandsPrefix = new ArrayList<>(Arrays.asList("play", "continue", "stop"));
ArrayList<String> commandsNoPrefix = new ArrayList<>(Arrays.asList("w", "a", "s", "d", "up", "left", "down",
"right", "r"));
@Override
public void onGuildLeave(GuildLeaveEvent event) {
Guild guild = event.getGuild();
Bot.prefixes.remove(guild.getIdLong());
}
@Override
public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
if (event.getAuthor().equals(event.getJDA().getSelfUser()) && event.getMessage().getEmbeds().size() > 0 && event.getMessage().getEmbeds().get(0).getTitle().length() > 0 && event.getMessage().getEmbeds().get(0).getTitle().charAt(0) == 'L') {
event.getMessage().addReaction("U+2B05").queue();
event.getMessage().addReaction("U+27A1").queue();
event.getMessage().addReaction("U+2B06").queue();
event.getMessage().addReaction("U+2B07").queue();
event.getMessage().addReaction("U+1F504").queue();
if (games.containsKey(event.getJDA().getUserById(event.getMessage().getEmbeds().get(0).getFields().get(0).getValue().substring(10, event.getMessage().getEmbeds().get(0).getFields().get(0).getValue().length() - 1))))
{
games.get(event.getJDA().getUserById(event.getMessage().getEmbeds().get(0).getFields().get(0).getValue().substring(10, event.getMessage().getEmbeds().get(0).getFields().get(0).getValue().length() - 1))).setGameMessage(event.getMessage());
User user = event.getAuthor();
Member member = event.getMember();
Message message = event.getMessage();
TextChannel channel = event.getChannel();
Guild guild = event.getGuild();
String prefix = Bot.getPrefix(guild);
if (user.getId().equals(event.getJDA().getSelfUser().getId())) {
List<MessageEmbed> embeds = message.getEmbeds();
if (embeds.size() > 0) {
MessageEmbed embed = embeds.get(0);
if (embed.getTitle() != null && embed.getTitle().length() > 0) {
if (embed.getTitle().startsWith("Sokobot | Level ")) {
message.addReaction("U+2B05").queue();
message.addReaction("U+27A1").queue();
message.addReaction("U+2B06").queue();
message.addReaction("U+2B07").queue();
message.addReaction("U+1F504").queue();
MessageEmbed.Footer footerObject = embed.getFooter();
if (footerObject != null) {
String footer = footerObject.getText();
if (footer != null) {
long playerId = Long.parseLong(footer.substring(10, footer.length() - 1));
if (games.containsKey(playerId)) {
Game game = games.get(playerId);
game.setGameMessage(message);
}
}
}
}
}
}
return;
}
String[] args = event.getMessage().getContentRaw().split("\\s+");
if (args.length > 0 && args[0].toLowerCase().equals(Bot.getPrefix(event.getGuild()) + "prefix"))
{
if (event.getMember().hasPermission(Permission.ADMINISTRATOR)) {
if (args.length == 2 && args[1].length() == 1) {
Bot.setPrefix(event.getGuild(), args[1].toLowerCase());
event.getChannel().sendMessage("Prefix successfully changed to ``" + Bot.getPrefix(event.getGuild()) + "``.").queue();
} else {
event.getChannel().sendMessage("``" + args[1] + "`` is not a valid prefix!").queue();
String[] args = message.getContentRaw().split("\\s+");
if (args.length > 0) {
String arg = args[0].toLowerCase();
if (arg.equals(prefix + "prefix")) {
if (!hasPermissions(guild, channel)) {
sendInvalidPermissionsMessage(user, channel);
return;
}
}
else
{
event.getChannel().sendMessage(event.getAuthor().getAsMention() + ", you do not have permission to use this command.").queue();
}
event.getMessage().delete().queue();
}
else if (args.length > 0 && ((commandsNoPrefix.contains(args[0].toLowerCase())) || (args[0].length() > 0 && Character.toString(args[0].toLowerCase().charAt(0)).equals(Bot.getPrefix(event.getGuild())) && commandsPrefix.contains(args[0].toLowerCase().substring(1)))))
{
if (!games.containsKey(event.getAuthor()))
{
games.put(event.getAuthor(), new Game(event.getAuthor()));
}
String userInput = args[0].toLowerCase();
if (Character.toString(userInput.charAt(0)).equals(Bot.getPrefix(event.getGuild())))
{
userInput = userInput.substring(1, userInput.length());
}
if (!games.get(event.getAuthor()).gameActive && userInput.equals("play") && args.length == 2 && EmojiManager.isEmoji(args[1]))
{
System.out.println(args[1]);
games.get(event.getAuthor()).setPlayerEmote(args[1]);
}
games.get(event.getAuthor()).run(event.getGuild(), event.getChannel(), userInput);
if (userInput.equals("stop")) //remove game from hashmap when player quits
{
if (games.containsKey(event.getAuthor()))
{
games.remove(event.getAuthor());
if (member.hasPermission(Permission.ADMINISTRATOR)) {
if (args.length == 2 && args[1].length() == 1) {
String newPrefix = args[1].toLowerCase();
Bot.setPrefix(event.getGuild(), newPrefix);
channel.sendMessage("Prefix successfully changed to ``" + newPrefix + "``.").queue();
} else channel.sendMessage("The prefix must be one character long!").queue();
} else
channel.sendMessage(user.getAsMention() + ", you do not have permission to use this " + "command" + ".").queue();
// No need to delete prefix-set command
// message.delete().queue();
} else if (((commandsNoPrefix.contains(arg)) || (arg.length() > 0 && Character.toString(arg.charAt(0)).equals(prefix) && commandsPrefix.contains(arg.substring(1))))) {
if (!hasPermissions(guild, channel)) {
sendInvalidPermissionsMessage(user, channel);
return;
}
Game game;
if (!games.containsKey(user.getIdLong())) {
game = new Game(user);
games.put(user.getIdLong(), game);
} else game = games.get(user.getIdLong());
String userInput = arg;
if (userInput.substring(0, 1).equals(prefix)) userInput = userInput.substring(1);
if (!game.gameActive && userInput.equals("play") && args.length == 2 && EmojiManager.isEmoji(args[1])) {
game.setPlayerEmote(args[1]);
}
game.run(event.getGuild(), channel, userInput);
if (userInput.equals("stop")) games.remove(user.getIdLong());
if (guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_MANAGE)) message.delete().queue();
} else if ((arg.equals(prefix + "info")) || (message.getMentionedUsers().size() > 0 && message.getMentionedUsers().get(0).equals(event.getJDA().getSelfUser()))) {
if (!hasPermissions(guild, channel)) {
sendInvalidPermissionsMessage(user, channel);
return;
}
channel.sendMessage(info(event.getGuild()).build()).queue();
if (guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_MANAGE)) message.delete().queue();
}
event.getMessage().delete().queue();
}
else if ((args.length > 0 && args[0].toLowerCase().equals(Bot.getPrefix(event.getGuild()) + "info")) || (event.getMessage().getMentionedUsers().size() > 0 && event.getMessage().getMentionedUsers().get(0).equals(event.getJDA().getSelfUser())))
{
event.getChannel().sendMessage(info(event.getGuild()).build()).queue();
event.getMessage().delete().queue();
}
}
public void onGuildMessageReactionAdd(GuildMessageReactionAddEvent event)
{
if (event.getMember().getUser().isBot())
{
private static final Collection<Permission> requiredPermissions = Arrays.asList(Permission.MESSAGE_ADD_REACTION,
Permission.MESSAGE_EMBED_LINKS, Permission.MESSAGE_MANAGE, Permission.MESSAGE_WRITE);
private boolean hasPermissions(Guild guild, TextChannel channel) {
Member self = guild.getSelfMember();
if (self.hasPermission(Permission.ADMINISTRATOR)) return true;
return self.hasPermission(channel, requiredPermissions);
}
private void sendInvalidPermissionsMessage(User user, TextChannel channel) {
if (channel.canTalk()) {
StringBuilder requiredPermissionsDisplay = new StringBuilder();
for (Permission requiredPermission : requiredPermissions) {
requiredPermissionsDisplay.append("`").append(requiredPermission.getName()).append("`, ");
}
if (requiredPermissionsDisplay.toString().endsWith(", "))
requiredPermissionsDisplay = new StringBuilder(requiredPermissionsDisplay.substring(0,
requiredPermissionsDisplay.length() - 2));
channel.sendMessage(user.getAsMention() + ", I don't have enough permissions to work properly.\nMake " +
"sure I have the following permissions: " + requiredPermissionsDisplay + "\nIf you think this is "
+ "an error, please contact a server administrator.").queue();
}
}
@Override
public void onGuildMessageReactionAdd(GuildMessageReactionAddEvent event) {
User user = event.getUser();
if (user.isBot()) {
return;
}
if (event.getChannel().retrieveMessageById(event.getMessageId()).complete().getAuthor().equals(event.getJDA().getSelfUser())) {
if (!games.containsKey(event.getMember().getUser()))
{
games.put(event.getMember().getUser(), new Game(event.getMember().getUser()));
Guild guild = event.getGuild();
MessageReaction reaction = event.getReaction();
TextChannel channel = event.getChannel();
channel.retrieveMessageById(event.getMessageId()).queue(message -> {
if (message.getAuthor().getId().equals(event.getJDA().getSelfUser().getId())) {
Game game;
if (!games.containsKey(user.getIdLong())) {
game = new Game(user);
games.put(user.getIdLong(), game);
} else game = games.get(user.getIdLong());
boolean reactionCommand = true;
String userInput = "";
switch (event.getReactionEmote().toString()) {
case "RE:U+2b05":
userInput = "left";
break;
case "RE:U+27a1":
userInput = "right";
break;
case "RE:U+2b06":
userInput = "up";
break;
case "RE:U+2b07":
userInput = "down";
break;
case "RE:U+1f504":
userInput = "r";
break;
default:
reactionCommand = false;
break;
}
if (reactionCommand) game.run(guild, channel, userInput);
reaction.removeReaction(user).queue();
}
boolean reactionCommand = true;
String userInput = "";
switch (event.getReactionEmote().toString())
{
case "RE:U+2b05":
userInput = "left";
break;
case "RE:U+27a1":
userInput = "right";
break;
case "RE:U+2b06":
userInput = "up";
break;
case "RE:U+2b07":
userInput = "down";
break;
case "RE:U+1f504":
userInput = "r";
break;
default:
reactionCommand = false;
break;
}
if (reactionCommand) {
games.get(event.getMember().getUser()).run(event.getGuild(), event.getChannel(), userInput);
}
event.getReaction().removeReaction(event.getUser()).queue();
}
});
}
EmbedBuilder info(Guild guild)
{
EmbedBuilder info(Guild guild) {
EmbedBuilder info = new EmbedBuilder();
info.setTitle("Sokobot");
info.setThumbnail("https://cdn.discordapp.com/avatars/713635251703906336/4094ba90942077c27549cccbd54cecd4.png?size=128");
info.setThumbnail(guild.getSelfMember().getUser().getAvatarUrl());
info.setDescription("Sokobot is a bot that lets you play Sokoban, the classic box-pushing puzzle game.");
info.setColor(0xdd2e53);
info.addField("How to Play", "You are a **Sokoban** :flushed:.\nYour job is to push **boxes** :brown_square: on top of their **destinations** :negative_squared_cross_mark:.", false);
info.addField("Features", ":white_small_square:**Infinite levels**\nThe maps in Sokobot are randomly generated, increasing in difficulty as you progress.\n:white_small_square:**Varied controls**\nSokobot has multiple control options to improve the player's experience, including reactions and wasd commands!\n:white_small_square:**Simultaneous games**\nThanks to the power of Java HashMaps:tm:, multiple users can use the bot at the same time without interfering with one another.\n:white_small_square:**Custom prefixes**\nTo prevent Sokobot from conflicting with other bots, admins can choose any single-character prefix to preface Sokobot's commands.", false);
info.addField("Commands", ("``" + Bot.getPrefix(guild) + "play`` can be used to start a game if you are not currently in one.\n``" + Bot.getPrefix(guild) + "stop`` can be used to stop your active game at any time.\n``" + Bot.getPrefix(guild) + "info`` provides some useful details about the bot and rules of the game.\n``"+ Bot.getPrefix(guild) + "prefix [character]`` can be used to change the prefix the bot responds to."), false);
info.addField("Add to your server", "https://top.gg/bot/713635251703906336\nSokobot is currently in " + guild.getJDA().getShardManager().getGuilds().size() + " servers.", false);
info.addField("How to Play", "You are a **Sokoban** :flushed:.\nYour job is to push **boxes** :brown_square: "
+ "on top of their **destinations** :negative_squared_cross_mark:.", false);
info.addField("Features", ":white_small_square:**Infinite levels**\nThe maps in Sokobot are randomly " +
"generated, increasing in difficulty as you progress.\n:white_small_square:**Varied " + "controls" +
"**\nSokobot has multiple control options to improve the player's experience, including " +
"reactions and wasd commands!\n:white_small_square:**Simultaneous games**\nThanks to the power of " + "Java HashMaps:tm:, multiple users can use the bot at the same time without interfering with one " + "another.\n:white_small_square:**Custom prefixes**\nTo prevent Sokobot from conflicting with other " + "bots, admins can choose any single-character prefix to preface Sokobot's commands.", false);
info.addField("Commands",
("``" + Bot.getPrefix(guild) + "play`` can be used to start a game if you are not " + "currently in " + "one.\n``" + Bot.getPrefix(guild) + "stop`` can be used to stop your active game at any " + "time.\n``" + Bot.getPrefix(guild) + "info`` provides some useful details about the bot and " + "rules of " + "the game.\n``" + Bot.getPrefix(guild) + "prefix [character]`` can be used to " + "change the prefix the " + "bot responds to."), false);
info.addField("Add to your server",
"https://top.gg/bot/713635251703906336\nSokobot is currently in " + Bot.getShardManager().getGuilds().size() + " servers.", false);
info.addField("Source code", "https://github.com/PolyMarsDev/Sokobot", false);
info.setFooter("created by PolyMars", "https://avatars0.githubusercontent.com/u/51007356?s=460&u=4eb8fd498421a2eee9781edfbadf654386cf06c7&v=4");
info.setFooter("created by PolyMars", "https://avatars0.githubusercontent" + ".com/u/51007356?s=460&u" +
"=4eb8fd498421a2eee9781edfbadf654386cf06c7&v=4");
return info;
}
public static void sendGameEmbed(MessageChannel channel, String level, String game, User user)
{
public static void sendGameEmbed(MessageChannel channel, String level, String game, User user) {
EmbedBuilder embed = new EmbedBuilder();
embed.setTitle("Level " + level);
embed.setTitle("Sokobot | Level " + level);
embed.setDescription(game);
embed.addField("Enter direction (``up``, ``down``, ``left``, ``right``/``wasd``) or ``r`` to reset", "Player: " + user.getAsMention(), false);
embed.addField("Enter direction (``up``, ``down``, ``left``, ``right``/``wasd``) or ``r`` to reset", "", false);
embed.setFooter("Game of " + user.getAsMention(), user.getAvatarUrl());
channel.sendMessage(embed.build()).queue();
}
public static void updateGameEmbed(Message message, String level, String game, User user)
{
public static void updateGameEmbed(Message message, String level, String game, User user) {
EmbedBuilder embed = new EmbedBuilder();
embed.setTitle("Level " + level);
embed.setTitle("Sokobot | Level " + level);
embed.setDescription(game);
embed.addField("Enter direction (``up``, ``down``, ``left``, ``right``/``wasd``) or ``r`` to reset", "Player: " + user.getAsMention(), false);
embed.addField("Enter direction (``up``, ``down``, ``left``, ``right``/``wasd``) or ``r`` to reset", "", false);
embed.setFooter("Game of " + user.getAsMention(), user.getAvatarUrl());
message.editMessage(embed.build()).queue();
}
public static void sendWinEmbed(Guild guild, Message message, String level)
{
public static void sendWinEmbed(Guild guild, Message message, String level) {
EmbedBuilder embed = new EmbedBuilder();
embed.setTitle("You win!");
embed.setTitle("Sokobot | You win!");
embed.setDescription("Type ``" + Bot.getPrefix(guild) + "continue`` to continue to Level " + level + " or ``" + Bot.getPrefix(guild) + "stop`` to quit ");
embed.setFooter("You can also press any reaction to continue.");
message.editMessage(embed.build()).queue();
+39 -46
View File
@@ -1,10 +1,8 @@
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.*;
public class Game {
Message gameMessage;
long gameMessageID;
long channelID;
User user;
String playerEmote = ":flushed:";
public boolean gameActive = false;
@@ -12,67 +10,59 @@ public class Game {
int width = 9;
int height = 6;
Grid grid = new Grid(width, height, level, playerEmote);
public Game(User user)
{
public Game(User user) {
this.user = user;
}
public void setPlayerEmote(String emote)
{
public void setPlayerEmote(String emote) {
playerEmote = emote;
}
public void setGameMessage(Message message)
{
gameMessage = message;
public void setGameMessage(Message gameMessage) {
// To avoid an Unknown Message error, we will store the IDs and retrieve the Channel object when needed.
gameMessageID = gameMessage.getIdLong();
channelID = gameMessage.getChannel().getIdLong();
}
public void newGame(MessageChannel channel)
{
if (!gameActive)
{
public void newGame(MessageChannel channel) {
if (!gameActive) {
level = 1;
width = 9;
height = 6;
grid = new Grid(width, height, level, playerEmote);
gameActive = true;
Commands.sendGameEmbed(channel, String.valueOf(level), grid.toString(), user);
}
}
public void run(Guild guild, MessageChannel channel, String userInput)
{
if (userInput.equals("stop") && gameActive)
{
channel.sendMessage("Thanks for playing, " + user.getAsMention() + "!").queue();
gameActive = false;
public void run(Guild guild, TextChannel channel, String userInput) {
if (userInput.equals("stop") && gameActive) {
channel.sendMessage("Thanks for playing, " + user.getAsMention() + "!").queue();
gameActive = false;
}
if (userInput.equals("play") && !gameActive)
{
if (userInput.equals("play") && !gameActive) {
newGame(channel);
}
else if (gameActive)
{
} else if (gameActive) {
if (!grid.hasWon()) {
String direction = userInput;
if (direction.equals("up") || direction.equals("w"))
{
if (direction.equals("up") || direction.equals("w")) {
grid.getPlayer().moveUp();
} else if (direction.equals("down") || direction.equals("s"))
{
} else if (direction.equals("down") || direction.equals("s")) {
grid.getPlayer().moveDown();
} else if (direction.equals("left") || direction.equals("a"))
{
} else if (direction.equals("left") || direction.equals("a")) {
grid.getPlayer().moveLeft();
} else if (direction.equals("right") || direction.equals("d"))
{
} else if (direction.equals("right") || direction.equals("d")) {
grid.getPlayer().moveRight();
} else if (direction.equals("r"))
{
} else if (direction.equals("r")) {
grid.reset();
}
if (!grid.hasWon()) { //need to check again
Commands.updateGameEmbed(gameMessage, String.valueOf(level), grid.toString(), user);
if (!grid.hasWon()) {
TextChannel textChannel = Bot.getShardManager().getTextChannelById(channelID);
if (textChannel != null) {
textChannel.retrieveMessageById(gameMessageID).queue(gameMessage -> Commands.updateGameEmbed(gameMessage, String.valueOf(level), grid.toString(), user));
}
}
}
if (grid.hasWon()) {
@@ -80,13 +70,16 @@ public class Game {
if (width < 13) {
width += 2;
}
if (height < 8)
{
if (height < 8) {
height += 1;
}
Commands.sendWinEmbed(guild, gameMessage, String.valueOf(level));
TextChannel textChannel = Bot.getShardManager().getTextChannelById(channelID);
if (textChannel != null) {
textChannel.retrieveMessageById(gameMessageID).queue(gameMessage -> Commands.sendWinEmbed(guild,
gameMessage, String.valueOf(level)));
}
grid = new Grid(width, height, level, playerEmote);
}
}
}
}
}