@@ -5,6 +5,8 @@ import { renderBackups, renderMenu } from '@/ps/games/menus';
55import { parseMod } from '@/ps/games/mods' ;
66import { generateId } from '@/ps/games/utils' ;
77import { ChatError } from '@/utils/chatError' ;
8+ import { fromHumanTime , toHumanTime } from '@/utils/humanTime' ;
9+ import { Timer } from '@/utils/timer' ;
810import { toId } from '@/utils/toId' ;
911
1012import type { NoTranslate , ToTranslate , TranslationFn } from '@/i18n/types' ;
@@ -218,20 +220,57 @@ export const command: PSCommand[] = Object.entries(Games).map(([_gameId, Game]):
218220 }
219221 } ,
220222 } ,
221- ...conditionalCommand ( Game . meta . autostart === false , {
222- name : 'start' ,
223- aliases : [ 's' , 'go' , 'g' ] ,
224- help : 'Starts a game if it does not have an auto-start.' ,
225- syntax : 'CMD [id]' ,
226- perms : Symbol . for ( 'games.create' ) ,
227- async run ( { message, arg, $T } ) : Promise < void > {
228- const { game } = getGame ( arg , { action : 'start' , user : message . author . id } , { room : message . target , $T } ) ;
229- if ( game . started ) throw new ChatError ( $T ( 'GAME.ALREADY_STARTED' ) ) ;
230- if ( ! game . startable ( ) ) throw new ChatError ( $T ( 'GAME.CANNOT_START' ) ) ;
231- game . start ( ) ;
232- game . closeSignups ( false ) ;
223+ ...conditionalCommand (
224+ Game . meta . autostart === false ,
225+ {
226+ name : 'start' ,
227+ aliases : [ 's' , 'go' , 'g' ] ,
228+ help : 'Starts a game if it does not have an auto-start.' ,
229+ syntax : 'CMD [id]' ,
230+ perms : Symbol . for ( 'games.create' ) ,
231+ async run ( { message, arg, $T } ) : Promise < void > {
232+ const { game } = getGame ( arg , { action : 'start' , user : message . author . id } , { room : message . target , $T } ) ;
233+ if ( game . started ) throw new ChatError ( $T ( 'GAME.ALREADY_STARTED' ) ) ;
234+ if ( ! game . startable ( ) ) throw new ChatError ( $T ( 'GAME.CANNOT_START' ) ) ;
235+ game . start ( ) ;
236+ game . closeSignups ( false ) ;
237+ } ,
233238 } ,
234- } ) ,
239+ {
240+ name : 'autostart' ,
241+ aliases : [ 'as' , 'auto' , 'schedule' ] ,
242+ help : 'Automatically starts the target game at the given time.' ,
243+ syntax : 'CMD [id], [time]' ,
244+ perms : Symbol . for ( 'games.create' ) ,
245+ async run ( { message, arg, $T } ) : Promise < void > {
246+ const { game, ctx } = getGame ( arg , { action : 'start' , user : message . author . id } , { room : message . target , $T } ) ;
247+ const startIn = fromHumanTime ( ctx ) ;
248+ if ( ! startIn ) throw new ChatError ( $T ( 'GAME.INVALID_INPUT' ) ) ;
249+ if ( game . started ) throw new ChatError ( $T ( 'GAME.ALREADY_STARTED' ) ) ;
250+ if ( game . scheduledStart ) {
251+ game . scheduledStart . cancel ( ) ;
252+ message . reply (
253+ $T ( 'COMMANDS.TIMER.CANCELLED' , {
254+ timeLeft : toHumanTime ( game . scheduledStart . endTime - Date . now ( ) , undefined , $T ) ,
255+ comment : ' for game autostart' ,
256+ } )
257+ ) ;
258+ game . scheduledStart = null ;
259+ }
260+ game . scheduledStart = new Timer (
261+ ( ) => {
262+ if ( game . started ) return ;
263+ if ( ! game . startable ( ) ) return game . room . send ( $T ( 'GAME.CANNOT_START' ) ) ;
264+ game . start ( ) ;
265+ game . closeSignups ( false ) ;
266+ } ,
267+ startIn ,
268+ 'Game start queued by ${message.author.name}'
269+ ) ;
270+ message . reply ( $T ( 'GAME.AUTOSTART_QUEUED' , { time : toHumanTime ( startIn , undefined , $T ) } ) ) ;
271+ } ,
272+ }
273+ ) ,
235274 reaction : {
236275 name : 'reaction' ,
237276 aliases : [ 'x' , '!!' ] ,
0 commit comments