`, true);
// deallocate games for each player.
- for (let i in this.playerTable) {
+ for (const i in this.playerTable) {
this.playerTable[i].destroy();
}
delete this.room.game;
@@ -618,43 +568,33 @@ class UnoGame extends Rooms.RoomGame {
}
class UnoGamePlayer extends Rooms.RoomGamePlayer {
- /**
- * @param {User} user
- * @param {UnoGame} game
- */
- constructor(user, game) {
+ hand: Card[];
+ game: UnoGame;
+ cardLock: string | null;
+
+ constructor(user: User, game: UnoGame) {
super(user, game);
- this.hand = /** @type {Card[]} */ ([]);
+ this.hand = [];
this.game = game;
- /** @type {string?} */
this.cardLock = null;
}
- /**
- * @return {boolean}
- */
canPlayWildFour() {
if (!this.game.topCard) {
// should never happen
throw new Error(`No top card in the discard pile.`);
}
- let color = (this.game.topCard.changedColor || this.game.topCard.color);
+ const color = (this.game.topCard.changedColor || this.game.topCard.color);
if (this.hand.some(c => c.color === color)) return false;
return true;
}
- /**
- * @param {string} cardName
- */
- hasCard(cardName) {
+ hasCard(cardName: string) {
return this.hand.find(card => card.name === cardName);
}
- /**
- * @param {string} cardName
- */
- removeCard(cardName) {
+ removeCard(cardName: string) {
for (const [i, card] of this.hand.entries()) {
if (card.name === cardName) {
this.hand.splice(i, 1);
@@ -663,26 +603,23 @@ class UnoGamePlayer extends Rooms.RoomGamePlayer {
}
}
- /**
- * @return {string[]}
- */
buildHand() {
return this.hand.sort((a, b) => a.color.localeCompare(b.color) || a.value.localeCompare(b.value))
.map((c, i) => cardHTML(c, i === this.hand.length - 1));
}
sendDisplay() {
- let hand = this.buildHand().join('');
- let players = `
Players (${this.game.playerCount}):
${this.game.getPlayers(true).join(' ')}`;
- let draw = '';
- let pass = '';
- let uno = ``;
+ const hand = this.buildHand().join('');
+ const players = `
Players (${this.game.playerCount}):
${this.game.getPlayers(true).join(' ')}`;
+ const draw = '';
+ const pass = '';
+ const uno = ``;
if (!this.game.topCard) {
// should never happen
throw new Error(`No top card in the discard pile.`);
}
- let top = `Top Card: ${this.game.topCard.name}`;
+ const top = `Top Card: ${this.game.topCard.name}`;
// clear previous display and show new display
this.sendRoom("|uhtmlchange|uno-hand|");
@@ -694,8 +631,7 @@ class UnoGamePlayer extends Rooms.RoomGamePlayer {
}
}
-/** @type {ChatCommands} */
-const commands = {
+export const commands: ChatCommands = {
uno: {
// roomowner commands
off: 'disable',
@@ -738,7 +674,7 @@ const commands = {
if (room.unoDisabled) return this.errorReply("UNO is currently disabled for this room.");
if (room.game) return this.errorReply("There is already a game in progress in this room.");
- let suppressMessages = cmd.includes('private') || !(cmd.includes('public') || room.roomid === 'gamecorner');
+ const suppressMessages = cmd.includes('private') || !(cmd.includes('public') || room.roomid === 'gamecorner');
let cap = parseInt(target);
if (isNaN(cap)) cap = 6;
@@ -750,8 +686,10 @@ const commands = {
start(target, room, user) {
if (!this.can('minigame', null, room)) return;
- const game = /** @type {UnoGame} */ (room.game);
- if (!game || game.gameid !== 'uno' || game.state !== 'signups') return this.errorReply("There is no UNO game in signups phase in this room.");
+ const game = room.game as UnoGame;
+ if (!game || game.gameid !== 'uno' || game.state !== 'signups') {
+ return this.errorReply("There is no UNO game in signups phase in this room.");
+ }
if (game.onStart()) {
this.privateModAction(`(The game of UNO was started by ${user.name}.)`);
this.modlog('UNO START');
@@ -770,9 +708,9 @@ const commands = {
timer(target, room, user) {
if (!this.can('minigame', null, room)) return;
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room.");
- let amount = parseInt(target);
+ const amount = parseInt(target);
if (!amount || amount < 5 || amount > 300) return this.errorReply("The amount must be a number between 5 and 300.");
game.maxTime = amount;
@@ -786,7 +724,7 @@ const commands = {
autostart(target, room, user) {
if (!this.can('minigame', null, room)) return;
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
if (toID(target) === 'off') {
if (!game.autostartTimer) return this.errorReply("There is no autostart timer running on.");
@@ -795,7 +733,9 @@ const commands = {
return;
}
const amount = parseInt(target);
- if (!amount || amount < 30 || amount > 600) return this.errorReply("The amount must be a number between 30 and 600 seconds.");
+ if (!amount || amount < 30 || amount > 600) {
+ return this.errorReply("The amount must be a number between 30 and 600 seconds.");
+ }
if (game.state !== 'signups') return this.errorReply("The game of UNO has already started.");
if (game.autostartTimer) clearTimeout(game.autostartTimer);
game.autostartTimer = setTimeout(() => {
@@ -807,10 +747,10 @@ const commands = {
dq: 'disqualify',
disqualify(target, room, user) {
if (!this.can('minigame', null, room)) return;
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
- let disqualified = game.eliminate(toID(target));
+ const disqualified = game.eliminate(toID(target));
if (disqualified === false) return this.errorReply(`Unable to disqualify ${target}.`);
this.privateModAction(`(${user.name} has disqualified ${disqualified} from the UNO game.)`);
this.modlog('UNO DQ', toID(target));
@@ -822,7 +762,7 @@ const commands = {
// TypeScript doesn't like 'join' being defined as a function
join: 'unojoin',
unojoin(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
if (!this.canTalk()) return false;
if (!game.joinGame(user)) return this.errorReply("Unable to join the game.");
@@ -832,38 +772,35 @@ const commands = {
l: 'leave',
leave(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
if (!game.leaveGame(user)) return this.errorReply("Unable to leave the game.");
return this.sendReply("You have left the game of UNO.");
},
play(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
- /** @type {UnoGamePlayer | undefined} */
- let player = game.playerTable[user.id];
+ const player: UnoGamePlayer | undefined = game.playerTable[user.id];
if (!player) return this.errorReply(`You are not in the game of UNO.`);
- let error = game.onPlay(player, target);
+ const error = game.onPlay(player, target);
if (error) this.errorReply(error);
},
draw(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
- /** @type {UnoGamePlayer | undefined} */
- let player = game.playerTable[user.id];
+ const player: UnoGamePlayer | undefined = game.playerTable[user.id];
if (!player) return this.errorReply(`You are not in the game of UNO.`);
- let error = game.onDraw(player);
+ const error = game.onDraw(player);
if (error) return this.errorReply("You have already drawn a card this turn.");
},
pass(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
if (game.currentPlayerid !== user.id) return this.errorReply("It is currently not your turn.");
- /** @type {UnoGamePlayer | undefined} */
- let player = game.playerTable[user.id];
+ const player: UnoGamePlayer | undefined = game.playerTable[user.id];
if (!player) return this.errorReply(`You are not in the game of UNO.`);
if (!player.cardLock) return this.errorReply("You cannot pass until you draw a card.");
if (game.state === 'color') return this.errorReply("You cannot pass until you choose a color.");
@@ -873,13 +810,11 @@ const commands = {
},
color(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return false;
- /** @type {UnoGamePlayer | undefined} */
- let player = game.playerTable[user.id];
+ const player: UnoGamePlayer | undefined = game.playerTable[user.id];
if (!player) return this.errorReply(`You are not in the game of UNO.`);
- /** @type {Color} */
- let color;
+ let color: Color;
if (target === 'Red' || target === 'Green' || target === 'Blue' || target === 'Yellow' || target === 'Black') {
color = target;
} else {
@@ -889,18 +824,17 @@ const commands = {
},
uno(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return false;
- /** @type {UnoGamePlayer | undefined} */
- let player = game.playerTable[user.id];
+ const player: UnoGamePlayer | undefined = game.playerTable[user.id];
if (!player) return this.errorReply(`You are not in the game of UNO.`);
- game.onUno(player, target);
+ game.onUno(player, toID(target));
},
// information commands
'': 'hand',
hand(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.parse("/help uno");
game.onSendHand(user);
},
@@ -909,7 +843,7 @@ const commands = {
users: 'getusers',
getplayers: 'getusers',
getusers(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
if (!this.runBroadcast()) return false;
this.sendReplyBox(`Players (${game.playerCount}): ${game.getPlayers().join(', ')}`);
@@ -921,15 +855,19 @@ const commands = {
// suppression commands
suppress(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
if (!this.can('minigame', null, room)) return;
target = toID(target);
- let state = target === 'on' ? true : target === 'off' ? false : undefined;
+ const state = target === 'on' ? true : target === 'off' ? false : undefined;
- if (state === undefined) return this.sendReply(`Suppression of UNO game messages is currently ${(game.suppressMessages ? 'on' : 'off')}.`);
- if (state === game.suppressMessages) return this.errorReply(`Suppression of UNO game messages is already ${(game.suppressMessages ? 'on' : 'off')}.`);
+ if (state === undefined) {
+ return this.sendReply(`Suppression of UNO game messages is currently ${(game.suppressMessages ? 'on' : 'off')}.`);
+ }
+ if (state === game.suppressMessages) {
+ return this.errorReply(`Suppression of UNO game messages is already ${(game.suppressMessages ? 'on' : 'off')}.`);
+ }
game.suppressMessages = state;
@@ -938,7 +876,7 @@ const commands = {
},
spectate(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
if (!game.suppressMessages) return this.errorReply("The current UNO game is not suppressing messages.");
@@ -949,7 +887,7 @@ const commands = {
},
unspectate(target, room, user) {
- const game = /** @type {UnoGame} */ (room.game);
+ const game = room.game as UnoGame;
if (!game || game.gameid !== 'uno') return this.errorReply("There is no UNO game going on in this room right now.");
if (!game.suppressMessages) return this.errorReply("The current UNO game is not suppressing messages.");
@@ -973,8 +911,8 @@ const commands = {
`/uno suppress [on|off] - Toggles suppression of game messages.`,
],
};
-/** @type {SettingsHandler} */
-const roomSettings = room => ({
+
+export const roomSettings: SettingsHandler = room => ({
label: "UNO",
permission: 'editroom',
options: [
@@ -982,8 +920,3 @@ const roomSettings = room => ({
[`enabled`, !room.unoDisabled || 'uno enable'],
],
});
-
-module.exports = {
- commands,
- roomSettings,
-};
diff --git a/tsconfig.json b/tsconfig.json
index 86542808f4..3f38c88c09 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -27,14 +27,11 @@
"./server/chat-plugins/*.ts",
"./server/chat-plugins/chat-monitor.js",
"./server/chat-plugins/daily-spotlight.js",
- "./server/chat-plugins/hangman.js",
"./server/chat-plugins/helptickets.js",
"./server/chat-plugins/mafia-data.js",
- "./server/chat-plugins/othermetas.js",
"./server/chat-plugins/room-faqs.js",
"./server/chat-plugins/thecafe.js",
"./server/chat-plugins/thing-of-the-day.js",
- "./server/chat-plugins/uno.js",
"./server/chat-plugins/wifi.js",
"./sim/**/*",
"./tools/set-import/*.ts"