From 541ee6d08d76c8325c1d482b818b1fa51a79add9 Mon Sep 17 00:00:00 2001 From: ponderingdemocritus Date: Thu, 12 Dec 2024 10:31:09 +1100 Subject: [PATCH 01/10] loaf-opti --- client/.env.production | 4 +- client/src/dojo/queries.ts | 118 +++++++++++ client/src/dojo/setup.ts | 185 +++++++++++++++++- .../resources/EntityResourceTable.tsx | 12 +- .../navigation/LeftNavigationModule.tsx | 11 ++ .../navigation/RightNavigationModule.tsx | 2 + 6 files changed, 328 insertions(+), 4 deletions(-) create mode 100644 client/src/dojo/queries.ts diff --git a/client/.env.production b/client/.env.production index d5b551f1c..694ce0a1c 100644 --- a/client/.env.production +++ b/client/.env.production @@ -1,5 +1,5 @@ -VITE_PUBLIC_MASTER_ADDRESS= -VITE_PUBLIC_MASTER_PRIVATE_KEY= +VITE_PUBLIC_MASTER_ADDRESS=0x5013b17c43a2b664ec2a38aa45f6d891db1188622ec7cf320411321c3248fb5 +VITE_PUBLIC_MASTER_PRIVATE_KEY=0x5013b17c43a2b664ec2a38aa45f6d891db1188622ec7cf320411321c3248fb5 VITE_PUBLIC_WORLD_ADDRESS="0x5013b17c43a2b664ec2a38aa45f6d891db1188622ec7cf320411321c3248fb5" VITE_PUBLIC_ACCOUNT_CLASS_HASH="0x07dc7899aa655b0aae51eadff6d801a58e97dd99cf4666ee59e704249e51adf2" VITE_PUBLIC_FEE_TOKEN_ADDRESS=0x49d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7 diff --git a/client/src/dojo/queries.ts b/client/src/dojo/queries.ts new file mode 100644 index 000000000..e7aeff821 --- /dev/null +++ b/client/src/dojo/queries.ts @@ -0,0 +1,118 @@ +// onload -> fetch single key entities + +import { Component, Metadata, Schema } from "@dojoengine/recs"; +import { setEntities } from "@dojoengine/state"; +import { Clause, EntityKeysClause, Subscription, ToriiClient } from "@dojoengine/torii-client"; + +// on hexception -> fetch below queries based on entityID + +// background sync after load -> + +export const getEntities = async ( + client: ToriiClient, + clause: Clause | undefined, + components: Component[], + limit: number = 100, + logging: boolean = false +) => { + if (logging) console.log("Starting getEntities"); + let offset = 0; + let continueFetching = true; + + while (continueFetching) { + const entities = await client.getEntities({ + limit, + offset, + clause, + dont_include_hashed_keys: false, + }); + + console.log("entities", entities); + + if (logging) console.log(`Fetched ${entities} entities`); + + setEntities(entities, components, logging); + + if (Object.keys(entities).length < limit) { + continueFetching = false; + } else { + offset += limit; + } + } +}; + + + +export const syncEntitiesEternum = async ( + client: ToriiClient, + components: Component[], + entityKeyClause: EntityKeysClause[], + logging: boolean = true +) => { + if (logging) console.log("Starting syncEntities"); + return await client.onEntityUpdated( + entityKeyClause, + (fetchedEntities: any, data: any) => { + if (logging) console.log("Entity updated", fetchedEntities); + + setEntities({ [fetchedEntities]: data }, components, logging); + } + ); +}; + +export const addToSubscription = async (client: ToriiClient, subscription: Subscription, entityID: string) => { + + const entities = await getEntities(client, { + Composite: { + operator: 'Or', + clauses: [ + { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, + { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, + { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, + ] + } + }, [], 1000, false); + + console.log("entities", entities); + + await client.updateEntitySubscription(subscription, [ + { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, + { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, + { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, + ]); +} + +const entityQueryOneKey = (entityID: string) => { + return { + Keys: { + keys: [entityID], + pattern_matching: 'FixedLen', + models: [], + }, + } +} + +const entityQueryTwoKey = (entityID: string) => { + return { + Keys: { + keys: [entityID, undefined], + pattern_matching: 'FixedLen', + models: [ + ], + }, + } +} + +const entityQueryThreeKey = (entityID: string) => { + return { + Keys: { + keys: [entityID, undefined, undefined], + pattern_matching: 'FixedLen', + models: [ + ], + }, + } +} + + + diff --git a/client/src/dojo/setup.ts b/client/src/dojo/setup.ts index 2df39000c..fdb22c3e0 100644 --- a/client/src/dojo/setup.ts +++ b/client/src/dojo/setup.ts @@ -14,8 +14,191 @@ export async function setup({ ...config }: DojoConfig) { const components = createClientComponents(network); const systemCalls = createSystemCalls(network); + const singleKeyQuery = { + + Keys: { + keys: [undefined], + pattern_matching: 'FixedLen', + models: [ + "s0_eternum-AddressName", + "s0_eternum-Army", + "s0_eternum-ArrivalTime", + "s0_eternum-Bank", + "s0_eternum-BankConfig", + "s0_eternum-Battle", + "s0_eternum-BattleConfig", + "s0_eternum-Building", + "s0_eternum-BuildingCategoryPopConfig", + "s0_eternum-BuildingConfig", + "s0_eternum-BuildingGeneralConfig", + "s0_eternum-BuildingQuantityv2", + "s0_eternum-CapacityCategory", + "s0_eternum-CapacityConfig", + "s0_eternum-Contribution", + "s0_eternum-DetachedResource", + "s0_eternum-EntityName", + "s0_eternum-EntityOwner", + "s0_eternum-Epoch", + "s0_eternum-Guild", + "s0_eternum-GuildMember", + "s0_eternum-GuildWhitelist", + "s0_eternum-Health", + "s0_eternum-Hyperstructure", + "s0_eternum-HyperstructureConfig", + "s0_eternum-HyperstructureResourceConfig", + "s0_eternum-Leaderboard", + "s0_eternum-LeaderboardEntry", + "s0_eternum-LeaderboardRegistered", + "s0_eternum-LeaderboardRewardClaimed", + "s0_eternum-LevelingConfig", + "s0_eternum-Liquidity", + "s0_eternum-MapConfig", + + "s0_eternum-MercenariesConfig", + "s0_eternum-Message", + "s0_eternum-Movable", + "s0_eternum-Orders", + "s0_eternum-OwnedResourcesTracker", + "s0_eternum-Owner", + "s0_eternum-Population", + "s0_eternum-PopulationConfig", + "s0_eternum-Position", + "s0_eternum-ProductionConfig", + "s0_eternum-ProductionDeadline", + "s0_eternum-ProductionInput", + "s0_eternum-ProductionOutput", + + "s0_eternum-Protectee", + "s0_eternum-Protector", + "s0_eternum-Quantity", + "s0_eternum-QuantityTracker", + + "s0_eternum-QuestConfig", + "s0_eternum-QuestRewardConfig", + // "s0_eternum-Realm", + ], + }, + } + + const twoKeyQuery = { + Keys: { + keys: ['763', undefined], + pattern_matching: 'FixedLen', + models: [ + + // 's0_eternum-Tile', + // 's0_eternum-BuildingQuantityv2', + // // 's0_eternum-Resource', + // // 's0_eternum-Production', + // 's0_eternum-GuildWhitelist', + // 's0_eternum-Progress', + // 's0_eternum-HyperstructureContribution', + // 's0_eternum-Epoch', + // // 's0_eternum-QuestBonus', + // // "s0_eternum-Progress", + // // "s0_eternum-Market", + // 's0_eternum-Quest', + // 's0_eternum-Position', + + ], + }, + } + + const threeKeyQuery = { + Keys: { + keys: [undefined, undefined, undefined], + pattern_matching: 'FixedLen', + models: [ + 's0_eternum-BuildingConfig', + 's0_eternum-Liquidity' + ], + }, + } + + const fourKeyQuery = { + Keys: { + keys: [undefined, undefined, undefined, undefined], + pattern_matching: 'FixedLen', + models: ['s0_eternum-Building'], + }, + } + // fetch all existing entities from torii - const sync = await getSyncEntities(network.toriiClient, network.contractComponents as any, undefined, [], 10_000); + const sync = await getSyncEntities(network.toriiClient, network.contractComponents as any, + { + Composite: { + operator: 'Or', + clauses: [ + { + Keys: { + keys: [undefined], + pattern_matching: 'FixedLen', + models: [ + // "s0_eternum-AddressName", + // "s0_eternum-Army", + // "s0_eternum-ArrivalTime", + // "s0_eternum-Bank", + // "s0_eternum-BankConfig", + // "s0_eternum-Battle", + // "s0_eternum-BattleConfig", + // "s0_eternum-Building", + // "s0_eternum-BuildingCategoryPopConfig", + // "s0_eternum-BuildingConfig", + // "s0_eternum-BuildingGeneralConfig", + // "s0_eternum-BuildingQuantityv2", + // "s0_eternum-CapacityCategory", + // "s0_eternum-CapacityConfig", + // "s0_eternum-Contribution", + // "s0_eternum-DetachedResource", + // "s0_eternum-EntityName", + // "s0_eternum-EntityOwner", + // "s0_eternum-Epoch", + // "s0_eternum-Guild", + // "s0_eternum-GuildMember", + // "s0_eternum-GuildWhitelist", + // "s0_eternum-Health", + // "s0_eternum-Hyperstructure", + // "s0_eternum-HyperstructureConfig", + // "s0_eternum-HyperstructureResourceConfig", + // "s0_eternum-Leaderboard", + // "s0_eternum-LeaderboardEntry", + // "s0_eternum-LeaderboardRegistered", + // "s0_eternum-LeaderboardRewardClaimed", + // "s0_eternum-LevelingConfig", + // "s0_eternum-Liquidity", + // "s0_eternum-MapConfig", + + // "s0_eternum-MercenariesConfig", + // "s0_eternum-Message", + // "s0_eternum-Movable", + // "s0_eternum-Orders", + // "s0_eternum-OwnedResourcesTracker", + // "s0_eternum-Owner", + // "s0_eternum-Population", + // "s0_eternum-PopulationConfig", + // "s0_eternum-Position", + // "s0_eternum-ProductionConfig", + // "s0_eternum-ProductionDeadline", + // "s0_eternum-ProductionInput", + // "s0_eternum-ProductionOutput", + + // "s0_eternum-Protectee", + // "s0_eternum-Protector", + // "s0_eternum-Quantity", + // "s0_eternum-QuantityTracker", + + // "s0_eternum-QuestConfig", + // "s0_eternum-QuestRewardConfig", + // "s0_eternum-Realm", + ], + }, + }, + ], + }, + }, + + [], 100); + const eventSync = getSyncEvents( network.toriiClient, network.contractComponents.events as any, diff --git a/client/src/ui/components/resources/EntityResourceTable.tsx b/client/src/ui/components/resources/EntityResourceTable.tsx index 37a04668b..bd79b5ddd 100644 --- a/client/src/ui/components/resources/EntityResourceTable.tsx +++ b/client/src/ui/components/resources/EntityResourceTable.tsx @@ -1,10 +1,11 @@ +import { addToSubscription } from "@/dojo/queries"; import { configManager } from "@/dojo/setup"; import { useDojo } from "@/hooks/context/DojoContext"; import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp"; import { getEntityIdFromKeys, gramToKg, multiplyByPrecision } from "@/ui/utils/utils"; import { BuildingType, CapacityConfigCategory, ID, RESOURCE_TIERS } from "@bibliothecadao/eternum"; import { useComponentValue } from "@dojoengine/react"; -import { useMemo } from "react"; +import { useEffect, useMemo } from "react"; import { ResourceChip } from "./ResourceChip"; export const EntityResourceTable = ({ entityId }: { entityId: ID | undefined }) => { @@ -23,6 +24,15 @@ export const EntityResourceTable = ({ entityId }: { entityId: ID | undefined }) return multiplyByPrecision(quantity * storehouseCapacityKg + storehouseCapacityKg); }, [quantity, entityId]); + + useEffect(() => { + + const fetch = async () => { + await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, entityId?.toString() || "0"); + } + fetch(); + }, [entityId]); + if (!entityId || entityId === 0) { return
No Entity Selected
; } diff --git a/client/src/ui/modules/navigation/LeftNavigationModule.tsx b/client/src/ui/modules/navigation/LeftNavigationModule.tsx index d5dcee341..6e4723e8e 100644 --- a/client/src/ui/modules/navigation/LeftNavigationModule.tsx +++ b/client/src/ui/modules/navigation/LeftNavigationModule.tsx @@ -1,3 +1,5 @@ +import { addToSubscription } from "@/dojo/queries"; +import { useDojo } from "@/hooks/context/DojoContext"; import { usePlayerArrivalsNotifications } from "@/hooks/helpers/use-resource-arrivals"; import { useEntitiesUtils } from "@/hooks/helpers/useEntities"; import { useQuery } from "@/hooks/helpers/useQuery"; @@ -218,6 +220,15 @@ export const LeftNavigationModule = memo(() => { visible: { x: "0%", transition: { duration: 0.5 } }, }; + const dojo = useDojo(); + useEffect(() => { + + const fetch = async () => { + await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, structureEntityId.toString()); + } + fetch(); + }, [structureEntityId]); + return (
diff --git a/client/src/ui/modules/navigation/RightNavigationModule.tsx b/client/src/ui/modules/navigation/RightNavigationModule.tsx index 6998d3403..4532fe384 100644 --- a/client/src/ui/modules/navigation/RightNavigationModule.tsx +++ b/client/src/ui/modules/navigation/RightNavigationModule.tsx @@ -21,6 +21,8 @@ export const RightNavigationModule = () => { const view = useUIStore((state) => state.rightNavigationView); const setView = useUIStore((state) => state.setRightNavigationView); + + const navigation = useMemo( () => [ { From 71d8df73881edf2c6e19469c44416be98953c59c Mon Sep 17 00:00:00 2001 From: ponderingdemocritus Date: Thu, 12 Dec 2024 11:08:30 +1100 Subject: [PATCH 02/10] buildings --- client/src/dojo/queries.ts | 59 ++++++++++++++----- .../resources/EntityResourceTable.tsx | 11 +--- .../navigation/LeftNavigationModule.tsx | 9 ++- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/client/src/dojo/queries.ts b/client/src/dojo/queries.ts index e7aeff821..c460c3b85 100644 --- a/client/src/dojo/queries.ts +++ b/client/src/dojo/queries.ts @@ -60,26 +60,45 @@ export const syncEntitiesEternum = async ( ); }; -export const addToSubscription = async (client: ToriiClient, subscription: Subscription, entityID: string) => { - - const entities = await getEntities(client, { - Composite: { - operator: 'Or', - clauses: [ - { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, - { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, - { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, - ] - } - }, [], 1000, false); - - console.log("entities", entities); +export const addToSubscription = async (client: ToriiClient, subscription: Subscription, components: Component[], entityID: string, position?: {x: number, y: number}) => { + + await getEntities(client, { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, components, 1000, false); + + await getEntities(client, { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, components, 1000, false); + + await getEntities(client, { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, components, 1000, false); + + await getEntities(client, { + Keys: { + keys: [String(position?.x || 0), String(position?.y || 0), undefined, undefined], + pattern_matching: 'FixedLen', + models: [ + ], + }, + }, components, 1000, false); await client.updateEntitySubscription(subscription, [ { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, + ]); + + await client.updateEntitySubscription(subscription, [ { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, + ]); + + await client.updateEntitySubscription(subscription, [ { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, ]); + + await client.updateEntitySubscription(subscription, [ + { + Keys: { + keys: [String(position?.x || 0), String(position?.y || 0), undefined, undefined], + pattern_matching: 'FixedLen', + models: [ + ], + }, + }, + ]); } const entityQueryOneKey = (entityID: string) => { @@ -114,5 +133,17 @@ const entityQueryThreeKey = (entityID: string) => { } } +const entityQueryFourKey = ( x: number, y: number) => { + return { + Keys: { + keys: [String(x), String(y), undefined, undefined], + pattern_matching: 'FixedLen', + models: [ + ], + }, + } +} + + diff --git a/client/src/ui/components/resources/EntityResourceTable.tsx b/client/src/ui/components/resources/EntityResourceTable.tsx index bd79b5ddd..4a713a625 100644 --- a/client/src/ui/components/resources/EntityResourceTable.tsx +++ b/client/src/ui/components/resources/EntityResourceTable.tsx @@ -1,11 +1,10 @@ -import { addToSubscription } from "@/dojo/queries"; import { configManager } from "@/dojo/setup"; import { useDojo } from "@/hooks/context/DojoContext"; import useNextBlockTimestamp from "@/hooks/useNextBlockTimestamp"; import { getEntityIdFromKeys, gramToKg, multiplyByPrecision } from "@/ui/utils/utils"; import { BuildingType, CapacityConfigCategory, ID, RESOURCE_TIERS } from "@bibliothecadao/eternum"; import { useComponentValue } from "@dojoengine/react"; -import { useEffect, useMemo } from "react"; +import { useMemo } from "react"; import { ResourceChip } from "./ResourceChip"; export const EntityResourceTable = ({ entityId }: { entityId: ID | undefined }) => { @@ -25,14 +24,6 @@ export const EntityResourceTable = ({ entityId }: { entityId: ID | undefined }) }, [quantity, entityId]); - useEffect(() => { - - const fetch = async () => { - await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, entityId?.toString() || "0"); - } - fetch(); - }, [entityId]); - if (!entityId || entityId === 0) { return
No Entity Selected
; } diff --git a/client/src/ui/modules/navigation/LeftNavigationModule.tsx b/client/src/ui/modules/navigation/LeftNavigationModule.tsx index 6e4723e8e..16e23d1c6 100644 --- a/client/src/ui/modules/navigation/LeftNavigationModule.tsx +++ b/client/src/ui/modules/navigation/LeftNavigationModule.tsx @@ -10,6 +10,8 @@ import { MarketModal } from "@/ui/components/trading/MarketModal"; import { BuildingThumbs, IS_MOBILE, MenuEnum } from "@/ui/config"; import { BaseContainer } from "@/ui/containers/BaseContainer"; import { KeyBoardKey } from "@/ui/elements/KeyBoardKey"; +import { useComponentValue } from "@dojoengine/react"; +import { getEntityIdFromKeys } from "@dojoengine/utils"; import { motion } from "framer-motion"; import { Suspense, lazy, memo, useEffect, useMemo } from "react"; import { construction, military, trade, worldStructures } from "../../components/navigation/Config"; @@ -220,11 +222,16 @@ export const LeftNavigationModule = memo(() => { visible: { x: "0%", transition: { duration: 0.5 } }, }; + + const dojo = useDojo(); + + const position = useComponentValue(dojo.setup.components.Position, getEntityIdFromKeys([BigInt(structureEntityId)])) + useEffect(() => { const fetch = async () => { - await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, structureEntityId.toString()); + await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, dojo.setup.network.contractComponents as any, structureEntityId.toString(), {x: position?.x || 0, y: position?.y || 0}); } fetch(); }, [structureEntityId]); From 0734b99dc2b75a57394095fc30b03d26d823f76d Mon Sep 17 00:00:00 2001 From: ponderingdemocritus Date: Thu, 12 Dec 2024 11:27:17 +1100 Subject: [PATCH 03/10] load --- client/src/dojo/queries.ts | 3 + client/src/dojo/setup.ts | 61 +------------------ client/src/ui/layouts/World.tsx | 20 +++++- .../navigation/LeftNavigationModule.tsx | 14 ----- 4 files changed, 24 insertions(+), 74 deletions(-) diff --git a/client/src/dojo/queries.ts b/client/src/dojo/queries.ts index c460c3b85..a6cce649d 100644 --- a/client/src/dojo/queries.ts +++ b/client/src/dojo/queries.ts @@ -62,11 +62,14 @@ export const syncEntitiesEternum = async ( export const addToSubscription = async (client: ToriiClient, subscription: Subscription, components: Component[], entityID: string, position?: {x: number, y: number}) => { + console.log("position", subscription); + await getEntities(client, { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, components, 1000, false); await getEntities(client, { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, components, 1000, false); await getEntities(client, { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, components, 1000, false); + await getEntities(client, { Keys: { diff --git a/client/src/dojo/setup.ts b/client/src/dojo/setup.ts index fdb22c3e0..9b0de9de2 100644 --- a/client/src/dojo/setup.ts +++ b/client/src/dojo/setup.ts @@ -133,71 +133,14 @@ export async function setup({ ...config }: DojoConfig) { Keys: { keys: [undefined], pattern_matching: 'FixedLen', - models: [ - // "s0_eternum-AddressName", - // "s0_eternum-Army", - // "s0_eternum-ArrivalTime", - // "s0_eternum-Bank", - // "s0_eternum-BankConfig", - // "s0_eternum-Battle", - // "s0_eternum-BattleConfig", - // "s0_eternum-Building", - // "s0_eternum-BuildingCategoryPopConfig", - // "s0_eternum-BuildingConfig", - // "s0_eternum-BuildingGeneralConfig", - // "s0_eternum-BuildingQuantityv2", - // "s0_eternum-CapacityCategory", - // "s0_eternum-CapacityConfig", - // "s0_eternum-Contribution", - // "s0_eternum-DetachedResource", - // "s0_eternum-EntityName", - // "s0_eternum-EntityOwner", - // "s0_eternum-Epoch", - // "s0_eternum-Guild", - // "s0_eternum-GuildMember", - // "s0_eternum-GuildWhitelist", - // "s0_eternum-Health", - // "s0_eternum-Hyperstructure", - // "s0_eternum-HyperstructureConfig", - // "s0_eternum-HyperstructureResourceConfig", - // "s0_eternum-Leaderboard", - // "s0_eternum-LeaderboardEntry", - // "s0_eternum-LeaderboardRegistered", - // "s0_eternum-LeaderboardRewardClaimed", - // "s0_eternum-LevelingConfig", - // "s0_eternum-Liquidity", - // "s0_eternum-MapConfig", - - // "s0_eternum-MercenariesConfig", - // "s0_eternum-Message", - // "s0_eternum-Movable", - // "s0_eternum-Orders", - // "s0_eternum-OwnedResourcesTracker", - // "s0_eternum-Owner", - // "s0_eternum-Population", - // "s0_eternum-PopulationConfig", - // "s0_eternum-Position", - // "s0_eternum-ProductionConfig", - // "s0_eternum-ProductionDeadline", - // "s0_eternum-ProductionInput", - // "s0_eternum-ProductionOutput", - - // "s0_eternum-Protectee", - // "s0_eternum-Protector", - // "s0_eternum-Quantity", - // "s0_eternum-QuantityTracker", - - // "s0_eternum-QuestConfig", - // "s0_eternum-QuestRewardConfig", - // "s0_eternum-Realm", - ], + models: [], }, }, ], }, }, - [], 100); + [], 1000); const eventSync = getSyncEvents( network.toriiClient, diff --git a/client/src/ui/layouts/World.tsx b/client/src/ui/layouts/World.tsx index 5b5bc256c..1982ccc62 100644 --- a/client/src/ui/layouts/World.tsx +++ b/client/src/ui/layouts/World.tsx @@ -1,10 +1,14 @@ import { Leva } from "leva"; -import { lazy, Suspense } from "react"; +import { lazy, Suspense, useEffect } from "react"; import { Redirect } from "wouter"; import useUIStore from "../../hooks/store/useUIStore"; +import { addToSubscription } from "@/dojo/queries"; +import { useDojo } from "@/hooks/context/DojoContext"; import { useStructureEntityId } from "@/hooks/helpers/useStructureEntityId"; import { useFetchBlockchainData } from "@/hooks/store/useBlockchainStore"; +import { useComponentValue } from "@dojoengine/react"; +import { getEntityIdFromKeys } from "@dojoengine/utils"; import { env } from "../../../env"; import { IS_MOBILE } from "../config"; import { LoadingScreen } from "../modules/LoadingScreen"; @@ -91,6 +95,20 @@ export const World = ({ backgroundImage }: { backgroundImage: string }) => { useFetchBlockchainData(); useStructureEntityId(); + const dojo = useDojo(); + + const structureEntityId = useUIStore((state) => state.structureEntityId); + + const position = useComponentValue(dojo.setup.components.Position, getEntityIdFromKeys([BigInt(structureEntityId)])) + + useEffect(() => { + + const fetch = async () => { + await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, dojo.setup.network.contractComponents as any, structureEntityId.toString(), {x: position?.x || 0, y: position?.y || 0}); + } + fetch(); + }, [structureEntityId]); + return (
{ diff --git a/client/src/ui/modules/navigation/LeftNavigationModule.tsx b/client/src/ui/modules/navigation/LeftNavigationModule.tsx index 16e23d1c6..47afe4ba2 100644 --- a/client/src/ui/modules/navigation/LeftNavigationModule.tsx +++ b/client/src/ui/modules/navigation/LeftNavigationModule.tsx @@ -1,5 +1,3 @@ -import { addToSubscription } from "@/dojo/queries"; -import { useDojo } from "@/hooks/context/DojoContext"; import { usePlayerArrivalsNotifications } from "@/hooks/helpers/use-resource-arrivals"; import { useEntitiesUtils } from "@/hooks/helpers/useEntities"; import { useQuery } from "@/hooks/helpers/useQuery"; @@ -10,8 +8,6 @@ import { MarketModal } from "@/ui/components/trading/MarketModal"; import { BuildingThumbs, IS_MOBILE, MenuEnum } from "@/ui/config"; import { BaseContainer } from "@/ui/containers/BaseContainer"; import { KeyBoardKey } from "@/ui/elements/KeyBoardKey"; -import { useComponentValue } from "@dojoengine/react"; -import { getEntityIdFromKeys } from "@dojoengine/utils"; import { motion } from "framer-motion"; import { Suspense, lazy, memo, useEffect, useMemo } from "react"; import { construction, military, trade, worldStructures } from "../../components/navigation/Config"; @@ -224,17 +220,7 @@ export const LeftNavigationModule = memo(() => { - const dojo = useDojo(); - const position = useComponentValue(dojo.setup.components.Position, getEntityIdFromKeys([BigInt(structureEntityId)])) - - useEffect(() => { - - const fetch = async () => { - await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, dojo.setup.network.contractComponents as any, structureEntityId.toString(), {x: position?.x || 0, y: position?.y || 0}); - } - fetch(); - }, [structureEntityId]); return (
From c206709262a893ef29bd5f924ff4eaf8e610055c Mon Sep 17 00:00:00 2001 From: tedison Date: Wed, 11 Dec 2024 19:28:29 -0500 Subject: [PATCH 04/10] push config --- client/src/dojo/setup.ts | 201 +++++++++++++++++++++------------------ 1 file changed, 107 insertions(+), 94 deletions(-) diff --git a/client/src/dojo/setup.ts b/client/src/dojo/setup.ts index 9b0de9de2..f6bd73547 100644 --- a/client/src/dojo/setup.ts +++ b/client/src/dojo/setup.ts @@ -1,3 +1,4 @@ +import { WORLD_CONFIG_ID } from "@bibliothecadao/eternum"; import { DojoConfig } from "@dojoengine/core"; import { getSyncEntities, getSyncEvents } from "@dojoengine/state"; import { createClientComponents } from "./createClientComponents"; @@ -15,77 +16,75 @@ export async function setup({ ...config }: DojoConfig) { const systemCalls = createSystemCalls(network); const singleKeyQuery = { - - Keys: { - keys: [undefined], - pattern_matching: 'FixedLen', - models: [ - "s0_eternum-AddressName", - "s0_eternum-Army", - "s0_eternum-ArrivalTime", - "s0_eternum-Bank", - "s0_eternum-BankConfig", - "s0_eternum-Battle", - "s0_eternum-BattleConfig", - "s0_eternum-Building", - "s0_eternum-BuildingCategoryPopConfig", - "s0_eternum-BuildingConfig", - "s0_eternum-BuildingGeneralConfig", - "s0_eternum-BuildingQuantityv2", - "s0_eternum-CapacityCategory", - "s0_eternum-CapacityConfig", - "s0_eternum-Contribution", - "s0_eternum-DetachedResource", - "s0_eternum-EntityName", - "s0_eternum-EntityOwner", - "s0_eternum-Epoch", - "s0_eternum-Guild", - "s0_eternum-GuildMember", - "s0_eternum-GuildWhitelist", - "s0_eternum-Health", - "s0_eternum-Hyperstructure", - "s0_eternum-HyperstructureConfig", - "s0_eternum-HyperstructureResourceConfig", - "s0_eternum-Leaderboard", - "s0_eternum-LeaderboardEntry", - "s0_eternum-LeaderboardRegistered", - "s0_eternum-LeaderboardRewardClaimed", - "s0_eternum-LevelingConfig", - "s0_eternum-Liquidity", - "s0_eternum-MapConfig", - - "s0_eternum-MercenariesConfig", - "s0_eternum-Message", - "s0_eternum-Movable", - "s0_eternum-Orders", - "s0_eternum-OwnedResourcesTracker", - "s0_eternum-Owner", - "s0_eternum-Population", - "s0_eternum-PopulationConfig", - "s0_eternum-Position", - "s0_eternum-ProductionConfig", - "s0_eternum-ProductionDeadline", - "s0_eternum-ProductionInput", - "s0_eternum-ProductionOutput", - - "s0_eternum-Protectee", - "s0_eternum-Protector", - "s0_eternum-Quantity", - "s0_eternum-QuantityTracker", - - "s0_eternum-QuestConfig", - "s0_eternum-QuestRewardConfig", - // "s0_eternum-Realm", - ], - }, - } + Keys: { + keys: [undefined], + pattern_matching: "FixedLen", + models: [ + "s0_eternum-AddressName", + "s0_eternum-Army", + "s0_eternum-ArrivalTime", + "s0_eternum-Bank", + "s0_eternum-BankConfig", + "s0_eternum-Battle", + "s0_eternum-BattleConfig", + "s0_eternum-Building", + "s0_eternum-BuildingCategoryPopConfig", + "s0_eternum-BuildingConfig", + "s0_eternum-BuildingGeneralConfig", + "s0_eternum-BuildingQuantityv2", + "s0_eternum-CapacityCategory", + "s0_eternum-CapacityConfig", + "s0_eternum-Contribution", + "s0_eternum-DetachedResource", + "s0_eternum-EntityName", + "s0_eternum-EntityOwner", + "s0_eternum-Epoch", + "s0_eternum-Guild", + "s0_eternum-GuildMember", + "s0_eternum-GuildWhitelist", + "s0_eternum-Health", + "s0_eternum-Hyperstructure", + "s0_eternum-HyperstructureConfig", + "s0_eternum-HyperstructureResourceConfig", + "s0_eternum-Leaderboard", + "s0_eternum-LeaderboardEntry", + "s0_eternum-LeaderboardRegistered", + "s0_eternum-LeaderboardRewardClaimed", + "s0_eternum-LevelingConfig", + "s0_eternum-Liquidity", + "s0_eternum-MapConfig", + + "s0_eternum-MercenariesConfig", + "s0_eternum-Message", + "s0_eternum-Movable", + "s0_eternum-Orders", + "s0_eternum-OwnedResourcesTracker", + "s0_eternum-Owner", + "s0_eternum-Population", + "s0_eternum-PopulationConfig", + "s0_eternum-Position", + "s0_eternum-ProductionConfig", + "s0_eternum-ProductionDeadline", + "s0_eternum-ProductionInput", + "s0_eternum-ProductionOutput", + + "s0_eternum-Protectee", + "s0_eternum-Protector", + "s0_eternum-Quantity", + "s0_eternum-QuantityTracker", + + "s0_eternum-QuestConfig", + "s0_eternum-QuestRewardConfig", + // "s0_eternum-Realm", + ], + }, + }; const twoKeyQuery = { Keys: { - keys: ['763', undefined], - pattern_matching: 'FixedLen', + keys: ["763", undefined], + pattern_matching: "FixedLen", models: [ - // 's0_eternum-Tile', // 's0_eternum-BuildingQuantityv2', // // 's0_eternum-Resource', @@ -99,49 +98,63 @@ export async function setup({ ...config }: DojoConfig) { // // "s0_eternum-Market", // 's0_eternum-Quest', // 's0_eternum-Position', - ], }, - } + }; const threeKeyQuery = { Keys: { keys: [undefined, undefined, undefined], - pattern_matching: 'FixedLen', - models: [ - 's0_eternum-BuildingConfig', - 's0_eternum-Liquidity' - ], + pattern_matching: "FixedLen", + models: ["s0_eternum-BuildingConfig", "s0_eternum-Liquidity"], }, - } + }; const fourKeyQuery = { Keys: { keys: [undefined, undefined, undefined, undefined], - pattern_matching: 'FixedLen', - models: ['s0_eternum-Building'], + pattern_matching: "FixedLen", + models: ["s0_eternum-Building"], }, - } + }; // fetch all existing entities from torii - const sync = await getSyncEntities(network.toriiClient, network.contractComponents as any, - { - Composite: { - operator: 'Or', - clauses: [ - { - Keys: { - keys: [undefined], - pattern_matching: 'FixedLen', - models: [], + const sync = await getSyncEntities( + network.toriiClient, + network.contractComponents as any, + { + Composite: { + operator: "Or", + clauses: [ + { + Keys: { + keys: [undefined], + pattern_matching: "FixedLen", + models: [], + }, }, - }, - ], + { + Keys: { + keys: [WORLD_CONFIG_ID.toString(), undefined], + pattern_matching: "VariableLen", + models: [], + }, + }, + { + Keys: { + keys: [WORLD_CONFIG_ID.toString()], + pattern_matching: "VariableLen", + models: [], + }, + }, + ], + }, }, - }, - - [], 1000); - + + [], + 1000, + ); + const eventSync = getSyncEvents( network.toriiClient, network.contractComponents.events as any, From 21668404c101872db739ebcdad46c21fa10acd90 Mon Sep 17 00:00:00 2001 From: ponderingdemocritus Date: Thu, 12 Dec 2024 11:31:43 +1100 Subject: [PATCH 05/10] loading --- client/src/hooks/store/useWorldLoading.tsx | 12 ++++++++++++ client/src/ui/layouts/World.tsx | 12 ++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 client/src/hooks/store/useWorldLoading.tsx diff --git a/client/src/hooks/store/useWorldLoading.tsx b/client/src/hooks/store/useWorldLoading.tsx new file mode 100644 index 000000000..52c654754 --- /dev/null +++ b/client/src/hooks/store/useWorldLoading.tsx @@ -0,0 +1,12 @@ +// World loading state +import { create } from "zustand"; + +interface WorldState { + isWorldLoading: boolean; + setWorldLoading: (loading: boolean) => void; +} + +export const useWorldStore = create((set) => ({ + isWorldLoading: true, + setWorldLoading: (loading: boolean) => set({ isWorldLoading: loading }), +})); \ No newline at end of file diff --git a/client/src/ui/layouts/World.tsx b/client/src/ui/layouts/World.tsx index 1982ccc62..1d14a6f83 100644 --- a/client/src/ui/layouts/World.tsx +++ b/client/src/ui/layouts/World.tsx @@ -7,6 +7,7 @@ import { addToSubscription } from "@/dojo/queries"; import { useDojo } from "@/hooks/context/DojoContext"; import { useStructureEntityId } from "@/hooks/helpers/useStructureEntityId"; import { useFetchBlockchainData } from "@/hooks/store/useBlockchainStore"; +import { useWorldStore } from "@/hooks/store/useWorldLoading"; import { useComponentValue } from "@dojoengine/react"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { env } from "../../../env"; @@ -82,6 +83,8 @@ const MiniMapNavigation = lazy(() => import("../modules/navigation/MiniMapNavigation").then((module) => ({ default: module.MiniMapNavigation })), ); + + export const World = ({ backgroundImage }: { backgroundImage: string }) => { const showBlankOverlay = useUIStore((state) => state.showBlankOverlay); const isLoadingScreenEnabled = useUIStore((state) => state.isLoadingScreenEnabled); @@ -95,18 +98,23 @@ export const World = ({ backgroundImage }: { backgroundImage: string }) => { useFetchBlockchainData(); useStructureEntityId(); - const dojo = useDojo(); + // We could optimise this deeper.... - const structureEntityId = useUIStore((state) => state.structureEntityId); + const worldLoading = useWorldStore((state) => state.isWorldLoading); + const setWorldLoading = useWorldStore((state) => state.setWorldLoading); + const dojo = useDojo(); + const structureEntityId = useUIStore((state) => state.structureEntityId); const position = useComponentValue(dojo.setup.components.Position, getEntityIdFromKeys([BigInt(structureEntityId)])) useEffect(() => { + setWorldLoading(true); const fetch = async () => { await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, dojo.setup.network.contractComponents as any, structureEntityId.toString(), {x: position?.x || 0, y: position?.y || 0}); } fetch(); + setWorldLoading(false); }, [structureEntityId]); return ( From d4b03f2f5414f1910fd6a931937677a7cb5d21ec Mon Sep 17 00:00:00 2001 From: ponderingdemocritus Date: Thu, 12 Dec 2024 12:59:00 +1100 Subject: [PATCH 06/10] tiles --- client/src/dojo/queries.ts | 49 ++++++++++++++----------- client/src/dojo/setup.ts | 1 + client/src/three/scenes/HexagonScene.ts | 2 + client/src/three/scenes/Worldmap.ts | 41 +++++++++++++++++++-- client/src/ui/layouts/World.tsx | 5 ++- 5 files changed, 71 insertions(+), 27 deletions(-) diff --git a/client/src/dojo/queries.ts b/client/src/dojo/queries.ts index a6cce649d..ae132c035 100644 --- a/client/src/dojo/queries.ts +++ b/client/src/dojo/queries.ts @@ -80,28 +80,35 @@ export const addToSubscription = async (client: ToriiClient, s }, }, components, 1000, false); - await client.updateEntitySubscription(subscription, [ - { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, - ]); - - await client.updateEntitySubscription(subscription, [ - { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, - ]); - - await client.updateEntitySubscription(subscription, [ - { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, - ]); - - await client.updateEntitySubscription(subscription, [ - { - Keys: { - keys: [String(position?.x || 0), String(position?.y || 0), undefined, undefined], - pattern_matching: 'FixedLen', - models: [ - ], + // await client.updateEntitySubscription(subscription, [ + // { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, + // ]); + + // await client.updateEntitySubscription(subscription, [ + // { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, + // ]); + + // await client.updateEntitySubscription(subscription, [ + // { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, + // ]); + + try { + await client.updateEntitySubscription(subscription, [ + { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, + { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, + { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, + { + Keys: { + keys: [String(position?.x || 0), String(position?.y || 0), undefined, undefined], + pattern_matching: 'FixedLen', + models: [ + ], + }, }, - }, - ]); + ]); + } catch (error) { + console.error("Error updating entity subscription:", error); + } } const entityQueryOneKey = (entityID: string) => { diff --git a/client/src/dojo/setup.ts b/client/src/dojo/setup.ts index f6bd73547..0a7156289 100644 --- a/client/src/dojo/setup.ts +++ b/client/src/dojo/setup.ts @@ -122,6 +122,7 @@ export async function setup({ ...config }: DojoConfig) { const sync = await getSyncEntities( network.toriiClient, network.contractComponents as any, + { Composite: { operator: "Or", diff --git a/client/src/three/scenes/HexagonScene.ts b/client/src/three/scenes/HexagonScene.ts index a7529871e..ce6c45bc6 100644 --- a/client/src/three/scenes/HexagonScene.ts +++ b/client/src/three/scenes/HexagonScene.ts @@ -258,6 +258,8 @@ export abstract class HexagonScene { const { row, col } = this.getHexFromWorldPosition(position); + console.log("row", row, col); + return { row, col, x: position.x, z: position.z }; } diff --git a/client/src/three/scenes/Worldmap.ts b/client/src/three/scenes/Worldmap.ts index b1718bfbc..5b5cd5c12 100644 --- a/client/src/three/scenes/Worldmap.ts +++ b/client/src/three/scenes/Worldmap.ts @@ -1,6 +1,3 @@ -import * as THREE from "three"; -import { Raycaster } from "three"; - import { ArmyMovementManager, TravelPaths } from "@/dojo/modelManager/ArmyMovementManager"; import { TileManager } from "@/dojo/modelManager/TileManager"; import { SetupResult } from "@/dojo/setup"; @@ -13,7 +10,11 @@ import { UNDEFINED_STRUCTURE_ENTITY_ID } from "@/ui/constants"; import { LeftView } from "@/ui/modules/navigation/LeftNavigationModule"; import { getWorldPositionForHex } from "@/ui/utils/utils"; import { BiomeType, getNeighborOffsets, ID } from "@bibliothecadao/eternum"; +import { getSyncEntities } from "@dojoengine/state"; +import * as torii from "@dojoengine/torii-client"; import throttle from "lodash/throttle"; +import * as THREE from "three"; +import { Raycaster } from "three"; import { MapControls } from "three/examples/jsm/controls/MapControls"; import { SceneManager } from "../SceneManager"; import { ArmyManager } from "../components/ArmyManager"; @@ -41,6 +42,8 @@ export default class WorldmapScene extends HexagonScene { private currentChunk: string = "null"; + private subscription: torii.Subscription | null = null; + private armyManager: ArmyManager; private structureManager: StructureManager; private battleManager: BattleManager; @@ -56,6 +59,8 @@ export default class WorldmapScene extends HexagonScene { private cachedMatrices: Map> = new Map(); + dojo: SetupResult; + constructor( dojoContext: SetupResult, raycaster: Raycaster, @@ -65,6 +70,8 @@ export default class WorldmapScene extends HexagonScene { ) { super(SceneName.WorldMap, controls, dojoContext, mouse, raycaster, sceneManager); + this.dojo = dojoContext; + this.GUIFolder.add(this, "moveCameraToURLLocation"); this.biome = new Biome(); @@ -503,6 +510,8 @@ export default class WorldmapScene extends HexagonScene { const globalRow = startRow + row; const globalCol = startCol + col; + + const isExplored = this.exploredTiles.get(globalCol)?.has(globalRow) || false; if (!isExplored) { @@ -565,9 +574,13 @@ export default class WorldmapScene extends HexagonScene { const hexPositions: THREE.Vector3[] = []; const batchSize = 25; // Adjust batch size as needed let currentIndex = 0; + let hashedTiles: string[] = []; - const processBatch = () => { + const processBatch = async () => { const endIndex = Math.min(currentIndex + batchSize, rows * cols); + + + for (let i = currentIndex; i < endIndex; i++) { const row = Math.floor(i / cols) - rows / 2; const col = (i % cols) - cols / 2; @@ -575,6 +588,10 @@ export default class WorldmapScene extends HexagonScene { const globalRow = startRow + row; const globalCol = startCol + col; + const hashedTile = torii.poseidonHash([(startCol + col + FELT_CENTER).toString(), (startRow + row + FELT_CENTER).toString()]); + + hashedTiles.push(hashedTile); + hexPositions.push(new THREE.Vector3(dummy.position.x, dummy.position.y, dummy.position.z)); const pos = getWorldPositionForHex({ row: globalRow, col: globalCol }); dummy.position.copy(pos); @@ -622,6 +639,7 @@ export default class WorldmapScene extends HexagonScene { } } + currentIndex = endIndex; if (currentIndex < rows * cols) { requestAnimationFrame(processBatch); @@ -640,9 +658,24 @@ export default class WorldmapScene extends HexagonScene { Promise.all(this.modelLoadPromises).then(() => { requestAnimationFrame(processBatch); + this.computeTileEntities(hashedTiles); }); } + private async computeTileEntities(hashedTiles: string[]) { + if (this.subscription) this.subscription.cancel(); + + const sub = await getSyncEntities(this.dojo.network.toriiClient, this.dojo.network.contractComponents as any, undefined, [ + { + HashedKeys: hashedTiles + }, + ]); + + console.log("entities", sub); + this.subscription = sub; + } + + private getExploredHexesForCurrentChunk() { const chunkKey = this.currentChunk.split(","); const startRow = parseInt(chunkKey[0]); diff --git a/client/src/ui/layouts/World.tsx b/client/src/ui/layouts/World.tsx index 1d14a6f83..8bfbee1c9 100644 --- a/client/src/ui/layouts/World.tsx +++ b/client/src/ui/layouts/World.tsx @@ -108,12 +108,13 @@ export const World = ({ backgroundImage }: { backgroundImage: string }) => { const position = useComponentValue(dojo.setup.components.Position, getEntityIdFromKeys([BigInt(structureEntityId)])) useEffect(() => { - - setWorldLoading(true); const fetch = async () => { await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, dojo.setup.network.contractComponents as any, structureEntityId.toString(), {x: position?.x || 0, y: position?.y || 0}); } + setWorldLoading(true); + console.log("world loading", worldLoading); fetch(); + console.log("world loading", worldLoading); setWorldLoading(false); }, [structureEntityId]); From 604868900be3795ca6ccf9364e483e9ada4faeb5 Mon Sep 17 00:00:00 2001 From: ponderingdemocritus Date: Thu, 12 Dec 2024 13:15:36 +1100 Subject: [PATCH 07/10] merge --- client/src/dojo/setup.ts | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/client/src/dojo/setup.ts b/client/src/dojo/setup.ts index 0a7156289..da0e080f1 100644 --- a/client/src/dojo/setup.ts +++ b/client/src/dojo/setup.ts @@ -85,16 +85,16 @@ export async function setup({ ...config }: DojoConfig) { keys: ["763", undefined], pattern_matching: "FixedLen", models: [ - // 's0_eternum-Tile', - // 's0_eternum-BuildingQuantityv2', - // // 's0_eternum-Resource', - // // 's0_eternum-Production', - // 's0_eternum-GuildWhitelist', - // 's0_eternum-Progress', - // 's0_eternum-HyperstructureContribution', - // 's0_eternum-Epoch', - // // 's0_eternum-QuestBonus', - // // "s0_eternum-Progress", + // 's0_eternum-Tile', - done + // 's0_eternum-BuildingQuantityv2', - done with Realm + // // 's0_eternum-Resource', - done with Realm + // // 's0_eternum-Production', - done with Realm + // 's0_eternum-GuildWhitelist', - add to subscription from somewhere + // 's0_eternum-Progress', - done + // 's0_eternum-HyperstructureContribution', - done + // 's0_eternum-Epoch', - done + // // 's0_eternum-QuestBonus', - done + // // "s0_eternum-Progress", - done // // "s0_eternum-Market", // 's0_eternum-Quest', // 's0_eternum-Position', @@ -102,27 +102,11 @@ export async function setup({ ...config }: DojoConfig) { }, }; - const threeKeyQuery = { - Keys: { - keys: [undefined, undefined, undefined], - pattern_matching: "FixedLen", - models: ["s0_eternum-BuildingConfig", "s0_eternum-Liquidity"], - }, - }; - - const fourKeyQuery = { - Keys: { - keys: [undefined, undefined, undefined, undefined], - pattern_matching: "FixedLen", - models: ["s0_eternum-Building"], - }, - }; - // fetch all existing entities from torii const sync = await getSyncEntities( network.toriiClient, network.contractComponents as any, - + { Composite: { operator: "Or", From 5989d8e8f4feb6e261fddab6428317536e451402 Mon Sep 17 00:00:00 2001 From: tedison Date: Wed, 11 Dec 2024 21:19:11 -0500 Subject: [PATCH 08/10] do sync --- client/package.json | 3 +- client/src/dojo/queries.ts | 251 +++++++++++++++----------------- client/src/dojo/setup.ts | 64 ++++---- client/src/ui/layouts/World.tsx | 20 ++- pnpm-lock.yaml | 3 + 5 files changed, 171 insertions(+), 170 deletions(-) diff --git a/client/package.json b/client/package.json index d69af3fb3..30c37b8d0 100644 --- a/client/package.json +++ b/client/package.json @@ -20,6 +20,7 @@ "@cartridge/connector": "0.5.5", "@cartridge/controller": "0.5.5", "@dojoengine/core": "1.0.1", + "@dojoengine/torii-wasm": "1.0.1", "@dojoengine/create-burner": "1.0.1", "@dojoengine/react": "1.0.1", "@dojoengine/recs": "^2.0.13", @@ -104,4 +105,4 @@ "vitest": "^2.0.5", "workbox-window": "^7.3.0" } -} \ No newline at end of file +} diff --git a/client/src/dojo/queries.ts b/client/src/dojo/queries.ts index ae132c035..53d327a86 100644 --- a/client/src/dojo/queries.ts +++ b/client/src/dojo/queries.ts @@ -2,158 +2,149 @@ import { Component, Metadata, Schema } from "@dojoengine/recs"; import { setEntities } from "@dojoengine/state"; -import { Clause, EntityKeysClause, Subscription, ToriiClient } from "@dojoengine/torii-client"; +import { Clause, EntityKeysClause, PatternMatching, Subscription, ToriiClient } from "@dojoengine/torii-client"; // on hexception -> fetch below queries based on entityID -// background sync after load -> +// background sync after load -> export const getEntities = async ( - client: ToriiClient, - clause: Clause | undefined, - components: Component[], - limit: number = 100, - logging: boolean = false + client: ToriiClient, + clause: Clause | undefined, + components: Component[], + limit: number = 100, + logging: boolean = false, ) => { - if (logging) console.log("Starting getEntities"); - let offset = 0; - let continueFetching = true; + if (logging) console.log("Starting getEntities"); + let offset = 0; + let continueFetching = true; - while (continueFetching) { - const entities = await client.getEntities({ - limit, - offset, - clause, - dont_include_hashed_keys: false, - }); + while (continueFetching) { + const entities = await client.getEntities({ + limit, + offset, + clause, + dont_include_hashed_keys: false, + }); - console.log("entities", entities); + console.log("entities", entities); - if (logging) console.log(`Fetched ${entities} entities`); + if (logging) console.log(`Fetched ${entities} entities`); - setEntities(entities, components, logging); + setEntities(entities, components, logging); - if (Object.keys(entities).length < limit) { - continueFetching = false; - } else { - offset += limit; - } + if (Object.keys(entities).length < limit) { + continueFetching = false; + } else { + offset += limit; } + } }; - - export const syncEntitiesEternum = async ( - client: ToriiClient, - components: Component[], - entityKeyClause: EntityKeysClause[], - logging: boolean = true + client: ToriiClient, + components: Component[], + entityKeyClause: EntityKeysClause[], + logging: boolean = true, ) => { - if (logging) console.log("Starting syncEntities"); - return await client.onEntityUpdated( - entityKeyClause, - (fetchedEntities: any, data: any) => { - if (logging) console.log("Entity updated", fetchedEntities); - - setEntities({ [fetchedEntities]: data }, components, logging); - } - ); + if (logging) console.log("Starting syncEntities"); + return await client.onEntityUpdated(entityKeyClause, (fetchedEntities: any, data: any) => { + if (logging) console.log("Entity updated", fetchedEntities); + + setEntities({ [fetchedEntities]: data }, components, logging); + }); }; -export const addToSubscription = async (client: ToriiClient, subscription: Subscription, components: Component[], entityID: string, position?: {x: number, y: number}) => { - - console.log("position", subscription); - - await getEntities(client, { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, components, 1000, false); - - await getEntities(client, { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, components, 1000, false); - - await getEntities(client, { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, components, 1000, false); - - - await getEntities(client, { - Keys: { - keys: [String(position?.x || 0), String(position?.y || 0), undefined, undefined], - pattern_matching: 'FixedLen', - models: [ - ], - }, - }, components, 1000, false); - - // await client.updateEntitySubscription(subscription, [ - // { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, - // ]); - - // await client.updateEntitySubscription(subscription, [ - // { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, - // ]); - - // await client.updateEntitySubscription(subscription, [ - // { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, - // ]); - - try { - await client.updateEntitySubscription(subscription, [ - { ...entityQueryOneKey(entityID), Keys: { ...entityQueryOneKey(entityID).Keys, pattern_matching: "FixedLen" } }, - { ...entityQueryTwoKey(entityID), Keys: { ...entityQueryTwoKey(entityID).Keys, pattern_matching: "FixedLen" } }, - { ...entityQueryThreeKey(entityID), Keys: { ...entityQueryThreeKey(entityID).Keys, pattern_matching: "FixedLen" } }, - { - Keys: { - keys: [String(position?.x || 0), String(position?.y || 0), undefined, undefined], - pattern_matching: 'FixedLen', - models: [ - ], - }, - }, - ]); - } catch (error) { - console.error("Error updating entity subscription:", error); - } -} +export const addToSubscription = async ( + client: ToriiClient, + syncObject: { sync: Subscription; clauses: EntityKeysClause[] }, + components: Component[], + entityID: string, + position?: { x: number; y: number }, +) => { + console.log("position", syncObject); + + await getEntities(client, { ...(entityQueryOneKey(entityID) as Clause) }, components, 1000, false); + + await getEntities(client, { ...(entityQueryTwoKey(entityID) as Clause) }, components, 1000, false); + + await getEntities(client, { ...(entityQueryThreeKey(entityID) as Clause) }, components, 1000, false); + + await getEntities( + client, + { + Keys: { + keys: [String(position?.x || 0), String(position?.y || 0), undefined, undefined], + pattern_matching: "FixedLen", + models: [], + }, + }, + components, + 1000, + false, + ); + const positionClause: EntityKeysClause = { + Keys: { + keys: [String(position?.x || 0), String(position?.y || 0), undefined, undefined], + pattern_matching: "FixedLen" as PatternMatching, + models: [], + }, + }; + + const newSubscriptions = [ + { ...entityQueryOneKey(entityID) }, + { ...entityQueryTwoKey(entityID) }, + { ...entityQueryThreeKey(entityID) }, + { ...entityQueryFourKey(position?.x || 0, position?.y || 0) }, + positionClause, + ...syncObject.clauses, + ]; + + try { + await client.updateEntitySubscription(syncObject.sync, newSubscriptions); + } catch (error) { + console.log("error", error); + } + + syncObject.clauses = newSubscriptions; +}; const entityQueryOneKey = (entityID: string) => { - return { - Keys: { - keys: [entityID], - pattern_matching: 'FixedLen', - models: [], - }, - } -} + return { + Keys: { + keys: [entityID], + pattern_matching: "FixedLen", + models: [], + }, + } as EntityKeysClause; +}; const entityQueryTwoKey = (entityID: string) => { - return { - Keys: { - keys: [entityID, undefined], - pattern_matching: 'FixedLen', - models: [ - ], - }, - } -} + return { + Keys: { + keys: [entityID, undefined], + pattern_matching: "FixedLen", + models: [], + }, + } as EntityKeysClause; +}; const entityQueryThreeKey = (entityID: string) => { - return { - Keys: { - keys: [entityID, undefined, undefined], - pattern_matching: 'FixedLen', - models: [ - ], - }, - } -} - -const entityQueryFourKey = ( x: number, y: number) => { - return { - Keys: { - keys: [String(x), String(y), undefined, undefined], - pattern_matching: 'FixedLen', - models: [ - ], - }, - } -} - - - + return { + Keys: { + keys: [entityID, undefined, undefined], + pattern_matching: "FixedLen", + models: [], + }, + } as EntityKeysClause; +}; +const entityQueryFourKey = (x: number, y: number) => { + return { + Keys: { + keys: [String(x), String(y), undefined, undefined], + pattern_matching: "FixedLen", + models: [], + }, + } as EntityKeysClause; +}; diff --git a/client/src/dojo/setup.ts b/client/src/dojo/setup.ts index 0a7156289..24db060dd 100644 --- a/client/src/dojo/setup.ts +++ b/client/src/dojo/setup.ts @@ -1,6 +1,7 @@ import { WORLD_CONFIG_ID } from "@bibliothecadao/eternum"; import { DojoConfig } from "@dojoengine/core"; import { getSyncEntities, getSyncEvents } from "@dojoengine/state"; +import { Clause } from "@dojoengine/torii-client"; import { createClientComponents } from "./createClientComponents"; import { createSystemCalls } from "./createSystemCalls"; import { ClientConfigManager } from "./modelManager/ConfigManager"; @@ -118,44 +119,45 @@ export async function setup({ ...config }: DojoConfig) { }, }; - // fetch all existing entities from torii - const sync = await getSyncEntities( - network.toriiClient, - network.contractComponents as any, - + const clauses: Clause[] = [ + { + Keys: { + keys: [undefined], + pattern_matching: "FixedLen", + models: [], + }, + }, + { + Keys: { + keys: [WORLD_CONFIG_ID.toString(), undefined], + pattern_matching: "VariableLen", + models: [], + }, + }, { - Composite: { - operator: "Or", - clauses: [ - { - Keys: { - keys: [undefined], - pattern_matching: "FixedLen", - models: [], - }, - }, - { - Keys: { - keys: [WORLD_CONFIG_ID.toString(), undefined], - pattern_matching: "VariableLen", - models: [], - }, - }, - { - Keys: { - keys: [WORLD_CONFIG_ID.toString()], - pattern_matching: "VariableLen", - models: [], - }, - }, - ], + Keys: { + keys: [WORLD_CONFIG_ID.toString()], + pattern_matching: "VariableLen", + models: [], }, }, + ]; + // fetch all existing entities from torii + const sync = await getSyncEntities( + network.toriiClient, + network.contractComponents as any, + { Composite: { operator: "Or", clauses: [...clauses] } }, [], 1000, + true, ); + const syncObject = { + sync, + clauses: [...clauses], + }; + const eventSync = getSyncEvents( network.toriiClient, network.contractComponents.events as any, @@ -172,7 +174,7 @@ export async function setup({ ...config }: DojoConfig) { network, components, systemCalls, - sync, + syncObject, eventSync, }; } diff --git a/client/src/ui/layouts/World.tsx b/client/src/ui/layouts/World.tsx index 8bfbee1c9..dcf279a95 100644 --- a/client/src/ui/layouts/World.tsx +++ b/client/src/ui/layouts/World.tsx @@ -9,11 +9,12 @@ import { useStructureEntityId } from "@/hooks/helpers/useStructureEntityId"; import { useFetchBlockchainData } from "@/hooks/store/useBlockchainStore"; import { useWorldStore } from "@/hooks/store/useWorldLoading"; import { useComponentValue } from "@dojoengine/react"; +import { EntityKeysClause, Subscription } from "@dojoengine/torii-client"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { env } from "../../../env"; import { IS_MOBILE } from "../config"; -import { LoadingScreen } from "../modules/LoadingScreen"; import { LoadingOroborus } from "../modules/loading-oroborus"; +import { LoadingScreen } from "../modules/LoadingScreen"; // Lazy load components const SelectedArmy = lazy(() => @@ -83,8 +84,6 @@ const MiniMapNavigation = lazy(() => import("../modules/navigation/MiniMapNavigation").then((module) => ({ default: module.MiniMapNavigation })), ); - - export const World = ({ backgroundImage }: { backgroundImage: string }) => { const showBlankOverlay = useUIStore((state) => state.showBlankOverlay); const isLoadingScreenEnabled = useUIStore((state) => state.isLoadingScreenEnabled); @@ -105,14 +104,19 @@ export const World = ({ backgroundImage }: { backgroundImage: string }) => { const dojo = useDojo(); const structureEntityId = useUIStore((state) => state.structureEntityId); - const position = useComponentValue(dojo.setup.components.Position, getEntityIdFromKeys([BigInt(structureEntityId)])) + const position = useComponentValue(dojo.setup.components.Position, getEntityIdFromKeys([BigInt(structureEntityId)])); useEffect(() => { - const fetch = async () => { - await addToSubscription(dojo.setup.network.toriiClient, dojo.setup.sync, dojo.setup.network.contractComponents as any, structureEntityId.toString(), {x: position?.x || 0, y: position?.y || 0}); - } setWorldLoading(true); - console.log("world loading", worldLoading); + const fetch = async () => { + await addToSubscription( + dojo.setup.network.toriiClient, + dojo.setup.syncObject as { sync: Subscription; clauses: EntityKeysClause[] }, + dojo.setup.network.contractComponents as any, + structureEntityId.toString(), + { x: position?.x || 0, y: position?.y || 0 }, + ); + }; fetch(); console.log("world loading", worldLoading); setWorldLoading(false); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 033831bc9..0c237c5ab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -154,6 +154,9 @@ importers: '@dojoengine/torii-client': specifier: 1.0.1 version: 1.0.1 + '@dojoengine/torii-wasm': + specifier: 1.0.1 + version: 1.0.1 '@dojoengine/utils': specifier: 1.0.1 version: 1.0.1(starknet@6.11.0(encoding@0.1.13))(typescript@5.6.3)(zod@3.23.8) From 90afac3088da9374832da3e6744752bb75f5824d Mon Sep 17 00:00:00 2001 From: ponderingdemocritus Date: Thu, 12 Dec 2024 13:19:20 +1100 Subject: [PATCH 09/10] bank --- .../src/ui/components/trading/MarketModal.tsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/client/src/ui/components/trading/MarketModal.tsx b/client/src/ui/components/trading/MarketModal.tsx index e6001befc..126a9dbcc 100644 --- a/client/src/ui/components/trading/MarketModal.tsx +++ b/client/src/ui/components/trading/MarketModal.tsx @@ -4,6 +4,7 @@ import { ReactComponent as Scroll } from "@/assets/icons/Scroll.svg"; import { ReactComponent as Sparkles } from "@/assets/icons/Sparkles.svg"; import { ReactComponent as Swap } from "@/assets/icons/Swap.svg"; import { BattleManager } from "@/dojo/modelManager/BattleManager"; +import { addToSubscription } from "@/dojo/queries"; import { configManager } from "@/dojo/setup"; import { useDojo } from "@/hooks/context/DojoContext"; import { useBattlesByPosition } from "@/hooks/helpers/battles/useBattles"; @@ -25,10 +26,10 @@ import { formatTimeDifference } from "@/ui/modules/military/battle-view/BattlePr import { currencyFormat, getEntityIdFromKeys } from "@/ui/utils/utils"; import { ID, ResourcesIds } from "@bibliothecadao/eternum"; import { useComponentValue } from "@dojoengine/react"; -import { Suspense, lazy, useMemo, useState } from "react"; +import { Suspense, lazy, useEffect, useMemo, useState } from "react"; +import { ModalContainer } from "../ModalContainer"; import { HintModal } from "../hints/HintModal"; import { TroopDisplay } from "../military/TroopChip"; -import { ModalContainer } from "../ModalContainer"; const MarketResourceSidebar = lazy(() => import("./MarketResourceSideBar").then((module) => ({ default: module.MarketResourceSidebar })), @@ -70,6 +71,20 @@ export const MarketModal = () => { const bankStructure = getStructure(bank?.position || { x: 0, y: 0 }); + useEffect(() => { + const fetch = async () => { + await addToSubscription( + dojo.setup.network.toriiClient, + dojo.setup.sync, + dojo.setup.network.contractComponents as any, + structureEntityId.toString(), + { x: 0, y: 0 }, + ); + }; + + fetch(); + }, [bankStructure?.entity_id]); + const battle = useMemo(() => { if (battles.length === 0) return null; return battles From 9c20e36710345f52de0cb3ad7e3006dd48dfb75d Mon Sep 17 00:00:00 2001 From: ponderingdemocritus Date: Thu, 12 Dec 2024 13:58:58 +1100 Subject: [PATCH 10/10] market --- client/src/dojo/setup.ts | 2 +- .../src/ui/components/trading/MarketModal.tsx | 17 +---------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/client/src/dojo/setup.ts b/client/src/dojo/setup.ts index b6b5dee43..cecdcfede 100644 --- a/client/src/dojo/setup.ts +++ b/client/src/dojo/setup.ts @@ -149,7 +149,7 @@ export async function setup({ ...config }: DojoConfig) { network.contractComponents as any, { Composite: { operator: "Or", clauses: [...clauses] } }, [], - 1000, + 5000, true, ); diff --git a/client/src/ui/components/trading/MarketModal.tsx b/client/src/ui/components/trading/MarketModal.tsx index 126a9dbcc..d388d544c 100644 --- a/client/src/ui/components/trading/MarketModal.tsx +++ b/client/src/ui/components/trading/MarketModal.tsx @@ -4,7 +4,6 @@ import { ReactComponent as Scroll } from "@/assets/icons/Scroll.svg"; import { ReactComponent as Sparkles } from "@/assets/icons/Sparkles.svg"; import { ReactComponent as Swap } from "@/assets/icons/Swap.svg"; import { BattleManager } from "@/dojo/modelManager/BattleManager"; -import { addToSubscription } from "@/dojo/queries"; import { configManager } from "@/dojo/setup"; import { useDojo } from "@/hooks/context/DojoContext"; import { useBattlesByPosition } from "@/hooks/helpers/battles/useBattles"; @@ -26,7 +25,7 @@ import { formatTimeDifference } from "@/ui/modules/military/battle-view/BattlePr import { currencyFormat, getEntityIdFromKeys } from "@/ui/utils/utils"; import { ID, ResourcesIds } from "@bibliothecadao/eternum"; import { useComponentValue } from "@dojoengine/react"; -import { Suspense, lazy, useEffect, useMemo, useState } from "react"; +import { Suspense, lazy, useMemo, useState } from "react"; import { ModalContainer } from "../ModalContainer"; import { HintModal } from "../hints/HintModal"; import { TroopDisplay } from "../military/TroopChip"; @@ -71,20 +70,6 @@ export const MarketModal = () => { const bankStructure = getStructure(bank?.position || { x: 0, y: 0 }); - useEffect(() => { - const fetch = async () => { - await addToSubscription( - dojo.setup.network.toriiClient, - dojo.setup.sync, - dojo.setup.network.contractComponents as any, - structureEntityId.toString(), - { x: 0, y: 0 }, - ); - }; - - fetch(); - }, [bankStructure?.entity_id]); - const battle = useMemo(() => { if (battles.length === 0) return null; return battles