Skip to content

Commit

Permalink
refactor use resources
Browse files Browse the repository at this point in the history
  • Loading branch information
aymericdelab committed Jan 15, 2025
1 parent ef8fc2b commit f4842ce
Show file tree
Hide file tree
Showing 15 changed files with 122 additions and 218 deletions.
146 changes: 2 additions & 144 deletions client/apps/game/src/hooks/helpers/use-resources.tsx
Original file line number Diff line number Diff line change
@@ -1,151 +1,9 @@
import { useDojo } from "@/hooks/context/dojo-context";
import useUIStore from "@/hooks/store/use-ui-store";
import useNextBlockTimestamp from "@/hooks/use-next-block-timestamp";
import {
CapacityConfigCategory,
ID,
ResourceManager,
ResourcesIds,
resources,
type Resource,
} from "@bibliothecadao/eternum";
import { ID, ResourceManager, ResourcesIds } from "@bibliothecadao/eternum";
import { useComponentValue } from "@dojoengine/react";
import { Has, HasValue, getComponentValue, runQuery, type Entity } from "@dojoengine/recs";
import { useEffect, useMemo, useState } from "react";
import { useMemo } from "react";
import { getEntityIdFromKeys } from "../../ui/utils/utils";

export function useResourcesUtils() {
const { setup } = useDojo();
const {
components: { Weight, Resource, ResourceCost, Realm, CapacityCategory },
} = setup;

const useResourcesFromBalance = (entityId: ID) => {
const { currentDefaultTick } = useNextBlockTimestamp();
const weight = useComponentValue(Weight, getEntityIdFromKeys([BigInt(entityId)]));
const capacityCategory = useComponentValue(CapacityCategory, getEntityIdFromKeys([BigInt(entityId)]));

return useMemo(() => {
if (!weight?.value && capacityCategory?.category !== CapacityConfigCategory[CapacityConfigCategory.Structure])
return [];

return resources
.map(({ id }) => {
const resourceManager = new ResourceManager(setup.components, entityId, id);
const balance = resourceManager.balance(currentDefaultTick);
return { resourceId: id, amount: balance };
})
.filter(({ amount }) => amount > 0);
}, [weight, entityId, currentDefaultTick]);
};

const getResourceCosts = (costUuid: bigint, count: number) => {
const resourceCosts = [];
for (let i = 0; i < count; i++) {
const resourceCost = getComponentValue(ResourceCost, getEntityIdFromKeys([costUuid, BigInt(i)]));
if (resourceCost) {
resourceCosts.push({ resourceId: resourceCost.resource_type, amount: Number(resourceCost.amount) });
}
}
return resourceCosts;
};

const getRealmsWithSpecificResource = (
resourceId: ResourcesIds,
minAmount: number,
): Array<{ realmEntityId: ID; realmId: ID; amount: number }> => {
const allRealms = Array.from(runQuery([Has(Realm)]));
const currentDefaultTick = useUIStore.getState().currentDefaultTick;
const realmsWithResource = allRealms
.map((id: Entity) => {
const realm = getComponentValue(Realm, id);
const resourceManager = realm ? new ResourceManager(setup.components, realm.entity_id, resourceId) : undefined;
const resource = resourceManager
? {
balance: resourceManager.balance(currentDefaultTick),
}
: undefined;

if (resource && resource.balance > minAmount) {
return {
realmEntityId: realm?.entity_id,
realmId: realm?.realm_id,
amount: Number(resource.balance),
};
}
})
.filter(Boolean) as Array<{ realmEntityId: ID; realmId: ID; amount: number }>;

return realmsWithResource;
};

return {
getRealmsWithSpecificResource,
getResourceCosts,
useResourcesFromBalance,
};
}

export function useResourceBalance() {
const dojo = useDojo();

const getFoodResources = (entityId: ID): Resource[] => {
const currentDefaultTick = useUIStore.getState().currentDefaultTick;
const wheatBalance = new ResourceManager(dojo.setup.components, entityId, ResourcesIds.Wheat).balance(
currentDefaultTick,
);
const fishBalance = new ResourceManager(dojo.setup.components, entityId, ResourcesIds.Fish).balance(
currentDefaultTick,
);

return [
{ resourceId: ResourcesIds.Wheat, amount: wheatBalance },
{ resourceId: ResourcesIds.Fish, amount: fishBalance },
];
};

const getResourceProductionInfo = (entityId: ID, resourceId: ResourcesIds) => {
const resourceManager = new ResourceManager(dojo.setup.components, entityId, resourceId);
return resourceManager.getProduction();
};

const getBalance = (entityId: ID, resourceId: ResourcesIds) => {
const currentDefaultTick = useUIStore.getState().currentDefaultTick;
const resourceManager = new ResourceManager(dojo.setup.components, entityId, resourceId);
return { balance: resourceManager.balance(currentDefaultTick), resourceId };
};

const getResourcesBalance = (entityId: ID) => {
const detachedResourceEntityIds = runQuery([
HasValue(dojo.setup.components.DetachedResource, { entity_id: entityId }),
]);
return Array.from(detachedResourceEntityIds).map((entityId) =>
getComponentValue(dojo.setup.components.DetachedResource, entityId),
);
};

// We should deprecate this hook and use getBalance instead - too many useEffects
const useBalance = (entityId: ID, resourceId: ResourcesIds) => {
const currentDefaultTick = useUIStore.getState().currentDefaultTick;
const [resourceBalance, setResourceBalance] = useState<Resource>({ amount: 0, resourceId });

useEffect(() => {
const resourceManager = new ResourceManager(dojo.setup.components, entityId, resourceId);
setResourceBalance({ amount: resourceManager.balance(currentDefaultTick), resourceId });
}, []);

return resourceBalance;
};

return {
getFoodResources,
getBalance,
useBalance,
getResourcesBalance,
getResourceProductionInfo,
};
}

export const useResourceManager = (entityId: ID, resourceId: ResourcesIds) => {
const dojo = useDojo();
const production = useComponentValue(
Expand Down
8 changes: 3 additions & 5 deletions client/apps/game/src/ui/components/bank/add-liquidity.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useDojo } from "@/hooks/context/dojo-context";
import { usePlayerStructures } from "@/hooks/helpers/use-entities";
import { useResourceBalance } from "@/hooks/helpers/use-resources";
import { useIsResourcesLocked } from "@/hooks/helpers/use-structures";
import { ConfirmationPopup } from "@/ui/components/bank/confirmation-popup";
import { LiquidityResourceRow } from "@/ui/components/bank/liquidity-resource-row";
Expand All @@ -9,6 +8,7 @@ import { ResourceBar } from "@/ui/components/bank/resource-bar";
import Button from "@/ui/elements/button";
import { ResourceCost } from "@/ui/elements/resource-cost";
import { divideByPrecision, multiplyByPrecision } from "@/ui/utils/utils";
import { getBalance } from "@/utils/resources";
import { ContractAddress, ID, MarketManager, ResourcesIds, resources } from "@bibliothecadao/eternum";
import { useEffect, useMemo, useState } from "react";

Expand All @@ -26,8 +26,6 @@ const AddLiquidity = ({
setup,
} = useDojo();

const { getBalance } = useResourceBalance();

const playerStructures = usePlayerStructures(ContractAddress(account.address));

const playerStructureIds = playerStructures.map((structure) => structure.entity_id);
Expand Down Expand Up @@ -63,8 +61,8 @@ const AddLiquidity = ({
}
}, [resourceAmount]);

const lordsBalance = getBalance(entityId, Number(ResourcesIds.Lords)).balance;
const resourceBalance = getBalance(entityId, Number(resourceId)).balance;
const lordsBalance = getBalance(entityId, Number(ResourcesIds.Lords), setup.components).balance;
const resourceBalance = getBalance(entityId, Number(resourceId), setup.components).balance;
const hasEnough =
lordsBalance >= multiplyByPrecision(lordsAmount) && resourceBalance >= multiplyByPrecision(resourceAmount);

Expand Down
11 changes: 7 additions & 4 deletions client/apps/game/src/ui/components/bank/resource-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useResourceBalance } from "@/hooks/helpers/use-resources";
import { useDojo } from "@/hooks/context/dojo-context";
import { HintSection } from "@/ui/components/hints/hint-modal";
import { NumberInput } from "@/ui/elements/number-input";
import { ResourceCost } from "@/ui/elements/resource-cost";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/ui/elements/select";
import TextInput from "@/ui/elements/text-input";
import { divideByPrecision, formatNumber } from "@/ui/utils/utils";
import { getBalance } from "@/utils/resources";
import { ID, Resources, ResourcesIds, findResourceById, findResourceIdByTrait } from "@bibliothecadao/eternum";
import { memo, useEffect, useRef, useState } from "react";

Expand Down Expand Up @@ -34,7 +35,7 @@ export const ResourceBar = memo(
onBlur?: () => void; // New prop
max?: number;
}) => {
const { getBalance } = useResourceBalance();
const dojo = useDojo();

const [selectedResourceBalance, setSelectedResourceBalance] = useState(0);
const [searchInput, setSearchInput] = useState("");
Expand All @@ -43,7 +44,9 @@ export const ResourceBar = memo(
const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
setSelectedResourceBalance(divideByPrecision(getBalance(entityId, Number(resourceId)).balance));
setSelectedResourceBalance(
divideByPrecision(getBalance(entityId, Number(resourceId), dojo.setup.components).balance),
);
}, [resourceId, getBalance, entityId]);

const handleResourceChange = (trait: string) => {
Expand Down Expand Up @@ -145,7 +148,7 @@ export const ResourceBar = memo(
<SelectItem key={resource.id} value={resource.trait} disabled={resource.id === resourceId}>
<ResourceCost
resourceId={resource.id}
amount={divideByPrecision(getBalance(entityId, resource.id).balance)}
amount={divideByPrecision(getBalance(entityId, resource.id, dojo.setup.components).balance)}
className="border-0 bg-transparent"
/>
</SelectItem>
Expand Down
13 changes: 9 additions & 4 deletions client/apps/game/src/ui/components/bank/swap.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ReactComponent as Refresh } from "@/assets/icons/common/refresh.svg";
import { configManager } from "@/dojo/setup";
import { useDojo } from "@/hooks/context/dojo-context";
import { useResourceBalance } from "@/hooks/helpers/use-resources";
import { useIsResourcesLocked, useStructures } from "@/hooks/helpers/use-structures";
import { useTravel } from "@/hooks/helpers/use-travel";
import { soundSelector, useUiSounds } from "@/hooks/use-ui-sound";
Expand All @@ -11,6 +10,7 @@ import { TravelInfo } from "@/ui/components/resources/travel-info";
import Button from "@/ui/elements/button";
import { ResourceIcon } from "@/ui/elements/resource-icon";
import { divideByPrecision, formatNumber, multiplyByPrecision } from "@/ui/utils/utils";
import { getBalance } from "@/utils/resources";
import {
ContractAddress,
DONKEY_ENTITY_TYPE,
Expand All @@ -37,7 +37,6 @@ export const ResourceSwap = ({
setup,
} = useDojo();

const { getBalance } = useResourceBalance();
const { computeTravelTime } = useTravel();
const { play: playLordsSound } = useUiSounds(soundSelector.addLords);

Expand Down Expand Up @@ -76,8 +75,14 @@ export const ResourceSwap = ({
}
}, [marketManager.resourceId]);

const lordsBalance = useMemo(() => getBalance(entityId, ResourcesIds.Lords).balance, [entityId, getBalance]);
const resourceBalance = useMemo(() => getBalance(entityId, resourceId).balance, [entityId, resourceId, getBalance]);
const lordsBalance = useMemo(
() => getBalance(entityId, ResourcesIds.Lords, setup.components).balance,
[entityId, getBalance],
);
const resourceBalance = useMemo(
() => getBalance(entityId, resourceId, setup.components).balance,
[entityId, resourceId, getBalance],
);

const hasEnough = useMemo(() => {
const amount = isBuyResource ? lordsAmount + ownerFee : resourceAmount;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { configManager } from "@/dojo/setup";
import { DojoResult, useDojo } from "@/hooks/context/dojo-context";
import { useResourceBalance } from "@/hooks/helpers/use-resources";
import useUIStore from "@/hooks/store/use-ui-store";
import { usePlayResourceSound } from "@/hooks/use-ui-sound";
import { ResourceMiningTypes } from "@/types";
Expand All @@ -22,6 +21,7 @@ import {
isResourceProductionBuilding,
} from "@/ui/utils/utils";
import { getRealmInfo } from "@/utils/realm";
import { getBalance } from "@/utils/resources";
import {
BuildingEnumToString,
BuildingType,
Expand All @@ -46,7 +46,6 @@ export const SelectPreviewBuildingMenu = ({ className, entityId }: { className?:

const realm = getRealmInfo(getEntityIdFromKeys([BigInt(entityId)]), dojo.setup.components);

const { getBalance } = useResourceBalance();
const { playResourceSound } = usePlayResourceSound();

const buildingTypes = Object.keys(BuildingType).filter(
Expand Down Expand Up @@ -75,7 +74,7 @@ export const SelectPreviewBuildingMenu = ({ className, entityId }: { className?:
const checkBalance = (cost: any) =>
Object.keys(cost).every((resourceId) => {
const resourceCost = cost[Number(resourceId)];
const balance = getBalance(entityId, resourceCost.resource);
const balance = getBalance(entityId, resourceCost.resource, dojo.setup.components);
return divideByPrecision(balance.balance) >= resourceCost.amount;
});

Expand Down Expand Up @@ -408,8 +407,6 @@ export const ResourceInfo = ({

const amountProducedPerTick = divideByPrecision(configManager.getResourceOutputs(resourceId));

const { getBalance } = useResourceBalance();

const consumedBy = useMemo(() => {
return getConsumedBy(resourceId);
}, [resourceId]);
Expand Down Expand Up @@ -461,7 +458,7 @@ export const ResourceInfo = ({
<div className="font-bold uppercase">consumed per/s</div>
<div className="grid grid-cols-2 gap-2">
{Object.keys(cost).map((resourceId) => {
const balance = getBalance(entityId || 0, cost[Number(resourceId)].resource);
const balance = getBalance(entityId || 0, cost[Number(resourceId)].resource, dojo.setup.components);

return (
<ResourceCost
Expand All @@ -478,7 +475,7 @@ export const ResourceInfo = ({

<div className="grid grid-cols-2 gap-2 text-sm">
{Object.keys(buildingCost).map((resourceId, index) => {
const balance = getBalance(entityId || 0, buildingCost[Number(resourceId)].resource);
const balance = getBalance(entityId || 0, buildingCost[Number(resourceId)].resource, dojo.setup.components);
return (
<ResourceCost
key={index}
Expand Down Expand Up @@ -541,8 +538,6 @@ export const BuildingInfo = ({
const perTick =
resourceProduced !== undefined ? divideByPrecision(configManager.getResourceOutputs(resourceProduced)) || 0 : 0;

const { getBalance } = useResourceBalance();

const usedIn = useMemo(() => {
return getConsumedBy(resourceProduced);
}, [resourceProduced]);
Expand Down Expand Up @@ -601,7 +596,11 @@ export const BuildingInfo = ({
<div className="grid grid-cols-2 gap-2">
{resourceProduced !== 0 &&
Object.keys(ongoingCost).map((resourceId, index) => {
const balance = getBalance(entityId || 0, ongoingCost[Number(resourceId)].resource);
const balance = getBalance(
entityId || 0,
ongoingCost[Number(resourceId)].resource,
dojo.setup.components,
);
return (
<ResourceCost
key={`ongoing-cost-${index}`}
Expand All @@ -621,7 +620,11 @@ export const BuildingInfo = ({
<div className="pt-2 font-bold uppercase">One Time Cost</div>
<div className="grid grid-cols-2 gap-2 text-sm">
{Object.keys(buildingCost).map((resourceId, index) => {
const balance = getBalance(entityId || 0, buildingCost[Number(resourceId)].resource);
const balance = getBalance(
entityId || 0,
buildingCost[Number(resourceId)].resource,
dojo.setup.components,
);
return (
<ResourceCost
key={`fixed-cost-${index}`}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { useDojo } from "@/hooks/context/dojo-context";
import { ProgressWithPercentage } from "@/hooks/helpers/use-hyperstructures";
import { useResourceBalance } from "@/hooks/helpers/use-resources";
import useUIStore from "@/hooks/store/use-ui-store";
import Button from "@/ui/elements/button";
import { NumberInput } from "@/ui/elements/number-input";
import { ResourceIcon } from "@/ui/elements/resource-icon";
import { currencyIntlFormat, divideByPrecision } from "@/ui/utils/utils";
import { getBalance, getResourceProductionInfo } from "@/utils/resources";
import { findResourceById, getIconResourceId, ID } from "@bibliothecadao/eternum";
import { useEffect, useState } from "react";

Expand All @@ -25,12 +26,13 @@ export const HyperstructureResourceChip = ({
progress,
resetContributions,
}: HyperstructureResourceChipProps) => {
const dojo = useDojo();

const [inputValue, setInputValue] = useState<number>(0);
const setTooltip = useUIStore((state) => state.setTooltip);

const { getBalance, getResourceProductionInfo } = useResourceBalance();
const balance = divideByPrecision(getBalance(structureEntityId, resourceId).balance);
const production = getResourceProductionInfo(structureEntityId, resourceId);
const balance = divideByPrecision(getBalance(structureEntityId, resourceId, dojo.setup.components).balance);
const production = getResourceProductionInfo(structureEntityId, resourceId, dojo.setup.components);

const safetyMargin = production !== undefined && production?.consumption_rate !== 0n ? 0.95 : 1;

Expand Down
Loading

0 comments on commit f4842ce

Please sign in to comment.