Skip to content

Commit

Permalink
Rework leaderboard options in a separate dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
4ian committed Apr 30, 2024
1 parent 29d8284 commit aa76d59
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 271 deletions.
26 changes: 25 additions & 1 deletion Extensions/Leaderboards/JsExtension.js
Expand Up @@ -34,7 +34,9 @@ module.exports = {
.addAction(
'SavePlayerScore',
_('Save player score'),
_("Save the player's score to the given leaderboard."),
_(
"Save the player's score to the given leaderboard. If the player is connected, the score will be attached to the connected player (unless disabled)."
),
_(
'Send to leaderboard _PARAM1_ the score _PARAM2_ with player name: _PARAM3_'
),
Expand Down Expand Up @@ -92,6 +94,28 @@ module.exports = {
'gdjs.evtTools.leaderboards.saveConnectedPlayerScore'
);

extension
.addAction(
'SetPreferSendConnectedPlayerScore',
_('Enable the score to the connected player'),
_(
'Set if the score sent to a leaderboard is always attached to the connected player - if any. This is on by default.'
),
_('Always attach the score to the connected player: _PARAM0_'),
_('Setup'),
'JsPlatform/Extensions/leaderboard.svg',
'JsPlatform/Extensions/leaderboard.svg'
)
.addCodeOnlyParameter('currentScene', '')
.addParameter('yesorno', _('Enable?'), '', false)
.setHelpPath('/all-features/leaderboards')
.getCodeExtraInformation()
.setIncludeFile('Extensions/Leaderboards/leaderboardstools.js')
.setFunctionName(
'gdjs.evtTools.leaderboards.setPreferSendConnectedPlayerScore'
);
// TODO: add player authentication files.

extension
.addCondition(
'HasLastSaveErrored',
Expand Down
51 changes: 32 additions & 19 deletions Extensions/Leaderboards/leaderboardstools.ts
Expand Up @@ -6,6 +6,7 @@ namespace gdjs {
export namespace evtTools {
export namespace leaderboards {
let _hasPlayerJustClosedLeaderboardView = false;
let _preferSendConnectedPlayerScore = true;

gdjs.registerRuntimeScenePostEventsCallback(() => {
// Set it back to false for the next frame.
Expand All @@ -24,6 +25,9 @@ namespace gdjs {
return shaObj.getHash('B64');
};

const leaderboardHostBaseUrl = 'https://gd.games';
// const leaderboardHostBaseUrl = 'http://localhost:4000';

type PublicLeaderboardEntry = {
id: string;
claimSecret?: string;
Expand Down Expand Up @@ -219,8 +223,9 @@ namespace gdjs {
let _leaderboardViewIframeLoading: boolean = false;
let _leaderboardViewIframeLoaded: boolean = false;
let _errorTimeoutId: NodeJS.Timeout | null = null;
let _leaderboardMessageListener: ((event: MessageEvent) => void) | null =
null;
let _leaderboardMessageListener:
| ((event: MessageEvent) => void)
| null = null;

const _loaderContainer: HTMLDivElement = document.createElement('div');
_loaderContainer.style.backgroundColor = '#000000';
Expand Down Expand Up @@ -363,37 +368,41 @@ namespace gdjs {
}
};

export const setPreferSendConnectedPlayerScore = (enable: boolean) => {
_preferSendConnectedPlayerScore = enable;
};

export const savePlayerScore = (
runtimeScene: gdjs.RuntimeScene,
leaderboardId: string,
score: float,
playerName: string
) =>
new gdjs.PromiseTask(
(async () => {
// Get the connected player id and token, if any.
// TODO: make a setting for this??
const playerId = gdjs.playerAuthentication.getUserId();
const playerToken = gdjs.playerAuthentication.getUserToken();
) => {
if (
_preferSendConnectedPlayerScore &&
gdjs.playerAuthentication.isAuthenticated()
) {
return saveConnectedPlayerScore(runtimeScene, leaderboardId, score);
}

return new gdjs.PromiseTask(
(async () => {
const scoreSavingState = (_scoreSavingStateByLeaderboard[
leaderboardId
] =
_scoreSavingStateByLeaderboard[leaderboardId] ||
new ScoreSavingState());

try {
const { closeSaving, closeSavingWithError } =
scoreSavingState.startSaving({ playerName, score });
const {
closeSaving,
closeSavingWithError,
} = scoreSavingState.startSaving({ playerName, score });

try {
const leaderboardEntry = await saveScore({
leaderboardId,
playerName,
// TODO: make a setting for this??
authenticatedPlayerData: playerToken
? { playerId, playerToken }
: undefined,
score,
runtimeScene,
});
Expand All @@ -406,6 +415,7 @@ namespace gdjs {
}
})()
);
};

export const saveConnectedPlayerScore = (
runtimeScene: gdjs.RuntimeScene,
Expand All @@ -430,8 +440,10 @@ namespace gdjs {
new ScoreSavingState());

try {
const { closeSaving, closeSavingWithError } =
scoreSavingState.startSaving({ playerId, score });
const {
closeSaving,
closeSavingWithError,
} = scoreSavingState.startSaving({ playerId, score });

try {
const leaderboardEntryId = await saveScore({
Expand Down Expand Up @@ -865,8 +877,9 @@ namespace gdjs {

resetLeaderboardDisplayErrorTimeout(runtimeScene);

_leaderboardViewIframe =
computeLeaderboardDisplayingIframe(targetUrl);
_leaderboardViewIframe = computeLeaderboardDisplayingIframe(
targetUrl
);
if (typeof window !== 'undefined') {
_leaderboardMessageListener = (event: MessageEvent) => {
receiveMessageFromLeaderboardView(
Expand Down
68 changes: 47 additions & 21 deletions Extensions/PlayerAuthentication/playerauthenticationtools.ts
Expand Up @@ -25,8 +25,9 @@ namespace gdjs {
let _authenticationTimeoutId: NodeJS.Timeout | null = null;

// Communication methods.
let _authenticationMessageCallback: ((event: MessageEvent) => void) | null =
null;
let _authenticationMessageCallback:
| ((event: MessageEvent) => void)
| null = null;
let _websocket: WebSocket | null = null;

type PlayerAuthenticationCallbacks = {
Expand Down Expand Up @@ -377,7 +378,10 @@ namespace gdjs {
const receiveAuthenticationMessage = function (
runtimeScene: gdjs.RuntimeScene,
event: MessageEvent,
{ checkOrigin, callbacks }: { checkOrigin: boolean, callbacks?: PlayerAuthenticationCallbacks }
{
checkOrigin,
callbacks,
}: { checkOrigin: boolean; callbacks?: PlayerAuthenticationCallbacks }
) {
const allowedOrigins = ['https://liluo.io', 'https://gd.games'];

Expand Down Expand Up @@ -493,7 +497,7 @@ namespace gdjs {
const onOpenAuthenticationWindow = () => {
openAuthenticationWindow(runtimeScene);
};
console.log({_userToken, _userId, _username});

return _userToken
? authComponents.computeAuthenticatedBanner(
onOpenAuthenticationWindow,
Expand Down Expand Up @@ -727,8 +731,12 @@ namespace gdjs {
const top = screen.height / 2 - 600 / 2;
const windowFeatures = `left=${left},top=${top},width=500,height=600`;
const openWindow = () => {
_authenticationWindow = window.open(targetUrl, 'authentication', windowFeatures);
}
_authenticationWindow = window.open(
targetUrl,
'authentication',
windowFeatures
);
};

openWindow();

Expand Down Expand Up @@ -825,10 +833,13 @@ namespace gdjs {
if (_authenticationBanner) _authenticationBanner.style.opacity = '0';

const playerAuthPlatform = getPlayerAuthPlatform(runtimeScene);
const { rootContainer, loaderContainer, iframeContainer } =
authComponents.computeAuthenticationContainer(
onAuthenticationContainerDismissed
);
const {
rootContainer,
loaderContainer,
iframeContainer,
} = authComponents.computeAuthenticationContainer(
onAuthenticationContainerDismissed
);
_authenticationRootContainer = rootContainer;
_authenticationLoaderContainer = loaderContainer;
_authenticationIframeContainer = iframeContainer;
Expand All @@ -850,13 +861,12 @@ namespace gdjs {
)
: null; // Only show a link if we're on electron.

_authenticationTextContainer =
authComponents.addAuthenticationTextsToLoadingContainer(
_authenticationLoaderContainer,
playerAuthPlatform,
isGameRegistered,
wikiOpenAction
);
_authenticationTextContainer = authComponents.addAuthenticationTextsToLoadingContainer(
_authenticationLoaderContainer,
playerAuthPlatform,
isGameRegistered,
wikiOpenAction
);
}
if (isGameRegistered) {
startAuthenticationWindowTimeout(runtimeScene);
Expand All @@ -865,17 +875,33 @@ namespace gdjs {
// with a different window, with or without a websocket.
switch (playerAuthPlatform) {
case 'electron':
openAuthenticationWindowForElectron(runtimeScene, _gameId, callbacks);
openAuthenticationWindowForElectron(
runtimeScene,
_gameId,
callbacks
);
break;
case 'cordova':
openAuthenticationWindowForCordova(runtimeScene, _gameId, callbacks);
openAuthenticationWindowForCordova(
runtimeScene,
_gameId,
callbacks
);
break;
case 'web-iframe':
openAuthenticationIframeForWeb(runtimeScene, _gameId, callbacks);
openAuthenticationIframeForWeb(
runtimeScene,
_gameId,
callbacks
);
break;
case 'web':
default:
openAuthenticationWindowForWeb(runtimeScene, _gameId, callbacks);
openAuthenticationWindowForWeb(
runtimeScene,
_gameId,
callbacks
);
break;
}
}
Expand Down

0 comments on commit aa76d59

Please sign in to comment.