From 0edb19f225e75554901d763f8de42ec03c051d99 Mon Sep 17 00:00:00 2001 From: Juror #9 <64419198+Jurorno9@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:59:18 +0530 Subject: [PATCH 01/12] /nextmap revamp --- build/scripts/commands/general.js | 106 +++++++++++++++++++++++------- src/commands/general.ts | 83 ++++++++++++++++++----- 2 files changed, 147 insertions(+), 42 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index 37f21622..f01a4a14 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -923,6 +923,7 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { // votekickmanager.handleVote(sender, args ? 1 : -1); // } // }, + // no, it will not get the menu. yes, I know it sucks, but I doubt we nee forcenextmap: { args: ["map:map"], description: 'Override the next map in queue.', @@ -941,16 +942,32 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { outputSuccess(f(templateObject_17 || (templateObject_17 = __makeTemplateObject(["Forced the next map to be \"", "\" by ", ""], ["Forced the next map to be \"", "\" by ", ""])), args.map.name(), args.map.author())); } }, - }, maps: { + }, + /* + maps: { args: [], description: 'Lists the available maps.', - perm: commands_1.Perm.none, - handler: function (_a) { - var output = _a.output; - output("[yellow]Use [white]/nextmap [lightgray] [yellow]to vote on a map.\n\n[blue]Available maps:\n_________________________\n".concat(Vars.maps.customMaps().toArray().map(function (map) { - return "[yellow]".concat(map.name()); - }).join("\n"))); + perm: Perm.none, + handler({output}){ + output(`\ +[yellow]Use [white]/nextmap [lightgray] [yellow]to vote on a map. + +[blue]Available maps: +_________________________ +${Vars.maps.customMaps().toArray().map(map => +`[yellow]${map.name()}` +).join("\n")}` + ); } + }, + */ + maps: { + description: 'depreciated, please use /maps instead', + args: [], + perm: commands_1.Perm.none, + handler: function () { + (0, commands_1.fail)('This command was moved to /nextmap'); + }, }, nextmap: (0, commands_1.command)(function () { var votes = new Map(); var lastVoteCount = 0; @@ -958,6 +975,56 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { var voteEndTime = -1; var voteDuration = funcs_1.Duration.minutes(1.5); var task = null; + var currentMenu = function (target) { + var mainMenu = menus_1.Menu.raw("Fish Map Manager", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); + mainMenu.then(function (res) { + switch (res) { + case '[green]Current Maps': + var CurrentMapsMenu = menus_1.Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 }); + CurrentMapsMenu.catch(function () { }).then(function (map) { + if (map == null) + return; + var CurrentMapMenu = menus_1.Menu.raw(map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [["[green]Vote for this Map"], ["[red]Back"]], target); + CurrentMapMenu.then(function (res) { + switch (res) { + case ("[green]Vote for this Map"): + sendVote(target, map); + break; + case ("[red]Back"): + currentMenu(target); + break; + } + }); + }); + break; + case '[yellow]Throwback Maps': + (0, utils_1.outputMessage)("Throwback maps have not yet been implemented.", target); + break; + case '[orange]Campaigns': + (0, utils_1.outputMessage)("Campaigns have not yet been implemented.", target); + break; + case 'Close': + break; + } + }); + }; + function sendVote(sender, map) { + if (config_1.Gamemode.testsrv()) + (0, commands_1.fail)("Please use /forcenextmap instead."); + if (votes.get(sender)) + (0, commands_1.fail)("You have already voted."); + votes.set(sender, map); + if (voteEndTime == -1) { + if ((Date.now() - lastVoteTime) < 60000) + (0, commands_1.fail)("Please wait 1 minute before starting a new map vote."); + startVote(); + Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] started a map vote, and voted for [yellow]").concat(map.name(), "[cyan]. Use [white]/nextmap ").concat(map.plainName(), "[] to add your vote, or run [white]/maps[] to see other available maps.")); + } + else { + Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] voted for [yellow]").concat(map.name(), "[cyan]. Time left: [scarlet]").concat((0, utils_1.formatTimeRelative)(voteEndTime, true))); + showVotes(); + } + } function resetVotes() { votes.clear(); voteEndTime = -1; @@ -1012,28 +1079,17 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { Events.on(EventType.GameOverEvent, resetVotes); Events.on(EventType.ServerLoadEvent, resetVotes); return { - args: ['map:map'], - description: 'Allows you to vote for the next map. Use /maps to see all available maps.', + args: ['map:map?'], + description: 'Allows you to vote for the next map.', perm: commands_1.Perm.play, data: { votes: votes, voteEndTime: function () { return voteEndTime; }, resetVotes: resetVotes, endVote: endVote }, requirements: [commands_1.Req.cooldown(10000)], handler: function (_a) { - var map = _a.args.map, sender = _a.sender; - if (config_1.Gamemode.testsrv()) - (0, commands_1.fail)("Please use /forcenextmap instead."); - if (votes.get(sender)) - (0, commands_1.fail)("You have already voted."); - votes.set(sender, map); - if (voteEndTime == -1) { - if ((Date.now() - lastVoteTime) < funcs_1.Duration.minutes(1)) - (0, commands_1.fail)("Please wait 1 minute before starting a new map vote."); - startVote(); - Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] started a map vote, and voted for [yellow]").concat(map.name(), "[cyan]. Use [white]/nextmap ").concat(map.plainName(), "[] to add your vote, or run [white]/maps[] to see other available maps.")); - } - else { - Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] voted for [yellow]").concat(map.name(), "[cyan]. Time left: [scarlet]").concat((0, utils_1.formatTimeRelative)(voteEndTime, true))); - showVotes(); - } + var args = _a.args, sender = _a.sender; + if (args.map) + sendVote(sender, args.map); + else + currentMenu(sender); } }; }), surrender: (0, commands_1.command)(function () { diff --git a/src/commands/general.ts b/src/commands/general.ts index 178133c1..2dbb3804 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -10,10 +10,10 @@ import type { FishCommandData } from "/frameworks/commands/types"; import { Menu } from "/frameworks/menus"; import { capitalizeText, Duration, escapeTextDiscord, StringBuilder, StringIO, to2DArray } from "/funcs"; import { FishEvents, fishPlugin, fishState, ipPortPattern, recentWhispers, tileHistory, uuidPattern } from "/globals"; -import { FMap } from "/maps"; +import { FMap, PartialMapRun } from "/maps"; import { FishPlayer } from "/players"; import { Rank, RoleFlag } from "/ranks"; -import { formatTime, formatTimeRelative, getColor, logAction, nearbyEnemyTile, neutralGameover, skipWaves, teleportPlayer } from "/utils"; +import { formatTime, formatTimeRelative, getColor, logAction, nearbyEnemyTile, neutralGameover, outputMessage, skipWaves, teleportPlayer } from "/utils"; import { VoteManager } from "/votes"; export const commands = commandList({ @@ -838,6 +838,7 @@ Please stop attacking and [lime]build defenses[] first!` // } // }, + // no, it will not get the menu. yes, I know it sucks, but I doubt we nee forcenextmap: { args: ["map:map"], description: 'Override the next map in queue.', @@ -857,6 +858,7 @@ Please stop attacking and [lime]build defenses[] first!` }, + /* maps: { args: [], description: 'Lists the available maps.', @@ -873,6 +875,16 @@ ${Vars.maps.customMaps().toArray().map(map => ); } }, + */ + + maps:{ + description:'depreciated, please use /maps instead', + args:[], + perm:Perm.none, + handler:() => { + fail('This command was moved to /nextmap'); + }, + }, nextmap: command(() => { const votes = new Map(); @@ -882,6 +894,53 @@ ${Vars.maps.customMaps().toArray().map(map => const voteDuration = Duration.minutes(1.5); let task: TimerTask | null = null; + let currentMenu = (target:FishPlayer) => { + let mainMenu = Menu.raw("Fish Map Manager",`[accent]---Current Map---\nMap Name: [white]${Vars.state.map.name()}\n[accent]Map Author: [white]${Vars.state.map.author()}\nFastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)}\nCurrent Time: [white]${formatTime(PartialMapRun.current!.duration())}`, [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); + mainMenu.then((res) => { + switch(res){ + case '[green]Current Maps': + let CurrentMapsMenu = Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), {optionStringifier: (map:MMap) => {return map.name()}, rowsPerPage:10, columns:1}); + CurrentMapsMenu.catch(() => {}).then((map) => { + if(map == null) return; + let CurrentMapMenu = Menu.raw(map.name(), `[accent]Description: [white]${map.description()}\n[accent]Author: [white]${map.author()}\n[accent]Fastest Time: [white]${formatTime((FMap.getCreate(map)).stats().shortestTime)}\n[accent]Runs: [white]${(FMap.getCreate(map)).stats().allRunCount}\n[accent]Winrate: [white]${((FMap.getCreate(map)).stats().winRate * 100).toFixed(2)}%`, [["[green]Vote for this Map"], ["[red]Back"]], target); + CurrentMapMenu.then(res => { + switch(res){ + case("[green]Vote for this Map"): + sendVote(target, map); + break; + case("[red]Back"): + currentMenu(target); + break; + } + }); + }); + break; + case '[yellow]Throwback Maps': + outputMessage("Throwback maps have not yet been implemented.", target); + break; + case '[orange]Campaigns': + outputMessage("Campaigns have not yet been implemented.", target); + break; + case 'Close': + break; + } + }); + } + + function sendVote(sender:FishPlayer, map:MMap){ + if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); + if(votes.get(sender)) fail(`You have already voted.`); + + votes.set(sender, map); + if(voteEndTime == -1){ + if((Date.now() - lastVoteTime) < 60_000) fail(`Please wait 1 minute before starting a new map vote.`); + startVote(); + Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] started a map vote, and voted for [yellow]${map.name()}[cyan]. Use [white]/nextmap ${map.plainName()}[] to add your vote, or run [white]/maps[] to see other available maps.`); + } else { + Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] voted for [yellow]${map.name()}[cyan]. Time left: [scarlet]${formatTimeRelative(voteEndTime, true)}`); + showVotes(); + } + } function resetVotes(){ votes.clear(); voteEndTime = -1; @@ -949,24 +1008,14 @@ ${highestVotedMaps.map(({key:map, value:votes}) => Events.on(EventType.ServerLoadEvent, resetVotes); return { - args: ['map:map'], - description: 'Allows you to vote for the next map. Use /maps to see all available maps.', + args: ['map:map?'], + description: 'Allows you to vote for the next map.', perm: Perm.play, data: {votes, voteEndTime: () => voteEndTime, resetVotes, endVote}, requirements: [Req.cooldown(10_000)], - handler({args:{map}, sender}){ - if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); - if(votes.get(sender)) fail(`You have already voted.`); - - votes.set(sender, map); - if(voteEndTime == -1){ - if((Date.now() - lastVoteTime) < Duration.minutes(1)) fail(`Please wait 1 minute before starting a new map vote.`); - startVote(); - Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] started a map vote, and voted for [yellow]${map.name()}[cyan]. Use [white]/nextmap ${map.plainName()}[] to add your vote, or run [white]/maps[] to see other available maps.`); - } else { - Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] voted for [yellow]${map.name()}[cyan]. Time left: [scarlet]${formatTimeRelative(voteEndTime, true)}`); - showVotes(); - } + handler({args, sender}){ + if(args.map) sendVote(sender, args.map); + else currentMenu(sender); } }; }), From 975703a01d446d366e2c11d15763d1b7558db500 Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:11:26 +0530 Subject: [PATCH 02/12] format --- build/scripts/commands/general.js | 12 ++++---- src/commands/general.ts | 46 +++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index f01a4a14..b12aeffc 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -975,17 +975,15 @@ ${Vars.maps.customMaps().toArray().map(map => var voteEndTime = -1; var voteDuration = funcs_1.Duration.minutes(1.5); var task = null; - var currentMenu = function (target) { + function currentMenu(target) { var mainMenu = menus_1.Menu.raw("Fish Map Manager", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); mainMenu.then(function (res) { switch (res) { case '[green]Current Maps': - var CurrentMapsMenu = menus_1.Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 }); - CurrentMapsMenu.catch(function () { }).then(function (map) { + menus_1.Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 }).catch(function () { }).then(function (map) { if (map == null) return; - var CurrentMapMenu = menus_1.Menu.raw(map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [["[green]Vote for this Map"], ["[red]Back"]], target); - CurrentMapMenu.then(function (res) { + menus_1.Menu.raw(map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [["[green]Vote for this Map"], ["[red]Back"]], target).then(function (res) { switch (res) { case ("[green]Vote for this Map"): sendVote(target, map); @@ -1007,7 +1005,7 @@ ${Vars.maps.customMaps().toArray().map(map => break; } }); - }; + } function sendVote(sender, map) { if (config_1.Gamemode.testsrv()) (0, commands_1.fail)("Please use /forcenextmap instead."); @@ -1015,7 +1013,7 @@ ${Vars.maps.customMaps().toArray().map(map => (0, commands_1.fail)("You have already voted."); votes.set(sender, map); if (voteEndTime == -1) { - if ((Date.now() - lastVoteTime) < 60000) + if ((Date.now() - lastVoteTime) < funcs_1.Duration.minutes(1)) (0, commands_1.fail)("Please wait 1 minute before starting a new map vote."); startVote(); Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] started a map vote, and voted for [yellow]").concat(map.name(), "[cyan]. Use [white]/nextmap ").concat(map.plainName(), "[] to add your vote, or run [white]/maps[] to see other available maps.")); diff --git a/src/commands/general.ts b/src/commands/general.ts index 2dbb3804..5bdf81f2 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -877,11 +877,11 @@ ${Vars.maps.customMaps().toArray().map(map => }, */ - maps:{ - description:'depreciated, please use /maps instead', - args:[], - perm:Perm.none, - handler:() => { + maps: { + description: 'depreciated, please use /maps instead', + args: [], + perm: Perm.none, + handler(){ fail('This command was moved to /nextmap'); }, }, @@ -894,16 +894,38 @@ ${Vars.maps.customMaps().toArray().map(map => const voteDuration = Duration.minutes(1.5); let task: TimerTask | null = null; - let currentMenu = (target:FishPlayer) => { - let mainMenu = Menu.raw("Fish Map Manager",`[accent]---Current Map---\nMap Name: [white]${Vars.state.map.name()}\n[accent]Map Author: [white]${Vars.state.map.author()}\nFastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)}\nCurrent Time: [white]${formatTime(PartialMapRun.current!.duration())}`, [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); + function currentMenu(target:FishPlayer){ + const mainMenu = Menu.raw( + "Fish Map Manager", +`[accent]---Current Map--- +Map Name: [white]${Vars.state.map.name()} +[accent]Map Author: [white]${Vars.state.map.author()} +Fastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)} +Current Time: [white]${formatTime(PartialMapRun.current!.duration())}`, + [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], + target + ); mainMenu.then((res) => { switch(res){ case '[green]Current Maps': - let CurrentMapsMenu = Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), {optionStringifier: (map:MMap) => {return map.name()}, rowsPerPage:10, columns:1}); - CurrentMapsMenu.catch(() => {}).then((map) => { + Menu.pagedList( + target, + "Current Maps", + "", + Vars.maps.customMaps().toArray(), + { optionStringifier: map => map.name(), rowsPerPage: 10, columns: 1 } + ).catch(() => {}).then(map => { if(map == null) return; - let CurrentMapMenu = Menu.raw(map.name(), `[accent]Description: [white]${map.description()}\n[accent]Author: [white]${map.author()}\n[accent]Fastest Time: [white]${formatTime((FMap.getCreate(map)).stats().shortestTime)}\n[accent]Runs: [white]${(FMap.getCreate(map)).stats().allRunCount}\n[accent]Winrate: [white]${((FMap.getCreate(map)).stats().winRate * 100).toFixed(2)}%`, [["[green]Vote for this Map"], ["[red]Back"]], target); - CurrentMapMenu.then(res => { + Menu.raw( + map.name(), + `[accent]Description: [white]${map.description()} +[accent]Author: [white]${map.author()} +[accent]Fastest Time: [white]${formatTime((FMap.getCreate(map)).stats().shortestTime)} +[accent]Runs: [white]${(FMap.getCreate(map)).stats().allRunCount} +[accent]Winrate: [white]${((FMap.getCreate(map)).stats().winRate * 100).toFixed(2)}%`, + [["[green]Vote for this Map"], ["[red]Back"]], + target + ).then(res => { switch(res){ case("[green]Vote for this Map"): sendVote(target, map); @@ -933,7 +955,7 @@ ${Vars.maps.customMaps().toArray().map(map => votes.set(sender, map); if(voteEndTime == -1){ - if((Date.now() - lastVoteTime) < 60_000) fail(`Please wait 1 minute before starting a new map vote.`); + if((Date.now() - lastVoteTime) < Duration.minutes(1)) fail(`Please wait 1 minute before starting a new map vote.`); startVote(); Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] started a map vote, and voted for [yellow]${map.name()}[cyan]. Use [white]/nextmap ${map.plainName()}[] to add your vote, or run [white]/maps[] to see other available maps.`); } else { From 1827cb06358f58a75e15db81e945f9dfae4d11ae Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:56:21 +0530 Subject: [PATCH 03/12] rewrite using async/await and higher level menu functions --- src/commands/general.ts | 83 ++++++++++++++++++----------------------- src/frameworks/menus.ts | 6 +-- 2 files changed, 39 insertions(+), 50 deletions(-) diff --git a/src/commands/general.ts b/src/commands/general.ts index 5bdf81f2..62ab6c5c 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -894,61 +894,50 @@ ${Vars.maps.customMaps().toArray().map(map => const voteDuration = Duration.minutes(1.5); let task: TimerTask | null = null; - function currentMenu(target:FishPlayer){ - const mainMenu = Menu.raw( - "Fish Map Manager", -`[accent]---Current Map--- + async function currentMenu(target: FishPlayer): Promise { + const result = await Menu.menu( + "Select a map", + `[accent]---Current Map--- Map Name: [white]${Vars.state.map.name()} [accent]Map Author: [white]${Vars.state.map.author()} Fastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)} Current Time: [white]${formatTime(PartialMapRun.current!.duration())}`, - [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], - target + ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], + target, + { columns: 1, includeCancel: "Close" } ); - mainMenu.then((res) => { - switch(res){ - case '[green]Current Maps': - Menu.pagedList( - target, - "Current Maps", - "", - Vars.maps.customMaps().toArray(), - { optionStringifier: map => map.name(), rowsPerPage: 10, columns: 1 } - ).catch(() => {}).then(map => { - if(map == null) return; - Menu.raw( - map.name(), - `[accent]Description: [white]${map.description()} + switch (result) { + case '[green]Current Maps': { + const map = await Menu.pagedList( + target, + "Current Maps", + "Select a map to view more information.", + Vars.maps.customMaps().toArray(), + { optionStringifier: map => map.name(), rowsPerPage: 10, columns: 1 } + ); + const res = await Menu.buttons( + target, + map.name(), + `[accent]Description: [white]${map.description()} [accent]Author: [white]${map.author()} [accent]Fastest Time: [white]${formatTime((FMap.getCreate(map)).stats().shortestTime)} [accent]Runs: [white]${(FMap.getCreate(map)).stats().allRunCount} [accent]Winrate: [white]${((FMap.getCreate(map)).stats().winRate * 100).toFixed(2)}%`, - [["[green]Vote for this Map"], ["[red]Back"]], - target - ).then(res => { - switch(res){ - case("[green]Vote for this Map"): - sendVote(target, map); - break; - case("[red]Back"): - currentMenu(target); - break; - } - }); - }); - break; - case '[yellow]Throwback Maps': - outputMessage("Throwback maps have not yet been implemented.", target); - break; - case '[orange]Campaigns': - outputMessage("Campaigns have not yet been implemented.", target); - break; - case 'Close': - break; + [[ + { data: true, text: "[green]Vote for this Map" } + ], [ + { data: false, text: "[red]Back" } + ]], + { onCancel: "null" } + ); + if(res) return map; + else return currentMenu(target); } - }); + case '[yellow]Throwback Maps': fail("Throwback maps have not yet been implemented."); + case '[orange]Campaigns': fail("Campaigns have not yet been implemented."); + }; } - + function sendVote(sender:FishPlayer, map:MMap){ if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); if(votes.get(sender)) fail(`You have already voted.`); @@ -1035,9 +1024,9 @@ ${highestVotedMaps.map(({key:map, value:votes}) => perm: Perm.play, data: {votes, voteEndTime: () => voteEndTime, resetVotes, endVote}, requirements: [Req.cooldown(10_000)], - handler({args, sender}){ - if(args.map) sendVote(sender, args.map); - else currentMenu(sender); + async handler({args, sender}){ + args.map ??= await currentMenu(sender); + sendVote(sender, args.map); } }; }), diff --git a/src/frameworks/menus.ts b/src/frameworks/menus.ts index b1a67b54..58bc99d5 100644 --- a/src/frameworks/menus.ts +++ b/src/frameworks/menus.ts @@ -49,8 +49,8 @@ type MenuConfirmProps = { type MenuCancelOption = "ignore" | "reject" | "null"; type MenuOptions = { - /** [red]Cancel[] will be added to the list of options. */ - includeCancel?: boolean; + /** The specified text, or "[red]Cancel[]", will be added to the list of options. */ + includeCancel?: boolean | string; optionStringifier?: (opt: TOption) => string; columns?: number; /** @@ -142,7 +142,7 @@ export const Menu = { const arrangedOptions = (options.length == 0 && !includeCancel) ? [] : to2DArray(options, columns); if(includeCancel){ - arrangedOptions.push(["[red]Cancel[]" as never]); + arrangedOptions.push([(typeof includeCancel == "string" ? includeCancel : "[red]Cancel[]") as never]); //This is safe because cancelOptionId is set, //so the handler will never get called with "Cancel". cancelOptionId = options.length; From 3b7801b10fb6e92b4380bca9ad63e8a7aa263909 Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:56:59 +0530 Subject: [PATCH 04/12] Run checks before the menu --- build/scripts/commands/general.js | 104 +++++++++++++++++++----------- build/scripts/frameworks/menus.js | 2 +- src/commands/general.ts | 6 +- 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index b12aeffc..30808c81 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -976,41 +976,49 @@ ${Vars.maps.customMaps().toArray().map(map => var voteDuration = funcs_1.Duration.minutes(1.5); var task = null; function currentMenu(target) { - var mainMenu = menus_1.Menu.raw("Fish Map Manager", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); - mainMenu.then(function (res) { - switch (res) { - case '[green]Current Maps': - menus_1.Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 }).catch(function () { }).then(function (map) { - if (map == null) - return; - menus_1.Menu.raw(map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [["[green]Vote for this Map"], ["[red]Back"]], target).then(function (res) { - switch (res) { - case ("[green]Vote for this Map"): - sendVote(target, map); - break; - case ("[red]Back"): - currentMenu(target); - break; - } - }); - }); - break; - case '[yellow]Throwback Maps': - (0, utils_1.outputMessage)("Throwback maps have not yet been implemented.", target); - break; - case '[orange]Campaigns': - (0, utils_1.outputMessage)("Campaigns have not yet been implemented.", target); - break; - case 'Close': - break; - } + return __awaiter(this, void 0, void 0, function () { + var result, _a, map, res; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, menus_1.Menu.menu("Select a map", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], target, { columns: 1, includeCancel: "Close" })]; + case 1: + result = _b.sent(); + _a = result; + switch (_a) { + case '[green]Current Maps': return [3 /*break*/, 2]; + case '[yellow]Throwback Maps': return [3 /*break*/, 5]; + case '[orange]Campaigns': return [3 /*break*/, 6]; + } + return [3 /*break*/, 7]; + case 2: return [4 /*yield*/, menus_1.Menu.pagedList(target, "Current Maps", "Select a map to view more information.", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 })]; + case 3: + map = _b.sent(); + return [4 /*yield*/, menus_1.Menu.buttons(target, map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [[ + { data: true, text: "[green]Vote for this Map" } + ], [ + { data: false, text: "[red]Back" } + ]], { onCancel: "null" })]; + case 4: + res = _b.sent(); + if (res) + return [2 /*return*/, map]; + else + return [2 /*return*/, currentMenu(target)]; + _b.label = 5; + case 5: + (0, commands_1.fail)("Throwback maps have not yet been implemented."); + _b.label = 6; + case 6: + (0, commands_1.fail)("Campaigns have not yet been implemented."); + _b.label = 7; + case 7: + ; + return [2 /*return*/]; + } + }); }); } function sendVote(sender, map) { - if (config_1.Gamemode.testsrv()) - (0, commands_1.fail)("Please use /forcenextmap instead."); - if (votes.get(sender)) - (0, commands_1.fail)("You have already voted."); votes.set(sender, map); if (voteEndTime == -1) { if ((Date.now() - lastVoteTime) < funcs_1.Duration.minutes(1)) @@ -1083,11 +1091,33 @@ ${Vars.maps.customMaps().toArray().map(map => data: { votes: votes, voteEndTime: function () { return voteEndTime; }, resetVotes: resetVotes, endVote: endVote }, requirements: [commands_1.Req.cooldown(10000)], handler: function (_a) { - var args = _a.args, sender = _a.sender; - if (args.map) - sendVote(sender, args.map); - else - currentMenu(sender); + return __awaiter(this, arguments, void 0, function (_b) { + var _c, _d; + var _e; + var args = _b.args, sender = _b.sender; + return __generator(this, function (_f) { + switch (_f.label) { + case 0: + if (config_1.Gamemode.testsrv()) + (0, commands_1.fail)("Please use /forcenextmap instead."); + if (votes.get(sender)) + (0, commands_1.fail)("You have already voted."); + if (!((_e = args.map) !== null && _e !== void 0)) return [3 /*break*/, 1]; + _c = _e; + return [3 /*break*/, 3]; + case 1: + _d = args; + return [4 /*yield*/, currentMenu(sender)]; + case 2: + _c = (_d.map = _f.sent()); + _f.label = 3; + case 3: + _c; + sendVote(sender, args.map); + return [2 /*return*/]; + } + }); + }); } }; }), surrender: (0, commands_1.command)(function () { diff --git a/build/scripts/frameworks/menus.js b/build/scripts/frameworks/menus.js index f8106970..12db4529 100644 --- a/build/scripts/frameworks/menus.js +++ b/build/scripts/frameworks/menus.js @@ -170,7 +170,7 @@ exports.Menu = { //Call.menu() with [[]] will cause a client crash, make sure to pass [] instead var arrangedOptions = (options.length == 0 && !includeCancel) ? [] : (0, funcs_1.to2DArray)(options, columns); if (includeCancel) { - arrangedOptions.push(["[red]Cancel[]"]); + arrangedOptions.push([(typeof includeCancel == "string" ? includeCancel : "[red]Cancel[]")]); //This is safe because cancelOptionId is set, //so the handler will never get called with "Cancel". cancelOptionId = options.length; diff --git a/src/commands/general.ts b/src/commands/general.ts index 62ab6c5c..9a7938bb 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -939,9 +939,6 @@ Current Time: [white]${formatTime(PartialMapRun.current!.duration())}`, } function sendVote(sender:FishPlayer, map:MMap){ - if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); - if(votes.get(sender)) fail(`You have already voted.`); - votes.set(sender, map); if(voteEndTime == -1){ if((Date.now() - lastVoteTime) < Duration.minutes(1)) fail(`Please wait 1 minute before starting a new map vote.`); @@ -1025,6 +1022,9 @@ ${highestVotedMaps.map(({key:map, value:votes}) => data: {votes, voteEndTime: () => voteEndTime, resetVotes, endVote}, requirements: [Req.cooldown(10_000)], async handler({args, sender}){ + if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); + if(votes.get(sender)) fail(`You have already voted.`); + args.map ??= await currentMenu(sender); sendVote(sender, args.map); } From a956465eafddc67de7aa3798e3d14d6372045fbd Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:59:43 +0530 Subject: [PATCH 05/12] Keep the /maps command --- build/scripts/commands/general.js | 30 +++++++----------------------- src/commands/general.ts | 15 ++------------- 2 files changed, 9 insertions(+), 36 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index 30808c81..71ad6875 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -942,32 +942,16 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { outputSuccess(f(templateObject_17 || (templateObject_17 = __makeTemplateObject(["Forced the next map to be \"", "\" by ", ""], ["Forced the next map to be \"", "\" by ", ""])), args.map.name(), args.map.author())); } }, - }, - /* - maps: { + }, maps: { args: [], description: 'Lists the available maps.', - perm: Perm.none, - handler({output}){ - output(`\ -[yellow]Use [white]/nextmap [lightgray] [yellow]to vote on a map. - -[blue]Available maps: -_________________________ -${Vars.maps.customMaps().toArray().map(map => -`[yellow]${map.name()}` -).join("\n")}` - ); - } - }, - */ - maps: { - description: 'depreciated, please use /maps instead', - args: [], perm: commands_1.Perm.none, - handler: function () { - (0, commands_1.fail)('This command was moved to /nextmap'); - }, + handler: function (_a) { + var output = _a.output; + output("[yellow]Use [white]/nextmap [lightgray][[map name] [yellow]to vote on a map.\n\n[blue]Available maps:\n_________________________\n".concat(Vars.maps.customMaps().toArray().map(function (map) { + return "[yellow]".concat(map.name()); + }).join("\n"))); + } }, nextmap: (0, commands_1.command)(function () { var votes = new Map(); var lastVoteCount = 0; diff --git a/src/commands/general.ts b/src/commands/general.ts index 9a7938bb..80a35efe 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -858,33 +858,22 @@ Please stop attacking and [lime]build defenses[] first!` }, - /* maps: { args: [], description: 'Lists the available maps.', perm: Perm.none, handler({output}){ output(`\ -[yellow]Use [white]/nextmap [lightgray] [yellow]to vote on a map. +[yellow]Use [white]/nextmap [lightgray][[map name] [yellow]to vote on a map. [blue]Available maps: _________________________ ${Vars.maps.customMaps().toArray().map(map => -`[yellow]${map.name()}` + `[yellow]${map.name()}` ).join("\n")}` ); } }, - */ - - maps: { - description: 'depreciated, please use /maps instead', - args: [], - perm: Perm.none, - handler(){ - fail('This command was moved to /nextmap'); - }, - }, nextmap: command(() => { const votes = new Map(); From c7fd8f140012fde6725174131cd18a906bc2f007 Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Tue, 13 Jan 2026 13:04:37 +0530 Subject: [PATCH 06/12] fix crash --- build/scripts/commands/general.js | 19 ++++++++++--------- src/commands/general.ts | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index 71ad6875..ff5a42c1 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -962,11 +962,12 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { function currentMenu(target) { return __awaiter(this, void 0, void 0, function () { var result, _a, map, res; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: return [4 /*yield*/, menus_1.Menu.menu("Select a map", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], target, { columns: 1, includeCancel: "Close" })]; + var _b, _c, _d, _e; + return __generator(this, function (_f) { + switch (_f.label) { + case 0: return [4 /*yield*/, menus_1.Menu.menu("Select a map", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)((_e = (_c = (_b = maps_1.PartialMapRun.current) === null || _b === void 0 ? void 0 : _b.duration()) !== null && _c !== void 0 ? _c : (_d = maps_1.FMap.getCreate(Vars.state.map).runs.at(-1)) === null || _d === void 0 ? void 0 : _d.duration()) !== null && _e !== void 0 ? _e : 0)), ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], target, { columns: 1, includeCancel: "Close" })]; case 1: - result = _b.sent(); + result = _f.sent(); _a = result; switch (_a) { case '[green]Current Maps': return [3 /*break*/, 2]; @@ -976,25 +977,25 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { return [3 /*break*/, 7]; case 2: return [4 /*yield*/, menus_1.Menu.pagedList(target, "Current Maps", "Select a map to view more information.", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 })]; case 3: - map = _b.sent(); + map = _f.sent(); return [4 /*yield*/, menus_1.Menu.buttons(target, map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [[ { data: true, text: "[green]Vote for this Map" } ], [ { data: false, text: "[red]Back" } ]], { onCancel: "null" })]; case 4: - res = _b.sent(); + res = _f.sent(); if (res) return [2 /*return*/, map]; else return [2 /*return*/, currentMenu(target)]; - _b.label = 5; + _f.label = 5; case 5: (0, commands_1.fail)("Throwback maps have not yet been implemented."); - _b.label = 6; + _f.label = 6; case 6: (0, commands_1.fail)("Campaigns have not yet been implemented."); - _b.label = 7; + _f.label = 7; case 7: ; return [2 /*return*/]; diff --git a/src/commands/general.ts b/src/commands/general.ts index 80a35efe..754d28d7 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -890,7 +890,7 @@ ${Vars.maps.customMaps().toArray().map(map => Map Name: [white]${Vars.state.map.name()} [accent]Map Author: [white]${Vars.state.map.author()} Fastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)} -Current Time: [white]${formatTime(PartialMapRun.current!.duration())}`, +Current Time: [white]${formatTime(PartialMapRun.current?.duration() ?? FMap.getCreate(Vars.state.map).runs.at(-1)?.duration() ?? 0)}`, ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], target, { columns: 1, includeCancel: "Close" } From 75f8548c486416eeb88bbc24d0562986c797d27d Mon Sep 17 00:00:00 2001 From: Juror #9 <64419198+Jurorno9@users.noreply.github.com> Date: Mon, 12 Jan 2026 14:59:18 +0530 Subject: [PATCH 07/12] /nextmap revamp --- build/scripts/commands/general.js | 106 +++++++++++++++++++++++------- src/commands/general.ts | 83 ++++++++++++++++++----- 2 files changed, 147 insertions(+), 42 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index 37f21622..f01a4a14 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -923,6 +923,7 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { // votekickmanager.handleVote(sender, args ? 1 : -1); // } // }, + // no, it will not get the menu. yes, I know it sucks, but I doubt we nee forcenextmap: { args: ["map:map"], description: 'Override the next map in queue.', @@ -941,16 +942,32 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { outputSuccess(f(templateObject_17 || (templateObject_17 = __makeTemplateObject(["Forced the next map to be \"", "\" by ", ""], ["Forced the next map to be \"", "\" by ", ""])), args.map.name(), args.map.author())); } }, - }, maps: { + }, + /* + maps: { args: [], description: 'Lists the available maps.', - perm: commands_1.Perm.none, - handler: function (_a) { - var output = _a.output; - output("[yellow]Use [white]/nextmap [lightgray] [yellow]to vote on a map.\n\n[blue]Available maps:\n_________________________\n".concat(Vars.maps.customMaps().toArray().map(function (map) { - return "[yellow]".concat(map.name()); - }).join("\n"))); + perm: Perm.none, + handler({output}){ + output(`\ +[yellow]Use [white]/nextmap [lightgray] [yellow]to vote on a map. + +[blue]Available maps: +_________________________ +${Vars.maps.customMaps().toArray().map(map => +`[yellow]${map.name()}` +).join("\n")}` + ); } + }, + */ + maps: { + description: 'depreciated, please use /maps instead', + args: [], + perm: commands_1.Perm.none, + handler: function () { + (0, commands_1.fail)('This command was moved to /nextmap'); + }, }, nextmap: (0, commands_1.command)(function () { var votes = new Map(); var lastVoteCount = 0; @@ -958,6 +975,56 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { var voteEndTime = -1; var voteDuration = funcs_1.Duration.minutes(1.5); var task = null; + var currentMenu = function (target) { + var mainMenu = menus_1.Menu.raw("Fish Map Manager", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); + mainMenu.then(function (res) { + switch (res) { + case '[green]Current Maps': + var CurrentMapsMenu = menus_1.Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 }); + CurrentMapsMenu.catch(function () { }).then(function (map) { + if (map == null) + return; + var CurrentMapMenu = menus_1.Menu.raw(map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [["[green]Vote for this Map"], ["[red]Back"]], target); + CurrentMapMenu.then(function (res) { + switch (res) { + case ("[green]Vote for this Map"): + sendVote(target, map); + break; + case ("[red]Back"): + currentMenu(target); + break; + } + }); + }); + break; + case '[yellow]Throwback Maps': + (0, utils_1.outputMessage)("Throwback maps have not yet been implemented.", target); + break; + case '[orange]Campaigns': + (0, utils_1.outputMessage)("Campaigns have not yet been implemented.", target); + break; + case 'Close': + break; + } + }); + }; + function sendVote(sender, map) { + if (config_1.Gamemode.testsrv()) + (0, commands_1.fail)("Please use /forcenextmap instead."); + if (votes.get(sender)) + (0, commands_1.fail)("You have already voted."); + votes.set(sender, map); + if (voteEndTime == -1) { + if ((Date.now() - lastVoteTime) < 60000) + (0, commands_1.fail)("Please wait 1 minute before starting a new map vote."); + startVote(); + Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] started a map vote, and voted for [yellow]").concat(map.name(), "[cyan]. Use [white]/nextmap ").concat(map.plainName(), "[] to add your vote, or run [white]/maps[] to see other available maps.")); + } + else { + Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] voted for [yellow]").concat(map.name(), "[cyan]. Time left: [scarlet]").concat((0, utils_1.formatTimeRelative)(voteEndTime, true))); + showVotes(); + } + } function resetVotes() { votes.clear(); voteEndTime = -1; @@ -1012,28 +1079,17 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { Events.on(EventType.GameOverEvent, resetVotes); Events.on(EventType.ServerLoadEvent, resetVotes); return { - args: ['map:map'], - description: 'Allows you to vote for the next map. Use /maps to see all available maps.', + args: ['map:map?'], + description: 'Allows you to vote for the next map.', perm: commands_1.Perm.play, data: { votes: votes, voteEndTime: function () { return voteEndTime; }, resetVotes: resetVotes, endVote: endVote }, requirements: [commands_1.Req.cooldown(10000)], handler: function (_a) { - var map = _a.args.map, sender = _a.sender; - if (config_1.Gamemode.testsrv()) - (0, commands_1.fail)("Please use /forcenextmap instead."); - if (votes.get(sender)) - (0, commands_1.fail)("You have already voted."); - votes.set(sender, map); - if (voteEndTime == -1) { - if ((Date.now() - lastVoteTime) < funcs_1.Duration.minutes(1)) - (0, commands_1.fail)("Please wait 1 minute before starting a new map vote."); - startVote(); - Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] started a map vote, and voted for [yellow]").concat(map.name(), "[cyan]. Use [white]/nextmap ").concat(map.plainName(), "[] to add your vote, or run [white]/maps[] to see other available maps.")); - } - else { - Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] voted for [yellow]").concat(map.name(), "[cyan]. Time left: [scarlet]").concat((0, utils_1.formatTimeRelative)(voteEndTime, true))); - showVotes(); - } + var args = _a.args, sender = _a.sender; + if (args.map) + sendVote(sender, args.map); + else + currentMenu(sender); } }; }), surrender: (0, commands_1.command)(function () { diff --git a/src/commands/general.ts b/src/commands/general.ts index 178133c1..2dbb3804 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -10,10 +10,10 @@ import type { FishCommandData } from "/frameworks/commands/types"; import { Menu } from "/frameworks/menus"; import { capitalizeText, Duration, escapeTextDiscord, StringBuilder, StringIO, to2DArray } from "/funcs"; import { FishEvents, fishPlugin, fishState, ipPortPattern, recentWhispers, tileHistory, uuidPattern } from "/globals"; -import { FMap } from "/maps"; +import { FMap, PartialMapRun } from "/maps"; import { FishPlayer } from "/players"; import { Rank, RoleFlag } from "/ranks"; -import { formatTime, formatTimeRelative, getColor, logAction, nearbyEnemyTile, neutralGameover, skipWaves, teleportPlayer } from "/utils"; +import { formatTime, formatTimeRelative, getColor, logAction, nearbyEnemyTile, neutralGameover, outputMessage, skipWaves, teleportPlayer } from "/utils"; import { VoteManager } from "/votes"; export const commands = commandList({ @@ -838,6 +838,7 @@ Please stop attacking and [lime]build defenses[] first!` // } // }, + // no, it will not get the menu. yes, I know it sucks, but I doubt we nee forcenextmap: { args: ["map:map"], description: 'Override the next map in queue.', @@ -857,6 +858,7 @@ Please stop attacking and [lime]build defenses[] first!` }, + /* maps: { args: [], description: 'Lists the available maps.', @@ -873,6 +875,16 @@ ${Vars.maps.customMaps().toArray().map(map => ); } }, + */ + + maps:{ + description:'depreciated, please use /maps instead', + args:[], + perm:Perm.none, + handler:() => { + fail('This command was moved to /nextmap'); + }, + }, nextmap: command(() => { const votes = new Map(); @@ -882,6 +894,53 @@ ${Vars.maps.customMaps().toArray().map(map => const voteDuration = Duration.minutes(1.5); let task: TimerTask | null = null; + let currentMenu = (target:FishPlayer) => { + let mainMenu = Menu.raw("Fish Map Manager",`[accent]---Current Map---\nMap Name: [white]${Vars.state.map.name()}\n[accent]Map Author: [white]${Vars.state.map.author()}\nFastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)}\nCurrent Time: [white]${formatTime(PartialMapRun.current!.duration())}`, [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); + mainMenu.then((res) => { + switch(res){ + case '[green]Current Maps': + let CurrentMapsMenu = Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), {optionStringifier: (map:MMap) => {return map.name()}, rowsPerPage:10, columns:1}); + CurrentMapsMenu.catch(() => {}).then((map) => { + if(map == null) return; + let CurrentMapMenu = Menu.raw(map.name(), `[accent]Description: [white]${map.description()}\n[accent]Author: [white]${map.author()}\n[accent]Fastest Time: [white]${formatTime((FMap.getCreate(map)).stats().shortestTime)}\n[accent]Runs: [white]${(FMap.getCreate(map)).stats().allRunCount}\n[accent]Winrate: [white]${((FMap.getCreate(map)).stats().winRate * 100).toFixed(2)}%`, [["[green]Vote for this Map"], ["[red]Back"]], target); + CurrentMapMenu.then(res => { + switch(res){ + case("[green]Vote for this Map"): + sendVote(target, map); + break; + case("[red]Back"): + currentMenu(target); + break; + } + }); + }); + break; + case '[yellow]Throwback Maps': + outputMessage("Throwback maps have not yet been implemented.", target); + break; + case '[orange]Campaigns': + outputMessage("Campaigns have not yet been implemented.", target); + break; + case 'Close': + break; + } + }); + } + + function sendVote(sender:FishPlayer, map:MMap){ + if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); + if(votes.get(sender)) fail(`You have already voted.`); + + votes.set(sender, map); + if(voteEndTime == -1){ + if((Date.now() - lastVoteTime) < 60_000) fail(`Please wait 1 minute before starting a new map vote.`); + startVote(); + Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] started a map vote, and voted for [yellow]${map.name()}[cyan]. Use [white]/nextmap ${map.plainName()}[] to add your vote, or run [white]/maps[] to see other available maps.`); + } else { + Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] voted for [yellow]${map.name()}[cyan]. Time left: [scarlet]${formatTimeRelative(voteEndTime, true)}`); + showVotes(); + } + } function resetVotes(){ votes.clear(); voteEndTime = -1; @@ -949,24 +1008,14 @@ ${highestVotedMaps.map(({key:map, value:votes}) => Events.on(EventType.ServerLoadEvent, resetVotes); return { - args: ['map:map'], - description: 'Allows you to vote for the next map. Use /maps to see all available maps.', + args: ['map:map?'], + description: 'Allows you to vote for the next map.', perm: Perm.play, data: {votes, voteEndTime: () => voteEndTime, resetVotes, endVote}, requirements: [Req.cooldown(10_000)], - handler({args:{map}, sender}){ - if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); - if(votes.get(sender)) fail(`You have already voted.`); - - votes.set(sender, map); - if(voteEndTime == -1){ - if((Date.now() - lastVoteTime) < Duration.minutes(1)) fail(`Please wait 1 minute before starting a new map vote.`); - startVote(); - Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] started a map vote, and voted for [yellow]${map.name()}[cyan]. Use [white]/nextmap ${map.plainName()}[] to add your vote, or run [white]/maps[] to see other available maps.`); - } else { - Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] voted for [yellow]${map.name()}[cyan]. Time left: [scarlet]${formatTimeRelative(voteEndTime, true)}`); - showVotes(); - } + handler({args, sender}){ + if(args.map) sendVote(sender, args.map); + else currentMenu(sender); } }; }), From 54fcb448605d17cb5eb23036a7ce41e0e7bb0d43 Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:11:26 +0530 Subject: [PATCH 08/12] format --- build/scripts/commands/general.js | 12 ++++---- src/commands/general.ts | 46 +++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index f01a4a14..b12aeffc 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -975,17 +975,15 @@ ${Vars.maps.customMaps().toArray().map(map => var voteEndTime = -1; var voteDuration = funcs_1.Duration.minutes(1.5); var task = null; - var currentMenu = function (target) { + function currentMenu(target) { var mainMenu = menus_1.Menu.raw("Fish Map Manager", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); mainMenu.then(function (res) { switch (res) { case '[green]Current Maps': - var CurrentMapsMenu = menus_1.Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 }); - CurrentMapsMenu.catch(function () { }).then(function (map) { + menus_1.Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 }).catch(function () { }).then(function (map) { if (map == null) return; - var CurrentMapMenu = menus_1.Menu.raw(map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [["[green]Vote for this Map"], ["[red]Back"]], target); - CurrentMapMenu.then(function (res) { + menus_1.Menu.raw(map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [["[green]Vote for this Map"], ["[red]Back"]], target).then(function (res) { switch (res) { case ("[green]Vote for this Map"): sendVote(target, map); @@ -1007,7 +1005,7 @@ ${Vars.maps.customMaps().toArray().map(map => break; } }); - }; + } function sendVote(sender, map) { if (config_1.Gamemode.testsrv()) (0, commands_1.fail)("Please use /forcenextmap instead."); @@ -1015,7 +1013,7 @@ ${Vars.maps.customMaps().toArray().map(map => (0, commands_1.fail)("You have already voted."); votes.set(sender, map); if (voteEndTime == -1) { - if ((Date.now() - lastVoteTime) < 60000) + if ((Date.now() - lastVoteTime) < funcs_1.Duration.minutes(1)) (0, commands_1.fail)("Please wait 1 minute before starting a new map vote."); startVote(); Call.sendMessage("[cyan]Next Map Vote: ".concat(sender.name, "[cyan] started a map vote, and voted for [yellow]").concat(map.name(), "[cyan]. Use [white]/nextmap ").concat(map.plainName(), "[] to add your vote, or run [white]/maps[] to see other available maps.")); diff --git a/src/commands/general.ts b/src/commands/general.ts index 2dbb3804..5bdf81f2 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -877,11 +877,11 @@ ${Vars.maps.customMaps().toArray().map(map => }, */ - maps:{ - description:'depreciated, please use /maps instead', - args:[], - perm:Perm.none, - handler:() => { + maps: { + description: 'depreciated, please use /maps instead', + args: [], + perm: Perm.none, + handler(){ fail('This command was moved to /nextmap'); }, }, @@ -894,16 +894,38 @@ ${Vars.maps.customMaps().toArray().map(map => const voteDuration = Duration.minutes(1.5); let task: TimerTask | null = null; - let currentMenu = (target:FishPlayer) => { - let mainMenu = Menu.raw("Fish Map Manager",`[accent]---Current Map---\nMap Name: [white]${Vars.state.map.name()}\n[accent]Map Author: [white]${Vars.state.map.author()}\nFastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)}\nCurrent Time: [white]${formatTime(PartialMapRun.current!.duration())}`, [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); + function currentMenu(target:FishPlayer){ + const mainMenu = Menu.raw( + "Fish Map Manager", +`[accent]---Current Map--- +Map Name: [white]${Vars.state.map.name()} +[accent]Map Author: [white]${Vars.state.map.author()} +Fastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)} +Current Time: [white]${formatTime(PartialMapRun.current!.duration())}`, + [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], + target + ); mainMenu.then((res) => { switch(res){ case '[green]Current Maps': - let CurrentMapsMenu = Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), {optionStringifier: (map:MMap) => {return map.name()}, rowsPerPage:10, columns:1}); - CurrentMapsMenu.catch(() => {}).then((map) => { + Menu.pagedList( + target, + "Current Maps", + "", + Vars.maps.customMaps().toArray(), + { optionStringifier: map => map.name(), rowsPerPage: 10, columns: 1 } + ).catch(() => {}).then(map => { if(map == null) return; - let CurrentMapMenu = Menu.raw(map.name(), `[accent]Description: [white]${map.description()}\n[accent]Author: [white]${map.author()}\n[accent]Fastest Time: [white]${formatTime((FMap.getCreate(map)).stats().shortestTime)}\n[accent]Runs: [white]${(FMap.getCreate(map)).stats().allRunCount}\n[accent]Winrate: [white]${((FMap.getCreate(map)).stats().winRate * 100).toFixed(2)}%`, [["[green]Vote for this Map"], ["[red]Back"]], target); - CurrentMapMenu.then(res => { + Menu.raw( + map.name(), + `[accent]Description: [white]${map.description()} +[accent]Author: [white]${map.author()} +[accent]Fastest Time: [white]${formatTime((FMap.getCreate(map)).stats().shortestTime)} +[accent]Runs: [white]${(FMap.getCreate(map)).stats().allRunCount} +[accent]Winrate: [white]${((FMap.getCreate(map)).stats().winRate * 100).toFixed(2)}%`, + [["[green]Vote for this Map"], ["[red]Back"]], + target + ).then(res => { switch(res){ case("[green]Vote for this Map"): sendVote(target, map); @@ -933,7 +955,7 @@ ${Vars.maps.customMaps().toArray().map(map => votes.set(sender, map); if(voteEndTime == -1){ - if((Date.now() - lastVoteTime) < 60_000) fail(`Please wait 1 minute before starting a new map vote.`); + if((Date.now() - lastVoteTime) < Duration.minutes(1)) fail(`Please wait 1 minute before starting a new map vote.`); startVote(); Call.sendMessage(`[cyan]Next Map Vote: ${sender.name}[cyan] started a map vote, and voted for [yellow]${map.name()}[cyan]. Use [white]/nextmap ${map.plainName()}[] to add your vote, or run [white]/maps[] to see other available maps.`); } else { From a5517e6b45d45f4d28db73ec5ad1cf21a7ec9ce8 Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:56:21 +0530 Subject: [PATCH 09/12] rewrite using async/await and higher level menu functions --- src/commands/general.ts | 83 ++++++++++++++++++----------------------- src/frameworks/menus.ts | 6 +-- 2 files changed, 39 insertions(+), 50 deletions(-) diff --git a/src/commands/general.ts b/src/commands/general.ts index 5bdf81f2..62ab6c5c 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -894,61 +894,50 @@ ${Vars.maps.customMaps().toArray().map(map => const voteDuration = Duration.minutes(1.5); let task: TimerTask | null = null; - function currentMenu(target:FishPlayer){ - const mainMenu = Menu.raw( - "Fish Map Manager", -`[accent]---Current Map--- + async function currentMenu(target: FishPlayer): Promise { + const result = await Menu.menu( + "Select a map", + `[accent]---Current Map--- Map Name: [white]${Vars.state.map.name()} [accent]Map Author: [white]${Vars.state.map.author()} Fastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)} Current Time: [white]${formatTime(PartialMapRun.current!.duration())}`, - [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], - target + ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], + target, + { columns: 1, includeCancel: "Close" } ); - mainMenu.then((res) => { - switch(res){ - case '[green]Current Maps': - Menu.pagedList( - target, - "Current Maps", - "", - Vars.maps.customMaps().toArray(), - { optionStringifier: map => map.name(), rowsPerPage: 10, columns: 1 } - ).catch(() => {}).then(map => { - if(map == null) return; - Menu.raw( - map.name(), - `[accent]Description: [white]${map.description()} + switch (result) { + case '[green]Current Maps': { + const map = await Menu.pagedList( + target, + "Current Maps", + "Select a map to view more information.", + Vars.maps.customMaps().toArray(), + { optionStringifier: map => map.name(), rowsPerPage: 10, columns: 1 } + ); + const res = await Menu.buttons( + target, + map.name(), + `[accent]Description: [white]${map.description()} [accent]Author: [white]${map.author()} [accent]Fastest Time: [white]${formatTime((FMap.getCreate(map)).stats().shortestTime)} [accent]Runs: [white]${(FMap.getCreate(map)).stats().allRunCount} [accent]Winrate: [white]${((FMap.getCreate(map)).stats().winRate * 100).toFixed(2)}%`, - [["[green]Vote for this Map"], ["[red]Back"]], - target - ).then(res => { - switch(res){ - case("[green]Vote for this Map"): - sendVote(target, map); - break; - case("[red]Back"): - currentMenu(target); - break; - } - }); - }); - break; - case '[yellow]Throwback Maps': - outputMessage("Throwback maps have not yet been implemented.", target); - break; - case '[orange]Campaigns': - outputMessage("Campaigns have not yet been implemented.", target); - break; - case 'Close': - break; + [[ + { data: true, text: "[green]Vote for this Map" } + ], [ + { data: false, text: "[red]Back" } + ]], + { onCancel: "null" } + ); + if(res) return map; + else return currentMenu(target); } - }); + case '[yellow]Throwback Maps': fail("Throwback maps have not yet been implemented."); + case '[orange]Campaigns': fail("Campaigns have not yet been implemented."); + }; } - + function sendVote(sender:FishPlayer, map:MMap){ if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); if(votes.get(sender)) fail(`You have already voted.`); @@ -1035,9 +1024,9 @@ ${highestVotedMaps.map(({key:map, value:votes}) => perm: Perm.play, data: {votes, voteEndTime: () => voteEndTime, resetVotes, endVote}, requirements: [Req.cooldown(10_000)], - handler({args, sender}){ - if(args.map) sendVote(sender, args.map); - else currentMenu(sender); + async handler({args, sender}){ + args.map ??= await currentMenu(sender); + sendVote(sender, args.map); } }; }), diff --git a/src/frameworks/menus.ts b/src/frameworks/menus.ts index b1a67b54..58bc99d5 100644 --- a/src/frameworks/menus.ts +++ b/src/frameworks/menus.ts @@ -49,8 +49,8 @@ type MenuConfirmProps = { type MenuCancelOption = "ignore" | "reject" | "null"; type MenuOptions = { - /** [red]Cancel[] will be added to the list of options. */ - includeCancel?: boolean; + /** The specified text, or "[red]Cancel[]", will be added to the list of options. */ + includeCancel?: boolean | string; optionStringifier?: (opt: TOption) => string; columns?: number; /** @@ -142,7 +142,7 @@ export const Menu = { const arrangedOptions = (options.length == 0 && !includeCancel) ? [] : to2DArray(options, columns); if(includeCancel){ - arrangedOptions.push(["[red]Cancel[]" as never]); + arrangedOptions.push([(typeof includeCancel == "string" ? includeCancel : "[red]Cancel[]") as never]); //This is safe because cancelOptionId is set, //so the handler will never get called with "Cancel". cancelOptionId = options.length; From 84dc9ca95efd6f385a96498fb1842c25cdfddf57 Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:56:59 +0530 Subject: [PATCH 10/12] Run checks before the menu --- build/scripts/commands/general.js | 104 +++++++++++++++++++----------- build/scripts/frameworks/menus.js | 2 +- src/commands/general.ts | 6 +- 3 files changed, 71 insertions(+), 41 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index b12aeffc..30808c81 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -976,41 +976,49 @@ ${Vars.maps.customMaps().toArray().map(map => var voteDuration = funcs_1.Duration.minutes(1.5); var task = null; function currentMenu(target) { - var mainMenu = menus_1.Menu.raw("Fish Map Manager", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), [["[green]Current Maps"], ["[yellow]Throwback Maps"], ["[orange]Campaigns"], ["Close"]], target); - mainMenu.then(function (res) { - switch (res) { - case '[green]Current Maps': - menus_1.Menu.pagedList(target, "Current Maps", "", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 }).catch(function () { }).then(function (map) { - if (map == null) - return; - menus_1.Menu.raw(map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [["[green]Vote for this Map"], ["[red]Back"]], target).then(function (res) { - switch (res) { - case ("[green]Vote for this Map"): - sendVote(target, map); - break; - case ("[red]Back"): - currentMenu(target); - break; - } - }); - }); - break; - case '[yellow]Throwback Maps': - (0, utils_1.outputMessage)("Throwback maps have not yet been implemented.", target); - break; - case '[orange]Campaigns': - (0, utils_1.outputMessage)("Campaigns have not yet been implemented.", target); - break; - case 'Close': - break; - } + return __awaiter(this, void 0, void 0, function () { + var result, _a, map, res; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: return [4 /*yield*/, menus_1.Menu.menu("Select a map", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], target, { columns: 1, includeCancel: "Close" })]; + case 1: + result = _b.sent(); + _a = result; + switch (_a) { + case '[green]Current Maps': return [3 /*break*/, 2]; + case '[yellow]Throwback Maps': return [3 /*break*/, 5]; + case '[orange]Campaigns': return [3 /*break*/, 6]; + } + return [3 /*break*/, 7]; + case 2: return [4 /*yield*/, menus_1.Menu.pagedList(target, "Current Maps", "Select a map to view more information.", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 })]; + case 3: + map = _b.sent(); + return [4 /*yield*/, menus_1.Menu.buttons(target, map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [[ + { data: true, text: "[green]Vote for this Map" } + ], [ + { data: false, text: "[red]Back" } + ]], { onCancel: "null" })]; + case 4: + res = _b.sent(); + if (res) + return [2 /*return*/, map]; + else + return [2 /*return*/, currentMenu(target)]; + _b.label = 5; + case 5: + (0, commands_1.fail)("Throwback maps have not yet been implemented."); + _b.label = 6; + case 6: + (0, commands_1.fail)("Campaigns have not yet been implemented."); + _b.label = 7; + case 7: + ; + return [2 /*return*/]; + } + }); }); } function sendVote(sender, map) { - if (config_1.Gamemode.testsrv()) - (0, commands_1.fail)("Please use /forcenextmap instead."); - if (votes.get(sender)) - (0, commands_1.fail)("You have already voted."); votes.set(sender, map); if (voteEndTime == -1) { if ((Date.now() - lastVoteTime) < funcs_1.Duration.minutes(1)) @@ -1083,11 +1091,33 @@ ${Vars.maps.customMaps().toArray().map(map => data: { votes: votes, voteEndTime: function () { return voteEndTime; }, resetVotes: resetVotes, endVote: endVote }, requirements: [commands_1.Req.cooldown(10000)], handler: function (_a) { - var args = _a.args, sender = _a.sender; - if (args.map) - sendVote(sender, args.map); - else - currentMenu(sender); + return __awaiter(this, arguments, void 0, function (_b) { + var _c, _d; + var _e; + var args = _b.args, sender = _b.sender; + return __generator(this, function (_f) { + switch (_f.label) { + case 0: + if (config_1.Gamemode.testsrv()) + (0, commands_1.fail)("Please use /forcenextmap instead."); + if (votes.get(sender)) + (0, commands_1.fail)("You have already voted."); + if (!((_e = args.map) !== null && _e !== void 0)) return [3 /*break*/, 1]; + _c = _e; + return [3 /*break*/, 3]; + case 1: + _d = args; + return [4 /*yield*/, currentMenu(sender)]; + case 2: + _c = (_d.map = _f.sent()); + _f.label = 3; + case 3: + _c; + sendVote(sender, args.map); + return [2 /*return*/]; + } + }); + }); } }; }), surrender: (0, commands_1.command)(function () { diff --git a/build/scripts/frameworks/menus.js b/build/scripts/frameworks/menus.js index f8106970..12db4529 100644 --- a/build/scripts/frameworks/menus.js +++ b/build/scripts/frameworks/menus.js @@ -170,7 +170,7 @@ exports.Menu = { //Call.menu() with [[]] will cause a client crash, make sure to pass [] instead var arrangedOptions = (options.length == 0 && !includeCancel) ? [] : (0, funcs_1.to2DArray)(options, columns); if (includeCancel) { - arrangedOptions.push(["[red]Cancel[]"]); + arrangedOptions.push([(typeof includeCancel == "string" ? includeCancel : "[red]Cancel[]")]); //This is safe because cancelOptionId is set, //so the handler will never get called with "Cancel". cancelOptionId = options.length; diff --git a/src/commands/general.ts b/src/commands/general.ts index 62ab6c5c..9a7938bb 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -939,9 +939,6 @@ Current Time: [white]${formatTime(PartialMapRun.current!.duration())}`, } function sendVote(sender:FishPlayer, map:MMap){ - if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); - if(votes.get(sender)) fail(`You have already voted.`); - votes.set(sender, map); if(voteEndTime == -1){ if((Date.now() - lastVoteTime) < Duration.minutes(1)) fail(`Please wait 1 minute before starting a new map vote.`); @@ -1025,6 +1022,9 @@ ${highestVotedMaps.map(({key:map, value:votes}) => data: {votes, voteEndTime: () => voteEndTime, resetVotes, endVote}, requirements: [Req.cooldown(10_000)], async handler({args, sender}){ + if(Gamemode.testsrv()) fail(`Please use /forcenextmap instead.`); + if(votes.get(sender)) fail(`You have already voted.`); + args.map ??= await currentMenu(sender); sendVote(sender, args.map); } From 47d66b51720760a0b733f0964799dab76aa97b21 Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Tue, 13 Jan 2026 12:59:43 +0530 Subject: [PATCH 11/12] Keep the /maps command --- build/scripts/commands/general.js | 30 +++++++----------------------- src/commands/general.ts | 15 ++------------- 2 files changed, 9 insertions(+), 36 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index 30808c81..71ad6875 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -942,32 +942,16 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { outputSuccess(f(templateObject_17 || (templateObject_17 = __makeTemplateObject(["Forced the next map to be \"", "\" by ", ""], ["Forced the next map to be \"", "\" by ", ""])), args.map.name(), args.map.author())); } }, - }, - /* - maps: { + }, maps: { args: [], description: 'Lists the available maps.', - perm: Perm.none, - handler({output}){ - output(`\ -[yellow]Use [white]/nextmap [lightgray] [yellow]to vote on a map. - -[blue]Available maps: -_________________________ -${Vars.maps.customMaps().toArray().map(map => -`[yellow]${map.name()}` -).join("\n")}` - ); - } - }, - */ - maps: { - description: 'depreciated, please use /maps instead', - args: [], perm: commands_1.Perm.none, - handler: function () { - (0, commands_1.fail)('This command was moved to /nextmap'); - }, + handler: function (_a) { + var output = _a.output; + output("[yellow]Use [white]/nextmap [lightgray][[map name] [yellow]to vote on a map.\n\n[blue]Available maps:\n_________________________\n".concat(Vars.maps.customMaps().toArray().map(function (map) { + return "[yellow]".concat(map.name()); + }).join("\n"))); + } }, nextmap: (0, commands_1.command)(function () { var votes = new Map(); var lastVoteCount = 0; diff --git a/src/commands/general.ts b/src/commands/general.ts index 9a7938bb..80a35efe 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -858,33 +858,22 @@ Please stop attacking and [lime]build defenses[] first!` }, - /* maps: { args: [], description: 'Lists the available maps.', perm: Perm.none, handler({output}){ output(`\ -[yellow]Use [white]/nextmap [lightgray] [yellow]to vote on a map. +[yellow]Use [white]/nextmap [lightgray][[map name] [yellow]to vote on a map. [blue]Available maps: _________________________ ${Vars.maps.customMaps().toArray().map(map => -`[yellow]${map.name()}` + `[yellow]${map.name()}` ).join("\n")}` ); } }, - */ - - maps: { - description: 'depreciated, please use /maps instead', - args: [], - perm: Perm.none, - handler(){ - fail('This command was moved to /nextmap'); - }, - }, nextmap: command(() => { const votes = new Map(); From 7510ecac7b5add2750c54bebd98047f01bdbc5e9 Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Tue, 13 Jan 2026 13:04:37 +0530 Subject: [PATCH 12/12] fix crash --- build/scripts/commands/general.js | 19 ++++++++++--------- src/commands/general.ts | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index 71ad6875..ff5a42c1 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -962,11 +962,12 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { function currentMenu(target) { return __awaiter(this, void 0, void 0, function () { var result, _a, map, res; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: return [4 /*yield*/, menus_1.Menu.menu("Select a map", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)(maps_1.PartialMapRun.current.duration())), ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], target, { columns: 1, includeCancel: "Close" })]; + var _b, _c, _d, _e; + return __generator(this, function (_f) { + switch (_f.label) { + case 0: return [4 /*yield*/, menus_1.Menu.menu("Select a map", "[accent]---Current Map---\nMap Name: [white]".concat(Vars.state.map.name(), "\n[accent]Map Author: [white]").concat(Vars.state.map.author(), "\nFastest Time: [white]").concat((0, utils_1.formatTime)(maps_1.FMap.getCreate(Vars.state.map).stats().shortestTime), "\nCurrent Time: [white]").concat((0, utils_1.formatTime)((_e = (_c = (_b = maps_1.PartialMapRun.current) === null || _b === void 0 ? void 0 : _b.duration()) !== null && _c !== void 0 ? _c : (_d = maps_1.FMap.getCreate(Vars.state.map).runs.at(-1)) === null || _d === void 0 ? void 0 : _d.duration()) !== null && _e !== void 0 ? _e : 0)), ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], target, { columns: 1, includeCancel: "Close" })]; case 1: - result = _b.sent(); + result = _f.sent(); _a = result; switch (_a) { case '[green]Current Maps': return [3 /*break*/, 2]; @@ -976,25 +977,25 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { return [3 /*break*/, 7]; case 2: return [4 /*yield*/, menus_1.Menu.pagedList(target, "Current Maps", "Select a map to view more information.", Vars.maps.customMaps().toArray(), { optionStringifier: function (map) { return map.name(); }, rowsPerPage: 10, columns: 1 })]; case 3: - map = _b.sent(); + map = _f.sent(); return [4 /*yield*/, menus_1.Menu.buttons(target, map.name(), "[accent]Description: [white]".concat(map.description(), "\n[accent]Author: [white]").concat(map.author(), "\n[accent]Fastest Time: [white]").concat((0, utils_1.formatTime)((maps_1.FMap.getCreate(map)).stats().shortestTime), "\n[accent]Runs: [white]").concat((maps_1.FMap.getCreate(map)).stats().allRunCount, "\n[accent]Winrate: [white]").concat(((maps_1.FMap.getCreate(map)).stats().winRate * 100).toFixed(2), "%"), [[ { data: true, text: "[green]Vote for this Map" } ], [ { data: false, text: "[red]Back" } ]], { onCancel: "null" })]; case 4: - res = _b.sent(); + res = _f.sent(); if (res) return [2 /*return*/, map]; else return [2 /*return*/, currentMenu(target)]; - _b.label = 5; + _f.label = 5; case 5: (0, commands_1.fail)("Throwback maps have not yet been implemented."); - _b.label = 6; + _f.label = 6; case 6: (0, commands_1.fail)("Campaigns have not yet been implemented."); - _b.label = 7; + _f.label = 7; case 7: ; return [2 /*return*/]; diff --git a/src/commands/general.ts b/src/commands/general.ts index 80a35efe..754d28d7 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -890,7 +890,7 @@ ${Vars.maps.customMaps().toArray().map(map => Map Name: [white]${Vars.state.map.name()} [accent]Map Author: [white]${Vars.state.map.author()} Fastest Time: [white]${formatTime(FMap.getCreate(Vars.state.map).stats().shortestTime)} -Current Time: [white]${formatTime(PartialMapRun.current!.duration())}`, +Current Time: [white]${formatTime(PartialMapRun.current?.duration() ?? FMap.getCreate(Vars.state.map).runs.at(-1)?.duration() ?? 0)}`, ["[green]Current Maps", "[yellow]Throwback Maps", "[orange]Campaigns"], target, { columns: 1, includeCancel: "Close" }