diff --git a/packages/client/src/svelte/components/Main/Bars/TabBar.svelte b/packages/client/src/svelte/components/Main/Bars/TabBar.svelte index 56f96d31..3217b513 100644 --- a/packages/client/src/svelte/components/Main/Bars/TabBar.svelte +++ b/packages/client/src/svelte/components/Main/Bars/TabBar.svelte @@ -31,18 +31,16 @@ $: unreadInboxItems = $staticContent.messages .filter( msg => - msg.tutorial || msg.graduation || $discoveredMessages.includes(msg._id) + msg.tutorial || msg.graduation || $discoveredMessages.includes(msg._id), ) .filter(msg => !$inboxRead.includes(msg._id)) - $: console.log(unreadInboxItems) - $: notify = unreadInboxItems.length > 0 && $tutorialProgress > 30 $: advanceTutorial($activeTab, $tutorialProgress, "tab") $: availableTabsLength = Object.values(HIDDEN_CONDITIONS).filter( - num => $tutorialProgress > num + num => $tutorialProgress > num, ).length const onClick = (e: MouseEvent) => { diff --git a/packages/client/src/svelte/components/Spawn/Spawn.svelte b/packages/client/src/svelte/components/Spawn/Spawn.svelte index 04f5e2f8..03e89d61 100644 --- a/packages/client/src/svelte/components/Spawn/Spawn.svelte +++ b/packages/client/src/svelte/components/Spawn/Spawn.svelte @@ -16,6 +16,7 @@ import { setupWalletNetwork } from "@mud/setupWalletNetwork" import { store as accountKitStore } from "@latticexyz/account-kit/bundle" import { tutorialProgress } from "@modules/ui/assistant" + import { initEntities } from "@modules/systems/initEntities" export let environment: ENVIRONMENT @@ -88,6 +89,9 @@ ) // Set player address to main wallet address playerAddress.set(accountKitStoreState.userAddress) + + // Set initial local state + initEntities() } } diff --git a/packages/client/src/svelte/components/Spawn/narrative.ts b/packages/client/src/svelte/components/Spawn/narrative.ts index f28c2fc5..54504541 100644 --- a/packages/client/src/svelte/components/Spawn/narrative.ts +++ b/packages/client/src/svelte/components/Spawn/narrative.ts @@ -21,7 +21,6 @@ import { } from "@modules/state/simulated/stores" import { inboxRead } from "@modules/ui/stores" import { BUG_MATERIAL } from "@modules/ui/constants" -import { tutorialProgress } from "@modules/ui/assistant" import { renderNaming } from "@components/Main/Terminal/functions/renderNaming" import { publicNetwork, walletNetwork } from "@modules/network" import { setupWalletNetwork } from "@mud/setupWalletNetwork" @@ -29,6 +28,8 @@ import { ENVIRONMENT } from "@mud/enums" import { initSignalNetwork } from "@modules/signal" import { connect } from "./account-kit-connect" import type { AccountKitConnectReturn } from "./account-kit-connect/types" +import { initEntities } from "@modules/systems/initEntities" + async function writeNarrative(text: string) { await typeWriteToTerminal( @@ -110,6 +111,10 @@ export const narrative = [ ) { // Burner wallet already initialized in Spawn component await typeWriteNarrativeSuccess("No verification required.") + + // Set initial local state + initEntities() + } else { // Account kit await writeNarrative("Starting verification process...") @@ -137,6 +142,9 @@ export const narrative = [ ) // Set player address to main wallet address playerAddress.set(accountKitConnectReturn.userAddress) + + // Set initial local state + initEntities() } // Websocket connection for off-chain messaging diff --git a/packages/client/src/svelte/modules/systems/createComponentSystem.ts b/packages/client/src/svelte/modules/systems/createComponentSystem.ts index 8fdc2161..6c169c72 100644 --- a/packages/client/src/svelte/modules/systems/createComponentSystem.ts +++ b/packages/client/src/svelte/modules/systems/createComponentSystem.ts @@ -11,16 +11,23 @@ export function createComponentSystem(componentKey: string) { // If the values are the same we assume // this is directly after hydration + // Abort if (deepEqual(nextValue, prevValue)) return + const entityID = update.entity + const propertyName = componentKey === "ContainedMaterial" ? "materialId" : toCamelCase(componentKey) + + // TODO: filter updates + // - Update to component comes in + // - is the component on a type of entity that we might want to filter? + // - is the update relevant to the player? + // Single-value components have a "value" property, structs do not const newValue = nextValue && Object.prototype.hasOwnProperty.call(nextValue, "value") ? nextValue.value : nextValue - const entityID = update.entity - const propertyName = componentKey === "ContainedMaterial" ? "materialId" : toCamelCase(componentKey) entities.update(value => { // Create an empty entity if it does not exist diff --git a/packages/client/src/svelte/modules/systems/createSyncProgressSystem.ts b/packages/client/src/svelte/modules/systems/createSyncProgressSystem.ts index bbb18ea6..19ece784 100644 --- a/packages/client/src/svelte/modules/systems/createSyncProgressSystem.ts +++ b/packages/client/src/svelte/modules/systems/createSyncProgressSystem.ts @@ -1,8 +1,7 @@ import { get } from "svelte/store" import { publicNetwork, ready, loadingMessage } from "@modules/network" import { SyncStep } from "@latticexyz/store-sync" -import { initEntities } from "@modules/systems/initEntities" -import { createComponentSystem } from "@modules/systems/" +// import { createComponentSystem } from "@modules/systems/" export function createSyncProgressSystem() { let subscription = get(publicNetwork).components.SyncProgress.update$.subscribe( @@ -11,14 +10,6 @@ export function createSyncProgressSystem() { if (update.value[0]?.step === SyncStep.LIVE) { // Data loaded from indexer - // Set initial local state - initEntities() - - // Create systems to listen to changes to game-specific tables - for (const componentKey of get(publicNetwork).tableKeys) { - createComponentSystem(componentKey) - } - ready.set(true) subscription.unsubscribe() diff --git a/packages/client/src/svelte/modules/systems/initEntities.ts b/packages/client/src/svelte/modules/systems/initEntities.ts index df44e346..5d1fe520 100644 --- a/packages/client/src/svelte/modules/systems/initEntities.ts +++ b/packages/client/src/svelte/modules/systems/initEntities.ts @@ -2,6 +2,10 @@ import { get } from "svelte/store" import { publicNetwork } from "@modules/network" import { filterObjectByKey, toCamelCase, removePrivateKeys } from "@modules/utils" import { entities } from "@modules/state/base/stores" +import { playerAddress } from "@modules/state/base/stores" +import { ENTITY_TYPE } from "@modules/state/base/enums" +import { addressToId } from "@modules/utils" +import { createComponentSystem } from "@modules/systems" export function initEntities() { const tableKeys = get(publicNetwork).tableKeys @@ -41,6 +45,56 @@ export function initEntities() { } } + const filteredEntities = filterEntities(syncEntities) + // Single write to store - entities.set(syncEntities) + entities.set(filteredEntities) + + // Create systems to listen to changes to game - specific tables + for (const componentKey of get(publicNetwork).tableKeys) { + createComponentSystem(componentKey) + } + +} + +function filterEntities(syncEntities: Entities) { + const playerEntity = syncEntities[addressToId(get(playerAddress))] + if (!playerEntity) return syncEntities + + const playerPodId = playerEntity.carriedBy + if (!playerPodId) return syncEntities + + let filteredEntities = {} as Entities + + // To matche: config, orders, offers, recipes and materials + const GLOBAL_TABLES = ['gameConfig', 'order', 'offer', 'recipe', 'materialMetadata'] + + Object.entries(syncEntities).forEach(([key, entity]) => { + if (hasCommonElement(GLOBAL_TABLES, Object.keys(entity))) { + // Global entites + filteredEntities[key] = entity + } else if (entity.entityType === ENTITY_TYPE.POD) { + // Pods + if (key == playerPodId) { + filteredEntities[key] = entity + } + } else if (entity.entityType == ENTITY_TYPE.MACHINE && entity.carriedBy) { + // Machines + if (entity.carriedBy == playerPodId) { + filteredEntities[key] = entity + } + } else if (entity.entityType == ENTITY_TYPE.TANK && entity.carriedBy) { + // Tanks + if (entity.carriedBy == playerPodId) { + filteredEntities[key] = entity + } + } + }) + + return filteredEntities +} + +function hasCommonElement(arr1: string[], arr2: string[]): boolean { + const set1 = new Set(arr1); + return arr2.some(element => set1.has(element)); }