diff --git a/README.md b/README.md index d295dc3..5f2d017 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,68 @@ -# SDK Utils Player Library +# SDK Mini Games Library -This library provides utilities for managing player queues and active players in a scene. -## Exported Functions +## [Step 1: Install & Init Library](https://github.com/decentraland/sdk-mini-games/pull/19/files) -### initLibrary(_engine: IEngine, syncEntity: typeof syncEntity, playersApi: typeof players)` +#### Install @dcl-sdk/mini-games Library in your scene +```ts +// Run the following command in the scene terminal +npm install @dcl-sdk/mini-games@next +``` +#### Copy all the assets needed for the UI, Scoreboard and other models inside your scene. +```ts +// Run the following command in the scene terminal +node ./node_modules/@dcl-sdk/mini-games/scripts/postinstall.js +// This will create the `mini-games-assets` folder inside your scene with all the models that the library uses. +``` -Initializes the library with the necessary dependencies. Returns listeners that can be overridden with callbacks. +### Import Mini Games library in your scene +```ts +// game.ts file +import { initLibrary } from '@dcl-sdk/mini-games/src' +import { syncEntity } from '@dcl/sdk/network' +import players from '@dcl/sdk/players' -### setNextPlayer() +// make sure to put this line outside the main function. +initLibrary(engine, syncEntity, players, { + environment: 'dev', + gameId: 'game-id-here' +}) + +function main() { + // code scene here +} +``` -Sets the next player in the queue as active and removes the current active player. +## [Step 2: Players queue](https://github.com/decentraland/sdk-mini-games/pull/20/files) -### addPlayer() +The library provides all the logic behind to handle the multiplayers queue. + +### Queue Players Functions +```ts +import { queue } from '@dcl-sdk/mini-games/src' +``` + +#### queue.addPlayer(): void Adds the current player to the queue if they're not already in it. -### isActive(): boolean +#### queue.setNextPlayer(): void +Removes current player from the queue (if its the active one), and set the next player in the queue as active. +#### queue.isActive(): boolean Checks if the current user is the active player. -### getQueue() +#### queue.getQueue(): Player[] +Returns an array of players in the queue, sorted by the ime they join the queue. -Returns an array of players in the queue, sorted by join time. +#### queue.initQueueDisplay(displayTransform: TransformType): void +Create a display on the scene that informs the player the current status of the queue. +After installing the library needs to place display glb model in `mini-game-assets/models/queueDisplay/workstation_display.glb` -## Exported Types +### Listener for active player updates +#### listeners.onActivePlayerChange -### PlayerType +### Player Type ```typescript type PlayerType = { @@ -37,47 +73,119 @@ type PlayerType = { } ``` -## Exported Listeners -### onActivePlayerChange: (player: PlayerType) => void +## [Step 3: Scene Rotation + Game Area Checker + Timeout](https://github.com/decentraland/sdk-mini-games/pull/21/files) + +### Scene Rotation +Set the orientation of the scene. You can set any number but ideally you want to set 0, 90, 180 or 270. +This would add a RootEntity and then you can parent all the entities to this root entity so they all point to the same orientation. + + +### Game Area Check +You can define your play game area. So if the active player decides to leave the area, it switches automatically to the next player. +Also if a player finds a way to enter the game area and is not the active player, it will be kicked out. + +### Timeout check +Set a max amout of time that a player can play the game without being kicked. +If the player is alone in the game, it will continue playing till a new user arrives. + + +This can be done by passing extra params to the initLibrary +```ts +import { initLibrary, sceneParentEntity } from '@dcl-sdk/mini-games/src' +const _1_SEC = 1000 +const _1_MIN = _1_SEC * 60 + +miniGames.initLibrary(engine as any, syncEntity, playersApi, { + gameId: "4ee1d308-5e1e-4b2b-9e91-9091878a7e3d", + environment: "dev", + // time in ms + gameTimeoutMs: _1_MIN, + inactiveTimeoutMs: 20 * _1_SEC_, + // game area rectangle + gameArea: { + // top left point + topLeft: Vector3.create(5.15, 0, 2.23), + // bottom right point + bottomRight: Vector3.create(13.77, 0, 13.77), + // point outside the game area to exit players + exitSpawnPoint: Vector3.create(0,0,7) + } +}) +function main() { + const gameArea = engine.addEntity() + Transform.create(gameArea, { parent: sceneParentEntity, position, ...etc }) +} +``` -You can override this listener to perform custom actions when the active player changes. +## [Step 4: UI](https://github.com/decentraland/sdk-mini-games/pull/22/files) -## Example -```typescript -import { engine } from '@dcl/sdk/ecs' -import { syncEntity } from '@dcl/sdk/network' -import playersApi from '@dcl/sdk/players' -import { initPlayersQueue, listeners, addPlayer, isActive, getQueue, setNextPlayer } from './sdk-utils-player' +We already implement the generic UI to use inside the mini-games. Like the Play Game sign, Music On/Off, Levels, etc. -// Initialize the library -initPlayersQueue(engine, syncEntity, playersApi) +#### Menu Button UI -// Override the onActivePlayerChange listener -listeners.onActivePlayerChange = (player) => { - console.log(`New active player: ${player.address}`) -} -const startCube = createCube(2, 1, 2) -const finishCube = createCube(2, 4, 2) +```ts +// MenuButton(position: TransformType, assetShape, assetIcon, hoverText, callback, enabledByDefault (optional), releaseTime (optional) ) +import { ui } from '@dcl-sdk/mini-games/src' -// Listen to changes on the queue -listeners.onActivePlayerChange = (player) => { - console.log('active player changed', player) -} +// All the available icons +const icons = ui.uiAssets.icons +// All the available Shapes & Colors +const shapes = ui.uiAssets.shapes -// Add player to the queue -pointerEventsSystem.onPointerDown({ entity: startCube, opts: { hoverText: 'Add player to queue' } }, () => { - addPlayer() -}) -// Finish game and set the next player -pointerEventsSystem.onPointerDown({ entity: finishCube, opts: { hoverText: 'Finish game'} }, () => { - setNextPlayer() +new ui.MenuButton( + { + parent: sceneParentEntity, + position: Vector3.create(-3.74, 1.03, 0), + rotation: Quaternion.fromEulerDegrees(-45, 90, 0), + scale: Vector3.create(1.2, 1.2, 1.2) + }, + ui.uiAssets.shapes.RECT_GREEN, + ui.uiAssets.icons.playText, + "PLAY GAME", + () => { + queue.addPlayer() + } +) +``` + +## [Step 5: Progress API](https://github.com/decentraland/sdk-mini-games/pull/23/files) +We manage all the Progress API for you. We use the gameId set on the initLibrary, so be sure to update this value ! + +### Get last user progress of the game +```ts +type ProgressKey = 'level' | 'score' | 'moves' | 'time' +const userProgress = await progress.getProgress('level', progress.SortDirection.DESC, 1) +``` + +### Upsert the user progress based on the game. +```ts +import { progress } from '@dcl-sdk/mini-games/src' + +await progress.upsertProgress({ + level: gameData.currentLevel, + time: gameData.levelFinishedAt - gameData.levelStartedAt, + moves: gameData.moves }) +``` -// Check if current player is active -console.log(`Is current player active? ${isActive()}`); +## [Step 6: ScoreBoard](https://github.com/decentraland/sdk-mini-games/pull/24/files) +Initialize the scoreboard and that's it ! +```ts +// Add scoreboard + const width = 2.5 + const height = 2.8 + const scale = 1.2 + new ui.ScoreBoard( + { + // parent: sideSignB, + position: Vector3.create(1.3, 4, 0.15), + rotation: Quaternion.fromEulerDegrees(0, 180, 0) + }, + width, + height, + scale, + ui.TIME_LEVEL + ) -// Get the current Queue -const queue = getQueue(); -console.log('Current queue:', queue); ``` \ No newline at end of file diff --git a/example-scene/src/index.ts b/example-scene/src/index.ts index 685a47f..e380b82 100644 --- a/example-scene/src/index.ts +++ b/example-scene/src/index.ts @@ -45,6 +45,21 @@ export function main() { rotation: Quaternion.fromEulerDegrees(0, -90, 0) }) + // Add scoreboard + const width = 2.5 + const height = 2.8 + const scale = 1.2 + new ui.ScoreBoard( + { + position: Vector3.create(4, 4, 0.15), + rotation: Quaternion.fromEulerDegrees(0, 180, 0) + }, + width, + height, + scale, + ui.TIME_LEVEL + ) + // Add the Play Button to the fence instead of the old start game cube. new ui.MenuButton( { @@ -72,7 +87,7 @@ export function main() { queue.listeners.onActivePlayerChange = (player) => { // If the user is the active player, move it to the game area if (queue.isActive()) { - startGame() + void startGame() void movePlayerTo({ newRelativePosition: Vector3.create(6.5, 2, 8), cameraTarget: Vector3.create(13, 2, 8) }) } console.log('active player changed', player) diff --git a/package-lock.json b/package-lock.json index a4b984c..93122a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,8 +9,7 @@ "version": "1.0.0", "hasInstallScript": true, "dependencies": { - "@dcl/js-runtime": "latest", - "@dcl/sdk": "latest" + "@dcl/sdk": "^7.5.8-11038883764.commit-7e87395" }, "devDependencies": { "@dcl/eslint-config": "^2.2.1", @@ -315,16 +314,6 @@ "node": ">=6.9.0" } }, - "node_modules/@dcl-sdk/mini-games": { - "version": "1.0.0-20240809014550.commit-99a6336", - "resolved": "https://registry.npmjs.org/@dcl-sdk/mini-games/-/mini-games-1.0.0-20240809014550.commit-99a6336.tgz", - "integrity": "sha512-WJGFtYmBhy5slXOUnGZFQhQOcQD4pph9itp0LUAO0vEz+J3sML+gZudz2uQ1wgWcFqZkyHpS28nemdXxZVcefQ==", - "hasInstallScript": true, - "dependencies": { - "@dcl/js-runtime": "latest", - "@dcl/sdk": "latest" - } - }, "node_modules/@dcl-sdk/utils": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@dcl-sdk/utils/-/utils-1.2.8.tgz", @@ -332,357 +321,33 @@ "license": "Apache-2.0" }, "node_modules/@dcl/asset-packs": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/@dcl/asset-packs/-/asset-packs-1.20.0.tgz", - "integrity": "sha512-N90ZoXORvDyk+BFQPKOdtTpixeTltfa/U1dKmRPRQwAZwmt+C5U+73iJDrd3nyywpgEH6cjhqeatPX/HYL3amg==", + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/@dcl/asset-packs/-/asset-packs-1.20.1.tgz", + "integrity": "sha512-BDYM1Oc2W6NCG7YqcEzjp0Teeeam0+8wztjPdzr1hJ9bMByk8VrCnBSIAchoSQWjWcgcdDIVp5AAdd6TMBpygw==", "license": "ISC", "dependencies": { "@dcl-sdk/utils": "^1.2.8", + "@dcl/ecs": "^7.5.6", "@dcl/js-runtime": "7.5.2", - "@dcl/sdk": "7.5.2", - "mitt": "^3.0.1" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@dcl/asset-packs/-/asset-packs-1.19.0.tgz", - "integrity": "sha512-mPyjenp8qzqxgQELEDiKSBlKYuUNIKDvM8WlyT2k+YW/ySTv0e57ActCgUQs6ME1olZmjs+uBZtn97NSZGpazA==", - "license": "ISC", - "dependencies": { - "@dcl-sdk/utils": "^1.2.8", - "@dcl/js-runtime": "7.4.10", - "@dcl/sdk": "7.4.15", "mitt": "^3.0.1" } }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@dcl/asset-packs/-/asset-packs-1.16.0.tgz", - "integrity": "sha512-QOGyEmXj/g+42zMrshDQBYuk8lEuf+85bF92M5QQHeQ29FC2Uavs9HNL7NNz52/wWla5pP88ZlXEYGBezyVuZA==", - "license": "ISC", - "dependencies": { - "@dcl-sdk/utils": "^1.2.7", - "@dcl/js-runtime": "7.4.10", - "@dcl/sdk": "7.4.10", - "mitt": "^3.0.1" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/ecs": { - "version": "7.4.10", - "resolved": "https://registry.npmjs.org/@dcl/ecs/-/ecs-7.4.10.tgz", - "integrity": "sha512-0hpDWGGrFdqbDeFp38h33b4/rzMYceZm4My3bC3JEuUB1L+cnq+F0qZ49BUF699wgWYfyiyAA/I4bs3Nx8RcFw==", - "license": "Apache-2.0" - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/explorer": { - "version": "1.0.161055-20240311152126.commit-cae33b0", - "resolved": "https://registry.npmjs.org/@dcl/explorer/-/explorer-1.0.161055-20240311152126.commit-cae33b0.tgz", - "integrity": "sha512-iLSXjkGssjKagPAK9ylTO4pzCrao6qlSbBP73PlH4HBFwJXLQuRI0eLTWn2FfAO3UdwoJSsXRoZjwEmsZdML/w==", - "license": "Apache-2.0" - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/inspector": { - "version": "7.4.10", - "resolved": "https://registry.npmjs.org/@dcl/inspector/-/inspector-7.4.10.tgz", - "integrity": "sha512-alwv+yMV+KF74wTKpRERZ5lqMWn4MWAKCiqg2srj2WsKZDQDrX2pIhuLF0AoiyGM80RA1k+AjzDc8uDnZmR+mA==", - "dependencies": { - "@dcl/asset-packs": "^1.14.0", - "ts-deepmerge": "^7.0.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/react-ecs": { - "version": "7.4.10", - "resolved": "https://registry.npmjs.org/@dcl/react-ecs/-/react-ecs-7.4.10.tgz", - "integrity": "sha512-w8duoBH+byyOc+PL4iUCnVsZxsiJfCDuGeenjrXhTHTf41ErIjAYheZ+3oLDPZWAp3m3y9Mhww01tX9e3bEeCQ==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/ecs": "7.4.10", - "react": "^18.2.0", - "react-reconciler": "^0.29.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/sdk": { - "version": "7.4.10", - "resolved": "https://registry.npmjs.org/@dcl/sdk/-/sdk-7.4.10.tgz", - "integrity": "sha512-mHErm/5VPaOmUpeIXnTAvccTHAnrFMQ5iKXnLT0RfQM2qXfUZy98yhqx8x2Nwxjn4UtABw7p2tZQZRnO1FCvOQ==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/ecs": "7.4.10", - "@dcl/ecs-math": "2.0.2", - "@dcl/explorer": "1.0.161055-20240311152126.commit-cae33b0", - "@dcl/js-runtime": "7.4.10", - "@dcl/react-ecs": "7.4.10", - "@dcl/sdk-commands": "7.4.10", - "text-encoding": "0.7.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/sdk-commands": { - "version": "7.4.10", - "resolved": "https://registry.npmjs.org/@dcl/sdk-commands/-/sdk-commands-7.4.10.tgz", - "integrity": "sha512-7OKg5Agqtz4mO3k5IuScm6DLRUCmQyZIYQocAJSKy9zGNdim2siF0vo5nxU8b9KzvxpEb9uySPVkcNBMwyLf+A==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/crypto": "^3.4.4", - "@dcl/ecs": "7.4.10", - "@dcl/hashing": "1.1.3", - "@dcl/inspector": "7.4.10", - "@dcl/linker-dapp": "^0.12.0", - "@dcl/mini-comms": "1.0.1-20230216163137.commit-a4c75be", - "@dcl/protocol": "1.0.0-8299166777.commit-9493ffe", - "@dcl/quests-client": "^1.0.3", - "@dcl/quests-manager": "^0.1.4", - "@dcl/rpc": "^1.1.1", - "@dcl/schemas": "^8.2.3-20230718182824.commit-356025c", - "@segment/analytics-node": "^1.1.3", - "@well-known-components/env-config-provider": "^1.2.0", - "@well-known-components/fetch-component": "^2.0.2", - "@well-known-components/http-server": "^2.0.0-20230501134558.commit-be9a25d", - "@well-known-components/logger": "^3.1.2", - "@well-known-components/metrics": "^2.0.1", - "archiver": "^5.3.1", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "colorette": "^2.0.19", - "dcl-catalyst-client": "^21.5.0", - "esbuild": "^0.18.17", - "extract-zip": "2.0.1", - "fp-future": "^1.0.1", - "glob": "^9.3.2", - "ignore": "^5.2.4", - "node-fetch": "^2.7.0", - "open": "^8.4.0", - "portfinder": "^1.0.32", - "prompts": "^2.4.2", - "typescript": "^5.0.2", - "undici": "^5.19.1", - "uuid": "^9.0.1" - }, - "bin": { - "sdk-commands": "dist/index.js" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/ecs": { - "version": "7.4.15", - "resolved": "https://registry.npmjs.org/@dcl/ecs/-/ecs-7.4.15.tgz", - "integrity": "sha512-iGetQ19PpHq/NWs5SeqCFShg34iPmYK0IfIch8gmqPjOnLilRIanYg8Q0y1IzsZYs6kJ8sQf435xA76h07btiQ==", - "license": "Apache-2.0" - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/explorer": { - "version": "1.0.161749-20240401171209.commit-d6d28f4", - "resolved": "https://registry.npmjs.org/@dcl/explorer/-/explorer-1.0.161749-20240401171209.commit-d6d28f4.tgz", - "integrity": "sha512-5jji07MVmMiNPY9gIHWrL3Wwh4SpdaUKnzMHMiKy830QJ1Nif9jpi5qcISmoDdXhoEJbC2vM1Gyj5D4rQibHew==", - "license": "Apache-2.0" - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/inspector": { - "version": "7.4.15", - "resolved": "https://registry.npmjs.org/@dcl/inspector/-/inspector-7.4.15.tgz", - "integrity": "sha512-gFzOmKvYRdKk1dkSjsrn937LJELYy24WSdHxxW/3hXBwwcm32pysrU/3prMxl7T4wrCXSOqbkeofA9udNzo24Q==", - "dependencies": { - "@dcl/asset-packs": "1.16.0", - "ts-deepmerge": "^7.0.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/js-runtime": { - "version": "7.4.10", - "resolved": "https://registry.npmjs.org/@dcl/js-runtime/-/js-runtime-7.4.10.tgz", - "integrity": "sha512-h3coABWz24xFZosDh1cj1CVK64IaSq53yfvgXzO6FHrvnTxgHnRd+VRgQtfIBGpI+P4Oy3/XOSXHvrFTW36IYQ==", - "license": "Apache-2.0" - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/protocol": { - "version": "1.0.0-8299166777.commit-9493ffe", - "resolved": "https://registry.npmjs.org/@dcl/protocol/-/protocol-1.0.0-8299166777.commit-9493ffe.tgz", - "integrity": "sha512-QgYSltXnQvDlt66BsxRJ/o77xOPWDH1ku+OE8jchohwyXEY8KD5UV/seNU2u+TM8iPMjE+9a40p2AAtAjBnsJQ==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/ts-proto": "1.154.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/react-ecs": { - "version": "7.4.15", - "resolved": "https://registry.npmjs.org/@dcl/react-ecs/-/react-ecs-7.4.15.tgz", - "integrity": "sha512-FnupG6D+ufu894nOxtrosgC8aKi97VxdyA4bRq4LpfPC0E2RwMb4TqwfQRVQIpYXOyKa/XDzdQbg7lnWAS7qew==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/ecs": "7.4.15", - "react": "^18.2.0", - "react-reconciler": "^0.29.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/sdk": { - "version": "7.4.15", - "resolved": "https://registry.npmjs.org/@dcl/sdk/-/sdk-7.4.15.tgz", - "integrity": "sha512-45LYGhuAmzQmcD+RfdrybSYexA88rkZvTTnag5+v/q31wpXMk46+WMOddy82zl1XRbb9Qo31f/ZlGmzfsJUiMQ==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/ecs": "7.4.15", - "@dcl/ecs-math": "2.0.2", - "@dcl/explorer": "1.0.161749-20240401171209.commit-d6d28f4", - "@dcl/js-runtime": "7.4.15", - "@dcl/react-ecs": "7.4.15", - "@dcl/sdk-commands": "7.4.15", - "text-encoding": "0.7.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/sdk-commands": { - "version": "7.4.15", - "resolved": "https://registry.npmjs.org/@dcl/sdk-commands/-/sdk-commands-7.4.15.tgz", - "integrity": "sha512-U+a2LpEst+8ofOPLh/JAu3sDmNMsZvooRWhnp1r7vENDaYrXe3Kiq+Z09CuZvIB7afvQ6mhrJGWNW12eEYtsyg==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/crypto": "^3.4.4", - "@dcl/ecs": "7.4.15", - "@dcl/hashing": "1.1.3", - "@dcl/inspector": "7.4.15", - "@dcl/linker-dapp": "^0.12.0", - "@dcl/mini-comms": "1.0.1-20230216163137.commit-a4c75be", - "@dcl/protocol": "1.0.0-8299166777.commit-9493ffe", - "@dcl/quests-client": "^1.0.3", - "@dcl/quests-manager": "^0.1.4", - "@dcl/rpc": "^1.1.1", - "@dcl/schemas": "^8.2.3-20230718182824.commit-356025c", - "@segment/analytics-node": "^1.1.3", - "@well-known-components/env-config-provider": "^1.2.0", - "@well-known-components/fetch-component": "^2.0.2", - "@well-known-components/http-server": "^2.0.0-20230501134558.commit-be9a25d", - "@well-known-components/logger": "^3.1.2", - "@well-known-components/metrics": "^2.0.1", - "archiver": "^5.3.1", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "colorette": "^2.0.19", - "dcl-catalyst-client": "^21.6.1", - "esbuild": "^0.18.17", - "extract-zip": "2.0.1", - "fp-future": "^1.0.1", - "glob": "^9.3.2", - "ignore": "^5.2.4", - "node-fetch": "^2.7.0", - "open": "^8.4.0", - "portfinder": "^1.0.32", - "prompts": "^2.4.2", - "typescript": "^5.0.2", - "undici": "^5.19.1", - "uuid": "^9.0.1" - }, - "bin": { - "sdk-commands": "dist/index.js" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/asset-packs/node_modules/@dcl/sdk/node_modules/@dcl/js-runtime": { - "version": "7.4.15", - "resolved": "https://registry.npmjs.org/@dcl/js-runtime/-/js-runtime-7.4.15.tgz", - "integrity": "sha512-GZkr/KNtm6VfcaBSrVO011NMQpHm4sSRWWSZOIOQ1K0wR/k95AbIx+T1efFaGQN2y9n60PUK9cdbAuInBK0RLg==", - "license": "Apache-2.0" - }, "node_modules/@dcl/asset-packs/node_modules/@dcl/ecs": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/@dcl/ecs/-/ecs-7.5.2.tgz", - "integrity": "sha512-f1+TF2f5Gkg2Xl7bQ+KWNMOYubNdZIVXQC+xU54iH4l8o+a4S2PzI8yzALfvThtXh1PsSrmm/6mOmg0B2O6oJA==", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/@dcl/ecs/-/ecs-7.5.7.tgz", + "integrity": "sha512-hNDXz6FXx3x5+WHVjkQ5/CvWq9P3+Jp6uKupAplSjzf+dBTxgEH3O4tlZQ8yLg8zOu9ouXtlsxj9e0I2R7EYiw==", "license": "Apache-2.0" }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/explorer": { - "version": "1.0.163304-20240520163732.commit-e8937d1", - "resolved": "https://registry.npmjs.org/@dcl/explorer/-/explorer-1.0.163304-20240520163732.commit-e8937d1.tgz", - "integrity": "sha512-RWnbLM4WocFH02btXVKnAoCzUT+WmQ6evfxrNNp5BpX16yyhvz9VgIx9Gd47Oi7pW6tb/CZgUYuSIPB6TfMY1A==", - "license": "Apache-2.0" - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/inspector": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/@dcl/inspector/-/inspector-7.5.2.tgz", - "integrity": "sha512-6LCPD/0mymqh/TqRuvBIAFVVmQ83a26CpHad+luQxJL+IPEZ8Yt0A684DsMHZOSGZPk7Zt5ivNTXW7QMmUJ8Gg==", - "dependencies": { - "@dcl/asset-packs": "1.19.0", - "ts-deepmerge": "^7.0.0" - } - }, "node_modules/@dcl/asset-packs/node_modules/@dcl/js-runtime": { "version": "7.5.2", "resolved": "https://registry.npmjs.org/@dcl/js-runtime/-/js-runtime-7.5.2.tgz", "integrity": "sha512-KZbxb2ONV6QlKmCer0gi/1Z0DKD6TcZZK+wfHRPlFrrIwd9ZoYRbKAqZXDChu1ZgWen2k3GwvYCEP7vyI/Ay3Q==", "license": "Apache-2.0" }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/protocol": { - "version": "1.0.0-9115457439.commit-926ebd1", - "resolved": "https://registry.npmjs.org/@dcl/protocol/-/protocol-1.0.0-9115457439.commit-926ebd1.tgz", - "integrity": "sha512-4MA1sx4cpfapP+EDAZdpdaONthoDlv4VMc0CwAKcmhp0vxGgExeEpLkPh6gvNXmkl8z8z3nEcDOX1X95dvCYuA==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/ts-proto": "1.154.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/react-ecs": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/@dcl/react-ecs/-/react-ecs-7.5.2.tgz", - "integrity": "sha512-O3clRhPYEv91kaFijfLdGjLE7fLiRdxGu1vF5CzirR6cju7UmRi7DPb4BzxdIHQvYYWb+m2JmVNZ8ckz9mvsRw==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/ecs": "7.5.2", - "react": "^18.2.0", - "react-reconciler": "^0.29.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/sdk": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/@dcl/sdk/-/sdk-7.5.2.tgz", - "integrity": "sha512-SlJXEgXdKeZAjQp27b684v6wCSAvu66RcBKdUcQsokkdTuW1Se15c5MhMNGv3KexV75DgTGiQEPVSAnsYJBGhg==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/ecs": "7.5.2", - "@dcl/ecs-math": "2.0.2", - "@dcl/explorer": "1.0.163304-20240520163732.commit-e8937d1", - "@dcl/js-runtime": "7.5.2", - "@dcl/react-ecs": "7.5.2", - "@dcl/sdk-commands": "7.5.2", - "text-encoding": "0.7.0" - } - }, - "node_modules/@dcl/asset-packs/node_modules/@dcl/sdk-commands": { - "version": "7.5.2", - "resolved": "https://registry.npmjs.org/@dcl/sdk-commands/-/sdk-commands-7.5.2.tgz", - "integrity": "sha512-bOHTNrIaTQos+9KXCQVq5ER3sGex0DQHzFLy5KlnWZd+bDAys63qfFIp/Igf7qCGBZv4A7MQQmxm0w+9RUGRww==", - "license": "Apache-2.0", - "dependencies": { - "@dcl/crypto": "^3.4.4", - "@dcl/ecs": "7.5.2", - "@dcl/hashing": "1.1.3", - "@dcl/inspector": "7.5.2", - "@dcl/linker-dapp": "^0.12.0", - "@dcl/mini-comms": "1.0.1-20230216163137.commit-a4c75be", - "@dcl/protocol": "1.0.0-9115457439.commit-926ebd1", - "@dcl/quests-client": "^1.0.3", - "@dcl/quests-manager": "^0.1.4", - "@dcl/rpc": "^1.1.1", - "@dcl/schemas": "^8.2.3-20230718182824.commit-356025c", - "@segment/analytics-node": "^1.1.3", - "@well-known-components/env-config-provider": "^1.2.0", - "@well-known-components/fetch-component": "^2.0.2", - "@well-known-components/http-server": "^2.0.0-20230501134558.commit-be9a25d", - "@well-known-components/logger": "^3.1.2", - "@well-known-components/metrics": "^2.0.1", - "archiver": "^5.3.1", - "arg": "^5.0.2", - "chokidar": "^3.5.3", - "colorette": "^2.0.19", - "dcl-catalyst-client": "^21.6.1", - "esbuild": "^0.18.17", - "extract-zip": "2.0.1", - "fp-future": "^1.0.1", - "glob": "^9.3.2", - "ignore": "^5.2.4", - "node-fetch": "^2.7.0", - "open": "^8.4.0", - "portfinder": "^1.0.32", - "prompts": "^2.4.2", - "typescript": "^5.0.2", - "undici": "^5.19.1", - "uuid": "^9.0.1" - }, - "bin": { - "sdk-commands": "dist/index.js" - } - }, "node_modules/@dcl/catalyst-contracts": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@dcl/catalyst-contracts/-/catalyst-contracts-4.4.1.tgz", - "integrity": "sha512-auKNcpZUQV4u7BiL65TXGB0j+eLRVzvpE7oDd7ML0wyB4A8op9B1Ca+7JKZQLClrhj6nbyXoDT7JzFeSpkipoA==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@dcl/catalyst-contracts/-/catalyst-contracts-4.4.2.tgz", + "integrity": "sha512-gJZo3IB8U+jhBJWR0DgoLS+zaUDIb/u79e7Rp+MEM78uH3bvC19S3Dd8lxWEbPXNKlCB0saUptfK/Buw0c1y2Q==", "license": "Apache-2.0" }, "node_modules/@dcl/crypto": { @@ -708,9 +373,9 @@ } }, "node_modules/@dcl/ecs": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@dcl/ecs/-/ecs-7.5.6.tgz", - "integrity": "sha512-lXRmJy0eYj+kVJHhjnlFsCWLX8cngaCTqDf+LSqhhjawqvLkTLt159CiYdg4jBEdADafgW5A8LUABUI8dIn56A==", + "version": "7.5.8-11038883764.commit-7e87395", + "resolved": "https://registry.npmjs.org/@dcl/ecs/-/ecs-7.5.8-11038883764.commit-7e87395.tgz", + "integrity": "sha512-f6nHm7DXPpAiAfX4m/VDzXib/I3iT1Vr9mSxtCFJ/hP/kHvZCeWKnAM3qyTN24asjbneE2P8s4g125fHhaM87w==", "license": "Apache-2.0" }, "node_modules/@dcl/ecs-math": { @@ -740,9 +405,9 @@ } }, "node_modules/@dcl/explorer": { - "version": "1.0.164182-20240702173148.commit-d4a0e99", - "resolved": "https://registry.npmjs.org/@dcl/explorer/-/explorer-1.0.164182-20240702173148.commit-d4a0e99.tgz", - "integrity": "sha512-98i49nM4mpTA8gcs/ja/1SDRORJ5i9vpl7tQ/L04scW0wFWzFwZJDGsp5lEJ3e0A1asSCktQv1oP0mGJNiTWZw==", + "version": "1.0.164509-20240802172549.commit-fb95b9b", + "resolved": "https://registry.npmjs.org/@dcl/explorer/-/explorer-1.0.164509-20240802172549.commit-fb95b9b.tgz", + "integrity": "sha512-R+vmK+rdxjKJ7s3/1nNdefEG5tCyB1Z8VZH+s6EvV9mMwMXpiI4hFUAZ0gSCEQz9D2P7clern9E95AajWzbeIQ==", "license": "Apache-2.0" }, "node_modules/@dcl/hashing": { @@ -757,24 +422,24 @@ } }, "node_modules/@dcl/inspector": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@dcl/inspector/-/inspector-7.5.6.tgz", - "integrity": "sha512-l3EDXjkaDDGb3+VCwj5nn3L4wwKdj59Pd3bGQAkromuN41IDdPmnRTrqOFE74bc1upENqIuhSlv07HYxZOlOWw==", + "version": "7.5.8-11038883764.commit-7e87395", + "resolved": "https://registry.npmjs.org/@dcl/inspector/-/inspector-7.5.8-11038883764.commit-7e87395.tgz", + "integrity": "sha512-4/Fcm0NHirCbG/BJPwQQgqIkw+3WKZ+cblOfTDwZfh62WkMrCyesokX6QfP83R9tA+Bz5msEFay+Mx6ZbWx0Fw==", "dependencies": { - "@dcl/asset-packs": "1.20.0", + "@dcl/asset-packs": "1.20.1", "ts-deepmerge": "^7.0.0" } }, "node_modules/@dcl/js-runtime": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@dcl/js-runtime/-/js-runtime-7.5.6.tgz", - "integrity": "sha512-uIfpcpmVAAm03vuXUw0sgEydrxKxTGVt/78ihSRQWlzlUYTF/c6g+c6/STSIxvnW9DYZ+QK9i9TJZKzy0To5AA==", + "version": "7.5.8-11038883764.commit-7e87395", + "resolved": "https://registry.npmjs.org/@dcl/js-runtime/-/js-runtime-7.5.8-11038883764.commit-7e87395.tgz", + "integrity": "sha512-H1EbfydVz19Jw8R/nXQ0FPno3ZltiTzXs9URQPDUyNMEq3YlvAnu7pL/gjuDuNf5z4m9Voj6w11NAdNFxsTMJw==", "license": "Apache-2.0" }, "node_modules/@dcl/linker-dapp": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@dcl/linker-dapp/-/linker-dapp-0.12.0.tgz", - "integrity": "sha512-bYxvZ2ljoBuy1KyGugakL9hCRFXjoK55qm40DSfkm5g1o7r2FVEMMVP4e1aSj7IczYrDqp1bibO0+hZF/ddeLg==", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/@dcl/linker-dapp/-/linker-dapp-0.14.2.tgz", + "integrity": "sha512-Sq3ziGZUN/fXpSZ0+y7ngdS8WbHuinuJKJeNm81izDH7qo/viToDcnKMNX3lqgGqZqtDes604QxBhehJ0MhsRQ==", "license": "Apache-2.0" }, "node_modules/@dcl/mini-comms": { @@ -808,9 +473,9 @@ } }, "node_modules/@dcl/protocol": { - "version": "1.0.0-9466805132.commit-365e0bb", - "resolved": "https://registry.npmjs.org/@dcl/protocol/-/protocol-1.0.0-9466805132.commit-365e0bb.tgz", - "integrity": "sha512-CMO2/JkdMPLJQj+jdT5yqolKFDPkQF2hkS/HEUtsxCzkLoN3H0xXmDUhRuh2LTmBBl401meH/tJ+fQcPyd9xLQ==", + "version": "1.0.0-10955038136.commit-7fe9554", + "resolved": "https://registry.npmjs.org/@dcl/protocol/-/protocol-1.0.0-10955038136.commit-7fe9554.tgz", + "integrity": "sha512-0BcRTJxFhxpX1k4oN8ErL+HiJYDmd98aDh6Kti54zoCph3SlJqkq0r1KshHAeMaXLSKNRtljjgkf4KkB8MriKA==", "license": "Apache-2.0", "dependencies": { "@dcl/ts-proto": "1.154.0" @@ -835,12 +500,12 @@ "license": "Apache-2.0" }, "node_modules/@dcl/react-ecs": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@dcl/react-ecs/-/react-ecs-7.5.6.tgz", - "integrity": "sha512-oRnU/+f76Jsh8F86ofFskdG3ugT9IwYENqmNzLuWCa8Jcrdhg8Yxa6aYvn77ao5l7/qF9EE6hCAMzh49Wabktw==", + "version": "7.5.8-11038883764.commit-7e87395", + "resolved": "https://registry.npmjs.org/@dcl/react-ecs/-/react-ecs-7.5.8-11038883764.commit-7e87395.tgz", + "integrity": "sha512-YCEZKASxsCVa5WY+aFF8HOHUAXSgiHo39wVDT9w3y0uKVI3T7F/t6bThhRWmKirjjp39DS+6rQ/GGTLgpd13aA==", "license": "Apache-2.0", "dependencies": { - "@dcl/ecs": "7.5.6", + "@dcl/ecs": "7.5.8-11038883764.commit-7e87395", "react": "^18.2.0", "react-reconciler": "^0.29.0" } @@ -867,33 +532,33 @@ } }, "node_modules/@dcl/sdk": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@dcl/sdk/-/sdk-7.5.6.tgz", - "integrity": "sha512-1FvmC3XrEkE+v9J57T7uJ8B7ZqL18ut7noOzs5vSGhtZVfupvmp9DYnkbTzsOekjM73FykVU9H8LtbWXRsrWXg==", + "version": "7.5.8-11038883764.commit-7e87395", + "resolved": "https://registry.npmjs.org/@dcl/sdk/-/sdk-7.5.8-11038883764.commit-7e87395.tgz", + "integrity": "sha512-j6Mi2gN0kkKALIbmqf464qCdZx3RhrfPVaCssLjKDBrS+6fTG/Xu5AfiBKN8PTEGMqzwFun8BEjlIUU9fca26g==", "license": "Apache-2.0", "dependencies": { - "@dcl/ecs": "7.5.6", + "@dcl/ecs": "7.5.8-11038883764.commit-7e87395", "@dcl/ecs-math": "2.0.2", - "@dcl/explorer": "1.0.164182-20240702173148.commit-d4a0e99", - "@dcl/js-runtime": "7.5.6", - "@dcl/react-ecs": "7.5.6", - "@dcl/sdk-commands": "7.5.6", + "@dcl/explorer": "1.0.164509-20240802172549.commit-fb95b9b", + "@dcl/js-runtime": "7.5.8-11038883764.commit-7e87395", + "@dcl/react-ecs": "7.5.8-11038883764.commit-7e87395", + "@dcl/sdk-commands": "7.5.8-11038883764.commit-7e87395", "text-encoding": "0.7.0" } }, "node_modules/@dcl/sdk-commands": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/@dcl/sdk-commands/-/sdk-commands-7.5.6.tgz", - "integrity": "sha512-8pBXnv+TVMuuS2+kKX8qyKH0AyBcudLyUHi5baJdXCMwgwe0oV67ArwILeG0qX+R4q/CZYXD3mJPZ9BwaZyOlg==", + "version": "7.5.8-11038883764.commit-7e87395", + "resolved": "https://registry.npmjs.org/@dcl/sdk-commands/-/sdk-commands-7.5.8-11038883764.commit-7e87395.tgz", + "integrity": "sha512-bwXU+t7gcybhBE79E61xCU2VNKI6EKl4LHwInBOAM0eOVLWK+skQDPpM6LAEjRCOA/zO1uEcY5CHvsSs2lZ2nw==", "license": "Apache-2.0", "dependencies": { "@dcl/crypto": "^3.4.4", - "@dcl/ecs": "7.5.6", + "@dcl/ecs": "7.5.8-11038883764.commit-7e87395", "@dcl/hashing": "1.1.3", - "@dcl/inspector": "7.5.6", - "@dcl/linker-dapp": "^0.12.0", + "@dcl/inspector": "7.5.8-11038883764.commit-7e87395", + "@dcl/linker-dapp": "^0.14.2", "@dcl/mini-comms": "1.0.1-20230216163137.commit-a4c75be", - "@dcl/protocol": "1.0.0-9466805132.commit-365e0bb", + "@dcl/protocol": "1.0.0-10955038136.commit-7fe9554", "@dcl/quests-client": "^1.0.3", "@dcl/quests-manager": "^0.1.4", "@dcl/rpc": "^1.1.1", @@ -1389,9 +1054,9 @@ "license": "BSD-3-Clause" }, "node_modules/@scure/base": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.7.tgz", - "integrity": "sha512-PPNYBslrLNNUQ/Yad37MHYsNQtK67EhWb6WtSvNLLPo7SdVZgkUjD6Dg+5On7zNwmskf8OX7I7Nx5oN+MIWE0g==", + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", "license": "MIT", "funding": { "url": "https://paulmillr.com/funding/" @@ -1488,12 +1153,12 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.1.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", - "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", + "version": "22.7.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.1.tgz", + "integrity": "sha512-adOMRLVmleuWs/5V/w5/l7o0chDK/az+5ncCsIapTKogsu/3MVWvSgP58qVTXi5IwpfGt8pMobNq9rOWtJyu5Q==", "license": "MIT", "dependencies": { - "undici-types": "~6.13.0" + "undici-types": "~6.19.2" } }, "node_modules/@types/node-fetch": { @@ -1832,20 +1497,14 @@ } }, "node_modules/@well-known-components/interfaces/node_modules/@types/node": { - "version": "20.14.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.14.tgz", - "integrity": "sha512-d64f00982fS9YoOgJkAMolK7MN8Iq3TDdVjchbYHdEmjth/DHowx82GnoA+tVUAN+7vxfYUgAzi+JXbKNd2SDQ==", + "version": "20.16.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.8.tgz", + "integrity": "sha512-sbo5JmfbZNkyDv+2HCccr9Y9ZkKJBMTru7UdAsCojMGjKNjdaOV73bqEW242QrHEZL8R4LbHMrW+FHB5lZ5/bw==", "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, - "node_modules/@well-known-components/interfaces/node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" - }, "node_modules/@well-known-components/logger": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@well-known-components/logger/-/logger-3.1.3.tgz", @@ -2106,9 +1765,9 @@ } }, "node_modules/async": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", - "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "license": "MIT" }, "node_modules/asynckit": { @@ -2682,9 +2341,9 @@ } }, "node_modules/dset": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", - "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", "license": "MIT", "engines": { "node": ">=4" @@ -4823,9 +4482,9 @@ } }, "node_modules/path-to-regexp": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.2.tgz", - "integrity": "sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz", + "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==", "license": "MIT" }, "node_modules/path-type": { @@ -5047,9 +4706,9 @@ } }, "node_modules/protobufjs": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.3.2.tgz", - "integrity": "sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -5071,9 +4730,9 @@ } }, "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -5704,9 +5363,9 @@ } }, "node_modules/ts-proto": { - "version": "1.181.1", - "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-1.181.1.tgz", - "integrity": "sha512-lNmd/KEgqWtwDG9mIM3EpcxBx+URRVHkDP/EEJBgQJaQwmZFTk6VjHg56HNQswd114yXGfF+8pKQvJ2iH9KfWw==", + "version": "1.181.2", + "resolved": "https://registry.npmjs.org/ts-proto/-/ts-proto-1.181.2.tgz", + "integrity": "sha512-knJ8dtjn2Pd0c5ZGZG8z9DMiD4PUY8iGI9T9tb8DvGdWRMkLpf0WcPO7G+7cmbZyxvNTAG6ci3fybEaFgMZIvg==", "license": "ISC", "dependencies": { "case-anything": "^2.1.13", @@ -5801,9 +5460,9 @@ } }, "node_modules/undici-types": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", - "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT" }, "node_modules/update-browserslist-db": { diff --git a/package.json b/package.json index bcc03b2..d74c7ad 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,7 @@ "trailingComma": "none" }, "dependencies": { - "@dcl/js-runtime": "latest", - "@dcl/sdk": "latest" + "@dcl/sdk": "^7.5.8-11038883764.commit-7e87395" }, "repository": { "url": "https://github.com/decentraland/sdk-mini-games" diff --git a/src/index.ts b/src/index.ts index 84c59d2..5f69c11 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,7 @@ export type IOptions = { gameId: string environment: string gameTimeoutMs?: number + inactiveTimeoutMs?: number sceneRotation?: number gameArea?: { topLeft: TransformType['position'] diff --git a/src/queue/index.ts b/src/queue/index.ts index 912ac14..07477e8 100644 --- a/src/queue/index.ts +++ b/src/queue/index.ts @@ -1,4 +1,4 @@ -import { Entity } from '@dcl/sdk/ecs' +import { Entity, InputAction, PointerEventType } from '@dcl/sdk/ecs' import { initQueueDisplay } from './display' import { getSDK } from '../sdk' @@ -30,6 +30,7 @@ export function startPlayersQueue() { }) engine.addSystem(internalPlayerSystem()) + engine.addSystem(inputsCheckTimer()) } /** * Add current player to the queue @@ -121,9 +122,10 @@ export function setNextPlayer() { lastActivePlayer = nextPlayer.player.address Player.getMutable(nextPlayer.entity).active = true Player.getMutable(nextPlayer.entity).startPlayingAt = Date.now() + inactiveSince = Date.now() } - if (listeners.onActivePlayerChange) { + if (listeners.onActivePlayerChange && activePlayer?.address !== nextPlayer?.player.address) { listeners.onActivePlayerChange(Player.getOrNull(nextPlayer?.entity)) } } @@ -154,12 +156,10 @@ function internalPlayerSystem() { if (!activePlayer) { setNextPlayer() } - - // TIMER for active player const { config } = getSDK() + + // TIMER for active player and inactivity detection if ( - // true Conditions - config.gameTimeoutMs && activePlayer && // // I'm the player playnig @@ -167,21 +167,28 @@ function internalPlayerSystem() { // // If you are the only player connected, keep playing. getQueue().length > 1 && - // - // Check if the time has passed - Date.now() - activePlayer.startPlayingAt >= config.gameTimeoutMs + ((config.gameTimeoutMs && Date.now() - activePlayer.startPlayingAt >= config.gameTimeoutMs) || + (config.inactiveTimeoutMs && Date.now() > inactiveSince + config.inactiveTimeoutMs)) ) { setNextPlayer() } + } +} + +let inactiveSince = 0 +function inputsCheckTimer() { + return function () { + const { inputSystem } = getSDK() - // Remove disconected players - for (const { player } of getQueue()) { - if (!isPlayerConnected(player.address)) { - removePlayer(player.address) - } + if (!isActive()) return + + //update player inactivty timer + if (inputSystem.isTriggered(InputAction.IA_ANY, PointerEventType.PET_DOWN)) { + inactiveSince = Date.now() } } } + function isPlayerConnected(userId: string) { const { engine, diff --git a/src/ui/button.ts b/src/ui/button.ts index f17c76d..af3651a 100644 --- a/src/ui/button.ts +++ b/src/ui/button.ts @@ -21,6 +21,7 @@ export class MenuButton { buttonShapeDisabled: ButtonShapeData iconGlowMat: PBMaterial_PbrMaterial iconDisabledMat: PBMaterial_PbrMaterial + releaseTime: number constructor( transform: TransformTypeWithOptionals, @@ -28,7 +29,8 @@ export class MenuButton { icon: IconData, _hoverText: string, callback: () => void, - enabledByDefault?: boolean + enabledByDefault?: boolean, + releaseTime: number = 500 ) { const { engine, @@ -41,8 +43,7 @@ export class MenuButton { PointerEvents, VisibilityComponent, Tween, - TweenSequence, - TweenState + TweenSequence }, tweenSystem } = getSDK() @@ -52,6 +53,8 @@ export class MenuButton { this.enabled = enabledByDefault } + this.releaseTime = releaseTime + this.buttonShapeEnabled = buttonShapeData this.buttonShapeDisabled = uiAssets.shapes.RECT_BLACK if (!buttonShapeData.isRect) { @@ -101,14 +104,9 @@ export class MenuButton { }) engine.addSystem(() => { - // TODO: Why is not been triggered ? if (tweenSystem.tweenCompleted(this.button)) { - console.log('asd', Tween.getOrNull(this.button)) - } - - // TODO: this should be tweenCompleted but no idea why is not working :sadcat: - if (TweenState.getOrNull(this.button)?.currentTime === 1 && TweenSequence.getOrNull(this.button)) { if (!TweenSequence.get(this.button).sequence.length) { + this.enable() // Tween.deleteFrom(this.button) TweenSequence.deleteFrom(this.button) VisibilityComponent.getMutable(this.glowPlane).visible = false @@ -120,11 +118,13 @@ export class MenuButton { } } } + // this.disable() if (inputSystem.isTriggered(InputAction.IA_POINTER, PointerEventType.PET_DOWN, this.button)) { if (this.enabled) { callback() this.playSound('mini-game-assets/sounds/button_click.mp3') + this.disable() //flash the emissive of the icon Material.setPbrMaterial(this.icon, { texture: Material.Texture.Common({ src: uiAtlas }), @@ -137,7 +137,7 @@ export class MenuButton { VisibilityComponent.getMutable(this.glowPlane).visible = true //tween button inward Tween.createOrReplace(this.button, { - duration: 500, + duration: this.releaseTime / 2, currentTime: 0, playing: true, easingFunction: EasingFunction.EF_EASEOUTSINE, @@ -146,7 +146,7 @@ export class MenuButton { TweenSequence.createOrReplace(this.button, { sequence: [ { - duration: 500, + duration: this.releaseTime / 2, currentTime: 0, playing: true, easingFunction: EasingFunction.EF_EASEOUTSINE, diff --git a/src/ui/counter.ts b/src/ui/counter.ts index 99fe77c..fb6754a 100644 --- a/src/ui/counter.ts +++ b/src/ui/counter.ts @@ -3,6 +3,8 @@ import { Vector3 } from '@dcl/sdk/math' import { syncEntity } from '@dcl/sdk/network' import { getSDK } from '../sdk' +type justification = 'left' | 'right' | 'center' + function separateDigits(value: number): number[] { const arr: number[] = [] let lastDigit: number @@ -30,13 +32,15 @@ export class Counter3D { spacing: number = 1 currentNumber: number = 0 zeroPadding: boolean + justify: justification = 'center' constructor( transform: TransformTypeWithOptionals, maxDigits: number, digitSpacing: number, zeroPadding: boolean, - id: number + id: number, + justify?: justification ) { const { engine, @@ -49,9 +53,11 @@ export class Counter3D { this.maxDigits = maxDigits this.zeroPadding = zeroPadding this.id = id + this.justify = justify ?? 'center' this.addDigits() } + addDigits() { const { engine, @@ -66,7 +72,44 @@ export class Counter3D { VisibilityComponent.createOrReplace(numberEntity) this.digits.push(numberEntity) - syncEntity(numberEntity, [GltfContainer.componentId], this.id * 20000 + i) + syncEntity(numberEntity, [Transform.componentId, GltfContainer.componentId], this.id * 20000 + i) + } + } + + justifyNumber() { + const { + components: { Transform } + } = getSDK() + const numberArr = separateDigits(this.currentNumber) + let offset = 0 + + switch (this.justify) { + case 'left': { + offset = 0 + break + } + case 'right': { + if (!this.zeroPadding) { + offset = -(numberArr.length - 1) * this.spacing + } else { + offset = -(this.digits.length - 1) * this.spacing + } + + break + } + case 'center': { + if (!this.zeroPadding) { + offset = -((numberArr.length - 1) * this.spacing) / 2 + } else { + offset = -((this.digits.length - 1) * this.spacing) / 2 + } + + break + } + } + + for (let i = 0; i < this.digits.length; i++) { + Transform.getMutable(this.digits[i]).position = Vector3.create(i * this.spacing + offset, 0, 0) } } @@ -94,6 +137,8 @@ export class Counter3D { } } } + + this.justifyNumber() } reduceNumberBy(_decrement: number) { diff --git a/src/ui/scoreboard/columnData.ts b/src/ui/scoreboard/columnData.ts index 3d5e6de..36d38dd 100644 --- a/src/ui/scoreboard/columnData.ts +++ b/src/ui/scoreboard/columnData.ts @@ -2,51 +2,50 @@ import { Entity, Font, TextAlignMode } from '@dcl/sdk/ecs' import { Color4, Vector3 } from '@dcl/sdk/math' import { getSDK } from '../../sdk' -export type ColumnData = { - placementStart: number - nameStart: number - nameHeader: string - scoreHeader?: string - timeHeader?: string - movesHeader?: string - levelHeader?: string - scoreStart?: number - timeStart?: number - movesStart?: number - levelStart?: number +export const NAME_START = 0.065 +export const PLACEMENT_START = 0.05 + +export enum SCOREBOARD_VALUE_TYPE { + LEVEL, + TIME, + SCORE, + MOVES +} + +export type Column = { + headerText: string + type: SCOREBOARD_VALUE_TYPE + valueFieldWidth: number } -export const TIME_LEVEL_MOVES: ColumnData = { - placementStart: 0.075, - nameStart: 0.09, - timeStart: 0.6, - levelStart: 0.78, - movesStart: 0.96, - nameHeader: 'PLAYER', - timeHeader: 'TIME', - movesHeader: 'MOVES', - levelHeader: 'LEVEL' +export const SCORE: Column = { + headerText: 'POINTS', + type: SCOREBOARD_VALUE_TYPE.SCORE, + valueFieldWidth: 0.2 } -export const TIME_LEVEL: ColumnData = { - placementStart: 0.06, - nameStart: 0.08, - timeStart: 0.7, - levelStart: 0.96, - nameHeader: 'PLAYER', - timeHeader: 'TIME', - levelHeader: 'LEVEL' + +export const TIME: Column = { + headerText: 'TIME', + type: SCOREBOARD_VALUE_TYPE.TIME, + valueFieldWidth: 0.2 +} + +export const LEVEL: Column = { + headerText: 'LEVEL', + type: SCOREBOARD_VALUE_TYPE.LEVEL, + valueFieldWidth: 0.18 } -export const POINTS_TIME: ColumnData = { - placementStart: 0.06, - nameStart: 0.08, - scoreStart: 0.65, - timeStart: 0.96, - nameHeader: 'PLAYER', - scoreHeader: 'POINTS', - timeHeader: 'TIME' +export const MOVES: Column = { + headerText: 'MOVES', + type: SCOREBOARD_VALUE_TYPE.MOVES, + valueFieldWidth: 0.18 } +export const TIME_LEVEL_MOVES: Column[] = [TIME, LEVEL, MOVES] +export const TIME_LEVEL: Column[] = [TIME, LEVEL] +export const POINTS_TIME: Column[] = [SCORE, TIME] + export function addHeaderText(entity: Entity, text: string, fontSize: number, align: TextAlignMode) { const { components: { TextShape } @@ -65,12 +64,10 @@ export function addHeaderText(entity: Entity, text: string, fontSize: number, al export class HeaderRow { nameHeader: Entity - scoreHeader?: Entity - timeHeader?: Entity - movesHeader?: Entity - levelHeader?: Entity + currentColumnStart: number = 0.98 + headers: Entity[] = [] - constructor(columnData: ColumnData, width: number, height: number, parent: Entity, fontSize: number) { + constructor(columnData: Column[], width: number, height: number, parent: Entity, fontSize: number) { const { engine, components: { Transform } @@ -78,68 +75,28 @@ export class HeaderRow { this.nameHeader = engine.addEntity() Transform.create(this.nameHeader, { - position: Vector3.create(columnData.nameStart * width, height, 0), + position: Vector3.create(NAME_START * width, height, 0), parent: parent }) - addHeaderText(this.nameHeader, columnData.nameHeader, fontSize, TextAlignMode.TAM_MIDDLE_LEFT) - - //score - if (columnData.scoreHeader && columnData.scoreStart) { - this.scoreHeader = engine.addEntity() - Transform.create(this.scoreHeader, { - position: Vector3.create(columnData.scoreStart * width, height, 0), - parent: parent - }) - addHeaderText(this.scoreHeader, columnData.scoreHeader, fontSize, TextAlignMode.TAM_MIDDLE_RIGHT) - } - - //time - if (columnData.timeStart && columnData.timeHeader) { - this.timeHeader = engine.addEntity() - Transform.create(this.timeHeader, { - position: Vector3.create(columnData.timeStart * width, height, 0), + addHeaderText(this.nameHeader, 'PLAYER', fontSize, TextAlignMode.TAM_MIDDLE_LEFT) + // add all columns listed in columndata + for (let i = columnData.length - 1; i >= 0; i--) { + const currentHeader = engine.addEntity() + Transform.create(currentHeader, { + position: Vector3.create(this.currentColumnStart * width, height, 0), parent: parent }) - addHeaderText(this.timeHeader, columnData.timeHeader, fontSize, TextAlignMode.TAM_MIDDLE_RIGHT) - } - - //moves - if (columnData.movesStart && columnData.movesHeader) { - this.movesHeader = engine.addEntity() - Transform.create(this.movesHeader, { - position: Vector3.create(columnData.movesStart * width, height, 0), - parent: parent - }) - addHeaderText(this.movesHeader, columnData.movesHeader, fontSize, TextAlignMode.TAM_MIDDLE_RIGHT) - } + addHeaderText(currentHeader, columnData[i].headerText ?? '-', fontSize, TextAlignMode.TAM_MIDDLE_RIGHT) - //level - if (columnData.levelStart && columnData.levelHeader) { - this.levelHeader = engine.addEntity() - Transform.create(this.levelHeader, { - position: Vector3.create(columnData.levelStart * width, height, 0), - parent: parent - }) - addHeaderText(this.levelHeader, columnData.levelHeader, fontSize, TextAlignMode.TAM_MIDDLE_RIGHT) + this.currentColumnStart -= columnData[i].valueFieldWidth } } removeHeaders() { const { engine } = getSDK() - if (this.levelHeader) { - engine.removeEntity(this.levelHeader) - } - if (this.scoreHeader) { - engine.removeEntity(this.scoreHeader) - } - if (this.nameHeader) { - engine.removeEntity(this.nameHeader) - } - if (this.timeHeader) { - engine.removeEntity(this.timeHeader) - } - if (this.movesHeader) { - engine.removeEntity(this.movesHeader) + + for (let i = 0; i < this.headers.length; i++) { + engine.removeEntity(this.headers[i]) } } } diff --git a/src/ui/scoreboard/scoreboard.ts b/src/ui/scoreboard/scoreboard.ts index 475a679..e19b9cd 100644 --- a/src/ui/scoreboard/scoreboard.ts +++ b/src/ui/scoreboard/scoreboard.ts @@ -4,9 +4,18 @@ import { Color4, Quaternion, Vector3 } from '@dcl/sdk/math' import { MenuButton } from '../button' import { uiAssets } from '../resources' import { timeStringFromMs } from '../utilities' -import { ColumnData, HeaderRow } from './columnData' +import { Column, HeaderRow, NAME_START, PLACEMENT_START, SCOREBOARD_VALUE_TYPE } from './columnData' import { getSDK } from '../../sdk' +type sortOrder = 'asc' | 'desc' + +type scoreboardConfig = { + showButtons: boolean + frameGLB?: string + sortBy?: SCOREBOARD_VALUE_TYPE + sortDirection?: sortOrder +} + class ScoreRow { place: number name: string @@ -17,15 +26,12 @@ class ScoreRow { placeEntity: Entity nameEntity: Entity - scoreEntity?: Entity - timeEntity?: Entity - movesEntity?: Entity - levelEntity?: Entity + valueEntities: Entity[] constructor( place: number, scoreData: any, - columnData: ColumnData, + columnData: Column[], width: number, height: number, parent: Entity, @@ -45,7 +51,7 @@ class ScoreRow { //placement number this.placeEntity = engine.addEntity() Transform.create(this.placeEntity, { - position: Vector3.create(columnData.placementStart * width, height, 0), + position: Vector3.create(PLACEMENT_START * width, height, 0), parent: parent }) TextShape.createOrReplace(this.placeEntity, { @@ -61,7 +67,7 @@ class ScoreRow { //player name this.nameEntity = engine.addEntity() Transform.create(this.nameEntity, { - position: Vector3.create(columnData.nameStart * width, height, 0), + position: Vector3.create(NAME_START * width, height, 0), parent: parent }) TextShape.createOrReplace(this.nameEntity, { @@ -77,33 +83,39 @@ class ScoreRow { outlineWidth: 0.2 }) - //score - if (columnData.scoreStart && scoreData.score) { - this.scoreEntity = engine.addEntity() - Transform.create(this.scoreEntity, { - position: Vector3.create(columnData.scoreStart * width, height, 0), - parent: parent - }) - TextShape.createOrReplace(this.scoreEntity, { - text: scoreData.score.toString(), - fontSize: fontSize, - textAlign: TextAlignMode.TAM_MIDDLE_RIGHT, - textColor: Color4.fromHexString('#ff2d55ff'), - outlineColor: Color4.fromHexString('#ff2d55ff'), - outlineWidth: 0.2, - font: Font.F_SANS_SERIF - }) - } + this.valueEntities = [] + let currentColumnStart = 0.98 - //time - if (columnData.timeStart && scoreData.time) { - this.timeEntity = engine.addEntity() - Transform.create(this.timeEntity, { - position: Vector3.create(columnData.timeStart * width, height, 0), + for (let i = columnData.length - 1; i >= 0; i--) { + const valueEntity = engine.addEntity() + Transform.create(valueEntity, { + position: Vector3.create(currentColumnStart * width, height, 0), parent: parent }) - TextShape.createOrReplace(this.timeEntity, { - text: timeStringFromMs(scoreData.time), + + let valueText = 'NaN' + + switch (columnData[i].type) { + case SCOREBOARD_VALUE_TYPE.LEVEL: { + valueText = 'Level ' + scoreData.level.toString() + break + } + case SCOREBOARD_VALUE_TYPE.SCORE: { + valueText = scoreData.score.toString() + break + } + case SCOREBOARD_VALUE_TYPE.TIME: { + valueText = timeStringFromMs(scoreData.time) + break + } + case SCOREBOARD_VALUE_TYPE.MOVES: { + valueText = scoreData.moves.toString() + break + } + } + + TextShape.createOrReplace(valueEntity, { + text: valueText, fontSize: fontSize, textAlign: TextAlignMode.TAM_MIDDLE_RIGHT, textColor: Color4.fromHexString('#ff2d55ff'), @@ -111,73 +123,32 @@ class ScoreRow { outlineWidth: 0.2, font: Font.F_SANS_SERIF }) - } - //moves - if (columnData.movesStart && scoreData.moves) { - this.movesEntity = engine.addEntity() - Transform.create(this.movesEntity, { - position: Vector3.create(columnData.movesStart * width, height, 0), - parent: parent - }) - TextShape.createOrReplace(this.movesEntity, { - text: scoreData.moves.toString(), - fontSize: fontSize, - textAlign: TextAlignMode.TAM_MIDDLE_RIGHT, - font: Font.F_SANS_SERIF, - textColor: Color4.Black(), - outlineColor: Color4.Black(), - outlineWidth: 0.2 - }) - } - - //level - if (columnData.levelStart && scoreData.level) { - this.levelEntity = engine.addEntity() - Transform.create(this.levelEntity, { - position: Vector3.create(columnData.levelStart * width, height, 0), - parent: parent - }) - TextShape.createOrReplace(this.levelEntity, { - text: 'Level ' + scoreData.level.toString(), - fontSize: fontSize, - textAlign: TextAlignMode.TAM_MIDDLE_RIGHT, - font: Font.F_SANS_SERIF, - textColor: Color4.Black(), - outlineColor: Color4.Black(), - outlineWidth: 0.2 - }) + currentColumnStart -= columnData[i].valueFieldWidth + this.valueEntities.push(valueEntity) } } removeRow() { const { engine } = getSDK() - if (this.levelEntity) { - engine.removeEntity(this.levelEntity) - } - if (this.scoreEntity) { - engine.removeEntity(this.scoreEntity) + + for (let i = 0; i < this.valueEntities.length; i++) { + engine.removeEntity(this.valueEntities[i]) } if (this.nameEntity) { engine.removeEntity(this.nameEntity) } - if (this.timeEntity) { - engine.removeEntity(this.timeEntity) - } if (this.placeEntity) { engine.removeEntity(this.placeEntity) } - if (this.movesEntity) { - engine.removeEntity(this.movesEntity) - } } } export class ScoreBoard { uiRoot: Entity frame: Entity - buttonLeft: MenuButton - buttonRight: MenuButton + buttonLeft?: MenuButton + buttonRight?: MenuButton width: number height: number rowsVisible: number = 10 @@ -185,14 +156,19 @@ export class ScoreBoard { header: HeaderRow rowHeight: number fontScale: number - columnData: ColumnData + columnData: Column[] + sortDirection: sortOrder = 'desc' + sortBy: SCOREBOARD_VALUE_TYPE = SCOREBOARD_VALUE_TYPE.LEVEL + showButtons: boolean = false + frameGLB: string = uiAssets.scoreboard.scoreboardBackgroundLight constructor( rootTransform: TransformTypeWithOptionals, boardWidth: number, boardHeight: number, fontScale: number, - _columnData: ColumnData + _columnData: Column[], + config?: scoreboardConfig ) { const { engine } = getSDK() @@ -208,6 +184,13 @@ export class ScoreBoard { this.scores = [] this.uiRoot = engine.addEntity() + if (config) { + this.sortBy = config.sortBy ? config.sortBy : SCOREBOARD_VALUE_TYPE.LEVEL + this.sortDirection = config.sortDirection ? config.sortDirection : 'desc' + this.showButtons = config.showButtons ? config.showButtons : false + this.frameGLB = config.frameGLB ? config.frameGLB : uiAssets.scoreboard.scoreboardBackgroundLight + } + //https://exploration-games.decentraland.zone/api/games/4ee1d308-5e1e-4b2b-9e91-9091878a7e3d/leaderboard?sort=time this.header = new HeaderRow(_columnData, this.width, -this.rowHeight / 2, this.uiRoot, fontScale) @@ -222,39 +205,38 @@ export class ScoreBoard { scale: Vector3.create(this.width, this.height, 1), parent: this.uiRoot }) - GltfContainer.create(this.frame, { src: uiAssets.scoreboard.scoreboardBackgroundLight }) - - this.buttonLeft = new MenuButton( - { - position: Vector3.create(-buttonSize / 4, -this.height * 0.5, 0), - rotation: Quaternion.fromEulerDegrees(-90, 0, 0), - scale: Vector3.create(buttonSize, buttonSize, buttonSize), - parent: this.uiRoot - }, - uiAssets.shapes.SQUARE_RED, - uiAssets.icons.leftArrow, - 'PREVIOUS PAGE', - () => { - console.log('PREV PAGE PRESSED') - //this.loadScores(scoreData, POINTS_TIME ) - } - ) - - this.buttonRight = new MenuButton( - { - position: Vector3.create(this.width + buttonSize / 4 - 0.05, -this.height * 0.5, 0), - rotation: Quaternion.fromEulerDegrees(-90, 0, 0), - scale: Vector3.create(buttonSize, buttonSize, buttonSize), - parent: this.uiRoot - }, - uiAssets.shapes.SQUARE_RED, - uiAssets.icons.rightArrow, - 'NEXT PAGE', - () => { - console.log('NEXT PAGE PRESSED') - // this.loadScores(scoreData, TIME_LEVEL ) - } - ) + GltfContainer.create(this.frame, { src: this.frameGLB }) + if (this.showButtons) { + this.buttonLeft = new MenuButton( + { + position: Vector3.create(-buttonSize / 4, -this.height * 0.5, 0), + rotation: Quaternion.fromEulerDegrees(-90, 0, 0), + scale: Vector3.create(buttonSize, buttonSize, buttonSize), + parent: this.uiRoot + }, + uiAssets.shapes.SQUARE_RED, + uiAssets.icons.leftArrow, + 'PREVIOUS PAGE', + () => { + console.log('PREV PAGE PRESSED') + } + ) + + this.buttonRight = new MenuButton( + { + position: Vector3.create(this.width + buttonSize / 4 - 0.05, -this.height * 0.5, 0), + rotation: Quaternion.fromEulerDegrees(-90, 0, 0), + scale: Vector3.create(buttonSize, buttonSize, buttonSize), + parent: this.uiRoot + }, + uiAssets.shapes.SQUARE_RED, + uiAssets.icons.rightArrow, + 'NEXT PAGE', + () => { + console.log('NEXT PAGE PRESSED') + } + ) + } //this.loadScores(scoreData, TIME_LEVEL_MOVES) void this.getScores() @@ -263,10 +245,58 @@ export class ScoreBoard { async getScores() { const { config } = getSDK() const GAME_ID = config.gameId ?? '5728b531-4760-4647-a843-d164283dae6d' - // https://exploration-games.decentraland.zone/api/games/4ee1d308-5e1e-4b2b-9e91-9091878a7e3d/leaderboard?sort=time - //let scores: any[] = [] + + let urlEnding = 'org' + if (config.environment === 'dev') { + urlEnding = 'zone' + } + if (config.environment === 'prd') { + urlEnding = 'org' + } + // empty string will sort by level (default server setting) + let sortString = '' + + switch (this.sortBy) { + case SCOREBOARD_VALUE_TYPE.LEVEL: { + sortString = '' + break + } + case SCOREBOARD_VALUE_TYPE.TIME: { + sortString = 'time' + break + } + case SCOREBOARD_VALUE_TYPE.SCORE: { + sortString = 'score' + break + } + case SCOREBOARD_VALUE_TYPE.MOVES: { + sortString = 'moves' + break + } + } + + let sorDirString = 'DESC' + + switch (this.sortDirection) { + case 'asc': { + sorDirString = 'ASC' + break + } + case 'desc': { + sorDirString = 'DESC' + break + } + } + const url = - 'https://exploration-games.decentraland.zone/api/games/' + GAME_ID + '/leaderboard?sort=time&direction=ASC' + 'https://exploration-games.decentraland.' + + urlEnding + + '/api/games/' + + GAME_ID + + '/leaderboard?sort=' + + sortString + + '&direction=' + + sorDirString try { const response = await fetch(url) @@ -302,7 +332,7 @@ export class ScoreBoard { console.log(json) return this.scores } catch (e) { - console.log('error getting trending scene data ', e) + console.log('error getting score data ', e) } } }