Spaces:
Running
Running
{ | |
"version": 3, | |
"sources": ["../../server/room-game.ts"], | |
"sourcesContent": ["/**\n * Room games\n * Pokemon Showdown - http://pokemonshowdown.com/\n *\n * Room games are an abstract representation of an activity that a room\n * can be focused on, such as a battle, tournament, or chat game like\n * Hangman. Rooms are limited to one roomgame at a time.\n *\n * Room games can keep track of designated players. If a user is a player,\n * they will not be allowed to change name until their games are complete.\n *\n * The player system is optional: Some games, like Hangman, don't designate\n * players and just allow any user in the room to play.\n *\n * @license MIT\n */\n\n/**\n * Available globally as `Rooms.RoomGamePlayer`.\n *\n * Players are an abstraction for the people playing a `RoomGame`. They\n * may or may not be associated with a user. If they are, the game will\n * appear on the user's games list.\n *\n * Either way, they give a level of abstraction to players, allowing you\n * to easily sub out users or otherwise associate/dissociate users.\n *\n * You should mostly only be adding/removing players with functions like\n * `addPlayer`, `removePlayer`, etc, and changing the associated user\n * with `setPlayerUser` or `setEnded`.\n *\n * Do not modify `playerTable` or `player.id` yourself, it will make\n * users' games lists get out of sync.\n */\nexport class RoomGamePlayer<GameClass extends RoomGame = SimpleRoomGame> {\n\treadonly num: number;\n\treadonly game: GameClass;\n\t/**\n\t * Will be the username of the user playing, but with some exceptions:\n\t *\n\t * - Creating a game with no users will initialize player names to\n\t * \"Player 1\", \"Player 2\", etc.\n\t * - Players will retain the name of the last active user, even if that\n\t * user abandons the game.\n\t */\n\tname: string;\n\t/**\n\t * This will be '' if there's no user associated with the player.\n\t *\n\t * After the game ends, this will still be the user's ID, but it\n\t * won't be in the user's game list anymore.\n\t *\n\t * We intentionally don't hold a direct reference to the user.\n\t *\n\t * Do not modify directly. You usually want `game.updatePlayer`\n\t * (respects allowRenames) or `game.setPlayerUser` (overrides\n\t * allowRenames) or `game.renamePlayer` (overrides allowRenames\n\t * and also skips gamelist updates if the change was a simple\n\t * user rename).\n\t *\n\t * If force-modifying: remember to sync `this.game.playerTable` and\n\t * `this.getUser().games`.\n\t */\n\treadonly id: ID;\n\tcompleted?: boolean;\n\tconstructor(user: User | string | null, game: GameClass, num = 0) {\n\t\tthis.num = num;\n\t\tif (!user) user = num ? `Player ${num}` : `Player`;\n\t\tthis.game = game;\n\t\tthis.name = (typeof user === 'string' ? user : user.name);\n\t\tif (typeof user === 'string') user = null;\n\t\tthis.id = user ? user.id : '';\n\t\tif (user && !this.game.isSubGame) {\n\t\t\tuser.games.add(this.game.roomid);\n\t\t\tuser.updateSearch();\n\t\t}\n\t}\n\tdestroy() {\n\t\t(this.game as any) = null;\n\t}\n\n\ttoString() {\n\t\treturn this.id;\n\t}\n\tgetUser() {\n\t\treturn this.id ? Users.getExact(this.id) : null;\n\t}\n\tsend(data: string) {\n\t\tthis.getUser()?.send(data);\n\t}\n\tsendRoom(data: string) {\n\t\tthis.getUser()?.sendTo(this.game.roomid, data);\n\t}\n}\n\n/**\n * globally Rooms.RoomGame\n *\n * If you don't want to define your own player class, you should extend SimpleRoomGame.\n */\nexport abstract class RoomGame<PlayerClass extends RoomGamePlayer = RoomGamePlayer> {\n\tabstract gameid: ID;\n\troomid: RoomID;\n\t/**\n\t * The room this roomgame is in. Rooms can have two RoomGames at a time,\n\t * which are available as `this.room.game === this` and `this.room.subGame === this`.\n\t */\n\troom: Room;\n\ttitle = 'Game';\n\tallowRenames = false;\n\tisSubGame: boolean;\n\t/**\n\t * userid:player table.\n\t *\n\t * Does not contain userless players: use this.players for the full list.\n\t *\n\t * Do not iterate. You usually want to iterate `game.players` instead.\n\t *\n\t * Do not modify directly. You usually want `game.addPlayer` or\n\t * `game.removePlayer` instead.\n\t *\n\t * Not a source of truth. Should be kept in sync with\n\t * `Object.fromEntries(this.players.filter(p => p.id).map(p => [p.id, p]))`\n\t */\n\tplayerTable: { [userid: string]: PlayerClass } = Object.create(null);\n\tplayers: PlayerClass[] = [];\n\tplayerCount = 0;\n\tplayerCap = 0;\n\t/** should only be set by setEnded */\n\treadonly ended: boolean = false;\n\t/** Does `/guess` or `/choose` require the user to be able to talk? */\n\tcheckChat = false;\n\t/**\n\t * We should really resolve this collision at _some_ point, but it will have\n\t * to be later. The /timer command is written to be resilient to this.\n\t */\n\ttimer?: { timerRequesters?: Set<ID>, start: (force?: User) => void, stop: (force?: User) => void } |\n\t\tNodeJS.Timeout | null;\n\tconstructor(room: Room, isSubGame = false) {\n\t\tthis.roomid = room.roomid;\n\t\tthis.room = room;\n\t\tthis.isSubGame = isSubGame;\n\n\t\tif (this.isSubGame) {\n\t\t\tthis.room.subGame = this;\n\t\t} else {\n\t\t\tthis.room.game = this;\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tthis.setEnded();\n\t\tif (this.isSubGame) {\n\t\t\tthis.room.subGame = null;\n\t\t} else {\n\t\t\tthis.room.game = null;\n\t\t}\n\t\t(this as any).room = null;\n\t\tfor (const player of this.players) {\n\t\t\tplayer.destroy();\n\t\t}\n\t\t(this as any).players = null;\n\t\t(this as any).playerTable = null;\n\t}\n\n\taddPlayer(user: User | string | null = null, ...rest: any[]): PlayerClass | null {\n\t\tif (typeof user !== 'string' && user) {\n\t\t\tif (user.id in this.playerTable) return null;\n\t\t}\n\t\tif (this.playerCap > 0 && this.playerCount >= this.playerCap) return null;\n\t\tconst player = this.makePlayer(user, ...rest);\n\t\tif (!player) return null;\n\t\tif (typeof user === 'string') user = null;\n\t\tthis.players.push(player);\n\t\tif (user) {\n\t\t\tthis.playerTable[user.id] = player;\n\t\t\tthis.playerCount++;\n\t\t}\n\t\treturn player;\n\t}\n\n\tupdatePlayer(player: PlayerClass, userOrName: User | string | null) {\n\t\tif (!this.allowRenames) return;\n\t\tthis.setPlayerUser(player, userOrName);\n\t}\n\tsetPlayerUser(player: PlayerClass, userOrName: User | string | null) {\n\t\tif (this.ended) return;\n\t\tif (player.id === toID(userOrName)) return;\n\t\tif (player.id) {\n\t\t\tdelete this.playerTable[player.id];\n\t\t\tconst user = Users.getExact(player.id);\n\t\t\tif (user) {\n\t\t\t\tuser.games.delete(this.roomid);\n\t\t\t\tuser.updateSearch();\n\t\t\t}\n\t\t}\n\t\tif (userOrName) {\n\t\t\tconst { name, id } = typeof userOrName === 'string' ? { name: userOrName, id: toID(userOrName) } : userOrName;\n\t\t\t(player.id as string) = id;\n\t\t\tplayer.name = name;\n\t\t\tthis.playerTable[player.id] = player;\n\t\t\tif (this.room.roomid.startsWith('battle-') || this.room.roomid.startsWith('game-')) {\n\t\t\t\tthis.room.auth.set(id, Users.PLAYER_SYMBOL);\n\t\t\t}\n\n\t\t\tconst user = typeof userOrName === 'string' ? Users.getExact(id) : userOrName;\n\t\t\tif (user) {\n\t\t\t\tuser.games.add(this.roomid);\n\t\t\t\tuser.updateSearch();\n\t\t\t}\n\t\t} else {\n\t\t\t(player.id as string) = '';\n\t\t}\n\t}\n\n\tabstract makePlayer(user: User | string | null, ...rest: any[]): PlayerClass;\n\n\tremovePlayer(player: PlayerClass) {\n\t\tthis.setPlayerUser(player, null);\n\t\tconst playerIndex = this.players.indexOf(player);\n\t\tif (playerIndex < 0) return false;\n\t\tthis.players.splice(playerIndex, 1);\n\t\tplayer.destroy();\n\t\tthis.playerCount--;\n\t\treturn true;\n\t}\n\n\t/**\n\t * Like `setPlayerUser`, but bypasses some unnecessary game list updates if\n\t * the user renamed directly from the old userid.\n\t *\n\t * `this.playerTable[oldUserid]` must exist or this will crash.\n\t */\n\trenamePlayer(user: User, oldUserid: ID) {\n\t\tif (user.id === oldUserid) {\n\t\t\tthis.playerTable[user.id].name = user.name;\n\t\t} else {\n\t\t\tthis.playerTable[user.id] = this.playerTable[oldUserid];\n\t\t\t(this.playerTable[user.id].id as string) = user.id;\n\t\t\tthis.playerTable[user.id].name = user.name;\n\t\t\tdelete this.playerTable[oldUserid];\n\t\t}\n\t}\n\n\t/**\n\t * This is purely for cleanup, suitable for calling from `destroy()`.\n\t * You should make a different function, call it `end` or something,\n\t * to end a game properly. See BestOfGame for an example of an `end`\n\t * function.\n\t */\n\tsetEnded() {\n\t\tif (this.ended) return;\n\t\t(this.ended as boolean) = true;\n\t\tif (this.isSubGame) return;\n\t\tfor (const player of this.players) {\n\t\t\tconst user = player.getUser();\n\t\t\tif (user) {\n\t\t\t\tuser.games.delete(this.roomid);\n\t\t\t\tuser.updateSearch();\n\t\t\t}\n\t\t}\n\t}\n\n\trenameRoom(roomid: RoomID) {\n\t\tfor (const player of this.players) {\n\t\t\tconst user = player.getUser();\n\t\t\tuser?.games.delete(this.roomid);\n\t\t\tuser?.games.add(roomid);\n\t\t}\n\t\tthis.roomid = roomid;\n\t}\n\n\t// Commands:\n\n\t// These are all optional to implement:\n\n\t/**\n\t * Called when a user uses /forfeit\n\t * Also used for some force-forfeit situations, such\n\t * as when a user changes their name and .allowRenames === false\n\t * This is strongly recommended to be supported, as the user is\n\t * extremely unlikely to keep playing after this function is\n\t * called.\n\t *\n\t * @param user\n\t * @param reason if a forced forfeit; should start with space\n\t */\n\tforfeit?(user: User | string, reason?: string): void;\n\n\t/**\n\t * Called when a user uses /choose [text]\n\t * If you have buttons, you are recommended to use this interface\n\t * instead of making your own commands.\n\t */\n\tchoose?(user: User, text: string): void;\n\n\t/**\n\t * Called when a user uses /undo [text]\n\t */\n\tundo?(user: User, text: string): void;\n\n\t/**\n\t * Called when a user uses /joingame [text]\n\t */\n\tjoinGame?(user: User, text?: string): void;\n\n\t/**\n\t * Called when a user uses /leavegame [text]\n\t */\n\tleaveGame?(user: User, text?: string): void;\n\n\t// Events:\n\n\t// Note:\n\t// A user can have multiple connections. For instance, if you have\n\t// two tabs open and connected to PS, those tabs represent two\n\t// connections, but a single PS user. Each tab can be in separate\n\t// rooms.\n\n\t/**\n\t * Called when a user joins a room. (i.e. when the user's first\n\t * connection joins)\n\t *\n\t * While connection is passed, it should not usually be used:\n\t * Any handling of connections should happen in onConnect.\n\t */\n\tonJoin(user: User, connection: Connection) {}\n\n\t/**\n\t * Called when a subroom game (battle or bestof) ends, on the\n\t * parent game (bestof or tournament).\n\t */\n\tonBattleWin?(room: GameRoom, winnerid: ID): void;\n\n\t/**\n\t * Called when a user is banned from the room this game is taking\n\t * place in.\n\t */\n\tremoveBannedUser(user: User) {\n\t\tthis.forfeit?.(user, \" lost by being banned.\");\n\t}\n\n\t/**\n\t * Called when a user in the game is renamed. `isJoining` is true\n\t * if the user was previously a guest, but now has a username.\n\t * Check `!user.named` for the case where a user previously had a\n\t * username but is now a guest. By default, updates a player's\n\t * name as long as allowRenames is set to true.\n\t */\n\tonRename(user: User, oldUserid: ID, isJoining: boolean, isForceRenamed: boolean) {\n\t\tif (!this.allowRenames || (!user.named && !isForceRenamed)) {\n\t\t\tif (!(user.id in this.playerTable) && !this.isSubGame) {\n\t\t\t\tuser.games.delete(this.roomid);\n\t\t\t\tuser.updateSearch();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (!(oldUserid in this.playerTable)) return;\n\t\tif (!user.named) {\n\t\t\treturn this.onLeave(user, oldUserid);\n\t\t}\n\t\tthis.renamePlayer(user, oldUserid);\n\t}\n\n\t/**\n\t * Called when a user leaves the room. (i.e. when the user's last\n\t * connection leaves)\n\t */\n\tonLeave(user: User, oldUserid?: ID) {}\n\n\t/**\n\t * Called each time a connection joins a room (after onJoin if\n\t * applicable). By default, this is also called when connection\n\t * is updated in some way (such as by changing user or renaming).\n\t * If you don't want this behavior, override onUpdateConnection\n\t * and/or onRename.\n\t *\n\t * This means that by default, it's called twice: once when\n\t * connected to the server (as guest1763 or whatever), and once\n\t * when logged in.\n\t */\n\tonConnect(user: User, connection: Connection) {}\n\n\t/**\n\t * Called for each connection in a room that changes users by\n\t * merging into a different user. By default, runs the onConnect\n\t * handler.\n\t *\n\t * Player updates and an up-to-date report of what's going on in\n\t * the game should be sent during `onConnect`. You should rarely\n\t * need to handle the other events.\n\t */\n\tonUpdateConnection(user: User, connection: Connection) {\n\t\tthis.onConnect(user, connection);\n\t}\n\n\t/**\n\t * Called for every message a user sends while this game is active.\n\t * Return an error message to prevent the message from being sent,\n\t * an empty string to prevent it with no error message, or\n\t * `undefined` to let it through.\n\t */\n\tonChatMessage(message: string, user: User): string | void {}\n\n\t/**\n\t * Called for every message a user sends while this game is active.\n\t * Unlike onChatMessage, this function runs after the message has been added to the room's log.\n\t * Do not try to use this to block messages, use onChatMessage for that.\n\t */\n\tonLogMessage(message: string, user: User) {}\n\n\t/**\n\t * Called when a game's timer needs to be started. Used mainly for tours.\n\t */\n\tstartTimer() {}\n}\n\n/**\n * globally Rooms.SimpleRoomGame\n *\n * A RoomGame without a custom player class. Gives a default implementation for makePlayer.\n */\nexport abstract class SimpleRoomGame extends RoomGame {\n\tmakePlayer(user: User | string | null, ...rest: any[]): RoomGamePlayer {\n\t\tconst num = this.players.length ? this.players[this.players.length - 1].num : 1;\n\t\treturn new RoomGamePlayer(user, this, num);\n\t}\n}\n"], | |
"mappings": "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", | |
"names": [] | |
} | |