Skip to content

Commit

Permalink
Add PVE player profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
Razzmatazzz committed Sep 14, 2024
1 parent 11461ad commit ba06b92
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 16 deletions.
13 changes: 12 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const WipeLength = React.lazy(() => import('./pages/wipe-length/index.js'));
const Achievements = React.lazy(() => import('./pages/achievements/index.js'));
const Players = React.lazy(() => import('./pages/players/index.js'));
const Player = React.lazy(() => import('./pages/player/index.js'));
const PlayerForward = React.lazy(() => import('./pages/player/player-forward.js'));
const Converter = React.lazy(() => import('./pages/converter/index.js'));
const About = React.lazy(() => import('./pages/about/index.js'));

Expand Down Expand Up @@ -924,7 +925,7 @@ function App() {
]}
/>
<Route
path="/player/:accountId"
path="/players/:gameMode/:accountId"
key="player-route"
element={[
<Suspense fallback={<Loading />} key="suspense-player-wrapper">
Expand All @@ -933,6 +934,16 @@ function App() {
remoteControlSessionElement,
]}
/>
<Route
path="/player/:accountId"
key="player-regular-route"
element={[
<Suspense fallback={<Loading />} key="suspense-player-forward-wrapper">
<PlayerForward />
</Suspense>,
remoteControlSessionElement,
]}
/>
<Route
path={'/converter'}
key="converter-route"
Expand Down
14 changes: 9 additions & 5 deletions src/modules/player-stats.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ const requestMethod = 'GET';

const playerStats = {
useTurnstile: false,
request: async (path, body) => {
request: async (path, gameMode, body) => {
try {
const method = body ? 'POST' : 'GET';
const response = await fetch(apiUrl + path, {
method,
body,
headers: {
'game-mode': gameMode,
}
});

if (response.status !== 200) {
Expand All @@ -33,13 +36,14 @@ const playerStats = {
}
return json;
} catch (error) {
console.log(error);
if (error.message.includes('NetworkError')) {
return Promise.reject(new Error('Rate limited exceeded. Wait one minute to send another request.'));
}
return Promise.reject(error);
}
},
searchPlayers: async (searchString, turnstileToken) => {
searchPlayers: async (searchString, gameMode = 'regular', turnstileToken) => {
// Create a form request to send the Turnstile token
// This avoids sending an extra pre-flight request
let body;
Expand All @@ -52,14 +56,14 @@ const playerStats = {
searchParams = `?token=${turnstileToken}`;
}
}
return playerStats.request(`/name/${searchString}${searchParams}`, body).catch(error => {
return playerStats.request(`/name/${searchString}${searchParams}`, gameMode, body).catch(error => {
if (error.message.includes('Malformed')) {
return Promise.reject(new Error('Error searching player profile; try removing one character from the end until the search works.'));
}
return Promise.reject(error);
});
},
getProfile: async (accountId, turnstileToken) => {
getProfile: async (accountId, gameMode = 'regular', turnstileToken) => {
let body;
let searchParams = '';
if (turnstileToken) {
Expand All @@ -70,7 +74,7 @@ const playerStats = {
searchParams = `?token=${turnstileToken}`;
}
}
return playerStats.request(`/account/${accountId}${searchParams}`, body);
return playerStats.request(`/account/${accountId}${searchParams}`, gameMode, body);
},
};

Expand Down
16 changes: 9 additions & 7 deletions src/pages/player/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ function Player() {
const params = useParams();
const navigate = useNavigate();

const gameMode = params.gameMode;

const [accountId, setAccountId] = useState(params.accountId);

useEffect(() => {
Expand Down Expand Up @@ -125,7 +127,7 @@ function Player() {
}
for (const result of searchResponse) {
if (result.name.toLowerCase() === accountId.toLowerCase()) {
navigate('/player/'+result.aid);
navigate(`/players/${gameMode}/${result.aid}`);
return;
}
}
Expand All @@ -143,7 +145,7 @@ function Player() {
} catch (error) {
setProfileError(error.message);
}
}, [accountId, setPlayerData, setProfileError, navigate, turnstileToken, turnstileRef]);
}, [accountId, setPlayerData, setProfileError, navigate, turnstileToken, turnstileRef, gameMode]);

const downloadProfile = useCallback(() => {
if (!playerData.aid) {
Expand All @@ -166,13 +168,13 @@ function Player() {
const data = JSON.parse(text);
data.saved = true;
setPlayerData(data);
window.history.replaceState(null, null, `/player/${data.aid}`);
window.history.replaceState(null, null, `/players/${gameMode}/${data.aid}`);
} catch(error) {
setProfileError('Error reading profile');
}
};
reader.readAsText(e.target.files[0]);
}, [setPlayerData, setProfileError]);
}, [setPlayerData, setProfileError, gameMode]);

const playerLevel = useMemo(() => {
if (playerData.info.experience === 0) {
Expand Down Expand Up @@ -708,11 +710,11 @@ function Player() {
countLabel = tag.Level;
let killerInfo = <span>{tag.KillerName}</span>;
if (tag.KillerAccountId) {
killerInfo = <Link to={`/player/${tag.KillerAccountId}`}>{tag.KillerName}</Link>;
killerInfo = <Link to={`/players/${gameMode}/${tag.KillerAccountId}`}>{tag.KillerName}</Link>;
}
label = (
<span>
<Link to={`/player/${tag.AccountId}`}>{tag.Nickname}</Link>
<Link to={`/players/${gameMode}/${tag.AccountId}`}>{tag.Nickname}</Link>
<span>{` ${t(tag.Status)} `}</span>
{killerInfo}
{weapon !== undefined && [
Expand Down Expand Up @@ -753,7 +755,7 @@ function Player() {
/>
);
return { image: itemImage, label };
}, [items, t]);
}, [items, t, gameMode]);

const getLoadoutContents = useCallback((parentItem, itemType = 'loadout') => {
const itemSource = itemType === 'loadout' ? playerData?.equipment?.Items : playerData?.favoriteItems;
Expand Down
9 changes: 9 additions & 0 deletions src/pages/player/player-forward.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { useParams, useNavigate } from 'react-router-dom';

function PlayerForward() {
const params = useParams();
const navigate = useNavigate();
navigate('/players/regular/'+params.accountId);
}

export default PlayerForward;
10 changes: 10 additions & 0 deletions src/pages/players/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,13 @@
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
}

.game-mode .select__control {
color: #1b1919;
background-color: #2d2c2e;
border-color: #9a8866;
}

.game-mode .select__single-value {
color: #fff;
}
30 changes: 27 additions & 3 deletions src/pages/players/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useState, useCallback, useMemo, useEffect, useRef } from 'react';
import { useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import { Trans, useTranslation } from 'react-i18next';
import { Turnstile } from '@marsidev/react-turnstile'

import Select from 'react-select';
import { Icon } from '@mdi/react';
import { mdiAccountSearch } from '@mdi/js';

Expand All @@ -12,6 +13,7 @@ import SEO from '../../components/SEO.jsx';
import { InputFilter } from '../../components/filter/index.js';

import playerStats from '../../modules/player-stats.mjs';
import gameModes from '../../data/game-modes.json';

import './index.css';

Expand All @@ -23,6 +25,9 @@ function Players() {

const enterPress = useKeyPress('Enter');

const gameModeSetting = useSelector((state) => state.settings.gameMode);
const [ gameMode, setGameMode ] = useState(gameModeSetting);

const [nameFilter, setNameFilter] = useState('');
const [nameResults, setNameResults] = useState([]);
const [nameResultsError, setNameResultsError] = useState(false);
Expand Down Expand Up @@ -56,7 +61,7 @@ function Players() {
try {
setNameResultsError(false);
setButtonDisabled(true);
setNameResults((await playerStats.searchPlayers(nameFilter, turnstileToken.current)).sort((a, b) => a.name.localeCompare(b.name)));
setNameResults((await playerStats.searchPlayers(nameFilter, gameMode, turnstileToken.current)).sort((a, b) => a.name.localeCompare(b.name)));
setSearched(true);
} catch (error) {
setSearched(false);
Expand All @@ -67,7 +72,7 @@ function Players() {
if (turnstileRef.current?.reset) {
turnstileRef.current.reset();
}
}, [nameFilter, searchTextValid, setNameResults, setNameResultsError, turnstileToken, turnstileRef]);
}, [nameFilter, searchTextValid, setNameResults, setNameResultsError, turnstileToken, turnstileRef, gameMode]);

const searchResults = useMemo(() => {
if (!searched) {
Expand Down Expand Up @@ -122,6 +127,25 @@ function Players() {
</p>
</Trans>
</div>
<label className={'single-filter-wrapper'} style={{marginBottom: '1em'}}>
<span className={'single-filter-label'}>{t('Game mode')}</span>
<Select
label={t('Game mode')}
placeholder={t(`game_mode_${gameModeSetting}`)}
defaultValue={gameModeSetting}
options={gameModes.map(m => {
return {
label: t(`game_mode_${m}`),
value: m,
}
})}
className="basic-multi-select game-mode"
classNamePrefix="select"
onChange={(event) => {
setGameMode(event.value);
}}
/>
</label>
<div className='search-controls'>
<InputFilter
label={t('Player Name')}
Expand Down

0 comments on commit ba06b92

Please sign in to comment.