import React from 'react'; import { UploadRunContent } from '../types/Content'; import { ScoreboardTempUpdate, SourceDemoParser, NetMessages } from '@nekz/sdp'; import '../css/UploadRunDialog.css'; import { Game } from '../types/Game'; import { Map } from '../types/Map'; import { API } from '../api/Api'; import { useNavigate } from 'react-router-dom'; import useMessage from '../hooks/UseMessage'; import useConfirm from '../hooks/UseConfirm'; interface UploadRunDialogProps { token?: string; open: boolean; onClose: () => void; games: Game[]; } const UploadRunDialog: React.FC = ({ token, open, onClose, games }) => { const [confirmMessage, setConfirmMessage] = React.useState("Are you sure you want to upload this demo?"); const { message, MessageDialogComponent } = useMessage(); const { confirm, ConfirmDialogComponent } = useConfirm(); const navigate = useNavigate(); const [uploadRunContent, setUploadRunContent] = React.useState({ map_id: 0, host_demo: null, partner_demo: null, }); const [currentMap, setCurrentMap] = React.useState(""); const _set_current_map = (game_name: string) => { setCurrentMap(game_name); } const [selectedGameID, setSelectedGameID] = React.useState(0); const [selectedGameMaps, setSelectedGameMaps] = React.useState([]); const [selectedGameName, setSelectedGameName] = React.useState(""); // dropdowns const [dropdown1Vis, setDropdown1Vis] = React.useState(false); const [dropdown2Vis, setDropdown2Vis] = React.useState(false); const [loading, setLoading] = React.useState(false); const _handle_dropdowns = (dropdown: number) => { setDropdown1Vis(false); setDropdown2Vis(false); if (dropdown == 1) { setDropdown1Vis(!dropdown1Vis); } else if (dropdown == 2) { setDropdown2Vis(!dropdown2Vis); document.querySelector("#dropdown2")?.scrollTo(0, 0); } } const _handle_game_select = async (game_id: string, game_name: string) => { setLoading(true); const gameMaps = await API.get_game_maps(game_id); setSelectedGameMaps(gameMaps); setUploadRunContent({ map_id: gameMaps.find((map) => !map.is_disabled)!.id, //gameMaps[0].id, host_demo: null, partner_demo: null, }); _set_current_map(gameMaps.find((map) => !map.is_disabled)!.name); setSelectedGameID(parseInt(game_id) - 1); setSelectedGameName(game_name); setLoading(false); }; const _handle_file_change = async (e: React.ChangeEvent, host: boolean) => { if (e.target.files) { if (host) { setUploadRunContent({ ...uploadRunContent, host_demo: e.target.files[0], }); } else { setUploadRunContent({ ...uploadRunContent, partner_demo: e.target.files[0], }); } } }; const _upload_run = async () => { if (token) { if (games[selectedGameID].is_coop) { if (uploadRunContent.host_demo === null) { message("Error", "You must select a host demo to upload.") return } else if (uploadRunContent.partner_demo === null) { message("Error", "You must select a partner demo to upload.") return } } else { if (uploadRunContent.host_demo === null) { message("Error", "You must select a demo to upload.") return } } const demo = SourceDemoParser.default() .setOptions({ packets: true, header: true }) .parse(await uploadRunContent.host_demo.arrayBuffer()); const scoreboard = demo.findPacket((message) => { return message instanceof NetMessages.SvcUserMessage && message.userMessage instanceof ScoreboardTempUpdate; }) if (!scoreboard) { message("Error", "Error while processing demo: Unable to get scoreboard result. Either there is a demo that is corrupt or haven't been recorded in challenge mode.") return } const { portalScore, timeScore } = scoreboard.userMessage?.as() ?? {}; console.log(`Map Name: ${demo.mapName}. Portal Count: ${portalScore}. Ticks: ${timeScore}.`); setConfirmMessage(`Map Name: ${demo.mapName}\nPortal Count: ${portalScore}\nTicks: ${timeScore}\n\nAre you sure you want to upload this demo?`) const userConfirmed = await confirm("Upload demo?", confirmMessage); if (!userConfirmed) { return; } const response = await API.post_record(token, uploadRunContent); message("Message", response); // navigate(0); onClose(); } }; React.useEffect(() => { if (open) { _handle_game_select("1", "Portal 2 - Singleplayer"); // a different approach?. } }, [open]); if (open) { return ( <>
{MessageDialogComponent} {ConfirmDialogComponent}

Select Game

_handle_dropdowns(1)} style={{ display: "flex", alignItems: "center", cursor: "pointer", justifyContent: "space-between" }}>
{selectedGameName}
{games.map((game) => (
{ _handle_game_select(game.id.toString(), game.name); _handle_dropdowns(1) }} key={game.id}>{game.name}
))}
{ !loading && ( <>

Select Map

_handle_dropdowns(2)} style={{ display: "flex", alignItems: "center", cursor: "pointer", justifyContent: "space-between" }}> {currentMap}
Host Demo _handle_file_change(e, true)} /> { games[selectedGameID].is_coop && ( <> Partner Demo _handle_file_change(e, false)} /> ) }
) }
); } return ( <> ); }; export default UploadRunDialog;