Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix structure owners & transfers #2544

Merged
merged 1 commit into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions client/src/dojo/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,26 @@ export const syncPosition = async <S extends Schema>(
30_000,
);
};
export const syncBuildingQty = async <S extends Schema>(

export const addToSubscriptionTwoKeyModelbyRealmEntityId = async <S extends Schema>(
client: ToriiClient,
components: Component<S, Metadata, undefined>[],
entityID: string,
entityID: string[],
) => {
await getEntities(
client,
{
Keys: {
keys: [entityID, undefined],
pattern_matching: "FixedLen" as PatternMatching,
models: ["s0_eternum-BuildingQuantityv2"],
Composite: {
operator: "Or",
clauses: [
...entityID.map((id) => ({
Keys: {
keys: [id, undefined],
pattern_matching: "VariableLen" as PatternMatching,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding error handling and retry logic for failed entity fetches

models: ["s0_eternum-BuildingQuantityv2"],
},
})),
Comment on lines +32 to +49
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor duplicate code in subscription functions

The functions addToSubscriptionTwoKeyModelbyRealmEntityId and addToSubscriptionOneKeyModelbyRealmEntityId share similar logic in constructing composite queries. Consider creating a helper function to reduce code duplication and improve maintainability.

],
},
},
components,
Expand All @@ -49,12 +57,11 @@ export const syncBuildingQty = async <S extends Schema>(
);
};

export const addToSubscriptionBuildingQty = async <S extends Schema>(
export const addToSubscriptionOneKeyModelbyRealmEntityId = async <S extends Schema>(
client: ToriiClient,
components: Component<S, Metadata, undefined>[],
entityID: string[],
) => {
const start = performance.now();
await getEntities(
client,
{
Expand All @@ -63,9 +70,9 @@ export const addToSubscriptionBuildingQty = async <S extends Schema>(
clauses: [
...entityID.map((id) => ({
Keys: {
keys: [id, undefined],
keys: [id],
pattern_matching: "VariableLen" as PatternMatching,
models: ["s0_eternum-BuildingQuantityv2"],
models: ["s0_eternum-ArrivalTime", "s0_eternum-OwnedResourcesTracker"],
},
})),
],
Expand All @@ -76,8 +83,6 @@ export const addToSubscriptionBuildingQty = async <S extends Schema>(
[],
30_000,
);
const end = performance.now();
console.log("AddToSubscription Building qty", end - start);
};

export const addToSubscription = async <S extends Schema>(
Expand Down
15 changes: 1 addition & 14 deletions client/src/dojo/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,16 +114,13 @@ export async function setup({ ...config }: DojoConfig) {
},
];

const CompositeStart = performance.now();
await getEntities(
network.toriiClient,
{ Composite: { operator: "Or", clauses: configClauses } },
network.contractComponents as any,
);
const CompositeEnd = performance.now();

// fetch all existing entities from torii
const SingleKeyStart = performance.now();
await getEntities(
network.toriiClient,
{
Expand All @@ -143,7 +140,7 @@ export async function setup({ ...config }: DojoConfig) {
"s0_eternum-Army",
"s0_eternum-Structure",
"s0_eternum-Battle",
// Probably load this w/ market
"s0_eternum-EntityOwner",
],
},
},
Expand All @@ -153,9 +150,7 @@ export async function setup({ ...config }: DojoConfig) {
40_000,
false,
);
const SingleKeyEnd = performance.now();

const DoubleKeyStart = performance.now();
await getEntities(
network.toriiClient,
{
Expand All @@ -171,11 +166,8 @@ export async function setup({ ...config }: DojoConfig) {
40_000,
false,
);
const DoubleKeyEnd = performance.now();

const SyncStart = performance.now();
const sync = await syncEntitiesDebounced(network.toriiClient, network.contractComponents as any, [], false);
const SyncEnd = performance.now();

configManager.setDojo(components);

Expand Down Expand Up @@ -207,11 +199,6 @@ export async function setup({ ...config }: DojoConfig) {
false,
);

console.log("CompositeEnd", CompositeEnd - CompositeStart);
console.log("SyncEnd", SyncEnd - SyncStart);
console.log("SingleKeyEnd", SingleKeyEnd - SingleKeyStart);
console.log("DoubleKeyEnd", DoubleKeyEnd - DoubleKeyStart);

return {
network,
components,
Expand Down
3 changes: 2 additions & 1 deletion client/src/hooks/helpers/use-resource-arrivals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ const usePlayerArrivals = () => {
];

const getArrivalsWithResourceOnPosition = useCallback((positions: Position[]) => {
return positions.flatMap((position) => {
const arrivals = positions.flatMap((position) => {
return Array.from(runQuery([HasValue(Position, { x: position.x, y: position.y }), ...queryFragments]));
});
return arrivals;
Comment on lines +62 to +65
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This intermediate variable assignment is unnecessary. You can return the flatMap result directly.

Suggested change
const arrivals = positions.flatMap((position) => {
return Array.from(runQuery([HasValue(Position, { x: position.x, y: position.y }), ...queryFragments]));
});
return arrivals;
return positions.flatMap((position) => {
return Array.from(runQuery([HasValue(Position, { x: position.x, y: position.y }), ...queryFragments]));
});

}, []);

const createArrivalInfo = useCallback(
Expand Down
4 changes: 4 additions & 0 deletions client/src/hooks/store/useWorldLoading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import { create } from "zustand";
interface WorldState {
isWorldLoading: boolean;
isMarketLoading: boolean;
isStructuresLoading: boolean;
setWorldLoading: (loading: boolean) => void;
setMarketLoading: (loading: boolean) => void;
setStructuresLoading: (loading: boolean) => void;
}

export const useWorldStore = create<WorldState>((set) => ({
isWorldLoading: true,
isMarketLoading: true,
isStructuresLoading: true,
setWorldLoading: (loading: boolean) => set({ isWorldLoading: loading }),
setMarketLoading: (loading: boolean) => set({ isMarketLoading: loading }),
setStructuresLoading: (loading: boolean) => set({ isStructuresLoading: loading }),
}));
34 changes: 13 additions & 21 deletions client/src/ui/layouts/World.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@ import { lazy, Suspense, useEffect, useMemo, useState } from "react";
import { Redirect } from "wouter";
import useUIStore from "../../hooks/store/useUIStore";

import { addMarketSubscription, addToSubscription, addToSubscriptionBuildingQty, syncBuildingQty } from "@/dojo/queries";
import {
addMarketSubscription,
addToSubscription,
addToSubscriptionOneKeyModelbyRealmEntityId,
addToSubscriptionTwoKeyModelbyRealmEntityId,
} from "@/dojo/queries";
import { useDojo } from "@/hooks/context/DojoContext";
import { PlayerStructure, useEntities } from "@/hooks/helpers/useEntities";
import { useStructureEntityId } from "@/hooks/helpers/useStructureEntityId";
import { useFetchBlockchainData } from "@/hooks/store/useBlockchainStore";
import { useWorldStore } from "@/hooks/store/useWorldLoading";
import { ADMIN_BANK_ENTITY_ID, BuildingType } from "@bibliothecadao/eternum";
import { ADMIN_BANK_ENTITY_ID } from "@bibliothecadao/eternum";
import { getComponentValue } from "@dojoengine/recs";
import { getEntityIdFromKeys } from "@dojoengine/utils";
import { env } from "../../../env";
import { IS_MOBILE } from "../config";
import { LoadingOroborus } from "../modules/loading-oroborus";
import { LoadingScreen } from "../modules/LoadingScreen";
import { useBuildings } from "@/hooks/helpers/use-buildings";
// Lazy load components

const SelectedArmy = lazy(() =>
Expand Down Expand Up @@ -117,12 +121,6 @@ export const World = ({ backgroundImage }: { backgroundImage: string }) => {
[structures, subscriptions],
);

// const { getBuildings } = useBuildings();
// filteredStructures.forEach((structure) => {
// console.log("Buildings", getBuildings(structure.position.x, structure.position.y));
// });

// console.log("FilteredStructures", filteredStructures);
useEffect(() => {
if (
!structureEntityId ||
Expand All @@ -133,13 +131,6 @@ export const World = ({ backgroundImage }: { backgroundImage: string }) => {
return;
}

// syncBuildingQty(dojo.network.toriiClient, dojo.network.contractComponents as any, structureEntityId.toString());
// filteredStructures.forEach((structure) => {
// syncBuildingQty(dojo.network.toriiClient, dojo.network.contractComponents as any, structure.entity_id.toString());
// });



const position = getComponentValue(
dojo.setup.components.Position,
getEntityIdFromKeys([BigInt(structureEntityId)]),
Expand All @@ -155,9 +146,13 @@ export const World = ({ backgroundImage }: { backgroundImage: string }) => {

const fetch = async () => {
try {
const start = performance.now();
await Promise.all([
addToSubscriptionBuildingQty(
addToSubscriptionOneKeyModelbyRealmEntityId(
dojo.network.toriiClient,
dojo.network.contractComponents as any,
[...filteredStructures.map((structure) => structure.entity_id.toString())],
),
addToSubscriptionTwoKeyModelbyRealmEntityId(
dojo.network.toriiClient,
dojo.network.contractComponents as any,
[...filteredStructures.map((structure) => structure.entity_id.toString())],
Expand All @@ -179,14 +174,11 @@ export const World = ({ backgroundImage }: { backgroundImage: string }) => {
),
addMarketSubscription(dojo.network.toriiClient, dojo.network.contractComponents as any),
]);
const end = performance.now();
console.log("FetchEnd", end - start);
} catch (error) {
console.error("Fetch failed", error);
} finally {
setWorldLoading(false);
setMarketLoading(false);
console.log("Done fetching")
}
};

Expand Down
58 changes: 32 additions & 26 deletions client/src/ui/modules/world-structures/WorldStructuresMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ 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 { useWorldStore } 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";
Expand All @@ -16,16 +17,9 @@ import { ViewOnMapIcon } from "@/ui/components/military/ArmyManagementCard";
import { Checkbox } from "@/ui/elements/Checkbox";
import { HintModalButton } from "@/ui/elements/HintModalButton";
import { ResourceIcon } from "@/ui/elements/ResourceIcon";
import { currencyFormat, currencyIntlFormat, divideByPrecision, getEntityIdFromKeys } from "@/ui/utils/utils";
import {
BattleSide,
ContractAddress,
HYPERSTRUCTURE_CONFIG_ID,
ID,
ResourcesIds,
findResourceById,
} from "@bibliothecadao/eternum";
import { Metadata, getComponentValue } from "@dojoengine/recs";
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";
Expand All @@ -39,10 +33,18 @@ export const WorldStructuresMenu = ({ className }: { className?: string }) => {
network: { toriiClient, contractComponents },
} = useDojo();

const isStructuresLoading = useWorldStore((state) => state.isStructuresLoading);
const setStructuresLoading = useWorldStore((state) => state.setStructuresLoading);

useEffect(() => {
const fetchData = async () => {
try {
await fetchHyperstructureData(toriiClient, contractComponents as any);
await fetchHyperstructureData(
toriiClient,
contractComponents as any,
isStructuresLoading,
setStructuresLoading,
);
} catch (error) {
console.error("Failed to fetch hyperstructure data:", error);
}
Expand Down Expand Up @@ -140,6 +142,14 @@ export const WorldStructuresMenu = ({ className }: { className?: string }) => {
[selectedTab, hyperstructures, fragmentMines, showOnlyMine, account.address, myHyperstructures],
);

if (isStructuresLoading) {
return (
<div className="flex items-center justify-center h-full">
<div className="text-gold">Loading structures...</div>
</div>
);
}

return (
<>
<HintModalButton className="absolute top-1 right-1" section={HintSection.WorldStructures} />
Expand Down Expand Up @@ -333,16 +343,17 @@ const EntityHeader = ({ entity }: { entity: any }) => {
);
};

const fetchHyperstructureData = async (client: ToriiClient, components: Component<S, Metadata, undefined>[]) => {
const hyperstructureConfig = getComponentValue(
(components as any).HyperstructureResourceConfig,
getEntityIdFromKeys([HYPERSTRUCTURE_CONFIG_ID, 4n]),
);

if (hyperstructureConfig) {
const fetchHyperstructureData = async (
client: ToriiClient,
components: Component<S, Metadata, undefined>[],
isStructuresLoading: boolean,
setStructuresLoading: (loading: boolean) => void,
) => {
if (!isStructuresLoading) {
return;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a timeout to prevent infinite loading states

console.log("Fetching hyperstructure data");
await getEntities(
client,
{
Expand All @@ -363,13 +374,6 @@ const fetchHyperstructureData = async (client: ToriiClient, components: Componen
models: ["s0_eternum-Epoch", "s0_eternum-Progress"],
},
},
{
Keys: {
keys: [HYPERSTRUCTURE_CONFIG_ID.toString(), undefined],
pattern_matching: "VariableLen",
models: [],
},
},
],
},
},
Expand All @@ -378,5 +382,7 @@ const fetchHyperstructureData = async (client: ToriiClient, components: Componen
[],
40_000,
false,
);
).finally(() => {
setStructuresLoading(false);
});
};
Loading