我正在尝试制作一个连接 4 的游戏,一切都很顺利,直到我要测试最终产品并且不知从哪里得到这个错误
Cannot read property 'members' of undefined TypeError: Cannot read property 'members' of undefined
at Object.module.exports.run (C:\Users\user\OneDrive\Skrivbord\HandlerBot\HandlerBot\commands\Fun\connect4.js:7:34)
at module.exports (C:\Users\user\OneDrive\Skrivbord\HandlerBot\HandlerBot\events\message\message.js:236:19)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
我不知道为什么会出现此错误,因为 message.mentions.members.first() 应该是正确的。这是connect4游戏的代码
const { MessageEmbed, MessageAttachment } = require('discord.js');
const Pagination = require('discord-paginationembed');
const Canvas = require('canvas');
module.exports.run = async (message) => {
let player1 = message.author;
let player2 = message.mentions.members.first()
if (player1.id === player2.id) {
return message.channel.send("Sorry can't play against yourself");
}
if (player2.bot) {
return message.channel.send("Sorry can't play against a bot user");
}
if (message.guild.gameData.connect4Players.has(player1.id)) {
message.reply("You can't play more than 1 game at a time");
return;
}
if (message.guild.gameData.connect4Players.has(player2.id)) {
message.reply(`${player2.username} is already playing`);
return;
}
const player1Avatar = player1.displayAvatarURL({
format: 'jpg'
});
const player1Piece =
player1Avatar.length > 0 ? await Canvas.loadImage(player1Avatar) : null;
const player2Avatar = player2.avatarURL({
format: 'jpg'
});
const player2Piece =
player1Avatar.length > 0 ? await Canvas.loadImage(player2Avatar) : null;
let gameBoard = [
[0, 0, 0, 0, 0, 0, 0], // row 6
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0] // row 1
// column ->
];
const row = {
0: [1, 2, 3, 4, 5, 6], // column 1
1: [1, 2, 3, 4, 5, 6],
2: [1, 2, 3, 4, 5, 6],
3: [1, 2, 3, 4, 5, 6],
4: [1, 2, 3, 4, 5, 6],
5: [1, 2, 3, 4, 5, 6],
6: [1, 2, 3, 4, 5, 6] // column 7
// row ->
};
let currentPlayer = player1.id;
let boardImageURL = null;
let currentTurn = 0;
await createBoard(message);
++currentTurn;
new Pagination.Embeds()
.setArray([new MessageEmbed()])
.setAuthorizedUsers([player1.id, player2.id])
.setThumbnail(player1Avatar)
.setChannel(message.channel)
.setColor('RED')
.setTitle(`Connect 4 - Player 1's Turn`)
.setDescription(
`Incase of invisible board click ?.
Use 1️⃣, 2️⃣, 3️⃣, etc... to place your colored disc in that column.
Thumbnail and Title indicate current players turn.
You have 1 minute per turn or it's an automatic forfeit.`
)
.setImage(boardImageURL)
.setFooter('Incase of invisible board click ?')
.setTimestamp()
.setTimeout(60000)
.setDisabledNavigationEmojis(['all'])
//.setDeleteOnTimeout(true)
.setFunctionEmojis({
// Column 1
'1️⃣': async function(user, instance) {
await playerMove(0, user, instance);
},
// Column 2
'2️⃣': async function(user, instance) {
await playerMove(1, user, instance);
},
// Column 3
'3️⃣': async function(user, instance) {
await playerMove(2, user, instance);
},
// Column 4
'4️⃣': async function(user, instance) {
await playerMove(3, user, instance);
},
// Column 5
'5️⃣': async function(user, instance) {
await playerMove(4, user, instance);
},
// Column 6
'6️⃣': async function(user, instance) {
await playerMove(5, user, instance);
},
// Column 7
'7️⃣': async function(user, instance) {
await playerMove(6, user, instance);
},
// Refresh Image
'?': function(_, instance) {
instance.setImage(boardImageURL);
}
})
.build();
function createBoard(message) {
// Set asset sizes
const boardHeight = 600;
const boardWidth = 700;
const pieceSize = 75 / 2;
const offset = 25 / 2;
// Set Image size
const canvas = Canvas.createCanvas(boardWidth, boardHeight);
const ctx = canvas.getContext('2d');
// Get Center to Center measurements for grid spacing
const positionX = boardWidth / 7;
const positionY = boardHeight / 6;
// Connect 4 Board
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, boardWidth, boardHeight);
// Build the Game Board
for (let columnIndex = 0; columnIndex < 7; ++columnIndex) {
for (let rowIndex = 0; rowIndex < 6; ++rowIndex) {
// Empty Spaces
if (gameBoard[rowIndex][columnIndex] === 0) {
ctx.beginPath();
ctx.shadowColor = 'white';
ctx.shadowBlur = 7;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.arc(
offset + (pieceSize + positionX * columnIndex),
offset + (pieceSize + positionY * rowIndex),
pieceSize,
0,
Math.PI * 2,
true
);
ctx.fillStyle = 'grey';
ctx.fill();
}
// Player 1 Pieces
if (gameBoard[rowIndex][columnIndex] === 1) {
ctx.beginPath();
ctx.shadowColor = 'grey';
ctx.shadowBlur = 7;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
if (player1Piece) {
ctx.save();
ctx.arc(
offset + (pieceSize + positionX * columnIndex),
offset + (pieceSize + positionY * rowIndex),
pieceSize,
0,
Math.PI * 2,
true
);
ctx.fillStyle = 'grey';
ctx.fill();
ctx.clip();
ctx.drawImage(
player1Piece,
offset + positionX * columnIndex,
offset + positionY * rowIndex,
pieceSize * 2,
pieceSize * 2
);
ctx.restore();
} else {
ctx.arc(
offset + (pieceSize + positionX * columnIndex),
offset + (pieceSize + positionY * rowIndex),
pieceSize,
0,
Math.PI * 2,
true
);
ctx.fillStyle = 'red';
ctx.fill();
}
}
// Player 2 Pieces
if (gameBoard[rowIndex][columnIndex] === 2) {
ctx.beginPath();
ctx.shadowColor = 'grey';
ctx.shadowBlur = 7;
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
if (player2Piece) {
ctx.save();
ctx.arc(
offset + (pieceSize + positionX * columnIndex),
offset + (pieceSize + positionY * rowIndex),
pieceSize,
0,
Math.PI * 2,
true
);
ctx.fillStyle = 'grey';
ctx.fill();
ctx.clip();
ctx.drawImage(
player2Piece,
offset + positionX * columnIndex,
offset + positionY * rowIndex,
pieceSize * 2,
pieceSize * 2
);
ctx.restore();
} else {
ctx.arc(
offset + (pieceSize + positionX * columnIndex),
offset + (pieceSize + positionY * rowIndex),
pieceSize,
0,
Math.PI * 2,
true
);
ctx.fillStyle = 'blue';
ctx.fill();
}
}
}
}
const attachment = new MessageAttachment(
canvas.toBuffer(),
`connect4Game${player1.id}-${player2.id}${currentTurn}.png` // to prevent cross-talk when multiple games are running at the same time in the same channel
);
return message.channel
.send(attachment)
.then(result => {
boardImageURL = result.attachments.entries().next().value[1].url;
result.delete();
})
.catch(err => {
if (err) {
console.log(err);
}
});
}
async function playerMove(index, user, instance) {
if (row[index].length === 0 || currentPlayer === 'Game Over') {
return; // Ignore Columns that are full or if the game is over
}
if (currentPlayer === user.id) {
row[index].pop();
if (currentPlayer === player1.id) {
gameBoard[row[index].length][index] = 1;
currentPlayer = player2.id;
instance
.setThumbnail(player2Avatar)
.setTitle(`Connect 4 - Player 2's Turn`)
.setColor('BLUE')
.setTimestamp();
} else {
gameBoard[row[index].length][index] = 2;
currentPlayer = player1.id;
instance
.setThumbnail(player1Avatar)
.setTitle(`Connect 4 - Player 1's Turn`)
.setColor('RED')
.setTimestamp();
}
await createBoard(message);
++currentTurn;
}
if (checkWinner(gameBoard) === 0) {
// No More Possible Moves
if (!emptySpaces(gameBoard)) {
instance
.setTitle(`Connect 4 - Game Over`)
.setColor('GREY')
.setThumbnail('');
currentPlayer = 'Game Over';
message.guild.gameData.connect4Players.delete(player1.id);
message.guild.gameData.connect4Players.delete(player2.id);
}
return instance.setImage(boardImageURL).setTimestamp();
} else {
instance
.setImage(boardImageURL)
.setTitle(`Connect 4 - ? Player ${checkWinner(gameBoard)} Wins! ?`)
.setTimestamp();
if (currentPlayer === player1.id) {
instance.setThumbnail(player2Avatar).setColor('BLUE');
} else {
instance.setThumbnail(player1Avatar).setColor('RED');
}
currentPlayer = 'Game Over';
message.guild.gameData.connect4Players.delete(player1.id);
message.guild.gameData.connect4Players.delete(player2.id);
return;
}
}
// Check for available spaces
function emptySpaces(board) {
let result = false;
for (let columnIndex = 0; columnIndex < 7; ++columnIndex) {
for (let rowIndex = 0; rowIndex < 6; ++rowIndex) {
if (board[rowIndex][columnIndex] == 0) {
result = true;
}
}
}
return result;
}
// Reference https://stackoverflow.com/questions/15457796/four-in-a-row-logic/15457826#15457826
// Check for Win Conditions
function checkLine(a, b, c, d) {
// Check first cell non-zero and all cells match
return a != 0 && a == b && a == c && a == d;
}
function checkWinner(board) {
// Check down
for (let r = 0; r < 3; r++)
for (let c = 0; c < 7; c++)
if (
checkLine(
board[r][c],
board[r + 1][c],
board[r + 2][c],
board[r + 3][c]
)
)
return board[r][c];
// Check right
for (let r = 0; r < 6; r++)
for (let c = 0; c < 4; c++)
if (
checkLine(
board[r][c],
board[r][c + 1],
board[r][c + 2],
board[r][c + 3]
)
)
return board[r][c];
// Check down-right
for (let r = 0; r < 3; r++)
for (let c = 0; c < 4; c++)
if (
checkLine(
board[r][c],
board[r + 1][c + 1],
board[r + 2][c + 2],
board[r + 3][c + 3]
)
)
return board[r][c];
// Check down-left
for (let r = 3; r < 6; r++)
for (let c = 0; c < 4; c++)
if (
checkLine(
board[r][c],
board[r - 1][c + 1],
board[r - 2][c + 2],
board[r - 3][c + 3]
)
)
return board[r][c];
return 0;
}
};
module.exports.help = {
name: 'connect4',
aliases: ['connect4',],
category: 'fun',
description: 'Play a game of Connect 4 against a friend',
cooldown: 5,
usage: '@user',
example: ["connect4 @iLikeBouncyBalls"],
moderator: false,
isUserAdmin: false,
args: true,
userPermissions: [],
botPermissions: [],
}
这里也是游戏保存的代码
module.exports = client => {
client.gameData = {
connect4Players = new Map(),
tictactoePlayers = new Map()
};
}
exports.gameData = gameData;
这里是 console.log(message) 的完整日志
'411445025042464768' => [User],//a bunch more of users
}
},
guilds: GuildManager {
cacheType: [class Collection extends Collection],
cache: Collection(12) [Map] {
'818930375488962611' => [Guild], //a bunch more of guilds
}
},
channels: ChannelManager {
cacheType: [class Collection extends Collection],
cache: Collection(344) [Map] {
'822478699587829760' => [NewsChannel],
'827539969333264404' => [CategoryChannel],//a bunch more of channels
}
},
presence: ClientPresence {
userID: null,
guild: null,
status: 'online',
activities: [ [Activity] ],
clientStatus: null
},
user: ClientUser {
id: '818983820866879498',
system: null,
locale: null,
flags: UserFlags { bitfield: 0 },
username: 'Handler Bot',
bot: true,
discriminator: '7798',
avatar: 'cc419dac6d34ab3280e43acde193ee36',
lastMessageID: null,
lastMessageChannelID: null,
verified: true,
mfaEnabled: true,
_typing: Map(0) {}
},
readyAt: 2021-06-02T11:01:31.641Z,
createGuild: [AsyncFunction (anonymous)],
deleteGuild: [AsyncFunction (anonymous)],
getGuild: [AsyncFunction (anonymous)],
updateGuild: [AsyncFunction (anonymous)],
createUser: [AsyncFunction (anonymous)],
getUser: [AsyncFunction (anonymous)],
getUsers: [AsyncFunction (anonymous)],
updateUser: [AsyncFunction (anonymous)],
addExp: [AsyncFunction (anonymous)],
removeExp: [AsyncFunction (anonymous)],
console: [Function (anonymous)],
resolveMember: [AsyncFunction (anonymous)],
resolveUser: [Function (anonymous)],
resolveChannel: [Function (anonymous)],
resolveGuild: [Function (anonymous)],
resolveRole: [Function (anonymous)],
isUnicode: [Function (anonymous)],
resolveGuildEmoji: [AsyncFunction (anonymous)],
checkMod: [AsyncFunction (anonymous)],
mongoose: { init: [Function: init] },
commands: Collection(56) [Map] {
'charge' => { run: [AsyncFunction (anonymous)], help: [Object] },
'eval' => { run: [AsyncFunction (anonymous)], help: [Object] },
'exe' => { run: [AsyncFunction (anonymous)], help: [Object] },
'execute' => { run: [AsyncFunction (anonymous)], help: [Object] },
'premium' => { run: [AsyncFunction (anonymous)], help: [Object] },
'pull' => { run: [AsyncFunction (anonymous)], help: [Object] },
'reload' => { run: [AsyncFunction (anonymous)], help: [Object] },
'restart' => { run: [AsyncFunction (anonymous)], help: [Object] },
'8ball' => { run: [Function (anonymous)], help: [Object] },
'akinator' => { run: [AsyncFunction (anonymous)], help: [Object] },
'avatar' => { run: [AsyncFunction (anonymous)], help: [Object] },
'connect4' => { run: [AsyncFunction (anonymous)], help: [Object] },
'info' => { run: [AsyncFunction (anonymous)], help: [Object] },
'poll' => { run: [AsyncFunction (anonymous)], help: [Object] },
'rip' => { run: [AsyncFunction (anonymous)], help: [Object] },
'say' => { run: [Function (anonymous)], help: [Object] },
'test' => { run: {}, help: [Object] },
'twitch' => { run: [AsyncFunction (anonymous)], help: [Object] },
'weather' => { run: [AsyncFunction (anonymous)], help: [Object] },
'gend' => { run: [AsyncFunction (anonymous)], help: [Object] },
'giveaway' => { run: [AsyncFunction (anonymous)], help: [Object] },
'greroll' => { run: [AsyncFunction (anonymous)], help: [Object] },
'gstart' => { run: [AsyncFunction (anonymous)], help: [Object] },
'leaderboard' => { run: [AsyncFunction (anonymous)], help: [Object] },
'rank' => { run: [AsyncFunction (anonymous)], help: [Object] },
'xp' => { run: [AsyncFunction (anonymous)], help: [Object] },
'channel' => { run: [AsyncFunction (anonymous)], help: [Object] },
'commands' => { run: [AsyncFunction (anonymous)], help: [Object] },
'emojis' => { run: [AsyncFunction (anonymous)], help: [Object] },
'modroles' => { run: [AsyncFunction (anonymous)], help: [Object] },
'reactionroles' => { run: [AsyncFunction (anonymous)], help: [Object] },
'roles' => { run: [AsyncFunction (anonymous)], help: [Object] },
'server' => { run: [Function (anonymous)], help: [Object] },
'ban' => { run: [AsyncFunction (anonymous)], help: [Object] },
'filter' => { run: [AsyncFunction (anonymous)], help: [Object] },
'kick' => { run: [AsyncFunction (anonymous)], help: [Object] },
'lock' => { run: [AsyncFunction (anonymous)], help: [Object] },
'mute' => { run: [AsyncFunction (anonymous)], help: [Object] },
'nick' => { run: [AsyncFunction (anonymous)], help: [Object] },
'purge' => { run: [AsyncFunction (anonymous)], help: [Object] },
'slowmode' => { run: [AsyncFunction (anonymous)], help: [Object] },
'softban' => { run: [AsyncFunction (anonymous)], help: [Object] },
'unban' => { run: [AsyncFunction (anonymous)], help: [Object] },
'unlock' => { run: [AsyncFunction (anonymous)], help: [Object] },
'unmute' => { run: [AsyncFunction (anonymous)], help: [Object] },
'warn' => { run: [AsyncFunction (anonymous)], help: [Object] },
'afk' => { run: [AsyncFunction (anonymous)], help: [Object] },
'invite' => { run: [AsyncFunction (anonymous)], help: [Object] },
'ping' => { run: [AsyncFunction (anonymous)], help: [Object] },
'anti-alt' => { run: [AsyncFunction (anonymous)], help: [Object] },
'backup' => { run: [AsyncFunction (anonymous)], help: [Object] },
'config' => { run: [AsyncFunction (anonymous)], help: [Object] },
'help' => { run: [Function (anonymous)], help: [Object] },
'ignore' => { run: [AsyncFunction (anonymous)], help: [Object] },
'prefix' => { run: [AsyncFunction (anonymous)], help: [Object] },
'setmodlogs' => { run: [AsyncFunction (anonymous)], help: [Object] }
},
cooldowns: Collection(12) [Map] {
'giveaway' => Collection(0) [Map] {},
'gend' => Collection(0) [Map] {},
'greroll' => Collection(0) [Map] {},
'purge' => Collection(0) [Map] {},
'gstart' => Collection(0) [Map] {},
'info' => Collection(0) [Map] {},
'help' => Collection(0) [Map] {},
'afk' => Collection(0) [Map] {},
'rank' => Collection(0) [Map] {},
'akinator' => Collection(0) [Map] {},
'invite' => Collection(0) [Map] {},
'connect4' => Collection(1) [Map] { '399267988513095690' => 1622635684262 }
},
config: {
PREFIX: 'h!',
IDOFFITIEL: '689210215488684044',
owner: { id: '399267988513095690', username: 'iLikeBouncyBalls#6969' },
api: {
AME_API: 'notshowing',
youtubeapi: 'notshowing',
twitchClientID: 'notshowing',
twitchClientSecret: 'notshowing'
},
ADMIN: [ '399267988513095690' ],
LINKS: {
invite: 'https://discord.com/api/oauth2/authorize?client_id=818983820866879498&permissions=1551363318&scope=bot',
topgg: 'https://top.gg/',
vote: 'https://top.gg/'
},
CHANNELCONSOLE: '846741794997272606',
color: {
EMBEDCOLOR: '#18191c',
ROUGE: '#ff0000',
ORANGE: '#ff8400',
VERT: '#71fd71'
},
emojis: {
ONLINE: '<:online:846761800846540821>',
IDLE: '<:idle:846761843615072296>',
DND: '<:dnd:846762141435822120>',
OFFLINE: '<:offline:846761881352142869>',
CHANNEL: '<:TextChannel:849300005118672936>',
CHANNELNSFW: '<:Nsfw:847178031771549704>',
VOICE: '<:VoiceChannel:846762691288104970>',
ETIQUETTE: '<:Category:849300012160253972>',
TRUE: '<a:VoteYes:845231909163237398>',
FALSE: '<a:VoteNo:845231966722326578>',
LOADING: '<a:Loading:846763929576276110>',
BOOST: '<a:Booster:846763388154806303>',
FLECHE: '<:arrow:849277506787737610>',
LOGOBOT: '<:HandlerBot:847564501963374653>',
GIVEAWAY: '<a:Giveaway:849252879558115408>・',
MANAGEMENT: '<a:Management:845620433369956353>・',
LEVELING: '<:Leveling:849418785252573204>・',
MODERATION: '<:Moderation:849378781410885672>・',
FUN: '<:Fun:849298621556195399>・',
OTHER: '<:Other:849293708191989786>・',
success: '<a:VoteYes:845231909163237398>',
error: '<:X:845800788449427496>',
loading: '<a:Loading:846763929576276110>',
fleche: '<:arrow:849277506787737610>'
}
},
configuration: {
TOKENS: {
DISCORD: 'notshowing'
},
MONGOOSE: {
DBCONNECTION: 'notshowing'
},
DEFAULTSETTINGS: {
prefix: 'h!',
logChannel: '846741794997272606',
welcomeMessage: 'Welcome',
rankcard: './util/HandlerBot.png',
invitations: false,
antialt: false
},
WEBHOOKS: { ERRORS: [Object], CONSOLE: [Object], CONNECTIONS: [Object] },
ADMIN: { ORIGINPULL: 'https://github.com/Rdimo/HandlerBot.git' }
},
errorHook: <ref *2> WebhookClient {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
_timeouts: Set(0) {},
_intervals: Set(1) {
Timeout {
_idleTimeout: 60000,
_idlePrev: [Timeout],
_idleNext: [Timeout],
_idleStart: 3960622,
_onTimeout: [Function (anonymous)],
_timerArgs: undefined,
_repeat: 60000,
_destroyed: false,
[Symbol(refed)]: true,
[Symbol(kHasPrimitive)]: false,
[Symbol(asyncId)]: 12,
[Symbol(triggerId)]: 1
}
},
_immediates: Set(0) {},
options: {
shardCount: 1,
messageCacheMaxSize: 200,
messageCacheLifetime: 0,
messageSweepInterval: 0,
messageEditHistoryMaxSize: -1,
fetchAllMembers: false,
disableMentions: 'none',
partials: [],
restWsBridgeTimeout: 5000,
restRequestTimeout: 15000,
retryLimit: 1,
restTimeOffset: 500,
restSweepInterval: 60,
presence: {},
ws: [Object],
http: [Object]
},
rest: RESTManager {
client: [Circular *2],
handlers: Collection(0) [Map] {},
tokenPrefix: 'Bot',
versioned: true,
globalTimeout: null
},
id: '846845024096092200',
[Symbol(kCapture)]: false
},
giveawaysManager: GiveawaysManager {
_events: [Object: null prototype] {
giveawayReactionAdded: [AsyncFunction (anonymous)],
endedGiveawayReactionAdded: [Function (anonymous)],
giveawayEnded: [Function (anonymous)],
giveawayRerolled: [Function (anonymous)],
giveawayReactionRemoved: [Function (anonymous)]
},
_eventsCount: 5,
_maxListeners: undefined,
client: [Circular *1],
ready: true,
giveaways: [
[Giveaway], [Giveaway],
[Giveaway], [Giveaway],
[Giveaway], [Giveaway],
[Giveaway], [Giveaway],
[Giveaway], [Giveaway],
[Giveaway], [Giveaway]
],
options: {
storage: './giveaways.json',
updateCountdownEvery: 3000,
endedGiveawaysLifetime: null,
hasGuildMemberIntent: false,
default: [Object]
},
[Symbol(kCapture)]: false
},
[Symbol(kCapture)]: false
}
答案 0 :(得分:0)
嗯,它“应该是对的”并不一定意味着它实际上是对的。
请查看带有 message
的 console.log()
。我很确定没有 mentions
。
module.exports.run = async (message) => {
let player1 = message.author;
console.log(message);
// rest of your code