diff --git a/server/chat-commands/info.ts b/server/chat-commands/info.ts index be814ff80cea..5af54311eb3a 100644 --- a/server/chat-commands/info.ts +++ b/server/chat-commands/info.ts @@ -585,7 +585,7 @@ export const commands: Chat.ChatCommands = { const gen = parseInt(cmd.substr(-1)); if (gen) target += `, gen${gen}`; - const {dex, format, targets} = this.splitFormat(target, true); + const {dex, format, targets} = this.splitFormat(target, true, true); let buffer = ''; target = targets.join(','); @@ -2819,7 +2819,7 @@ export const commands: Chat.ChatCommands = { allowEmpty: true, useIDs: false, }); const format = Dex.formats.get(toID(args.format[0])); - if (!format.exists) { + if (format.effectType !== 'Format') { return this.popupReply(`The format '${format}' does not exist.`); } delete args.format; @@ -3170,8 +3170,8 @@ export const pages: Chat.PageTable = { buf += `
`; const formatId = toID(query[0]); const format = Dex.formats.get(formatId); - if (!formatId || !format.exists) { - if (formatId && !format.exists) { + if (!formatId || format.effectType !== 'Format') { + if (formatId) { buf += `
The format '${formatId}' does not exist.

`; } buf += `
`; diff --git a/server/chat-commands/room-settings.ts b/server/chat-commands/room-settings.ts index 99ce0d45efa6..76e1ce7589a9 100644 --- a/server/chat-commands/room-settings.ts +++ b/server/chat-commands/room-settings.ts @@ -1615,7 +1615,7 @@ export const commands: Chat.ChatCommands = { target = toID(target); const format = Dex.formats.get(target); - if (format.exists) { + if (format.effectType === 'Format') { target = format.name; } const {isMatch} = this.extractFormat(target); diff --git a/server/chat-plugins/datasearch.ts b/server/chat-plugins/datasearch.ts index bfe1bd1c0339..8babc9960d18 100644 --- a/server/chat-plugins/datasearch.ts +++ b/server/chat-plugins/datasearch.ts @@ -1149,7 +1149,7 @@ function runDexsearch(target: string, cmd: string, canAll: boolean, message: str // LC handling, checks for LC Pokemon in higher tiers that need to be handled separately, // as well as event-only Pokemon that are not eligible for LC despite being the first stage let format = Dex.formats.get('gen' + mod.gen + 'lc'); - if (!format.exists) format = Dex.formats.get('gen9lc'); + if (format.effectType !== 'Format') format = Dex.formats.get('gen9lc'); if ( alts.tiers.LC && !dex[mon].prevo && @@ -2576,7 +2576,7 @@ function runLearn(target: string, cmd: string, canAll: boolean, formatid: string while (targets.length) { const targetid = toID(targets[0]); if (targetid === 'pentagon') { - if (format.exists) { + if (format.effectType === 'Format') { return {error: "'pentagon' can't be used with formats."}; } minSourceGen = 6; @@ -2584,7 +2584,7 @@ function runLearn(target: string, cmd: string, canAll: boolean, formatid: string continue; } if (targetid.startsWith('minsourcegen')) { - if (format.exists) { + if (format.effectType === 'Format') { return {error: "'min source gen' can't be used with formats."}; } minSourceGen = parseInt(targetid.slice(12)); @@ -2600,14 +2600,15 @@ function runLearn(target: string, cmd: string, canAll: boolean, formatid: string break; } let gen; - if (!format.exists) { + if (format.effectType !== 'Format') { + if (!(formatid in Dex.dexes)) { + // can happen if you hotpatch formats without hotpatching chat + return {error: `"${formatid}" is not a supported format.`}; + } const dex = Dex.mod(formatid).includeData(); - // can happen if you hotpatch formats without hotpatching chat - if (!dex) return {error: `"${formatid}" is not a supported format.`}; - gen = dex.gen; formatName = `Gen ${gen}`; - format = new Dex.Format({mod: formatid}); + format = new Dex.Format({mod: formatid, effectType: 'Format', exists: true}); const ruleTable = dex.formats.getRuleTable(format); if (minSourceGen) { formatName += ` (Min Source Gen = ${minSourceGen})`; diff --git a/server/chat-plugins/randombattles/index.ts b/server/chat-plugins/randombattles/index.ts index e7111018c87d..d9ca18a6adea 100644 --- a/server/chat-plugins/randombattles/index.ts +++ b/server/chat-plugins/randombattles/index.ts @@ -857,7 +857,7 @@ export const commands: Chat.ChatCommands = { if (!target) return this.parse('/help generateteam'); const format = Dex.formats.get(target); - if (!format.exists) throw new Chat.ErrorMessage(`"${target}" is not a recognized format.`); + if (format.effectType !== 'Format') throw new Chat.ErrorMessage(`"${target}" is not a recognized format.`); if (!format.team) throw new Chat.ErrorMessage(`"${format.name}" requires you to bring your own team.`); const team = Teams.getGenerator(format).getTeam(); diff --git a/server/chat-plugins/sample-teams.ts b/server/chat-plugins/sample-teams.ts index 334b498000d0..3ff4663f3307 100644 --- a/server/chat-plugins/sample-teams.ts +++ b/server/chat-plugins/sample-teams.ts @@ -107,7 +107,7 @@ export const SampleTeams = new class SampleTeams { sanitizeFormat(formatid: string, checkExists = false) { const format = Dex.formats.get(formatid); - if (checkExists && !format.exists) { + if (checkExists && format.effectType !== 'Format') { throw new Chat.ErrorMessage(`Format "${formatid.trim()}" not found. Check spelling?`); } if (format.team) { diff --git a/server/chat-plugins/suspect-tests.ts b/server/chat-plugins/suspect-tests.ts index 762e693b08ee..c5458c0a18bd 100644 --- a/server/chat-plugins/suspect-tests.ts +++ b/server/chat-plugins/suspect-tests.ts @@ -67,7 +67,7 @@ export const commands: Chat.ChatCommands = { } const format = Dex.formats.get(tier); - if (!format.exists) throw new Chat.ErrorMessage(`"${tier}" is not a valid tier.`); + if (format.effectType !== 'Format') throw new Chat.ErrorMessage(`"${tier}" is not a valid tier.`); const suspectString = suspect.trim(); diff --git a/server/chat-plugins/teams.ts b/server/chat-plugins/teams.ts index 280d288e736d..3d47713ac5dc 100644 --- a/server/chat-plugins/teams.ts +++ b/server/chat-plugins/teams.ts @@ -124,7 +124,7 @@ export const TeamsHandler = new class { } const user = connection.user; const format = Dex.formats.get(toID(formatName)); - if (!format.exists || format.team) { + if (format.effectType !== 'Format' || format.team) { connection.popup("Invalid format:\n\n" + formatName); return null; } diff --git a/server/chat.ts b/server/chat.ts index 8ea704c06fe2..95c76921cf6a 100644 --- a/server/chat.ts +++ b/server/chat.ts @@ -291,19 +291,19 @@ export abstract class MessageContext { * for the format/mod, or the default dex if none was found), and * `targets` (the rest of the array). */ - splitFormat(target: string | string[], atLeastOneTarget?: boolean) { + splitFormat(target: string | string[], atLeastOneTarget?: boolean, allowRules?: boolean) { const targets = typeof target === 'string' ? target.split(',') : target; if (!targets[0].trim()) targets.pop(); if (targets.length > (atLeastOneTarget ? 1 : 0)) { - const {dex, format, isMatch} = this.extractFormat(targets[0].trim()); + const {dex, format, isMatch} = this.extractFormat(targets[0].trim(), allowRules); if (isMatch) { targets.shift(); return {dex, format, targets}; } } if (targets.length > 1) { - const {dex, format, isMatch} = this.extractFormat(targets[targets.length - 1].trim()); + const {dex, format, isMatch} = this.extractFormat(targets[targets.length - 1].trim(), allowRules); if (isMatch) { targets.pop(); return {dex, format, targets}; @@ -311,16 +311,16 @@ export abstract class MessageContext { } const room = (this as any as CommandContext).room; - const {dex, format} = this.extractFormat(room?.settings.defaultFormat || room?.battle?.format); + const {dex, format} = this.extractFormat(room?.settings.defaultFormat || room?.battle?.format, allowRules); return {dex, format, targets}; } - extractFormat(formatOrMod?: string): {dex: ModdedDex, format: Format | null, isMatch: boolean} { + extractFormat(formatOrMod?: string, allowRules?: boolean): {dex: ModdedDex, format: Format | null, isMatch: boolean} { if (!formatOrMod) { return {dex: Dex.includeData(), format: null, isMatch: false}; } const format = Dex.formats.get(formatOrMod); - if (format.exists) { + if (format.effectType === 'Format' || allowRules && format.effectType === 'Rule') { return {dex: Dex.forFormat(format), format: format, isMatch: true}; } diff --git a/sim/dex-formats.ts b/sim/dex-formats.ts index a70619fa877b..89813628c97b 100644 --- a/sim/dex-formats.ts +++ b/sim/dex-formats.ts @@ -628,7 +628,7 @@ export class DexFormats { validate(name: string) { const [formatName, customRulesString] = name.split('@@@', 2); const format = this.get(formatName); - if (!format.exists) throw new Error(`Unrecognized format "${formatName}"`); + if (format.effectType !== 'Format') throw new Error(`Unrecognized format "${formatName}"`); if (!customRulesString) return format.id; const ruleTable = this.getRuleTable(format); const customRules = customRulesString.split(',').map(rule => { diff --git a/tools/set-import/importer.ts b/tools/set-import/importer.ts index 8947035abd04..b9619962d978 100644 --- a/tools/set-import/importer.ts +++ b/tools/set-import/importer.ts @@ -55,7 +55,7 @@ const VALIDATORS = new Map(); for (let gen = 1; gen <= 9; gen++) { for (const tier of TIERS) { const format = Dex.formats.get(`gen${gen}${tier}`); - if (format.exists) { + if (format.effectType === 'Format') { FORMATS.set(format.id, {gen: gen as GenerationNum, format}); VALIDATORS.set(format.id, new TeamValidator(format)); }