From d8fa2e2736f893e1f59292cd44248a6cca086b49 Mon Sep 17 00:00:00 2001 From: Constantin Wastchenko <80072466+cwastche@users.noreply.github.com> Date: Fri, 2 Aug 2024 16:06:45 +0200 Subject: [PATCH] fix army weight when exploring, add weigh + capacity in UI (#1117) * fix army weight when exploring, add weigh + capacity in UI * fix rebase * small fixes * Fix conflicts * prettier * fix build * ui fixes * prettier * fix sell order weight amount * fix build & knip --- .../dojo/modelManager/__tests__/__mock__.ts | 1 + client/src/hooks/helpers/useArmies.tsx | 62 ++++++++++++++++++- client/src/ui/components/entities/Entity.tsx | 2 + .../src/ui/components/military/ArmyChip.tsx | 2 + .../src/ui/components/military/ArmyList.tsx | 7 ++- client/src/ui/components/quest/QuestInfo.tsx | 11 +++- .../components/trading/MarketOrderPanel.tsx | 2 +- .../worldmap/armies/ArmyInfoLabel.tsx | 5 +- .../worldmap/hexagon/ActionInfo.tsx | 16 +++++ .../worldmap/hexagon/useTravelPath.tsx | 8 ++- .../ui/components/worldmap/hexagon/utils.tsx | 5 +- client/src/ui/elements/ArmyCapacity.tsx | 19 ++++++ .../navigation/LeftNavigationModule.tsx | 3 +- .../navigation/RightNavigationModule.tsx | 2 +- sdk/packages/eternum/src/config/index.ts | 3 +- .../eternum/src/constants/structures.ts | 3 +- 16 files changed, 135 insertions(+), 16 deletions(-) create mode 100644 client/src/ui/elements/ArmyCapacity.tsx diff --git a/client/src/dojo/modelManager/__tests__/__mock__.ts b/client/src/dojo/modelManager/__tests__/__mock__.ts index c7a72e00a..74c4baf29 100644 --- a/client/src/dojo/modelManager/__tests__/__mock__.ts +++ b/client/src/dojo/modelManager/__tests__/__mock__.ts @@ -105,6 +105,7 @@ export const generateMockArmyInfo = (alive?: boolean, isMine?: boolean, battleEn intermediate_coord_y: 0, }, capacity: { entity_id: ARMY_ENTITY_ID, weight_gram: 10n }, + weight: { entity_id: ARMY_ENTITY_ID, value: 0n }, arrivalTime: { entity_id: ARMY_ENTITY_ID, arrives_at: 0n }, stamina: { entity_id: ARMY_ENTITY_ID, amount: 1, last_refill_tick: 0n }, realm: { diff --git a/client/src/hooks/helpers/useArmies.tsx b/client/src/hooks/helpers/useArmies.tsx index 0024cd05b..ba73dcb01 100644 --- a/client/src/hooks/helpers/useArmies.tsx +++ b/client/src/hooks/helpers/useArmies.tsx @@ -29,9 +29,10 @@ export type ArmyInfo = ComponentValue & { owner: ComponentValue; entityOwner: ComponentValue; protectee: ComponentValue | undefined; - quantity: ComponentValue | undefined; + quantity: ComponentValue; movable: ComponentValue | undefined; - capacity: ComponentValue | undefined; + capacity: ComponentValue; + weight: ComponentValue; arrivalTime: ComponentValue | undefined; stamina: ComponentValue | undefined; realm: ComponentValue | undefined; @@ -48,6 +49,7 @@ const formatArmies = ( Quantity: Component, Movable: Component, Capacity: Component, + Weight: Component, ArrivalTime: Component, Position: Component, EntityOwner: Component, @@ -89,9 +91,42 @@ const formatArmies = ( }; } const protectee = getComponentValue(Protectee, armyEntityId); + const quantity = getComponentValue(Quantity, armyEntityId); + let quantityClone = structuredClone(quantity); + if (quantityClone) { + quantityClone.value = BigInt(quantityClone.value) / BigInt(EternumGlobalConfig.resources.resourcePrecision); + } else { + quantityClone = { + entity_id: army.entity_id, + value: 0n, + }; + } + const movable = getComponentValue(Movable, armyEntityId); + const capacity = getComponentValue(Capacity, armyEntityId); + let capacityClone = structuredClone(capacity); + if (capacityClone) { + capacityClone.weight_gram = capacityClone.weight_gram * quantityClone.value; + } else { + capacityClone = { + entity_id: army.entity_id, + weight_gram: BigInt(EternumGlobalConfig.carryCapacity.army) * quantityClone.value, + }; + } + + const weight = getComponentValue(Weight, armyEntityId); + let weightClone = structuredClone(weight); + if (weightClone) { + weightClone.value = weightClone.value / BigInt(EternumGlobalConfig.resources.resourcePrecision); + } else { + weightClone = { + entity_id: army.entity_id, + value: 0n, + }; + } + const arrivalTime = getComponentValue(ArrivalTime, armyEntityId); const stamina = getComponentValue(Stamina, armyEntityId); const name = getComponentValue(Name, armyEntityId); @@ -111,7 +146,8 @@ const formatArmies = ( health: healthClone, quantity, movable, - capacity, + capacity: capacityClone, + weight: weightClone, arrivalTime, position, entityOwner, @@ -142,6 +178,7 @@ export const useMovableArmies = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Realm, Army, @@ -174,6 +211,7 @@ export const useMovableArmies = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -195,6 +233,7 @@ export const useArmiesByEntityOwner = ({ entity_owner_entity_id }: { entity_owne Quantity, Movable, Capacity, + Weight, ArrivalTime, Realm, Army, @@ -219,6 +258,7 @@ export const useArmiesByEntityOwner = ({ entity_owner_entity_id }: { entity_owne Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -244,6 +284,7 @@ export const getArmiesByBattleId = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Realm, Army, @@ -267,6 +308,7 @@ export const getArmiesByBattleId = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -289,6 +331,7 @@ export const useArmyByArmyEntityId = (entityId: ID) => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Realm, Army, @@ -311,6 +354,7 @@ export const useArmyByArmyEntityId = (entityId: ID) => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -332,6 +376,7 @@ export const getUserArmyInBattle = (battle_id: ID) => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Realm, Army, @@ -360,6 +405,7 @@ export const getUserArmyInBattle = (battle_id: ID) => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -385,6 +431,7 @@ export const useOwnArmiesByPosition = ({ position, inBattle }: { position: Posit Quantity, Movable, Capacity, + Weight, ArrivalTime, Realm, Army, @@ -414,6 +461,7 @@ export const useOwnArmiesByPosition = ({ position, inBattle }: { position: Posit Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -440,6 +488,7 @@ export const useEnemyArmiesByPosition = ({ position }: { position: Position }) = Quantity, Movable, Capacity, + Weight, ArrivalTime, Realm, Army, @@ -468,6 +517,7 @@ export const useEnemyArmiesByPosition = ({ position }: { position: Position }) = Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -492,6 +542,7 @@ export const getArmyByEntityId = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Realm, Army, @@ -516,6 +567,7 @@ export const getArmyByEntityId = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -538,6 +590,7 @@ export const getArmyByEntityId = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -561,6 +614,7 @@ export const getArmiesAtPosition = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Realm, Army, @@ -598,6 +652,7 @@ export const getArmiesAtPosition = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, @@ -616,6 +671,7 @@ export const getArmiesAtPosition = () => { Quantity, Movable, Capacity, + Weight, ArrivalTime, Position, EntityOwner, diff --git a/client/src/ui/components/entities/Entity.tsx b/client/src/ui/components/entities/Entity.tsx index 2a6364788..35e86f5fa 100644 --- a/client/src/ui/components/entities/Entity.tsx +++ b/client/src/ui/components/entities/Entity.tsx @@ -13,6 +13,7 @@ import clsx from "clsx"; import React, { useMemo, useState } from "react"; import { DepositResources } from "../resources/DepositResources"; import { TravelEntityPopup } from "./TravelEntityPopup"; +import { ArmyCapacity } from "@/ui/elements/ArmyCapacity"; const entityIcon: Record = { [EntityType.DONKEY]: "🫏", @@ -123,6 +124,7 @@ export const Entity = ({ entityId, ...props }: EntityProps) => {
{renderEntityStatus()}
+ {entity.entityType === EntityType.TROOP && }
{renderResources()}
{entityState !== EntityState.Traveling && (
+
diff --git a/client/src/ui/components/military/ArmyList.tsx b/client/src/ui/components/military/ArmyList.tsx index 227a515ee..73b3ec76b 100644 --- a/client/src/ui/components/military/ArmyList.tsx +++ b/client/src/ui/components/military/ArmyList.tsx @@ -13,6 +13,7 @@ import React, { useMemo, useState } from "react"; import { EntityList } from "../list/EntityList"; import { InventoryResources } from "../resources/InventoryResources"; import { ArmyManagementCard } from "./ArmyManagementCard"; +import { ArmyCapacity } from "@/ui/elements/ArmyCapacity"; const MAX_AMOUNT_OF_DEFENSIVE_ARMIES = 1; @@ -75,7 +76,6 @@ export const EntityArmyList = ({ structure }: { structure: PlayerStructure }) => is_defensive_army, }).finally(() => setLoading(Loading.None)); }; - return ( <> } title="armies" panel={({ entity, setSelectedEntity }) => ( - + <> + + + )} questing={selectedQuest?.id === QuestId.CreateArmy} /> diff --git a/client/src/ui/components/quest/QuestInfo.tsx b/client/src/ui/components/quest/QuestInfo.tsx index 4cc87d251..eadcf5804 100644 --- a/client/src/ui/components/quest/QuestInfo.tsx +++ b/client/src/ui/components/quest/QuestInfo.tsx @@ -87,12 +87,19 @@ export const QuestInfo = ({ quest, entityId }: { quest: Quest; entityId: ID }) = }; const QuestRewards = ({ prizes }: { prizes: Prize[] }) => { + const [showRewards, setShowRewards] = useState(false); const { getQuestResources } = useRealm(); return (
-
Quest Rewards
- {prizes && +
+
Quest Rewards
+ +
+ {showRewards && + prizes && prizes.map((prize, index) => (
{getQuestResources()[prize.id].map((resource, i) => ( diff --git a/client/src/ui/components/trading/MarketOrderPanel.tsx b/client/src/ui/components/trading/MarketOrderPanel.tsx index b7f40d6c6..cf03aaa41 100644 --- a/client/src/ui/components/trading/MarketOrderPanel.tsx +++ b/client/src/ui/components/trading/MarketOrderPanel.tsx @@ -398,7 +398,7 @@ const OrderCreation = ({ const orderWeight = useMemo(() => { const totalWeight = getTotalResourceWeight([ - { resourceId: isBuy ? resourceId : ResourcesIds.Lords, amount: resource }, + { resourceId: isBuy ? resourceId : ResourcesIds.Lords, amount: isBuy ? resource : lords }, ]); return multiplyByPrecision(totalWeight); }, [resource, lords]); diff --git a/client/src/ui/components/worldmap/armies/ArmyInfoLabel.tsx b/client/src/ui/components/worldmap/armies/ArmyInfoLabel.tsx index 4a9f4d454..92f83801f 100644 --- a/client/src/ui/components/worldmap/armies/ArmyInfoLabel.tsx +++ b/client/src/ui/components/worldmap/armies/ArmyInfoLabel.tsx @@ -1,7 +1,7 @@ import useBlockchainStore from "../../../../hooks/store/useBlockchainStore"; import { currencyFormat } from "../../../utils/utils"; -import { ArmyInfo } from "@/hooks/helpers/useArmies"; +import { ArmyInfo, useArmyByArmyEntityId } from "@/hooks/helpers/useArmies"; import { BaseThreeTooltip, Position } from "@/ui/elements/BaseThreeTooltip"; import { Headline } from "@/ui/elements/Headline"; import { ResourceIcon } from "@/ui/elements/ResourceIcon"; @@ -12,6 +12,7 @@ import { useMemo } from "react"; import { useRealm } from "../../../../hooks/helpers/useRealm"; import { getRealmNameById } from "../../../utils/realms"; import { InventoryResources } from "../../resources/InventoryResources"; +import { ArmyCapacity } from "@/ui/elements/ArmyCapacity"; interface ArmyInfoLabelProps { army: ArmyInfo; @@ -104,7 +105,7 @@ const RaiderInfo = ({ army }: ArmyInfoLabelProps) => {
{currencyFormat(troops.paladin_count, 0)}
- +
diff --git a/client/src/ui/components/worldmap/hexagon/ActionInfo.tsx b/client/src/ui/components/worldmap/hexagon/ActionInfo.tsx index c1727a0f8..1ebc3911e 100644 --- a/client/src/ui/components/worldmap/hexagon/ActionInfo.tsx +++ b/client/src/ui/components/worldmap/hexagon/ActionInfo.tsx @@ -6,6 +6,7 @@ import { Headline } from "@/ui/elements/Headline"; import { ResourceCost } from "@/ui/elements/ResourceCost"; import { StaminaResourceCost } from "@/ui/elements/StaminaResourceCost"; import { getUIPositionFromColRow } from "@/ui/utils/utils"; +import { BuildingThumbs } from "@/ui/modules/navigation/LeftNavigationModule"; import { EternumGlobalConfig, ResourcesIds } from "@bibliothecadao/eternum"; import { useMemo } from "react"; @@ -54,6 +55,21 @@ export const ActionInfo = () => { isExplored={isExplored} travelLength={travelPath.path.length - 1} /> +
+
+ +
+
+{EternumGlobalConfig.exploration.reward}
+
Reward
+
+
)} diff --git a/client/src/ui/components/worldmap/hexagon/useTravelPath.tsx b/client/src/ui/components/worldmap/hexagon/useTravelPath.tsx index c4dcbb36c..20a49472f 100644 --- a/client/src/ui/components/worldmap/hexagon/useTravelPath.tsx +++ b/client/src/ui/components/worldmap/hexagon/useTravelPath.tsx @@ -9,6 +9,7 @@ import { EternumGlobalConfig } from "@bibliothecadao/eternum"; import { useEffect } from "react"; import { canExplore, findAccessiblePositionsAndPaths } from "./utils.js"; import { useExploredHexesStore } from "./WorldHexagon.js"; +import { getArmyByEntityId } from "@/hooks/helpers/useArmies.js"; export const useTravelPath = () => { const selectedEntity = useUIStore((state) => state.selectedEntity); @@ -19,9 +20,14 @@ export const useTravelPath = () => { const { getFoodResources } = getResourceBalance(); const { useStaminaByEntityId } = useStamina(); const { getEntityOwner } = useRealm(); + const { getArmy } = getArmyByEntityId(); const stamina = useStaminaByEntityId({ travelingEntityId: selectedEntity?.id || 0 }); + const army = getArmy(selectedEntity?.id || 0); + const hasCapacity = + (army?.capacity?.weight_gram || 0n) - (army?.weight?.value || 0n) >= BigInt(EternumGlobalConfig.exploration.reward); + useEffect(() => { if (!selectedEntity || !stamina) return; @@ -33,7 +39,7 @@ export const useTravelPath = () => { selectedEntity.position, exploredHexes, maxTravelPossible, - canExplore(stamina?.amount, food), + canExplore(stamina?.amount, food, hasCapacity), ); const path = Array.from(pathMap.entries()).map(([key, path]) => { diff --git a/client/src/ui/components/worldmap/hexagon/utils.tsx b/client/src/ui/components/worldmap/hexagon/utils.tsx index 1caf44012..39761494a 100644 --- a/client/src/ui/components/worldmap/hexagon/utils.tsx +++ b/client/src/ui/components/worldmap/hexagon/utils.tsx @@ -24,7 +24,7 @@ export const getPositionsAtIndex = (mesh: InstancedMesh, index: number return positions; }; -export const canExplore = (stamina: number | undefined, food: Resource[]) => { +export const canExplore = (stamina: number | undefined, food: Resource[], hasCapacity: boolean) => { if (stamina && stamina < EternumGlobalConfig.stamina.exploreCost) { return false; } @@ -36,6 +36,9 @@ export const canExplore = (stamina: number | undefined, food: Resource[]) => { if ((wheat?.amount || 0) < EternumGlobalConfig.exploration.wheatBurn) { return false; } + if (!hasCapacity) { + return false; + } return true; }; diff --git a/client/src/ui/elements/ArmyCapacity.tsx b/client/src/ui/elements/ArmyCapacity.tsx new file mode 100644 index 000000000..11cd92350 --- /dev/null +++ b/client/src/ui/elements/ArmyCapacity.tsx @@ -0,0 +1,19 @@ +import { ArmyInfo } from "@/hooks/helpers/useArmies"; +import { EternumGlobalConfig } from "@bibliothecadao/eternum"; +import clsx from "clsx"; + +export const ArmyCapacity = ({ army, className }: { army: ArmyInfo | undefined; className?: string }) => { + if (!army) return null; + return ( +
+ Capacity : {Number(army.weight?.value)} / {Number(army.capacity?.weight_gram)} +
+ ); +}; diff --git a/client/src/ui/modules/navigation/LeftNavigationModule.tsx b/client/src/ui/modules/navigation/LeftNavigationModule.tsx index c5337e9d1..d53fc59a7 100644 --- a/client/src/ui/modules/navigation/LeftNavigationModule.tsx +++ b/client/src/ui/modules/navigation/LeftNavigationModule.tsx @@ -132,6 +132,7 @@ export const LeftNavigationModule = () => { disabled={!realmIsMine} className={clsx({ "animate-pulse": view != View.ConstructionView && isBuildQuest && isPopupOpen(questsPopup), + hidden: !questClaimStatus[QuestId.Settle], })} image={BuildingThumbs.construction} tooltipLocation="top" @@ -183,7 +184,7 @@ export const LeftNavigationModule = () => { item.name === MenuEnum.construction || item.name === MenuEnum.worldStructures, ); - }, [location, view, openedPopups, selectedQuest, armiesCanMoveCount, questClaimStatus]); + }, [location, view, openedPopups, selectedQuest, armiesCanMoveCount, questClaimStatus, realmEntityId]); if (realmEntityId === undefined) { return null; diff --git a/client/src/ui/modules/navigation/RightNavigationModule.tsx b/client/src/ui/modules/navigation/RightNavigationModule.tsx index 1572585ec..1cd662b25 100644 --- a/client/src/ui/modules/navigation/RightNavigationModule.tsx +++ b/client/src/ui/modules/navigation/RightNavigationModule.tsx @@ -114,7 +114,7 @@ export const RightNavigationModule = () => { ), }, ]; - }, [location, view, questClaimStatus, openedPopups, selectedQuest, getAllArrivalsWithResources]); + }, [location, view, questClaimStatus, openedPopups, selectedQuest, getAllArrivalsWithResources, realmEntityId]); const slideRight = { hidden: { x: "100%" }, diff --git a/sdk/packages/eternum/src/config/index.ts b/sdk/packages/eternum/src/config/index.ts index 385c53d5c..83b9ccbdc 100644 --- a/sdk/packages/eternum/src/config/index.ts +++ b/sdk/packages/eternum/src/config/index.ts @@ -220,7 +220,8 @@ export const setCapacityConfig = async (account: Account, provider: EternumProvi const txArmy = await provider.set_capacity_config({ signer: account, entity_type: ARMY_ENTITY_TYPE, - weight_gram: EternumGlobalConfig.carryCapacity.army * EternumGlobalConfig.resources.resourcePrecision, + // No precision mod used because weight check in contract uses army qty x precision + weight_gram: EternumGlobalConfig.carryCapacity.army, }); console.log(`Configuring capacity Army config ${txArmy.statusReceipt}...`); diff --git a/sdk/packages/eternum/src/constants/structures.ts b/sdk/packages/eternum/src/constants/structures.ts index 52d484c83..cc9b4230f 100644 --- a/sdk/packages/eternum/src/constants/structures.ts +++ b/sdk/packages/eternum/src/constants/structures.ts @@ -1,7 +1,8 @@ import { CairoCustomEnum } from "starknet"; import { ResourcesIds } from "../constants"; -/** @knipignore */ +// Knip ignore tag +/** @public */ export enum StructureType { Realm = 1, Hyperstructure = 2,