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

updates #2563

Merged
merged 2 commits into from
Dec 19, 2024
Merged

updates #2563

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
114 changes: 114 additions & 0 deletions client/src/dojo/debouncedQueries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { Component, Metadata, Schema } from "@dojoengine/recs";
import { ToriiClient } from "@dojoengine/torii-client";
import debounce from "lodash/debounce";
import {
addMarketSubscription,
addToSubscription,
addToSubscriptionOneKeyModelbyRealmEntityId,
addToSubscriptionTwoKeyModelbyRealmEntityId,
syncPosition,
} from "./queries";

// Queue class to manage requests
class RequestQueue {
private queue: Array<() => Promise<void>> = [];
private processing = false;
private batchSize = 3; // Number of concurrent requests
private batchDelayMs = 100; // Delay between batches

async add(request: () => Promise<void>) {
this.queue.push(request);
if (!this.processing) {
this.processing = true;
this.processQueue();
}
}

private async processQueue() {
while (this.queue.length > 0) {
const batch = this.queue.splice(0, this.batchSize);

try {
await Promise.all(batch.map((request) => request()));
} catch (error) {
console.error("Error processing request batch:", error);
}

if (this.queue.length > 0) {
// Add delay between batches to prevent overwhelming the server
await new Promise((resolve) => setTimeout(resolve, this.batchDelayMs));
}
}
this.processing = false;
}

clear() {
this.queue = [];
}
}

// Create separate queues for different types of requests
const positionQueue = new RequestQueue();
const subscriptionQueue = new RequestQueue();
const marketQueue = new RequestQueue();

// Debounced functions that add to queues
export const debouncedSyncPosition = debounce(
async <S extends Schema>(client: ToriiClient, components: Component<S, Metadata, undefined>[], entityID: string) => {
await positionQueue.add(() => syncPosition(client, components, entityID));
},
100,
{ leading: true }, // Add leading: true to execute immediately on first call
);

export const debouncedAddToSubscriptionTwoKey = debounce(
async <S extends Schema>(
client: ToriiClient,
components: Component<S, Metadata, undefined>[],
entityID: string[],
) => {
await subscriptionQueue.add(() => addToSubscriptionTwoKeyModelbyRealmEntityId(client, components, entityID));
},
250,
{ leading: true },
);

export const debouncedAddToSubscriptionOneKey = debounce(
async <S extends Schema>(
client: ToriiClient,
components: Component<S, Metadata, undefined>[],
entityID: string[],
) => {
await subscriptionQueue.add(() => addToSubscriptionOneKeyModelbyRealmEntityId(client, components, entityID));
},
250,
{ leading: true },
);

export const debouncedAddToSubscription = debounce(
async <S extends Schema>(
client: ToriiClient,
components: Component<S, Metadata, undefined>[],
entityID: string[],
position?: { x: number; y: number }[],
) => {
await subscriptionQueue.add(() => addToSubscription(client, components, entityID, position));
},
250,
{ leading: true },
);

export const debouncedAddMarketSubscription = debounce(
async <S extends Schema>(client: ToriiClient, components: Component<S, Metadata, undefined>[]) => {
await marketQueue.add(() => addMarketSubscription(client, components));
},
500,
{ leading: true },
);

// Utility function to clear all queues if needed
export const clearAllQueues = () => {
positionQueue.clear();
subscriptionQueue.clear();
marketQueue.clear();
};
10 changes: 5 additions & 5 deletions client/src/dojo/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const syncPosition = async <S extends Schema>(
components,
[],
[],
30_000,
5_000,
);
};

Expand Down Expand Up @@ -53,7 +53,7 @@ export const addToSubscriptionTwoKeyModelbyRealmEntityId = async <S extends Sche
components,
[],
[],
30_000,
5_000,
);
};

Expand Down Expand Up @@ -81,7 +81,7 @@ export const addToSubscriptionOneKeyModelbyRealmEntityId = async <S extends Sche
components,
[],
[],
30_000,
5_000,
);
};

Expand Down Expand Up @@ -122,7 +122,7 @@ export const addToSubscription = async <S extends Schema>(
components as any,
[],
[],
30_000,
5_000,
);
const end = performance.now();
console.log("AddToSubscriptionEnd", end - start);
Expand All @@ -145,7 +145,7 @@ export const addMarketSubscription = async <S extends Schema>(
components,
[],
[],
30_000,
5_000,
false,
);
const end = performance.now();
Expand Down
2 changes: 1 addition & 1 deletion client/src/dojo/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export async function setup({ ...config }: DojoConfig) {
},
{
Keys: {
keys: [HYPERSTRUCTURE_CONFIG_ID.toString(), undefined],
keys: [HYPERSTRUCTURE_CONFIG_ID.toString()],
pattern_matching: "VariableLen",
models: [],
},
Expand Down
2 changes: 2 additions & 0 deletions client/src/hooks/helpers/use-resource-arrivals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ const usePlayerArrivals = () => {
const arrivals = positions.flatMap((position) => {
return Array.from(runQuery([HasValue(Position, { x: position.x, y: position.y }), ...queryFragments]));
});

console.log("arrivals", arrivals);
return arrivals;
}, []);

Expand Down
92 changes: 13 additions & 79 deletions client/src/hooks/helpers/useEntities.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
type ID,
} from "@bibliothecadao/eternum";
import { useEntityQuery } from "@dojoengine/react";
import { Has, getComponentValue, type ComponentValue } from "@dojoengine/recs";
import { Has, HasValue, getComponentValue, type ComponentValue } from "@dojoengine/recs";
import { useMemo } from "react";
import { shortString } from "starknet";
import { useDojo } from "../context/DojoContext";
Expand All @@ -23,7 +23,7 @@ export type PlayerStructure = ComponentValue<ClientComponents["Structure"]["sche
owner: ComponentValue<ClientComponents["Owner"]["schema"]>;
};

type RealmWithPosition = ComponentValue<ClientComponents["Realm"]["schema"]> & {
export type RealmWithPosition = ComponentValue<ClientComponents["Realm"]["schema"]> & {
position: ComponentValue<ClientComponents["Position"]["schema"]>;
name: string;
owner: ComponentValue<ClientComponents["Owner"]["schema"]>;
Expand All @@ -43,53 +43,18 @@ export const useEntities = () => {
const { getEntityName } = useEntitiesUtils();

// Get all realms
const allRealms = useEntityQuery([Has(Realm)]);

const filterPlayerRealms = useMemo(() => {
return allRealms.filter((id) => {
const owner = getComponentValue(Owner, id);
return owner && ContractAddress(owner.address) === ContractAddress(address);
});
}, [allRealms, address]);

const filterOtherRealms = useMemo(() => {
return allRealms.filter((id) => {
const owner = getComponentValue(Owner, id);
return owner && ContractAddress(owner.address) !== ContractAddress(address);
});
}, [allRealms, address]);
const playerRealmsQuery = useEntityQuery([Has(Realm), HasValue(Owner, { address: address })]);

// Get all structures
const allStructures = useEntityQuery([Has(Structure), Has(Position), Has(Owner)]);

const filterPlayerStructures = useMemo(() => {
return allStructures.filter((id) => {
const owner = getComponentValue(Owner, id);
return owner && ContractAddress(owner.address) === ContractAddress(address);
});
}, [allStructures, address]);

const filterOtherStructures = useMemo(() => {
return allStructures.filter((id) => {
const owner = getComponentValue(Owner, id);
return owner && ContractAddress(owner.address) !== ContractAddress(address);
});
}, [allStructures, address]);
const playerStructuresQuery = useEntityQuery([
Has(Structure),
Has(Position),
Has(Owner),
HasValue(Owner, { address: address }),
]);

const playerRealms = useMemo(() => {
return filterPlayerRealms.map((id) => {
const realm = getComponentValue(Realm, id);
return {
...realm,
position: getComponentValue(Position, id),
name: getRealmNameById(realm!.realm_id),
owner: getComponentValue(Owner, id),
} as RealmWithPosition;
});
}, [filterPlayerRealms]);

const otherRealms = useMemo(() => {
return filterOtherRealms.map((id) => {
return playerRealmsQuery.map((id) => {
const realm = getComponentValue(Realm, id);
return {
...realm,
Expand All @@ -98,10 +63,10 @@ export const useEntities = () => {
owner: getComponentValue(Owner, id),
} as RealmWithPosition;
});
}, [filterOtherRealms]);
}, [playerRealmsQuery]);

const playerStructures = useMemo(() => {
return filterPlayerStructures
return playerStructuresQuery
.map((id) => {
const structure = getComponentValue(Structure, id);
if (!structure) return;
Expand All @@ -121,24 +86,7 @@ export const useEntities = () => {
if (b.category === StructureType[StructureType.Realm]) return 1;
return a.category.localeCompare(b.category);
});
}, [filterPlayerStructures]);

const otherStructures = useMemo(() => {
return filterOtherStructures
.map((id) => {
const structure = getComponentValue(Structure, id);
if (!structure || structure.category === StructureType[StructureType.Realm]) return;

const position = getComponentValue(Position, id);

const structureName = getEntityName(structure.entity_id);

const name = structureName ? `${structure?.category} ${structureName}` : structure.category || "";
return { ...structure, position: position!, name, owner: getComponentValue(Owner, id) };
})
.filter((structure): structure is PlayerStructure => structure !== undefined)
.sort((a, b) => a.category.localeCompare(b.category));
}, [filterOtherStructures]);
}, [playerStructuresQuery]);

const getPlayerRealms = (filterFn?: (realm: RealmWithPosition) => boolean) => {
return useMemo(() => {
Expand All @@ -147,30 +95,16 @@ export const useEntities = () => {
}, [playerRealms, filterFn]);
};

const getOtherRealms = (filterFn?: (realm: RealmWithPosition) => boolean) => {
return useMemo(() => {
return filterFn ? otherRealms.filter(filterFn) : otherRealms;
}, [otherRealms, filterFn]);
};

const getPlayerStructures = (filterFn?: (structure: PlayerStructure) => boolean) => {
return useMemo(() => {
const structures = filterFn ? playerStructures.filter(filterFn) : playerStructures;
return structures.sort((a, b) => a.name.localeCompare(b.name));
}, [playerStructures, filterFn]);
};

const getOtherStructures = (filterFn?: (structure: PlayerStructure) => boolean) => {
return useMemo(() => {
return filterFn ? otherStructures.filter(filterFn) : otherStructures;
}, [otherStructures, filterFn]);
};

return {
playerRealms: getPlayerRealms,
otherRealms: getOtherRealms,
playerStructures: getPlayerStructures,
otherStructures: getOtherStructures,
};
};

Expand Down
12 changes: 6 additions & 6 deletions client/src/hooks/helpers/useRealm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { type ClientComponents } from "@/dojo/createClientComponents";
import { configManager } from "@/dojo/setup";
import {
ContractAddress,
type ID,
getOrderName,
getQuestResources as getStartingResources,
type ID,
} from "@bibliothecadao/eternum";
import { useEntityQuery } from "@dojoengine/react";
import { type ComponentValue, type Entity, Has, HasValue, getComponentValue, runQuery } from "@dojoengine/recs";
import { Has, HasValue, getComponentValue, runQuery, type ComponentValue, type Entity } from "@dojoengine/recs";
import { useMemo } from "react";
import { shortString } from "starknet";
import realmIdsByOrder from "../../data/realmids_by_order.json";
Expand Down Expand Up @@ -265,7 +265,7 @@ export function getRealms(): RealmInfo[] {
const position = getComponentValue(Position, entity);
const population = getComponentValue(Population, entity);

if (!realm || !owner || !position) return;
if (!realm || !owner || !position) return null;

const { realm_id, entity_id, produced_resources, order } = realm;

Expand All @@ -291,7 +291,7 @@ export function getRealms(): RealmInfo[] {
hasWonder: realm.has_wonder,
};
})
.filter((realm) => realm !== undefined);
.filter((realm): realm is RealmInfo => realm !== null);
}

export function usePlayerRealms(): RealmInfo[] {
Expand All @@ -312,7 +312,7 @@ export function usePlayerRealms(): RealmInfo[] {
const position = getComponentValue(Position, entity);
const population = getComponentValue(Population, entity);

if (!realm || !owner || !position) return;
if (!realm || !owner || !position) return null;

const { realm_id, entity_id, produced_resources, order } = realm;

Expand All @@ -338,7 +338,7 @@ export function usePlayerRealms(): RealmInfo[] {
hasWonder: realm.has_wonder,
};
})
.filter((realm) => realm !== undefined);
.filter((realm): realm is RealmInfo => realm !== null);
}, [realmEntities]);
return realms;
}
4 changes: 2 additions & 2 deletions client/src/ui/components/resources/InventoryResources.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { addToSubscription } from "@/dojo/queries";
import { debouncedAddToSubscription } from "@/dojo/debouncedQueries";
import { useDojo } from "@/hooks/context/DojoContext";
import { useResourceBalance, useResourcesUtils } from "@/hooks/helpers/useResources";
import { ResourceCost } from "@/ui/elements/ResourceCost";
Expand Down Expand Up @@ -52,7 +52,7 @@ export const InventoryResources = ({
setIsSyncing(true);
try {
console.log("AddToSubscriptionStart - 4");
await addToSubscription(dojo.network.toriiClient, dojo.network.contractComponents as any, [
await debouncedAddToSubscription(dojo.network.toriiClient, dojo.network.contractComponents as any, [
entityId.toString(),
]);
localStorage.setItem(cacheKey, now.toString());
Expand Down
Loading
Loading