From b53f985422767b8db9e0e79bde270d60991f239d Mon Sep 17 00:00:00 2001 From: R13 Date: Wed, 3 Jan 2024 19:50:47 -0300 Subject: [PATCH 01/21] dispatchSetting(), --- .../src/pistols/components/ChallengeModal.tsx | 2 +- .../src/pistols/components/ChallengeTable.tsx | 2 +- client/src/pistols/components/CommitModal.tsx | 4 +-- client/src/pistols/components/Duel.tsx | 2 +- .../src/pistols/components/GameContainer.tsx | 2 +- client/src/pistols/components/Menus.tsx | 25 ++++---------- client/src/pistols/components/ui/Buttons.tsx | 33 +++++++++++-------- client/src/pistols/hooks/SettingsContext.tsx | 10 +++++- client/src/pistols/three/game.tsx | 4 +-- 9 files changed, 44 insertions(+), 40 deletions(-) diff --git a/client/src/pistols/components/ChallengeModal.tsx b/client/src/pistols/components/ChallengeModal.tsx index e31ec329..e3a11a72 100644 --- a/client/src/pistols/components/ChallengeModal.tsx +++ b/client/src/pistols/components/ChallengeModal.tsx @@ -9,7 +9,7 @@ import { ProfileDescription } from '@/pistols/components/account/ProfileDescript import { ProfilePicButton } from '@/pistols/components/account/ProfilePic' import { ActionButton } from '@/pistols/components/ui/Buttons' import { ChallengeState, makeDuelUrl } from '@/pistols/utils/pistols' -import { AccountShort } from './ui/Account' +import { AccountShort } from '@/pistols/components/ui/Account' const Row = Grid.Row const Col = Grid.Column diff --git a/client/src/pistols/components/ChallengeTable.tsx b/client/src/pistols/components/ChallengeTable.tsx index d8c49bb1..0d95f844 100644 --- a/client/src/pistols/components/ChallengeTable.tsx +++ b/client/src/pistols/components/ChallengeTable.tsx @@ -7,7 +7,7 @@ import { ProfilePicSquare } from '@/pistols/components/account/ProfilePic' import { MenuKey, usePistolsContext } from '@/pistols/hooks/PistolsContext' import { ChallengeState, ChallengeStateNames } from '@/pistols/utils/pistols' import { formatTimestamp, formatTimestampDelta } from '@/pistols/utils/utils' -import { useTimestampCountdown } from '../hooks/useTimestamp' +import { useTimestampCountdown } from '@/pistols/hooks/useTimestamp' const Row = Grid.Row const Col = Grid.Column diff --git a/client/src/pistols/components/CommitModal.tsx b/client/src/pistols/components/CommitModal.tsx index bb10a8ed..bca68634 100644 --- a/client/src/pistols/components/CommitModal.tsx +++ b/client/src/pistols/components/CommitModal.tsx @@ -3,8 +3,8 @@ import { Button, Divider, Grid, Modal, Pagination } from 'semantic-ui-react' import { useDojoAccount, useDojoSystemCalls } from '@/dojo/DojoContext' import { ActionButton } from '@/pistols/components/ui/Buttons' import { useMakeCommitMove } from '@/pistols/hooks/useCommitReveal' -import { pedersen } from '../utils/utils' -import { Blades, BladesNames } from '../utils/pistols' +import { pedersen } from '@/pistols/utils/utils' +import { Blades, BladesNames } from '@/pistols/utils/pistols' const Row = Grid.Row const Col = Grid.Column diff --git a/client/src/pistols/components/Duel.tsx b/client/src/pistols/components/Duel.tsx index bd2b0ac5..72fc27a0 100644 --- a/client/src/pistols/components/Duel.tsx +++ b/client/src/pistols/components/Duel.tsx @@ -11,7 +11,7 @@ import { useEffectOnce } from '@/pistols/hooks/useEffectOnce' import { ProfileDescription } from '@/pistols/components/account/ProfileDescription' import { ProfilePic } from '@/pistols/components/account/ProfilePic' import { BladesNames, FULL_HEALTH, HALF_HEALTH, RoundState } from '@/pistols/utils/pistols' -import { MenuDuel, MenuDebugAnimations } from './Menus' +import { MenuDuel, MenuDebugAnimations } from '@/pistols/components/Menus' import CommitModal from '@/pistols/components/CommitModal' import { AnimationState } from '@/pistols/three/game' diff --git a/client/src/pistols/components/GameContainer.tsx b/client/src/pistols/components/GameContainer.tsx index 0fc872a6..77bb02f8 100644 --- a/client/src/pistols/components/GameContainer.tsx +++ b/client/src/pistols/components/GameContainer.tsx @@ -4,7 +4,7 @@ import { GameState, useGameplayContext } from '@/pistols/hooks/GameplayContext' import { loadAudioAssets, isAudioAssetsLoaded, AudioName } from '@/pistols/data/assets' import { ActionButton } from '@/pistols/components/ui/Buttons' import GameView from '@/pistols/components/GameView' -import { useSettingsContext } from '../hooks/SettingsContext' +import { useSettingsContext } from '@/pistols/hooks/SettingsContext' function GameContainer({ isVisible, diff --git a/client/src/pistols/components/Menus.tsx b/client/src/pistols/components/Menus.tsx index 0e738c97..82f62111 100644 --- a/client/src/pistols/components/Menus.tsx +++ b/client/src/pistols/components/Menus.tsx @@ -6,9 +6,10 @@ import { useChallengeIdsByState, useChallengesByDuelist } from '@/pistols/hooks/ import { useDojoAccount } from '@/dojo/DojoContext' import { ChallengeState } from '@/pistols/utils/pistols' import AccountHeader from '@/pistols/components/account/AccountHeader' -import { SPRITESHEETS } from '../data/assets' -import { useGameplayContext } from '../hooks/GameplayContext' -import { useSettingsContext } from '../hooks/SettingsContext' +import { SPRITESHEETS } from '@/pistols/data/assets' +import { useGameplayContext } from '@/pistols/hooks/GameplayContext' +import { useSettingsContext } from '@/pistols/hooks/SettingsContext' +import { SettingsMenuItem } from '@/pistols/components/ui/Buttons' const Row = Grid.Row const Col = Grid.Column @@ -73,27 +74,15 @@ export function MenuTavern({ export function MenuDuel({ }) { const router = useRouter() - - const { settings, SettingsActions, dispatch } = useSettingsContext() - const _switch = (type, payload) => { - dispatch({ - type, - payload, - }) - } - + const { settings, SettingsActions } = useSettingsContext() return (
router.push('/tavern')}> Back to Tavern - _switch(SettingsActions.MUSIC_ENABLED, !settings.musicEnabled)}> - Music {settings.musicEnabled ? 'ON' : 'OFF'} - - _switch(SettingsActions.SFX_ENABLED, !settings.sfxEnabled)}> - SFX {settings.sfxEnabled ? 'ON' : 'OFF'} - + +
) diff --git a/client/src/pistols/components/ui/Buttons.tsx b/client/src/pistols/components/ui/Buttons.tsx index 527c1af5..08f26af8 100644 --- a/client/src/pistols/components/ui/Buttons.tsx +++ b/client/src/pistols/components/ui/Buttons.tsx @@ -1,4 +1,5 @@ import React from 'react' +import { Menu } from 'semantic-ui-react' import { useSettingsContext } from '@/pistols/hooks/SettingsContext' //----------------- @@ -14,9 +15,9 @@ type ActionButtonProps = { attention?: boolean className?: string onClick: () => void -}; +} -const ActionButton = ({ +export const ActionButton = ({ label, disabled = false, large = false, @@ -55,21 +56,27 @@ export function SettingsButton({ name, value, }: SettingsButtonProps) { - const { dispatch } = useSettingsContext() + const { dispatchSetting } = useSettingsContext() const _switch = () => { - dispatch({ - type: name, - payload: !value, - }) + dispatchSetting(name, !value) } return _switch()} /> } - -//----------------- -// Exports -// -export { - ActionButton, +export function SettingsMenuItem({ + prefix, + settingsKey, + currentValue, +}) { + const { dispatchSetting } = useSettingsContext() + const _switch = () => { + dispatchSetting(settingsKey, !currentValue) + } + return ( + _switch()}> + {prefix} {currentValue ? 'ON' : 'OFF'} + + ) } + diff --git a/client/src/pistols/hooks/SettingsContext.tsx b/client/src/pistols/hooks/SettingsContext.tsx index b66ae4bb..4377dcc6 100644 --- a/client/src/pistols/hooks/SettingsContext.tsx +++ b/client/src/pistols/hooks/SettingsContext.tsx @@ -102,11 +102,19 @@ export { SettingsProvider, SettingsContext, SettingsActions } export const useSettingsContext = () => { const { state, dispatch } = useContext(SettingsContext) + + const dispatchSetting = (key: string, value: any) => { + dispatch({ + type: key, + payload: value, + }) + } + return { ...state, // expose individual settings values settings: { ...state }, // expose settings as object {} - dispatch, SettingsActions, + dispatchSetting, } } diff --git a/client/src/pistols/three/game.tsx b/client/src/pistols/three/game.tsx index 189d1b4c..74c2ef9b 100644 --- a/client/src/pistols/three/game.tsx +++ b/client/src/pistols/three/game.tsx @@ -9,9 +9,9 @@ import ee from 'event-emitter' export var emitter = ee() import { AudioName, AUDIO_ASSETS, TEXTURES, SPRITESHEETS, AnimName } from '@/pistols/data/assets' -import { map } from '../utils/utils' +import { map } from '@/pistols/utils/utils' import { SpriteSheet, Actor } from './SpriteSheetMaker' -import { Blades, FULL_HEALTH } from '../utils/pistols' +import { Blades, FULL_HEALTH } from '@/pistols/utils/pistols' const PI = Math.PI const HALF_PI = Math.PI * 0.5 From b62e9b4c6b77c217474e7480c53c399a38aebcfa Mon Sep 17 00:00:00 2001 From: R13 Date: Wed, 3 Jan 2024 21:22:46 -0300 Subject: [PATCH 02/21] Music on Menus only (need to be preloaded in-game) --- .../src/pistols/components/GameContainer.tsx | 35 +++++++++++++++++-- client/src/pistols/components/Menus.tsx | 28 +++++++++++---- client/src/pistols/components/Tavern.tsx | 5 ++- client/src/pistols/data/assets.tsx | 27 ++++++++++---- client/styles/index.scss | 10 +++--- 5 files changed, 84 insertions(+), 21 deletions(-) diff --git a/client/src/pistols/components/GameContainer.tsx b/client/src/pistols/components/GameContainer.tsx index 77bb02f8..d8fb1e39 100644 --- a/client/src/pistols/components/GameContainer.tsx +++ b/client/src/pistols/components/GameContainer.tsx @@ -5,6 +5,7 @@ import { loadAudioAssets, isAudioAssetsLoaded, AudioName } from '@/pistols/data/ import { ActionButton } from '@/pistols/components/ui/Buttons' import GameView from '@/pistols/components/GameView' import { useSettingsContext } from '@/pistols/hooks/SettingsContext' +import { useEffectOnce } from '../hooks/useEffectOnce' function GameContainer({ isVisible, @@ -82,6 +83,9 @@ function GameStartOverlay({ ) } +//------------------------------------------------- +// Displayed only when the three.js game is visible +// const GameAudios = ({ isVisible }) => { @@ -90,12 +94,12 @@ const GameAudios = ({ useEffect(() => { const _play = (musicEnabled && isVisible) - gameImpl?.playAudio(AudioName.AMBIENT, _play) + gameImpl?.playAudio(AudioName.MUSIC_INGAME, _play) }, [musicEnabled, isVisible]) useEffect(() => { if (!isVisible) { - gameImpl?.stopAudio(AudioName.AMBIENT) + gameImpl?.stopAudio(AudioName.MUSIC_INGAME) } }, [isVisible]) @@ -106,5 +110,32 @@ const GameAudios = ({ return <> } +//----------------------------------------------------- +// Displayed only when the three.js game is NOT visible +// Will disable MUSIC settings if not interacted yet +// +export const TavernAudios = () => { + const { musicEnabled } = useSettingsContext() + const { gameImpl } = useGameplayContext() + + useEffect(() => { + // const hasBeenActive = navigator?.userActivation?.hasBeenActive + // if (musicEnabled && !hasBeenActive) { + // dispatchSettings(MUSIC, false) + // } + + return () => { + gameImpl?.stopAudio(AudioName.MUSIC_MENUS) + } + }, []) + + useEffect(() => { + gameImpl?.playAudio(AudioName.MUSIC_MENUS, musicEnabled) + }, [musicEnabled]) + + return <> +} + + export default GameContainer diff --git a/client/src/pistols/components/Menus.tsx b/client/src/pistols/components/Menus.tsx index 82f62111..8844962f 100644 --- a/client/src/pistols/components/Menus.tsx +++ b/client/src/pistols/components/Menus.tsx @@ -60,7 +60,7 @@ export function MenuTavern({ }, [menuKey, yourDuelsBubble, liveDuelsBubble]) return ( - + {items} @@ -71,17 +71,33 @@ export function MenuTavern({ ) } +export function MenuSettings({ +}) { + const router = useRouter() + const { settings, SettingsActions } = useSettingsContext() + const { hasLoadedAudioAssets } = useGameplayContext() + if (!hasLoadedAudioAssets) return <> + return ( +
+ + + +
+ ) +} + + export function MenuDuel({ }) { const router = useRouter() const { settings, SettingsActions } = useSettingsContext() return ( -
+
router.push('/tavern')}> Back to Tavern - + {/* */}
@@ -112,7 +128,7 @@ function MenuDebugTriggers() { return ( <> -
+
_paces(1, 1, 0, 0)}> 1_1:DD @@ -177,7 +193,7 @@ function MenuDebugTriggers() {
-
+
_blades(1, 1, 100, 100)}> H_H:AA @@ -235,7 +251,7 @@ function MenuDebugActors({ }, [gameImpl]) return ( -
+
{items} diff --git a/client/src/pistols/components/Tavern.tsx b/client/src/pistols/components/Tavern.tsx index 47da0205..57a59b9f 100644 --- a/client/src/pistols/components/Tavern.tsx +++ b/client/src/pistols/components/Tavern.tsx @@ -2,10 +2,11 @@ import React from 'react' import { Container, Grid } from 'semantic-ui-react' import { usePistolsContext } from '@/pistols/hooks/PistolsContext' import { ChallengeTableYour, ChallengeTableLive, ChallengeTablePast } from '@/pistols/components/ChallengeTable' +import { MenuSettings, MenuTavern } from '@/pistols/components/Menus' import { DuelistTable } from '@/pistols/components/DuelistTable' +import { TavernAudios } from '@/pistols/components/GameContainer' import ChallengeModal from '@/pistols/components/ChallengeModal' import DuelistModal from '@/pistols/components/DuelistModal' -import { MenuTavern } from '@/pistols/components/Menus' const Row = Grid.Row const Col = Grid.Column @@ -15,6 +16,7 @@ export default function Tavern() { return ( <> + {/* */}
@@ -31,6 +33,7 @@ export default function Tavern() {
+ ) diff --git a/client/src/pistols/data/assets.tsx b/client/src/pistols/data/assets.tsx index 1218f0e9..664b1ceb 100644 --- a/client/src/pistols/data/assets.tsx +++ b/client/src/pistols/data/assets.tsx @@ -121,7 +121,8 @@ const SPRITESHEETS: Spritesheets = { // Audio Assets // enum AudioName { - AMBIENT = 'AMBIENT', + MUSIC_MENUS = 'MUSIC_MENUS', + MUSIC_INGAME = 'MUSIC_INGAME', SHOOT = 'SHOOT', BODY_FALL = 'BODY_FALL', GRUNT_FEMALE = 'GRUNT_FEMALE', @@ -135,9 +136,11 @@ interface AudioAsset { path: string loop?: boolean volume?: number + disabled?: boolean + delaySeconds?: number // we can delay playback to match animation frame + // loader object?: any loaded?: boolean - delaySeconds?: number // we can delay playback to match animation frame } type AudioAssets = { [key in AudioName]: AudioAsset @@ -145,11 +148,17 @@ type AudioAssets = { let AUDIO_ASSETS: AudioAssets = { - AMBIENT: { + MUSIC_MENUS: { path: '/audio/biodecay-song6.mp3', volume: 0.5, loop: true, }, + MUSIC_INGAME: { + path: '/audio/biodecay-song6.mp3', + volume: 0.5, + loop: true, + disabled: true, + }, SHOOT: { path: '/audio/sfx/pistol-shot.mp3', loop: false, @@ -193,11 +202,11 @@ let AUDIO_ASSETS: AudioAssets = { // Loaders // // Generic loader -const _loader = async (ASSETS, onLoading) => { +const _loader = async (ASSETS: any, onLoading: Function) => { return new Promise((resolve, reject) => { let assetsToLoad = Object.keys(ASSETS).length Object.keys(ASSETS).forEach((name) => { - onLoading(name, (object) => { + onLoading(name, (object: any) => { ASSETS[name].object = object if (--assetsToLoad == 0) { resolve() @@ -210,10 +219,14 @@ const _loader = async (ASSETS, onLoading) => { //----------------- // Audios // -const _loadAudios = async (listener) => { +const _loadAudios = async (listener: THREE.AudioListener) => { const loader = new THREE.AudioLoader() - return _loader(AUDIO_ASSETS, (name, resolve) => { + return _loader(AUDIO_ASSETS, (name: string, resolve: Function) => { const asset = AUDIO_ASSETS[name] + if (asset.disabled) { + resolve(null) + return + } try { loader.load(asset.path, function (buffer) { // load asset... diff --git a/client/styles/index.scss b/client/styles/index.scss index 3ba2c5e3..64507258 100644 --- a/client/styles/index.scss +++ b/client/styles/index.scss @@ -426,15 +426,15 @@ $box-h: calc((100vh - $aspect-h) / 2); // Pistols -.MenuTavern { +.MenuTop { width: 100%; position: absolute; top: 0; left: 0; padding: 15px; } -.MenuDuel { - @extend .MenuTavern; +.MenuBottom { + @extend .MenuTop; top: unset; bottom: 0; } @@ -595,13 +595,13 @@ $box-h: calc((100vh - $aspect-h) / 2); // font-weight: 600; } .ui.secondary.menu .item { - background-color: rgba($color-shadow, 0.4); + background-color: rgba($color-bg, 0.5); color: $color-important; } .ui.secondary.menu .dropdown.item:hover, .ui.secondary.menu .link.item:hover, .ui.secondary.menu a.item:hover { - background-color: rgba($color-bg, 0.5); + background-color: rgba($color-bg, 0.7); color: $color-important; } // From 46d18d97f71b62f6d31300d05ffcfe4be5f493da Mon Sep 17 00:00:00 2001 From: R13 Date: Thu, 4 Jan 2024 18:35:18 -0300 Subject: [PATCH 03/21] Sortable Duelist table --- .../src/pistols/components/DuelistTable.tsx | 85 ++++++++++++++++--- client/src/pistols/hooks/useDuelist.tsx | 4 +- 2 files changed, 75 insertions(+), 14 deletions(-) diff --git a/client/src/pistols/components/DuelistTable.tsx b/client/src/pistols/components/DuelistTable.tsx index f103b504..1b451788 100644 --- a/client/src/pistols/components/DuelistTable.tsx +++ b/client/src/pistols/components/DuelistTable.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react' +import React, { useEffect, useMemo, useState } from 'react' import { useRouter } from 'next/navigation' import { Grid, Table } from 'semantic-ui-react' import { useDojoAccount } from '@/dojo/DojoContext' @@ -12,37 +12,91 @@ const Col = Grid.Column const Cell = Table.Cell const HeaderCell = Table.HeaderCell +enum DuelistColumn { + Name = 'Name', + Honour = 'Honour', + Wins = 'Wins', + Losses = 'Losses', + Draws = 'Draws', + Total = 'Total', +} +enum SortDirection { + Ascending = 'ascending', + Descending = 'descending', +} + export function DuelistTable() { const { account } = useDojoAccount() const { duelistIds } = useAllDuelistIds() + // callback to store each Duelist data for sorting + const [duelistsData, setDuelistsData] = useState({}) + const _dataCallback = (address:bigint, data:any) => { + // this pattern can handle simultaneous state set + setDuelistsData(o => ({ ...o, [address.toString()]: data })) + } + const rows = useMemo(() => { let result = [] duelistIds.forEach((duelistId, index) => { const isYou = (duelistId == BigInt(account.address)) - result.push() + result.push() }) return result }, [duelistIds]) + // Sort + const [sortColumn, setSortColumn] = useState(DuelistColumn.Honour) + const [sortDirection, setSortDirection] = useState(SortDirection.Descending) + const _sortBy = (column: DuelistColumn) => { + if (column == sortColumn) { + setSortDirection(sortDirection == SortDirection.Ascending ? SortDirection.Descending : SortDirection.Ascending) + } else { + setSortColumn(column) + setSortDirection(column == DuelistColumn.Name ? SortDirection.Ascending : SortDirection.Descending) + } + } + + // Sort rows + const sortedRows = useMemo(() => rows.sort((a, b) => { + const dataA = duelistsData[a.props.address] + const dataB = duelistsData[b.props.address] + if (!dataA && !dataB) return 0 + if (!dataA) return 1 + if (!dataB) return -1 + const isAscending = (sortDirection == SortDirection.Ascending) + if (sortColumn == DuelistColumn.Name) { + return isAscending ? dataA.name.localeCompare(dataB.name) : dataB.name.localeCompare(dataA.name) + } + const _sortTotals = (a, b) => (!isAscending ? (b - a) : (a && !b) ? -1 : (!a && b) ? 1 : (a - b)) + if (sortColumn == DuelistColumn.Honour) return _sortTotals(dataA.honour, dataB.honour) + if (sortColumn == DuelistColumn.Wins) return _sortTotals(dataA.total_wins, dataB.total_wins) + if (sortColumn == DuelistColumn.Losses) return _sortTotals(dataA.total_losses, dataB.total_losses) + if (sortColumn == DuelistColumn.Draws) return _sortTotals(dataA.total_draws, dataB.total_draws) + if (sortColumn == DuelistColumn.Total) return _sortTotals(dataA.total_duels, dataB.total_duels) + return 0 + }), [rows, duelistsData, sortColumn, sortDirection]) + + const isEmpty = (sortedRows.length == 0) + return ( - +
- Duelist - Honour - Wins - Losses - Draws - Total + _sortBy(DuelistColumn.Name)}>Duelist + _sortBy(DuelistColumn.Honour)}>Honour + _sortBy(DuelistColumn.Wins)}>Wins + _sortBy(DuelistColumn.Losses)}>Losses + _sortBy(DuelistColumn.Draws)}>Draws + _sortBy(DuelistColumn.Total)}>Total - {rows.length > 0 ? + {!isEmpty ? - {rows} + {sortedRows} : @@ -62,10 +116,17 @@ function DuelistItem({ address, index, isYou, + dataCallback, }) { - const { name, profilePic, total_wins, total_losses, total_draws, total_duels, honourDisplay } = useDuelist(address) + const duelistData = useDuelist(address) + const { name, profilePic, total_wins, total_losses, total_draws, total_duels, honourDisplay } = duelistData const { dispatchSetDuelist } = usePistolsContext() + useEffect(() => { + // console.log(duelistData) + dataCallback(address, duelistData) + }, [duelistData]) + return ( dispatchSetDuelist(address)}> diff --git a/client/src/pistols/hooks/useDuelist.tsx b/client/src/pistols/hooks/useDuelist.tsx index 9142a592..9908ef6e 100644 --- a/client/src/pistols/hooks/useDuelist.tsx +++ b/client/src/pistols/hooks/useDuelist.tsx @@ -38,8 +38,8 @@ export const useDuelist = (address: bigint | string) => { const total_losses = useMemo(() => (duelist?.total_losses ?? 0), [duelist]) const total_draws = useMemo(() => (duelist?.total_draws ?? 0), [duelist]) const total_honour = useMemo(() => (duelist?.total_honour ?? 0), [duelist]) - const honour = useMemo(() => (duelist?.honour ?? 0), [duelist]) - const honourDisplay = useMemo(() => (total_duels > 0 && honour > 0 ? (parseFloat(duelist.honour) / 10.0).toFixed(1) : '—'), [honour, total_duels]) + const honour = useMemo(() => (parseFloat((duelist?.honour ?? 0)) / 10.0), [duelist, total_duels]) + const honourDisplay = useMemo(() => (total_duels > 0 && honour > 0 ? honour.toFixed(1) : '—'), [honour, total_duels]) return { address, From 129af02818d1d6320cfc91d288049d5d9f084845 Mon Sep 17 00:00:00 2001 From: R13 Date: Thu, 4 Jan 2024 20:41:50 -0300 Subject: [PATCH 04/21] Duel refactor: moved duelStage to useDuel() --- client/src/pistols/components/Duel.tsx | 44 +++++++---------------- client/src/pistols/hooks/useChallenge.tsx | 8 ++--- client/src/pistols/hooks/useDuel.tsx | 31 ++++++++++++++-- 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/client/src/pistols/components/Duel.tsx b/client/src/pistols/components/Duel.tsx index 72fc27a0..4b6a88ed 100644 --- a/client/src/pistols/components/Duel.tsx +++ b/client/src/pistols/components/Duel.tsx @@ -5,7 +5,7 @@ import { usePistolsContext, MenuKey } from '@/pistols/hooks/PistolsContext' import { useGameplayContext } from '@/pistols/hooks/GameplayContext' import { useChallenge, useChallengeDescription } from '@/pistols/hooks/useChallenge' import { useDuelist } from '@/pistols/hooks/useDuelist' -import { useDuel } from '@/pistols/hooks/useDuel' +import { DuelStage, useDuel } from '@/pistols/hooks/useDuel' import { useCommitMove } from '@/pistols/hooks/useCommitReveal' import { useEffectOnce } from '@/pistols/hooks/useEffectOnce' import { ProfileDescription } from '@/pistols/components/account/ProfileDescription' @@ -93,16 +93,6 @@ function DuelProfile({ ) } -enum DuelStage { - Null, // 0 - StepsCommit, // 1 - StepsReveal, // 2 - PistolsShootout, // 3 - BladesCommit, // 4 - BladesReveal, // 5 - BladesClash, // 6 - Finished, // 7 -} function DuelProgress({ account, @@ -114,28 +104,24 @@ function DuelProgress({ floated, }) { const { name } = useDuelist(isA ? duelistA : duelistB) - const { challenge, round1, round2 } = useDuel(duelId) - // console.log(`Challenge:`, challenge) - // console.log(`Round 1:`, round1) - // console.log(`Round 2:`, round2) + const { challenge, round1, round2, roundNumber, duelStage } = useDuel(duelId) + console.log(`Challenge:`, challenge) + console.log(`Round 1:`, round1) + console.log(`Round 2:`, round2) + const { gameImpl, animated, hasLoadedAudioAssets, dispatchAnimated } = useGameplayContext() //------------------------- // Duel progression // - const currentStage = useMemo(() => { - if (!round1 || round1.state == RoundState.Null) return DuelStage.Null - if (round1.state == RoundState.Commit) return DuelStage.StepsCommit - if (round1.state == RoundState.Reveal) return DuelStage.StepsReveal - if (animated < AnimationState.Pistols) return DuelStage.PistolsShootout - if (!round2) return DuelStage.Finished // finished on pistols - if (round2.state == RoundState.Commit) return DuelStage.BladesCommit - if (round2.state == RoundState.Reveal) return DuelStage.BladesReveal - if (animated < AnimationState.Blades) return DuelStage.BladesClash - return DuelStage.Finished - }, [round1, round2, animated]) + const currentStage = useMemo(() => { + if (duelStage > DuelStage.PistolsShootout && animated < AnimationState.Pistols) return DuelStage.PistolsShootout + if (round2 && duelStage > DuelStage.BladesClash && animated < AnimationState.Blades) return DuelStage.BladesClash + return duelStage + }, [duelStage, animated]) + const isAnimatingPistols = useMemo(() => (currentStage == DuelStage.PistolsShootout), [currentStage]) const isAnimatingBlades = useMemo(() => (currentStage == DuelStage.BladesClash), [currentStage]) useEffect(() => { @@ -158,12 +144,6 @@ function DuelProgress({ } }, [gameImpl, isAnimatingBlades]) - const roundNumber = useMemo(() => { - if (currentStage == DuelStage.StepsCommit || currentStage == DuelStage.StepsReveal) return 1 - if (currentStage == DuelStage.BladesCommit || currentStage == DuelStage.BladesReveal) return 2 - return 0 - }, [currentStage]) - const completedStages = useMemo(() => { return { [DuelStage.StepsCommit]: (isA && Boolean(round1?.duelist_a.hash)) || (isB && Boolean(round1?.duelist_b.hash)), diff --git a/client/src/pistols/hooks/useChallenge.tsx b/client/src/pistols/hooks/useChallenge.tsx index 7c267b7c..7627e4d6 100644 --- a/client/src/pistols/hooks/useChallenge.tsx +++ b/client/src/pistols/hooks/useChallenge.tsx @@ -78,7 +78,7 @@ export const useChallenge = (duelId: bigint | string) => { const message = useMemo(() => feltToString(challenge?.message ?? 0n), [challenge]) const passCode = useMemo(() => feltToString(challenge?.pass_code ?? 0n), [challenge]) const lords = useMemo(() => (challenge?.lords ?? 0), [challenge]) - const round = useMemo(() => (challenge?.round_number ?? 0), [challenge]) + const roundNumber = useMemo(() => (challenge?.round_number ?? 0), [challenge]) const timestamp = useMemo(() => (challenge?.timestamp ?? 0), [challenge]) const timestamp_expire = useMemo(() => (challenge?.timestamp_expire ?? 0), [challenge]) const timestamp_start = useMemo(() => (challenge?.timestamp_start ?? 0), [challenge]) @@ -87,8 +87,6 @@ export const useChallenge = (duelId: bigint | string) => { return { challengeExists: (challenge != null), state, - isLive: (state == ChallengeState.Awaiting || state == ChallengeState.InProgress), - isFinished: (state == ChallengeState.Resolved || state == ChallengeState.Draw), duelistA, duelistB, challenger: duelistA, @@ -97,8 +95,10 @@ export const useChallenge = (duelId: bigint | string) => { passCode, lords, // progress and results - round, + roundNumber, winner, + isLive: (state == ChallengeState.Awaiting || state == ChallengeState.InProgress), + isFinished: (state == ChallengeState.Resolved || state == ChallengeState.Draw), // times timestamp, timestamp_expire, diff --git a/client/src/pistols/hooks/useDuel.tsx b/client/src/pistols/hooks/useDuel.tsx index 2302c50d..de2dd079 100644 --- a/client/src/pistols/hooks/useDuel.tsx +++ b/client/src/pistols/hooks/useDuel.tsx @@ -2,20 +2,45 @@ import { useMemo } from "react" import { Entity, HasValue, Has, getComponentValue } from '@dojoengine/recs' import { useComponentValue, useEntityQuery } from "@dojoengine/react" import { useDojoComponents } from '@/dojo/DojoContext' -import { bigintToEntity, keysToEntity } from "../utils/utils" -import { useEntityKeys } from '@/pistols/hooks/useEntityKeysQuery' -import { useChallenge } from "./useChallenge" +import { useChallenge } from "@/pistols/hooks/useChallenge" +import { keysToEntity } from "@/pistols/utils/utils" +import { RoundState } from "@/pistols/utils/pistols" +export enum DuelStage { + Null, // 0 + StepsCommit, // 1 + StepsReveal, // 2 + PistolsShootout, // 3 + BladesCommit, // 4 + BladesReveal, // 5 + BladesClash, // 6 + Finished, // 7 +} export const useDuel = (duelId: bigint | string) => { const { Round } = useDojoComponents() const challenge = useChallenge(duelId) const round1: any = useComponentValue(Round, keysToEntity([duelId, 1n])) const round2: any = useComponentValue(Round, keysToEntity([duelId, 2n])) + + const duelStage = useMemo(() => { + if (!round1 || round1.state == RoundState.Null) return DuelStage.Null + if (round1.state == RoundState.Commit) return DuelStage.StepsCommit + if (round1.state == RoundState.Reveal) return DuelStage.StepsReveal + // if (animated < AnimationState.Pistols) return DuelStage.PistolsShootout + if (!round2) return DuelStage.Finished // finished on pistols + if (round2.state == RoundState.Commit) return DuelStage.BladesCommit + if (round2.state == RoundState.Reveal) return DuelStage.BladesReveal + // if (animated < AnimationState.Blades) return DuelStage.BladesClash + return DuelStage.Finished + }, [round1, round2]) + return { challenge, + roundNumber: challenge.roundNumber, round1, round2, + duelStage, } } From f2ef23d233d4adad075658b2907d566fbfdbf4eb Mon Sep 17 00:00:00 2001 From: R13 Date: Thu, 4 Jan 2024 22:12:46 -0300 Subject: [PATCH 05/21] Duel refactor: moved animations to useAnimatedDuel() --- client/src/pistols/components/Duel.tsx | 116 ++++++++++--------------- client/src/pistols/hooks/useDuel.tsx | 59 ++++++++++++- 2 files changed, 104 insertions(+), 71 deletions(-) diff --git a/client/src/pistols/components/Duel.tsx b/client/src/pistols/components/Duel.tsx index 4b6a88ed..96fc34ad 100644 --- a/client/src/pistols/components/Duel.tsx +++ b/client/src/pistols/components/Duel.tsx @@ -5,7 +5,7 @@ import { usePistolsContext, MenuKey } from '@/pistols/hooks/PistolsContext' import { useGameplayContext } from '@/pistols/hooks/GameplayContext' import { useChallenge, useChallengeDescription } from '@/pistols/hooks/useChallenge' import { useDuelist } from '@/pistols/hooks/useDuelist' -import { DuelStage, useDuel } from '@/pistols/hooks/useDuel' +import { DuelStage, useAnimatedDuel, useDuel } from '@/pistols/hooks/useDuel' import { useCommitMove } from '@/pistols/hooks/useCommitReveal' import { useEffectOnce } from '@/pistols/hooks/useEffectOnce' import { ProfileDescription } from '@/pistols/components/account/ProfileDescription' @@ -28,6 +28,10 @@ export default function Duel({ const { isLive, isFinished, message, duelistA, duelistB } = useChallenge(duelId) const { challengeDescription } = useChallengeDescription(duelId) + const { round1, round2, duelStage } = useAnimatedDuel(duelId) + // console.log(`Round 1:`, round1) + // console.log(`Round 2:`, round2) + useEffectOnce(() => { gameImpl?.resetScene() }, []) @@ -47,15 +51,27 @@ export default function Duel({
- +
- +
- +
- +
@@ -68,7 +84,6 @@ export default function Duel({ } function DuelProfile({ - duelId, address, floated, }) { @@ -95,55 +110,21 @@ function DuelProfile({ function DuelProgress({ - account, - duelId, isA = false, isB = false, - duelistA = null, - duelistB = null, + duelId, + duelStage, + account, + duelistAccount, floated, }) { - const { name } = useDuelist(isA ? duelistA : duelistB) - const { challenge, round1, round2, roundNumber, duelStage } = useDuel(duelId) - console.log(`Challenge:`, challenge) - console.log(`Round 1:`, round1) - console.log(`Round 2:`, round2) - - - const { gameImpl, animated, hasLoadedAudioAssets, dispatchAnimated } = useGameplayContext() + const { name } = useDuelist(duelistAccount) + const { round1, round2, roundNumber } = useDuel(duelId) //------------------------- // Duel progression // - const currentStage = useMemo(() => { - if (duelStage > DuelStage.PistolsShootout && animated < AnimationState.Pistols) return DuelStage.PistolsShootout - if (round2 && duelStage > DuelStage.BladesClash && animated < AnimationState.Blades) return DuelStage.BladesClash - return duelStage - }, [duelStage, animated]) - - const isAnimatingPistols = useMemo(() => (currentStage == DuelStage.PistolsShootout), [currentStage]) - const isAnimatingBlades = useMemo(() => (currentStage == DuelStage.BladesClash), [currentStage]) - useEffect(() => { - if (currentStage == DuelStage.Finished) { - dispatchAnimated(AnimationState.Finished) - } - }, [currentStage]) - - useEffect(() => { - if (isA && gameImpl && isAnimatingPistols && hasLoadedAudioAssets) { - console.log(`TRIGGER animateShootout()`) - gameImpl.animateShootout(round1.duelist_a.move, round1.duelist_b.move, round1.duelist_a.health, round1.duelist_b.health) - } - }, [gameImpl, isAnimatingPistols, hasLoadedAudioAssets]) - - useEffect(() => { - if (isA && gameImpl && isAnimatingBlades) { - console.log(`TRIGGER animateBlades()`) - gameImpl.animateBlades(round2.duelist_a.move, round2.duelist_b.move, round2.duelist_a.health, round2.duelist_b.health) - } - }, [gameImpl, isAnimatingBlades]) - const completedStages = useMemo(() => { return { [DuelStage.StepsCommit]: (isA && Boolean(round1?.duelist_a.hash)) || (isB && Boolean(round1?.duelist_b.hash)), @@ -155,26 +136,26 @@ function DuelProgress({ const _healthResult = (round: any) => { const health = isA ? round.duelist_a.health : round.duelist_b.health - return (health == 0 ? 'is DEAD!' : health < FULL_HEALTH ? 'got INJURED!' : 'gets out ALIVE!') + return (health == 0 ? 'is DEAD!' : health < FULL_HEALTH ? 'gets out INJURED!' : 'gets out ALIVE!') } const pistolsResult = useMemo(() => { - if (round1?.state == RoundState.Finished && !isAnimatingPistols) { + if (duelStage > DuelStage.PistolsShootout) { const steps = isA ? round1.duelist_a.move : round1.duelist_b.move const health = _healthResult(round1) return {name} walks {steps} steps
and {health}
} return null - }, [round1, isAnimatingPistols]) + }, [round1, duelStage]) const bladesResult = useMemo(() => { - if (round2?.state == RoundState.Finished && !isAnimatingBlades) { + if (round2 && duelStage > DuelStage.BladesClash) { const blade = isA ? round2.duelist_a.move : round2.duelist_b.move const health = _healthResult(round2) return {name} clashes with {BladesNames[blade]}
and {health}
} return null - }, [round2, isAnimatingBlades]) + }, [round2, duelStage]) //------------------------------ // Duelist interaction @@ -197,19 +178,18 @@ function DuelProgress({ } // onClick - const isDuelistA = useMemo(() => (BigInt(account?.address) == duelistA), [account, duelistA]) - const isDuelistB = useMemo(() => (BigInt(account?.address) == duelistB), [account, duelistB]) + const isYou = useMemo(() => (BigInt(account?.address) == duelistAccount), [account, duelistAccount]) const onClick = useMemo(() => { - if (!completedStages[currentStage] && (isDuelistA || isDuelistB)) { - if (currentStage == DuelStage.StepsCommit || currentStage == DuelStage.BladesCommit) { + if (!completedStages[duelStage] && isYou) { + if (duelStage == DuelStage.StepsCommit || duelStage == DuelStage.BladesCommit) { return _commit } - if (currentStage == DuelStage.StepsReveal || currentStage == DuelStage.BladesReveal) { + if (duelStage == DuelStage.StepsReveal || duelStage == DuelStage.BladesReveal) { return _reveal } } return null - }, [completedStages, currentStage, isDuelistA, isDuelistB]) + }, [completedStages, duelStage, isYou]) const _resultBackground = (round) => { const health = isA ? round.duelist_a.health : round.duelist_b.health @@ -224,7 +204,7 @@ function DuelProgress({ - {(round2 && currentStage >= DuelStage.BladesCommit) && + {(round2 && duelStage >= DuelStage.BladesCommit) && <> { } } + +//---------------------------------------------- +// extends useDuel(), adding animations Stages +// Use only ONCE inside !! +// +export const useAnimatedDuel = (duelId: bigint | string) => { + const result = useDuel(duelId) + const { round1, round2, duelStage } = result + + const { gameImpl, animated, hasLoadedAudioAssets, dispatchAnimated } = useGameplayContext() + + //------------------------------------- + // Add intermediate animation DuelStage + // + const currentStage = useMemo(() => { + if (duelStage > DuelStage.PistolsShootout && animated < AnimationState.Pistols) return DuelStage.PistolsShootout + if (round2 && duelStage > DuelStage.BladesClash && animated < AnimationState.Blades) return DuelStage.BladesClash + return duelStage + }, [duelStage, animated]) + + //------------------------ + // Trigger next animations + // + const isAnimatingPistols = useMemo(() => (currentStage == DuelStage.PistolsShootout), [currentStage]) + const isAnimatingBlades = useMemo(() => (currentStage == DuelStage.BladesClash), [currentStage]) + useEffect(() => { + if (currentStage == DuelStage.Finished) { + dispatchAnimated(AnimationState.Finished) + } + }, [currentStage]) + + useEffect(() => { + if (gameImpl && isAnimatingPistols && hasLoadedAudioAssets) { + console.log(`TRIGGER animateShootout()`) + gameImpl.animateShootout(round1.duelist_a.move, round1.duelist_b.move, round1.duelist_a.health, round1.duelist_b.health) + } + }, [gameImpl, isAnimatingPistols, hasLoadedAudioAssets]) + + useEffect(() => { + if (gameImpl && isAnimatingBlades) { + console.log(`TRIGGER animateBlades()`) + gameImpl.animateBlades(round2.duelist_a.move, round2.duelist_b.move, round2.duelist_a.health, round2.duelist_b.health) + } + }, [gameImpl, isAnimatingBlades]) + + return { + ...result, + duelStage: currentStage, + } +} + From 10ac6e0c913a6a8d937d275902f2e7322eca107f Mon Sep 17 00:00:00 2001 From: R13 Date: Thu, 4 Jan 2024 22:33:30 -0300 Subject: [PATCH 06/21] Duel refactor: moved completedStages to useDuel() --- client/src/pistols/components/Duel.tsx | 30 +++++++++++--------------- client/src/pistols/hooks/useDuel.tsx | 26 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/client/src/pistols/components/Duel.tsx b/client/src/pistols/components/Duel.tsx index 96fc34ad..1a3a3ea5 100644 --- a/client/src/pistols/components/Duel.tsx +++ b/client/src/pistols/components/Duel.tsx @@ -28,7 +28,7 @@ export default function Duel({ const { isLive, isFinished, message, duelistA, duelistB } = useChallenge(duelId) const { challengeDescription } = useChallengeDescription(duelId) - const { round1, round2, duelStage } = useAnimatedDuel(duelId) + const { duelStage, completedStagesA, completedStagesB } = useAnimatedDuel(duelId) // console.log(`Round 1:`, round1) // console.log(`Round 2:`, round2) @@ -59,6 +59,7 @@ export default function Duel({ duelStage={duelStage} account={account} duelistAccount={duelistA} + completedStages={completedStagesA} />
@@ -71,6 +72,7 @@ export default function Duel({ duelStage={duelStage} account={account} duelistAccount={duelistB} + completedStages={completedStagesB} />
@@ -116,24 +118,16 @@ function DuelProgress({ duelStage, account, duelistAccount, + completedStages, floated, }) { - const { name } = useDuelist(duelistAccount) const { round1, round2, roundNumber } = useDuel(duelId) + const { name } = useDuelist(duelistAccount) //------------------------- // Duel progression // - const completedStages = useMemo(() => { - return { - [DuelStage.StepsCommit]: (isA && Boolean(round1?.duelist_a.hash)) || (isB && Boolean(round1?.duelist_b.hash)), - [DuelStage.StepsReveal]: (isA && Boolean(round1?.duelist_a.move)) || (isB && Boolean(round1?.duelist_b.move)), - [DuelStage.BladesCommit]: (isA && Boolean(round2?.duelist_a.hash)) || (isB && Boolean(round2?.duelist_b.hash)), - [DuelStage.BladesReveal]: (isA && Boolean(round2?.duelist_a.move)) || (isB && Boolean(round2?.duelist_b.move)), - } - }, [isA, isB, round1, round2]) - const _healthResult = (round: any) => { const health = isA ? round.duelist_a.health : round.duelist_b.health return (health == 0 ? 'is DEAD!' : health < FULL_HEALTH ? 'gets out INJURED!' : 'gets out ALIVE!') @@ -157,9 +151,16 @@ function DuelProgress({ return null }, [round2, duelStage]) + const _resultBackground = (round) => { + const health = isA ? round.duelist_a.health : round.duelist_b.health + return health == FULL_HEALTH ? 'Positive' : health == HALF_HEALTH ? 'Warning' : 'Negative' + } + + //------------------------------ // Duelist interaction // + const isYou = useMemo(() => (BigInt(account?.address) == duelistAccount), [account, duelistAccount]) // Commit modal control const [commitStepsIsOpen, setCommitStepsIsOpen] = useState(false) @@ -178,9 +179,8 @@ function DuelProgress({ } // onClick - const isYou = useMemo(() => (BigInt(account?.address) == duelistAccount), [account, duelistAccount]) const onClick = useMemo(() => { - if (!completedStages[duelStage] && isYou) { + if (isYou && !completedStages[duelStage]) { if (duelStage == DuelStage.StepsCommit || duelStage == DuelStage.BladesCommit) { return _commit } @@ -191,10 +191,6 @@ function DuelProgress({ return null }, [completedStages, duelStage, isYou]) - const _resultBackground = (round) => { - const health = isA ? round.duelist_a.health : round.duelist_b.health - return health == FULL_HEALTH ? 'Positive' : health == HALF_HEALTH ? 'Warning' : 'Negative' - } //------------------------------ return ( diff --git a/client/src/pistols/hooks/useDuel.tsx b/client/src/pistols/hooks/useDuel.tsx index 364716c5..212de276 100644 --- a/client/src/pistols/hooks/useDuel.tsx +++ b/client/src/pistols/hooks/useDuel.tsx @@ -25,6 +25,8 @@ export const useDuel = (duelId: bigint | string) => { const round1: any = useComponentValue(Round, keysToEntity([duelId, 1n])) const round2: any = useComponentValue(Round, keysToEntity([duelId, 2n])) + // + // The actual stage of this duel const duelStage = useMemo(() => { if (!round1 || round1.state == RoundState.Null) return DuelStage.Null if (round1.state == RoundState.Commit) return DuelStage.StepsCommit @@ -37,12 +39,36 @@ export const useDuel = (duelId: bigint | string) => { return DuelStage.Finished }, [round1, round2]) + // + // Actions completed by Duelist A + const completedStagesA = useMemo(() => { + return { + [DuelStage.StepsCommit]: Boolean(round1?.duelist_a.hash), + [DuelStage.StepsReveal]: Boolean(round1?.duelist_a.move), + [DuelStage.BladesCommit]: Boolean(round2?.duelist_a.has), + [DuelStage.BladesReveal]: Boolean(round2?.duelist_a.move), + } + }, [round1, round2]) + + // + // Actions completed by Duelist B + const completedStagesB = useMemo(() => { + return { + [DuelStage.StepsCommit]: Boolean(round1?.duelist_b.hash), + [DuelStage.StepsReveal]: Boolean(round1?.duelist_b.move), + [DuelStage.BladesCommit]: Boolean(round2?.duelist_b.hash), + [DuelStage.BladesReveal]: Boolean(round2?.duelist_b.move), + } + }, [round1, round2]) + return { challenge, roundNumber: challenge.roundNumber, round1, round2, duelStage, + completedStagesA, + completedStagesB, } } From b64ae2bd4d2ae63ad901382e74f3a9acc4a261ab Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 12:15:28 -0300 Subject: [PATCH 07/21] Duel custom icons, --- client/src/pistols/components/Duel.tsx | 33 ++++++++++++++++------ client/src/pistols/components/ui/Icons.tsx | 29 +++++++++++++++++++ client/styles/index.scss | 8 ++++++ 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/client/src/pistols/components/Duel.tsx b/client/src/pistols/components/Duel.tsx index 1a3a3ea5..ad7bd7d1 100644 --- a/client/src/pistols/components/Duel.tsx +++ b/client/src/pistols/components/Duel.tsx @@ -10,10 +10,11 @@ import { useCommitMove } from '@/pistols/hooks/useCommitReveal' import { useEffectOnce } from '@/pistols/hooks/useEffectOnce' import { ProfileDescription } from '@/pistols/components/account/ProfileDescription' import { ProfilePic } from '@/pistols/components/account/ProfilePic' -import { BladesNames, FULL_HEALTH, HALF_HEALTH, RoundState } from '@/pistols/utils/pistols' +import { BladesNames, FULL_HEALTH, HALF_HEALTH } from '@/pistols/utils/pistols' import { MenuDuel, MenuDebugAnimations } from '@/pistols/components/Menus' -import CommitModal from '@/pistols/components/CommitModal' import { AnimationState } from '@/pistols/three/game' +import { EmojiIcon } from '@/pistols/components/ui/Icons' +import CommitModal from '@/pistols/components/CommitModal' const Row = Grid.Row const Col = Grid.Column @@ -53,7 +54,7 @@ export default function Duel({
- @@ -234,17 +237,20 @@ function DuelProgress({ <> { + const style = _right ? { margin: '0 0 0 1rem' } : {} + if (emoji && icon && !_completed) return + if (icon) return + return <> + }, [icon, emoji, _completed, _right]) + if (_right) classNames.push('AlignRight') if (!_link) classNames.push('NoMouse') return ( @@ -299,12 +316,12 @@ function ProgressItem({ link={_link} onClick={_link ? onClick : null} > - {_left && icon && } + {_left && _icon} {title} {description} - {_right && icon && } + {_right && _icon} ) } diff --git a/client/src/pistols/components/ui/Icons.tsx b/client/src/pistols/components/ui/Icons.tsx index 4ad89b48..097a31d1 100644 --- a/client/src/pistols/components/ui/Icons.tsx +++ b/client/src/pistols/components/ui/Icons.tsx @@ -1,6 +1,7 @@ import React from 'react' import Link from 'next/link' import { Icon, Popup } from 'semantic-ui-react' +import { IconSizeProp } from 'semantic-ui-react/dist/commonjs/elements/Icon/Icon' // Semantic UI Icons // https://react.semantic-ui.com/elements/icon/ @@ -123,3 +124,31 @@ export function LoadingIcon(props) { LoadingIcon.defaultProps = { size: 'small', } + + + +//--------------------------------- +// Emoji Icon +// +interface EmojiIconProps { + emoji: string + size?: IconSizeProp + style?: any + flipped?: 'horizontally' | 'vertically' + rotated?: 'clockwise' | 'counterclockwise' +} +export function EmojiIcon({ + emoji, + size = 'small', + style = {}, + flipped = null, + rotated = null, +}: EmojiIconProps) { + return ( + +
+ {emoji} +
+
+ ) +} diff --git a/client/styles/index.scss b/client/styles/index.scss index 64507258..feb19bfe 100644 --- a/client/styles/index.scss +++ b/client/styles/index.scss @@ -514,6 +514,14 @@ $box-h: calc((100vh - $aspect-h) / 2); @extend .Icon; // color: $color-icon; } + +.CustomIcon { + width: 1.5em; + height: 1.5em; + border: 0; +} + + // Icon click feedback .IconClick:active { animation-name: IconClickAnimation; From 071e790910cad028774882185da4ec9be2263fd3 Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 12:30:05 -0300 Subject: [PATCH 08/21] Icons refactor, replaced defaultProps for Props interfaces --- .../src/pistols/components/DuelistTable.tsx | 2 +- client/src/pistols/components/ui/Icons.tsx | 167 ++++++++++-------- 2 files changed, 96 insertions(+), 73 deletions(-) diff --git a/client/src/pistols/components/DuelistTable.tsx b/client/src/pistols/components/DuelistTable.tsx index 1b451788..7cb2f4c1 100644 --- a/client/src/pistols/components/DuelistTable.tsx +++ b/client/src/pistols/components/DuelistTable.tsx @@ -130,7 +130,7 @@ function DuelistItem({ return ( dispatchSetDuelist(address)}> - + diff --git a/client/src/pistols/components/ui/Icons.tsx b/client/src/pistols/components/ui/Icons.tsx index 097a31d1..7dd6aa37 100644 --- a/client/src/pistols/components/ui/Icons.tsx +++ b/client/src/pistols/components/ui/Icons.tsx @@ -1,6 +1,6 @@ import React from 'react' import Link from 'next/link' -import { Icon, Popup } from 'semantic-ui-react' +import { Icon, Popup, PopupContent, PopupHeader, SemanticICONS } from 'semantic-ui-react' import { IconSizeProp } from 'semantic-ui-react/dist/commonjs/elements/Icon/Icon' // Semantic UI Icons @@ -14,47 +14,58 @@ export { Icon } // Popup Tooltip // wrap content in so it will apeear on disabled buttons // -export function Tooltip(props) { - const trigger = props.disabledTooltip ? - {props.children} - : props.children - const content = Array.isArray(props.content) - ? props.content.map((v, i) => {v}
) - : props.content - const style = props.cursor ? { cursor: props.cursor } : {} - return ( - - - - ) +interface TooltipProps { + content: string | typeof PopupContent + header: typeof PopupHeader + disabledTooltip?: boolean + cursor?: string + children: any } -Tooltip.defaultProps = { - header: null, - content: 'gabba bagga hey', - disabledTooltip: false, - cursor: null, +export function Tooltip({ + header = null, + content = 'gabba bagga hey', + disabledTooltip = false, + cursor = null, + children = null, +}: TooltipProps) { + const _trigger = disabledTooltip ? + {children} + : children + const _content = Array.isArray(content) + ? content.map((v, i) => {v}
) + : content + const _style = cursor ? { cursor: cursor } : {} + return ( + + + + ) } //--------------------------------- // Info icon + Tooltip // -export function InfoIcon(props) { - return ( - - - - ) +interface InfoIconProps { + size?: IconSizeProp + content: string | typeof PopupContent + header: typeof PopupHeader } -InfoIcon.defaultProps = { - size: null, // normal size - header: null, - content: 'gabba bagga hey', +export function InfoIcon({ + size = null, // normal size + header = null, + content = 'gabba bagga hey', +}: InfoIconProps) { + return ( + + + + ) } @@ -62,13 +73,17 @@ InfoIcon.defaultProps = { //--------------------------------- // Semantic Ui icon // -export function IconIcon(props) { - return +interface IconIconProps { + name: SemanticICONS + size?: IconSizeProp + className: string } -IconIcon.defaultProps = { - name: 'smile outline', - className: '', - size: null, // normal size +export function IconIcon({ + name = 'smile outline', + className = '', + size = null, // normal size +}: IconIconProps) { + return } @@ -76,53 +91,61 @@ IconIcon.defaultProps = { //--------------------------------- // Hyperlink icon // -export function AnchorLinkIcon(props) { - return ( - - - - - - ) +interface AnchorLinkIconProps { + size?: IconSizeProp + url: string } -AnchorLinkIcon.defaultProps = { - size: null, // normal size - url: '#', +export function AnchorLinkIcon({ + size = null, // normal size + url = '#', +}: AnchorLinkIconProps) { + return ( + + + + + + ) } //--------------------------------- // Copy to clipboard icon // -export function CopyIcon(props) { - function _copy() { - navigator?.clipboard?.writeText(props.content) - } - return ( - _copy()} /> - ) +interface CopyIconProps { + size?: IconSizeProp + content: string } -CopyIcon.defaultProps = { - size: null, // normal size - content: null, // content to copy +export function CopyIcon({ + size = null, // normal size + content = null, // content to copy +}: CopyIconProps) { + function _copy() { + navigator?.clipboard?.writeText(content) + } + return ( + _copy()} /> + ) } //--------------------------------- // Sync spinner // -export function LoadingIcon(props) { - return ( - ) +interface LoadingIconProps { + size?: IconSizeProp } -LoadingIcon.defaultProps = { - size: 'small', +export function LoadingIcon({ + size = 'small', +}: LoadingIconProps) { + return ( + ) } From df3fc1eb3d25a73644b4a6506f8dfc5c4e2e3a30 Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 15:35:50 -0300 Subject: [PATCH 09/21] Duel progress icons on Duels tables --- .../src/pistols/components/ChallengeTable.tsx | 70 ++++++++++++--- .../src/pistols/components/DuelistModal.tsx | 11 ++- client/src/pistols/components/Tavern.tsx | 23 +++-- client/src/pistols/components/ui/Icons.tsx | 89 +++++++++++++++++-- client/src/pistols/hooks/useDuel.tsx | 5 +- client/src/pistols/utils/pistols.tsx | 7 +- client/styles/index.scss | 20 +++-- 7 files changed, 178 insertions(+), 47 deletions(-) diff --git a/client/src/pistols/components/ChallengeTable.tsx b/client/src/pistols/components/ChallengeTable.tsx index 0d95f844..deb837ae 100644 --- a/client/src/pistols/components/ChallengeTable.tsx +++ b/client/src/pistols/components/ChallengeTable.tsx @@ -1,13 +1,15 @@ import React, { useEffect, useMemo, useState } from 'react' -import { Grid, SemanticCOLORS, Table } from 'semantic-ui-react' -import { useDuelist } from '@/pistols/hooks/useDuelist' -import { useAllChallengeIds, useChallenge, useChallengeIdsByDuelist, useLiveChallengeIds, usePastChallengeIds } from '@/pistols/hooks/useChallenge' +import { Grid, Icon, SemanticCOLORS, Table } from 'semantic-ui-react' import { useDojoAccount } from '@/dojo/DojoContext' +import { useAllChallengeIds, useChallengeIdsByDuelist, useLiveChallengeIds, usePastChallengeIds } from '@/pistols/hooks/useChallenge' +import { useDuelist } from '@/pistols/hooks/useDuelist' +import { DuelStage, useDuel } from '@/pistols/hooks/useDuel' +import { useTimestampCountdown } from '@/pistols/hooks/useTimestamp' import { ProfilePicSquare } from '@/pistols/components/account/ProfilePic' import { MenuKey, usePistolsContext } from '@/pistols/hooks/PistolsContext' -import { ChallengeState, ChallengeStateNames } from '@/pistols/utils/pistols' +import { Blades, ChallengeState, ChallengeStateNames } from '@/pistols/utils/pistols' import { formatTimestamp, formatTimestampDelta } from '@/pistols/utils/utils' -import { useTimestampCountdown } from '@/pistols/hooks/useTimestamp' +import { BladesIcon, CompletedIcon, EmojiIcon, StepsIcon } from '@/pistols/components/ui/Icons' const Row = Grid.Row const Col = Grid.Column @@ -31,9 +33,10 @@ export function ChallengeTablePast() { export function ChallengeTableByDuelist({ address = null, + compact = false, }) { const { challengeIds } = useChallengeIdsByDuelist(address) - return + return } export function ChallengeTableYour() { @@ -45,7 +48,8 @@ export function ChallengeTableYour() { function ChallengeTableByIds({ challengeIds, - color = 'orange' + color = 'orange', + compact = false, }) { const [order, setOrder] = useState({}) const _sortCallback = (id, state, timestamp) => { @@ -55,7 +59,7 @@ function ChallengeTableByIds({ const rows = useMemo(() => { let result = [] challengeIds.forEach((duelId, index) => { - result.push() + result.push() }) return result }, [challengeIds]) @@ -104,15 +108,19 @@ function ChallengeTableByIds({ function DuelItem({ duelId, sortCallback, + compact = false, }) { const { account } = useDojoAccount() const { dispatchSetDuel } = usePistolsContext() - const { duelistA, duelistB, state, isLive, winner, timestamp, timestamp_expire, timestamp_start, timestamp_end } = useChallenge(duelId) + const { + challenge: { duelistA, duelistB, state, isLive, isFinished, winner, timestamp, timestamp_expire, timestamp_start, timestamp_end }, + round1, round2, duelStage, completedStagesA, completedStagesB, + } = useDuel(duelId) const { name: nameA, profilePic: profilePicA } = useDuelist(duelistA) const { name: nameB, profilePic: profilePicB } = useDuelist(duelistB) const timestamp_system = useTimestampCountdown() // console.log(timestamp, timestamp_expire, `>`, timestamp_system) - + useEffect(() => { sortCallback(duelId, state, timestamp) }, [state, timestamp]) @@ -137,14 +145,52 @@ function DuelItem({ dispatchSetDuel(duelId, isYours ? MenuKey.YourDuels : isLive ? MenuKey.LiveDuels : MenuKey.PastDuels) } + const _duelistIcons = (movesRound1, movesRound2, completedStages) => { + if (isInProgress) { + return (<> + {movesRound1 && duelStage >= DuelStage.StepsCommit && + + + + } + {movesRound1 && duelStage == DuelStage.StepsReveal && + + + + } + {movesRound2 && duelStage >= DuelStage.BladesCommit && + + + + } + {movesRound2 && duelStage == DuelStage.BladesReveal && + + + + } + ) + } + if (isFinished) { + return (<> + {movesRound1 && } + {movesRound2 && } + ) + } + return <> + } + const iconsA = useMemo(() => _duelistIcons(round1?.duelist_a, round2?.duelist_a, completedStagesA), [isInProgress, isFinished, round1, round2, completedStagesA]) + const iconsB = useMemo(() => _duelistIcons(round1?.duelist_b, round2?.duelist_b, completedStagesB), [isInProgress, isFinished, round1, round2, completedStagesB]) + return ( - _gotoChallenge()}> + _gotoChallenge()}> {nameA} + {compact ?
: ' '} + {iconsA}
@@ -153,6 +199,8 @@ function DuelItem({ {nameB} + {compact ?
: ' '} + {iconsB}
diff --git a/client/src/pistols/components/DuelistModal.tsx b/client/src/pistols/components/DuelistModal.tsx index 8f6eb19c..293aa6a8 100644 --- a/client/src/pistols/components/DuelistModal.tsx +++ b/client/src/pistols/components/DuelistModal.tsx @@ -1,5 +1,4 @@ import React, { useEffect, useMemo, useState } from 'react' -import { useRouter } from 'next/navigation' import { Grid, Table, Modal, Form, Divider, Dropdown } from 'semantic-ui-react' import { useDojoAccount, useDojoSystemCalls } from '@/dojo/DojoContext' import { MenuKey, usePistolsContext } from '@/pistols/hooks/PistolsContext' @@ -40,7 +39,7 @@ export default function DuelistModal() { create_challenge(account, duelistAddress, '', challengeArgs.message, challengeArgs.expire_seconds) } } - + return ( We've found the following gravatar image associated with your e-mail address.

*/} {!isChallenging &&
} - {isChallenging && } + {isChallenging && } @@ -89,7 +88,7 @@ function ChallengesList({ }) { return (
- +
) } @@ -98,7 +97,7 @@ function CreateChallenge({ setChallengeArgs }) { const [message, setMessage] = useState('') - const [days, setDays] = useState(1) + const [days, setDays] = useState(7) const [hours, setHours] = useState(0) const [lords, setLords] = useState(0) @@ -181,7 +180,7 @@ function CreateChallenge({ { const _lords = parseInt(e.target.value as string) - if(!isNaN(_lords)) { + if (!isNaN(_lords)) { setLords(_lords) } }} /> diff --git a/client/src/pistols/components/Tavern.tsx b/client/src/pistols/components/Tavern.tsx index 57a59b9f..41d90316 100644 --- a/client/src/pistols/components/Tavern.tsx +++ b/client/src/pistols/components/Tavern.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { Container, Grid } from 'semantic-ui-react' +import { Grid } from 'semantic-ui-react' import { usePistolsContext } from '@/pistols/hooks/PistolsContext' import { ChallengeTableYour, ChallengeTableLive, ChallengeTablePast } from '@/pistols/components/ChallengeTable' import { MenuSettings, MenuTavern } from '@/pistols/components/Menus' @@ -24,17 +24,16 @@ export default function Tavern() {

of Honourable Lords 👑

- -
- {atDuelists && } - {atYourDuels && } - {atLiveDuels && } - {atPastDuels && } -
- - - -
+
+ {atDuelists && } + {atYourDuels && } + {atLiveDuels && } + {atPastDuels && } +
+ + + + ) } diff --git a/client/src/pistols/components/ui/Icons.tsx b/client/src/pistols/components/ui/Icons.tsx index 7dd6aa37..1bd956db 100644 --- a/client/src/pistols/components/ui/Icons.tsx +++ b/client/src/pistols/components/ui/Icons.tsx @@ -1,7 +1,8 @@ -import React from 'react' +import React, { useMemo } from 'react' import Link from 'next/link' -import { Icon, Popup, PopupContent, PopupHeader, SemanticICONS } from 'semantic-ui-react' +import { Icon, IconGroup, Popup, PopupContent, PopupHeader, SemanticICONS } from 'semantic-ui-react' import { IconSizeProp } from 'semantic-ui-react/dist/commonjs/elements/Icon/Icon' +import { Blades } from '@/pistols/utils/pistols' // Semantic UI Icons // https://react.semantic-ui.com/elements/icon/ @@ -157,21 +158,95 @@ interface EmojiIconProps { emoji: string size?: IconSizeProp style?: any + className?: string + disabled?: boolean flipped?: 'horizontally' | 'vertically' rotated?: 'clockwise' | 'counterclockwise' } export function EmojiIcon({ emoji, - size = 'small', + size = null, style = {}, + className = null, + disabled = false, flipped = null, rotated = null, }: EmojiIconProps) { return ( - -
- {emoji} -
+ + {emoji} ) } + + +//--------------------------------- +// Duel Icons +// +interface StepsIconProps { + stepCount: number + size?: IconSizeProp +} +export function StepsIcon({ + stepCount, + size = null, +}: StepsIconProps) { + if (stepCount < 1 || stepCount > 10) { + return + } + const emoji = stepCount == 10 ? '10' : '1234567890'[stepCount - 1] + return ( + // + + + + + ) +} +interface BladesIconProps { + blades: Blades + size?: IconSizeProp +} +export function BladesIcon({ + blades, + size = 'large', +}: BladesIconProps) { + if (blades <= Blades.Null || blades >= Blades.Count) { + return + } + const emoji = + blades == Blades.Light ? '🔪' + : blades == Blades.Heavy ? '🗡️' + : blades == Blades.Block ? '🛡️' + : '?' + return ( + // + // + + // + ) +} + + +//--------------------------------- +// Ticked Icons +// +interface CompletedIconProps { + completed: boolean + size?: IconSizeProp + tickSize?: IconSizeProp + children: any +} +export function CompletedIcon({ + completed, + size = null, + tickSize = 'large', + children, +}: CompletedIconProps) { + return ( + + {children} + {completed && } + + ) +} \ No newline at end of file diff --git a/client/src/pistols/hooks/useDuel.tsx b/client/src/pistols/hooks/useDuel.tsx index 212de276..e70439fe 100644 --- a/client/src/pistols/hooks/useDuel.tsx +++ b/client/src/pistols/hooks/useDuel.tsx @@ -1,6 +1,5 @@ import { useEffect, useMemo } from "react" -import { Entity, HasValue, Has, getComponentValue } from '@dojoengine/recs' -import { useComponentValue, useEntityQuery } from "@dojoengine/react" +import { useComponentValue } from "@dojoengine/react" import { useDojoComponents } from '@/dojo/DojoContext' import { useGameplayContext } from "@/pistols/hooks/GameplayContext" import { useChallenge } from "@/pistols/hooks/useChallenge" @@ -45,7 +44,7 @@ export const useDuel = (duelId: bigint | string) => { return { [DuelStage.StepsCommit]: Boolean(round1?.duelist_a.hash), [DuelStage.StepsReveal]: Boolean(round1?.duelist_a.move), - [DuelStage.BladesCommit]: Boolean(round2?.duelist_a.has), + [DuelStage.BladesCommit]: Boolean(round2?.duelist_a.hash), [DuelStage.BladesReveal]: Boolean(round2?.duelist_a.move), } }, [round1, round2]) diff --git a/client/src/pistols/utils/pistols.tsx b/client/src/pistols/utils/pistols.tsx index 1b84810b..714ae1d3 100644 --- a/client/src/pistols/utils/pistols.tsx +++ b/client/src/pistols/utils/pistols.tsx @@ -82,9 +82,10 @@ export enum RoundState { // export enum Blades { Null, - Light, - Heavy, - Block, + Light, // 1 + Heavy, // 2 + Block, // 3 + Count, } export const BladesNames = { diff --git a/client/styles/index.scss b/client/styles/index.scss index feb19bfe..6d575d98 100644 --- a/client/styles/index.scss +++ b/client/styles/index.scss @@ -330,6 +330,7 @@ $box-h: calc((100vh - $aspect-h) / 2); position: relative; margin-top: 100px; max-height: 500px; + width: 800px; scrollbar-width: thin; overflow-y: scroll; // border: 0.5px solid #0001; @@ -514,11 +515,20 @@ $box-h: calc((100vh - $aspect-h) / 2); @extend .Icon; // color: $color-icon; } - -.CustomIcon { - width: 1.5em; - height: 1.5em; - border: 0; +.StepsIcon { + font-family: monospace!important; + font-size: 16px!important; + font-weight: 600!important; + color: $color-bg; + text-shadow: $text-shadow; + margin: -2px 0 0 -2px!important; +} +.StepsIconRound { + font-family: monospace!important; + font-size: 16px!important; + // circle + border-radius: 50%; + background: rgba($color-bg, 0.8); } From dc8cbbc82a5d00f803ec094d459f373ffba6ae28 Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 16:53:41 -0300 Subject: [PATCH 10/21] , added to Duel modal --- .../src/pistols/components/ChallengeModal.tsx | 31 +++++++- .../src/pistols/components/ChallengeTable.tsx | 54 ++----------- client/src/pistols/components/DuelIcons.tsx | 76 +++++++++++++++++++ .../components/account/ProfileDescription.tsx | 4 +- client/src/pistols/components/ui/Icons.tsx | 38 +++++++--- client/styles/index.scss | 24 +++++- 6 files changed, 166 insertions(+), 61 deletions(-) create mode 100644 client/src/pistols/components/DuelIcons.tsx diff --git a/client/src/pistols/components/ChallengeModal.tsx b/client/src/pistols/components/ChallengeModal.tsx index e3a11a72..6c8c782f 100644 --- a/client/src/pistols/components/ChallengeModal.tsx +++ b/client/src/pistols/components/ChallengeModal.tsx @@ -10,6 +10,7 @@ import { ProfilePicButton } from '@/pistols/components/account/ProfilePic' import { ActionButton } from '@/pistols/components/ui/Buttons' import { ChallengeState, makeDuelUrl } from '@/pistols/utils/pistols' import { AccountShort } from '@/pistols/components/ui/Account' +import { DuelIcons } from '@/pistols/components/DuelIcons' const Row = Grid.Row const Col = Grid.Column @@ -22,7 +23,7 @@ export default function ChallengeModal() { const { atYourDuels, atLiveDuels, atPastDuels, duelId, dispatchSetDuel, dispatchSetDuelist } = usePistolsContext() - const { state, message, duelistA, duelistB, lords } = useChallenge(duelId) + const { state, message, duelistA, duelistB, lords, isLive, isFinished } = useChallenge(duelId) const { challengeDescription } = useChallengeDescription(duelId) @@ -60,7 +61,7 @@ export default function ChallengeModal() {
- +
challenged
@@ -72,7 +73,7 @@ export default function ChallengeModal() {
- +
for a duel
@@ -85,7 +86,7 @@ export default function ChallengeModal() {
{lords == 0 ? : - +
for {lords} $LORDS each
} @@ -96,6 +97,28 @@ export default function ChallengeModal() {

{challengeDescription}

+ {(isLive || isFinished) && + <> + +
+ +
moves
+
+ + + +
+ + + + vs + + + + + + + } dispatchSetDuelist(duelistB)} /> diff --git a/client/src/pistols/components/ChallengeTable.tsx b/client/src/pistols/components/ChallengeTable.tsx index deb837ae..548ccf2b 100644 --- a/client/src/pistols/components/ChallengeTable.tsx +++ b/client/src/pistols/components/ChallengeTable.tsx @@ -1,15 +1,14 @@ import React, { useEffect, useMemo, useState } from 'react' -import { Grid, Icon, SemanticCOLORS, Table } from 'semantic-ui-react' +import { Grid, SemanticCOLORS, Table } from 'semantic-ui-react' import { useDojoAccount } from '@/dojo/DojoContext' -import { useAllChallengeIds, useChallengeIdsByDuelist, useLiveChallengeIds, usePastChallengeIds } from '@/pistols/hooks/useChallenge' +import { useAllChallengeIds, useChallenge, useChallengeIdsByDuelist, useLiveChallengeIds, usePastChallengeIds } from '@/pistols/hooks/useChallenge' import { useDuelist } from '@/pistols/hooks/useDuelist' -import { DuelStage, useDuel } from '@/pistols/hooks/useDuel' import { useTimestampCountdown } from '@/pistols/hooks/useTimestamp' import { ProfilePicSquare } from '@/pistols/components/account/ProfilePic' import { MenuKey, usePistolsContext } from '@/pistols/hooks/PistolsContext' -import { Blades, ChallengeState, ChallengeStateNames } from '@/pistols/utils/pistols' +import { ChallengeState, ChallengeStateNames } from '@/pistols/utils/pistols' import { formatTimestamp, formatTimestampDelta } from '@/pistols/utils/utils' -import { BladesIcon, CompletedIcon, EmojiIcon, StepsIcon } from '@/pistols/components/ui/Icons' +import { DuelIcons } from '@/pistols/components/DuelIcons' const Row = Grid.Row const Col = Grid.Column @@ -113,9 +112,8 @@ function DuelItem({ const { account } = useDojoAccount() const { dispatchSetDuel } = usePistolsContext() const { - challenge: { duelistA, duelistB, state, isLive, isFinished, winner, timestamp, timestamp_expire, timestamp_start, timestamp_end }, - round1, round2, duelStage, completedStagesA, completedStagesB, - } = useDuel(duelId) + duelistA, duelistB, state, isLive, isFinished, winner, timestamp, timestamp_expire, timestamp_start, timestamp_end, + }= useChallenge(duelId) const { name: nameA, profilePic: profilePicA } = useDuelist(duelistA) const { name: nameB, profilePic: profilePicB } = useDuelist(duelistB) const timestamp_system = useTimestampCountdown() @@ -145,42 +143,6 @@ function DuelItem({ dispatchSetDuel(duelId, isYours ? MenuKey.YourDuels : isLive ? MenuKey.LiveDuels : MenuKey.PastDuels) } - const _duelistIcons = (movesRound1, movesRound2, completedStages) => { - if (isInProgress) { - return (<> - {movesRound1 && duelStage >= DuelStage.StepsCommit && - - - - } - {movesRound1 && duelStage == DuelStage.StepsReveal && - - - - } - {movesRound2 && duelStage >= DuelStage.BladesCommit && - - - - } - {movesRound2 && duelStage == DuelStage.BladesReveal && - - - - } - ) - } - if (isFinished) { - return (<> - {movesRound1 && } - {movesRound2 && } - ) - } - return <> - } - const iconsA = useMemo(() => _duelistIcons(round1?.duelist_a, round2?.duelist_a, completedStagesA), [isInProgress, isFinished, round1, round2, completedStagesA]) - const iconsB = useMemo(() => _duelistIcons(round1?.duelist_b, round2?.duelist_b, completedStagesB), [isInProgress, isFinished, round1, round2, completedStagesB]) - return ( _gotoChallenge()}> @@ -190,7 +152,7 @@ function DuelItem({ {nameA} {compact ?
: ' '} - {iconsA} +
@@ -200,7 +162,7 @@ function DuelItem({ {nameB} {compact ?
: ' '} - {iconsB} +
diff --git a/client/src/pistols/components/DuelIcons.tsx b/client/src/pistols/components/DuelIcons.tsx new file mode 100644 index 00000000..1d6858d8 --- /dev/null +++ b/client/src/pistols/components/DuelIcons.tsx @@ -0,0 +1,76 @@ +import React from 'react' +import { Icon } from 'semantic-ui-react' +import { IconSizeProp } from 'semantic-ui-react/dist/commonjs/elements/Icon/Icon' +import { DuelStage, useDuel } from '@/pistols/hooks/useDuel' +import { Blades, ChallengeState } from '@/pistols/utils/pistols' +import { BladesIcon, CompletedIcon, EmojiIcon, StepsIcon } from '@/pistols/components/ui/Icons' + + +export function DuelIcons({ + duelId, + account, + size = 'large', +}) { + const { + challenge: { duelistA, duelistB, state, isFinished }, + round1, round2, duelStage, completedStagesA, completedStagesB, + } = useDuel(duelId) + + const isA = account == duelistA + const isB = account == duelistB + const movesRound1 = isA ? (round1?.duelist_a ?? null) : isB ? (round1?.duelist_b ?? null) : null + const movesRound2 = isA ? (round2?.duelist_a ?? null) : isB ? (round2?.duelist_b ?? null) : null + const completedStages = isA ? (completedStagesA) : isB ? (completedStagesB) : null + + const _size = size as IconSizeProp + + if (state == ChallengeState.Awaiting) { + return (<> + {isA && + + + + } + {isB && + + + + } + ) + } + + if (state == ChallengeState.InProgress) { + return (<> + {movesRound1 && duelStage >= DuelStage.StepsCommit && + + + + } + {movesRound1 && duelStage == DuelStage.StepsReveal && + + + + } + {movesRound2 && duelStage >= DuelStage.BladesCommit && + + + + } + {movesRound2 && duelStage == DuelStage.BladesReveal && + + + + } + ) + } + + if (isFinished) { + return (<> + {movesRound1 && } + {movesRound2 && } + ) + } + + return <> +} + diff --git a/client/src/pistols/components/account/ProfileDescription.tsx b/client/src/pistols/components/account/ProfileDescription.tsx index fafd0ccc..248a48c0 100644 --- a/client/src/pistols/components/account/ProfileDescription.tsx +++ b/client/src/pistols/components/account/ProfileDescription.tsx @@ -4,11 +4,13 @@ import { useDuelist } from '@/pistols/hooks/useDuelist' export function ProfileDescription({ address, + preName = null, + postName = null, }) { const { name, honourDisplay } = useDuelist(address) return (
-

{name}

+

{preName} {name} {postName}

Honour: {honourDisplay}

diff --git a/client/src/pistols/components/ui/Icons.tsx b/client/src/pistols/components/ui/Icons.tsx index 1bd956db..9ba9cb1b 100644 --- a/client/src/pistols/components/ui/Icons.tsx +++ b/client/src/pistols/components/ui/Icons.tsx @@ -11,6 +11,28 @@ import { Blades } from '@/pistols/utils/pistols' // re-export semantic ui Icon for convenience export { Icon } +const _downSize = (size) => { + return ( + size == 'small' ? 'tiny' + : size == null ? 'small' + : size == 'large' ? null + : size == 'big' ? 'large' + : size == 'huge' ? 'big' + : null + ) +} + +const _upSize = (size) => { + return ( + size == 'tiny' ? 'small' + : size == 'small' ? null + : size == null ? 'large' + : size == 'large' ? 'big' + : size == 'big' ? 'huge' + : null + ) +} + //--------------------------------- // Popup Tooltip // wrap content in so it will apeear on disabled buttons @@ -173,7 +195,7 @@ export function EmojiIcon({ rotated = null, }: EmojiIconProps) { return ( - + {emoji} ) @@ -189,17 +211,17 @@ interface StepsIconProps { } export function StepsIcon({ stepCount, - size = null, + size = 'large', }: StepsIconProps) { if (stepCount < 1 || stepCount > 10) { return } - const emoji = stepCount == 10 ? '10' : '1234567890'[stepCount - 1] + const steps = stepCount == 10 ? '10' : '1234567890'[stepCount - 1] return ( // - + - + ) } @@ -234,19 +256,17 @@ export function BladesIcon({ interface CompletedIconProps { completed: boolean size?: IconSizeProp - tickSize?: IconSizeProp children: any } export function CompletedIcon({ completed, size = null, - tickSize = 'large', children, }: CompletedIconProps) { return ( - + {children} - {completed && } + {completed && } ) } \ No newline at end of file diff --git a/client/styles/index.scss b/client/styles/index.scss index 6d575d98..451f3e90 100644 --- a/client/styles/index.scss +++ b/client/styles/index.scss @@ -133,6 +133,8 @@ canvas { .NoBorder { border: 0!important } .AutoMargin { margin: auto!important } +.Margin6 { margin: 6px!important } + .Block { display: inline-block; } .Flex { display: flex; } @@ -195,6 +197,16 @@ canvas { .Relative { position: relative; } +.AbsoluteLeft { + position: absolute; + top: 0; + left: 0; +} +.AbsoluteRight { + position: absolute; + top: 0; + right: 0; +} .Grayscale { filter: grayscale(100%); /* Current draft standard */ @@ -520,9 +532,19 @@ $box-h: calc((100vh - $aspect-h) / 2); font-size: 16px!important; font-weight: 600!important; color: $color-bg; - text-shadow: $text-shadow; + text-shadow: 0 0 2px #000; margin: -2px 0 0 -2px!important; } +.StepsIcon.small { + font-size: 14px!important; +} +.StepsIcon.large { + font-size: 20px!important; +} +.StepsIcon.big { + font-size: 24px!important; +} + .StepsIconRound { font-family: monospace!important; font-size: 16px!important; From 38d5e39f751ae5866009e5b8703fc1dffb9e7a19 Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 17:33:33 -0300 Subject: [PATCH 11/21] Added scores to Duelist profile modal --- .../src/pistols/components/ChallengeModal.tsx | 2 +- client/src/pistols/components/DuelIcons.tsx | 4 +-- .../src/pistols/components/DuelistModal.tsx | 6 ++-- .../src/pistols/components/DuelistTable.tsx | 31 ++++++++++++------- .../components/account/ProfileDescription.tsx | 18 +++++++++-- client/src/pistols/components/ui/Icons.tsx | 4 +-- client/styles/index.scss | 19 ++++++++++-- 7 files changed, 60 insertions(+), 24 deletions(-) diff --git a/client/src/pistols/components/ChallengeModal.tsx b/client/src/pistols/components/ChallengeModal.tsx index 6c8c782f..4b22207d 100644 --- a/client/src/pistols/components/ChallengeModal.tsx +++ b/client/src/pistols/components/ChallengeModal.tsx @@ -114,7 +114,7 @@ export default function ChallengeModal() { vs
- + diff --git a/client/src/pistols/components/DuelIcons.tsx b/client/src/pistols/components/DuelIcons.tsx index 1d6858d8..a036ce14 100644 --- a/client/src/pistols/components/DuelIcons.tsx +++ b/client/src/pistols/components/DuelIcons.tsx @@ -28,12 +28,12 @@ export function DuelIcons({ return (<> {isA && - + } {isB && - + } ) diff --git a/client/src/pistols/components/DuelistModal.tsx b/client/src/pistols/components/DuelistModal.tsx index 293aa6a8..c1cfac78 100644 --- a/client/src/pistols/components/DuelistModal.tsx +++ b/client/src/pistols/components/DuelistModal.tsx @@ -52,7 +52,7 @@ export default function DuelistModal() { - +
{/*

We've found the following gravatar image associated with your e-mail address.

*/} @@ -70,7 +70,7 @@ export default function DuelistModal() { {!isYou &&
{ - hasPact ? dispatchSetDuel(pactDuelId, MenuKey.YourDuels)} /> + hasPact ? dispatchSetDuel(pactDuelId, MenuKey.YourDuels)} /> : isChallenging ? _challenge()} /> : setIsChallenging(true)} /> } @@ -87,7 +87,7 @@ function ChallengesList({ duelistAddress }) { return ( -
+
) diff --git a/client/src/pistols/components/DuelistTable.tsx b/client/src/pistols/components/DuelistTable.tsx index 7cb2f4c1..b2bc16e9 100644 --- a/client/src/pistols/components/DuelistTable.tsx +++ b/client/src/pistols/components/DuelistTable.tsx @@ -15,6 +15,7 @@ const HeaderCell = Table.HeaderCell enum DuelistColumn { Name = 'Name', Honour = 'Honour', + TotalHonour = 'TotalHonour', Wins = 'Wins', Losses = 'Losses', Draws = 'Draws', @@ -70,6 +71,7 @@ export function DuelistTable() { } const _sortTotals = (a, b) => (!isAscending ? (b - a) : (a && !b) ? -1 : (!a && b) ? 1 : (a - b)) if (sortColumn == DuelistColumn.Honour) return _sortTotals(dataA.honour, dataB.honour) + if (sortColumn == DuelistColumn.TotalHonour) return _sortTotals(dataA.honour, dataB.total_honour) if (sortColumn == DuelistColumn.Wins) return _sortTotals(dataA.total_wins, dataB.total_wins) if (sortColumn == DuelistColumn.Losses) return _sortTotals(dataA.total_losses, dataB.total_losses) if (sortColumn == DuelistColumn.Draws) return _sortTotals(dataA.total_draws, dataB.total_draws) @@ -86,11 +88,12 @@ export function DuelistTable() { _sortBy(DuelistColumn.Name)}>Duelist - _sortBy(DuelistColumn.Honour)}>Honour - _sortBy(DuelistColumn.Wins)}>Wins - _sortBy(DuelistColumn.Losses)}>Losses - _sortBy(DuelistColumn.Draws)}>Draws - _sortBy(DuelistColumn.Total)}>Total + _sortBy(DuelistColumn.Honour)}>Honour + _sortBy(DuelistColumn.Wins)}>Total
Wins
+ _sortBy(DuelistColumn.Losses)}>Total
Losses
+ _sortBy(DuelistColumn.Draws)}>Total
Draws
+ _sortBy(DuelistColumn.TotalHonour)}>Total
Honour
+ _sortBy(DuelistColumn.Total)}>Total
Duels
@@ -119,7 +122,7 @@ function DuelistItem({ dataCallback, }) { const duelistData = useDuelist(address) - const { name, profilePic, total_wins, total_losses, total_draws, total_duels, honourDisplay } = duelistData + const { name, profilePic, total_wins, total_losses, total_draws, total_duels, total_honour, honourDisplay } = duelistData const { dispatchSetDuelist } = usePistolsContext() useEffect(() => { @@ -127,6 +130,8 @@ function DuelistItem({ dataCallback(address, duelistData) }, [duelistData]) + const isRookie = (total_duels == 0) + return ( dispatchSetDuelist(address)}> @@ -142,23 +147,27 @@ function DuelistItem({ - {honourDisplay} + {isRookie ? '-' : {honourDisplay}} + + + + {isRookie ? '-' : {total_wins}} - {total_wins} + {isRookie ? '-' : {total_losses}} - {total_losses} + {isRookie ? '-' : {total_draws}} - {total_draws} + {isRookie ? '-' : {total_honour}} - {total_duels} + {isRookie ? '-' : {total_duels}} ) diff --git a/client/src/pistols/components/account/ProfileDescription.tsx b/client/src/pistols/components/account/ProfileDescription.tsx index 248a48c0..9399bc72 100644 --- a/client/src/pistols/components/account/ProfileDescription.tsx +++ b/client/src/pistols/components/account/ProfileDescription.tsx @@ -6,13 +6,27 @@ export function ProfileDescription({ address, preName = null, postName = null, + displayStats = false }) { - const { name, honourDisplay } = useDuelist(address) + const { name, total_wins, total_losses, total_draws, total_duels, total_honour, honourDisplay } = useDuelist(address) return ( -
+

{preName} {name} {postName}

Honour: {honourDisplay}

+ {displayStats && +
+ Total Duels: {total_duels} +
+ Total Wins: {total_wins} +
+ Total Losses: {total_losses} +
+ Total Draws: {total_draws} +
+ Total Honour: {total_honour} +
+ }
) } diff --git a/client/src/pistols/components/ui/Icons.tsx b/client/src/pistols/components/ui/Icons.tsx index 9ba9cb1b..a5df7a30 100644 --- a/client/src/pistols/components/ui/Icons.tsx +++ b/client/src/pistols/components/ui/Icons.tsx @@ -264,9 +264,9 @@ export function CompletedIcon({ children, }: CompletedIconProps) { return ( - + {children} - {completed && } + {completed && } ) } \ No newline at end of file diff --git a/client/styles/index.scss b/client/styles/index.scss index 451f3e90..15449c31 100644 --- a/client/styles/index.scss +++ b/client/styles/index.scss @@ -128,11 +128,16 @@ canvas { .AlignBottom { vertical-align: bottom; } .NoPadding { padding: 0!important; } -.Padded { padding: 0.5em!important; } .NoMargin { margin: 0!important } .NoBorder { border: 0!important } .AutoMargin { margin: auto!important } +.Padded { padding: 0.5em!important; } +.PaddedLeft { padding-left: 0.5em!important; } +.PaddedRight { padding-right: 0.5em!important; } +.PaddedTop { padding-top: 0.5em!important; } +.PaddedBottom { padding-bottom: 0.5em!important; } + .Margin6 { margin: 6px!important } .Block { display: inline-block; } @@ -144,6 +149,9 @@ canvas { .Important { color: $color-important; } +.Bold { + font-weight: 600; +} .Positive { background-color: $color-positive!important; @@ -352,9 +360,14 @@ $box-h: calc((100vh - $aspect-h) / 2); max-height: 290px; margin: 0; } +.TableValue { + font-size: 14px; + font-weight: 600; +} + // .TableHeader { -// position: absolute; -// top: 0; +// height: 30px!important; +// max-height: 30px!important; // } // .TableBody { // margin-top: 100px; From c4cb566be11c615ac2c12c817117ce509b41f57f Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 18:42:44 -0300 Subject: [PATCH 12/21] Use full resolution profile pics --- client/src/pistols/components/account/ProfilePic.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/pistols/components/account/ProfilePic.tsx b/client/src/pistols/components/account/ProfilePic.tsx index 4cdaf57b..26b5ede7 100644 --- a/client/src/pistols/components/account/ProfilePic.tsx +++ b/client/src/pistols/components/account/ProfilePic.tsx @@ -6,7 +6,7 @@ const _makeUrl = (profilePic: number, suffix: string) => { return `/profiles/${('00' + profilePic).slice(-2)}_${suffix}.jpg` } const _className = (square: boolean, duel: boolean) => (square ? 'ProfilePicSquare' : duel ? 'ProfilePicDuel' : 'ProfilePic') -const _suffix = (square: boolean) => (square ? 'sq' : 'b') +const _suffix = (square: boolean) => (square ? 'sq' : 'a') //--------------- // Portraits From b7ed3ee10a3f0eeeb9da34451aa1d89a899dd5ca Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 18:43:02 -0300 Subject: [PATCH 13/21] Default expiry 7 days --- client/src/pistols/components/DuelistModal.tsx | 16 ++++++---------- client/styles/index.scss | 4 ++-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/client/src/pistols/components/DuelistModal.tsx b/client/src/pistols/components/DuelistModal.tsx index c1cfac78..4a511dc1 100644 --- a/client/src/pistols/components/DuelistModal.tsx +++ b/client/src/pistols/components/DuelistModal.tsx @@ -51,11 +51,9 @@ export default function DuelistModal() { Duelist - + -
- {/*

We've found the following gravatar image associated with your e-mail address.

*/} - + {!isChallenging &&
} {isChallenging && }
@@ -135,10 +133,8 @@ function CreateChallenge({ })), []) return ( -
- - -

Issue a Challenge

+
+

New Challenge!


@@ -168,7 +164,7 @@ function CreateChallenge({
- setDays(parseInt(value as string))} /> + setDays(parseInt(value as string))} /> setHours(parseInt(value as string))} /> @@ -177,7 +173,7 @@ function CreateChallenge({ - + { const _lords = parseInt(e.target.value as string) if (!isNaN(_lords)) { diff --git a/client/styles/index.scss b/client/styles/index.scss index 15449c31..d227578d 100644 --- a/client/styles/index.scss +++ b/client/styles/index.scss @@ -227,12 +227,12 @@ canvas { } .FillWidth { - width: 100%; + width: 100%!important; min-width: 100%; align-items: center; } .FillHeight { - height: 100%; + height: 100%!important; min-height: 100%; vertical-align: middle; } From 18bed336235bf28c5657ba5f11a4cdb374a553e9 Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 19:29:32 -0300 Subject: [PATCH 14/21] Fixed Awaiting challenge countdown --- .../src/pistols/components/ChallengeTable.tsx | 12 +++--- client/src/pistols/hooks/useTimestamp.tsx | 39 +++++++++++++++---- client/src/pistols/utils/utils.tsx | 14 +++++-- 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/client/src/pistols/components/ChallengeTable.tsx b/client/src/pistols/components/ChallengeTable.tsx index 548ccf2b..1a7452a3 100644 --- a/client/src/pistols/components/ChallengeTable.tsx +++ b/client/src/pistols/components/ChallengeTable.tsx @@ -3,12 +3,12 @@ import { Grid, SemanticCOLORS, Table } from 'semantic-ui-react' import { useDojoAccount } from '@/dojo/DojoContext' import { useAllChallengeIds, useChallenge, useChallengeIdsByDuelist, useLiveChallengeIds, usePastChallengeIds } from '@/pistols/hooks/useChallenge' import { useDuelist } from '@/pistols/hooks/useDuelist' -import { useTimestampCountdown } from '@/pistols/hooks/useTimestamp' import { ProfilePicSquare } from '@/pistols/components/account/ProfilePic' import { MenuKey, usePistolsContext } from '@/pistols/hooks/PistolsContext' import { ChallengeState, ChallengeStateNames } from '@/pistols/utils/pistols' import { formatTimestamp, formatTimestampDelta } from '@/pistols/utils/utils' import { DuelIcons } from '@/pistols/components/DuelIcons' +import { useClientTimestamp } from '../hooks/useTimestamp' const Row = Grid.Row const Col = Grid.Column @@ -58,7 +58,7 @@ function ChallengeTableByIds({ const rows = useMemo(() => { let result = [] challengeIds.forEach((duelId, index) => { - result.push() + result.push() }) return result }, [challengeIds]) @@ -116,8 +116,6 @@ function DuelItem({ }= useChallenge(duelId) const { name: nameA, profilePic: profilePicA } = useDuelist(duelistA) const { name: nameB, profilePic: profilePicB } = useDuelist(duelistB) - const timestamp_system = useTimestampCountdown() - // console.log(timestamp, timestamp_expire, `>`, timestamp_system) useEffect(() => { sortCallback(duelId, state, timestamp) @@ -131,13 +129,15 @@ function DuelItem({ const isCanceled = useMemo(() => [ChallengeState.Withdrawn, ChallengeState.Refused].includes(state), [state]) const isDraw = useMemo(() => [ChallengeState.Draw].includes(state), [state]) + const { clientTimestamp } = useClientTimestamp(isAwaiting) + const date = useMemo(() => { - if (isAwaiting) return '⏱️ ' + formatTimestampDelta(timestamp_system, timestamp_expire) + if (isAwaiting) return '⏱️ ' + formatTimestampDelta(clientTimestamp, timestamp_expire) if (isInProgress || winnerIsA || winnerIsB) return /*'⚔️ ' +*/ formatTimestamp(timestamp_start) if (isCanceled) return /*'🚫 ' +*/ formatTimestamp(timestamp_end) if (isDraw) return /*'🤝 ' +*/ formatTimestamp(timestamp_end) return formatTimestamp(timestamp) - }, [state, timestamp, timestamp_expire, timestamp_start, timestamp_end]) + }, [state, timestamp, timestamp_expire, timestamp_start, timestamp_end, clientTimestamp]) const _gotoChallenge = () => { dispatchSetDuel(duelId, isYours ? MenuKey.YourDuels : isLive ? MenuKey.LiveDuels : MenuKey.PastDuels) diff --git a/client/src/pistols/hooks/useTimestamp.tsx b/client/src/pistols/hooks/useTimestamp.tsx index 36840825..54979fee 100644 --- a/client/src/pistols/hooks/useTimestamp.tsx +++ b/client/src/pistols/hooks/useTimestamp.tsx @@ -1,8 +1,37 @@ -import { useState } from "react" +import { useEffect, useState } from "react" import { useDojoSystemCalls } from '@/dojo/DojoContext' import { useEffectOnce } from "@/pistols/hooks/useEffectOnce" -export const useSystemTimestamp = () => { +export const useClientTimestamp = (autoUpdate: boolean = false) => { + const [clientTimestamp, setClientTimestamp] = useState(0) + + const _getTimestamp = () => (Math.floor(new Date().getTime() / 1000)) + + useEffect(() => { + let _mounted = true + let _timeout = null + // initialize + setClientTimestamp(_getTimestamp()) + // auto updates + if (autoUpdate) { + _timeout = setInterval(() => { + if (_mounted) { + setClientTimestamp(_getTimestamp()) + } + }, 1000) + } + return () => { + _mounted = false + clearTimeout(_timeout) + } + }, []) + + return { + clientTimestamp + } +} + +export const useContractTimestamp = () => { const { get_timestamp } = useDojoSystemCalls() const [isLoading, setIsLoading] = useState(null) const [timestamp, setTimestamp] = useState(null) @@ -30,9 +59,3 @@ export const useSystemTimestamp = () => { } } -export const useTimestampCountdown = () => { - const { timestamp } = useSystemTimestamp() - // TODO: create countdown loop - return timestamp -} - diff --git a/client/src/pistols/utils/utils.tsx b/client/src/pistols/utils/utils.tsx index 9e7a4ef8..84329af4 100644 --- a/client/src/pistols/utils/utils.tsx +++ b/client/src/pistols/utils/utils.tsx @@ -34,14 +34,22 @@ export const formatTimestamp = (t: number): string => { return `${date} ${hour}:${minutes}` } +export const formatTimestampCountdown = (end: number): string => { + const now = Math.floor(new Date().getTime() / 1000) + return formatTimestampDelta(now, end) +} + export const formatTimestampDelta = (start: number, end: number): string => { - const t = Math.max(end - start, 0) + const t = Math.max(0, end - start) const iso = (new Date(t * 1000).toISOString()) const [date, iso2] = iso.split('T') const [time, iso3] = iso2.split('.') const [hour, minutes, seconds] = time.split(':') - const days = '?' - return `${days}d ${hour}h ${minutes}m ${seconds}s` + const days = Math.floor(t / (24 * 60 * 60)) + let result = '' + if (days > 0) result += `${days}d ` + if (days > 0 || parseInt(hour) > 0) result += `${hour == '00' ? '0' : hour}h ` + return result + `${minutes}m ${seconds}s` } export const makeRandomInt = (maxNonInclusive: number) => (Math.floor(Math.random() * maxNonInclusive)) From b816649b8aa380b3a86d6524a049791f8c741153 Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 19:55:23 -0300 Subject: [PATCH 15/21] added to Challenge modal --- .../src/pistols/components/ChallengeModal.tsx | 19 ++++++++++--- .../src/pistols/components/ChallengeTable.tsx | 23 ++++------------ .../src/pistols/components/ChallengeTime.tsx | 27 +++++++++++++++++++ .../src/pistols/components/DuelistModal.tsx | 6 ++--- .../components/account/ProfileDescription.tsx | 12 ++++----- client/src/pistols/hooks/useChallenge.tsx | 5 ++++ 6 files changed, 62 insertions(+), 30 deletions(-) create mode 100644 client/src/pistols/components/ChallengeTime.tsx diff --git a/client/src/pistols/components/ChallengeModal.tsx b/client/src/pistols/components/ChallengeModal.tsx index 4b22207d..a3b5002b 100644 --- a/client/src/pistols/components/ChallengeModal.tsx +++ b/client/src/pistols/components/ChallengeModal.tsx @@ -11,6 +11,7 @@ import { ActionButton } from '@/pistols/components/ui/Buttons' import { ChallengeState, makeDuelUrl } from '@/pistols/utils/pistols' import { AccountShort } from '@/pistols/components/ui/Account' import { DuelIcons } from '@/pistols/components/DuelIcons' +import { ChallengeTime } from './ChallengeTime' const Row = Grid.Row const Col = Grid.Column @@ -23,7 +24,7 @@ export default function ChallengeModal() { const { atYourDuels, atLiveDuels, atPastDuels, duelId, dispatchSetDuel, dispatchSetDuelist } = usePistolsContext() - const { state, message, duelistA, duelistB, lords, isLive, isFinished } = useChallenge(duelId) + const { state, message, duelistA, duelistB, lords, isLive, isFinished, isAwaiting } = useChallenge(duelId) const { challengeDescription } = useChallengeDescription(duelId) @@ -49,7 +50,19 @@ export default function ChallengeModal() { onOpen={() => {}} open={(atYourDuels || atLiveDuels || atPastDuels) && duelId > 0} > - Challenge    + + + + + Challenge    + + + + + + + + dispatchSetDuelist(duelistA)} /> @@ -114,7 +127,7 @@ export default function ChallengeModal() { vs - + diff --git a/client/src/pistols/components/ChallengeTable.tsx b/client/src/pistols/components/ChallengeTable.tsx index 1a7452a3..9c64e6bd 100644 --- a/client/src/pistols/components/ChallengeTable.tsx +++ b/client/src/pistols/components/ChallengeTable.tsx @@ -3,12 +3,13 @@ import { Grid, SemanticCOLORS, Table } from 'semantic-ui-react' import { useDojoAccount } from '@/dojo/DojoContext' import { useAllChallengeIds, useChallenge, useChallengeIdsByDuelist, useLiveChallengeIds, usePastChallengeIds } from '@/pistols/hooks/useChallenge' import { useDuelist } from '@/pistols/hooks/useDuelist' +import { useClientTimestamp } from '@/pistols/hooks/useTimestamp' import { ProfilePicSquare } from '@/pistols/components/account/ProfilePic' import { MenuKey, usePistolsContext } from '@/pistols/hooks/PistolsContext' import { ChallengeState, ChallengeStateNames } from '@/pistols/utils/pistols' import { formatTimestamp, formatTimestampDelta } from '@/pistols/utils/utils' +import { ChallengeTime } from '@/pistols/components/ChallengeTime' import { DuelIcons } from '@/pistols/components/DuelIcons' -import { useClientTimestamp } from '../hooks/useTimestamp' const Row = Grid.Row const Col = Grid.Column @@ -112,7 +113,7 @@ function DuelItem({ const { account } = useDojoAccount() const { dispatchSetDuel } = usePistolsContext() const { - duelistA, duelistB, state, isLive, isFinished, winner, timestamp, timestamp_expire, timestamp_start, timestamp_end, + duelistA, duelistB, state, isLive, isCanceled, isInProgress, isFinished, isDraw, winner, timestamp, timestamp_expire, timestamp_start, timestamp_end, }= useChallenge(duelId) const { name: nameA, profilePic: profilePicA } = useDuelist(duelistA) const { name: nameB, profilePic: profilePicB } = useDuelist(duelistB) @@ -124,27 +125,13 @@ function DuelItem({ const isYours = useMemo(() => (BigInt(account.address) == duelistA || BigInt(account.address) == duelistB), [account, duelistA, duelistB]) const winnerIsA = useMemo(() => (duelistA == winner), [duelistA, winner]) const winnerIsB = useMemo(() => (duelistB == winner), [duelistB, winner]) - const isAwaiting = useMemo(() => [ChallengeState.Awaiting].includes(state), [state]) - const isInProgress = useMemo(() => [ChallengeState.InProgress].includes(state), [state]) - const isCanceled = useMemo(() => [ChallengeState.Withdrawn, ChallengeState.Refused].includes(state), [state]) - const isDraw = useMemo(() => [ChallengeState.Draw].includes(state), [state]) - - const { clientTimestamp } = useClientTimestamp(isAwaiting) - - const date = useMemo(() => { - if (isAwaiting) return '⏱️ ' + formatTimestampDelta(clientTimestamp, timestamp_expire) - if (isInProgress || winnerIsA || winnerIsB) return /*'⚔️ ' +*/ formatTimestamp(timestamp_start) - if (isCanceled) return /*'🚫 ' +*/ formatTimestamp(timestamp_end) - if (isDraw) return /*'🤝 ' +*/ formatTimestamp(timestamp_end) - return formatTimestamp(timestamp) - }, [state, timestamp, timestamp_expire, timestamp_start, timestamp_end, clientTimestamp]) const _gotoChallenge = () => { dispatchSetDuel(duelId, isYours ? MenuKey.YourDuels : isLive ? MenuKey.LiveDuels : MenuKey.PastDuels) } return ( - _gotoChallenge()}> + _gotoChallenge()}> @@ -170,7 +157,7 @@ function DuelItem({ - {date} + ) diff --git a/client/src/pistols/components/ChallengeTime.tsx b/client/src/pistols/components/ChallengeTime.tsx new file mode 100644 index 00000000..aac8caf9 --- /dev/null +++ b/client/src/pistols/components/ChallengeTime.tsx @@ -0,0 +1,27 @@ +import React, { useMemo } from 'react' +import { useChallenge } from '@/pistols/hooks/useChallenge' +import { ChallengeState } from '@/pistols/utils/pistols' +import { formatTimestamp, formatTimestampDelta } from '@/pistols/utils/utils' +import { useClientTimestamp } from '../hooks/useTimestamp' + +export function ChallengeTime({ + duelId, + prefixed = false, +}) { + const { + isAwaiting, isLive, isFinished, isCanceled, + timestamp, timestamp_expire, timestamp_start, timestamp_end, + } = useChallenge(duelId) + + const { clientTimestamp } = useClientTimestamp(isAwaiting) + + const date = useMemo(() => { + if (isAwaiting) return '⏱️ ' + formatTimestampDelta(clientTimestamp, timestamp_expire) + if (isLive) return (prefixed ? 'Started at ' : '') + formatTimestamp(timestamp_start) + if (isCanceled || isFinished) return (prefixed ? 'Finished at ' : '') + formatTimestamp(timestamp_end) + return formatTimestamp(timestamp) + }, [isAwaiting, isCanceled, isLive, isFinished, timestamp, timestamp_expire, timestamp_start, timestamp_end, clientTimestamp]) + + return {date} +} + diff --git a/client/src/pistols/components/DuelistModal.tsx b/client/src/pistols/components/DuelistModal.tsx index 4a511dc1..9aa567f0 100644 --- a/client/src/pistols/components/DuelistModal.tsx +++ b/client/src/pistols/components/DuelistModal.tsx @@ -133,8 +133,8 @@ function CreateChallenge({ })), []) return ( -
-

New Challenge!

+
+

New Challenge Conditions


@@ -173,7 +173,7 @@ function CreateChallenge({ - + { const _lords = parseInt(e.target.value as string) if (!isNaN(_lords)) { diff --git a/client/src/pistols/components/account/ProfileDescription.tsx b/client/src/pistols/components/account/ProfileDescription.tsx index 9399bc72..efc7f39f 100644 --- a/client/src/pistols/components/account/ProfileDescription.tsx +++ b/client/src/pistols/components/account/ProfileDescription.tsx @@ -14,17 +14,17 @@ export function ProfileDescription({

{preName} {name} {postName}

Honour: {honourDisplay}

- {displayStats && + {displayStats && total_duels > 0 &&
- Total Duels: {total_duels} + Duels: {total_duels}
- Total Wins: {total_wins} + Wins: {total_wins}
- Total Losses: {total_losses} + Losses: {total_losses}
- Total Draws: {total_draws} + Draws: {total_draws}
- Total Honour: {total_honour} + Accumulated Honour: {total_honour}
}
diff --git a/client/src/pistols/hooks/useChallenge.tsx b/client/src/pistols/hooks/useChallenge.tsx index 7627e4d6..1898572b 100644 --- a/client/src/pistols/hooks/useChallenge.tsx +++ b/client/src/pistols/hooks/useChallenge.tsx @@ -98,7 +98,12 @@ export const useChallenge = (duelId: bigint | string) => { roundNumber, winner, isLive: (state == ChallengeState.Awaiting || state == ChallengeState.InProgress), + isAwaiting: (state == ChallengeState.Awaiting), + isInProgress: (state == ChallengeState.InProgress), isFinished: (state == ChallengeState.Resolved || state == ChallengeState.Draw), + isResolved: (state == ChallengeState.Resolved), + isDraw: (state == ChallengeState.Draw), + isCanceled: (state == ChallengeState.Withdrawn || state == ChallengeState.Refused), // times timestamp, timestamp_expire, From baa040454023b3bae9e675fde205ad85cc980772 Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 20:12:31 -0300 Subject: [PATCH 16/21] Fixed timestamp_end not set when Duel is finished --- dojo/src/systems/shooter.cairo | 6 +++++- dojo/src/tests/test_duel.cairo | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dojo/src/systems/shooter.cairo b/dojo/src/systems/shooter.cairo index 2dd539ee..fdc4fc68 100644 --- a/dojo/src/systems/shooter.cairo +++ b/dojo/src/systems/shooter.cairo @@ -2,7 +2,7 @@ mod shooter { use core::option::OptionTrait; use core::traits::TryInto; - use starknet::{ContractAddress}; + use starknet::{ContractAddress, get_block_timestamp}; use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; use pistols::systems::{utils}; @@ -143,19 +143,23 @@ mod shooter { if (round.duelist_a.health == 0 && round.duelist_b.health == 0) { // both dead! challenge.state = ChallengeState::Draw.into(); + challenge.timestamp_end = get_block_timestamp(); } else if (round.duelist_a.health == 0) { // A is dead! challenge.state = ChallengeState::Resolved.into(); challenge.winner = challenge.duelist_b; + challenge.timestamp_end = get_block_timestamp(); } else if (round.duelist_b.health == 0) { // B is dead! challenge.state = ChallengeState::Resolved.into(); challenge.winner = challenge.duelist_a; + challenge.timestamp_end = get_block_timestamp(); } else { // both alive! if (challenge.round_number == constants::ROUND_COUNT) { // end in a Draw challenge.state = ChallengeState::Draw.into(); + challenge.timestamp_end = get_block_timestamp(); } else { // next round challenge.round_number += 1; diff --git a/dojo/src/tests/test_duel.cairo b/dojo/src/tests/test_duel.cairo index 4ec19794..4e4b6795 100644 --- a/dojo/src/tests/test_duel.cairo +++ b/dojo/src/tests/test_duel.cairo @@ -160,6 +160,7 @@ mod tests { assert(challenge.state == ChallengeState::Resolved.into(), '4_challenge.state'); assert(challenge.winner != zero_address(), '4_challenge.winner'); assert(challenge.round_number == 1, '4_challenge.round_number'); + assert(challenge.timestamp_end > 0, '4_challenge.timestamp_end'); assert(round.round_number == 1, '4__round.round_number'); assert(round.state == RoundState::Finished.into(), '4__state'); assert(round.duelist_a.hash == hash_1_a, '43__hash'); @@ -213,6 +214,7 @@ mod tests { assert(challenge.state == ChallengeState::Resolved.into(), '4_challenge.state'); assert(challenge.winner != zero_address(), '4_challenge.winner'); assert(challenge.round_number == 1, '4_challenge.round_number'); + assert(challenge.timestamp_end > 0, '4_challenge.timestamp_end'); assert(round.round_number == 1, '4__round.round_number'); assert(round.state == RoundState::Finished.into(), '4__state'); let duelist_a = utils::get_Duelist(world, owner); @@ -515,6 +517,7 @@ mod tests { let (challenge, round) = utils::get_Challenge_Round(world, duel_id); assert(challenge.state == ChallengeState::Draw.into(), '2__challenge.state'); assert(challenge.round_number == 2, '2__challenge.round_number'); + assert(challenge.timestamp_end > 0, '2__challenge.timestamp_end'); assert(round.round_number == 2, '2__round.round_number'); assert(round.state == RoundState::Finished.into(), '2__round.state'); assert(round.duelist_a.hash == hash_1_a, '2__hash_a'); @@ -607,6 +610,7 @@ mod tests { let (challenge, round) = utils::get_Challenge_Round(world, duel_id); assert(challenge.state == ChallengeState::Resolved.into(), '2__challenge.state'); assert(challenge.round_number == 2, '2__challenge.round_number'); + assert(challenge.timestamp_end > 0, '2__challenge.timestamp_end'); assert(round.round_number == 2, '2__round.round_number'); assert(round.state == RoundState::Finished.into(), '2__round.state'); assert(round.duelist_a.hash == hash_1_a, '2__hash_a'); From 374dca2b3d90d834018a660649b0673bd482ca26 Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 5 Jan 2024 20:30:12 -0300 Subject: [PATCH 17/21] Format all dates in local timezone --- client/src/pistols/utils/utils.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/src/pistols/utils/utils.tsx b/client/src/pistols/utils/utils.tsx index 84329af4..b9973ce5 100644 --- a/client/src/pistols/utils/utils.tsx +++ b/client/src/pistols/utils/utils.tsx @@ -27,7 +27,10 @@ export const feltToString = (hex: string): string => (BigInt(hex) > 0n ? shortSt export const pedersen = (a: bigint | string | number, b: bigint | string | number): bigint => (BigInt(ec.starkCurve.pedersen(BigInt(a), BigInt(b)))) export const formatTimestamp = (t: number): string => { - const iso = (new Date(t * 1000).toISOString()) + const timeUTC = new Date(t * 1000).getTime() + const tzoffset = (new Date(0)).getTimezoneOffset() * 60000 // local timezone offset in milliseconds + const localDate = new Date(timeUTC - tzoffset) + const iso = localDate.toISOString() const [date, iso2] = iso.split('T') const [time, iso3] = iso2.split('.') const [hour, minutes, seconds] = time.split(':') From 6dd4c0b86265cd73352f234cf00bbeadf2122b3e Mon Sep 17 00:00:00 2001 From: R13 Date: Wed, 10 Jan 2024 20:03:13 -0300 Subject: [PATCH 18/21] misc updates --- README.md | 1 + client/.env.dev | 1 - client/.env.slot | 2 +- client/src/dojo/DojoContext.tsx | 2 +- client/src/dojo/setupNetwork.ts | 6 ++-- client/src/manifest.json | 2 +- client/src/pistols/components/AppDojo.tsx | 2 +- client/src/pistols/hooks/useChallenge.tsx | 8 ++--- client/src/pistols/hooks/useDuelist.tsx | 2 +- client/src/pistols/hooks/useEntityKeys.tsx | 13 ++++++++ .../src/pistols/hooks/useEntityKeysQuery.tsx | 13 -------- dojo/scripts/default_auth.sh | 30 +++++++++++-------- 12 files changed, 43 insertions(+), 39 deletions(-) create mode 100644 client/src/pistols/hooks/useEntityKeys.tsx delete mode 100644 client/src/pistols/hooks/useEntityKeysQuery.tsx diff --git a/README.md b/README.md index 05154f08..83b705d6 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ rustup update curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh | sh # other stuff you might need +cargo install toml-cli brew install protobuf ``` diff --git a/client/.env.dev b/client/.env.dev index 06528727..bc93adf5 100644 --- a/client/.env.dev +++ b/client/.env.dev @@ -1,5 +1,4 @@ # pistols -NEXT_PUBLIC_PROOF_LOST_GAMES=1 NEXT_PUBLIC_DEBUG=1 # static diff --git a/client/.env.slot b/client/.env.slot index 2fd63863..28f45c1b 100644 --- a/client/.env.slot +++ b/client/.env.slot @@ -1,5 +1,5 @@ # pistols -NEXT_PUBLIC_PROOF_LOST_GAMES=0 +NEXT_PUBLIC_DEBUG=1 # static NEXT_PUBLIC_ETH_CONTRACT_ADDRESS=0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 diff --git a/client/src/dojo/DojoContext.tsx b/client/src/dojo/DojoContext.tsx index bc2195fa..02fd6210 100644 --- a/client/src/dojo/DojoContext.tsx +++ b/client/src/dojo/DojoContext.tsx @@ -92,7 +92,7 @@ export const useDojo = () => { // -// pistols +// NEW // export const useDojoAccount = () => { diff --git a/client/src/dojo/setupNetwork.ts b/client/src/dojo/setupNetwork.ts index 3417f50c..ebcfb164 100644 --- a/client/src/dojo/setupNetwork.ts +++ b/client/src/dojo/setupNetwork.ts @@ -1,9 +1,9 @@ +import { Account, num } from 'starknet' +import { DojoProvider, } from '@dojoengine/core' +import * as torii from '@dojoengine/torii-client' import { defineContractComponents } from './contractComponents' import { world } from './world' -import { DojoProvider, } from '@dojoengine/core' -import { Account, num } from 'starknet' import manifest from '@/manifest.json' -import * as torii from '@dojoengine/torii-client' export type SetupNetworkResult = Awaited> diff --git a/client/src/manifest.json b/client/src/manifest.json index 7cbfd7f5..d62bb2f2 100644 --- a/client/src/manifest.json +++ b/client/src/manifest.json @@ -949,7 +949,7 @@ { "name": "pistols::systems::actions::actions", "address": "0x78af18db6887ee0eb2b339f95619e88b65aa47c7025ad42dc81c7be43b631ff", - "class_hash": "0x601e133e04612f3e315dd692d926f3e1fc04effea91773fc3b2cf21591eaa7d", + "class_hash": "0x6fd66f89f1e1ccde9397313d2cb416fb340f1f98b1e509877ef93593a327637", "abi": [ { "type": "impl", diff --git a/client/src/pistols/components/AppDojo.tsx b/client/src/pistols/components/AppDojo.tsx index 123db162..91404b79 100644 --- a/client/src/pistols/components/AppDojo.tsx +++ b/client/src/pistols/components/AppDojo.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' import { useEffectOnce } from '@/pistols/hooks/useEffectOnce' import { DojoProvider } from '@/dojo/DojoContext' -import { setup } from '@/dojo/setup.ts' +import { setup } from '@/dojo/setup' import { GameplayProvider } from '@/pistols/hooks/GameplayContext' import App from '@/pistols/components/App' diff --git a/client/src/pistols/hooks/useChallenge.tsx b/client/src/pistols/hooks/useChallenge.tsx index 1898572b..a151c620 100644 --- a/client/src/pistols/hooks/useChallenge.tsx +++ b/client/src/pistols/hooks/useChallenge.tsx @@ -4,7 +4,7 @@ import { useComponentValue, useEntityQuery } from "@dojoengine/react" import { useDojoComponents } from '@/dojo/DojoContext' import { bigintToEntity, bigintToHex, feltToString } from "../utils/utils" import { ChallengeState, ChallengeStateDescriptions } from "@/pistols/utils/pistols" -import { useEntityKeys, useEntityKeysQuery } from '@/pistols/hooks/useEntityKeysQuery' +import { useEntityKeys, useEntityKeysQuery } from '@/pistols/hooks/useEntityKeys' import { useDuelist } from "./useDuelist" @@ -22,7 +22,7 @@ export const useAllChallengeIds = () => { export const useChallengeIdsByState = (state: ChallengeState) => { const { Challenge } = useDojoComponents() - const challengeIds: bigint[] = useEntityKeysQuery(Challenge, [HasValue(Challenge, { state: state })], 'duel_id') + const challengeIds: bigint[] = useEntityKeysQuery(Challenge, 'duel_id', [HasValue(Challenge, { state: state })]) return { challengeIds, } @@ -137,8 +137,8 @@ export const useChallengeDescription = (duelId: bigint) => { export const useChallengeIdsByDuelist = (address: bigint) => { const { Challenge } = useDojoComponents() - const challengerIds: bigint[] = useEntityKeysQuery(Challenge, [HasValue(Challenge, { duelist_a: BigInt(address) })], 'duel_id') - const challengedIds: bigint[] = useEntityKeysQuery(Challenge, [HasValue(Challenge, { duelist_b: BigInt(address) })], 'duel_id') + const challengerIds: bigint[] = useEntityKeysQuery(Challenge, 'duel_id', [HasValue(Challenge, { duelist_a: BigInt(address) })]) + const challengedIds: bigint[] = useEntityKeysQuery(Challenge, 'duel_id', [HasValue(Challenge, { duelist_b: BigInt(address) })]) const challengeIds: bigint[] = useMemo(() => ( [...challengerIds, ...challengedIds] ), [challengerIds, challengedIds]) diff --git a/client/src/pistols/hooks/useDuelist.tsx b/client/src/pistols/hooks/useDuelist.tsx index 9908ef6e..29778ce8 100644 --- a/client/src/pistols/hooks/useDuelist.tsx +++ b/client/src/pistols/hooks/useDuelist.tsx @@ -3,7 +3,7 @@ import { Entity, HasValue, Has, getComponentValue } from '@dojoengine/recs' import { useComponentValue, useEntityQuery } from '@dojoengine/react' import { useDojoComponents } from '@/dojo/DojoContext' import { bigintToEntity, feltToString } from '@/pistols/utils/utils' -import { useEntityKeys } from '@/pistols/hooks/useEntityKeysQuery' +import { useEntityKeys } from '@/pistols/hooks/useEntityKeys' //------------------ diff --git a/client/src/pistols/hooks/useEntityKeys.tsx b/client/src/pistols/hooks/useEntityKeys.tsx new file mode 100644 index 00000000..2ed523d6 --- /dev/null +++ b/client/src/pistols/hooks/useEntityKeys.tsx @@ -0,0 +1,13 @@ +import { useMemo } from 'react' +import { Entity, Has, getComponentValue, Component, QueryFragment } from '@dojoengine/recs' +import { useEntityQuery } from '@dojoengine/react' + +export const useEntityKeys = (component: Component, keyName: string) => { + return useEntityKeysQuery(component, keyName, [Has(component)]) +} + +export const useEntityKeysQuery = (component: Component, keyName: string, query: QueryFragment[]) => { + const entityIds: Entity[] = useEntityQuery(query) ?? [] + const keys: bigint[] = useMemo(() => entityIds.map((entityId) => BigInt(getComponentValue(component, entityId)[keyName])), [entityIds]) + return keys +} diff --git a/client/src/pistols/hooks/useEntityKeysQuery.tsx b/client/src/pistols/hooks/useEntityKeysQuery.tsx deleted file mode 100644 index e9666da4..00000000 --- a/client/src/pistols/hooks/useEntityKeysQuery.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useMemo } from 'react' -import { Entity, HasValue, Has, getComponentValue, Component, QueryFragment } from '@dojoengine/recs' -import { useEntityQuery, useComponentValue } from '@dojoengine/react' - -export const useEntityKeys = (component: Component, keyName: string) => { - return useEntityKeysQuery(component, [Has(component)], keyName) -} - -export const useEntityKeysQuery = (component: Component, query: QueryFragment[], keyName: string) => { - const entityIds: Entity[] = useEntityQuery(query) ?? [] - const keys: bigint[] = useMemo(() => entityIds.map((entityId) => BigInt(getComponentValue(component, entityId)[keyName])), [entityIds]) - return keys -} diff --git a/dojo/scripts/default_auth.sh b/dojo/scripts/default_auth.sh index 6fb2a393..5aa9256c 100755 --- a/dojo/scripts/default_auth.sh +++ b/dojo/scripts/default_auth.sh @@ -2,25 +2,29 @@ set -euo pipefail pushd $(dirname "$0")/.. -export RPC_URL="http://localhost:5050" +if ! [ -x "$(command -v toml)" ]; then + echo 'Error: toml not instlaled! Instal with: cargo install toml-cli' + exit 1 +fi -export WORLD_ADDRESS=$(cat ./target/dev/manifest.json | jq -r '.world.address') +export RPC_URL=$(toml get Scarb.toml --raw tool.dojo.env.rpc_url) +export ACCOUNT_ADDRESS=$(toml get Scarb.toml --raw tool.dojo.env.account_address) export ACTIONS_ADDRESS=$(cat ./target/dev/manifest.json | jq -r '.contracts[] | select(.name == "pistols::systems::actions::actions" ).address') +export WORLD_ADDRESS=$(cat ./target/dev/manifest.json | jq -r '.world.address') + +export COMPONENTS=("Duelist" "Challenge" "Pact" "Move" "Round") echo "---------------------------------------------------------------------------" -echo "auth writer" -echo "world : $WORLD_ADDRESS" -echo "actions : $ACTIONS_ADDRESS" -echo "RPC : $RPC_URL" +echo "sozo auth writer" +echo "RPC : $RPC_URL" +echo "world : $WORLD_ADDRESS" +echo "account : $ACCOUNT_ADDRESS" +echo "actions : $ACTIONS_ADDRESS" +echo "components : ${COMPONENTS[*]}" echo "---------------------------------------------------------------------------" -# enable system -> component authorizations -COMPONENTS=("Duelist" "Challenge" "Pact" "Move" "Round") - for component in ${COMPONENTS[@]}; do - sozo auth writer --world $WORLD_ADDRESS --rpc-url $RPC_URL $component $ACTIONS_ADDRESS - # SLOT - # sozo auth writer --world $WORLD_ADDRESS --rpc-url https://api.cartridge.gg/x/pistols/katana $component 0x78af18db6887ee0eb2b339f95619e88b65aa47c7025ad42dc81c7be43b631ff --account-address 0x3de8cead289fe145cfea143ac58ced6c83e518a758469df850e5c37445c95ae + sozo auth writer --world $WORLD_ADDRESS --rpc-url $RPC_URL $component $ACTIONS_ADDRESS --account-address $ACCOUNT_ADDRESS done -echo "Default authorizations have been successfully set." +echo "Default authorizations have been successfully set! 👍" From 13decd4f66e0797a576f8d2feefcbeba74abb978 Mon Sep 17 00:00:00 2001 From: R13 Date: Tue, 16 Jan 2024 13:03:07 -0300 Subject: [PATCH 19/21] Fixed vscode debugger --- .vscode/launch.json | 12 ++---------- client/tsconfig.json | 4 +++- pistols.code-workspace | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index a69b8d5e..e4910e96 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,16 +8,8 @@ "type": "chrome", "request": "launch", "name": "Launch Chrome against localhost", - "url": "http://localhost:5173/", - "webRoot": "/Users/roger/Dev/Blockchain/Realms/lootunderworld/client/src/dojo", - // "webRoot": "${workspaceFolder}", - "sourceMapPathOverrides": { - "webpack:/*": "${webRoot}/*", - "/./*": "${webRoot}/*", - "/src/*": "${webRoot}/*", - "/*": "*", - "/./~/*": "${webRoot}/node_modules/*" - }, + "url": "http://localhost:3000/", + "webRoot": "${workspaceRoot}/client", } ] } \ No newline at end of file diff --git a/client/tsconfig.json b/client/tsconfig.json index d789e405..62e7a1e3 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -41,7 +41,9 @@ "src/*" ] }, - "strict": false + "strict": false, + // vscode debugger + "sourceMap": true }, "include": [ "./src", diff --git a/pistols.code-workspace b/pistols.code-workspace index e1aae1c5..487b53dd 100644 --- a/pistols.code-workspace +++ b/pistols.code-workspace @@ -9,10 +9,10 @@ "**/node_modules": true, "**/build": true, "**/.github": true, - "**/.vscode": true, "**/.next": true, "**/_bak": true, "**/*.tsbuildinfo": true, + // "**/.vscode": true, // "**/.env*": true, }, "search.exclude": { From b7a41b3ba10d1b50c726e203acfdad3affafee19 Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 19 Jan 2024 14:19:17 -0300 Subject: [PATCH 20/21] Upgrade to Dojo 0.4.4, Cairo 2.4, dojo.js 0.3.4 --- client/package-lock.json | 98 +++++++++++++++++++-------------- client/package.json | 13 +++-- client/src/dojo/setup.ts | 2 +- client/src/dojo/setupNetwork.ts | 2 +- client/styles/index.scss | 8 +-- dojo/Scarb.toml | 4 +- 6 files changed, 72 insertions(+), 55 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index ab473fac..13fd4b7a 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -8,12 +8,13 @@ "name": "pistols", "version": "0.1.0", "dependencies": { - "@dojoengine/core": "^0.2.9", - "@dojoengine/create-burner": "^0.2.9", - "@dojoengine/react": "^0.2.9", + "@dojoengine/core": "^0.3.4", + "@dojoengine/create-burner": "^0.3.4", + "@dojoengine/react": "^0.3.4", "@dojoengine/recs": "^0.1.35", - "@dojoengine/torii-client": "^0.2.9", - "@dojoengine/utils": "^0.2.9", + "@dojoengine/state": "^0.3.4", + "@dojoengine/torii-client": "^0.3.4", + "@dojoengine/utils": "^0.3.4", "@tweenjs/tween.js": "^21.0.0", "event-emitter": "^0.3.5", "next": "^13.5.6", @@ -26,7 +27,7 @@ "semantic-ui-react": "^3.0.0-beta.0", "starknet": "5.24.3", "three": "^0.157.0", - "type-fest": "^4.8.3", + "type-fest": "^2.14.0", "use-local-storage-state": "^19.1.0" }, "devDependencies": { @@ -58,9 +59,9 @@ "integrity": "sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw==" }, "node_modules/@babel/runtime": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.6.tgz", - "integrity": "sha512-zHd0eUrf5GZoOWVCXp6koAKQTfZV07eit6bGPmJgnZdnSAvvZee6zniW2XMF7Cmc4ISOOnPy3QaSiIJGJkVEDQ==", + "version": "7.23.8", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.8.tgz", + "integrity": "sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -69,20 +70,20 @@ } }, "node_modules/@dojoengine/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@dojoengine/core/-/core-0.2.9.tgz", - "integrity": "sha512-5qXGi7ddCoP+cuaOFroz5U3Asb9fa4DiEApIGtJjMJWr3eVNzXhHYiwvNJjQOUgBXVhqnFBfIqilrPKekR9Svg==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@dojoengine/core/-/core-0.3.4.tgz", + "integrity": "sha512-mFuARLAomz+TQILr9IWSzhBGYtE31FMhZSYqYctoIDOQCCuUvBUUrwx5A1AOKC+CYv5LgvHc40L/mNEX5JUsKw==", "bin": { "create-components": "dist/bin/generateComponents.cjs" }, "peerDependencies": { - "starknet": "5.24.3" + "starknet": "^5.24.3" } }, "node_modules/@dojoengine/create-burner": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@dojoengine/create-burner/-/create-burner-0.2.9.tgz", - "integrity": "sha512-C4lEgAi4IjeDCcfZKBM+QrWxyut9Mio9WafSl/mit+GQB4D0vo542B97O7/tWAh4Bl2jDZ5PwWgfndRzUBYqSA==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@dojoengine/create-burner/-/create-burner-0.3.4.tgz", + "integrity": "sha512-VlehQ8hZHA80fqIAZGSR3GlV2ELVVpM4Sbf8Dyn6eFbK/oHBm8cKLDs1jgtvdZyETr4BnGBwqPGLmbH5DJCYzQ==", "dependencies": { "@starknet-react/core": "^1.0.3", "encoding": "^0.1.13", @@ -91,7 +92,7 @@ }, "peerDependencies": { "react": "^18.2.0", - "starknet": "5.24.3" + "starknet": "^5.24.3" } }, "node_modules/@dojoengine/create-burner/node_modules/@starknet-react/core": { @@ -115,13 +116,14 @@ "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" }, "node_modules/@dojoengine/react": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@dojoengine/react/-/react-0.2.9.tgz", - "integrity": "sha512-6b7+vj/+sdPjj63fnXWYi83Z70wAhDpjlvswjQPhaPC2R7a9CCOAC7eCbyLvMfD5nhYYtB5LU7IpKo9TNEmrFQ==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@dojoengine/react/-/react-0.3.4.tgz", + "integrity": "sha512-1lurtkgxBdNzcjp6VisgBLvIHyV4WU49FVEVcSaKreNMjNnF7djaGq2QghmIGWPw7hELMbo6845J3ctes5uRrQ==", "dependencies": { "@dojoengine/recs": "0.1.35", - "@dojoengine/torii-client": "^0.2.9", - "@dojoengine/utils": "^0.2.9", + "@dojoengine/state": "^0.3.4", + "@dojoengine/torii-client": "^0.3.4", + "@dojoengine/utils": "^0.3.4", "@latticexyz/utils": "^2.0.0-next.11", "encoding": "^0.1.13", "fast-deep-equal": "^3.1.3", @@ -131,7 +133,8 @@ }, "peerDependencies": { "react": "^18.2.0", - "starknet": "^5.19.0" + "starknet": "^5.24.3", + "type-fest": "^2.14.0" } }, "node_modules/@dojoengine/recs": { @@ -145,24 +148,37 @@ "rxjs": "7.5.5" } }, + "node_modules/@dojoengine/state": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@dojoengine/state/-/state-0.3.4.tgz", + "integrity": "sha512-6O7s3LNzrbov7dfihuGRkIBKROJunHLov1cwI5zt0FtIHQIk/0+n3Y+KjI6o2zdSI+/MZ98V6505+GnLSHumMQ==", + "dependencies": { + "@dojoengine/recs": "0.1.35", + "@dojoengine/torii-client": "^0.3.4", + "@latticexyz/utils": "^2.0.0-next.11" + }, + "peerDependencies": { + "starknet": "^5.24.3" + } + }, "node_modules/@dojoengine/torii-client": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@dojoengine/torii-client/-/torii-client-0.2.9.tgz", - "integrity": "sha512-TRDb7L8Y6YtDdDfdsRUbW94M5s0xws+rnk/9t1ckw3qeK9phRVnMup+vgmU/Q2KTbsX5IxmSNzj7g71RXd5VJQ==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@dojoengine/torii-client/-/torii-client-0.3.4.tgz", + "integrity": "sha512-ZTMy9S2f6NDmUFBMhNMwc7jDn0TnWkwdhk760HSpXZmky1AZw88/9pcqr7IP3s6Q2mCx+/GKoQ/vBRoucnjGng==", "dependencies": { - "@dojoengine/torii-wasm": "^0.2.9", + "@dojoengine/torii-wasm": "^0.3.4", "typescript": "^5.0.3" } }, "node_modules/@dojoengine/torii-wasm": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@dojoengine/torii-wasm/-/torii-wasm-0.2.9.tgz", - "integrity": "sha512-mvCnWwxyM5LjQVCXVqHt56ySXUh3svrFStBRw/UCg3IlDp+FBbJfgEglaChL0pBzFHqH9o1hPE8vmPQWwK2tjQ==" + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@dojoengine/torii-wasm/-/torii-wasm-0.3.4.tgz", + "integrity": "sha512-XiFQSHwKMqpVoul8Y4tpVnxa9qA1GI2/231Ar7yxgFnqSJkSYuehorJsGNuckUWZPDwzHRJ/c21OXF2qpnMydA==" }, "node_modules/@dojoengine/utils": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@dojoengine/utils/-/utils-0.2.9.tgz", - "integrity": "sha512-/KKeoOhE/sYBs/7tiEJ9YWPTaeWslF4uSLxVlWvnLa0XQbr29qww5a1109d651ozCTiDxficIDAt3npEEuY+pQ==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@dojoengine/utils/-/utils-0.3.4.tgz", + "integrity": "sha512-7c4Y2dqMqjfTNAJddVmGI9qtCEOMJ6w42H0iQyIn1XF8fFECfH2iEdf5ok5p28EfGh5ihyAvNydTVlBIMmTGVg==", "dependencies": { "@dojoengine/recs": "0.1.35", "@latticexyz/utils": "^2.0.0-next.11", @@ -3020,11 +3036,11 @@ "integrity": "sha512-BP0vn+NGYvzDielvBZaFain/wgeJ1hTvURCqtKvhr1SCPePdaaTanmmcplrHfEJSJOUql7hk4FHwToNJjWRY3g==" }, "node_modules/mathjs": { - "version": "12.2.1", - "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-12.2.1.tgz", - "integrity": "sha512-/uG/yMP0wUSfALCyJkKco0gYlrp0kHFt4yNT3E+ZCoiWpsT9GdtLqydxHp3gjDCQrR4GGBDXMnKOQtJbmIe9SQ==", + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-12.3.0.tgz", + "integrity": "sha512-Mik+O8gbH14/1V2D/vdJNgu+qGXpF+2oeBJVBqN8nbOdZNuu4Nxw6aDbJ0QOkDSq/9bQ+AZpXoIxBuErRODS8w==", "dependencies": { - "@babel/runtime": "^7.23.6", + "@babel/runtime": "^7.23.8", "complex.js": "^2.1.1", "decimal.js": "^10.4.3", "escape-latex": "^1.2.0", @@ -3865,11 +3881,11 @@ } }, "node_modules/type-fest": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.3.tgz", - "integrity": "sha512-//BaTm14Q/gHBn09xlnKNqfI8t6bmdzx2DXYfPBNofN0WUybCEUDcbCWcTa0oF09lzLjZgPphXAsvRiMK0V6Bw==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "engines": { - "node": ">=16" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" diff --git a/client/package.json b/client/package.json index 4d3cfb40..71a150d6 100644 --- a/client/package.json +++ b/client/package.json @@ -12,12 +12,13 @@ "create-components_local": "script/generateComponents.cjs ../dojo/target/dev/manifest.json src/dojo/contractComponents.ts" }, "dependencies": { - "@dojoengine/core": "^0.2.9", - "@dojoengine/create-burner": "^0.2.9", - "@dojoengine/react": "^0.2.9", + "@dojoengine/core": "^0.3.4", + "@dojoengine/create-burner": "^0.3.4", + "@dojoengine/react": "^0.3.4", "@dojoengine/recs": "^0.1.35", - "@dojoengine/torii-client": "^0.2.9", - "@dojoengine/utils": "^0.2.9", + "@dojoengine/state": "^0.3.4", + "@dojoengine/torii-client": "^0.3.4", + "@dojoengine/utils": "^0.3.4", "@tweenjs/tween.js": "^21.0.0", "event-emitter": "^0.3.5", "next": "^13.5.6", @@ -30,7 +31,7 @@ "semantic-ui-react": "^3.0.0-beta.0", "starknet": "5.24.3", "three": "^0.157.0", - "type-fest": "^4.8.3", + "type-fest": "^2.14.0", "use-local-storage-state": "^19.1.0" }, "devDependencies": { diff --git a/client/src/dojo/setup.ts b/client/src/dojo/setup.ts index a61fb4d0..a31742f3 100644 --- a/client/src/dojo/setup.ts +++ b/client/src/dojo/setup.ts @@ -1,7 +1,7 @@ import { createClientComponents } from './createClientComponents' import { createSystemCalls } from './createSystemCalls' import { setupNetwork } from './setupNetwork' -import { getSyncEntities } from '@dojoengine/react' +import { getSyncEntities } from '@dojoengine/state' export type SetupResult = Awaited> diff --git a/client/src/dojo/setupNetwork.ts b/client/src/dojo/setupNetwork.ts index ebcfb164..c3026bfe 100644 --- a/client/src/dojo/setupNetwork.ts +++ b/client/src/dojo/setupNetwork.ts @@ -14,7 +14,7 @@ export async function setupNetwork() { if (!process.env.NEXT_PUBLIC_TORII) throw (`NEXT_PUBLIC_TORII is null`) // Create a new DojoProvider instance. - const provider = new DojoProvider(process.env.NEXT_PUBLIC_WORLD_ADDRESS, manifest, process.env.NEXT_PUBLIC_NODE_URL) + const provider = new DojoProvider(manifest, process.env.NEXT_PUBLIC_NODE_URL) const toriiClient = await torii.createClient([], { rpcUrl: process.env.NEXT_PUBLIC_NODE_URL, diff --git a/client/styles/index.scss b/client/styles/index.scss index d227578d..e326da1f 100644 --- a/client/styles/index.scss +++ b/client/styles/index.scss @@ -542,20 +542,20 @@ $box-h: calc((100vh - $aspect-h) / 2); } .StepsIcon { font-family: monospace!important; - font-size: 16px!important; + font-size: 12px!important; font-weight: 600!important; color: $color-bg; text-shadow: 0 0 2px #000; margin: -2px 0 0 -2px!important; } .StepsIcon.small { - font-size: 14px!important; + font-size: 12px!important; } .StepsIcon.large { - font-size: 20px!important; + font-size: 16px!important; } .StepsIcon.big { - font-size: 24px!important; + font-size: 20px!important; } .StepsIconRound { diff --git a/dojo/Scarb.toml b/dojo/Scarb.toml index 2f995453..acae37b7 100644 --- a/dojo/Scarb.toml +++ b/dojo/Scarb.toml @@ -7,7 +7,7 @@ website = "https://pistols.lootunder.world" socials.x = "https://twitter.com/lootunderworld" [package] -cairo-version = "2.3.1" +cairo-version = "2.4.0" name = "pistols" version = "0.2.0" @@ -16,7 +16,7 @@ sierra-replace-ids = true [dependencies] # dojo = { git = "https://github.com/dojoengine/dojo.git", rev = "01eab985a3f5056e47cc7b4753ca24f64d3a078a" } -dojo = { git = "https://github.com/dojoengine/dojo.git", tag = "v0.4.3" } +dojo = { git = "https://github.com/dojoengine/dojo.git", tag = "v0.4.4" } [[target.dojo]] From 92d48a50a3c88241165bf8998ed0784adcb8778f Mon Sep 17 00:00:00 2001 From: R13 Date: Fri, 19 Jan 2024 14:50:58 -0300 Subject: [PATCH 21/21] Slot deployment, version 0.3.0 --- client/.env.slot | 4 ++-- dojo/Scarb.toml | 6 +++--- dojo/migrate | 19 +++++++++++++------ dojo/migrate_slot | 14 -------------- 4 files changed, 18 insertions(+), 25 deletions(-) delete mode 100755 dojo/migrate_slot diff --git a/client/.env.slot b/client/.env.slot index 28f45c1b..d3bf8c56 100644 --- a/client/.env.slot +++ b/client/.env.slot @@ -11,5 +11,5 @@ NEXT_PUBLIC_WORLD_ADDRESS=0x269c58e5fa1e7f6fe3756f1de88ecdfab7d03ba67e79ba0365b4 NEXT_PUBLIC_NODE_URL=https://api.cartridge.gg/x/pistols/katana NEXT_PUBLIC_TORII=https://api.cartridge.gg/x/pistols/torii # from katana -NEXT_PUBLIC_MASTER_ADDRESS=0x35d0cdaf12e6816f4a1a5c074befbddd08abf61bbea87765342289b48b4bc16 -NEXT_PUBLIC_MASTER_PRIVATE_KEY=0x2cbd34ec84e50d1616c3d0b17799a5f2fd7448f2039e4652eb950586f06ad60 +NEXT_PUBLIC_MASTER_ADDRESS=0x2e0e12a0275b03172bb09aafac8e288599678032493fef65adc1af87771bdaa +NEXT_PUBLIC_MASTER_PRIVATE_KEY=0x3cfcac8524dd04d352479c89b5685b9f3b4e788e226305e1df18712154afd76 diff --git a/dojo/Scarb.toml b/dojo/Scarb.toml index acae37b7..ed466b3c 100644 --- a/dojo/Scarb.toml +++ b/dojo/Scarb.toml @@ -9,7 +9,7 @@ socials.x = "https://twitter.com/lootunderworld" [package] cairo-version = "2.4.0" name = "pistols" -version = "0.2.0" +version = "0.3.0" [cairo] sierra-replace-ids = true @@ -34,5 +34,5 @@ world_address = "0x269c58e5fa1e7f6fe3756f1de88ecdfab7d03ba67e79ba0365b4ef1e81155 # SLOT rpc_url = "https://api.cartridge.gg/x/pistols/katana" -account_address = "0x3de8cead289fe145cfea143ac58ced6c83e518a758469df850e5c37445c95ae" -private_key = "0x2cbd34ec84e50d1616c3d0b17799a5f2fd7448f2039e4652eb950586f06ad60" +account_address = "0x2e0e12a0275b03172bb09aafac8e288599678032493fef65adc1af87771bdaa" +private_key = "0x3cfcac8524dd04d352479c89b5685b9f3b4e788e226305e1df18712154afd76" diff --git a/dojo/migrate b/dojo/migrate index 3a0a2d80..88dd6677 100755 --- a/dojo/migrate +++ b/dojo/migrate @@ -1,18 +1,25 @@ #!/bin/bash set -e -export WORLD_ADDRESS="0x269c58e5fa1e7f6fe3756f1de88ecdfab7d03ba67e79ba0365b4ef1e81155be" -export RPC_URL="http://localhost:5050/" - - -#sozo --offline build +#----------------- +# migrate +# sozo migrate +#----------------- +# auth write +# scripts/default_auth.sh -cp target/dev/manifest.json ../client/src/ +#----------------- +# client setup +# +export WORLD_ADDRESS="0x269c58e5fa1e7f6fe3756f1de88ecdfab7d03ba67e79ba0365b4ef1e81155be" +export RPC_URL="http://localhost:5050/" +cp target/dev/manifest.json ../client/src/ cd ../client npm run create-components $RPC_URL $WORLD_ADDRESS +#----------------- echo "--- DONE! 👍" diff --git a/dojo/migrate_slot b/dojo/migrate_slot deleted file mode 100755 index f9c241ea..00000000 --- a/dojo/migrate_slot +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -e - -#sozo --offline build -sozo migrate --rpc-url https://api.cartridge.gg/x/pistols/katana --account-address 0x35d0cdaf12e6816f4a1a5c074befbddd08abf61bbea87765342289b48b4bc16 --verbose - -scripts/default_auth.sh - -# cp target/dev/manifest.json ../client/src/ - -# cd ../client -# npm run create-components - -echo "--- DONE! 👍"