-
Notifications
You must be signed in to change notification settings - Fork 4
Admin pause play #261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Admin pause play #261
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
f7836a3
Added pause dialogs
ymmot239 cafcf45
Notification dialog
ymmot239 e384175
Server pause structure
ymmot239 d87139b
Merge branch 'main' into admin-pause-play
ymmot239 a872c3f
advanced stop procedure
ymmot239 9fccb54
added robot saves
ymmot239 072b3a4
Merge branch 'main' into admin-pause-play
ymmot239 c2d7b5e
Added pause rollback
ymmot239 e166cf9
pause on reload
ymmot239 c2dfc02
Fixed merge conflicts
ymmot239 95d192c
Execution bugfix
ymmot239 c2cc89b
Apply suggestion from @Copilot
democat3457 fbffbc5
Readability and small bugs
ymmot239 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| import { | ||
| Button, | ||
| Dialog, | ||
| DialogBody, | ||
| DialogFooter, | ||
| NonIdealState, | ||
| } from "@blueprintjs/core"; | ||
| import { useState } from "react"; | ||
| import { bgColor, buttonColor, textColor } from "../check-dark-mode"; | ||
|
|
||
| interface DrawDialogProps { | ||
| dialogText?: string; | ||
| } | ||
|
|
||
| /** | ||
| * Shows a paused dialog that cannot be closed | ||
| * @param props - dialog text | ||
| * @returns - pause dialog | ||
| */ | ||
| export function PauseDialog(props: DrawDialogProps) { | ||
| const [isOpen, setIsOpen] = useState(true); | ||
| return ( | ||
| <Dialog | ||
| className={bgColor()} | ||
| isOpen={isOpen} | ||
| onClose={() => setIsOpen(false)} | ||
| canOutsideClickClose={false} | ||
| canEscapeKeyClose={false} | ||
| > | ||
| <DialogBody> | ||
| <NonIdealState> | ||
| <h4 className={textColor()}> | ||
| {props.dialogText || "Game Paused"} | ||
| </h4> | ||
| </NonIdealState> | ||
| </DialogBody> | ||
| </Dialog> | ||
| ); | ||
| } | ||
|
|
||
| interface NotificationDialogProps { | ||
| dialogText: string; | ||
| } | ||
|
|
||
| /** | ||
| * Shows a closable notification dialog | ||
| * @param props - dialog text | ||
| * @returns - notification dialog | ||
| */ | ||
| export function NotificationDialog(props: NotificationDialogProps) { | ||
| const [isOpen, setIsOpen] = useState(true); | ||
|
|
||
| /** okay button */ | ||
| const actions = ( | ||
| <Button | ||
| text="Continue" | ||
| rightIcon="arrow-right" | ||
| className={buttonColor()} | ||
| intent="primary" | ||
| onClick={() => { | ||
| setIsOpen(false); | ||
| }} | ||
| /> | ||
| ); | ||
|
|
||
| return ( | ||
| <Dialog | ||
| className={bgColor()} | ||
| isOpen={isOpen} | ||
| onClose={() => setIsOpen(false)} | ||
| canOutsideClickClose={true} | ||
| canEscapeKeyClose={true} | ||
| > | ||
| <DialogBody> | ||
| <NonIdealState> | ||
| <h4 className={textColor()}>{props.dialogText}</h4> | ||
| </NonIdealState> | ||
| </DialogBody> | ||
| <DialogFooter minimal actions={actions} /> | ||
| </Dialog> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -20,6 +20,7 @@ import { RegisterWebsocketMessage } from "../../common/message/message"; | |||||||||||||||||||||||
| import { | ||||||||||||||||||||||||
| clientManager, | ||||||||||||||||||||||||
| gameManager, | ||||||||||||||||||||||||
| gamePaused, | ||||||||||||||||||||||||
| setGameManager, | ||||||||||||||||||||||||
| socketManager, | ||||||||||||||||||||||||
| } from "./managers"; | ||||||||||||||||||||||||
|
|
@@ -59,6 +60,7 @@ import { | |||||||||||||||||||||||
| import { tcpServer } from "./tcp-interface"; | ||||||||||||||||||||||||
| import { robotManager } from "../robot/robot-manager"; | ||||||||||||||||||||||||
| import { executor } from "../command/executor"; | ||||||||||||||||||||||||
| import { GameHoldReason } from "../../common/game-end-reasons"; | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||
| * Helper function to move all robots from their home positions to their default positions | ||||||||||||||||||||||||
|
|
@@ -184,6 +186,17 @@ apiRouter.get("/client-information", async (req, res) => { | |||||||||||||||||||||||
| ), | ||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| const robotPos = new Map( | ||||||||||||||||||||||||
| oldSave!.robotPos?.map<[string, GridIndices]>((obj) => [ | ||||||||||||||||||||||||
| obj[1], | ||||||||||||||||||||||||
| new GridIndices( | ||||||||||||||||||||||||
| parseInt(obj[0].split(", ")[0]), | ||||||||||||||||||||||||
| parseInt(obj[0].split(", ")[1]), | ||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||
| ]), | ||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||
| console.log(robotPos); | ||||||||||||||||||||||||
| setAllRobotsToDefaultPositions(robotPos); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||
| * Note the client currently redirects to home from the game over screen | ||||||||||||||||||||||||
|
|
@@ -556,6 +569,50 @@ apiRouter.get("/get-puzzles", (_, res) => { | |||||||||||||||||||||||
| return res.send(out); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||
| * Pause the game | ||||||||||||||||||||||||
| * Todo: add authentication instead of an exposed pause call | ||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||
| apiRouter.get("/pause-game", (_, res) => { | ||||||||||||||||||||||||
| gamePaused.flag = true; | ||||||||||||||||||||||||
| robotManager.stopAllRobots(); | ||||||||||||||||||||||||
| socketManager.sendToAll(new GameHoldMessage(GameHoldReason.GAME_PAUSED)); | ||||||||||||||||||||||||
| return res.send({ message: "success" }); | ||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||
| * Unpause the game | ||||||||||||||||||||||||
| * Todo: add authentication instead of an exposed unpause call | ||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||
| apiRouter.get("/unpause-game", async (_, res) => { | ||||||||||||||||||||||||
|
Comment on lines
+586
to
+587
|
||||||||||||||||||||||||
| */ | |
| apiRouter.get("/unpause-game", async (_, res) => { | |
| * Now requires a valid x-api-key header. | |
| */ | |
| apiRouter.get("/unpause-game", async (req, res) => { | |
| // Simple authentication check using x-api-key header | |
| const API_KEY = "CHANGE_ME_TO_A_SECRET_KEY"; // Replace with env variable if available | |
| const clientKey = req.headers["x-api-key"]; | |
| if (clientKey !== API_KEY) { | |
| return res.status(401).send({ message: "Unauthorized" }); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pause endpoint is publicly accessible without authentication as noted in the TODO. This allows anyone to pause games, which could be abused to disrupt gameplay.