diff --git a/client/src/dojo/debouncedQueries.ts b/client/src/dojo/debouncedQueries.ts index 0f256ba09..58558184e 100644 --- a/client/src/dojo/debouncedQueries.ts +++ b/client/src/dojo/debouncedQueries.ts @@ -3,6 +3,7 @@ import { ToriiClient } from "@dojoengine/torii-client"; import debounce from "lodash/debounce"; import { addArrivalsSubscription, + addHyperstructureSubscription, addMarketSubscription, addToSubscription, addToSubscriptionOneKeyModelbyRealmEntityId, @@ -55,7 +56,7 @@ class RequestQueue { const positionQueue = new RequestQueue(); const subscriptionQueue = new RequestQueue(); const marketQueue = new RequestQueue(); - +const hyperstructureQueue = new RequestQueue(); // Debounced functions that add to queues export const debouncedSyncPosition = debounce( async ( @@ -141,9 +142,22 @@ export const debouncedAddMarketSubscription = debounce( { leading: true }, ); +export const debouncedAddHyperstructureSubscription = debounce( + async ( + client: ToriiClient, + components: Component[], + onComplete?: () => void, + ) => { + await hyperstructureQueue.add(() => addHyperstructureSubscription(client, components), onComplete); + }, + 500, + { leading: true }, +); + // Utility function to clear all queues if needed export const clearAllQueues = () => { positionQueue.clear(); subscriptionQueue.clear(); marketQueue.clear(); + hyperstructureQueue.clear(); }; diff --git a/client/src/dojo/queries.ts b/client/src/dojo/queries.ts index 35cb30953..20f2e334d 100644 --- a/client/src/dojo/queries.ts +++ b/client/src/dojo/queries.ts @@ -153,6 +153,44 @@ export const addMarketSubscription = async ( console.log("MarketEnd", end - start); }; +export const addHyperstructureSubscription = async ( + client: ToriiClient, + components: Component[], +) => { + const start = performance.now(); + await getEntities( + client, + { + Composite: { + operator: "Or", + clauses: [ + { + Keys: { + keys: [undefined, undefined], + pattern_matching: "FixedLen", + models: ["s0_eternum-Epoch", "s0_eternum-Progress"], + }, + }, + { + Keys: { + keys: [undefined, undefined, undefined], + pattern_matching: "FixedLen", + models: ["s0_eternum-Contribution"], + }, + }, + ], + }, + }, + components as any, + [], + [], + 40_000, + false, + ); + const end = performance.now(); + console.log("HyperstructureEnd", end - start); +}; + export const addArrivalsSubscription = async ( client: ToriiClient, components: Component[], diff --git a/client/src/ui/components/worldmap/players/PlayerList.tsx b/client/src/ui/components/worldmap/players/PlayerList.tsx index 1431ef3d9..b36ef8622 100644 --- a/client/src/ui/components/worldmap/players/PlayerList.tsx +++ b/client/src/ui/components/worldmap/players/PlayerList.tsx @@ -38,11 +38,16 @@ export const PlayerList = ({ sort: "none", }); + const sortedPlayers = useMemo( + () => sortItems(players, activeSort, { sortKey: "rank", sort: "asc" }), + [players, activeSort], + ); + return (
- {sortItems(players, activeSort, { sortKey: "rank", sort: "asc" }).map((player) => ( + {sortedPlayers.map((player) => ( { const term = searchTerm.toLowerCase(); diff --git a/client/src/ui/layouts/World.tsx b/client/src/ui/layouts/World.tsx index 07d4c9eb3..5448f989e 100644 --- a/client/src/ui/layouts/World.tsx +++ b/client/src/ui/layouts/World.tsx @@ -5,6 +5,7 @@ import useUIStore from "../../hooks/store/useUIStore"; import { debounceAddResourceArrivals, + debouncedAddHyperstructureSubscription, debouncedAddMarketSubscription, debouncedAddToSubscription, debouncedAddToSubscriptionOneKey, @@ -229,6 +230,27 @@ export const World = ({ backgroundImage }: { backgroundImage: string }) => { fetch(); }, []); + useEffect(() => { + const fetch = async () => { + try { + setLoading(LoadingStateKey.Hyperstructure, true); + console.log("AddToSubscriptionStart - 4"); + await Promise.all([ + debouncedAddHyperstructureSubscription(dojo.network.toriiClient, dojo.network.contractComponents as any, () => + setLoading(LoadingStateKey.Hyperstructure, false), + ), + ]); + } catch (error) { + console.error("Fetch failed", error); + } finally { + // Ensure loading states are reset even if there's an error + setLoading(LoadingStateKey.Hyperstructure, false); + } + }; + + fetch(); + }, []); + const battleViewContent = useMemo( () => (
diff --git a/client/src/ui/modules/navigation/TopNavigation.tsx b/client/src/ui/modules/navigation/TopNavigation.tsx index b8ebb09ab..551b1137c 100644 --- a/client/src/ui/modules/navigation/TopNavigation.tsx +++ b/client/src/ui/modules/navigation/TopNavigation.tsx @@ -1,5 +1,4 @@ import { useGetAllPlayers } from "@/hooks/helpers/use-get-all-players"; - import { memo } from "react"; import { Rewards } from "../rewards/Rewards"; import { SettingsWindow } from "../settings/Settings"; @@ -7,12 +6,11 @@ import { Social } from "../social/Social"; export const TopMiddleNavigation = memo(() => { const getPlayers = useGetAllPlayers(); - const players = getPlayers(); return ( <>
- +
diff --git a/client/src/ui/modules/social/Social.tsx b/client/src/ui/modules/social/Social.tsx index 92178c677..a38abdb77 100644 --- a/client/src/ui/modules/social/Social.tsx +++ b/client/src/ui/modules/social/Social.tsx @@ -1,5 +1,5 @@ import { useDojo } from "@/hooks/context/DojoContext"; -import { useHyperstructureData } from "@/hooks/store/useLeaderBoardStore"; +import { useHyperstructureData, useLeaderBoardStore } from "@/hooks/store/useLeaderBoardStore"; import useUIStore from "@/hooks/store/useUIStore"; import { HintSection } from "@/ui/components/hints/HintModal"; import { social } from "@/ui/components/navigation/Config"; @@ -12,11 +12,11 @@ import { Tabs } from "@/ui/elements/tab"; import { ContractAddress, ID, Player } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { Has } from "@dojoengine/recs"; -import { useMemo, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { EndSeasonButton } from "./EndSeasonButton"; import { PlayerId } from "./PlayerId"; -export const Social = ({ players }: { players: Player[] }) => { +export const Social = ({ getPlayers }: { getPlayers: () => Player[] }) => { const { setup: { components: { @@ -26,7 +26,7 @@ export const Social = ({ players }: { players: Player[] }) => { } = useDojo(); const [selectedTab, setSelectedTab] = useState(0); const [isExpanded, setIsExpanded] = useState(false); - + const [isLoading, setIsLoading] = useState(false); const [selectedGuild, setSelectedGuild] = useState(0); const [selectedPlayer, setSelectedPlayer] = useState(0n); @@ -35,8 +35,21 @@ export const Social = ({ players }: { players: Player[] }) => { const gameEnded = useEntityQuery([Has(GameEnded)]); + const [players, setPlayers] = useState(() => getPlayers()); + const playersByRank = useLeaderBoardStore((state) => state.playersByRank); + const updateLeaderboard = useHyperstructureData(); + const handleUpdatePoints = () => { + setIsLoading(true); + updateLeaderboard(); + }; + + useEffect(() => { + setPlayers(getPlayers()); + setIsLoading(false); + }, [playersByRank]); + const viewGuildMembers = (guildEntityId: ID) => { if (selectedGuild === guildEntityId) { setSelectedPlayer(0n); @@ -112,7 +125,7 @@ export const Social = ({ players }: { players: Player[] }) => {
{gameEnded.length === 0 && } -
diff --git a/client/src/ui/modules/world-structures/WorldStructuresMenu.tsx b/client/src/ui/modules/world-structures/WorldStructuresMenu.tsx index 22e5a2d58..2e55caf1e 100644 --- a/client/src/ui/modules/world-structures/WorldStructuresMenu.tsx +++ b/client/src/ui/modules/world-structures/WorldStructuresMenu.tsx @@ -7,8 +7,6 @@ import { useFragmentMines } from "@/hooks/helpers/useFragmentMines"; import { useGuilds } from "@/hooks/helpers/useGuilds"; import { useHyperstructureProgress, useHyperstructures } from "@/hooks/helpers/useHyperstructures"; import { useResourceBalance } from "@/hooks/helpers/useResources"; -import useUIStore from "@/hooks/store/useUIStore"; -import { LoadingStateKey } from "@/hooks/store/useWorldLoading"; import { FragmentMinePanel } from "@/ui/components/fragmentMines/FragmentMinePanel"; import { HintSection } from "@/ui/components/hints/HintModal"; import { DisplayedAccess, HyperstructurePanel } from "@/ui/components/hyperstructures/HyperstructurePanel"; @@ -20,37 +18,15 @@ import { HintModalButton } from "@/ui/elements/HintModalButton"; import { ResourceIcon } from "@/ui/elements/ResourceIcon"; import { currencyFormat, currencyIntlFormat, divideByPrecision } from "@/ui/utils/utils"; import { BattleSide, ContractAddress, ID, ResourcesIds, findResourceById } from "@bibliothecadao/eternum"; -import { Metadata } from "@dojoengine/recs"; -import { S } from "@dojoengine/recs/dist/types-3444e4c1"; -import { getEntities } from "@dojoengine/state"; -import { ToriiClient } from "@dojoengine/torii-wasm"; import { ArrowRight } from "lucide-react"; -import { Component, useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useMemo, useState } from "react"; import { Tabs } from "../../elements/tab"; export const WorldStructuresMenu = ({ className }: { className?: string }) => { const { account: { account }, - network: { toriiClient, contractComponents }, } = useDojo(); - const hyperstructuresLoaded = useUIStore((state) => state.loadingStates.hyperstructure); - const setLoading = useUIStore((state) => state.setLoading); - - useEffect(() => { - const fetchData = async () => { - try { - setLoading(LoadingStateKey.Hyperstructure, false), - await fetchHyperstructureData(toriiClient, contractComponents as any, hyperstructuresLoaded, () => - setLoading(LoadingStateKey.Hyperstructure, true), - ); - } catch (error) { - console.error("Failed to fetch hyperstructure data:", error); - } - }; - fetchData(); - }, [toriiClient, contractComponents]); - const [selectedTab, setSelectedTab] = useState(0); const [showOnlyMine, setShowOnlyMine] = useState(false); @@ -141,14 +117,6 @@ export const WorldStructuresMenu = ({ className }: { className?: string }) => { [selectedTab, hyperstructures, fragmentMines, showOnlyMine, account.address, myHyperstructures], ); - if (hyperstructuresLoaded) { - return ( -
-
Loading structures...
-
- ); - } - return ( <> @@ -341,47 +309,3 @@ const EntityHeader = ({ entity }: { entity: any }) => {
); }; - -const fetchHyperstructureData = async ( - client: ToriiClient, - components: Component[], - isStructuresLoading: boolean, - onCompleted?: () => void, -) => { - if (!isStructuresLoading) { - return; - } - - console.log("Fetching hyperstructure data"); - await getEntities( - client, - { - Composite: { - operator: "Or", - clauses: [ - { - Keys: { - keys: [undefined, undefined], - pattern_matching: "VariableLen", - models: ["s0_eternum-Contribution"], - }, - }, - { - Keys: { - keys: [undefined, undefined, undefined], - pattern_matching: "VariableLen", - models: ["s0_eternum-Epoch", "s0_eternum-Progress"], - }, - }, - ], - }, - }, - components as any, - [], - [], - 40_000, - false, - ).finally(() => { - onCompleted?.(); - }); -};